1 /* packet-nfs.c
2  * Routines for nfs dissection
3  * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
4  * Copyright 2000-2004, Mike Frisch <frisch@hummingbird.com> (NFSv4 decoding)
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * Copied from packet-smb.c
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14 
15 #include "config.h"
16 
17 #include <stdio.h>
18 #include <stdbool.h>
19 
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
22 #include <epan/exceptions.h>
23 #include <epan/expert.h>
24 #include <epan/proto_data.h>
25 #include <epan/to_str.h>
26 #include <epan/decode_as.h>
27 #include <epan/crc16-tvb.h>
28 #include <epan/crc32-tvb.h>
29 #include <wsutil/str_util.h>
30 #include "packet-nfs.h"
31 #include "packet-rpcrdma.h"
32 
33 void proto_register_nfs(void);
34 void proto_reg_handoff_nfs(void);
35 
36 /* NON-NFS-version-specific hf variables */
37 static int proto_nfs = -1;
38 static int proto_nfs_unknown = -1;
39 static int proto_nfs_svr4 = -1;
40 static int proto_nfs_knfsd_le = -1;
41 static int proto_nfs_nfsd_le = -1;
42 static int proto_nfs_knfsd_new = -1;
43 static int proto_nfs_ontap_v3 = -1;
44 static int proto_nfs_ontap_v4 = -1;
45 static int proto_nfs_ontap_gx_v3 = -1;
46 static int proto_nfs_celerra_vnx = -1;
47 static int proto_nfs_gluster = -1;
48 static int proto_nfs_dcache = -1;
49 static int proto_nfs_primary_data = -1;
50 static int proto_nfs_cb = -1;
51 static int hf_nfs_access_check  = -1;
52 static int hf_nfs_access_supported  = -1;
53 static int hf_nfs_access_rights = -1;
54 static int hf_nfs_access_supp_read = -1;
55 static int hf_nfs_access_supp_lookup = -1;
56 static int hf_nfs_access_supp_modify = -1;
57 static int hf_nfs_access_supp_extend = -1;
58 static int hf_nfs_access_supp_delete = -1;
59 static int hf_nfs_access_supp_execute = -1;
60 static int hf_nfs_access_supp_xattr_read = -1;
61 static int hf_nfs_access_supp_xattr_write = -1;
62 static int hf_nfs_access_supp_xattr_list = -1;
63 static int hf_nfs_access_read = -1;
64 static int hf_nfs_access_lookup = -1;
65 static int hf_nfs_access_modify = -1;
66 static int hf_nfs_access_extend = -1;
67 static int hf_nfs_access_delete = -1;
68 static int hf_nfs_access_execute = -1;
69 static int hf_nfs_access_xattr_read = -1;
70 static int hf_nfs_access_xattr_write = -1;
71 static int hf_nfs_access_xattr_list = -1;
72 static int hf_nfs_access_denied = -1;
73 static int hf_nfs_fh_length = -1;
74 static int hf_nfs_fh_hash = -1;
75 static int hf_nfs_fh_fhandle_data = -1;
76 static int hf_nfs_fh_mount_fileid = -1;
77 static int hf_nfs_fh_mount_generation = -1;
78 static int hf_nfs_fh_snapid = -1;
79 static int hf_nfs_fh_unused = -1;
80 static int hf_nfs_fh_flags = -1;
81 static int hf_nfs_fh_fileid = -1;
82 static int hf_nfs_fh_generation = -1;
83 static int hf_nfs_fh_fsid = -1;
84 static int hf_nfs_fh_export_fileid = -1;
85 static int hf_nfs_fh_export_generation = -1;
86 static int hf_nfs_fh_export_snapid = -1;
87 static int hf_nfs_fh_exportid = -1;
88 static int hf_nfs_fh_file_flag_mntpoint = -1;
89 static int hf_nfs_fh_file_flag_snapdir = -1;
90 static int hf_nfs_fh_file_flag_snapdir_ent = -1;
91 static int hf_nfs_fh_file_flag_empty = -1;
92 static int hf_nfs_fh_file_flag_vbn_access = -1;
93 static int hf_nfs_fh_file_flag_multivolume = -1;
94 static int hf_nfs_fh_file_flag_metadata = -1;
95 static int hf_nfs_fh_file_flag_orphan = -1;
96 static int hf_nfs_fh_file_flag_foster = -1;
97 static int hf_nfs_fh_file_flag_named_attr = -1;
98 static int hf_nfs_fh_file_flag_exp_snapdir = -1;
99 static int hf_nfs_fh_file_flag_vfiler = -1;
100 static int hf_nfs_fh_file_flag_aggr = -1;
101 static int hf_nfs_fh_file_flag_striped = -1;
102 static int hf_nfs_fh_file_flag_private = -1;
103 static int hf_nfs_fh_file_flag_next_gen = -1;
104 static int hf_nfs_fh_gfid = -1;
105 static int hf_nfs_fh_handle_type = -1;
106 static int hf_nfs_fh_fsid_major16_mask = -1;
107 static int hf_nfs_fh_fsid_minor16_mask = -1;
108 static int hf_nfs_fh_fsid_major16 = -1;
109 static int hf_nfs_fh_fsid_minor16 = -1;
110 static int hf_nfs_fh_fsid_major32 = -1;
111 static int hf_nfs_fh_fsid_minor32 = -1;
112 static int hf_nfs_fh_fsid_inode = -1;
113 static int hf_nfs_fh_xfsid_major = -1;
114 static int hf_nfs_fh_xfsid_minor = -1;
115 static int hf_nfs_fh_fstype = -1;
116 static int hf_nfs_fh_fn = -1;
117 static int hf_nfs_fh_fn_len = -1;
118 static int hf_nfs_fh_fn_inode = -1;
119 static int hf_nfs_fh_fn_generation = -1;
120 static int hf_nfs_fh_xfn = -1;
121 static int hf_nfs_fh_xfn_len = -1;
122 static int hf_nfs_fh_xfn_inode = -1;
123 static int hf_nfs_fh_xfn_generation = -1;
124 static int hf_nfs_fh_dentry = -1;
125 /* static int hf_nfs_fh_dev = -1; */
126 /* static int hf_nfs_fh_xdev = -1; */
127 static int hf_nfs_fh_dirinode = -1;
128 static int hf_nfs_fh_pinode = -1;
129 static int hf_nfs_fh_hp_len = -1;
130 static int hf_nfs_fh_hp_key = -1;
131 static int hf_nfs_fh_version = -1;
132 static int hf_nfs_fh_auth_type = -1;
133 static int hf_nfs_fh_fsid_type = -1;
134 static int hf_nfs_fh_fileid_type = -1;
135 static int hf_nfs_fh_obj_id = -1;
136 static int hf_nfs_fh_ro_node = -1;
137 static int hf_nfs_fh_obj = -1;
138 static int hf_nfs_fh_obj_fsid = -1;
139 static int hf_nfs_fh_obj_treeid = -1;
140 static int hf_nfs_fh_obj_kindid = -1;
141 static int hf_nfs_fh_obj_inode = -1;
142 static int hf_nfs_fh_obj_gen = -1;
143 static int hf_nfs_fh_ex = -1;
144 static int hf_nfs_fh_ex_fsid = -1;
145 static int hf_nfs_fh_ex_treeid = -1;
146 static int hf_nfs_fh_ex_kindid = -1;
147 static int hf_nfs_fh_ex_inode = -1;
148 static int hf_nfs_fh_ex_gen = -1;
149 static int hf_nfs_fh_flag = -1;
150 static int hf_nfs_fh_endianness = -1;
151 static int hf_nfs_fh_dc_opaque = -1;
152 static int hf_nfs_fh_dc_exportid = -1;
153 static int hf_nfs_fh_dc_handle_type = -1;
154 static int hf_nfs4_fh_pd_share = -1;
155 static int hf_nfs4_fh_pd_flags = -1;
156 static int hf_nfs4_fh_pd_flags_reserved = -1;
157 static int hf_nfs4_fh_pd_flags_version = -1;
158 static int hf_nfs4_fh_pd_container = -1;
159 static int hf_nfs4_fh_pd_inum = -1;
160 static int hf_nfs4_fh_pd_sites = -1;
161 static int hf_nfs4_fh_pd_sites_inum = -1;
162 static int hf_nfs4_fh_pd_sites_siteid = -1;
163 static int hf_nfs4_fh_pd_spaces = -1;
164 static int hf_nfs4_fh_pd_spaces_snapid = -1;
165 static int hf_nfs4_fh_pd_spaces_container = -1;
166 static int hf_nfs_full_name = -1;
167 static int hf_nfs_name = -1;
168 static int hf_nfs_data = -1;
169 static int hf_nfs_symlink_to = -1;
170 static int hf_nfs_readdir_eof = -1;
171 static int hf_nfs_readdir_entry = -1;
172 static int hf_nfs_atime = -1;
173 static int hf_nfs_atime_sec = -1;
174 static int hf_nfs_atime_nsec = -1;
175 static int hf_nfs_atime_usec = -1;
176 static int hf_nfs_mtime = -1;
177 static int hf_nfs_mtime_sec = -1;
178 static int hf_nfs_mtime_nsec = -1;
179 static int hf_nfs_mtime_usec = -1;
180 static int hf_nfs_ctime = -1;
181 static int hf_nfs_ctime_sec = -1;
182 static int hf_nfs_ctime_nsec = -1;
183 static int hf_nfs_ctime_usec = -1;
184 static int hf_nfs_dtime = -1;
185 static int hf_nfs_dtime_sec = -1;
186 static int hf_nfs_dtime_nsec = -1;
187 
188 /* Hidden field for v2, v3, and v4 status; also used in dissect-nfsacl.c */
189 int hf_nfs_status = -1;
190 
191 /* NFSv2 RFC 1094 hf variables */
192 static int hf_nfs2_procedure = -1;
193 static int hf_nfs2_status = -1;
194 static int hf_nfs2_readlink_data = -1;
195 /* static int hf_nfs2_fattr_type = -1; */
196 static int hf_nfs2_fattr_nlink = -1;
197 static int hf_nfs2_fattr_uid = -1;
198 static int hf_nfs2_fattr_gid = -1;
199 static int hf_nfs2_fattr_size = -1;
200 static int hf_nfs2_fattr_blocksize = -1;
201 static int hf_nfs2_fattr_rdev = -1;
202 static int hf_nfs2_fattr_blocks = -1;
203 static int hf_nfs2_fattr_fsid = -1;
204 static int hf_nfs2_fattr_fileid = -1;
205 static int hf_nfs2_ftype = -1;
206 static int hf_nfs2_mode = -1;
207 static int hf_nfs2_mode_name = -1;
208 static int hf_nfs2_mode_set_user_id = -1;
209 static int hf_nfs2_mode_set_group_id = -1;
210 static int hf_nfs2_mode_save_swap_text = -1;
211 static int hf_nfs2_mode_read_owner = -1;
212 static int hf_nfs2_mode_write_owner = -1;
213 static int hf_nfs2_mode_exec_owner = -1;
214 static int hf_nfs2_mode_read_group = -1;
215 static int hf_nfs2_mode_write_group = -1;
216 static int hf_nfs2_mode_exec_group = -1;
217 static int hf_nfs2_mode_read_other = -1;
218 static int hf_nfs2_mode_write_other = -1;
219 static int hf_nfs2_mode_exec_other = -1;
220 static int hf_nfs2_read_offset = -1;
221 static int hf_nfs2_read_count = -1;
222 static int hf_nfs2_read_totalcount = -1;
223 static int hf_nfs2_write_beginoffset = -1;
224 static int hf_nfs2_write_offset = -1;
225 static int hf_nfs2_write_totalcount = -1;
226 static int hf_nfs2_readdir_cookie = -1;
227 static int hf_nfs2_readdir_count = -1;
228 static int hf_nfs2_readdir_entry_fileid = -1;
229 static int hf_nfs2_readdir_entry_name = -1;
230 static int hf_nfs2_readdir_entry_cookie = -1;
231 static int hf_nfs2_statfs_tsize = -1;
232 static int hf_nfs2_statfs_bsize = -1;
233 static int hf_nfs2_statfs_blocks = -1;
234 static int hf_nfs2_statfs_bfree = -1;
235 static int hf_nfs2_statfs_bavail = -1;
236 
237 /* NFSv3 RFC 1813 header format variables */
238 static int hf_nfs3_procedure = -1;
239 static int hf_nfs3_fattr_type = -1;
240 static int hf_nfs3_fattr_nlink = -1;
241 static int hf_nfs3_fattr_uid = -1;
242 static int hf_nfs3_fattr_gid = -1;
243 static int hf_nfs3_fattr_size = -1;
244 static int hf_nfs3_fattr_used = -1;
245 /* static int hf_nfs3_fattr_rdev = -1; */
246 static int hf_nfs3_fattr_fsid = -1;
247 static int hf_nfs3_fattr_fileid = -1;
248 static int hf_nfs3_wcc_attr_size = -1;
249 static int hf_nfs3_set_size = -1;
250 static int hf_nfs3_cookie = -1;
251 static int hf_nfs3_fsstat_resok_tbytes = -1;
252 static int hf_nfs3_fsstat_resok_fbytes = -1;
253 static int hf_nfs3_fsstat_resok_abytes = -1;
254 static int hf_nfs3_fsstat_resok_tfiles = -1;
255 static int hf_nfs3_fsstat_resok_ffiles = -1;
256 static int hf_nfs3_fsstat_resok_afiles = -1;
257 static int hf_nfs3_uid = -1;
258 static int hf_nfs3_gid = -1;
259 static int hf_nfs3_offset = -1;
260 static int hf_nfs3_count = -1;
261 static int hf_nfs3_count_maxcount = -1;
262 static int hf_nfs3_count_dircount= -1;
263 static int hf_nfs3_mode = -1;
264 static int hf_nfs3_mode_suid = -1;
265 static int hf_nfs3_mode_sgid = -1;
266 static int hf_nfs3_mode_sticky = -1;
267 static int hf_nfs3_mode_rusr = -1;
268 static int hf_nfs3_mode_wusr = -1;
269 static int hf_nfs3_mode_xusr = -1;
270 static int hf_nfs3_mode_rgrp = -1;
271 static int hf_nfs3_mode_wgrp = -1;
272 static int hf_nfs3_mode_xgrp = -1;
273 static int hf_nfs3_mode_roth = -1;
274 static int hf_nfs3_mode_woth = -1;
275 static int hf_nfs3_mode_xoth = -1;
276 static int hf_nfs3_readdir_entry_fileid = -1;
277 static int hf_nfs3_readdir_entry_name = -1;
278 static int hf_nfs3_readdir_entry_cookie = -1;
279 static int hf_nfs3_readdirplus_entry_fileid = -1;
280 static int hf_nfs3_readdirplus_entry_name = -1;
281 static int hf_nfs3_readdirplus_entry_cookie = -1;
282 static int hf_nfs3_ftype = -1;
283 static int hf_nfs3_status = -1;
284 static int hf_nfs3_read_eof = -1;
285 static int hf_nfs3_write_stable = -1;
286 static int hf_nfs3_write_committed = -1;
287 static int hf_nfs3_createmode = -1;
288 static int hf_nfs3_fsstat_invarsec = -1;
289 static int hf_nfs3_fsinfo_rtmax = -1;
290 static int hf_nfs3_fsinfo_rtpref = -1;
291 static int hf_nfs3_fsinfo_rtmult = -1;
292 static int hf_nfs3_fsinfo_wtmax = -1;
293 static int hf_nfs3_fsinfo_wtpref = -1;
294 static int hf_nfs3_fsinfo_wtmult = -1;
295 static int hf_nfs3_fsinfo_dtpref = -1;
296 static int hf_nfs3_fsinfo_maxfilesize = -1;
297 static int hf_nfs3_fsinfo_properties = -1;
298 static int hf_nfs3_fsinfo_properties_setattr = -1;
299 static int hf_nfs3_fsinfo_properties_pathconf = -1;
300 static int hf_nfs3_fsinfo_properties_symlinks = -1;
301 static int hf_nfs3_fsinfo_properties_hardlinks = -1;
302 static int hf_nfs3_pathconf_linkmax = -1;
303 static int hf_nfs3_pathconf_name_max = -1;
304 static int hf_nfs3_pathconf_no_trunc = -1;
305 static int hf_nfs3_pathconf_chown_restricted = -1;
306 static int hf_nfs3_pathconf_case_insensitive = -1;
307 static int hf_nfs3_pathconf_case_preserving = -1;
308 static int hf_nfs3_gxfh_utlfield = -1;
309 static int hf_nfs3_gxfh_utlfield_tree = -1;
310 static int hf_nfs3_gxfh_utlfield_jun = -1;
311 static int hf_nfs3_gxfh_utlfield_ver = -1;
312 static int hf_nfs3_gxfh_volcnt = -1;
313 static int hf_nfs3_gxfh_epoch = -1;
314 static int hf_nfs3_gxfh_ldsid = -1;
315 static int hf_nfs3_gxfh_cid = -1;
316 static int hf_nfs3_gxfh_resv = -1;
317 static int hf_nfs3_gxfh_sfhflags = -1;
318 static int hf_nfs3_gxfh_sfhflags_resv1 = -1;
319 static int hf_nfs3_gxfh_sfhflags_resv2 = -1;
320 static int hf_nfs3_gxfh_sfhflags_ontap7G = -1;
321 static int hf_nfs3_gxfh_sfhflags_ontapGX = -1;
322 static int hf_nfs3_gxfh_sfhflags_striped = -1;
323 static int hf_nfs3_gxfh_sfhflags_empty = -1;
324 static int hf_nfs3_gxfh_sfhflags_snapdirent = -1;
325 static int hf_nfs3_gxfh_sfhflags_snapdir = -1;
326 static int hf_nfs3_gxfh_sfhflags_streamdir = -1;
327 static int hf_nfs3_gxfh_spinfid = -1;
328 static int hf_nfs3_gxfh_spinfuid = -1;
329 static int hf_nfs3_gxfh_exportptid = -1;
330 static int hf_nfs3_gxfh_exportptuid = -1;
331 static int hf_nfs3_verifier = -1;
332 static int hf_nfs3_specdata1 = -1;
333 static int hf_nfs3_specdata2 = -1;
334 static int hf_nfs3_attributes_follow = -1;
335 static int hf_nfs3_handle_follow = -1;
336 static int hf_nfs3_sattrguard3 = -1;
337 
338 
339 /* NFSv4 RFC 5661 header format variables */
340 static int hf_nfs4_procedure = -1;
341 static int hf_nfs4_status = -1;
342 static int hf_nfs4_op = -1;
343 static int hf_nfs4_main_opcode = -1;
344 static int hf_nfs4_linktext = -1;
345 static int hf_nfs4_tag = -1;
346 static int hf_nfs4_ops_count = -1;
347 static int hf_nfs4_pathname_components = -1;
348 static int hf_nfs4_component = -1;
349 static int hf_nfs4_clientid = -1;
350 /* static int hf_nfs4_ace = -1; */
351 static int hf_nfs4_recall = -1;
352 static int hf_nfs4_open_claim_type = -1;
353 static int hf_nfs4_opentype = -1;
354 static int hf_nfs4_state_protect_how = -1;
355 static int hf_nfs4_limit_by = -1;
356 static int hf_nfs4_open_delegation_type = -1;
357 static int hf_nfs4_why_no_delegation = -1;
358 static int hf_nfs4_ftype = -1;
359 static int hf_nfs4_change_info_atomic = -1;
360 static int hf_nfs4_open_share_access = -1;
361 static int hf_nfs4_open_share_deny = -1;
362 static int hf_nfs4_want_flags = -1;
363 static int hf_nfs4_want_notify_flags = -1;
364 static int hf_nfs4_want_signal_deleg_when_resrc_avail = -1;
365 static int hf_nfs4_want_push_deleg_when_uncontended = -1;
366 static int hf_nfs4_want_deleg_timestamps = -1;
367 static int hf_nfs4_seqid = -1;
368 static int hf_nfs4_lock_seqid = -1;
369 static int hf_nfs4_reqd_attr = -1;
370 static int hf_nfs4_reco_attr = -1;
371 static int hf_nfs4_attr_mask = -1;
372 static int hf_nfs4_attr_count = -1;
373 static int hf_nfs4_set_it_value_follows = -1;
374 static int hf_nfs4_time_how = -1;
375 static int hf_nfs4_time_how4 = -1;
376 static int hf_nfs4_fattr_link_support = -1;
377 static int hf_nfs4_fattr_symlink_support = -1;
378 static int hf_nfs4_fattr_named_attr = -1;
379 static int hf_nfs4_fattr_unique_handles = -1;
380 static int hf_nfs4_fattr_archive = -1;
381 static int hf_nfs4_fattr_cansettime = -1;
382 static int hf_nfs4_fattr_case_insensitive = -1;
383 static int hf_nfs4_fattr_case_preserving = -1;
384 static int hf_nfs4_fattr_chown_restricted = -1;
385 static int hf_nfs4_fattr_fh_expire_type = -1;
386 static int hf_nfs4_fattr_fh_expiry_noexpire_with_open = -1;
387 static int hf_nfs4_fattr_fh_expiry_volatile_any = -1;
388 static int hf_nfs4_fattr_fh_expiry_vol_migration = -1;
389 static int hf_nfs4_fattr_fh_expiry_vol_rename = -1;
390 static int hf_nfs4_fattr_hidden = -1;
391 static int hf_nfs4_fattr_homogeneous = -1;
392 static int hf_nfs4_fattr_mimetype = -1;
393 static int hf_nfs4_fattr_no_trunc = -1;
394 static int hf_nfs4_fattr_system = -1;
395 static int hf_nfs4_fattr_owner = -1;
396 static int hf_nfs4_fattr_owner_group = -1;
397 static int hf_nfs4_fattr_size = -1;
398 static int hf_nfs4_fattr_aclsupport = -1;
399 static int hf_nfs4_aclsupport_allow_acl = -1;
400 static int hf_nfs4_aclsupport_deny_acl = -1;
401 static int hf_nfs4_aclsupport_audit_acl = -1;
402 static int hf_nfs4_aclsupport_alarm_acl = -1;
403 static int hf_nfs4_fattr_lease_time = -1;
404 static int hf_nfs4_fattr_fs_charset_cap = -1;
405 static int hf_nfs4_fs_charset_cap_nonutf8 = -1;
406 static int hf_nfs4_fs_charset_cap_utf8 = -1;
407 static int hf_nfs4_fattr_fileid = -1;
408 static int hf_nfs4_fattr_files_avail = -1;
409 static int hf_nfs4_fattr_files_free = -1;
410 static int hf_nfs4_fattr_files_total = -1;
411 static int hf_nfs4_fattr_maxfilesize = -1;
412 static int hf_nfs4_fattr_maxlink = -1;
413 static int hf_nfs4_fattr_maxname = -1;
414 static int hf_nfs4_fattr_numlinks = -1;
415 static int hf_nfs4_fattr_maxread = -1;
416 static int hf_nfs4_fattr_maxwrite = -1;
417 static int hf_nfs4_fattr_quota_hard = -1;
418 static int hf_nfs4_fattr_quota_soft = -1;
419 static int hf_nfs4_fattr_quota_used = -1;
420 static int hf_nfs4_fattr_space_avail = -1;
421 static int hf_nfs4_fattr_space_free = -1;
422 static int hf_nfs4_fattr_space_total = -1;
423 static int hf_nfs4_fattr_space_used = -1;
424 static int hf_nfs4_fattr_mounted_on_fileid = -1;
425 static int hf_nfs4_fattr_layout_blksize = -1;
426 static int hf_nfs4_mdsthreshold_item = -1;
427 static int hf_nfs4_mdsthreshold_hint_mask = -1;
428 static int hf_nfs4_mdsthreshold_hint_count = -1;
429 static int hf_nfs4_mdsthreshold_mask_count = -1;
430 static int hf_nfs4_mdsthreshold_hint_file = -1;
431 static int hf_nfs4_fattr_security_label_lfs = -1;
432 static int hf_nfs4_fattr_security_label_pi = -1;
433 static int hf_nfs4_fattr_security_label_context = -1;
434 static int hf_nfs4_fattr_umask_mask = -1;
435 static int hf_nfs4_fattr_xattr_support = -1;
436 static int hf_nfs4_fattr_offline = -1;
437 static int hf_nfs4_who = -1;
438 static int hf_nfs4_server = -1;
439 static int hf_nfs4_servers = -1;
440 static int hf_nfs4_fslocation = -1;
441 static int hf_nfs4_stable_how = -1;
442 static int hf_nfs4_dirlist_eof = -1;
443 static int hf_nfs4_offset = -1;
444 static int hf_nfs4_specdata1 = -1;
445 static int hf_nfs4_specdata2 = -1;
446 static int hf_nfs4_lock_type = -1;
447 static int hf_nfs4_open_rflags = -1;
448 static int hf_nfs4_open_rflags_confirm = -1;
449 static int hf_nfs4_open_rflags_locktype_posix = -1;
450 static int hf_nfs4_open_rflags_preserve_unlinked = -1;
451 static int hf_nfs4_open_rflags_may_notify_lock = -1;
452 static int hf_nfs4_reclaim = -1;
453 static int hf_nfs4_length = -1;
454 static int hf_nfs4_changeid = -1;
455 static int hf_nfs4_changeid_before = -1;
456 static int hf_nfs4_changeid_after = -1;
457 static int hf_nfs4_time_seconds = -1;
458 static int hf_nfs4_time_nseconds = -1;
459 static int hf_nfs4_fsid_major = -1;
460 static int hf_nfs4_fsid_minor = -1;
461 static int hf_nfs4_acetype = -1;
462 static int hf_nfs4_aceflags = -1;
463 static int hf_nfs4_aceflag_file_inherit = -1;
464 static int hf_nfs4_aceflag_dir_inherit = -1;
465 static int hf_nfs4_aceflag_no_prop_inherit = -1;
466 static int hf_nfs4_aceflag_inherit_only = -1;
467 static int hf_nfs4_aceflag_successful_access = -1;
468 static int hf_nfs4_aceflag_failed_access = -1;
469 static int hf_nfs4_aceflag_id_group = -1;
470 static int hf_nfs4_aceflag_inherited_ace = -1;
471 static int hf_nfs4_acemask = -1;
472 static int hf_nfs4_ace_permission = -1;
473 static int hf_nfs4_delegate_type = -1;
474 static int hf_nfs4_secinfo_flavor = -1;
475 static int hf_nfs4_secinfo_arr = -1;
476 static int hf_nfs4_num_blocks = -1;
477 static int hf_nfs4_bytes_per_block = -1;
478 static int hf_nfs4_eof = -1;
479 static int hf_nfs4_verifier = -1;
480 static int hf_nfs4_value_follows = -1;
481 static int hf_nfs4_cookie = -1;
482 static int hf_nfs4_dir_entry_name = -1;
483 static int hf_nfs4_cookie_verf = -1;
484 static int hf_nfs4_cb_program = -1;
485 /* static int hf_nfs4_cb_location = -1; */
486 static int hf_nfs4_recall4 = -1;
487 static int hf_nfs4_filesize = -1;
488 static int hf_nfs4_count = -1;
489 static int hf_nfs4_count_dircount = -1;
490 static int hf_nfs4_count_maxcount = -1;
491 static int hf_nfs4_minorversion = -1;
492 static int hf_nfs4_open_owner = -1;
493 static int hf_nfs4_lock_owner = -1;
494 static int hf_nfs4_new_lock_owner = -1;
495 static int hf_nfs4_sec_oid = -1;
496 static int hf_nfs4_qop = -1;
497 static int hf_nfs4_secinfo_rpcsec_gss_info_service = -1;
498 static int hf_nfs4_attr_dir_create = -1;
499 static int hf_nfs4_client_id = -1;
500 static int hf_nfs4_stateid = -1;
501 static int hf_nfs4_seqid_stateid = -1;
502 static int hf_nfs4_stateid_other = -1;
503 static int hf_nfs4_stateid_hash = -1;
504 static int hf_nfs4_stateid_other_hash = -1;
505 static int hf_nfs4_lock_reclaim = -1;
506 static int hf_nfs4_aclflags = -1;
507 static int hf_nfs4_aclflag_auto_inherit = -1;
508 static int hf_nfs4_aclflag_protected = -1;
509 static int hf_nfs4_aclflag_defaulted = -1;
510 static int hf_nfs4_num_aces = -1;
511 static int hf_nfs4_callback_ident = -1;
512 static int hf_nfs4_r_netid = -1;
513 static int hf_nfs4_gsshandle = -1;
514 static int hf_nfs4_r_addr = -1;
515 static int hf_nfs4_createmode = -1;
516 static int hf_nfs4_op_mask = -1;
517 static int hf_nfs4_read_data_length = -1;
518 static int hf_nfs4_write_data_length = -1;
519 static int hf_nfs4_length_minlength = -1;
520 static int hf_nfs4_layout_type = -1;
521 static int hf_nfs4_layout_return_type = -1;
522 static int hf_nfs4_iomode = -1;
523 /* static int hf_nfs4_stripetype = -1; */
524 /* static int hf_nfs4_mdscommit = -1; */
525 static int hf_nfs4_stripeunit = -1;
526 static int hf_nfs4_newtime = -1;
527 static int hf_nfs4_newoffset = -1;
528 static int hf_nfs4_layout_avail = -1;
529 static int hf_nfs4_newsize = -1;
530 static int hf_nfs4_layoutupdate = -1;
531 static int hf_nfs4_deviceid = -1;
532 static int hf_nfs4_devicenum = -1;
533 static int hf_nfs4_deviceidx = -1;
534 static int hf_nfs4_layout = -1;
535 /* static int hf_nfs4_stripedevs = -1; */
536 /* static int hf_nfs4_devaddr = -1; */
537 static int hf_nfs4_devaddr_ssv_start = -1;
538 static int hf_nfs4_devaddr_ssv_length = -1;
539 static int hf_nfs4_devaddr_scsi_vol_type = -1;
540 static int hf_nfs4_devaddr_scsi_vol_index = -1;
541 static int hf_nfs4_devaddr_scsi_vol_ref_index = -1;
542 static int hf_nfs4_devaddr_ssv_stripe_unit = -1;
543 static int hf_nfs4_devaddr_scsi_vpd_code_set = -1;
544 static int hf_nfs4_devaddr_scsi_vpd_designator_type = -1;
545 static int hf_nfs4_devaddr_scsi_vpd_designator = -1;
546 static int hf_nfs4_devaddr_scsi_private_key = -1;
547 static int hf_nfs4_scsil_ext_file_offset = -1;
548 static int hf_nfs4_scsil_ext_length = -1;
549 static int hf_nfs4_scsil_ext_vol_offset = -1;
550 static int hf_nfs4_scsil_ext_state = -1;
551 static int hf_nfs4_return_on_close = -1;
552 static int hf_nfs4_slotid = -1;
553 static int hf_nfs4_high_slotid = -1;
554 static int hf_nfs4_target_high_slotid = -1;
555 static int hf_nfs4_serverscope4 = -1;
556 static int hf_nfs4_minorid = -1;
557 static int hf_nfs4_majorid = -1;
558 static int hf_nfs4_padsize = -1;
559 /* static int hf_nfs4_cbrenforce = -1; */
560 /* static int hf_nfs4_hashalg = -1; */
561 /* static int hf_nfs4_ssvlen = -1; */
562 static int hf_nfs4_maxreqsize = -1;
563 static int hf_nfs4_maxrespsize = -1;
564 static int hf_nfs4_maxrespsizecached = -1;
565 static int hf_nfs4_maxops = -1;
566 static int hf_nfs4_maxreqs = -1;
567 static int hf_nfs4_rdmachanattrs = -1;
568 static int hf_nfs4_machinename = -1;
569 static int hf_nfs4_flavor = -1;
570 static int hf_nfs4_stamp = -1;
571 static int hf_nfs4_uid = -1;
572 static int hf_nfs4_gid = -1;
573 static int hf_nfs4_service = -1;
574 static int hf_nfs4_sessionid = -1;
575 static int hf_nfs4_exchid_call_flags = -1;
576 static int hf_nfs4_exchid_reply_flags = -1;
577 static int hf_nfs4_exchid_flags_moved_refer = -1;
578 static int hf_nfs4_exchid_flags_moved_migr = -1;
579 static int hf_nfs4_exchid_flags_bind_princ = -1;
580 static int hf_nfs4_exchid_flags_non_pnfs = -1;
581 static int hf_nfs4_exchid_flags_pnfs_mds = -1;
582 static int hf_nfs4_exchid_flags_pnfs_ds = -1;
583 static int hf_nfs4_exchid_flags_upd_conf_rec_a = -1;
584 static int hf_nfs4_exchid_flags_confirmed_r = -1;
585 static int hf_nfs4_state_protect_window = -1;
586 static int hf_nfs4_state_protect_num_gss_handles = -1;
587 static int hf_nfs4_sp_parms_hash_algs = -1;
588 static int hf_nfs4_sp_parms_encr_algs = -1;
589 static int hf_nfs4_prot_info_spi_window = -1;
590 static int hf_nfs4_prot_info_svv_length = -1;
591 static int hf_nfs4_prot_info_encr_alg = -1;
592 static int hf_nfs4_prot_info_hash_alg = -1;
593 static int hf_nfs4_nii_domain = -1;
594 static int hf_nfs4_nii_name = -1;
595 static int hf_nfs4_create_session_flags_csa = -1;
596 static int hf_nfs4_create_session_flags_csr = -1;
597 static int hf_nfs4_create_session_flags_persist = -1;
598 static int hf_nfs4_create_session_flags_conn_back_chan = -1;
599 static int hf_nfs4_create_session_flags_conn_rdma = -1;
600 static int hf_nfs4_cachethis = -1;
601 /* static int hf_nfs4_util = -1; */
602 /* static int hf_nfs4_first_stripe_idx = -1; */
603 /* static int hf_nfs4_layout_count = -1; */
604 /* static int hf_nfs4_pattern_offset = -1; */
605 static int hf_nfs4_notification_mask = -1;
606 static int hf_nfs4_notification_type = -1;
607 static int hf_nfs4_lrs_present = -1;
608 static int hf_nfs4_nfl_mirrors = -1;
609 static int hf_nfs4_nfl_util = -1;
610 static int hf_nfs4_nfl_util_stripe_size = -1;
611 static int hf_nfs4_nfl_util_commit_thru_mds = -1;
612 static int hf_nfs4_nfl_util_dense = -1;
613 static int hf_nfs4_nfl_fhs = -1;
614 static int hf_nfs4_mirror_eff = -1;
615 static int hf_nfs4_nfl_first_stripe_index = -1;
616 static int hf_nfs4_lrf_body_content = -1;
617 static int hf_nfs4_reclaim_one_fs = -1;
618 static int hf_nfs4_bctsa_dir = -1;
619 static int hf_nfs4_bctsa_use_conn_in_rdma_mode = -1;
620 static int hf_nfs4_bctsr_dir = -1;
621 static int hf_nfs4_bctsr_use_conn_in_rdma_mode = -1;
622 static int hf_nfs4_sequence_status_flags = -1;
623 static int hf_nfs4_sequence_status_flags_cb_path_down = -1;
624 static int hf_nfs4_sequence_status_flags_cb_gss_contexts_expiring = -1;
625 static int hf_nfs4_sequence_status_flags_cb_gss_contexts_expired = -1;
626 static int hf_nfs4_sequence_status_flags_expired_all_state_revoked = -1;
627 static int hf_nfs4_sequence_status_flags_expired_some_state_revoked = -1;
628 static int hf_nfs4_sequence_status_flags_admin_state_revoked = -1;
629 static int hf_nfs4_sequence_status_flags_recallable_state_revoked = -1;
630 static int hf_nfs4_sequence_status_flags_lease_moved = -1;
631 static int hf_nfs4_sequence_status_flags_restart_reclaim_needed = -1;
632 static int hf_nfs4_sequence_status_flags_cb_path_down_session = -1;
633 static int hf_nfs4_sequence_status_flags_backchannel_fault = -1;
634 static int hf_nfs4_sequence_status_flags_devid_changed = -1;
635 static int hf_nfs4_sequence_status_flags_devid_deleted = -1;
636 static int hf_nfs4_secinfo_style = -1;
637 static int hf_nfs4_test_stateid_arg = -1;
638 static int hf_nfs4_test_stateid_res = -1;
639 static int hf_nfs4_seek_data_content = -1;
640 /* static int hf_nfs4_impl_id_len = -1; */
641 static int hf_nfs4_bitmap_data = -1;
642 static int hf_nfs4_huge_bitmap_length = -1;
643 static int hf_nfs4_universal_address_ipv4 = -1;
644 static int hf_nfs4_universal_address_ipv6 = -1;
645 static int hf_nfs4_getdevinfo = -1;
646 static int hf_nfs4_ff_version = -1;
647 static int hf_nfs4_ff_minorversion = -1;
648 static int hf_nfs4_ff_tightly_coupled = -1;
649 static int hf_nfs4_ff_rsize = -1;
650 static int hf_nfs4_ff_wsize = -1;
651 static int hf_nfs4_fattr_clone_blocksize = -1;
652 static int hf_nfs4_fattr_space_freed = -1;
653 static int hf_nfs4_fattr_change_attr_type = -1;
654 static int hf_nfs4_ff_layout_flags = -1;
655 static int hf_nfs4_ff_layout_flags_no_layoutcommit = -1;
656 static int hf_nfs4_ff_layout_flags_no_io_thru_mds = -1;
657 static int hf_nfs4_ff_layout_flags_no_read_io = -1;
658 static int hf_nfs4_ff_stats_collect_hint = -1;
659 static int hf_nfs4_ff_synthetic_owner = -1;
660 static int hf_nfs4_ff_synthetic_owner_group = -1;
661 static int hf_nfs4_ff_bytes_completed = -1;
662 static int hf_nfs4_ff_bytes_not_delivered = -1;
663 static int hf_nfs4_ff_bytes_requested = -1;
664 static int hf_nfs4_ff_local = -1;
665 static int hf_nfs4_ff_ops_completed = -1;
666 static int hf_nfs4_ff_ops_requested = -1;
667 static int hf_nfs4_io_bytes = -1;
668 static int hf_nfs4_io_count = -1;
669 static int hf_nfs4_layoutstats = -1;
670 static int hf_nfs4_callback_stateids = -1;
671 static int hf_nfs4_callback_stateids_index = -1;
672 static int hf_nfs4_num_offload_status = -1;
673 static int hf_nfs4_offload_status_index = -1;
674 static int hf_nfs4_consecutive = -1;
675 static int hf_nfs4_netloc = -1;
676 static int hf_nfs4_netloc_type = -1;
677 static int hf_nfs4_nl_name = -1;
678 static int hf_nfs4_nl_url = -1;
679 static int hf_nfs4_source_server_index = -1;
680 static int hf_nfs4_source_servers = -1;
681 static int hf_nfs4_synchronous = -1;
682 static int hf_nfs4_device_error_count = -1;
683 static int hf_nfs4_device_errors_index = -1;
684 static int hf_nfs4_ff_ioerrs_count = -1;
685 static int hf_nfs4_ff_ioerrs_index = -1;
686 static int hf_nfs4_ff_ioerrs_length = -1;
687 static int hf_nfs4_ff_ioerrs_offset = -1;
688 static int hf_nfs4_ff_iostats_count = -1;
689 static int hf_nfs4_ff_iostats_index = -1;
690 static int hf_nfs4_io_error_op = -1;
691 static int hf_nfs4_io_hints_mask = -1;
692 static int hf_nfs4_io_hint_count = -1;
693 static int hf_nfs4_io_advise_hint = -1;
694 static int hf_nfs4_bytes_copied = -1;
695 static int hf_nfs4_read_plus_contents = -1;
696 static int hf_nfs4_read_plus_content_type = -1;
697 static int hf_nfs4_block_size = -1;
698 static int hf_nfs4_block_count = -1;
699 static int hf_nfs4_reloff_blocknum = -1;
700 static int hf_nfs4_blocknum = -1;
701 static int hf_nfs4_reloff_pattern = -1;
702 static int hf_nfs4_pattern_hash = -1;
703 static int hf_nfs4_setxattr_options = -1;
704 static int hf_nfs4_listxattr_maxcount = -1;
705 static int hf_nfs4_listxattr_cookie = -1;
706 static int hf_nfs4_listxattr_names_len = -1;
707 static int hf_nfs4_xattrkey = -1;
708 static int hf_nfs4_listxattr_eof = -1;
709 
710 static gint ett_nfs = -1;
711 static gint ett_nfs_fh_encoding = -1;
712 static gint ett_nfs_fh_mount = -1;
713 static gint ett_nfs_fh_file = -1;
714 static gint ett_nfs_fh_export = -1;
715 static gint ett_nfs_fh_fsid = -1;
716 static gint ett_nfs_fh_xfsid = -1;
717 static gint ett_nfs_fh_fn = -1;
718 static gint ett_nfs_fh_xfn = -1;
719 static gint ett_nfs_fh_hp = -1;
720 static gint ett_nfs_fh_auth = -1;
721 static gint ett_nfs_fhandle = -1;
722 static gint ett_nfs_timeval = -1;
723 static gint ett_nfs_fattr = -1;
724 static gint ett_nfs_readdir_entry = -1;
725 static gint ett_nfs_fh_obj = -1;
726 static gint ett_nfs_fh_ex = -1;
727 static gint ett_nfs_utf8string = -1;
728 
729 static gint ett_nfs2_mode = -1;
730 static gint ett_nfs2_sattr = -1;
731 static gint ett_nfs2_diropargs = -1;
732 
733 static gint ett_nfs3_mode = -1;
734 static gint ett_nfs3_specdata = -1;
735 static gint ett_nfs3_fh = -1;
736 static gint ett_nfs3_nfstime = -1;
737 static gint ett_nfs3_fattr = -1;
738 static gint ett_nfs3_post_op_fh = -1;
739 static gint ett_nfs3_sattr = -1;
740 static gint ett_nfs3_diropargs = -1;
741 static gint ett_nfs3_sattrguard = -1;
742 static gint ett_nfs3_set_mode = -1;
743 static gint ett_nfs3_set_uid = -1;
744 static gint ett_nfs3_set_gid = -1;
745 static gint ett_nfs3_set_size = -1;
746 static gint ett_nfs3_set_atime = -1;
747 static gint ett_nfs3_set_mtime = -1;
748 static gint ett_nfs3_pre_op_attr = -1;
749 static gint ett_nfs3_post_op_attr = -1;
750 static gint ett_nfs3_wcc_attr = -1;
751 static gint ett_nfs3_wcc_data = -1;
752 static gint ett_nfs3_access = -1;
753 static gint ett_nfs3_fsinfo_properties = -1;
754 static gint ett_nfs3_gxfh_utlfield = -1;
755 static gint ett_nfs3_gxfh_sfhfield = -1;
756 static gint ett_nfs3_gxfh_sfhflags = -1;
757 static gint ett_nfs4_fh_pd_flags = -1;
758 static gint ett_nfs4_fh_pd_sites = -1;
759 static gint ett_nfs4_fh_pd_spaces = -1;
760 
761 static gint ett_nfs4_compound_call = -1;
762 static gint ett_nfs4_request_op = -1;
763 static gint ett_nfs4_response_op = -1;
764 static gint ett_nfs4_access = -1;
765 static gint ett_nfs4_access_supp = -1;
766 static gint ett_nfs4_close = -1;
767 static gint ett_nfs4_commit = -1;
768 static gint ett_nfs4_create = -1;
769 static gint ett_nfs4_delegpurge = -1;
770 static gint ett_nfs4_delegreturn = -1;
771 static gint ett_nfs4_getattr = -1;
772 static gint ett_nfs4_getattr_args = -1;
773 static gint ett_nfs4_getattr_resp = -1;
774 static gint ett_nfs4_resok4 = -1;
775 static gint ett_nfs4_obj_attrs = -1;
776 static gint ett_nfs4_fattr_new_attr_vals = -1;
777 static gint ett_nfs4_fattr4_attrmask = -1;
778 static gint ett_nfs4_attribute = -1;
779 static gint ett_nfs4_getfh = -1;
780 static gint ett_nfs4_link = -1;
781 static gint ett_nfs4_lock = -1;
782 static gint ett_nfs4_lockt = -1;
783 static gint ett_nfs4_locku = -1;
784 static gint ett_nfs4_lookup = -1;
785 static gint ett_nfs4_lookupp = -1;
786 static gint ett_nfs4_nverify = -1;
787 static gint ett_nfs4_open = -1;
788 static gint ett_nfs4_openattr = -1;
789 static gint ett_nfs4_open_confirm = -1;
790 static gint ett_nfs4_open_downgrade = -1;
791 static gint ett_nfs4_putfh = -1;
792 static gint ett_nfs4_putpubfh = -1;
793 static gint ett_nfs4_putrootfh = -1;
794 static gint ett_nfs4_read = -1;
795 static gint ett_nfs4_readdir = -1;
796 static gint ett_nfs4_readlink = -1;
797 static gint ett_nfs4_remove = -1;
798 static gint ett_nfs4_rename = -1;
799 static gint ett_nfs4_renew = -1;
800 static gint ett_nfs4_restorefh = -1;
801 static gint ett_nfs4_savefh = -1;
802 static gint ett_nfs4_secinfo = -1;
803 static gint ett_nfs4_setattr = -1;
804 static gint ett_nfs4_setclientid = -1;
805 static gint ett_nfs4_setclientid_confirm = -1;
806 static gint ett_nfs4_verify = -1;
807 static gint ett_nfs4_write = -1;
808 static gint ett_nfs4_release_lockowner = -1;
809 static gint ett_nfs4_backchannel_ctl = -1;
810 static gint ett_nfs4_illegal = -1;
811 static gint ett_nfs4_verifier = -1;
812 static gint ett_nfs4_dirlist = -1;
813 static gint ett_nfs4_dir_entry = -1;
814 static gint ett_nfs4_pathname = -1;
815 static gint ett_nfs4_change_info = -1;
816 static gint ett_nfs4_open_delegation = -1;
817 static gint ett_nfs4_open_claim = -1;
818 static gint ett_nfs4_opentype = -1;
819 static gint ett_nfs4_lock_owner = -1;
820 static gint ett_nfs4_cb_client = -1;
821 static gint ett_nfs4_client_id = -1;
822 static gint ett_nfs4_clientowner = -1;
823 static gint ett_nfs4_exchangeid_call_flags = -1;
824 static gint ett_nfs4_exchangeid_reply_flags = -1;
825 static gint ett_nfs4_server_owner = -1;
826 static gint ett_nfs4_bitmap = -1;
827 static gint ett_nfs4_attr_request = -1;
828 static gint ett_nfs4_fattr = -1;
829 static gint ett_nfs4_fsid = -1;
830 static gint ett_nfs4_fs_locations = -1;
831 static gint ett_nfs4_fs_location = -1;
832 static gint ett_nfs4_open_result_flags = -1;
833 static gint ett_nfs4_secinfo_flavor_info = -1;
834 static gint ett_nfs4_stateid = -1;
835 static gint ett_nfs4_fattr_fh_expire_type = -1;
836 static gint ett_nfs4_fattr_fs_charset_cap = -1;
837 static gint ett_nfs4_fattr_aclsupport = -1;
838 static gint ett_nfs4_aclflag = -1;
839 static gint ett_nfs4_ace = -1;
840 static gint ett_nfs4_clientaddr = -1;
841 static gint ett_nfs4_aceflag = -1;
842 static gint ett_nfs4_acemask = -1;
843 static gint ett_nfs4_create_session_flags = -1;
844 static gint ett_nfs4_sequence_status_flags = -1;
845 static gint ett_nfs4_fh_file   = -1;
846 static gint ett_nfs4_fh_file_flags = -1;
847 static gint ett_nfs4_fh_export = -1;
848 static gint ett_nfs4_layoutget = -1;
849 static gint ett_nfs4_layoutcommit = -1;
850 static gint ett_nfs4_layoutreturn = -1;
851 static gint ett_nfs4_getdevinfo = -1;
852 static gint ett_nfs4_getdevlist = -1;
853 static gint ett_nfs4_bind_conn_to_session = -1;
854 static gint ett_nfs4_exchange_id = -1;
855 static gint ett_nfs4_create_session = -1;
856 static gint ett_nfs4_destroy_session = -1;
857 static gint ett_nfs4_free_stateid = -1;
858 static gint ett_nfs4_secinfo_no_name = -1;
859 static gint ett_nfs4_sequence = -1;
860 static gint ett_nfs4_slotid = -1;
861 static gint ett_nfs4_sr_status = -1;
862 static gint ett_nfs4_serverscope = -1;
863 static gint ett_nfs4_minorid = -1;
864 static gint ett_nfs4_majorid = -1;
865 static gint ett_nfs4_persist = -1;
866 static gint ett_nfs4_backchan = -1;
867 static gint ett_nfs4_rdmamode = -1;
868 static gint ett_nfs4_padsize = -1;
869 static gint ett_nfs4_cbrenforce = -1;
870 static gint ett_nfs4_hashalg = -1;
871 static gint ett_nfs4_ssvlen = -1;
872 static gint ett_nfs4_maxreqsize = -1;
873 static gint ett_nfs4_maxrespsize = -1;
874 static gint ett_nfs4_maxrespsizecached = -1;
875 static gint ett_nfs4_maxops = -1;
876 static gint ett_nfs4_maxreqs = -1;
877 static gint ett_nfs4_streamchanattrs = -1;
878 static gint ett_nfs4_rdmachanattrs = -1;
879 static gint ett_nfs4_machinename = -1;
880 static gint ett_nfs4_flavor = -1;
881 static gint ett_nfs4_stamp = -1;
882 static gint ett_nfs4_uid = -1;
883 static gint ett_nfs4_gid = -1;
884 static gint ett_nfs4_service = -1;
885 static gint ett_nfs4_sessionid = -1;
886 static gint ett_nfs4_layoutseg = -1;
887 static gint ett_nfs4_layoutseg_sub = -1;
888 static gint ett_nfs4_nfl_util = -1;
889 static gint ett_nfs4_test_stateid = -1;
890 static gint ett_nfs4_destroy_clientid = -1;
891 static gint ett_nfs4_reclaim_complete = -1;
892 static gint ett_nfs4_allocate = -1;
893 static gint ett_nfs4_deallocate = -1;
894 static gint ett_nfs4_seek = -1;
895 static gint ett_nfs4_chan_attrs = -1;
896 static gint ett_nfs4_want_notify_flags = -1;
897 static gint ett_nfs4_ff_layout_flags = -1;
898 static gint ett_nfs4_scsi_layout_vol = -1;
899 static gint ett_nfs4_scsi_layout_vol_indices = -1;
900 static gint ett_nfs4_layoutstats = -1;
901 static gint ett_nfs4_io_info = -1;
902 static gint ett_nfs4_io_latency = -1;
903 static gint ett_nfs4_io_time = -1;
904 static gint ett_nfs4_callback_stateids_sub = -1;
905 static gint ett_nfs4_source_servers_sub = -1;
906 static gint ett_nfs4_copy = -1;
907 static gint ett_nfs4_copy_notify = -1;
908 static gint ett_nfs4_device_errors_sub = -1;
909 static gint ett_nfs4_layouterror = -1;
910 static gint ett_nfs4_ff_ioerrs_sub = -1;
911 static gint ett_nfs4_ff_iostats_sub = -1;
912 static gint ett_nfs4_clone = -1;
913 static gint ett_nfs4_getxattr = -1;
914 static gint ett_nfs4_setxattr = -1;
915 static gint ett_nfs4_listxattr = -1;
916 static gint ett_nfs4_removexattr = -1;
917 static gint ett_nfs4_offload_cancel = -1;
918 static gint ett_nfs4_offload_status = -1;
919 static gint ett_nfs4_osr_complete_sub = -1;
920 static gint ett_nfs4_io_advise = -1;
921 static gint ett_nfs4_read_plus = -1;
922 static gint ett_nfs4_read_plus_content_sub = -1;
923 static gint ett_nfs4_write_same = -1;
924 static gint ett_nfs4_listxattr_names = -1;
925 
926 static expert_field ei_nfs_too_many_ops = EI_INIT;
927 static expert_field ei_nfs_not_vnx_file = EI_INIT;
928 static expert_field ei_protocol_violation = EI_INIT;
929 static expert_field ei_nfs_too_many_bitmaps = EI_INIT;
930 static expert_field ei_nfs_bitmap_no_dissector = EI_INIT;
931 static expert_field ei_nfs_bitmap_skip_value = EI_INIT;
932 static expert_field ei_nfs_bitmap_undissected_data = EI_INIT;
933 static expert_field ei_nfs4_stateid_deprecated = EI_INIT;
934 static expert_field ei_nfs_file_system_cycle = EI_INIT;
935 
936 static const true_false_string tfs_read_write = { "Read", "Write" };
937 
938 /*
939  * Bitmaps are currently used for attributes and state_protect bits.
940  * Currently we don't expect more than 4 words, but future protocol
941  * revisions might add more bits, and in theory an implementation
942  * might legally zero-pad a bitmask out to something longer.  We keep
943  * a generous maximum here just as a sanity check:
944  */
945 #define MAX_BITMAPS 100
946 
947 /* Prototype for function to dissect attribute value */
948 typedef int (dissect_bitmap_item_t)(tvbuff_t *tvb, int offset, packet_info *pinfo,
949 		rpc_call_info_value *civ, proto_tree *attr_tree, proto_item *attr_item,
950 		guint32 bit_num, void *battr_data);
951 
952 /* Prototype for function to return the header field for the item label */
953 typedef int (get_bitmap_hinfo_t)(guint32 bit_num);
954 
955 /* Bitmap type */
956 typedef enum {
957 	NFS4_BITMAP_MASK,   /* Dissect the bitmap mask only */
958 	NFS4_BITMAP_VALUES  /* Dissect the bitmap mask and their values */
959 } nfs4_bitmap_type_t;
960 
961 /*
962  * Bitmap info structure to customize dissect_nfs4_bitmap() behavior
963  * Do not display the item when its corresponding hf_* label is set to NULL
964  */
965 typedef struct _nfs4_bitmap_info_t {
966 	value_string_ext       *vse_names_ext; /* Extended value strings which maps bit number to attribute name,
967 						* append list of attribute names to the attr mask header line */
968 	dissect_bitmap_item_t  *dissect_battr; /* Function to dissect attribute value given by the bit number */
969 
970 	void *battr_data;      /* Data pass to function dissect_battr */
971 
972 	int  *hf_mask_label;   /* Label for bitmap mask. If this is set to NULL the mask bytes are just consumed */
973 	int  *hf_item_label;   /* Label for bitmap item (see get_item_label below) */
974 	int  *hf_item_count;   /* Label for hidden attribute to display the number of bits set */
975 	int  *hf_mask_count;   /* Label to display the number of masks in the bitmap */
976 	int  *hf_btmap_data;   /* Label to display bitmap value data as an opaque */
977 
978 	get_bitmap_hinfo_t  *get_item_label;   /* Pointer to function to return a dynamically generated hf variable
979 						* for the item label, this takes precedence over hf_item_label */
980 } nfs4_bitmap_info_t;
981 
982 /* Types of fhandles we can dissect */
983 static dissector_table_t nfs_fhandle_table;
984 
985 typedef struct nfs_fhandle_data {
986 	int len;
987 	const unsigned char *fh;
988 } nfs_fhandle_data_t;
989 
990 /* For dissector helpers which take a "levels" argument to indicate how
991  * many expansions up they should populate the expansion items with
992  * text to enhance useability, this flag to "levels" specify that the
993  * text should also be appended to COL_INFO
994  */
995 #define COL_INFO_LEVEL 0x80000000
996 
997 
998 /* fhandle displayfilters to match also corresponding request/response
999    packet in addition to the one containing the actual filehandle */
1000 gboolean nfs_fhandle_reqrep_matching = FALSE;
1001 static wmem_tree_t *nfs_fhandle_frame_table = NULL;
1002 
1003 
1004 /* file name snooping */
1005 gboolean nfs_file_name_snooping = FALSE;
1006 static gboolean nfs_file_name_full_snooping = FALSE;
1007 typedef struct nfs_name_snoop {
1008 	int	       fh_length;
1009 	unsigned char *fh;
1010 	int	       name_len;
1011 	char	      *name;
1012 	int	       parent_len;
1013 	unsigned char *parent;
1014 	int	       full_name_len;
1015 	char	      *full_name;
1016 	bool	       fs_cycle;
1017 } nfs_name_snoop_t;
1018 
1019 typedef struct nfs_name_snoop_key {
1020 	int key;
1021 	int fh_length;
1022 	const unsigned char *fh;
1023 } nfs_name_snoop_key_t;
1024 
1025 static GHashTable *nfs_name_snoop_unmatched = NULL;
1026 
1027 static GHashTable *nfs_name_snoop_matched = NULL;
1028 
1029 static wmem_tree_t *nfs_name_snoop_known = NULL;
1030 static wmem_tree_t *nfs_file_handles = NULL;
1031 
1032 static gboolean nfs_display_v4_tag = TRUE;
1033 static gboolean display_major_nfs4_ops = TRUE;
1034 
1035 /* Types of RDMA reduced opaque data */
1036 typedef enum {
1037 	R_UTF8STRING,
1038 	R_NFS2_PATH,
1039 	R_NFS3_PATH,
1040 	R_NFSDATA,
1041 } rdma_reduce_type_t;
1042 
1043 static int dissect_nfsdata_reduced(rdma_reduce_type_t rtype, tvbuff_t *tvb,
1044 			int offset, proto_tree *tree, int hf, const char **name);
1045 
1046 static int dissect_nfs4_stateid(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash);
1047 
nfs_prompt(packet_info * pinfo _U_,gchar * result)1048 static void nfs_prompt(packet_info *pinfo _U_, gchar* result)
1049 {
1050 	g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Decode NFS file handles as");
1051 }
1052 
1053 /* This function will store one nfs filehandle in our global tree of
1054  * filehandles.
1055  * We store all filehandles we see in this tree so that every unique
1056  * filehandle is only stored once with a unique pointer.
1057  * We need to store pointers to filehandles in several of our other
1058  * structures and this is a way to make sure we don't keep any redundant
1059  * copies around for a specific filehandle.
1060  *
1061  * If this is the first time this filehandle has been seen an se block
1062  * is allocated to store the filehandle in.
1063  * If this filehandle has already been stored in the tree this function returns
1064  * a pointer to the original copy.
1065  */
1066 static nfs_fhandle_data_t *
store_nfs_file_handle(nfs_fhandle_data_t * nfs_fh)1067 store_nfs_file_handle(nfs_fhandle_data_t *nfs_fh)
1068 {
1069 	guint32		    fhlen;
1070 	guint32		   *fhdata;
1071 	wmem_tree_key_t	    fhkey[3];
1072 	nfs_fhandle_data_t *new_nfs_fh;
1073 
1074 	fhlen = nfs_fh->len/4;
1075 	/* align the file handle data */
1076 	fhdata = (guint32 *)g_memdup2(nfs_fh->fh, fhlen*4);
1077 	fhkey[0].length = 1;
1078 	fhkey[0].key	= &fhlen;
1079 	fhkey[1].length = fhlen;
1080 	fhkey[1].key	= fhdata;
1081 	fhkey[2].length = 0;
1082 
1083 	new_nfs_fh = (nfs_fhandle_data_t *)wmem_tree_lookup32_array(nfs_file_handles, &fhkey[0]);
1084 	if (new_nfs_fh) {
1085 		g_free(fhdata);
1086 		return new_nfs_fh;
1087 	}
1088 
1089 	new_nfs_fh = wmem_new(wmem_file_scope(), nfs_fhandle_data_t);
1090 	new_nfs_fh->len = nfs_fh->len;
1091 	new_nfs_fh->fh = (const unsigned char *)wmem_memdup(wmem_file_scope(), nfs_fh->fh, nfs_fh->len);
1092 	fhlen = nfs_fh->len/4;
1093 	fhkey[0].length = 1;
1094 	fhkey[0].key	= &fhlen;
1095 	fhkey[1].length = fhlen;
1096 	fhkey[1].key	= fhdata;
1097 	fhkey[2].length = 0;
1098 	wmem_tree_insert32_array(nfs_file_handles, &fhkey[0], new_nfs_fh);
1099 
1100 	g_free(fhdata);
1101 	return new_nfs_fh;
1102 }
1103 
1104 
1105 static gint
nfs_name_snoop_matched_equal(gconstpointer k1,gconstpointer k2)1106 nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
1107 {
1108 	const nfs_name_snoop_key_t *key1 = (const nfs_name_snoop_key_t *)k1;
1109 	const nfs_name_snoop_key_t *key2 = (const nfs_name_snoop_key_t *)k2;
1110 
1111 	return (key1->key == key2->key)
1112 	     &&(key1->fh_length == key2->fh_length)
1113 	     &&(!memcmp(key1->fh, key2->fh, key1->fh_length));
1114 }
1115 
1116 
1117 static guint
nfs_name_snoop_matched_hash(gconstpointer k)1118 nfs_name_snoop_matched_hash(gconstpointer k)
1119 {
1120 	const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
1121 	int i;
1122 	guint hash;
1123 
1124 	hash = key->key;
1125 	for (i=0; i<key->fh_length; i++)
1126 		hash ^= key->fh[i];
1127 
1128 	return hash;
1129 }
1130 
1131 
1132 static gint
nfs_name_snoop_unmatched_equal(gconstpointer k1,gconstpointer k2)1133 nfs_name_snoop_unmatched_equal(gconstpointer k1, gconstpointer k2)
1134 {
1135 	guint32 key1 = GPOINTER_TO_UINT(k1);
1136 	guint32 key2 = GPOINTER_TO_UINT(k2);
1137 
1138 	return key1 == key2;
1139 }
1140 
1141 
1142 static guint
nfs_name_snoop_unmatched_hash(gconstpointer k)1143 nfs_name_snoop_unmatched_hash(gconstpointer k)
1144 {
1145 	guint32 key = GPOINTER_TO_UINT(k);
1146 
1147 	return key;
1148 }
1149 
1150 
1151 static void
nfs_name_snoop_value_destroy(gpointer value)1152 nfs_name_snoop_value_destroy(gpointer value)
1153 {
1154 	nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
1155 
1156 	g_free((gpointer)nns->name);
1157 	g_free((gpointer)nns->full_name);
1158 	wmem_free(NULL, nns->parent);
1159 	wmem_free(NULL, nns->fh);
1160 	g_free(nns);
1161 }
1162 
1163 
1164 static void
nfs_name_snoop_init(void)1165 nfs_name_snoop_init(void)
1166 {
1167 	nfs_name_snoop_unmatched =
1168 		g_hash_table_new_full(nfs_name_snoop_unmatched_hash,
1169 		nfs_name_snoop_unmatched_equal,
1170 		NULL, nfs_name_snoop_value_destroy);
1171 	nfs_name_snoop_matched =
1172 		g_hash_table_new_full(nfs_name_snoop_matched_hash,
1173 		nfs_name_snoop_matched_equal,
1174 		NULL, nfs_name_snoop_value_destroy);
1175 }
1176 
1177 static void
nfs_name_snoop_cleanup(void)1178 nfs_name_snoop_cleanup(void)
1179 {
1180 	g_hash_table_destroy(nfs_name_snoop_unmatched);
1181 	g_hash_table_destroy(nfs_name_snoop_matched);
1182 }
1183 
1184 
1185 void
nfs_name_snoop_add_name(int xid,tvbuff_t * tvb,int name_offset,int name_len,int parent_offset,int parent_len,const char * name)1186 nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset,
1187 			int parent_len, const char *name)
1188 {
1189 	nfs_name_snoop_t *nns;
1190 	const char	 *ptr;
1191 
1192 	if (name_len <= 0) {
1193 		/* Do we need some way to signal an error here? This could be
1194 		 * programmatic or just a corrupt packet, depending on the
1195 		 * caller... */
1196 		return;
1197 	}
1198 
1199 	/* filter out all '.' and '..' names */
1200 	if (!name) {
1201 		ptr = (const char *)tvb_get_ptr(tvb, name_offset, name_len);
1202 	} else {
1203 		ptr = name;
1204 	}
1205 	if (ptr[0] == '.') {
1206 		if (name_len <= 1 || ptr[1] == 0) {
1207 			return;
1208 		}
1209 		if (ptr[1] == '.') {
1210 			if (name_len <= 2 || ptr[2] == 0) {
1211 				return;
1212 			}
1213 		}
1214 	}
1215 
1216 	nns = g_new(nfs_name_snoop_t, 1);
1217 
1218 	nns->fh_length = 0;
1219 	nns->fh = NULL;
1220 
1221 	if (parent_len) {
1222 		nns->parent_len = parent_len;
1223 		nns->parent = (unsigned char *)tvb_memdup(NULL, tvb, parent_offset, parent_len);
1224 	} else {
1225 		nns->parent_len = 0;
1226 		nns->parent = NULL;
1227 	}
1228 
1229 	if (name) {
1230 		nns->name_len = (int)strlen(name);
1231 		nns->name = g_strdup(name);
1232 	} else {
1233 		nns->name_len = name_len;
1234 		nns->name = (char *)g_malloc(name_len+1);
1235 		memcpy(nns->name, ptr, name_len);
1236 	}
1237 	nns->name[nns->name_len] = 0;
1238 
1239 	nns->full_name_len = 0;
1240 	nns->full_name = NULL;
1241 	nns->fs_cycle = false;
1242 
1243 	/* any old entry will be deallocated and removed */
1244 	g_hash_table_insert(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid), nns);
1245 }
1246 
1247 
1248 static void
nfs_name_snoop_add_fh(int xid,tvbuff_t * tvb,int fh_offset,int fh_length)1249 nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
1250 {
1251 	unsigned char	     *fh;
1252 	nfs_name_snoop_t     *nns;
1253 	nfs_name_snoop_key_t *key;
1254 
1255 	/* find which request we correspond to */
1256 	nns = (nfs_name_snoop_t *)g_hash_table_lookup(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1257 	if (!nns) {
1258 		/* oops couldn't find matching request, bail out */
1259 		return;
1260 	}
1261 
1262 	/* if we have already seen this response earlier */
1263 	if (nns->fh) {
1264 		return;
1265 	}
1266 
1267 	/* oki, we have a new entry */
1268 	fh = (unsigned char *)tvb_memdup(NULL, tvb, fh_offset, fh_length);
1269 	nns->fh = fh;
1270 	nns->fh_length = fh_length;
1271 
1272 	key = wmem_new(wmem_file_scope(), nfs_name_snoop_key_t);
1273 	key->key = 0;
1274 	key->fh_length = nns->fh_length;
1275 	key->fh = nns->fh;
1276 
1277 	g_hash_table_steal(nfs_name_snoop_unmatched, GINT_TO_POINTER(xid));
1278 	g_hash_table_replace(nfs_name_snoop_matched, key, nns);
1279 }
1280 
1281 #define NFS_MAX_FS_DEPTH 100
1282 
1283 static void
nfs_full_name_snoop(packet_info * pinfo,nfs_name_snoop_t * nns,int * len,char ** name,char ** pos)1284 nfs_full_name_snoop(packet_info *pinfo, nfs_name_snoop_t *nns, int *len, char **name, char **pos)
1285 {
1286 	nfs_name_snoop_t     *parent_nns = NULL;
1287 	nfs_name_snoop_key_t  key;
1288 
1289 	/* check if the nns component ends with a '/' else we just allocate
1290 	   an extra byte to len to accommodate for it later */
1291 	if (nns->name[nns->name_len-1] != '/') {
1292 		(*len)++;
1293 	}
1294 
1295 	(*len) += nns->name_len;
1296 
1297 	if (nns->parent == NULL) {
1298 		*name = (char *)g_malloc((*len)+1);
1299 		*pos = *name;
1300 
1301 		*pos += g_snprintf(*pos, (*len)+1, "%s", nns->name);
1302 		DISSECTOR_ASSERT((*pos-*name) <= *len);
1303 		return;
1304 	}
1305 
1306 	key.key = 0;
1307 	key.fh_length = nns->parent_len;
1308 	key.fh = nns->parent;
1309 
1310 	parent_nns = (nfs_name_snoop_t *)g_hash_table_lookup(nfs_name_snoop_matched, &key);
1311 
1312 	if (parent_nns) {
1313 		unsigned fs_depth = p_get_proto_depth(pinfo, proto_nfs);
1314 		if (++fs_depth >= NFS_MAX_FS_DEPTH) {
1315 			nns->fs_cycle = true;
1316 			return;
1317 		}
1318 		p_set_proto_depth(pinfo, proto_nfs, fs_depth);
1319 
1320 		nfs_full_name_snoop(pinfo, parent_nns, len, name, pos);
1321 		if (*name) {
1322 			/* make sure components are '/' separated */
1323 			*pos += g_snprintf(*pos, (*len+1) - (gulong)(*pos-*name), "%s%s",
1324 					   ((*pos)[-1] != '/')?"/":"", nns->name);
1325 			DISSECTOR_ASSERT((*pos-*name) <= *len);
1326 		}
1327 		p_set_proto_depth(pinfo, proto_nfs, fs_depth - 1);
1328 		return;
1329 	}
1330 
1331 	return;
1332 }
1333 
1334 
1335 static void
nfs_name_snoop_fh(packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb,int fh_offset,int fh_length,gboolean hidden)1336 nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_offset,
1337 				  int fh_length, gboolean hidden)
1338 {
1339 	nfs_name_snoop_key_t  key;
1340 	nfs_name_snoop_t     *nns = NULL;
1341 
1342 	/* if this is a new packet, see if we can register the mapping */
1343 	if (!pinfo->fd->visited) {
1344 		key.key = 0;
1345 		key.fh_length = fh_length;
1346 		key.fh = (const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
1347 
1348 		nns = (nfs_name_snoop_t *)g_hash_table_lookup(nfs_name_snoop_matched, &key);
1349 		if (nns) {
1350 			guint32 fhlen;
1351 			guint32 *fhdata;
1352 			wmem_tree_key_t fhkey[3];
1353 
1354 			fhlen = nns->fh_length;
1355 			/* align it */
1356 			fhdata = (guint32 *)g_memdup2(nns->fh, fhlen);
1357 			fhkey[0].length = 1;
1358 			fhkey[0].key	= &fhlen;
1359 			fhkey[1].length = fhlen/4;
1360 			fhkey[1].key	= fhdata;
1361 			fhkey[2].length = 0;
1362 			wmem_tree_insert32_array(nfs_name_snoop_known, &fhkey[0], nns);
1363 			g_free(fhdata);
1364 
1365 			if (nfs_file_name_full_snooping) {
1366 				char *name = NULL, *pos = NULL;
1367 				int len = 0;
1368 
1369 				nfs_full_name_snoop(pinfo, nns, &len, &name, &pos);
1370 				if (name) {
1371 					nns->full_name = name;
1372 					nns->full_name_len = len;
1373 				}
1374 			}
1375 		}
1376 	}
1377 
1378 	/* see if we know this mapping */
1379 	if (!nns) {
1380 		guint32 fhlen;
1381 		guint32 *fhdata;
1382 		wmem_tree_key_t fhkey[3];
1383 
1384 		fhlen = fh_length;
1385 		/* align it */
1386 		fhdata = (guint32 *)tvb_memdup(wmem_packet_scope(), tvb, fh_offset, fh_length);
1387 		fhkey[0].length = 1;
1388 		fhkey[0].key	= &fhlen;
1389 		fhkey[1].length = fhlen/4;
1390 		fhkey[1].key	= fhdata;
1391 		fhkey[2].length = 0;
1392 
1393 		nns = (nfs_name_snoop_t *)wmem_tree_lookup32_array(nfs_name_snoop_known, &fhkey[0]);
1394 	}
1395 
1396 	/* if we know the mapping, print the filename */
1397 	if (nns) {
1398 		proto_item *fh_item = NULL;
1399 
1400 		if (hidden) {
1401 			fh_item = proto_tree_add_string(tree, hf_nfs_name, NULL,
1402 				0, 0, nns->name);
1403 			proto_item_set_hidden(fh_item);
1404 		} else {
1405 			fh_item = proto_tree_add_string(tree, hf_nfs_name, tvb,
1406 				fh_offset, 0, nns->name);
1407 		}
1408 		proto_item_set_generated(fh_item);
1409 
1410 		if (nns->full_name) {
1411 			if (hidden) {
1412 				fh_item = proto_tree_add_string(tree, hf_nfs_full_name, NULL,
1413 					0, 0, nns->full_name);
1414 				proto_item_set_hidden(fh_item);
1415 			} else {
1416 				fh_item = proto_tree_add_string_format_value(tree, hf_nfs_full_name, tvb,
1417 					fh_offset, 0, nns->full_name, "%s", nns->full_name);
1418 			}
1419 			proto_item_set_generated(fh_item);
1420 		}
1421 
1422 		if (nns->fs_cycle) {
1423 			proto_tree_add_expert(tree, pinfo, &ei_nfs_file_system_cycle, tvb, 0, 0);
1424 		}
1425 	}
1426 }
1427 
1428 
1429 /* file handle dissection */
1430 
1431 static const true_false_string tfs_endianness = { "Little Endian", "Big Endian" };
1432 
1433 static void
nfs_fmt_fsid(gchar * result,guint32 revision)1434 nfs_fmt_fsid( gchar *result, guint32 revision )
1435 {
1436 	guint32 fsid_major;
1437 	guint32 fsid_minor;
1438 
1439 	fsid_major = ( revision>>18 ) &  0x3fff; /* 14 bits */
1440 	fsid_minor = ( revision     ) & 0x3ffff; /* 18 bits */
1441 
1442    g_snprintf( result, ITEM_LABEL_LENGTH, "%d,%d", fsid_major, fsid_minor);
1443 }
1444 
1445 /* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45), OpenSolaris (build 101a) */
1446 static int
dissect_fhandle_data_SVR4(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1447 dissect_fhandle_data_SVR4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1448 {
1449 	guint encoding = ENC_BIG_ENDIAN;	/* We support little endian and big endian. Default is big endian*/
1450 	gboolean have_flag = FALSE;	/* The flag field at the end is optional. Assume no flag is there */
1451 	gboolean found = FALSE;		/* Did we really detect the file handle format? */
1452 	guint32	 nof = 0;
1453 	guint32	 len1;
1454 	guint32	 len2;
1455 	guint32	 fhlen;		/* File handle length. */
1456 
1457 	static int * const fsid_fields[] = {
1458 		&hf_nfs_fh_fsid_major32,
1459 		&hf_nfs_fh_fsid_minor32,
1460 		NULL
1461 	};
1462 
1463 	/* Somehow this is no calling argument, so we have to re-calculate it. */
1464 	fhlen = tvb_reported_length(tvb);
1465 
1466 	/* Check for little endianness. */
1467 	len1 = tvb_get_letohs(tvb, 8);
1468 	if (tvb_bytes_exist(tvb, 10+len1, 2)) {
1469 		len2 = tvb_get_letohs(tvb, 10+len1);
1470 
1471 		if (12+len1+len2 == fhlen) {
1472 			encoding = ENC_LITTLE_ENDIAN;
1473 			have_flag = FALSE;
1474 			found = TRUE;
1475 		}
1476 		if (16+len1+len2 == fhlen) {
1477 			encoding = ENC_LITTLE_ENDIAN;
1478 			have_flag = TRUE;
1479 			found = TRUE;
1480 		}
1481 	}
1482 
1483 	if (!found) {
1484 		/* Check for big endianness. */
1485 		len1 = tvb_get_ntohs(tvb, 8);
1486 		if (tvb_bytes_exist(tvb, 10+len1, 2)) {
1487 			len2 = tvb_get_ntohs(tvb, 10+len1);
1488 
1489 			if (12+len1+len2 == fhlen) {
1490 				have_flag = FALSE;
1491 			}
1492 			if (16+len1+len2 == fhlen) {
1493 				have_flag = TRUE;
1494 			}
1495 		}
1496 	}
1497 
1498 	proto_tree_add_boolean(tree, hf_nfs_fh_endianness, tvb,	0, fhlen, (encoding == ENC_LITTLE_ENDIAN));
1499 
1500 	/* We are fairly sure, that when found == FALSE, the following code will
1501 	throw an exception. */
1502 
1503 	/* file system id */
1504 	proto_tree_add_bitmask(tree, tvb, nof, hf_nfs_fh_fsid,
1505 					ett_nfs_fh_fsid, fsid_fields, encoding);
1506 	nof += 4;
1507 
1508 	/* file system type */
1509 	proto_tree_add_item(tree, hf_nfs_fh_fstype, tvb, nof, 4, encoding);
1510 	nof += 4;
1511 
1512 	/* file number */
1513 	{
1514 		guint32 fn_O;
1515 		guint32 fn_len_O;
1516 		guint32 fn_len_L;
1517 		guint32 fn_len;
1518 		guint32 fn_data_O;
1519 		guint32 fn_data_inode_O;
1520 		guint32 fn_data_inode_L;
1521 		guint32 inode;
1522 		guint32 fn_data_gen_O;
1523 		guint32 fn_data_gen_L;
1524 		guint32 gen;
1525 		guint32 fn_L;
1526 
1527 		fn_O = nof;
1528 		fn_len_O = fn_O;
1529 		fn_len_L = 2;
1530 		fn_len = tvb_get_guint16(tvb, fn_len_O, encoding);
1531 		fn_data_O = fn_O + fn_len_L;
1532 		fn_data_inode_O = fn_data_O + 2;
1533 		fn_data_inode_L = 4;
1534 		inode = tvb_get_guint32(tvb, fn_data_inode_O, encoding);
1535 		fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
1536 		fn_data_gen_L = 4;
1537 		gen = tvb_get_guint32(tvb, fn_data_gen_O, encoding);
1538 		fn_L = fn_len_L + fn_len;
1539 		if (tree) {
1540 			proto_item *fn_item = NULL;
1541 			proto_tree *fn_tree = NULL;
1542 
1543 			fn_item = proto_tree_add_uint(tree, hf_nfs_fh_fn, tvb,
1544 						      fn_O, fn_L, inode);
1545 			fn_tree = proto_item_add_subtree(fn_item,
1546 							 ett_nfs_fh_fn);
1547 			proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_len,
1548 					    tvb, fn_len_O, fn_len_L, fn_len);
1549 			proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_inode,
1550 					    tvb, fn_data_inode_O, fn_data_inode_L, inode);
1551 			proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_generation,
1552 					    tvb, fn_data_gen_O, fn_data_gen_L, gen);
1553 		}
1554 		nof = fn_O + fn_len_L + fn_len;
1555 	}
1556 
1557 	/* exported file number */
1558 	{
1559 		guint32 xfn_O;
1560 		guint32 xfn_len_O;
1561 		guint32 xfn_len_L;
1562 		guint32 xfn_len;
1563 		guint32 xfn_data_O;
1564 		guint32 xfn_data_inode_O;
1565 		guint32 xfn_data_inode_L;
1566 		guint32 xinode;
1567 		guint32 xfn_data_gen_O;
1568 		guint32 xfn_data_gen_L;
1569 		guint32 xgen;
1570 		guint32 xfn_L;
1571 
1572 		xfn_O = nof;
1573 		xfn_len_O = xfn_O;
1574 		xfn_len_L = 2;
1575 		xfn_len = tvb_get_guint16(tvb, xfn_len_O, encoding);
1576 		xfn_data_O = xfn_O + xfn_len_L;
1577 		xfn_data_inode_O = xfn_data_O + 2;
1578 		xfn_data_inode_L = 4;
1579 		xinode = tvb_get_guint32(tvb, xfn_data_inode_O, encoding);
1580 		xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
1581 		xfn_data_gen_L = 4;
1582 		xgen = tvb_get_guint32(tvb, xfn_data_gen_O, encoding);
1583 		xfn_L = xfn_len_L + xfn_len;
1584 
1585 		if (tree) {
1586 			proto_item *xfn_item = NULL;
1587 			proto_tree *xfn_tree = NULL;
1588 
1589 			xfn_item = proto_tree_add_uint(tree, hf_nfs_fh_xfn, tvb,
1590 						       xfn_O, xfn_L, xinode);
1591 			xfn_tree = proto_item_add_subtree(xfn_item,
1592 							  ett_nfs_fh_xfn);
1593 			proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_len,
1594 					    tvb, xfn_len_O, xfn_len_L, xfn_len);
1595 			proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_inode,
1596 					    tvb, xfn_data_inode_O, xfn_data_inode_L, xinode);
1597 			proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_generation,
1598 					    tvb, xfn_data_gen_O, xfn_data_gen_L, xgen);
1599 		}
1600 		nof = xfn_O + xfn_len_L + xfn_len;
1601 	}
1602 
1603 	/* flag */
1604 	if (have_flag)
1605 		proto_tree_add_item(tree, hf_nfs_fh_flag, tvb, nof, 4, encoding);
1606 
1607 	return tvb_captured_length(tvb);
1608 }
1609 
1610 
1611 /* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
1612 
1613 static int
dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1614 dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1615 {
1616 	if (tree) {
1617 		int	offset = 0;
1618 		guint32 temp;
1619 		guint32 fsid_major;
1620 		guint32 fsid_minor;
1621 		guint32 xfsid_major;
1622 		guint32 xfsid_minor;
1623 
1624 		temp	    = tvb_get_letohs (tvb, offset+12);
1625 		fsid_major  = (temp >> 8) & 0xff;
1626 		fsid_minor  = (temp     ) & 0xff;
1627 		temp	    = tvb_get_letohs(tvb, offset+16);
1628 		xfsid_major = (temp >> 8) & 0xff;
1629 		xfsid_minor = (temp     ) & 0xff;
1630 
1631 		proto_tree_add_item(tree, hf_nfs_fh_dentry, tvb, offset+0, 4, ENC_LITTLE_ENDIAN);
1632 		proto_tree_add_item(tree, hf_nfs_fh_fn_inode, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1633 		proto_tree_add_item(tree, hf_nfs_fh_dirinode, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1634 
1635 		/* file system id (device) */
1636 		{
1637 			proto_tree *fsid_tree;
1638 
1639 			fsid_tree = proto_tree_add_subtree_format(tree, tvb,
1640 							offset+12, 4, ett_nfs_fh_fsid, NULL,
1641 							"file system ID: %d,%d",
1642 							fsid_major, fsid_minor);
1643 			proto_tree_add_item(fsid_tree, hf_nfs_fh_fsid_major16_mask, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
1644 			proto_tree_add_item(fsid_tree, hf_nfs_fh_fsid_minor16_mask, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
1645 		}
1646 
1647 		/* exported file system id (device) */
1648 		{
1649 			proto_tree *xfsid_tree;
1650 
1651 			xfsid_tree = proto_tree_add_subtree_format(tree, tvb,
1652 							 offset+16, 4, ett_nfs_fh_xfsid, NULL,
1653 							 "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
1654 			proto_tree_add_item(xfsid_tree, hf_nfs_fh_xfsid_major, tvb, offset+16, 2, ENC_LITTLE_ENDIAN);
1655 			proto_tree_add_item(xfsid_tree, hf_nfs_fh_xfsid_minor, tvb, offset+16, 2, ENC_LITTLE_ENDIAN);
1656 		}
1657 
1658 		proto_tree_add_item(tree, hf_nfs_fh_xfn_inode, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
1659 		proto_tree_add_item(tree, hf_nfs_fh_fn_generation, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
1660 	}
1661 	return tvb_captured_length(tvb);
1662 }
1663 
1664 
1665 /* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
1666 
1667 static int
dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1668 dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1669 {
1670 	int offset = 0;
1671 
1672 	/* pseudo inode */
1673 	proto_tree_add_item(tree, hf_nfs_fh_pinode, tvb, offset+0, 4, ENC_LITTLE_ENDIAN);
1674 
1675 	/* hash path */
1676 	{
1677 		guint32 hashlen;
1678 
1679 		hashlen  = tvb_get_guint8(tvb, offset+4);
1680 		if (tree) {
1681 			proto_tree *hash_tree;
1682 
1683 			hash_tree = proto_tree_add_subtree_format(tree, tvb, offset+4, hashlen + 1, ett_nfs_fh_hp, NULL,
1684 									"hash path: %s", tvb_bytes_to_str(wmem_packet_scope(), tvb, offset+5, hashlen));
1685 			proto_tree_add_uint(hash_tree,
1686 					    hf_nfs_fh_hp_len, tvb, offset+4, 1,
1687 					    hashlen);
1688 			proto_tree_add_item(hash_tree, hf_nfs_fh_hp_key, tvb, offset+5, hashlen, ENC_NA);
1689 		}
1690 	}
1691 	return tvb_captured_length(tvb);
1692 }
1693 
1694 
1695 static int
dissect_fhandle_data_NETAPP(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1696 dissect_fhandle_data_NETAPP(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1697 {
1698 	int offset = 0;
1699 	static int * const flags[] = {
1700 		&hf_nfs_fh_file_flag_mntpoint,
1701 		&hf_nfs_fh_file_flag_snapdir,
1702 		&hf_nfs_fh_file_flag_snapdir_ent,
1703 		&hf_nfs_fh_file_flag_empty,
1704 		&hf_nfs_fh_file_flag_vbn_access,
1705 		&hf_nfs_fh_file_flag_multivolume,
1706 		&hf_nfs_fh_file_flag_metadata,
1707 		NULL
1708 	};
1709 
1710 	if (tree) {
1711 		guint32 mount	       = tvb_get_letohl(tvb, offset +  0);
1712 
1713 		guint32 inum	       = tvb_get_ntohl( tvb, offset + 12);
1714 		guint32 nfsexport      = tvb_get_letohl(tvb, offset + 24);
1715 		guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
1716 
1717 		proto_tree *subtree = NULL;
1718 
1719 		subtree = proto_tree_add_subtree_format(tree, tvb, offset + 0, 8,
1720 					   ett_nfs_fh_mount, NULL, "mount (inode %u)", mount);
1721 		proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
1722 					   tvb, offset + 0, 4, mount);
1723 		proto_tree_add_item(subtree, hf_nfs_fh_mount_generation, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
1724 		subtree = proto_tree_add_subtree_format(tree, tvb, offset + 8, 16,
1725 					   ett_nfs_fh_file, NULL, "file (inode %u)", inum);
1726 
1727 		proto_tree_add_bitmask_with_flags(subtree, tvb, offset + 8, hf_nfs_fh_flags, ett_nfs4_fh_file_flags, flags, ENC_LITTLE_ENDIAN, BMT_NO_FALSE);
1728 
1729 		proto_tree_add_item(subtree, hf_nfs_fh_snapid, tvb, offset + 10, 1, ENC_NA);
1730 		proto_tree_add_item(subtree, hf_nfs_fh_unused, tvb, offset + 11, 1, ENC_NA);
1731 		proto_tree_add_item(subtree, hf_nfs_fh_fileid, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
1732 		proto_tree_add_item(subtree, hf_nfs_fh_generation, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN);
1733 		proto_tree_add_item(subtree, hf_nfs_fh_fsid, tvb, offset + 20, 4, ENC_LITTLE_ENDIAN);
1734 		subtree = proto_tree_add_subtree_format(tree, tvb, offset + 24, 8,
1735 					   ett_nfs_fh_export, NULL, "export (inode %u)", nfsexport);
1736 		proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
1737 					   tvb, offset + 24, 4, nfsexport);
1738 		proto_tree_add_uint(subtree,
1739 					   hf_nfs_fh_export_generation,
1740 					   tvb, offset + 28, 3,
1741 					   export_snapgen & 0xffffff);
1742 		proto_tree_add_uint(subtree, hf_nfs_fh_export_snapid,
1743 					   tvb, offset + 31, 1,
1744 					   export_snapgen >> 24);
1745 	}
1746 	return tvb_captured_length(tvb);
1747 }
1748 
1749 static const value_string handle_type_strings[] = {
1750 	{ 0, "NORMAL" },
1751 	{ 1, "UNEXP" },
1752 	{ 2, "VOLDIR" },
1753 	{ 3, "ROOT" },
1754 	{ 4, "ABSENT" },
1755 	{ 0, NULL }
1756 };
1757 
1758 static int
dissect_fhandle_data_NETAPP_V4(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1759 dissect_fhandle_data_NETAPP_V4(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1760 {
1761 	static int * const flags[] = {
1762 		&hf_nfs_fh_file_flag_mntpoint,
1763 		&hf_nfs_fh_file_flag_snapdir,
1764 		&hf_nfs_fh_file_flag_snapdir_ent,
1765 		&hf_nfs_fh_file_flag_empty,
1766 		&hf_nfs_fh_file_flag_vbn_access,
1767 		&hf_nfs_fh_file_flag_multivolume,
1768 		&hf_nfs_fh_file_flag_metadata,
1769 		&hf_nfs_fh_file_flag_orphan,
1770 		&hf_nfs_fh_file_flag_foster,
1771 		&hf_nfs_fh_file_flag_named_attr,
1772 		&hf_nfs_fh_file_flag_exp_snapdir,
1773 		&hf_nfs_fh_file_flag_vfiler,
1774 		&hf_nfs_fh_file_flag_aggr,
1775 		&hf_nfs_fh_file_flag_striped,
1776 		&hf_nfs_fh_file_flag_private,
1777 		&hf_nfs_fh_file_flag_next_gen,
1778 		NULL
1779 	};
1780 
1781 	if (tree == NULL)
1782 		return tvb_captured_length(tvb);
1783 
1784 	{
1785 		int	    offset = 0;
1786 		proto_tree *subtree;
1787 		guint32	    fileid;
1788 		guint32	    handle_type;
1789 		guint32	    inum;
1790 		guint encoding;
1791 
1792 		handle_type = tvb_get_ntohl(tvb, offset + 24);
1793 		inum	    = tvb_get_ntohl(tvb, offset + 12);
1794 
1795 		if ( handle_type != 0 && handle_type <= 255) {
1796 			encoding = ENC_BIG_ENDIAN;
1797 		} else {
1798 			encoding = ENC_LITTLE_ENDIAN;
1799 		}
1800         fileid = tvb_get_guint32(tvb, offset, encoding);
1801 		subtree = proto_tree_add_subtree_format(tree, tvb, offset + 0, 8, ett_nfs4_fh_export, NULL, "export (inode %u)", fileid);
1802 
1803 		proto_tree_add_item(subtree, hf_nfs_fh_export_fileid, tvb, offset + 0, 4, encoding);
1804 		proto_tree_add_item(subtree, hf_nfs_fh_export_generation, tvb, offset + 4, 4, encoding);
1805 		subtree = proto_tree_add_subtree_format(tree, tvb, offset + 8, 16, ett_nfs4_fh_file, NULL, "file (inode %u)", inum);
1806 
1807 		proto_tree_add_bitmask_with_flags(subtree, tvb, offset + 8, hf_nfs_fh_flags, ett_nfs4_fh_file_flags, flags, encoding, BMT_NO_FALSE);
1808 
1809 		proto_tree_add_item(subtree, hf_nfs_fh_snapid, tvb, offset + 10, 1, ENC_NA);
1810 		proto_tree_add_item(subtree, hf_nfs_fh_unused, tvb, offset + 11, 1, ENC_NA);
1811 		proto_tree_add_item(subtree, hf_nfs_fh_fileid, tvb, offset + 12, 4, encoding);
1812 		proto_tree_add_item(subtree, hf_nfs_fh_generation, tvb, offset + 16, 4, encoding);
1813 		proto_tree_add_item(subtree, hf_nfs_fh_fsid, tvb, offset + 20, 4, encoding);
1814 		proto_tree_add_item(tree, hf_nfs_fh_handle_type, tvb, offset+24, 4, encoding);
1815 	}
1816 	return tvb_captured_length(tvb);
1817 }
1818 
1819 #define NETAPP_GX_FH3_LENGTH		44
1820 #define NFS3GX_FH_TREE_MASK		0x80
1821 #define NFS3GX_FH_JUN_MASK		0x40
1822 #define NFS3GX_FH_VER_MASK		0x3F
1823 #define SPINNP_FH_FLAG_RESV1            0x80
1824 #define SPINNP_FH_FLAG_RESV2            0x40
1825 #define SPINNP_FH_FLAG_ONTAP_MASK	0x20
1826 #define SPINNP_FH_FLAG_STRIPED_MASK	0x10
1827 #define SPINNP_FH_FLAG_EMPTY_MASK	0x08
1828 #define SPINNP_FH_FLAG_SNAPDIR_ENT_MASK 0x04
1829 #define SPINNP_FH_FLAG_SNAPDIR_MASK	0x02
1830 #define SPINNP_FH_FLAG_STREAMDIR_MASK	0x01
1831 
1832 static int
dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1833 dissect_fhandle_data_NETAPP_GX_v3(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1834 {
1835 	if (tree) {
1836 		proto_tree *field_tree;
1837 		guint8      flags;
1838 		guint32     offset = 0;
1839 		static int * const fh_flags[] = {
1840 			&hf_nfs3_gxfh_sfhflags_resv1,
1841 			&hf_nfs3_gxfh_sfhflags_resv2,
1842 			&hf_nfs3_gxfh_sfhflags_ontapGX,
1843 			&hf_nfs3_gxfh_sfhflags_striped,
1844 			&hf_nfs3_gxfh_sfhflags_empty,
1845 			&hf_nfs3_gxfh_sfhflags_snapdirent,
1846 			&hf_nfs3_gxfh_sfhflags_snapdir,
1847 			&hf_nfs3_gxfh_sfhflags_streamdir,
1848 			NULL
1849 		};
1850 
1851 		static int * const fh_flags_ontap[] = {
1852 			&hf_nfs3_gxfh_sfhflags_resv1,
1853 			&hf_nfs3_gxfh_sfhflags_resv2,
1854 			&hf_nfs3_gxfh_sfhflags_ontap7G,
1855 			&hf_nfs3_gxfh_sfhflags_striped,
1856 			&hf_nfs3_gxfh_sfhflags_empty,
1857 			&hf_nfs3_gxfh_sfhflags_snapdirent,
1858 			&hf_nfs3_gxfh_sfhflags_snapdir,
1859 			&hf_nfs3_gxfh_sfhflags_streamdir,
1860 			NULL
1861 		};
1862 
1863 		static int * const utility_flags[] = {
1864 			&hf_nfs3_gxfh_utlfield_tree,
1865 			&hf_nfs3_gxfh_utlfield_jun,
1866 			&hf_nfs3_gxfh_utlfield_ver,
1867 			NULL
1868 		};
1869 
1870 		/* = utility = */
1871 		proto_tree_add_bitmask(tree, tvb, offset, hf_nfs3_gxfh_utlfield, ett_nfs3_gxfh_utlfield, utility_flags, ENC_NA);
1872 
1873 		/* = volume count== */
1874 		proto_tree_add_item(tree, hf_nfs3_gxfh_volcnt, tvb, offset+1, 1, ENC_NA);
1875 		/* = epoch = */
1876 		proto_tree_add_item(tree, hf_nfs3_gxfh_epoch, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1877 		/* = spin file handle = */
1878 		flags        = tvb_get_guint8(tvb, offset+11);
1879 
1880 		field_tree = proto_tree_add_subtree(tree, tvb, offset+4, 16,
1881 					 ett_nfs3_gxfh_sfhfield, NULL, "  spin file handle");
1882 
1883 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_ldsid, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1884 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_cid, tvb, offset+8, 2, ENC_BIG_ENDIAN);
1885 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_resv, tvb, offset+10, 1, ENC_BIG_ENDIAN);
1886 
1887 		if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
1888 			proto_tree_add_bitmask(field_tree, tvb, offset+11, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags_ontap, ENC_NA);
1889 		}
1890 		else {
1891 			proto_tree_add_bitmask(field_tree, tvb, offset+11, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags, ENC_NA);
1892 		}
1893 
1894 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfid, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1895 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfuid, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1896 
1897 		/* = spin file handle (mount point) = */
1898 		flags        = tvb_get_guint8(tvb, offset+27);
1899 
1900 		field_tree = proto_tree_add_subtree(tree, tvb, offset+20, 16,
1901 					 ett_nfs3_gxfh_sfhfield, NULL, "  spin (mount point) file handle");
1902 
1903 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_ldsid, tvb, offset+20, 4, ENC_BIG_ENDIAN);
1904 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_cid, tvb, offset+24, 2, ENC_BIG_ENDIAN);
1905 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_resv, tvb, offset+26, 1, ENC_BIG_ENDIAN);
1906 
1907 		if (flags & SPINNP_FH_FLAG_ONTAP_MASK) {
1908 			proto_tree_add_bitmask(field_tree, tvb, offset+27, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags_ontap, ENC_NA);
1909 		}
1910 		else {
1911 			proto_tree_add_bitmask(field_tree, tvb, offset+27, hf_nfs3_gxfh_sfhflags, ett_nfs3_gxfh_sfhflags, fh_flags, ENC_NA);
1912 		}
1913 
1914 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfid, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
1915 		proto_tree_add_item(field_tree, hf_nfs3_gxfh_spinfuid, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
1916 		/* = export point id  = */
1917 		proto_tree_add_item(tree, hf_nfs3_gxfh_exportptid, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
1918 		/* = export point unique id  = */
1919 		proto_tree_add_item(tree, hf_nfs3_gxfh_exportptuid, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
1920 
1921 	}  /* end of (tree) */
1922 	return tvb_captured_length(tvb);
1923 }
1924 
1925 /* Checked with SuSE 7.1 (kernel 2.4.0 knfsd) */
1926 /* read linux-2.4.5/include/linux/nfsd/nfsfh.h for more details */
1927 
1928 #define AUTH_TYPE_NONE 0
1929 static const value_string auth_type_names[] = {
1930 	{	AUTH_TYPE_NONE,				"no authentication"		},
1931 	{	0,	NULL}
1932 };
1933 
1934 #define FSID_TYPE_MAJOR_MINOR_INODE 0
1935 static const value_string fsid_type_names[] = {
1936 	{	FSID_TYPE_MAJOR_MINOR_INODE,		"major/minor/inode"		},
1937 	{	0,	NULL}
1938 };
1939 
1940 #define FILEID_TYPE_ROOT			0
1941 #define FILEID_TYPE_INODE_GENERATION		1
1942 #define FILEID_TYPE_INODE_GENERATION_PARENT	2
1943 static const value_string fileid_type_names[] = {
1944 	{	FILEID_TYPE_ROOT,			"root"				},
1945 	{	FILEID_TYPE_INODE_GENERATION,		"inode/generation"		},
1946 	{	FILEID_TYPE_INODE_GENERATION_PARENT,	"inode/generation/parent"	},
1947 	{	0,	NULL}
1948 };
1949 
1950 static int
dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1951 dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
1952 {
1953 	int    offset = 0;
1954 	guint32 version;
1955 	guint8 auth_type = 0;
1956 	guint8 fsid_type;
1957 	guint8 fileid_type;
1958 	proto_tree *fileid_tree;
1959 	proto_item *fileid_item;
1960 
1961 	proto_tree_add_item_ret_uint(tree, hf_nfs_fh_version, tvb, offset+0, 1, ENC_NA, &version);
1962 
1963 	switch (version) {
1964 		case 1:
1965 			auth_type   = tvb_get_guint8(tvb, offset + 1);
1966 			fsid_type   = tvb_get_guint8(tvb, offset + 2);
1967 			fileid_type = tvb_get_guint8(tvb, offset + 3);
1968 			if (tree) {
1969 				proto_tree *encoding_tree = proto_tree_add_subtree_format(tree, tvb,
1970 					offset + 1, 3,
1971 					ett_nfs_fh_encoding, NULL, "encoding: %u %u %u",
1972 					auth_type, fsid_type, fileid_type);
1973 
1974 				proto_tree_add_uint(encoding_tree, hf_nfs_fh_auth_type,
1975 							tvb, offset+1, 1, auth_type);
1976 				proto_tree_add_uint(encoding_tree, hf_nfs_fh_fsid_type,
1977 							tvb, offset+2, 1, fsid_type);
1978 				proto_tree_add_uint(encoding_tree, hf_nfs_fh_fileid_type,
1979 							tvb, offset+3, 1, fileid_type);
1980 			}
1981 			offset += 4;
1982 			break;
1983 		default: {
1984 			/* unknown version */
1985 			return 1;
1986 		}
1987 	}
1988 
1989 	if (auth_type != 0)
1990 	{
1991 		/* unknown authentication type */
1992 		return 2;
1993 	}
1994 
1995 	if (fsid_type != 0)
1996 	{
1997 		/* unknown authentication type */
1998 		return 3;
1999 	}
2000 
2001 	{
2002 	guint16 fsid_major;
2003 	guint16 fsid_minor;
2004 	guint32 fsid_inode;
2005 
2006 	fsid_major = tvb_get_ntohs(tvb, offset + 0);
2007 	fsid_minor = tvb_get_ntohs(tvb, offset + 2);
2008 	fsid_inode = tvb_get_letohl(tvb, offset + 4);
2009 	if (tree) {
2010 		proto_tree *fsid_tree = proto_tree_add_subtree_format(tree, tvb,
2011 			offset+0, 8, ett_nfs_fh_fsid, NULL,
2012 			"file system ID: %u,%u (inode %u)",
2013 			fsid_major, fsid_minor, fsid_inode);
2014 
2015 		proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major16,
2016 					tvb, offset+0, 2, fsid_major);
2017 		proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor16,
2018 					tvb, offset+2, 2, fsid_minor);
2019 		proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
2020 					tvb, offset+4, 4, fsid_inode);
2021 	}
2022 
2023 	offset += 8;
2024 	}
2025 
2026 	fileid_tree = proto_tree_add_subtree_format(tree, tvb,
2027 					offset, 0, ett_nfs_fh_fn, &fileid_item, "file ID");
2028 
2029 	switch (fileid_type) {
2030 		case 0: {
2031 			proto_item_append_text(fileid_item, ": root inode");
2032 		} break;
2033 		case 1: {
2034 			guint32 inode;
2035 			guint32 generation;
2036 
2037 			inode = tvb_get_letohl(tvb, offset + 0);
2038 			generation = tvb_get_letohl(tvb, offset + 4);
2039 
2040 			if (tree) {
2041 				proto_item_append_text(fileid_item, ": %u (%u)", inode, generation);
2042 				proto_item_set_len(fileid_item, 8);
2043 
2044 				proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
2045 						tvb, offset+0, 4, inode);
2046 				proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
2047 						tvb, offset+4, 4, generation);
2048 			}
2049 
2050 			/*offset += 8;*/
2051 		} break;
2052 		case 2: {
2053 			guint32 inode;
2054 			guint32 generation;
2055 
2056 			inode = tvb_get_letohl(tvb, offset + 0);
2057 			generation = tvb_get_letohl(tvb, offset + 4);
2058 
2059 			if (tree) {
2060 				proto_item_append_text(fileid_item, ": %u (%u)", inode, generation);
2061 				proto_item_set_len(fileid_item, 12);
2062 
2063 				proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
2064 						tvb, offset+0, 4, inode);
2065 				proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
2066 						tvb, offset+4, 4, generation);
2067 				proto_tree_add_item(fileid_tree, hf_nfs_fh_dirinode,
2068 						tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
2069 			}
2070 
2071 			/*offset += 12;*/
2072 		} break;
2073 		default: {
2074 			proto_item_append_text(fileid_item, ": unknown");
2075 			/* unknown fileid type */
2076 			return offset;
2077 		}
2078 	}
2079 	return tvb_captured_length(tvb);
2080 }
2081 
2082 
2083 /*
2084  * Dissect GlusterFS/NFS NFSv3 File Handle - glusterfs-3.3+
2085  * The filehandle is always 32 bytes and first 4 bytes of ident ":OGL"
2086  */
2087 static int
dissect_fhandle_data_GLUSTER(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2088 dissect_fhandle_data_GLUSTER(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2089 {
2090 	guint16 offset=0;
2091 	guint16	fhlen;
2092 	char *ident;
2093 
2094 	if (!tree)
2095 		return tvb_captured_length(tvb);
2096 
2097 	fhlen = tvb_reported_length(tvb);
2098 	if (fhlen != 36)
2099 		return tvb_captured_length(tvb);
2100 
2101 	ident = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 4, ENC_ASCII);
2102 	if (strncmp(":OGL", ident, 4))
2103 		return 4;
2104 	offset += 4;
2105 
2106 	proto_tree_add_item(tree, hf_nfs_fh_exportid, tvb, offset, 16, ENC_NA);
2107 	offset += 16;
2108 	proto_tree_add_item(tree, hf_nfs_fh_gfid, tvb, offset, 16, ENC_NA);
2109 	offset += 16;
2110 	return offset;
2111 }
2112 
2113 /*
2114  * Dissect dCache NFS File Handle - dcache > 2.6
2115  */
2116 
2117 #define DCACHE_MAGIC_MASK   0x00FFFFFF
2118 #define DCACHE_VERSION_MASK 0xFF000000
2119 #define DCACHE_MAGIC        0xCAFFEE
2120 
2121 static const value_string dcache_handle_types[] = {
2122 	{ 0, "INODE" },
2123 	{ 1, "TAG" },
2124 	{ 2, "TAGS" },
2125 	{ 3, "ID" },
2126 	{ 4, "PATHOF" },
2127 	{ 5, "PARENT" },
2128 	{ 6, "NAMEOF" },
2129 	{ 7, "PGET" },
2130 	{ 8, "PSET" },
2131 	{ 9, "CONST" },
2132 	{ 0, NULL }
2133 };
2134 
2135 static int
dissect_fhandle_data_DCACHE(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2136 dissect_fhandle_data_DCACHE(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2137 {
2138 	int offset = 0;
2139 	guint32 version;
2140 	guint32 magic;
2141 	guint8 obj_len;
2142 
2143 	if (!tree)
2144 		return tvb_captured_length(tvb);
2145 
2146 	version = (tvb_get_ntohl(tvb, offset) & DCACHE_VERSION_MASK) >> 24;
2147 	magic   = (tvb_get_ntohl(tvb, offset) & DCACHE_MAGIC_MASK);
2148 
2149 	if ((version != 1) || (magic != DCACHE_MAGIC)) {
2150 		/* unknown file handle */
2151 		return 0;
2152 	}
2153 
2154 	proto_tree_add_item(tree, hf_nfs_fh_version, tvb, offset, 1, ENC_BIG_ENDIAN);
2155 	proto_tree_add_item(tree, hf_nfs_fh_generation, tvb, offset+4, 4, ENC_BIG_ENDIAN);
2156 	proto_tree_add_item(tree, hf_nfs_fh_dc_exportid, tvb, offset+8, 4, ENC_BIG_ENDIAN);
2157 	proto_tree_add_item(tree, hf_nfs_fh_dc_handle_type, tvb, offset+15, 1, ENC_BIG_ENDIAN);
2158 	obj_len = tvb_get_guint8(tvb, offset + 16);
2159 	proto_tree_add_item(tree, hf_nfs_fh_dc_opaque, tvb, offset + 17, obj_len, ENC_NA);
2160 	return tvb_captured_length(tvb);
2161 }
2162 
2163 #define PD_VERSION_MASK   0xf0000000
2164 #define PD_RESERVED_MASK  0x0ffffffF
2165 #define PD_INUM_MASK      G_GUINT64_CONSTANT(0x0007ffffffffffff)
2166 #define PD_SITEID_MASK    G_GUINT64_CONSTANT(0xfff8000000000000)
2167 #define PD_SNAPID_MASK    G_GUINT64_CONSTANT(0x0000000000001fff)
2168 #define PD_CONTAINER_MASK G_GUINT64_CONSTANT(0xffffffffffffe000)
2169 
2170 static int
dissect_fhandle_data_PRIMARY_DATA(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2171 dissect_fhandle_data_PRIMARY_DATA(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2172 {
2173 	int offset = 0;
2174 	guint32 version;
2175 
2176 	static int * const fh_flags[] = {
2177 		&hf_nfs4_fh_pd_flags_version,
2178 		&hf_nfs4_fh_pd_flags_reserved,
2179 		NULL
2180 	};
2181 
2182 	static int * const fh_sites[] = {
2183 		&hf_nfs4_fh_pd_sites_inum,
2184 		&hf_nfs4_fh_pd_sites_siteid,
2185 		NULL
2186 	};
2187 
2188 	static int * const fh_spaces[] = {
2189 		&hf_nfs4_fh_pd_spaces_snapid,
2190 		&hf_nfs4_fh_pd_spaces_container,
2191 		NULL
2192 	};
2193 
2194 
2195 	if (!tree)
2196 		return tvb_captured_length(tvb);
2197 
2198 
2199 	version = (tvb_get_letohl(tvb, offset + 4) & PD_VERSION_MASK) >> 28;
2200 	if (version > 2) {
2201 		return 0;
2202 	}
2203 
2204 	proto_tree_add_item(tree, hf_nfs4_fh_pd_share, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2205 	proto_tree_add_bitmask(tree, tvb, offset + 4, hf_nfs4_fh_pd_flags, ett_nfs4_fh_pd_flags, fh_flags, ENC_LITTLE_ENDIAN);
2206 
2207 	if (version == 0) {
2208 		proto_tree_add_item(tree, hf_nfs4_fh_pd_inum, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
2209 	} else if (version == 1) {
2210 		proto_tree_add_item(tree, hf_nfs4_fh_pd_container, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
2211 		proto_tree_add_item(tree, hf_nfs4_fh_pd_inum, tvb, offset + 16, 8, ENC_LITTLE_ENDIAN);
2212 	} else if (version == 2) {
2213 		proto_tree_add_bitmask(tree, tvb, offset + 8, hf_nfs4_fh_pd_spaces, ett_nfs4_fh_pd_spaces, fh_spaces, ENC_LITTLE_ENDIAN);
2214 		proto_tree_add_bitmask(tree, tvb, offset + 16, hf_nfs4_fh_pd_sites, ett_nfs4_fh_pd_sites, fh_sites, ENC_LITTLE_ENDIAN);
2215 	}
2216 
2217 	return tvb_captured_length(tvb);
2218 }
2219 
2220 /* Dissect EMC Celerra or VNX NFSv3/v4 File Handle */
2221 static int
dissect_fhandle_data_CELERRA_VNX(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2222 dissect_fhandle_data_CELERRA_VNX(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2223 {
2224 	guint16 offset = 0;
2225 	guint16	fhlen;
2226 	guint32	obj_id;
2227 
2228 	fhlen = tvb_reported_length(tvb);
2229 
2230 	/* Display the entire file handle */
2231 	proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, ENC_NA);
2232 
2233 	/*	If fhlen = 32, it's an NFSv3 file handle */
2234 	if (fhlen == 32) {
2235 		/* Create a "File/Dir" subtree: bytes 0 thru 15 of the 32-byte file handle	 */
2236 		{
2237 		proto_item *obj_item;
2238 		proto_tree *obj_tree;
2239 
2240 		if (!tree)
2241 			return tvb_captured_length(tvb);
2242 
2243 		obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+0, 16, ENC_NA );
2244 		obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
2245 
2246 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_fsid,   tvb,  offset+0, 4, ENC_LITTLE_ENDIAN);
2247 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_kindid, tvb,  offset+4, 2, ENC_LITTLE_ENDIAN);
2248 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_treeid, tvb,  offset+6, 2, ENC_LITTLE_ENDIAN);
2249 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_inode,  tvb,  offset+8, 4, ENC_LITTLE_ENDIAN);
2250 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
2251 		}
2252 		{
2253 		/* Create "Export" subtree (NFSv3: Bytes 16 thru 31 of the 32-byte file handle  */
2254 		proto_item *ex_item;
2255 		proto_tree *ex_tree;
2256 		ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex, tvb,  offset+16, 16, ENC_NA );
2257 		ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
2258 
2259 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_fsid,     tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
2260 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_kindid,   tvb, offset+20, 2, ENC_LITTLE_ENDIAN);
2261 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_treeid,   tvb, offset+22, 2, ENC_LITTLE_ENDIAN);
2262 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_inode,    tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
2263 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_gen,      tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
2264 		}
2265 	} else if (fhlen == 40) {
2266 		/*
2267 		If fhlen = 40, it's an NFSv4 file handle).  In Celerra|VNX NFSv4 file handles,
2268 		the first 4 bytes hold the Named Attribute ID, and the next 4 bytes hold the
2269 		RO_Node boolean which if true, the file/dir is Read Only. Unlike NFSv3 file
2270 		handles where the file/dir info precedes the export info, the next 16 bytes contain
2271 		the *export* info followed by 16 bytes containing the *file/dir* info.
2272 		*/
2273 
2274 		if (!tree)
2275 			return tvb_captured_length(tvb);
2276 
2277 		/* "Named Attribute ID" or "Object ID" (bytes 0 thru 3) */
2278 		obj_id = tvb_get_letohl(tvb, offset+0);
2279 		if (obj_id <= 0 || obj_id > 9) obj_id = 1;
2280 		proto_tree_add_uint(tree, hf_nfs_fh_obj_id,         tvb,  offset+0, 4, obj_id);
2281 
2282 		/* "RO_Node" boolean (bytes 4 thru 7) */
2283 		proto_tree_add_item(tree, hf_nfs_fh_ro_node,     tvb,  offset+4, 4, ENC_LITTLE_ENDIAN);
2284 
2285 		/* Create "Export" subtree (bytes 8 thru 23 of the 40-byte file handle  */
2286 		{
2287 		proto_item *ex_item;
2288 		proto_tree *ex_tree;
2289 		ex_item = proto_tree_add_item(tree, hf_nfs_fh_ex,  tvb,  offset+8, 16, ENC_NA );
2290 		ex_tree = proto_item_add_subtree(ex_item, ett_nfs_fh_ex);
2291 
2292 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_fsid,    tvb,  offset+8,  4, ENC_LITTLE_ENDIAN);
2293 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_kindid,  tvb, offset+12,  2, ENC_LITTLE_ENDIAN);
2294 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_treeid,  tvb, offset+14,  2, ENC_LITTLE_ENDIAN);
2295 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_inode,   tvb, offset+16,  4, ENC_LITTLE_ENDIAN);
2296 		proto_tree_add_item(ex_tree, hf_nfs_fh_ex_gen,     tvb, offset+20,  4, ENC_LITTLE_ENDIAN);
2297 		}
2298 		/* Create a "File/Dir/Object" subtree (bytes 24 thru 39 of the 40-byte file handle) */
2299 		{
2300 		proto_item *obj_item;
2301 		proto_tree *obj_tree;
2302 		obj_item = proto_tree_add_item(tree, hf_nfs_fh_obj, tvb, offset+24, 16, ENC_NA);
2303 		obj_tree = proto_item_add_subtree(obj_item, ett_nfs_fh_obj);
2304 
2305 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_fsid,   tvb, offset+24,  4, ENC_LITTLE_ENDIAN);
2306 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_kindid, tvb, offset+28,  2, ENC_LITTLE_ENDIAN);
2307 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_treeid, tvb, offset+30,  2, ENC_LITTLE_ENDIAN);
2308 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_inode,  tvb, offset+32,  4, ENC_LITTLE_ENDIAN);
2309 		proto_tree_add_item(obj_tree, hf_nfs_fh_obj_gen,    tvb, offset+36,  4, ENC_LITTLE_ENDIAN);
2310 		}
2311 	} else {
2312 		/* This is not a Celerra|VNX file handle.  Display a warning. */
2313 		expert_add_info_format(pinfo, tree, &ei_nfs_not_vnx_file,
2314 			"Celerra|VNX file handles are 32 (NFSv3) or 40 (NFSv4) but the length is %u.\n"
2315 			"Change the 'Decode NFS file handles as' pref to the correct type or 'Unknown'.",
2316 			fhlen);
2317 	}
2318 	return tvb_captured_length(tvb);
2319 }
2320 
2321 
2322 static int
dissect_fhandle_data_unknown(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2323 dissect_fhandle_data_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
2324 {
2325 	guint fhlen = tvb_reported_length(tvb);
2326 
2327 	proto_tree_add_item(tree, hf_nfs_fh_fhandle_data, tvb, 0, fhlen, ENC_NA);
2328 	return tvb_captured_length(tvb);
2329 }
2330 
2331 
2332 static void
dissect_fhandle_data(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,unsigned int fhlen,gboolean hidden,guint32 * hash)2333 dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
2334 		     unsigned int fhlen, gboolean hidden, guint32 *hash)
2335 {
2336 	/* this is to set up fhandle display filters to find both packets
2337 	   of an RPC call */
2338 	if (nfs_fhandle_reqrep_matching && (!hidden) ) {
2339 		nfs_fhandle_data_t *old_fhd = NULL;
2340 
2341 		if ( !pinfo->fd->visited ) {
2342 			nfs_fhandle_data_t fhd;
2343 
2344 			/* first check if we have seen this fhandle before */
2345 			fhd.len = fhlen;
2346 			fhd.fh = (const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
2347 			old_fhd = store_nfs_file_handle(&fhd);
2348 
2349 			/* XXX here we should really check that we haven't stored
2350 			   this fhandle for this frame number already.
2351 			   We should also make sure we can handle when we have multiple
2352 			   fhandles seen for the same frame, which WILL happen for certain
2353 			   nfs calls. For now, we don't handle this and those calls will
2354 			   not work properly with this feature
2355 			*/
2356 			wmem_tree_insert32(nfs_fhandle_frame_table, pinfo->num, old_fhd);
2357 		}
2358 	}
2359 
2360 	/* Create a unique hash value for the filehandle using CRC32 */
2361 	{
2362 		guint32 fhhash;
2363 		proto_item *fh_item = NULL;
2364 
2365 		fhhash = crc32_ccitt_tvb_offset(tvb, offset, fhlen);
2366 
2367 		if (hidden) {
2368 			fh_item = proto_tree_add_uint(tree, hf_nfs_fh_hash, NULL, 0,
2369 				0, fhhash);
2370 			proto_item_set_hidden(fh_item);
2371 		} else {
2372 			fh_item = proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
2373 				fhlen, fhhash);
2374 		}
2375 		proto_item_set_generated(fh_item);
2376 		if (hash) {
2377 			*hash = fhhash;
2378 		}
2379 	}
2380 	if (nfs_file_name_snooping) {
2381 		nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
2382 	}
2383 
2384 	if (!hidden) {
2385 		tvbuff_t *fh_tvb;
2386 
2387 		fh_tvb = tvb_new_subset_length_caplen(tvb, offset, fhlen, fhlen);
2388 		if (!dissector_try_payload(nfs_fhandle_table, fh_tvb, pinfo, tree))
2389 			dissect_fhandle_data_unknown(fh_tvb, pinfo, tree, NULL);
2390 	}
2391 }
2392 
2393 
2394 void
dissect_fhandle_hidden(packet_info * pinfo,proto_tree * tree,int frame)2395 dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, int frame)
2396 {
2397 	nfs_fhandle_data_t *nfd;
2398 
2399 	nfd = (nfs_fhandle_data_t *)wmem_tree_lookup32(nfs_fhandle_frame_table, frame);
2400 	if (nfd && nfd->len) {
2401 		tvbuff_t *tvb;
2402 		tvb = tvb_new_real_data(nfd->fh, nfd->len, nfd->len);
2403 		/* There's no need to call add_new_data_source() since
2404 		   dissect_fhandle(), in the the 'hidden' case, never refers
2405 		   to the tvb when displaying a field based on the tvb */
2406 		dissect_fhandle_data(tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
2407 		tvb_free(tvb);
2408 	}
2409 }
2410 
2411 
2412 /***************************/
2413 /* NFS Version 2, RFC 1094 */
2414 /***************************/
2415 
2416 /* NFSv2 RFC 1094, Page 12..14 */
2417 static const value_string names_nfs2_stat[] =
2418 {
2419 	{	0,	"NFS_OK" },
2420 	{	1,	"NFS2ERR_PERM" },
2421 	{	2,	"NFS2ERR_NOENT" },
2422 	{	5,	"NFS2ERR_IO" },
2423 	{	6,	"NFS2ERR_NXIO" },
2424 	{	11,	"NFS2ERR_EAGAIN" },
2425 	{	13,	"NFS2ERR_ACCES" },
2426 	{	17,	"NFS2ERR_EXIST" },
2427 	{	18,	"NFS2ERR_XDEV" },	/* not in spec, but can happen */
2428 	{	19,	"NFS2ERR_NODEV" },
2429 	{	20,	"NFS2ERR_NOTDIR" },
2430 	{	21,	"NFS2ERR_ISDIR" },
2431 	{	22,	"NFS2ERR_INVAL" },	/* not in spec, but I think it can happen */
2432 	{	26,	"NFS2ERR_TXTBSY" },	/* not in spec, but I think it can happen */
2433 	{	27,	"NFS2ERR_FBIG" },
2434 	{	28,	"NFS2ERR_NOSPC" },
2435 	{	30,	"NFS2ERR_ROFS" },
2436 	{	31,	"NFS2ERR_MLINK" },	/* not in spec, but can happen */
2437 	{	45,	"NFS2ERR_OPNOTSUPP" },	/* not in spec, but I think it can happen */
2438 	{	63,	"NFS2ERR_NAMETOOLONG" },
2439 	{	66,	"NFS2ERR_NOTEMPTY" },
2440 	{	69,	"NFS2ERR_DQUOT" },
2441 	{	70,	"NFS2ERR_STALE" },
2442 	{	71,	"NFS2ERR_REMOTE" },
2443 	{	99,	"NFS2ERR_WFLUSH" },
2444 	{	10001,	"NFS2ERR_BADHANDLE" },
2445 	{	10002,	"NFS2ERR_NOT_SYNC" },
2446 	{	10003,	"NFS2ERR_BAD_COOKIE" },
2447 	{	10004,	"NFS2ERR_NOTSUPP" },
2448 	{	10005,	"NFS2ERR_TOOSMALL" },
2449 	{	10006,	"NFS2ERR_SERVERFAULT" },
2450 	{	10007,	"NFS2ERR_BADTYPE" },
2451 	{	10008,	"NFS2ERR_JUKEBOX" },
2452 	{	10009,	"NFS2ERR_SAME" },
2453 	{	10010,	"NFS2ERR_DENIED" },
2454 	{	10011,	"NFS2ERR_EXPIRED" },
2455 	{	10012,	"NFS2ERR_LOCKED" },
2456 	{	10013,	"NFS2ERR_GRACE" },
2457 	{	10014,	"NFS2ERR_FHEXPIRED" },
2458 	{	10015,	"NFS2ERR_SHARE_DENIED" },
2459 	{	10016,	"NFS2ERR_WRONGSEC" },
2460 	{	10017,	"NFS2ERR_CLID_INUSE" },
2461 	{	10018,	"NFS2ERR_RESOURCE" },
2462 	{	10019,	"NFS2ERR_MOVED" },
2463 	{	10020,	"NFS2ERR_NOFILEHANDLE" },
2464 	{	10021,	"NFS2ERR_MINOR_VERS_MISMATCH" },
2465 	{	10022,	"NFS2ERR_STALE_CLIENTID" },
2466 	{	10023,	"NFS2ERR_STALE_STATEID" },
2467 	{	10024,	"NFS2ERR_OLD_STATEID" },
2468 	{	10025,	"NFS2ERR_BAD_STATEID" },
2469 	{	10026,	"NFS2ERR_BAD_SEQID" },
2470 	{	10027,	"NFS2ERR_NOT_SAME" },
2471 	{	10028,	"NFS2ERR_LOCK_RANGE" },
2472 	{	10029,	"NFS2ERR_SYMLINK" },
2473 	{	10030,	"NFS2ERR_RESTOREFH" },
2474 	{	10031,	"NFS2ERR_LEASE_MOVED" },
2475 	{	10032,	"NFS2ERR_ATTRNOTSUPP" },
2476 	{	10033,	"NFS2ERR_NO_GRACE" },
2477 	{	10034,	"NFS2ERR_RECLAIM_BAD" },
2478 	{	10035,	"NFS2ERR_RECLAIM_CONFLICT" },
2479 	{	10036,	"NFS2ERR_BAD_XDR" },
2480 	{	10037,	"NFS2ERR_LOCKS_HELD" },
2481 	{	10038,	"NFS2ERR_OPENMODE" },
2482 	{	10039,	"NFS2ERR_BADOWNER" },
2483 	{	10040,	"NFS2ERR_BADCHAR" },
2484 	{	10041,	"NFS2ERR_BADNAME" },
2485 	{	10042,	"NFS2ERR_BAD_RANGE" },
2486 	{	10043,	"NFS2ERR_LOCK_NOTSUPP" },
2487 	{	10044,	"NFS2ERR_OP_ILLEGAL" },
2488 	{	10045,	"NFS2ERR_DEADLOCK" },
2489 	{	10046,	"NFS2ERR_FILE_OPEN" },
2490 	{	10047,	"NFS2ERR_ADMIN_REVOKED" },
2491 	{	10048,	"NFS2ERR_CB_PATH_DOWN" },
2492 	{	10049,	"NFS2ERR_REPLAY_ME" },
2493 	{	0,	NULL }
2494 };
2495 static value_string_ext names_nfs2_stat_ext = VALUE_STRING_EXT_INIT(names_nfs2_stat);
2496 
2497 /* NFSv2 RFC 1094, Page 12..14 */
2498 static int
dissect_nfs2_status(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * status)2499 dissect_nfs2_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status)
2500 {
2501 	guint32	    stat;
2502 	proto_item *stat_item;
2503 
2504 	proto_tree_add_item_ret_uint(tree, hf_nfs2_status, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stat);
2505 	stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, stat);
2506 	proto_item_set_hidden(stat_item);
2507 
2508 	offset += 4;
2509 
2510 	if (status)
2511 		*status = stat;
2512 
2513 	return offset;
2514 }
2515 
2516 
2517 /* NFSv2 RFC 1094, Page 12..14 */
2518 static int
dissect_nfs2_rmdir_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2519 dissect_nfs2_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2520 {
2521 	guint32	    status;
2522 	const char *err;
2523 	int offset = 0;
2524 
2525 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2526 	switch (status) {
2527 		case 0:
2528 			proto_item_append_text(tree, ", RMDIR Reply");
2529 			break;
2530 		default:
2531 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2532 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2533 			proto_item_append_text(tree, ", RMDIR Reply  Error: %s", err);
2534 	}
2535 
2536 	return offset;
2537 }
2538 
2539 
2540 static int
dissect_nfs2_symlink_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2541 dissect_nfs2_symlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2542 {
2543 	guint32	    status;
2544 	const char *err;
2545 	int offset = 0;
2546 
2547 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2548 	switch (status) {
2549 		case 0:
2550 			proto_item_append_text(tree, ", SYMLINK Reply");
2551 			break;
2552 		default:
2553 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2554 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2555 			proto_item_append_text(tree, ", SYMLINK Reply  Error: %s", err);
2556 	}
2557 
2558 	return offset;
2559 }
2560 
2561 
2562 static int
dissect_nfs2_link_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2563 dissect_nfs2_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2564 {
2565 	guint32	    status;
2566 	const char *err;
2567 	int offset = 0;
2568 
2569 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2570 	switch (status) {
2571 		case 0:
2572 			proto_item_append_text(tree, ", LINK Reply");
2573 			break;
2574 		default:
2575 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2576 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2577 			proto_item_append_text(tree, ", LINK Reply  Error: %s", err);
2578 	}
2579 
2580 	return offset;
2581 }
2582 
2583 
2584 static int
dissect_nfs2_rename_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2585 dissect_nfs2_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2586 {
2587 	guint32	    status;
2588 	const char *err;
2589 	int offset = 0;
2590 
2591 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2592 	switch (status) {
2593 		case 0:
2594 			proto_item_append_text(tree, ", RENAME Reply");
2595 			break;
2596 		default:
2597 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2598 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2599 			proto_item_append_text(tree, ", RENAME Reply  Error: %s", err);
2600 	}
2601 
2602 	return offset;
2603 }
2604 
2605 
2606 static int
dissect_nfs2_remove_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2607 dissect_nfs2_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2608 {
2609 	guint32	    status;
2610 	const char *err;
2611 	int offset = 0;
2612 
2613 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2614 	switch (status) {
2615 		case 0:
2616 			proto_item_append_text(tree, ", REMOVE Reply");
2617 			break;
2618 		default:
2619 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2620 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2621 			proto_item_append_text(tree, ", REMOVE Reply  Error: %s", err);
2622 	}
2623 
2624 	return offset;
2625 }
2626 
2627 
2628 /* NFSv2 RFC 1094, Page 15 */
2629 static const value_string nfs2_ftype[] =
2630 {
2631 	{	0,	"Non-File" },
2632 	{	1,	"Regular File" },
2633 	{	2,	"Directory" },
2634 	{	3,	"Block Special Device" },
2635 	{	4,	"Character Special Device" },
2636 	{	5,	"Symbolic Link" },
2637 	{	0,	NULL }
2638 };
2639 static value_string_ext nfs2_ftype_ext = VALUE_STRING_EXT_INIT(nfs2_ftype);
2640 
2641 static int
dissect_nfs2_ftype(tvbuff_t * tvb,int offset,proto_tree * tree)2642 dissect_nfs2_ftype(tvbuff_t *tvb, int offset, proto_tree *tree)
2643 {
2644 	proto_tree_add_item(tree, hf_nfs2_ftype, tvb, offset, 4, ENC_BIG_ENDIAN);
2645 	offset += 4;
2646 	return offset;
2647 }
2648 
2649 
2650 /* NFSv2 RFC 1094, Page 15 */
2651 int
dissect_fhandle(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name,guint32 * hash,rpc_call_info_value * civ)2652 dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
2653 	        const char *name, guint32 *hash, rpc_call_info_value *civ)
2654 {
2655 	proto_tree *ftree;
2656 
2657 	ftree = proto_tree_add_subtree(tree, tvb, offset, FHSIZE,
2658 				ett_nfs_fhandle, NULL, name);
2659 
2660 
2661 	/* are we snooping fh to filenames ?*/
2662 	if ((!pinfo->fd->visited) && nfs_file_name_snooping) {
2663 
2664 		/* NFS v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
2665 		if ( (civ->prog == 100003)
2666 		  &&(civ->vers == 2)
2667 		  &&(!civ->request)
2668 		  &&((civ->proc == 4)||(civ->proc == 9)||(civ->proc == 14))
2669 		) {
2670 			nfs_name_snoop_add_fh(civ->xid, tvb,
2671 				offset, 32);
2672 		}
2673 
2674 		/* MOUNT v1,v2 MNT replies might give us a filehandle*/
2675 		if ( (civ->prog == 100005)
2676 		  &&(civ->proc == 1)
2677 		  &&((civ->vers == 1)||(civ->vers == 2))
2678 		  &&(!civ->request)
2679 		) {
2680 			nfs_name_snoop_add_fh(civ->xid, tvb,
2681 				offset, 32);
2682 		}
2683 	}
2684 
2685 	dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
2686 
2687 	offset += FHSIZE;
2688 	return offset;
2689 }
2690 
2691 
2692 /* NFSv2 RFC 1094, Page 15 */
2693 static int
dissect_nfs2_statfs_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2694 dissect_nfs2_statfs_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2695 {
2696 	guint32 hash;
2697 	int offset = 0;
2698 
2699 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
2700 
2701 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
2702 	proto_item_append_text(tree, ", STATFS Call FH: 0x%08x", hash);
2703 
2704 	return offset;
2705 }
2706 
2707 
2708 static int
dissect_nfs2_readlink_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2709 dissect_nfs2_readlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2710 {
2711 	guint32 hash;
2712 	int offset = 0;
2713 
2714 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
2715 
2716 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
2717 	proto_item_append_text(tree, ", READLINK Call FH: 0x%08x", hash);
2718 
2719 	return offset;
2720 }
2721 
2722 
2723 static int
dissect_nfs2_getattr_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2724 dissect_nfs2_getattr_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2725 {
2726 	guint32 hash;
2727 	int offset = 0;
2728 
2729 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
2730 
2731 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
2732 	proto_item_append_text(tree, ", GETATTR Call FH: 0x%08x", hash);
2733 
2734 	return offset;
2735 }
2736 
2737 
2738 /* NFSv2 RFC 1094, Page 15 */
2739 static int
dissect_timeval(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_time,int hf_time_sec,int hf_time_usec)2740 dissect_timeval(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time, int hf_time_sec,
2741 			    int hf_time_usec)
2742 {
2743 
2744 	if (tree) {
2745 		proto_item *time_item;
2746 		proto_tree *time_tree;
2747 		guint32	    seconds;
2748 		guint32	    useconds;
2749 		nstime_t    ts;
2750 
2751 		seconds	 = tvb_get_ntohl(tvb, offset+0);
2752 		useconds = tvb_get_ntohl(tvb, offset+4);
2753 		ts.secs	 = seconds;
2754 		ts.nsecs = useconds * 1000;
2755 
2756 		time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
2757 				&ts);
2758 
2759 		time_tree = proto_item_add_subtree(time_item, ett_nfs_timeval);
2760 
2761 		proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
2762 				    seconds);
2763 		proto_tree_add_uint(time_tree, hf_time_usec, tvb, offset+4, 4,
2764 				    useconds);
2765 	}
2766 	offset += 8;
2767 	return offset;
2768 }
2769 
2770 /* NFSv2 RFC 1094, Page 16 */
2771 static const value_string nfs2_mode_names[] = {
2772 	{	0040000,	"Directory"	},
2773 	{	0020000,	"Character Special Device"	},
2774 	{	0060000,	"Block Special Device"	},
2775 	{	0100000,	"Regular File"	},
2776 	{	0120000,	"Symbolic Link"	},
2777 	{	0140000,	"Named Socket"	},
2778 	{	0000000,	NULL		}
2779 };
2780 
2781 static int
dissect_nfs2_mode(tvbuff_t * tvb,int offset,proto_tree * tree)2782 dissect_nfs2_mode(tvbuff_t *tvb, int offset, proto_tree *tree)
2783 {
2784 	static int * const modes[] = {
2785 		&hf_nfs2_mode_name,
2786 		&hf_nfs2_mode_set_user_id,
2787 		&hf_nfs2_mode_set_group_id,
2788 		&hf_nfs2_mode_save_swap_text,
2789 		&hf_nfs2_mode_read_owner,
2790 		&hf_nfs2_mode_write_owner,
2791 		&hf_nfs2_mode_exec_owner,
2792 		&hf_nfs2_mode_read_group,
2793 		&hf_nfs2_mode_write_group,
2794 		&hf_nfs2_mode_exec_group,
2795 		&hf_nfs2_mode_read_other,
2796 		&hf_nfs2_mode_write_other,
2797 		&hf_nfs2_mode_exec_other,
2798 		NULL
2799 	};
2800 
2801 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs2_mode, ett_nfs2_mode, modes, ENC_BIG_ENDIAN);
2802 
2803 	offset += 4;
2804 	return offset;
2805 }
2806 
2807 
2808 /* NFSv2 RFC 1094, Page 15 */
2809 int
dissect_nfs2_fattr(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)2810 dissect_nfs2_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
2811 {
2812 	proto_item *fattr_item;
2813 	proto_tree *fattr_tree;
2814 	int	    old_offset = offset;
2815 
2816 	fattr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
2817 			ett_nfs_fattr, &fattr_item, name);
2818 
2819 	offset = dissect_nfs2_ftype(tvb, offset, fattr_tree);
2820 	offset = dissect_nfs2_mode(tvb, offset, fattr_tree);
2821 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_nlink, offset);
2822 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_uid, offset);
2823 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_gid, offset);
2824 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_size, offset);
2825 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_blocksize, offset);
2826 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_rdev, offset);
2827 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_blocks, offset);
2828 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_fsid, offset);
2829 	offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs2_fattr_fileid, offset);
2830 
2831 	offset = dissect_timeval(tvb, offset, fattr_tree,
2832 		hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2833 	offset = dissect_timeval(tvb, offset, fattr_tree,
2834 		hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2835 	offset = dissect_timeval(tvb, offset, fattr_tree,
2836 		hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_usec);
2837 
2838 	/* now we know, that fattr is shorter */
2839 	proto_item_set_len(fattr_item, offset - old_offset);
2840 
2841 	return offset;
2842 }
2843 
2844 
2845 /* NFSv2 RFC 1094, Page 17 */
2846 static int
dissect_nfs2_sattr(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)2847 dissect_nfs2_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
2848 {
2849 	proto_item *sattr_item;
2850 	proto_tree *sattr_tree;
2851 	int	    old_offset = offset;
2852 
2853 	sattr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
2854 					ett_nfs2_sattr, &sattr_item, name);
2855 
2856 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2857 		offset = dissect_nfs2_mode(tvb, offset, sattr_tree);
2858 	else {
2859 		proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_mode, tvb, offset, 4, 0xffffffff, "no value");
2860 		offset += 4;
2861 	}
2862 
2863 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2864 		offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_uid,
2865 			offset);
2866 	else {
2867 		proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_uid, tvb, offset, 4, 0xffffffff, "no value");
2868 		offset += 4;
2869 	}
2870 
2871 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2872 		offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_gid,
2873 			offset);
2874 	else {
2875 		proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_gid, tvb, offset, 4, 0xffffffff, "no value");
2876 		offset += 4;
2877 	}
2878 
2879 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
2880 		offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs2_fattr_size,
2881 			offset);
2882 	else {
2883 		proto_tree_add_uint_format_value(sattr_tree, hf_nfs2_fattr_size, tvb, offset, 4, 0xffffffff, "no value");
2884 		offset += 4;
2885 	}
2886 
2887 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2888 		offset = dissect_timeval(tvb, offset, sattr_tree,
2889 			hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
2890 	} else {
2891 		nstime_t    ts;
2892 
2893 		ts.secs	 = 0xffffffff;
2894 		ts.nsecs = 0;
2895 
2896 		proto_tree_add_time_format_value(sattr_tree, hf_nfs_atime, tvb, offset, 8, &ts, "no value");
2897 		offset += 8;
2898 	}
2899 
2900 	if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
2901 		offset = dissect_timeval(tvb, offset, sattr_tree,
2902 			hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
2903 	} else {
2904 		nstime_t    ts;
2905 
2906 		ts.secs	 = 0xffffffff;
2907 		ts.nsecs = 0;
2908 
2909 		proto_tree_add_time_format_value(sattr_tree, hf_nfs_mtime, tvb, offset, 8, &ts, "no value");
2910 		offset += 8;
2911 	}
2912 
2913 	/* now we know, that sattr is shorter */
2914 	proto_item_set_len(sattr_item, offset - old_offset);
2915 
2916 	return offset;
2917 }
2918 
2919 
2920 /* NFSv2 RFC 1094, Page 17 */
2921 static int
dissect_filename(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** string_ret)2922 dissect_filename(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, const char **string_ret)
2923 {
2924 	offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
2925 	return offset;
2926 }
2927 
2928 
2929 /* NFSv2 RFC 1094, Page 17 */
2930 static int
dissect_path(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** name)2931 dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, const char **name)
2932 {
2933 	offset = dissect_rpc_string(tvb, tree, hf, offset, name);
2934 	return offset;
2935 }
2936 
2937 
2938 /* NFSv2 RFC 1094, Page 17,18 */
2939 static int
dissect_attrstat(tvbuff_t * tvb,int offset,proto_tree * tree,packet_info * pinfo,const char * funcname)2940 dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, const char *funcname)
2941 {
2942 	guint32	    status;
2943 	const char *err;
2944 
2945 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
2946 	switch (status) {
2947 		case 0:
2948 			offset = dissect_nfs2_fattr(tvb, offset, tree, "attributes");
2949 			proto_item_append_text(tree, ", %s Reply", funcname);
2950 		break;
2951 		default:
2952 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
2953 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
2954 			proto_item_append_text(tree, ", %s Reply  Error: %s", funcname, err);
2955 		break;
2956 	}
2957 
2958 	return offset;
2959 }
2960 
2961 
2962 /* NFSv2 RFC 1094, Page 17,18 */
2963 static int
dissect_nfs2_write_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2964 dissect_nfs2_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2965 {
2966 	return dissect_attrstat(tvb, 0, tree, pinfo, "WRITE");
2967 }
2968 
2969 
2970 /* NFSv2 RFC 1094, Page 18 */
2971 static int
dissect_nfs2_setattr_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2972 dissect_nfs2_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2973 {
2974 	return dissect_attrstat(tvb, 0, tree, pinfo, "SETATTR");
2975 }
2976 
2977 
2978 /* NFSv2 RFC 1094, Page 18 */
2979 static int
dissect_nfs2_getattr_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)2980 dissect_nfs2_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
2981 {
2982 	return dissect_attrstat(tvb, 0, tree, pinfo, "GETATTR");
2983 }
2984 
2985 
2986 /* NFSv2 RFC 1094, Page 18 */
2987 static int
dissect_diropargs(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * label,guint32 * hash,const char ** name,rpc_call_info_value * civ)2988 dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
2989 				  const char *label, guint32 *hash, const char **name, rpc_call_info_value *civ)
2990 {
2991 	proto_item *diropargs_item;
2992 	proto_tree *diropargs_tree;
2993 	int	    old_offset	   = offset;
2994 
2995 	diropargs_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
2996 			ett_nfs2_diropargs, &diropargs_item, label);
2997 
2998 	/* are we snooping fh to filenames ?*/
2999 	if ((!pinfo->fd->visited) && nfs_file_name_snooping) {
3000 		/* v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
3001 
3002 		if ( (civ->prog == 100003)
3003 		  &&(civ->vers == 2)
3004 		  &&(civ->request)
3005 		  &&((civ->proc == 4)||(civ->proc == 9)||(civ->proc == 14))
3006 		) {
3007 			nfs_name_snoop_add_name(civ->xid, tvb,
3008 				offset+36, tvb_get_ntohl(tvb, offset+32),
3009 				offset, 32, NULL);
3010 		}
3011 	}
3012 
3013 	offset = dissect_fhandle(tvb, offset, pinfo, diropargs_tree, "dir", hash, civ);
3014 	offset = dissect_filename(tvb, offset, diropargs_tree, hf_nfs_name, name);
3015 
3016 	/* now we know, that diropargs is shorter */
3017 	proto_item_set_len(diropargs_item, offset - old_offset);
3018 
3019 	return offset;
3020 }
3021 
3022 
3023 /* NFSv2 RFC 1094, Page 18 */
3024 static int
dissect_nfs2_rmdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3025 dissect_nfs2_rmdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3026 {
3027 	guint32	    hash;
3028 	const char *name = NULL;
3029 	int offset = 0;
3030 
3031 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
3032 
3033 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
3034 	proto_item_append_text(tree, ", RMDIR Call DH: 0x%08x/%s", hash, name);
3035 
3036 	return offset;
3037 }
3038 
3039 
3040 /* NFSv2 RFC 1094, Page 18 */
3041 static int
dissect_nfs2_remove_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3042 dissect_nfs2_remove_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3043 {
3044 	guint32	    hash;
3045 	const char *name = NULL;
3046 	int offset = 0;
3047 
3048 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
3049 
3050 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
3051 	proto_item_append_text(tree, ", REMOVE Call DH: 0x%08x/%s", hash, name);
3052 
3053 	return offset;
3054 }
3055 
3056 
3057 /* NFSv2 RFC 1094, Page 18 */
3058 static int
dissect_nfs2_lookup_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3059 dissect_nfs2_lookup_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3060 {
3061 	guint32	    hash;
3062 	const char *name = NULL;
3063 	int offset = 0;
3064 
3065 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
3066 
3067 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
3068 	proto_item_append_text(tree, ", LOOKUP Call DH: 0x%08x/%s", hash, name);
3069 
3070 	return offset;
3071 }
3072 
3073 
3074 /* NFSv2 RFC 1094, Page 18 */
3075 static int
dissect_diropres(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * funcname,rpc_call_info_value * civ)3076 dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo,
3077 		 proto_tree *tree, const char *funcname, rpc_call_info_value* civ)
3078 {
3079 	guint32	    status;
3080 	guint32	    hash;
3081 	const char *err;
3082 
3083 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
3084 	switch (status) {
3085 		case 0:
3086 			offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, civ);
3087 			offset = dissect_nfs2_fattr  (tvb, offset, tree, "attributes");
3088 			col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
3089 			proto_item_append_text(tree, ", %s Reply FH: 0x%08x", funcname, hash);
3090 		break;
3091 		default:
3092 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
3093 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
3094 			proto_item_append_text(tree, ", %s Reply  Error: %s", funcname, err);
3095 		break;
3096 	}
3097 
3098 	return offset;
3099 }
3100 
3101 
3102 /* nfsdata is simply a chunk of RPC opaque data (length, data, fill bytes) */
3103 static int
dissect_nfsdata(tvbuff_t * tvb,int offset,proto_tree * tree,int hf)3104 dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
3105 {
3106 	offset = dissect_rpc_data(tvb, tree, hf, offset);
3107 	return offset;
3108 }
3109 
3110 
3111 /* NFSv2 RFC 1094, Page 18 */
3112 static int
dissect_nfs2_mkdir_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3113 dissect_nfs2_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo,
3114 			 proto_tree *tree, void *data)
3115 {
3116 	return dissect_diropres(tvb, 0, pinfo, tree, "MKDIR", (rpc_call_info_value*)data);
3117 }
3118 
3119 
3120 static int
dissect_nfs2_create_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3121 dissect_nfs2_create_reply(tvbuff_t *tvb, packet_info *pinfo,
3122 			  proto_tree *tree, void *data _U_)
3123 {
3124 	return dissect_diropres(tvb, 0, pinfo, tree, "CREATE", (rpc_call_info_value*)data);
3125 }
3126 
3127 
3128 static int
dissect_nfs2_lookup_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3129 dissect_nfs2_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
3130 			  proto_tree *tree, void *data _U_)
3131 {
3132 	return dissect_diropres(tvb, 0, pinfo, tree, "LOOKUP", (rpc_call_info_value*)data);
3133 }
3134 
3135 
3136 /* RFC 1094, Page 6 */
3137 static int
dissect_nfs2_setattr_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3138 dissect_nfs2_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
3139 			  proto_tree *tree, void *data)
3140 {
3141 	guint32 hash;
3142 	int offset = 0;
3143 
3144 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
3145 	offset = dissect_nfs2_sattr  (tvb, offset,        tree, "attributes");
3146 
3147 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
3148 	proto_item_append_text(tree, ", SETATTR Call FH: 0x%08x", hash);
3149 	return offset;
3150 }
3151 
3152 
3153 /* NFSv2 RFC 1094, Page 6 */
3154 static int
dissect_nfs2_readlink_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3155 dissect_nfs2_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
3156 			    proto_tree *tree, void *data _U_)
3157 {
3158 	guint32	    status;
3159 	const char *err;
3160 	const char *name = NULL;
3161 	int offset = 0;
3162 
3163 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
3164 	switch (status) {
3165 		case 0:
3166 			offset = dissect_nfsdata_reduced(R_NFS2_PATH, tvb, offset, tree, hf_nfs2_readlink_data, &name);
3167 			col_append_fstr(pinfo->cinfo, COL_INFO, " Path: %s", name);
3168 			proto_item_append_text(tree, ", READLINK Reply Path: %s", name);
3169 		break;
3170 		default:
3171 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
3172 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
3173 			proto_item_append_text(tree, ", READLINK Reply  Error: %s", err);
3174 		break;
3175 	}
3176 
3177 	return offset;
3178 }
3179 
3180 
3181 /* NFSv2 RFC 1094, Page 7 */
3182 static int
dissect_nfs2_read_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3183 dissect_nfs2_read_call(tvbuff_t *tvb, packet_info *pinfo,
3184 		       proto_tree *tree, void *data)
3185 {
3186 	guint32 offset_value;
3187 	guint32 count;
3188 	guint32 totalcount;
3189 	guint32 hash;
3190 	int offset = 0;
3191 
3192 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
3193 	proto_tree_add_item_ret_uint(tree, hf_nfs2_read_offset, tvb,
3194 		offset+0, 4, ENC_BIG_ENDIAN, &offset_value);
3195 	proto_tree_add_item_ret_uint(tree, hf_nfs2_read_count, tvb,
3196 		offset+4, 4, ENC_BIG_ENDIAN, &count);
3197 	proto_tree_add_item_ret_uint(tree, hf_nfs2_read_totalcount, tvb,
3198 		offset+8, 4, ENC_BIG_ENDIAN, &totalcount);
3199 	offset += 12;
3200 
3201 	col_append_fstr(pinfo->cinfo, COL_INFO,	", FH: 0x%08x Offset: %d Count: %d TotalCount: %d",
3202 		hash, offset_value, count, totalcount);
3203 	proto_item_append_text(tree, ", READ Call FH: 0x%08x Offset: %d Count: %d TotalCount: %d",
3204 		hash, offset_value, count, totalcount);
3205 
3206 	return offset;
3207 }
3208 
3209 
3210 /* NFSv2 RFC 1094, Page 7 */
3211 static int
dissect_nfs2_read_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3212 dissect_nfs2_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
3213 			proto_tree *tree, void *data _U_)
3214 {
3215 	guint32	    status;
3216 	const char *err;
3217 	int offset = 0;
3218 
3219 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
3220 	switch (status) {
3221 		case 0:
3222 			offset = dissect_nfs2_fattr(tvb, offset, tree, "attributes");
3223 			proto_item_append_text(tree, ", READ Reply");
3224 			offset = dissect_nfsdata_reduced(R_NFSDATA, tvb, offset, tree, hf_nfs_data, NULL);
3225 		break;
3226 		default:
3227 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
3228 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
3229 			proto_item_append_text(tree, ", READ Reply  Error: %s", err);
3230 		break;
3231 	}
3232 
3233 	return offset;
3234 }
3235 
3236 
3237 /* NFSv2 RFC 1094, Page 8 */
3238 static int
dissect_nfs2_write_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3239 dissect_nfs2_write_call(tvbuff_t *tvb, packet_info *pinfo,
3240 			proto_tree *tree, void *data)
3241 {
3242 	guint32 beginoffset;
3243 	guint32 offset_value;
3244 	guint32 totalcount;
3245 	guint32 hash;
3246 	int offset = 0;
3247 
3248 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
3249 
3250 	proto_tree_add_item_ret_uint(tree, hf_nfs2_write_beginoffset, tvb,
3251 		offset+0, 4, ENC_BIG_ENDIAN, &beginoffset);
3252 	proto_tree_add_item_ret_uint(tree, hf_nfs2_write_offset, tvb,
3253 		offset+4, 4, ENC_BIG_ENDIAN, &offset_value);
3254 	proto_tree_add_item_ret_uint(tree, hf_nfs2_write_totalcount, tvb,
3255 		offset+8, 4, ENC_BIG_ENDIAN, &totalcount);
3256 	offset += 12;
3257 
3258 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x BeginOffset: %d Offset: %d TotalCount: %d",
3259 		hash, beginoffset, offset_value, totalcount);
3260 	proto_item_append_text(tree, ", WRITE Call FH: 0x%08x BeginOffset: %d Offset: %d TotalCount: %d",
3261 		hash, beginoffset, offset_value, totalcount);
3262 
3263 	offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
3264 
3265 	return offset;
3266 }
3267 
3268 
3269 /* NFSv2 RFC 1094, Page 8 */
3270 static int
dissect_nfs2_mkdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3271 dissect_nfs2_mkdir_call(tvbuff_t *tvb, packet_info *pinfo,
3272 			proto_tree *tree, void *data)
3273 {
3274 	guint32	    hash;
3275 	const char *name = NULL;
3276 	int offset = 0;
3277 
3278 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
3279 	offset = dissect_nfs2_sattr    (tvb, offset,        tree, "attributes");
3280 
3281 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
3282 	proto_item_append_text(tree, ", MKDIR Call DH: 0x%08x/%s", hash, name);
3283 
3284 	return offset;
3285 }
3286 
3287 static int
dissect_nfs2_create_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3288 dissect_nfs2_create_call(tvbuff_t *tvb, packet_info *pinfo,
3289 			 proto_tree *tree, void *data)
3290 {
3291 	guint32	    hash;
3292 	const char *name = NULL;
3293 	int offset = 0;
3294 
3295 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
3296 	offset = dissect_nfs2_sattr    (tvb, offset,        tree, "attributes");
3297 
3298 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
3299 	proto_item_append_text(tree, ", CREATE Call DH: 0x%08x/%s", hash, name);
3300 
3301 	return offset;
3302 }
3303 
3304 
3305 /* NFSv2 RFC 1094, Page 9 */
3306 static int
dissect_nfs2_rename_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3307 dissect_nfs2_rename_call(tvbuff_t *tvb, packet_info *pinfo,
3308 			 proto_tree *tree, void *data)
3309 {
3310 	guint32	    from_hash;
3311 	const char *from_name = NULL;
3312 	guint32	    to_hash;
3313 	const char *to_name   = NULL;
3314 	int offset = 0;
3315 
3316 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
3317 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
3318 
3319 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x/%s To DH: 0x%08x/%s",
3320 		from_hash, from_name, to_hash, to_name);
3321 	proto_item_append_text(tree, ", RENAME Call From DH: 0x%08x/%s To DH: 0x%08x/%s",
3322 		from_hash, from_name, to_hash, to_name);
3323 
3324 	return offset;
3325 }
3326 
3327 
3328 /* NFSv2 RFC 1094, Page 9 */
3329 static int
dissect_nfs2_link_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3330 dissect_nfs2_link_call(tvbuff_t *tvb, packet_info *pinfo,
3331 		       proto_tree *tree, void *data)
3332 {
3333 	guint32	    from_hash;
3334 	guint32	    to_hash;
3335 	const char *to_name = NULL;
3336 	int offset = 0;
3337 
3338 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash, (rpc_call_info_value*)data);
3339 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
3340 
3341 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x To DH: 0x%08x/%s",
3342 		from_hash, to_hash, to_name);
3343 	proto_item_append_text(tree, ", LINK Call From DH: 0x%08x To DH: 0x%08x/%s",
3344 		from_hash, to_hash, to_name);
3345 
3346 	return offset;
3347 }
3348 
3349 
3350 /* NFSv2 RFC 1094, Page 10 */
3351 static int
dissect_nfs2_symlink_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3352 dissect_nfs2_symlink_call(tvbuff_t *tvb, packet_info *pinfo,
3353 			  proto_tree *tree, void *data)
3354 {
3355 	guint32	    from_hash;
3356 	const char *from_name = NULL;
3357 	const char *to_name   = NULL;
3358 	int offset = 0;
3359 
3360 	offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
3361 	offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
3362 	offset = dissect_nfs2_sattr(tvb, offset, tree, "attributes");
3363 
3364 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x/%s To %s",
3365 		from_hash, from_name, to_name);
3366 	proto_item_append_text(tree, ", SYMLINK Call From DH: 0x%08x/%s To %s",
3367 		from_hash, from_name, to_name);
3368 
3369 	return offset;
3370 }
3371 
3372 
3373 /* NFSv2 RFC 1094, Page 11 */
3374 static int
dissect_nfs2_readdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3375 dissect_nfs2_readdir_call(tvbuff_t *tvb, packet_info *pinfo,
3376 			  proto_tree *tree, void *data)
3377 {
3378 	guint32 hash;
3379 	int offset = 0;
3380 
3381 	offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
3382 
3383 	proto_tree_add_item(tree, hf_nfs2_readdir_cookie, tvb, offset+ 0, 4, ENC_BIG_ENDIAN);
3384 	proto_tree_add_item(tree, hf_nfs2_readdir_count, tvb, offset+ 4, 4, ENC_BIG_ENDIAN);
3385 	offset += 8;
3386 
3387 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
3388 	proto_item_append_text(tree, ", READDIR Call FH: 0x%08x", hash);
3389 
3390 	return offset;
3391 }
3392 
3393 
3394 /* NFSv2 RFC 1094, Page 11 */
3395 static int
dissect_readdir_entry(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3396 dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
3397 		      proto_tree *tree, void *data _U_)
3398 {
3399 	proto_item *entry_item = NULL;
3400 	proto_tree *entry_tree = NULL;
3401 	int	    old_offset = offset;
3402 	guint32	    fileid;
3403 	const char *name;
3404 
3405 	if (tree) {
3406 		entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
3407 			offset+0, -1, ENC_NA);
3408 		entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
3409 	}
3410 
3411 	proto_tree_add_item_ret_uint(entry_tree, hf_nfs2_readdir_entry_fileid, tvb,
3412 			offset, 4, ENC_BIG_ENDIAN, &fileid);
3413 	offset += 4;
3414 
3415 	offset = dissect_filename(tvb, offset, entry_tree,
3416 		hf_nfs2_readdir_entry_name, &name);
3417 	if (entry_item)
3418 		proto_item_set_text(entry_item, "Entry: file ID %u, name %s", fileid, name);
3419 
3420 	proto_tree_add_item(entry_tree, hf_nfs2_readdir_entry_cookie, tvb, offset, 4, ENC_BIG_ENDIAN);
3421 	offset += 4;
3422 
3423 	/* now we know, that a readdir entry is shorter */
3424 	if (entry_item) {
3425 		proto_item_set_len(entry_item, offset - old_offset);
3426 	}
3427 
3428 	return offset;
3429 }
3430 
3431 
3432 /* NFSv2 RFC 1094, Page 11 */
3433 static int
dissect_nfs2_readdir_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3434 dissect_nfs2_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
3435 			   proto_tree *tree, void *data _U_)
3436 {
3437 	guint32	    status;
3438 	guint32	    eof_value;
3439 	const char *err;
3440 	int offset = 0;
3441 
3442 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
3443 	switch (status) {
3444 		case 0:
3445 			proto_item_append_text(tree, ", READDIR Reply");
3446 
3447 			offset = dissect_rpc_list(tvb, pinfo, tree, offset,
3448 				dissect_readdir_entry, NULL);
3449 			proto_tree_add_item_ret_uint(tree, hf_nfs_readdir_eof, tvb,
3450 					offset, 4, ENC_BIG_ENDIAN, &eof_value);
3451 			offset += 4;
3452 		break;
3453 		default:
3454 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
3455 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
3456 			proto_item_append_text(tree, ", READDIR Reply  Error: %s", err);
3457 		break;
3458 	}
3459 
3460 	return offset;
3461 }
3462 
3463 
3464 /* NFSv2 RFC 1094, Page 12 */
3465 static int
dissect_nfs2_statfs_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3466 dissect_nfs2_statfs_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
3467 			  proto_tree *tree, void *data _U_)
3468 {
3469 	guint32	    status;
3470 	const char *err;
3471 	int offset = 0;
3472 
3473 	offset = dissect_nfs2_status(tvb, offset, tree, &status);
3474 	switch (status) {
3475 		case 0:
3476 			proto_tree_add_item(tree, hf_nfs2_statfs_tsize, tvb, offset+ 0, 4, ENC_BIG_ENDIAN);
3477 			proto_tree_add_item(tree, hf_nfs2_statfs_bsize, tvb, offset+ 4, 4, ENC_BIG_ENDIAN);
3478 			proto_tree_add_item(tree, hf_nfs2_statfs_blocks, tvb, offset+ 8, 4, ENC_BIG_ENDIAN);
3479 			proto_tree_add_item(tree, hf_nfs2_statfs_bfree, tvb, offset+12, 4, ENC_BIG_ENDIAN);
3480 			proto_tree_add_item(tree, hf_nfs2_statfs_bavail, tvb, offset+16, 4, ENC_BIG_ENDIAN);
3481 			offset += 20;
3482 			proto_item_append_text(tree, ", STATFS Reply");
3483 		break;
3484 		default:
3485 			err = val_to_str_ext(status, &names_nfs2_stat_ext, "Unknown error: %u");
3486 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
3487 			proto_item_append_text(tree, ", STATFS Reply  Error: %s", err);
3488 		break;
3489 	}
3490 
3491 	return offset;
3492 }
3493 
3494 
3495 /* proc number, "proc name", dissect_request, dissect_reply */
3496 static const vsff nfs2_proc[] = {
3497 	{ 0,	"NULL",		/* OK */
3498 	dissect_rpc_void,		dissect_rpc_void },
3499 	{ 1,	"GETATTR",	/* OK */
3500 	dissect_nfs2_getattr_call,	dissect_nfs2_getattr_reply },
3501 	{ 2,	"SETATTR",	/* OK */
3502 	dissect_nfs2_setattr_call,	dissect_nfs2_setattr_reply },
3503 	{ 3,	"ROOT",		/* OK */
3504 	dissect_rpc_void,		dissect_rpc_void },
3505 	{ 4,	"LOOKUP",	/* OK */
3506 	dissect_nfs2_lookup_call,	dissect_nfs2_lookup_reply },
3507 	{ 5,	"READLINK",	/* OK */
3508 	dissect_nfs2_readlink_call,	dissect_nfs2_readlink_reply },
3509 	{ 6,	"READ",		/* OK */
3510 	dissect_nfs2_read_call,		dissect_nfs2_read_reply },
3511 	{ 7,	"WRITECACHE",	/* OK */
3512 	dissect_rpc_void,		dissect_rpc_void },
3513 	{ 8,	"WRITE",	/* OK */
3514 	dissect_nfs2_write_call,	dissect_nfs2_write_reply },
3515 	{ 9,	"CREATE",	/* OK */
3516 	dissect_nfs2_create_call,	dissect_nfs2_create_reply },
3517 	{ 10,	"REMOVE",	/* OK */
3518 	dissect_nfs2_remove_call,	dissect_nfs2_remove_reply },
3519 	{ 11,	"RENAME",	/* OK */
3520 	dissect_nfs2_rename_call,	dissect_nfs2_rename_reply },
3521 	{ 12,	"LINK",		/* OK */
3522 	dissect_nfs2_link_call,		dissect_nfs2_link_reply },
3523 	{ 13,	"SYMLINK",	/* OK */
3524 	dissect_nfs2_symlink_call,	dissect_nfs2_symlink_reply },
3525 	{ 14,	"MKDIR",	/* OK */
3526 	dissect_nfs2_mkdir_call,	dissect_nfs2_mkdir_reply },
3527 	{ 15,	"RMDIR",	/* OK */
3528 	dissect_nfs2_rmdir_call,	dissect_nfs2_rmdir_reply },
3529 	{ 16,	"READDIR",	/* OK */
3530 	dissect_nfs2_readdir_call,	dissect_nfs2_readdir_reply },
3531 	{ 17,	"STATFS",	/* OK */
3532 	dissect_nfs2_statfs_call,	dissect_nfs2_statfs_reply },
3533 	{ 0,	NULL,	NULL,	NULL }
3534 };
3535 
3536 static const value_string nfs2_proc_vals[] = {
3537 	{ 0,	"NULL" },
3538 	{ 1,	"GETATTR" },
3539 	{ 2,	"SETATTR" },
3540 	{ 3,	"ROOT" },
3541 	{ 4,	"LOOKUP" },
3542 	{ 5,	"READLINK" },
3543 	{ 6,	"READ" },
3544 	{ 7,	"WRITECACHE" },
3545 	{ 8,	"WRITE" },
3546 	{ 9,	"CREATE" },
3547 	{ 10,	"REMOVE" },
3548 	{ 11,	"RENAME" },
3549 	{ 12,	"LINK" },
3550 	{ 13,	"SYMLINK" },
3551 	{ 14,	"MKDIR" },
3552 	{ 15,	"RMDIR" },
3553 	{ 16,	"READDIR" },
3554 	{ 17,	"STATFS" },
3555 	{ 0,	NULL }
3556 };
3557 static value_string_ext nfs2_proc_vals_ext = VALUE_STRING_EXT_INIT(nfs2_proc_vals);
3558 
3559 /* end of NFS Version 2 */
3560 
3561 
3562 /***************************/
3563 /* NFS Version 3, RFC 1813 */
3564 /***************************/
3565 
3566 /* NFSv3 RFC 1813, Page 15 */
3567 static int
dissect_nfs3_filename(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** string_ret)3568 dissect_nfs3_filename(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, const char **string_ret)
3569 {
3570 	offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
3571 	return offset;
3572 }
3573 
3574 
3575 /* NFSv3 RFC 1813, Page 15 */
3576 static int
dissect_nfs3_path(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** name)3577 dissect_nfs3_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, const char **name)
3578 {
3579 	offset = dissect_rpc_string(tvb, tree, hf, offset, name);
3580 	return offset;
3581 }
3582 
3583 
3584 /* NFSv3 RFC 1813, Page 15 */
3585 static int
dissect_nfs3_cookie_verf(tvbuff_t * tvb,int offset,proto_tree * tree)3586 dissect_nfs3_cookie_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
3587 {
3588 	proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_COOKIEVERFSIZE, NULL, "Opaque Data");
3589 	offset += NFS3_COOKIEVERFSIZE;
3590 	return offset;
3591 }
3592 
3593 
3594 /* NFSv3 RFC 1813, Page 16 */
3595 static int
dissect_nfs3_create_verf(tvbuff_t * tvb,int offset,proto_tree * tree)3596 dissect_nfs3_create_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
3597 {
3598 	proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_CREATEVERFSIZE, NULL, "Opaque Data");
3599 	offset += NFS3_CREATEVERFSIZE;
3600 	return offset;
3601 }
3602 
3603 
3604 /* NFSv3 RFC 1813, Page 16 */
3605 static int
dissect_nfs3_write_verf(tvbuff_t * tvb,int offset,proto_tree * tree)3606 dissect_nfs3_write_verf(tvbuff_t *tvb, int offset, proto_tree *tree)
3607 {
3608 	proto_tree_add_bytes_format_value(tree, hf_nfs3_verifier, tvb, offset, NFS3_WRITEVERFSIZE, NULL, "Opaque Data");
3609 	offset += NFS3_WRITEVERFSIZE;
3610 	return offset;
3611 }
3612 
3613 
3614 /* RFC 1813, Page 16 */
3615 static int
dissect_nfs3_mode(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * mode)3616 dissect_nfs3_mode(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *mode)
3617 {
3618 	static int * const mode_bits[] = {
3619 		&hf_nfs3_mode_suid,
3620 		&hf_nfs3_mode_sgid,
3621 		&hf_nfs3_mode_sticky,
3622 		&hf_nfs3_mode_rusr,
3623 		&hf_nfs3_mode_wusr,
3624 		&hf_nfs3_mode_xusr,
3625 		&hf_nfs3_mode_rgrp,
3626 		&hf_nfs3_mode_wgrp,
3627 		&hf_nfs3_mode_xgrp,
3628 		&hf_nfs3_mode_roth,
3629 		&hf_nfs3_mode_woth,
3630 		&hf_nfs3_mode_xoth,
3631 		NULL
3632 	};
3633 
3634 
3635 	if (mode) {
3636 		*mode = tvb_get_ntohl(tvb, offset+0);
3637 	}
3638 
3639 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs3_mode, ett_nfs3_mode, mode_bits, ENC_BIG_ENDIAN);
3640 
3641 	offset += 4;
3642 	return offset;
3643 }
3644 
3645 
3646 /* NFSv3 RFC 1813, Page 16,17 */
3647 static const value_string names_nfs_nfsstat3[] =
3648 {
3649 	{	0,	"NFS3_OK" },
3650 	{	1,	"NFS3ERR_PERM" },
3651 	{	2,	"NFS3ERR_NOENT" },
3652 	{	5,	"NFS3ERR_IO" },
3653 	{	6,	"NFS3ERR_NXIO" },
3654 	{	13,	"NFS3ERR_ACCES" },
3655 	{	17,	"NFS3ERR_EXIST" },
3656 	{	18,	"NFS3ERR_XDEV" },
3657 	{	19,	"NFS3ERR_NODEV" },
3658 	{	20,	"NFS3ERR_NOTDIR" },
3659 	{	21,	"NFS3ERR_ISDIR" },
3660 	{	22,	"NFS3ERR_INVAL" },
3661 	{	27,	"NFS3ERR_FBIG" },
3662 	{	28,	"NFS3ERR_NOSPC" },
3663 	{	30,	"NFS3ERR_ROFS" },
3664 	{	31,	"NFS3ERR_MLINK" },
3665 	{	63,	"NFS3ERR_NAMETOOLONG" },
3666 	{	66,	"NFS3ERR_NOTEMPTY" },
3667 	{	69,	"NFS3ERR_DQUOT" },
3668 	{	70,	"NFS3ERR_STALE" },
3669 	{	71,	"NFS3ERR_REMOTE" },
3670 	{	10001,	"NFS3ERR_BADHANDLE" },
3671 	{	10002,	"NFS3ERR_NOT_SYNC" },
3672 	{	10003,	"NFS3ERR_BAD_COOKIE" },
3673 	{	10004,	"NFS3ERR_NOTSUPP" },
3674 	{	10005,	"NFS3ERR_TOOSMALL" },
3675 	{	10006,	"NFS3ERR_SERVERFAULT" },
3676 	{	10007,	"NFS3ERR_BADTYPE" },
3677 	{	10008,	"NFS3ERR_JUKEBOX" },
3678 	{	0,	NULL }
3679 };
3680 static value_string_ext names_nfs3_status_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat3);
3681 
3682 /* NFSv3 RFC 1813, Page 16 */
3683 static int
dissect_nfs3_status(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * status)3684 dissect_nfs3_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status)
3685 {
3686 	guint32	    nfsstat3;
3687 
3688 	nfsstat3 = tvb_get_ntohl(tvb, offset+0);
3689 
3690 	if (tree) {
3691 		proto_item *stat_item;
3692 		proto_tree_add_uint(tree, hf_nfs3_status, tvb, offset+0, 4, nfsstat3);
3693 		stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, nfsstat3);
3694 		proto_item_set_hidden(stat_item);
3695 	}
3696 
3697 	offset += 4;
3698 	*status = nfsstat3;
3699 	return offset;
3700 }
3701 
3702 
3703 static const value_string names_nfs_ftype3[] =
3704 {
3705 	{	NF3REG,	 "Regular File" },
3706 	{	NF3DIR,	 "Directory" },
3707 	{	NF3BLK,	 "Block Special Device" },
3708 	{	NF3CHR,	 "Character Special Device" },
3709 	{	NF3LNK,	 "Symbolic Link" },
3710 	{	NF3SOCK, "Socket" },
3711 	{	NF3FIFO, "Named Pipe" },
3712 	{	0,	NULL }
3713 };
3714 static value_string_ext names_nfs_ftype3_ext = VALUE_STRING_EXT_INIT(names_nfs_ftype3);
3715 
3716 /* NFSv3 RFC 1813, Page 20 */
3717 static int
dissect_ftype3(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,guint32 * ftype3)3718 dissect_ftype3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf,
3719 	       guint32* ftype3)
3720 {
3721 	guint32 type;
3722 
3723 	proto_tree_add_item_ret_uint(tree, hf, tvb, offset, 4, ENC_BIG_ENDIAN, &type);
3724 
3725 	offset += 4;
3726 	*ftype3 = type;
3727 	return offset;
3728 }
3729 
3730 
3731 /* NFSv3 RFC 1813, Page 20 */
3732 static int
dissect_nfs3_specdata(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3733 dissect_nfs3_specdata(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
3734 {
3735 	guint32	    specdata1;
3736 	guint32	    specdata2;
3737 
3738 	specdata1 = tvb_get_ntohl(tvb, offset+0);
3739 	specdata2 = tvb_get_ntohl(tvb, offset+4);
3740 
3741 	if (tree) {
3742 		proto_tree *specdata3_tree;
3743 
3744 		specdata3_tree = proto_tree_add_subtree_format(tree, tvb, offset, 8,
3745 			ett_nfs3_specdata, NULL, "%s: %u,%u", name, specdata1, specdata2);
3746 
3747 		proto_tree_add_uint(specdata3_tree, hf_nfs3_specdata1, tvb, offset+0, 4, specdata1);
3748 		proto_tree_add_uint(specdata3_tree, hf_nfs3_specdata2, tvb, offset+4, 4, specdata2);
3749 	}
3750 
3751 	offset += 8;
3752 	return offset;
3753 }
3754 
3755 
3756 /* NFSv3 RFC 1813, Page 21 */
3757 int
dissect_nfs3_fh(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name,guint32 * hash,rpc_call_info_value * civ)3758 dissect_nfs3_fh(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
3759 		const char *name, guint32 *hash, rpc_call_info_value *civ)
3760 {
3761 	guint	    fh3_len;
3762 	guint	    fh3_len_full;
3763 	/*guint       fh3_fill;*/
3764 	proto_tree *ftree;
3765 	int	    fh_offset, fh_length;
3766 
3767 	fh3_len = tvb_get_ntohl(tvb, offset+0);
3768 	fh3_len_full = rpc_roundup(fh3_len);
3769 	/*fh3_fill = fh3_len_full - fh3_len;*/
3770 
3771 	ftree = proto_tree_add_subtree(tree, tvb, offset, 4+fh3_len_full,
3772 			ett_nfs3_fh, NULL, name);
3773 
3774 	/* are we snooping fh to filenames ?*/
3775 	if ((!pinfo->fd->visited) && nfs_file_name_snooping) {
3776 		/* NFS v3 LOOKUP, CREATE, MKDIR, READDIRPLUS
3777 			calls might give us a mapping*/
3778 		if ( ((civ->prog == 100003)
3779 		  &&((civ->vers == 3)
3780 		  &&(!civ->request)
3781 		  &&((civ->proc == 3)||(civ->proc == 8)||(civ->proc == 9)||(civ->proc == 17))))
3782 		|| civ->vers == 4
3783 		) {
3784 			fh_length = tvb_get_ntohl(tvb, offset);
3785 			fh_offset = offset+4;
3786 			nfs_name_snoop_add_fh(civ->xid, tvb, fh_offset,
3787 					      fh_length);
3788 		}
3789 
3790 		/* MOUNT v3 MNT replies might give us a filehandle */
3791 		if ( (civ->prog == 100005)
3792 		  &&(civ->vers == 3)
3793 		  &&(!civ->request)
3794 		  &&(civ->proc == 1)
3795 		) {
3796 			fh_length = tvb_get_ntohl(tvb, offset);
3797 			fh_offset = offset+4;
3798 			nfs_name_snoop_add_fh(civ->xid, tvb, fh_offset,
3799 					      fh_length);
3800 		}
3801 	}
3802 
3803 	proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4,
3804 			fh3_len);
3805 
3806 	/* Handle WebNFS requests where filehandle may be 0 length */
3807 	if (fh3_len > 0)
3808 	{
3809 		dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE, hash);
3810 
3811 		offset += fh3_len_full;
3812 	}
3813 	else if (hash) {
3814 		/* Make sure hash is set regardless, as our caller expects it
3815 		 * to be initialized */
3816 		*hash = 0;
3817 	}
3818 
3819 	offset += 4;
3820 
3821 	return offset;
3822 }
3823 
3824 
3825 /* NFSv3 RFC 1813, Page 21 */
3826 static int
dissect_nfstime3(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_time,int hf_time_sec,int hf_time_nsec)3827 dissect_nfstime3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time,
3828 		 int hf_time_sec, int hf_time_nsec)
3829 {
3830 	guint32	 seconds;
3831 	guint32	 nseconds;
3832 	nstime_t ts;
3833 
3834 	seconds = tvb_get_ntohl(tvb, offset+0);
3835 	nseconds = tvb_get_ntohl(tvb, offset+4);
3836 	ts.secs = seconds;
3837 	ts.nsecs = nseconds;
3838 
3839 	if (tree) {
3840 		proto_item *time_item;
3841 		proto_tree *time_tree;
3842 
3843 		time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
3844 				&ts);
3845 
3846 		time_tree = proto_item_add_subtree(time_item, ett_nfs3_nfstime);
3847 
3848 		proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
3849 					seconds);
3850 		proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset+4, 4,
3851 					nseconds);
3852 	}
3853 	offset += 8;
3854 	return offset;
3855 }
3856 
3857 
3858 /* NFSv3 RFC 1813, Page 22
3859  * The levels parameter tells this helper how many levels up in the tree it
3860  * should display useful info such as type,mode,uid,gid
3861  * If level has the COL_INFO_LEVEL flag set it will also display
3862  * this info in the info column.
3863  */
3864 static int
dissect_nfs_fattr3(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * tree,const char * name,guint32 levels)3865 dissect_nfs_fattr3(packet_info *pinfo, tvbuff_t *tvb, int offset,
3866 		   proto_tree *tree, const char *name, guint32 levels)
3867 {
3868 	proto_item *fattr3_item = NULL;
3869 	proto_tree *fattr3_tree = NULL;
3870 	int	    old_offset	= offset;
3871 	guint32	    type, mode, uid, gid;
3872 
3873 	fattr3_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
3874 			ett_nfs3_fattr, &fattr3_item, name);
3875 
3876 	/* ftype */
3877 	offset = dissect_ftype3(tvb, offset, fattr3_tree, hf_nfs3_fattr_type, &type);
3878 
3879 	/* mode */
3880 	offset = dissect_nfs3_mode(tvb, offset, fattr3_tree, &mode);
3881 
3882 	/* nlink */
3883 	offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs3_fattr_nlink,
3884 		offset);
3885 
3886 	/* uid */
3887 	uid = tvb_get_ntohl(tvb, offset);
3888 	offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs3_fattr_uid,
3889 		offset);
3890 
3891 	/* gid */
3892 	gid = tvb_get_ntohl(tvb, offset);
3893 	offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs3_fattr_gid,
3894 		offset);
3895 
3896 	/* size*/
3897 	offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs3_fattr_size,
3898 		offset);
3899 
3900 	/* used */
3901 	offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs3_fattr_used,
3902 		offset);
3903 
3904 	/* rdev */
3905 	offset = dissect_nfs3_specdata(tvb, offset, fattr3_tree, "rdev");
3906 
3907 	/* fsid */
3908 	offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs3_fattr_fsid,
3909 		offset);
3910 
3911 	/* fileid */
3912 	offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs3_fattr_fileid,
3913 		offset);
3914 
3915 	/* atime */
3916 	offset = dissect_nfstime3 (tvb, offset, fattr3_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
3917 
3918 	/* mtime */
3919 	offset = dissect_nfstime3 (tvb, offset, fattr3_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_nsec);
3920 
3921 	/* ctime */
3922 	offset = dissect_nfstime3 (tvb, offset, fattr3_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
3923 
3924 	/* now we know, that fattr3 is shorter */
3925 	proto_item_set_len(fattr3_item, offset - old_offset);
3926 
3927 	/* put some nice info in COL_INFO for GETATTR replies */
3928 	if (levels & COL_INFO_LEVEL) {
3929 		levels &= (~COL_INFO_LEVEL);
3930 		col_append_fstr(pinfo->cinfo, COL_INFO,
3931 				"  %s mode: %04o uid: %d gid: %d",
3932 				val_to_str_ext(type, &names_nfs_ftype3_ext, "Unknown Type: 0x%x"),
3933 				mode&0x0fff, uid, gid);
3934 	}
3935 	/* populate the expansion lines with some nice useable info */
3936 	while ( fattr3_tree && levels-- ) {
3937 		proto_item_append_text(fattr3_tree, "  %s mode: %04o uid: %d gid: %d",
3938 				val_to_str_ext(type, &names_nfs_ftype3_ext, "Unknown Type: 0x%x"),
3939 				mode&0x0fff, uid, gid);
3940 		fattr3_tree = fattr3_tree->parent;
3941 	}
3942 
3943 	return offset;
3944 }
3945 
3946 
3947 static const value_string value_follows[] =
3948 {
3949 	{ 0, "no value" },
3950 	{ 1, "value follows" },
3951 	{ 0, NULL }
3952 };
3953 
3954 
3955 /* NFSv3 RFC 1813, Page 23 */
3956 int
dissect_nfs3_post_op_attr(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name)3957 dissect_nfs3_post_op_attr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
3958 			 const char *name)
3959 {
3960 	proto_item *post_op_attr_item;
3961 	proto_tree *post_op_attr_tree;
3962 	int	    old_offset	      = offset;
3963 	guint32	    attributes_follow = 0;
3964 
3965 	attributes_follow = tvb_get_ntohl(tvb, offset+0);
3966 
3967 	post_op_attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
3968 			ett_nfs3_post_op_attr, &post_op_attr_item, name);
3969 
3970 	proto_tree_add_uint(post_op_attr_tree, hf_nfs3_attributes_follow, tvb, offset, 4, attributes_follow);
3971 
3972 	offset += 4;
3973 	switch (attributes_follow) {
3974 		case TRUE:
3975 			offset = dissect_nfs_fattr3(pinfo, tvb, offset,
3976 						    post_op_attr_tree,
3977 						    "attributes", 2);
3978 		break;
3979 		case FALSE:
3980 			/* void */
3981 		break;
3982 	}
3983 
3984 	/* now we know, that post_op_attr_tree is shorter */
3985 	proto_item_set_len(post_op_attr_item, offset - old_offset);
3986 
3987 	return offset;
3988 }
3989 
3990 
3991 /* NFSv3 RFC 1813, Page 24 */
3992 static int
dissect_wcc_attr(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)3993 dissect_wcc_attr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
3994 {
3995 	proto_item *wcc_attr_item;
3996 	proto_tree *wcc_attr_tree;
3997 	int	    old_offset	  = offset;
3998 
3999 	wcc_attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4000 			ett_nfs3_wcc_attr, &wcc_attr_item, name);
4001 
4002 	offset = dissect_rpc_uint64(tvb, wcc_attr_tree, hf_nfs3_wcc_attr_size,
4003 		offset);
4004 	offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_mtime,
4005 		hf_nfs_mtime_sec, hf_nfs_mtime_nsec);
4006 	offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_ctime,
4007 		hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
4008 	/* now we know, that wcc_attr_tree is shorter */
4009 	proto_item_set_len(wcc_attr_item, offset - old_offset);
4010 
4011 	return offset;
4012 }
4013 
4014 
4015 /* NFSv3 RFC 1813, Page 24 */
4016 static int
dissect_pre_op_attr(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4017 dissect_pre_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4018 {
4019 	proto_item *pre_op_attr_item;
4020 	proto_tree *pre_op_attr_tree;
4021 	int	    old_offset	     = offset;
4022 	guint32	    attributes_follow;
4023 
4024 	pre_op_attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4025 			ett_nfs3_pre_op_attr, &pre_op_attr_item, name);
4026 
4027 	proto_tree_add_item_ret_uint(pre_op_attr_tree, hf_nfs3_attributes_follow, tvb, offset, 4, ENC_BIG_ENDIAN, &attributes_follow);
4028 	offset += 4;
4029 	switch (attributes_follow) {
4030 		case TRUE:
4031 			offset = dissect_wcc_attr(tvb, offset, pre_op_attr_tree,
4032 					"attributes");
4033 		break;
4034 		case FALSE:
4035 			/* void */
4036 		break;
4037 	}
4038 
4039 	/* now we know, that pre_op_attr_tree is shorter */
4040 	proto_item_set_len(pre_op_attr_item, offset - old_offset);
4041 
4042 	return offset;
4043 }
4044 
4045 
4046 /* NFSv3 RFC 1813, Page 24 */
4047 static int
dissect_wcc_data(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name)4048 dissect_wcc_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, const char *name)
4049 {
4050 	proto_item *wcc_data_item;
4051 	proto_tree *wcc_data_tree;
4052 	int	    old_offset	  = offset;
4053 
4054 	wcc_data_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4055 			ett_nfs3_wcc_data, &wcc_data_item, name);
4056 
4057 	offset = dissect_pre_op_attr (tvb, offset, wcc_data_tree, "before");
4058 	offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, wcc_data_tree, "after" );
4059 
4060 	/* now we know, that wcc_data is shorter */
4061 	proto_item_set_len(wcc_data_item, offset - old_offset);
4062 
4063 	return offset;
4064 }
4065 
4066 
4067 /* NFSv3 RFC 1813, Page 25 */
4068 static int
dissect_nfs3_post_op_fh(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name,rpc_call_info_value * civ)4069 dissect_nfs3_post_op_fh(tvbuff_t *tvb, int offset, packet_info *pinfo,
4070 		    proto_tree *tree, const char *name, rpc_call_info_value *civ)
4071 {
4072 	proto_item *post_op_fh3_item;
4073 	proto_tree *post_op_fh3_tree;
4074 	int	    old_offset	     = offset;
4075 	guint32	    handle_follows;
4076 
4077 	post_op_fh3_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4078 			ett_nfs3_post_op_fh, &post_op_fh3_item, name);
4079 
4080 	proto_tree_add_item_ret_uint(post_op_fh3_tree, hf_nfs3_handle_follow, tvb, offset, 4, ENC_BIG_ENDIAN, &handle_follows);
4081 	offset += 4;
4082 	switch (handle_follows) {
4083 		case TRUE:
4084 			offset = dissect_nfs3_fh(tvb, offset, pinfo, post_op_fh3_tree,
4085 					"handle", NULL, civ);
4086 		break;
4087 		case FALSE:
4088 			/* void */
4089 		break;
4090 	}
4091 
4092 	/* now we know, that post_op_fh3_tree is shorter */
4093 	if (post_op_fh3_item) {
4094 		proto_item_set_len(post_op_fh3_item, offset - old_offset);
4095 	}
4096 
4097 	return offset;
4098 }
4099 
4100 
4101 /* NFSv3 RFC 1813, Page 25 */
4102 static int
dissect_set_mode3(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4103 dissect_set_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4104 {
4105 	proto_item *set_mode3_item;
4106 	proto_tree *set_mode3_tree;
4107 	int	    old_offset	   = offset;
4108 	guint32	    set_it;
4109 	const char *set_it_name;
4110 
4111 	set_it = tvb_get_ntohl(tvb, offset+0);
4112 
4113 	set_it_name = val_to_str_const(set_it, value_follows, "Unknown");
4114 
4115 	set_mode3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4116 			ett_nfs3_set_mode, &set_mode3_item, "%s: %s", name, set_it_name);
4117 
4118 	proto_tree_add_uint(set_mode3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
4119 
4120 	offset += 4;
4121 
4122 	switch (set_it) {
4123 		case 1:
4124 			offset = dissect_nfs3_mode(tvb, offset, set_mode3_tree, NULL);
4125 		break;
4126 		default:
4127 			/* void */
4128 		break;
4129 	}
4130 
4131 	/* now we know, that set_mode3 is shorter */
4132 	proto_item_set_len(set_mode3_item, offset - old_offset);
4133 
4134 	return offset;
4135 }
4136 
4137 
4138 /* NFSv3 RFC 1813, Page 26 */
4139 static int
dissect_set_uid3(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4140 dissect_set_uid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4141 {
4142 	proto_item *set_uid3_item;
4143 	proto_tree *set_uid3_tree;
4144 	int	    old_offset	  = offset;
4145 	guint32	    set_it;
4146 	const char *set_it_name;
4147 
4148 	set_it = tvb_get_ntohl(tvb, offset+0);
4149 	set_it_name = val_to_str_const(set_it, value_follows, "Unknown");
4150 
4151 	set_uid3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4152 			ett_nfs3_set_uid, &set_uid3_item, "%s: %s", name, set_it_name);
4153 
4154 	proto_tree_add_uint(set_uid3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
4155 	offset += 4;
4156 
4157 	switch (set_it) {
4158 		case 1:
4159 			offset = dissect_rpc_uint32(tvb, set_uid3_tree,
4160 						    hf_nfs3_uid, offset);
4161 		break;
4162 		default:
4163 			/* void */
4164 		break;
4165 	}
4166 
4167 	/* now we know, that set_uid3 is shorter */
4168 	proto_item_set_len(set_uid3_item, offset - old_offset);
4169 
4170 	return offset;
4171 }
4172 
4173 
4174 /* NFSv3 RFC 1813, Page 26 */
4175 static int
dissect_set_gid3(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4176 dissect_set_gid3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4177 {
4178 	proto_item *set_gid3_item;
4179 	proto_tree *set_gid3_tree;
4180 	int	    old_offset	  = offset;
4181 	guint32	    set_it;
4182 	const char *set_it_name;
4183 
4184 	set_it = tvb_get_ntohl(tvb, offset+0);
4185 
4186 	set_it_name = val_to_str_const(set_it, value_follows, "Unknown");
4187 	set_gid3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4188 			ett_nfs3_set_gid, &set_gid3_item, "%s: %s", name, set_it_name);
4189 
4190 	proto_tree_add_uint(set_gid3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
4191 
4192 	offset += 4;
4193 
4194 	switch (set_it) {
4195 		case 1:
4196 			offset = dissect_rpc_uint32(tvb, set_gid3_tree,
4197 				hf_nfs3_gid, offset);
4198 		break;
4199 		default:
4200 			/* void */
4201 		break;
4202 	}
4203 
4204 	/* now we know, that set_gid3 is shorter */
4205 	proto_item_set_len(set_gid3_item, offset - old_offset);
4206 
4207 	return offset;
4208 }
4209 
4210 
4211 /* NFSv3 RFC 1813, Page 26 */
4212 static int
dissect_set_size3(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4213 dissect_set_size3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4214 {
4215 	proto_item *set_size3_item;
4216 	proto_tree *set_size3_tree;
4217 	int	    old_offset	   = offset;
4218 	guint32	    set_it;
4219 	const char *set_it_name;
4220 
4221 	set_it = tvb_get_ntohl(tvb, offset+0);
4222 
4223 	set_it_name = val_to_str_const(set_it, value_follows, "Unknown");
4224 
4225 	set_size3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4226 			ett_nfs3_set_size, &set_size3_item, "%s: %s", name, set_it_name);
4227 	proto_tree_add_uint(set_size3_tree, hf_nfs4_set_it_value_follows, tvb, offset, 4, set_it);
4228 
4229 	offset += 4;
4230 
4231 	switch (set_it) {
4232 		case 1:
4233 			offset = dissect_rpc_uint64(tvb, set_size3_tree,
4234 				hf_nfs3_set_size, offset);
4235 		break;
4236 		default:
4237 			/* void */
4238 		break;
4239 	}
4240 
4241 	/* now we know, that set_size3 is shorter */
4242 	proto_item_set_len(set_size3_item, offset - old_offset);
4243 
4244 	return offset;
4245 }
4246 
4247 
4248 /* NFSv3 RFC 1813, Page 25 */
4249 #define DONT_CHANGE 0
4250 #define SET_TO_SERVER_TIME 1
4251 #define SET_TO_CLIENT_TIME 2
4252 
4253 static const value_string time_how[] =
4254 {
4255 	{ DONT_CHANGE,		"don't change" },
4256 	{ SET_TO_SERVER_TIME,	"set to server time" },
4257 	{ SET_TO_CLIENT_TIME,	"set to client time" },
4258 	{ 0, NULL }
4259 };
4260 
4261 
4262 /* NFSv3 RFC 1813, Page 26 */
4263 static int
dissect_set_atime(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4264 dissect_set_atime(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4265 {
4266 	proto_item *set_atime_item;
4267 	proto_tree *set_atime_tree;
4268 	int	    old_offset	   = offset;
4269 	guint32	    set_it;
4270 	const char *set_it_name;
4271 
4272 	set_it = tvb_get_ntohl(tvb, offset+0);
4273 
4274 	set_it_name = val_to_str_const(set_it, time_how, "Unknown");
4275 
4276 	set_atime_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4277 			ett_nfs3_set_atime, &set_atime_item, "%s: %s", name, set_it_name);
4278 
4279 	proto_tree_add_uint(set_atime_tree, hf_nfs4_time_how, tvb, offset, 4, set_it);
4280 	offset += 4;
4281 
4282 	switch (set_it) {
4283 		case SET_TO_CLIENT_TIME:
4284 			offset = dissect_nfstime3(tvb, offset, set_atime_tree,
4285 					hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
4286 		break;
4287 		default:
4288 			/* void */
4289 		break;
4290 	}
4291 
4292 	/* now we know, that set_atime is shorter */
4293 	proto_item_set_len(set_atime_item, offset - old_offset);
4294 
4295 	return offset;
4296 }
4297 
4298 
4299 /* NFSv3 RFC 1813, Page 26 */
4300 static int
dissect_set_mtime(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4301 dissect_set_mtime(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4302 {
4303 	proto_item *set_mtime_item;
4304 	proto_tree *set_mtime_tree;
4305 	int	    old_offset	   = offset;
4306 	guint32	    set_it;
4307 	const char *set_it_name;
4308 
4309 	set_it = tvb_get_ntohl(tvb, offset+0);
4310 
4311 	set_it_name = val_to_str_const(set_it, time_how, "Unknown");
4312 
4313 	set_mtime_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4314 			ett_nfs3_set_mtime, &set_mtime_item, "%s: %s", name, set_it_name);
4315 	proto_tree_add_uint(set_mtime_tree, hf_nfs4_time_how, tvb, offset, 4, set_it);
4316 
4317 	offset += 4;
4318 
4319 	switch (set_it) {
4320 		case SET_TO_CLIENT_TIME:
4321 			offset = dissect_nfstime3(tvb, offset, set_mtime_tree,
4322 					hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
4323 		break;
4324 		default:
4325 			/* void */
4326 		break;
4327 	}
4328 
4329 	/* now we know, that set_mtime is shorter */
4330 	proto_item_set_len(set_mtime_item, offset - old_offset);
4331 
4332 	return offset;
4333 }
4334 
4335 
4336 /* NFSv3 RFC 1813, Page 25..27 */
4337 static int
dissect_nfs3_sattr(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4338 dissect_nfs3_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4339 {
4340 	proto_item *sattr3_item;
4341 	proto_tree *sattr3_tree;
4342 	int	    old_offset	= offset;
4343 
4344 	sattr3_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4345 			ett_nfs3_sattr, &sattr3_item, name);
4346 
4347 	offset = dissect_set_mode3(tvb, offset, sattr3_tree, "mode");
4348 	offset = dissect_set_uid3 (tvb, offset, sattr3_tree, "uid");
4349 	offset = dissect_set_gid3 (tvb, offset, sattr3_tree, "gid");
4350 	offset = dissect_set_size3(tvb, offset, sattr3_tree, "size");
4351 	offset = dissect_set_atime(tvb, offset, sattr3_tree, "atime");
4352 	offset = dissect_set_mtime(tvb, offset, sattr3_tree, "mtime");
4353 
4354 	/* now we know, that sattr3 is shorter */
4355 	proto_item_set_len(sattr3_item, offset - old_offset);
4356 
4357 	return offset;
4358 }
4359 
4360 
4361 /* NFSv3 RFC 1813, Page 27 */
4362 static int
dissect_diropargs3(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * label,guint32 * hash,const char ** name,rpc_call_info_value * civ)4363 dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
4364 				   const char *label, guint32 *hash, const char **name, rpc_call_info_value *civ)
4365 {
4366 	proto_item *diropargs3_item;
4367 	proto_tree *diropargs3_tree;
4368 	int	    old_offset	    = offset;
4369 	int	    parent_offset, parent_len;
4370 	int	    name_offset, name_len;
4371 
4372 	diropargs3_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
4373 			ett_nfs3_diropargs, &diropargs3_item, label);
4374 
4375 	parent_offset = offset+4;
4376 	parent_len = tvb_get_ntohl(tvb, offset);
4377 	offset = dissect_nfs3_fh(tvb, offset, pinfo, diropargs3_tree, "dir", hash, civ);
4378 	name_offset = offset+4;
4379 	name_len = tvb_get_ntohl(tvb, offset);
4380 	offset = dissect_nfs3_filename(tvb, offset, diropargs3_tree,
4381 		hf_nfs_name, name);
4382 
4383 	/* are we snooping fh to filenames ?*/
4384 	if ((!pinfo->fd->visited) && nfs_file_name_snooping) {
4385 		/* v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
4386 		if ( (civ->prog == 100003)
4387 		  &&(civ->vers == 3)
4388 		  &&(civ->request)
4389 		  &&((civ->proc == 3)||(civ->proc == 8)||(civ->proc == 9))
4390 		) {
4391 			nfs_name_snoop_add_name(civ->xid, tvb,
4392 				name_offset, name_len,
4393 				parent_offset, parent_len, NULL);
4394 		}
4395 	}
4396 
4397 
4398 	/* now we know, that diropargs3 is shorter */
4399 	proto_item_set_len(diropargs3_item, offset - old_offset);
4400 
4401 	return offset;
4402 }
4403 
4404 
4405 static int
dissect_nfs3_remove_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4406 dissect_nfs3_remove_call(tvbuff_t *tvb, packet_info *pinfo,
4407 			 proto_tree *tree, void *data)
4408 {
4409 	guint32	    hash = 0;
4410 	const char *name = NULL;
4411 	int offset = 0;
4412 
4413 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
4414 
4415 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
4416 	proto_item_append_text(tree, ", REMOVE Call DH: 0x%08x/%s", hash, name);
4417 
4418 	return offset;
4419 }
4420 
4421 
4422 static int
dissect_nfs3_null_call(tvbuff_t * tvb _U_,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4423 dissect_nfs3_null_call(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
4424 		       proto_tree *tree, void *data _U_)
4425 {
4426 	proto_item_append_text(tree, ", NULL Call");
4427 
4428 	return 0;
4429 }
4430 
4431 
4432 static int
dissect_nfs3_null_reply(tvbuff_t * tvb _U_,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4433 dissect_nfs3_null_reply(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
4434 			proto_tree *tree, void *data _U_)
4435 {
4436 	proto_item_append_text(tree, ", NULL Reply");
4437 
4438 	return 0;
4439 }
4440 
4441 
4442 static int
dissect_nfs3_rmdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4443 dissect_nfs3_rmdir_call(tvbuff_t *tvb, packet_info *pinfo,
4444 	proto_tree *tree, void *data)
4445 {
4446 	guint32	    hash = 0;
4447 	const char *name = NULL;
4448 	int offset = 0;
4449 
4450 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name, (rpc_call_info_value*)data);
4451 
4452 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
4453 	proto_item_append_text(tree, ", RMDIR Call DH: 0x%08x/%s", hash, name);
4454 
4455 	return offset;
4456 }
4457 
4458 
4459 /* NFSv3 RFC 1813, Page 32,33 */
4460 static int
dissect_nfs3_getattr_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4461 dissect_nfs3_getattr_call(tvbuff_t *tvb, packet_info *pinfo,
4462 			  proto_tree *tree, void *data)
4463 {
4464 	guint32 hash = 0;
4465 	int offset = 0;
4466 
4467 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
4468 
4469 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
4470 	proto_item_append_text(tree, ", GETATTR Call FH: 0x%08x", hash);
4471 
4472 	return offset;
4473 }
4474 
4475 
4476 /* NFSv3 RFC 1813, Page 32,33 */
4477 static int
dissect_nfs3_getattr_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4478 dissect_nfs3_getattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
4479 			   proto_tree *tree, void *data _U_)
4480 {
4481 	guint32	    status;
4482 	const char *err;
4483 	int offset = 0;
4484 
4485 	proto_item_append_text(tree, ", GETATTR Reply");
4486 
4487 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
4488 	switch (status) {
4489 		case 0:
4490 			offset = dissect_nfs_fattr3(pinfo, tvb, offset, tree, "obj_attributes", 2|COL_INFO_LEVEL);
4491 		break;
4492 		default:
4493 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
4494 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
4495 			proto_item_append_text(tree, "  Error: %s", err);
4496 		break;
4497 	}
4498 
4499 	return offset;
4500 }
4501 
4502 
4503 /* NFSv3 RFC 1813, Page 33 */
4504 static int
dissect_sattrguard3(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)4505 dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
4506 {
4507 	proto_item *sattrguard3_item;
4508 	proto_tree *sattrguard3_tree;
4509 	int	    old_offset	     = offset;
4510 	guint32	    check;
4511 	const char *check_name;
4512 
4513 	check = tvb_get_ntohl(tvb, offset+0);
4514 
4515 	check_name = val_to_str_const(check, value_follows, "Unknown");
4516 
4517 	sattrguard3_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
4518 			ett_nfs3_sattrguard, &sattrguard3_item, "%s: %s", name, check_name);
4519 
4520 	proto_tree_add_uint(sattrguard3_tree, hf_nfs3_sattrguard3, tvb, offset, 4, check);
4521 
4522 
4523 	offset += 4;
4524 
4525 	switch (check) {
4526 		case TRUE:
4527 			offset = dissect_nfstime3(tvb, offset, sattrguard3_tree,
4528 					hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
4529 		break;
4530 		case FALSE:
4531 			/* void */
4532 		break;
4533 	}
4534 
4535 	/* now we know, that sattrguard3 is shorter */
4536 	proto_item_set_len(sattrguard3_item, offset - old_offset);
4537 
4538 	return offset;
4539 }
4540 
4541 
4542 /* NFSv3 RFC 1813, Page 33..36 */
4543 static int
dissect_nfs3_setattr_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4544 dissect_nfs3_setattr_call(tvbuff_t *tvb, packet_info *pinfo,
4545 			  proto_tree *tree, void *data)
4546 {
4547 	guint32 hash = 0;
4548 	int offset = 0;
4549 
4550 	offset = dissect_nfs3_fh    (tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
4551 	offset = dissect_nfs3_sattr     (tvb, offset,        tree, "new_attributes");
4552 	offset = dissect_sattrguard3(tvb, offset,        tree, "guard");
4553 
4554 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
4555 	proto_item_append_text(tree, ", SETATTR Call FH: 0x%08x", hash);
4556 
4557 	return offset;
4558 }
4559 
4560 
4561 /* NFSv3 RFC 1813, Page 33..36 */
4562 static int
dissect_nfs3_setattr_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4563 dissect_nfs3_setattr_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
4564 			   proto_tree *tree, void *data _U_)
4565 {
4566 	guint32	    status;
4567 	const char *err;
4568 	int offset = 0;
4569 
4570 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
4571 	switch (status) {
4572 		case 0:
4573 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
4574 			proto_item_append_text(tree, ", SETATTR Reply");
4575 		break;
4576 		default:
4577 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "obj_wcc");
4578 
4579 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
4580 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
4581 			proto_item_append_text(tree, ", SETATTR Reply  Error: %s", err);
4582 		break;
4583 	}
4584 
4585 	return offset;
4586 }
4587 
4588 
4589 /* NFSv3 RFC 1813, Page 37..39 */
4590 static int
dissect_nfs3_lookup_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4591 dissect_nfs3_lookup_call(tvbuff_t *tvb, packet_info *pinfo,
4592 			 proto_tree *tree, void *data)
4593 {
4594 	guint32	    hash = 0;
4595 	const char *name = NULL;
4596 	int offset = 0;
4597 
4598 	offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name, (rpc_call_info_value*)data);
4599 
4600 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
4601 	proto_item_append_text(tree, ", LOOKUP Call DH: 0x%08x/%s", hash, name);
4602 
4603 	return offset;
4604 }
4605 
4606 
4607 /* NFSv3 RFC 1813, Page 37..39 */
4608 static int
dissect_nfs3_lookup_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4609 dissect_nfs3_lookup_reply(tvbuff_t *tvb, packet_info *pinfo,
4610 			  proto_tree *tree, void *data)
4611 {
4612 	guint32	    status;
4613 	const char *err;
4614 	guint32	    hash = 0;
4615 	int offset = 0;
4616 
4617 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
4618 	switch (status) {
4619 		case 0:
4620 			offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
4621 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4622 				"obj_attributes");
4623 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4624 				"dir_attributes");
4625 
4626 			col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
4627 			proto_item_append_text(tree, ", LOOKUP Reply FH: 0x%08x", hash);
4628 		break;
4629 		default:
4630 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4631 				"dir_attributes");
4632 
4633 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
4634 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
4635 			proto_item_append_text(tree, ", LOOKUP Reply  Error: %s", err);
4636 		break;
4637 	}
4638 
4639 	return offset;
4640 }
4641 
4642 
4643 static const value_string accvs[] = {
4644 	{ 0x001,	"RD" },
4645 	{ 0x002,	"LU" },
4646 	{ 0x004,	"MD" },
4647 	{ 0x008,	"XT" },
4648 	{ 0x010,	"DL" },
4649 	{ 0x020,	"XE" },
4650 	{ 0x040,	"XAR" },
4651 	{ 0x080,	"XAW" },
4652 	{ 0x100,	"XAL" },
4653 	{ 0,		NULL }
4654 };
4655 
4656 static const true_false_string tfs_access_supp	 = { "supported",	"!NOT Supported!"};
4657 static const true_false_string tfs_access_rights = {"allowed", "*Access Denied*"};
4658 
4659 proto_tree*
display_access_items(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint32 amask,char mtype,int version,wmem_strbuf_t * optext,const char * label)4660 display_access_items(tvbuff_t* tvb, int offset, packet_info* pinfo, proto_tree *tree,
4661 		     guint32 amask, char mtype, int version, wmem_strbuf_t* optext, const char *label)
4662 {
4663 	gboolean    nfsv3	   = ((version == 3) ? TRUE : FALSE);
4664 	proto_item *access_item	   = NULL;
4665 	proto_tree *access_subtree = NULL;
4666 	proto_item *access_subitem = NULL;
4667 	guint32	    itype;
4668 
4669 	/* XXX Legend (delete if desired)
4670 
4671 	   'C' CHECK access:      append label to both headers and create subtree and list
4672 	   'N' NOT SUPPORTED:     append label to both headers
4673 	   'S' SUPPORTED or not:  create subtree and list
4674 	   'D' DENIED:            append label to both headers
4675 	   'A' ALLOWED:           append label to both headers
4676 	   'R' RIGHTS:            create subtree and list */
4677 
4678 	switch (mtype) {
4679 		case 'C':
4680 			access_item = proto_tree_add_item(tree, hf_nfs_access_check, tvb,
4681 				offset, 4, ENC_BIG_ENDIAN);
4682 			access_subtree = proto_item_add_subtree(access_item,
4683 				(nfsv3 ? ett_nfs3_access : ett_nfs4_access));
4684 			break;
4685 		case 'S':
4686 			access_item = proto_tree_add_item(tree, hf_nfs_access_supported, tvb,
4687 				offset, 4, ENC_BIG_ENDIAN);
4688 			access_subtree = proto_item_add_subtree(access_item, ett_nfs4_access_supp);
4689 			break;
4690 		case 'R':
4691 			access_item = proto_tree_add_item(tree, hf_nfs_access_rights, tvb,
4692 				offset, 4, ENC_BIG_ENDIAN);
4693 			access_subtree = proto_item_add_subtree(access_item,
4694 				(nfsv3 ? ett_nfs3_access : ett_nfs4_access));
4695 			break;
4696 	}
4697 	/* Append label to the Info column and tree */
4698 	if (mtype != 'S' && mtype != 'R') {
4699 		if (nfsv3) {
4700 			col_append_fstr(pinfo->cinfo, COL_INFO, ", [%s:", label);
4701 		} else {
4702 			wmem_strbuf_append_printf (optext, ", [%s:", label);
4703 		}
4704 		proto_item_append_text(tree, ", [%s:", label);
4705 	}
4706 
4707 	for (itype=0; itype < 9; itype++) {
4708 		if (amask & accvs[itype].value) {
4709 			if (mtype != 'S' && mtype != 'R')	{
4710 				/* List access type in Info column and tree */
4711 				if (nfsv3) {
4712 					col_append_fstr(pinfo->cinfo, COL_INFO, " %s", accvs[itype].strptr);
4713 				} else {
4714 					wmem_strbuf_append_printf (optext, " %s", accvs[itype].strptr);
4715 				}
4716 				proto_item_append_text(tree, " %s", accvs[itype].strptr);
4717 			}
4718 			if (mtype == 'C' || mtype == 'S' || mtype == 'R') {
4719 
4720 				switch (itype) {
4721 					case 0:
4722 						access_subitem = proto_tree_add_item (access_subtree,
4723 							(mtype == 'S' ? hf_nfs_access_supp_read : hf_nfs_access_read),
4724 							tvb, offset, 4, ENC_BIG_ENDIAN);
4725 						break;
4726 					case 1:
4727 						access_subitem = proto_tree_add_item (access_subtree,
4728 							(mtype == 'S' ? hf_nfs_access_supp_lookup : hf_nfs_access_lookup),
4729 							tvb, offset, 4, ENC_BIG_ENDIAN);
4730 						break;
4731 					case 2:
4732 						access_subitem = proto_tree_add_item (access_subtree,
4733 							(mtype == 'S' ? hf_nfs_access_supp_modify : hf_nfs_access_modify),
4734 							tvb, offset, 4, ENC_BIG_ENDIAN);
4735 						break;
4736 					case 3:
4737 						access_subitem = proto_tree_add_item (access_subtree,
4738 							(mtype == 'S' ? hf_nfs_access_supp_extend : hf_nfs_access_extend),
4739 							tvb, offset, 4, ENC_BIG_ENDIAN);
4740 						break;
4741 					case 4:
4742 						access_subitem = proto_tree_add_item (access_subtree,
4743 							(mtype == 'S' ? hf_nfs_access_supp_delete : hf_nfs_access_delete),
4744 							tvb, offset, 4, ENC_BIG_ENDIAN);
4745 						break;
4746 					case 5:
4747 						access_subitem = proto_tree_add_item (access_subtree,
4748 							(mtype == 'S' ? hf_nfs_access_supp_execute : hf_nfs_access_execute),
4749 							tvb, offset, 4, ENC_BIG_ENDIAN);
4750 						break;
4751 					case 6:
4752 						access_subitem = proto_tree_add_item (access_subtree,
4753 							(mtype == 'S' ? hf_nfs_access_supp_xattr_read : hf_nfs_access_xattr_read),
4754 							tvb, offset, 4, ENC_BIG_ENDIAN);
4755 						break;
4756 					case 7:
4757 						access_subitem = proto_tree_add_item (access_subtree,
4758 							(mtype == 'S' ? hf_nfs_access_supp_xattr_write : hf_nfs_access_xattr_write),
4759 							tvb, offset, 4, ENC_BIG_ENDIAN);
4760 						break;
4761 					case 8:
4762 						access_subitem = proto_tree_add_item (access_subtree,
4763 							(mtype == 'S' ? hf_nfs_access_supp_xattr_list : hf_nfs_access_xattr_list),
4764 							tvb, offset, 4, ENC_BIG_ENDIAN);
4765 						break;
4766 				}
4767 				if (mtype == 'C') proto_item_append_text(access_subitem, "?" );
4768 			}
4769 		}
4770 	}
4771 	if (mtype != 'S' && mtype != 'R') {
4772 		if (nfsv3) {
4773 			col_append_str(pinfo->cinfo, COL_INFO, "]");
4774 		} else {
4775 			wmem_strbuf_append_printf (optext, "]");
4776 		}
4777 		proto_item_append_text(tree, "]");
4778 	}
4779 	return access_subtree = NULL;
4780 }
4781 
4782 /* NFSv3 RFC 1813, Page 40..43 */
4783 /* NFSv4 RFC 3530, Page 140..142 */
4784 int
dissect_access_reply(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,int version,wmem_strbuf_t * optext,rpc_call_info_value * civ)4785 dissect_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
4786 		     int version, wmem_strbuf_t *optext, rpc_call_info_value *civ)
4787 {
4788 	guint32	   *acc_req;
4789 	guint32	    acc_supp;
4790 	guint32	    acc_rights;
4791 	guint32	    mask_not_supp;
4792 	guint32	    mask_denied;
4793 	guint32	    mask_allowed;
4794 	guint32	    e_check, e_rights;
4795 	gboolean    nfsv3	  = ((version == 3) ? TRUE : FALSE);
4796 	gboolean    nfsv4	  = ((version == 4) ? TRUE : FALSE);
4797 	gboolean    have_acc_supp = TRUE;
4798 	proto_tree *access_tree;
4799 	proto_item *ditem;
4800 
4801 	/* Retrieve the access mask from the call if available. It
4802 	   will not be available if the packet containing the call is
4803 	   missing or truncated. */
4804 	acc_req = (guint32 *)civ->private_data;
4805 	if (nfsv4) {
4806 		acc_supp = tvb_get_ntohl(tvb, offset+0);
4807 	} else if (acc_req) {
4808 		acc_supp = *acc_req;
4809 	} else {
4810 		have_acc_supp = FALSE;
4811 	}
4812 	/*  V3/V4 - Get access rights mask and create a subtree for it */
4813 	acc_rights = tvb_get_ntohl(tvb, (nfsv3 ? offset+0: offset+4));
4814 	if (!have_acc_supp) {
4815 		/* The v3 access call isn't available. Using acc_rights for
4816 		   acc_supp ensures mask_allowed will be correct */
4817 		acc_supp = acc_rights;
4818 	}
4819 
4820 	/* Create access masks: not_supported, denied, and allowed */
4821 	if (acc_req && have_acc_supp)
4822 		mask_not_supp = *acc_req ^ acc_supp;
4823 	else
4824 		mask_not_supp = 0;
4825 
4826 	e_check = acc_supp;
4827 	e_rights = acc_supp & acc_rights;  /* guard against broken implementations */
4828 	mask_denied =  e_check ^ e_rights;
4829 	mask_allowed = e_check & e_rights;
4830 
4831 	if (nfsv4) {
4832 		if (mask_not_supp > 0) {
4833 			display_access_items(tvb, offset, pinfo, tree, mask_not_supp, 'N', 4,
4834 				optext, "NOT Supported") ;
4835 		}
4836 		display_access_items(tvb, offset, pinfo, tree, acc_supp, 'S', 4,
4837 			optext, "Supported");
4838 		offset+=4;
4839 	}
4840 	if (mask_denied > 0) {
4841 		display_access_items(tvb, offset, pinfo, tree, mask_denied, 'D', version,
4842 			optext, "Access Denied") ;
4843 	}
4844 	if (mask_allowed > 0) {
4845 		display_access_items(tvb, offset, pinfo, tree, mask_allowed, 'A', version,
4846 			optext, "Allowed") ;
4847 	}
4848 	/* Pass the OR'd masks rather than acc_rights so that display_access_items will
4849 	   process types that have been denied access. Since proto_tree_add_item uses the
4850 	   mask in the tvb (not the passed mask), the correct (denied) access is displayed. */
4851 	access_tree = display_access_items(tvb, offset, pinfo, tree,
4852 		(mask_allowed | mask_denied), 'R', version, optext, NULL) ;
4853 
4854 	ditem = proto_tree_add_boolean(access_tree, hf_nfs_access_denied, tvb,
4855 				offset, 4, (mask_denied > 0 ? TRUE : FALSE ));
4856 	proto_item_set_generated(ditem);
4857 
4858 	return offset+4;
4859 }
4860 
4861 
4862 /* NFSv3 RFC 1813, Page 40..43 */
4863 static int
dissect_nfs3_access_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4864 dissect_nfs3_access_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4865 {
4866 	int offset = 0;
4867 	guint32 fhhash = 0, *acc_request, amask;
4868 	rpc_call_info_value *civ = (rpc_call_info_value*)data;
4869 
4870 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &fhhash, civ);
4871 
4872 	/* Get access mask to check and save it for comparison to the access reply. */
4873 	amask = tvb_get_ntohl(tvb, offset);
4874 	acc_request = (guint32 *)wmem_memdup(wmem_file_scope(),  &amask, sizeof(guint32));
4875 	civ->private_data = acc_request;
4876 
4877 	/* Append filehandle to Info column and main tree header */
4878 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", fhhash);
4879 	proto_item_append_text(tree, ", ACCESS Call, FH: 0x%08x", fhhash);
4880 
4881 	display_access_items(tvb, offset, pinfo, tree, amask, 'C', 3, NULL, "Check") ;
4882 
4883 	offset+=4;
4884 	return offset;
4885 }
4886 
4887 
4888 /* NFSv3 RFC 1813, Page 40..43 */
4889 static int
dissect_nfs3_access_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4890 dissect_nfs3_access_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
4891 			  proto_tree *tree, void *data _U_)
4892 {
4893 	guint32	    status;
4894 	const char *err;
4895 	int offset = 0;
4896 
4897 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
4898 	offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4899 					"obj_attributes");
4900 
4901 	if (status == 0) {
4902 		proto_item_append_text(tree, ", ACCESS Reply");
4903 		offset = dissect_access_reply(tvb, offset, pinfo, tree, 3, NULL, (rpc_call_info_value*)data);
4904 	} else {
4905 		err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
4906 		col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
4907 		proto_item_append_text(tree, ", ACCESS Reply  Error: %s", err);
4908 	}
4909 	return offset;
4910 }
4911 
4912 
4913 /* NFSv3 RFC 1813, Page 44,45 */
4914 static int
dissect_nfs3_readlink_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4915 dissect_nfs3_readlink_call(tvbuff_t *tvb, packet_info *pinfo,
4916 			   proto_tree *tree, void *data)
4917 {
4918 	guint32 hash = 0;
4919 	int offset = 0;
4920 
4921 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
4922 
4923 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
4924 	proto_item_append_text(tree, ", READLINK Call FH: 0x%08x", hash);
4925 
4926 	return offset;
4927 }
4928 
4929 
4930 static int
dissect_nfs3_readlink_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4931 dissect_nfs3_readlink_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
4932 			    proto_tree *tree, void *data _U_)
4933 {
4934 	guint32	    status;
4935 	const char *err;
4936 	const char *name = NULL;
4937 	int offset = 0;
4938 
4939 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
4940 	switch (status) {
4941 		case 0:
4942 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4943 				"symlink_attributes");
4944 			offset = dissect_nfsdata_reduced(R_NFS3_PATH, tvb, offset, tree,
4945 				hf_nfs2_readlink_data, &name);
4946 
4947 			col_append_fstr(pinfo->cinfo, COL_INFO, " Path: %s", name);
4948 			proto_item_append_text(tree, ", READLINK Reply Path: %s", name);
4949 		break;
4950 		default:
4951 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
4952 				"symlink_attributes");
4953 
4954 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
4955 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
4956 			proto_item_append_text(tree, ", READLINK Reply  Error: %s", err);
4957 		break;
4958 	}
4959 
4960 	return offset;
4961 }
4962 
4963 
4964 /* NFSv3 RFC 1813, Page 46..48 */
4965 static int
dissect_nfs3_read_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)4966 dissect_nfs3_read_call(tvbuff_t *tvb, packet_info *pinfo,
4967 		       proto_tree *tree, void *data)
4968 {
4969 	guint64 off;
4970 	guint32 len;
4971 	guint32 hash = 0;
4972 	int offset = 0;
4973 
4974 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
4975 
4976 	off = tvb_get_ntoh64(tvb, offset);
4977 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_offset, offset);
4978 
4979 	len = tvb_get_ntohl(tvb, offset);
4980 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count, offset);
4981 
4982 
4983 	col_append_fstr(pinfo->cinfo, COL_INFO,
4984 		", FH: 0x%08x Offset: %" G_GINT64_MODIFIER "u Len: %u", hash, off, len);
4985 	proto_item_append_text(tree,
4986 		", READ Call FH: 0x%08x Offset: %" G_GINT64_MODIFIER "u Len: %u", hash, off, len);
4987 
4988 	return offset;
4989 }
4990 
4991 
4992 /* NFSv3 RFC 1813, Page 46..48 */
4993 static int
dissect_nfs3_read_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4994 dissect_nfs3_read_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
4995 			proto_tree *tree, void *data _U_)
4996 {
4997 	guint32	    status;
4998 	guint32	    len;
4999 	const char *err;
5000 	int offset = 0;
5001 
5002 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5003 	switch (status) {
5004 		case 0:
5005 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5006 				"file_attributes");
5007 			len = tvb_get_ntohl(tvb, offset);
5008 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count,
5009 				offset);
5010 			offset = dissect_rpc_bool(tvb, tree, hf_nfs3_read_eof,
5011 				offset);
5012 			col_append_fstr(pinfo->cinfo, COL_INFO, " Len: %d", len);
5013 			proto_item_append_text(tree, ", READ Reply Len: %d", len);
5014 			offset = dissect_nfsdata_reduced(R_NFSDATA, tvb, offset, tree, hf_nfs_data, NULL);
5015 		break;
5016 		default:
5017 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5018 				"file_attributes");
5019 
5020 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5021 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5022 			proto_item_append_text(tree, ", READ Reply  Error: %s", err);
5023 		break;
5024 	}
5025 
5026 	return offset;
5027 }
5028 
5029 
5030 /* NFSv3 RFC 1813, Page 49 */
5031 static const value_string names_stable_how[] = {
5032 	{	UNSTABLE,  "UNSTABLE"  },
5033 	{	DATA_SYNC, "DATA_SYNC" },
5034 	{	FILE_SYNC, "FILE_SYNC" },
5035 	{	0, NULL }
5036 };
5037 
5038 /* NFSv3 RFC 1813, Page 49 */
5039 static int
dissect_stable_how(tvbuff_t * tvb,int offset,proto_tree * tree,int hfindex)5040 dissect_stable_how(tvbuff_t *tvb, int offset, proto_tree *tree, int hfindex)
5041 {
5042 	proto_tree_add_item(tree, hfindex, tvb,	offset, 4, ENC_BIG_ENDIAN);
5043 	offset += 4;
5044 
5045 	return offset;
5046 }
5047 
5048 /* NFSv3 RFC 1813, Page 49..54 */
5049 static int
dissect_nfs3_write_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5050 dissect_nfs3_write_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5051 {
5052 	guint64 off;
5053 	guint32 len;
5054 	guint32 stable;
5055 	guint32 hash = 0;
5056 	int offset = 0;
5057 
5058 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
5059 
5060 	off = tvb_get_ntoh64(tvb, offset);
5061 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_offset, offset);
5062 
5063 	len = tvb_get_ntohl(tvb, offset);
5064 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count, offset);
5065 
5066 	stable = tvb_get_ntohl(tvb, offset);
5067 	offset = dissect_stable_how(tvb, offset, tree, hf_nfs3_write_stable);
5068 
5069 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x Offset: %" G_GINT64_MODIFIER "u Len: %u %s",
5070 		hash, off, len, val_to_str(stable, names_stable_how, "Stable: %u"));
5071 	proto_item_append_text(tree, ", WRITE Call FH: 0x%08x Offset: %" G_GINT64_MODIFIER "u Len: %u %s",
5072 		hash, off, len, val_to_str(stable, names_stable_how, "Stable: %u"));
5073 
5074 	offset = dissect_nfsdata   (tvb, offset, tree, hf_nfs_data);
5075 
5076 	return offset;
5077 }
5078 
5079 
5080 /* NFSv3 RFC 1813, Page 49..54 */
5081 static int
dissect_nfs3_write_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5082 dissect_nfs3_write_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5083 {
5084 	guint32	    status;
5085 	guint32	    len;
5086 	guint32	    stable;
5087 	const char *err;
5088 	int offset = 0;
5089 
5090 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5091 	switch (status) {
5092 		case 0:
5093 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
5094 			len = tvb_get_ntohl(tvb, offset);
5095 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count,
5096 				offset);
5097 			stable = tvb_get_ntohl(tvb, offset);
5098 			offset = dissect_stable_how(tvb, offset, tree,
5099 				hf_nfs3_write_committed);
5100 			offset = dissect_nfs3_write_verf(tvb, offset, tree);
5101 
5102 			col_append_fstr(pinfo->cinfo, COL_INFO,
5103 				" Len: %d %s", len, val_to_str(stable, names_stable_how, "Stable: %u"));
5104 			proto_item_append_text(tree, ", WRITE Reply Len: %d %s",
5105 				len, val_to_str(stable, names_stable_how, "Stable: %u"));
5106 		break;
5107 		default:
5108 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
5109 
5110 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5111 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5112 			proto_item_append_text(tree, ", WRITE Reply  Error: %s", err);
5113 		break;
5114 	}
5115 
5116 	return offset;
5117 }
5118 
5119 
5120 /* NFSv3 RFC 1813, Page 54 */
5121 static const value_string names_createmode3[] = {
5122 	{	UNCHECKED, "UNCHECKED" },
5123 	{	GUARDED,   "GUARDED" },
5124 	{	EXCLUSIVE, "EXCLUSIVE" },
5125 	{	0, NULL }
5126 };
5127 
5128 /* NFSv3 RFC 1813, Page 54 */
5129 static int
dissect_createmode3(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * mode)5130 dissect_createmode3(tvbuff_t *tvb, int offset, proto_tree *tree, guint32* mode)
5131 {
5132 	guint32 mode_value;
5133 
5134 	mode_value = tvb_get_ntohl(tvb, offset + 0);
5135 	if (tree)
5136 		proto_tree_add_uint(tree, hf_nfs3_createmode, tvb, offset+0, 4, mode_value);
5137 	offset += 4;
5138 
5139 	*mode = mode_value;
5140 	return offset;
5141 }
5142 
5143 
5144 /* NFSv3 RFC 1813, Page 54..58 */
5145 static int
dissect_nfs3_create_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5146 dissect_nfs3_create_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5147 {
5148 	guint32	    mode;
5149 	guint32	    hash = 0;
5150 	const char *name = NULL;
5151 	int offset = 0;
5152 
5153 	offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
5154 	offset = dissect_createmode3(tvb, offset, tree, &mode);
5155 	switch (mode) {
5156 		case UNCHECKED:
5157 		case GUARDED:
5158 			offset = dissect_nfs3_sattr(tvb, offset, tree, "obj_attributes");
5159 		break;
5160 		case EXCLUSIVE:
5161 			offset = dissect_nfs3_create_verf(tvb, offset, tree);
5162 		break;
5163 	}
5164 
5165 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s Mode: %s", hash, name,
5166 		val_to_str(mode, names_createmode3, "Unknown Mode: %u"));
5167 	proto_item_append_text(tree, ", CREATE Call DH: 0x%08x/%s Mode: %s", hash, name,
5168 		val_to_str(mode, names_createmode3, "Unknown Mode: %u"));
5169 
5170 	return offset;
5171 }
5172 
5173 
5174 /* NFSv3 RFC 1813, Page 54..58 */
5175 static int
dissect_nfs3_create_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5176 dissect_nfs3_create_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5177 {
5178 	guint32	    status;
5179 	const char *err;
5180 	int offset = 0;
5181 
5182 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5183 	switch (status) {
5184 		case 0:
5185 			offset = dissect_nfs3_post_op_fh (tvb, offset, pinfo, tree, "obj", (rpc_call_info_value*)data);
5186 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5187 				"obj_attributes");
5188 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5189 			proto_item_append_text(tree, ", CREATE Reply");
5190 		break;
5191 		default:
5192 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5193 
5194 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5195 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5196 			proto_item_append_text(tree, ", CREATE Reply  Error: %s", err);
5197 		break;
5198 	}
5199 
5200 	return offset;
5201 }
5202 
5203 
5204 /* NFSv3 RFC 1813, Page 58..60 */
5205 static int
dissect_nfs3_mkdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5206 dissect_nfs3_mkdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5207 {
5208 	guint32	    hash = 0;
5209 	const char *name = NULL;
5210 	int offset = 0;
5211 
5212 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
5213 	offset = dissect_nfs3_sattr    (tvb, offset, tree, "attributes");
5214 
5215 	col_append_fstr(pinfo->cinfo, COL_INFO, ", DH: 0x%08x/%s", hash, name);
5216 	proto_item_append_text(tree, ", MKDIR Call DH: 0x%08x/%s", hash, name);
5217 
5218 	return offset;
5219 }
5220 
5221 
5222 static int
dissect_nfs3_mkdir_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5223 dissect_nfs3_mkdir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5224 {
5225 	guint32	    status;
5226 	const char *err;
5227 	int offset = 0;
5228 
5229 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5230 	switch (status) {
5231 		case 0:
5232 			offset = dissect_nfs3_post_op_fh (tvb, offset, pinfo, tree, "obj", (rpc_call_info_value*)data);
5233 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5234 				"obj_attributes");
5235 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5236 			proto_item_append_text(tree, ", MKDIR Reply");
5237 		break;
5238 		default:
5239 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5240 
5241 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5242 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5243 			proto_item_append_text(tree, ", MKDIR Reply  Error: %s", err);
5244 		break;
5245 	}
5246 
5247 	return offset;
5248 }
5249 
5250 
5251 /* NFSv3 RFC 1813, Page 61..63 */
5252 static int
dissect_nfs3_symlink_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5253 dissect_nfs3_symlink_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5254 {
5255 	guint32	    from_hash = 0;
5256 	const char *from_name =	NULL;
5257 	const char *to_name   =	NULL;
5258 	int offset = 0;
5259 
5260 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name, (rpc_call_info_value*)data);
5261 	offset = dissect_nfs3_sattr    (tvb, offset,        tree, "symlink_attributes");
5262 	offset = dissect_nfs3_path  (tvb, offset,        tree, hf_nfs_symlink_to, &to_name);
5263 
5264 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x/%s To %s",
5265 		from_hash, from_name, to_name);
5266 	proto_item_append_text(tree, ", SYMLINK Call From DH: 0x%08x/%s To %s",
5267 		from_hash, from_name, to_name);
5268 
5269 	return offset;
5270 }
5271 
5272 
5273 static int
dissect_nfs3_symlink_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5274 dissect_nfs3_symlink_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5275 {
5276 	guint32	    status;
5277 	const char *err;
5278 	int offset = 0;
5279 
5280 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5281 	switch (status) {
5282 		case 0:
5283 			offset = dissect_nfs3_post_op_fh (tvb, offset, pinfo, tree, "obj", (rpc_call_info_value*)data);
5284 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5285 				"obj_attributes");
5286 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5287 			proto_item_append_text(tree, ", SYMLINK Reply");
5288 		break;
5289 		default:
5290 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5291 
5292 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5293 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5294 			proto_item_append_text(tree, ", SYMLINK Reply  Error: %s", err);
5295 		break;
5296 	}
5297 
5298 	return offset;
5299 }
5300 
5301 
5302 /* NFSv3 RFC 1813, Page 63..66 */
5303 static int
dissect_nfs3_mknod_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5304 dissect_nfs3_mknod_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5305 {
5306 	guint32	    type;
5307 	guint32	    hash = 0;
5308 	const char *name = NULL;
5309 	const char *type_str;
5310 	int offset = 0;
5311 
5312 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name, (rpc_call_info_value*)data);
5313 	offset = dissect_ftype3(tvb, offset, tree, hf_nfs3_ftype, &type);
5314 	switch (type) {
5315 		case NF3CHR:
5316 		case NF3BLK:
5317 			offset = dissect_nfs3_sattr(tvb, offset, tree, "dev_attributes");
5318 			offset = dissect_nfs3_specdata(tvb, offset, tree, "spec");
5319 		break;
5320 		case NF3SOCK:
5321 		case NF3FIFO:
5322 			offset = dissect_nfs3_sattr(tvb, offset, tree, "pipe_attributes");
5323 		break;
5324 		default:
5325 			/* nothing to do */
5326 		break;
5327 	}
5328 
5329 	type_str = val_to_str_ext(type, &names_nfs_ftype3_ext, "Unknown type: %u");
5330 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x/%s %s", hash, name, type_str);
5331 	proto_item_append_text(tree, ", MKNOD Call FH: 0x%08x/%s %s", hash, name, type_str);
5332 
5333 	return offset;
5334 }
5335 
5336 
5337 static int
dissect_nfs3_mknod_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5338 dissect_nfs3_mknod_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5339 {
5340 	guint32	    status;
5341 	const char *err;
5342 	int offset = 0;
5343 
5344 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5345 	switch (status) {
5346 		case 0:
5347 			offset = dissect_nfs3_post_op_fh (tvb, offset, pinfo, tree, "obj", (rpc_call_info_value*)data);
5348 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5349 				"obj_attributes");
5350 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5351 			proto_item_append_text(tree, ", MKNOD Reply");
5352 		break;
5353 		default:
5354 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5355 
5356 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5357 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5358 			proto_item_append_text(tree, ", MKNOD Reply  Error: %s", err);
5359 		break;
5360 	}
5361 
5362 	return offset;
5363 }
5364 
5365 
5366 /* NFSv3 RFC 1813, Page 67..69 */
5367 static int
dissect_nfs3_remove_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5368 dissect_nfs3_remove_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5369 {
5370 	guint32	    status;
5371 	const char *err;
5372 	int offset = 0;
5373 
5374 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5375 	switch (status) {
5376 		case 0:
5377 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5378 			proto_item_append_text(tree, ", REMOVE Reply");
5379 		break;
5380 		default:
5381 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5382 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5383 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5384 			proto_item_append_text(tree, ", REMOVE Reply  Error: %s", err);
5385 		break;
5386 	}
5387 
5388 	return offset;
5389 }
5390 
5391 
5392 static int
dissect_nfs3_rmdir_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5393 dissect_nfs3_rmdir_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5394 {
5395 	guint32	    status;
5396 	const char *err;
5397 	int offset = 0;
5398 
5399 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5400 	switch (status) {
5401 		case 0:
5402 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5403 			proto_item_append_text(tree, ", RMDIR Reply");
5404 		break;
5405 		default:
5406 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "dir_wcc");
5407 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5408 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5409 			proto_item_append_text(tree, ", RMDIR Reply  Error: %s", err);
5410 		break;
5411 	}
5412 
5413 	return offset;
5414 }
5415 
5416 
5417 /* NFSv3 RFC 1813, Page 71..74 */
5418 static int
dissect_nfs3_rename_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5419 dissect_nfs3_rename_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5420 {
5421 	guint32	    from_hash = 0;
5422 	const char *from_name =	NULL;
5423 	guint32	    to_hash   = 0;
5424 	const char *to_name   =	NULL;
5425 	int offset = 0;
5426 
5427 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name, (rpc_call_info_value*)data);
5428 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name, (rpc_call_info_value*)data);
5429 
5430 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x/%s To DH: 0x%08x/%s",
5431 		from_hash, from_name, to_hash, to_name);
5432 	proto_item_append_text(tree, ", RENAME Call From DH: 0x%08x/%s To DH: 0x%08x/%s",
5433 		from_hash, from_name, to_hash, to_name);
5434 
5435 	return offset;
5436 }
5437 
5438 
5439 /* NFSv3 RFC 1813, Page 71..74 */
5440 static int
dissect_nfs3_rename_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5441 dissect_nfs3_rename_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
5442 			  proto_tree *tree, void *data _U_)
5443 {
5444 	guint32	    status;
5445 	const char *err;
5446 	int offset = 0;
5447 
5448 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5449 	switch (status) {
5450 		case 0:
5451 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
5452 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
5453 			proto_item_append_text(tree, ", RENAME Reply");
5454 		break;
5455 		default:
5456 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "fromdir_wcc");
5457 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "todir_wcc");
5458 
5459 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5460 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5461 			proto_item_append_text(tree, ", RENAME Reply  Error: %s", err);
5462 		break;
5463 	}
5464 
5465 	return offset;
5466 }
5467 
5468 
5469 /* NFSv3 RFC 1813, Page 74..76 */
5470 static int
dissect_nfs3_link_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5471 dissect_nfs3_link_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5472 {
5473 	guint32	    from_hash = 0;
5474 	guint32	    to_hash   = 0;
5475 	const char *to_name   =	NULL;
5476 	int offset = 0;
5477 
5478 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &from_hash, (rpc_call_info_value*)data);
5479 	offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name, (rpc_call_info_value*)data);
5480 
5481 	col_append_fstr(pinfo->cinfo, COL_INFO, ", From DH: 0x%08x To DH: 0x%08x/%s",
5482 		from_hash, to_hash, to_name);
5483 	proto_item_append_text(tree, ", LINK Call From DH: 0x%08x To DH: 0x%08x/%s",
5484 		from_hash, to_hash, to_name);
5485 
5486 	return offset;
5487 }
5488 
5489 
5490 /* NFSv3 RFC 1813, Page 74..76 */
5491 static int
dissect_nfs3_link_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5492 dissect_nfs3_link_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5493 {
5494 	guint32	    status;
5495 	const char *err;
5496 	int offset = 0;
5497 
5498 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5499 	switch (status) {
5500 		case 0:
5501 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5502 				"file_attributes");
5503 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
5504 			proto_item_append_text(tree, ", LINK Reply");
5505 		break;
5506 		default:
5507 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5508 				"file_attributes");
5509 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "linkdir_wcc");
5510 
5511 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5512 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5513 			proto_item_append_text(tree, ", LINK Reply  Error: %s", err);
5514 		break;
5515 	}
5516 
5517 	return offset;
5518 }
5519 
5520 
5521 /* NFSv3 RFC 1813, Page 76..80 */
5522 static int
dissect_nfs3_readdir_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5523 dissect_nfs3_readdir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5524 {
5525 	guint32 hash = 0;
5526 	int offset = 0;
5527 
5528 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
5529 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
5530 	offset = dissect_nfs3_cookie_verf(tvb, offset, tree);
5531 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count, offset);
5532 
5533 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5534 	proto_item_append_text(tree, ", READDIR Call FH: 0x%08x", hash);
5535 
5536 	return offset;
5537 }
5538 
5539 
5540 /* NFSv3 RFC 1813, Page 76..80 */
5541 static int
dissect_entry3(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5542 dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
5543 	       proto_tree *tree, void *data _U_)
5544 {
5545 	proto_item *entry_item;
5546 	proto_tree *entry_tree;
5547 	int	    old_offset = offset;
5548 	const char *name       = NULL;
5549 
5550 	entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb, offset+0, -1, ENC_NA);
5551 	entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
5552 
5553 	offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs3_readdir_entry_fileid, offset);
5554 
5555 	offset = dissect_nfs3_filename(tvb, offset, entry_tree,	hf_nfs3_readdir_entry_name, &name);
5556 	proto_item_set_text(entry_item, "Entry: name %s", name);
5557 
5558 	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
5559 
5560 	offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs3_readdir_entry_cookie, offset);
5561 
5562 	/* now we know, that a readdir entry is shorter */
5563 	proto_item_set_len(entry_item, offset - old_offset);
5564 
5565 	return offset;
5566 }
5567 
5568 
5569 /* NFSv3 RFC 1813, Page 76..80 */
5570 static int
dissect_nfs3_readdir_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5571 dissect_nfs3_readdir_reply(tvbuff_t *tvb, packet_info *pinfo,
5572 			   proto_tree *tree, void *data _U_)
5573 {
5574 	guint32	    status;
5575 	const char *err;
5576 	int offset = 0;
5577 
5578 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5579 	switch (status) {
5580 		case 0:
5581 			proto_item_append_text(tree, ", READDIR Reply");
5582 
5583 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5584 				"dir_attributes");
5585 			offset = dissect_nfs3_cookie_verf(tvb, offset, tree);
5586 			offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5587 				dissect_entry3, NULL);
5588 			proto_tree_add_item(tree, hf_nfs_readdir_eof, tvb,
5589 					offset+ 0, 4, ENC_BIG_ENDIAN);
5590 			offset += 4;
5591 		break;
5592 		default:
5593 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5594 				"dir_attributes");
5595 
5596 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5597 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5598 			proto_item_append_text(tree, ", READDIR Reply  Error: %s", err);
5599 		break;
5600 	}
5601 
5602 	return offset;
5603 }
5604 
5605 
5606 /* NFSv3 RFC 1813, Page 80..83 */
5607 static int
dissect_nfs3_readdirplus_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5608 dissect_nfs3_readdirplus_call(tvbuff_t *tvb, packet_info *pinfo,
5609 			      proto_tree *tree, void *data)
5610 {
5611 	guint32 hash = 0;
5612 	int offset = 0;
5613 
5614 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "dir", &hash, (rpc_call_info_value*)data);
5615 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_cookie, offset);
5616 	offset = dissect_nfs3_cookie_verf(tvb, offset, tree);
5617 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count_dircount,
5618 		offset);
5619 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count_maxcount,
5620 		offset);
5621 
5622 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5623 	proto_item_append_text(tree, ", READDIRPLUS Call FH: 0x%08x", hash);
5624 
5625 	return offset;
5626 }
5627 
5628 
5629 /* NFSv3 RFC 1813, Page 80..83 */
5630 static int
dissect_nfs3_entryplus(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,void * data)5631 dissect_nfs3_entryplus(tvbuff_t *tvb, int offset, packet_info *pinfo,
5632 		   proto_tree *tree, void *data)
5633 {
5634 	proto_item *entry_item;
5635 	proto_tree *entry_tree;
5636 	int	    old_offset = offset;
5637 	const char *name       = NULL;
5638 	rpc_call_info_value *civ = (rpc_call_info_value *)data;
5639 
5640 	entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb, offset+0, -1, ENC_NA);
5641 	entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
5642 
5643 	offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs3_readdirplus_entry_fileid, offset);
5644 
5645 	offset = dissect_nfs3_filename(tvb, offset, entry_tree,	hf_nfs3_readdirplus_entry_name, &name);
5646 
5647 	/* are we snooping fh to filenames ?*/
5648 	if ((!pinfo->fd->visited) && nfs_file_name_snooping) {
5649 		/* v3 READDIRPLUS replies will give us a mapping */
5650 		if ( (civ->prog == 100003)
5651 		  &&(civ->vers == 3)
5652 		  &&(!civ->request)
5653 		  &&((civ->proc == 17))
5654 		) {
5655 			nfs_name_snoop_add_name(civ->xid, tvb, 0, 0,
5656 				0/*parent offset*/, 0/*parent len*/,
5657 				name);
5658 		}
5659 	}
5660 
5661 	proto_item_set_text(entry_item, "Entry: name %s", name);
5662 
5663 	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
5664 
5665 	offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs3_readdirplus_entry_cookie,
5666 		offset);
5667 
5668 	offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, entry_tree, "name_attributes");
5669 
5670 	offset = dissect_nfs3_post_op_fh(tvb, offset, pinfo, entry_tree, "name_handle", civ);
5671 
5672 	/* now we know, that a readdirplus entry is shorter */
5673 	proto_item_set_len(entry_item, offset - old_offset);
5674 
5675 	return offset;
5676 }
5677 
5678 
5679 /* NFSv3 RFC 1813, Page 80..83 */
5680 static int
dissect_nfs3_readdirplus_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5681 dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5682 {
5683 	guint32	    status;
5684 	const char *err;
5685 	int offset = 0;
5686 
5687 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5688 	switch (status) {
5689 		case 0:
5690 			proto_item_append_text(tree, ", READDIRPLUS Reply");
5691 
5692 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5693 				"dir_attributes");
5694 			offset = dissect_nfs3_cookie_verf(tvb, offset, tree);
5695 			offset = dissect_rpc_list(tvb, pinfo, tree, offset,
5696 				dissect_nfs3_entryplus, data);
5697 			proto_tree_add_item(tree, hf_nfs_readdir_eof, tvb,
5698 					offset+ 0, 4, ENC_BIG_ENDIAN);
5699 			offset += 4;
5700 		break;
5701 		default:
5702 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5703 				"dir_attributes");
5704 
5705 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5706 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5707 			proto_item_append_text(tree, ", READDIRPLUS Reply  Error: %s", err);
5708 		break;
5709 	}
5710 
5711 	return offset;
5712 }
5713 
5714 
5715 /* NFSv3 RFC 1813, Page 84..86 */
5716 static int
dissect_nfs3_fsstat_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5717 dissect_nfs3_fsstat_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5718 {
5719 	guint32 hash = 0;
5720 	int offset = 0;
5721 
5722 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
5723 
5724 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5725 	proto_item_append_text(tree, ", FSSTAT Call DH: 0x%08x", hash);
5726 	return offset;
5727 }
5728 
5729 
5730 static int
dissect_nfs3_fsstat_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5731 dissect_nfs3_fsstat_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5732 {
5733 	guint32	    status;
5734 	guint32	    invarsec;
5735 	const char *err;
5736 	int offset = 0;
5737 
5738 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5739 	switch (status) {
5740 		case 0:
5741 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5742 				"obj_attributes");
5743 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_tbytes,
5744 				offset);
5745 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_fbytes,
5746 				offset);
5747 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_abytes,
5748 				offset);
5749 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_tfiles,
5750 				offset);
5751 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_ffiles,
5752 				offset);
5753 			offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_fsstat_resok_afiles,
5754 				offset);
5755 			invarsec = tvb_get_ntohl(tvb, offset + 0);
5756 			if (tree)
5757 				proto_tree_add_uint(tree, hf_nfs3_fsstat_invarsec, tvb,
5758 				offset+0, 4, invarsec);
5759 			offset += 4;
5760 
5761 			proto_item_append_text(tree, ", FSSTAT Reply");
5762 		break;
5763 		default:
5764 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5765 				"obj_attributes");
5766 
5767 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5768 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5769 			proto_item_append_text(tree, ", FSSTAT Reply  Error: %s", err);
5770 		break;
5771 	}
5772 
5773 	return offset;
5774 }
5775 
5776 
5777 #define FSF3_LINK        0x0001
5778 #define FSF3_SYMLINK     0x0002
5779 #define FSF3_HOMOGENEOUS 0x0008
5780 #define FSF3_CANSETTIME  0x0010
5781 
5782 static const true_false_string tfs_nfs_pathconf =
5783 	{ "is valid for all files", "should be get for every single file" };
5784 
5785 
5786 /* NFSv3 RFC 1813, Page 86..90 */
5787 static int
dissect_nfs3_fsinfo_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5788 dissect_nfs3_fsinfo_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5789 {
5790 	guint32 hash = 0;
5791 	int offset = 0;
5792 
5793 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
5794 
5795 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5796 	proto_item_append_text(tree, ", FSINFO Call DH: 0x%08x", hash);
5797 	return offset;
5798 }
5799 
5800 
5801 static int
dissect_nfs3_fsinfo_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5802 dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5803 {
5804 	guint32	    status;
5805 	static int * const properties[] = {
5806 		&hf_nfs3_fsinfo_properties_setattr,
5807 		&hf_nfs3_fsinfo_properties_pathconf,
5808 		&hf_nfs3_fsinfo_properties_symlinks,
5809 		&hf_nfs3_fsinfo_properties_hardlinks,
5810 		NULL
5811 	};
5812 	int offset = 0;
5813 
5814 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5815 	switch (status) {
5816 		case 0:
5817 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5818 				"obj_attributes");
5819 			proto_tree_add_item(tree, hf_nfs3_fsinfo_rtmax, tvb, offset, 4, ENC_BIG_ENDIAN);
5820 			offset += 4;
5821 			proto_tree_add_item(tree, hf_nfs3_fsinfo_rtpref, tvb, offset, 4, ENC_BIG_ENDIAN);
5822 			offset += 4;
5823 			proto_tree_add_item(tree, hf_nfs3_fsinfo_rtmult, tvb, offset, 4, ENC_BIG_ENDIAN);
5824 			offset += 4;
5825 			proto_tree_add_item(tree, hf_nfs3_fsinfo_wtmax, tvb, offset, 4, ENC_BIG_ENDIAN);
5826 			offset += 4;
5827 			proto_tree_add_item(tree, hf_nfs3_fsinfo_wtpref, tvb, offset, 4, ENC_BIG_ENDIAN);
5828 			offset += 4;
5829 			proto_tree_add_item(tree, hf_nfs3_fsinfo_wtmult, tvb, offset, 4, ENC_BIG_ENDIAN);
5830 			offset += 4;
5831 			proto_tree_add_item(tree, hf_nfs3_fsinfo_dtpref, tvb, offset, 4, ENC_BIG_ENDIAN);
5832 			offset += 4;
5833 
5834 			offset = dissect_rpc_uint64(tvb, tree,	hf_nfs3_fsinfo_maxfilesize, offset);
5835 			offset = dissect_nfstime3(tvb, offset, tree, hf_nfs_dtime, hf_nfs_dtime_sec,
5836 				hf_nfs_dtime_nsec);
5837 
5838 			proto_tree_add_bitmask(tree, tvb, offset, hf_nfs3_fsinfo_properties, ett_nfs3_fsinfo_properties, properties, ENC_BIG_ENDIAN);
5839 			offset += 4;
5840 
5841 			proto_item_append_text(tree, ", FSINFO Reply");
5842 			break;
5843 		default:
5844 		{
5845 			const char *err;
5846 
5847 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5848 				"obj_attributes");
5849 
5850 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5851 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5852 			proto_item_append_text(tree, ", FSINFO Reply  Error: %s", err);
5853 			break;
5854 		}
5855 	}
5856 
5857 	return offset;
5858 }
5859 
5860 
5861 /* NFSv3 RFC 1813, Page 90..92 */
5862 static int
dissect_nfs3_pathconf_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5863 dissect_nfs3_pathconf_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5864 {
5865 	guint32 hash = 0;
5866 	int offset = 0;
5867 
5868 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "object", &hash, (rpc_call_info_value*)data);
5869 
5870 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5871 	proto_item_append_text(tree, ", PATHCONF Call DH: 0x%08x", hash);
5872 	return offset;
5873 }
5874 
5875 
5876 static int
dissect_nfs3_pathconf_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5877 dissect_nfs3_pathconf_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5878 {
5879 	guint32	    status;
5880 	guint32	    linkmax;
5881 	guint32	    name_max;
5882 	const char *err;
5883 	int offset = 0;
5884 
5885 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5886 	switch (status) {
5887 		case 0:
5888 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5889 				"obj_attributes");
5890 			linkmax = tvb_get_ntohl(tvb, offset + 0);
5891 			if (tree)
5892 				proto_tree_add_uint(tree, hf_nfs3_pathconf_linkmax, tvb,
5893 				offset+0, 4, linkmax);
5894 			offset += 4;
5895 			name_max = tvb_get_ntohl(tvb, offset + 0);
5896 			if (tree)
5897 				proto_tree_add_uint(tree, hf_nfs3_pathconf_name_max, tvb,
5898 				offset+0, 4, name_max);
5899 			offset += 4;
5900 			offset = dissect_rpc_bool(tvb, tree,
5901 				hf_nfs3_pathconf_no_trunc, offset);
5902 			offset = dissect_rpc_bool(tvb, tree,
5903 				hf_nfs3_pathconf_chown_restricted, offset);
5904 			offset = dissect_rpc_bool(tvb, tree,
5905 				hf_nfs3_pathconf_case_insensitive, offset);
5906 			offset = dissect_rpc_bool(tvb, tree,
5907 				hf_nfs3_pathconf_case_preserving, offset);
5908 
5909 			proto_item_append_text(tree, ", PATHCONF Reply");
5910 		break;
5911 		default:
5912 			offset = dissect_nfs3_post_op_attr(tvb, offset, pinfo, tree,
5913 				"obj_attributes");
5914 
5915 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5916 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5917 			proto_item_append_text(tree, ", PATHCONF Reply  Error: %s", err);
5918 		break;
5919 	}
5920 
5921 	return offset;
5922 }
5923 
5924 
5925 /* NFSv3 RFC 1813, Page 92..95 */
5926 static int
dissect_nfs3_commit_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)5927 dissect_nfs3_commit_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5928 {
5929 	guint32 hash = 0;
5930 	int offset = 0;
5931 
5932 	offset = dissect_nfs3_fh(tvb, offset, pinfo, tree, "file", &hash, (rpc_call_info_value*)data);
5933 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs3_offset, offset);
5934 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs3_count, offset);
5935 
5936 	col_append_fstr(pinfo->cinfo, COL_INFO, ", FH: 0x%08x", hash);
5937 	proto_item_append_text(tree, ", COMMIT Call FH: 0x%08x", hash);
5938 
5939 	return offset;
5940 }
5941 
5942 
5943 /* NFSv3 RFC 1813, Page 92..95 */
5944 static int
dissect_nfs3_commit_reply(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)5945 dissect_nfs3_commit_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
5946 {
5947 	guint32	    status;
5948 	const char *err;
5949 	int offset = 0;
5950 
5951 	offset = dissect_nfs3_status(tvb, offset, tree, &status);
5952 	switch (status) {
5953 		case 0:
5954 			offset = dissect_wcc_data  (tvb, offset, pinfo, tree, "file_wcc");
5955 			offset = dissect_nfs3_write_verf(tvb, offset, tree);
5956 
5957 			proto_item_append_text(tree, ", COMMIT Reply");
5958 		break;
5959 		default:
5960 			offset = dissect_wcc_data(tvb, offset, pinfo, tree, "file_wcc");
5961 
5962 			err = val_to_str_ext(status, &names_nfs3_status_ext, "Unknown error: %u");
5963 			col_append_fstr(pinfo->cinfo, COL_INFO, " Error: %s", err);
5964 			proto_item_append_text(tree, ", COMMIT Reply  Error: %s", err);
5965 		break;
5966 	}
5967 
5968 	return offset;
5969 }
5970 
5971 /*************************************************************************************
5972 *  NFS Version 4.1, RFC 5661.  Note that error 19 NFS4ERR_NOTDIR defined in RFC 3010
5973 *  was eliminated in RFC 3530 (NFSv4) which replaced RFC 3010 and remains so in
5974 *  RFC 5661. Nevertheless, it has been included in this table in the event that some
5975 *  RFC 3010 implementations still exist out there.
5976 **************************************************************************************/
5977 static const value_string names_nfs4_status[] = {
5978 	{	0,	"NFS4_OK"			    },
5979 	{	1,	"NFS4ERR_PERM"			    },
5980 	{	2,	"NFS4ERR_NOENT"			    },
5981 	{	5,	"NFS4ERR_IO"			    },
5982 	{	6,	"NFS4ERR_NXIO"			    },
5983 	{	13,	"NFS4ERR_ACCESS"		    },
5984 	{	17,	"NFS4ERR_EXIST"			    },
5985 	{	18,	"NFS4ERR_XDEV"			    },
5986 	{	19,	"NFS4ERR_DQUOT"			    },
5987 	{	20,	"NFS4ERR_NOTDIR"		    },
5988 	{	21,	"NFS4ERR_ISDIR"			    },
5989 	{	22,	"NFS4ERR_INVAL"			    },
5990 	{	27,	"NFS4ERR_FBIG"			    },
5991 	{	28,	"NFS4ERR_NOSPC"			    },
5992 	{	30,	"NFS4ERR_ROFS"			    },
5993 	{	31,	"NFS4ERR_MLINK"			    },
5994 	{	63,	"NFS4ERR_NAMETOOLONG"		    },
5995 	{	66,	"NFS4ERR_NOTEMPTY"		    },
5996 	{	69,	"NFS4ERR_DQUOT"			    },
5997 	{	70,	"NFS4ERR_STALE"			    },
5998 	{	10001,	"NFS4ERR_BADHANDLE"		    },
5999 	{	10003,	"NFS4ERR_BAD_COOKIE"		    },
6000 	{	10004,	"NFS4ERR_NOTSUPP"		    },
6001 	{	10005,	"NFS4ERR_TOOSMALL"		    },
6002 	{	10006,	"NFS4ERR_SERVERFAULT"		    },
6003 	{	10007,	"NFS4ERR_BADTYPE"		    },
6004 	{	10008,	"NFS4ERR_DELAY"			    },
6005 	{	10009,	"NFS4ERR_SAME"			    },
6006 	{	10010,	"NFS4ERR_DENIED"		    },
6007 	{	10011,	"NFS4ERR_EXPIRED"		    },
6008 	{	10012,	"NFS4ERR_LOCKED"		    },
6009 	{	10013,	"NFS4ERR_GRACE"			    },
6010 	{	10014,	"NFS4ERR_FHEXPIRED"		    },
6011 	{	10015,	"NFS4ERR_SHARE_DENIED"		    },
6012 	{	10016,	"NFS4ERR_WRONGSEC"		    },
6013 	{	10017,	"NFS4ERR_CLID_INUSE"		    },
6014 	{	10018,	"NFS4ERR_RESOURCE"		    },
6015 	{	10019,	"NFS4ERR_MOVED"			    },
6016 	{	10020,	"NFS4ERR_NOFILEHANDLE"		    },
6017 	{	10021,	"NFS4ERR_MINOR_VERS_MISMATCH"	    },
6018 	{	10022,	"NFS4ERR_STALE_CLIENTID"	    },
6019 	{	10023,	"NFS4ERR_STALE_STATEID"		    },
6020 	{	10024,	"NFS4ERR_OLD_STATEID"		    },
6021 	{	10025,	"NFS4ERR_BAD_STATEID"		    },
6022 	{	10026,	"NFS4ERR_BAD_SEQID"		    },
6023 	{	10027,	"NFS4ERR_NOT_SAME"		    },
6024 	{	10028,	"NFS4ERR_LOCK_RANGE"		    },
6025 	{	10029,	"NFS4ERR_SYMLINK"		    },
6026 	{	10030,	"NFS4ERR_READDIR_NOSPC"		    },
6027 	{	10031,	"NFS4ERR_LEASE_MOVED"		    },
6028 	{	10032,	"NFS4ERR_ATTRNOTSUPP"		    },
6029 	{	10033,	"NFS4ERR_NO_GRACE"		    },
6030 	{	10034,	"NFS4ERR_RECLAIM_BAD"		    },
6031 	{	10035,	"NFS4ERR_RECLAIM_CONFLICT"	    },
6032 	{	10036,	"NFS4ERR_BADXDR"		    },
6033 	{	10037,	"NFS4ERR_LOCKS_HELD"		    },
6034 	{	10038,	"NFS4ERR_OPENMODE"		    },
6035 	{	10039,	"NFS4ERR_BADOWNER"		    },
6036 	{	10040,	"NFS4ERR_BADCHAR"		    },
6037 	{	10041,	"NFS4ERR_BADNAME"		    },
6038 	{	10042,	"NFS4ERR_BAD_RANGE"		    },
6039 	{	10043,	"NFS4ERR_LOCK_NOTSUPP"		    },
6040 	{	10044,	"NFS4ERR_OP_ILLEGAL"		    },
6041 	{	10045,	"NFS4ERR_DEADLOCK"		    },
6042 	{	10046,	"NFS4ERR_FILE_OPEN"		    },
6043 	{	10047,	"NFS4ERR_ADMIN_REVOKED"		    },
6044 	{	10048,	"NFS4ERR_CB_PATH_DOWN"		    },
6045 	{	10049,	"NFS4ERR_BADIOMODE"		    },
6046 	{	10050,	"NFS4ERR_BADLAYOUT"		    },
6047 	{	10051,	"NFS4ERR_BAD_SESSION_DIGEST"	    },
6048 	{	10052,	"NFS4ERR_BADSESSION"		    },
6049 	{	10053,	"NFS4ERR_BADSLOT"		    },
6050 	{	10054,	"NFS4ERR_COMPLETE_ALREADY"	    },
6051 	{	10055,	"NFS4ERR_CONN_NOT_BOUND_TO_SESSION" },
6052 	{	10056,	"NFS4ERR_DELEG_ALREADY_WANTED"	    },
6053 	{	10057,	"NFS4ERR_DIRDELEG_UNAVAIL"	    },
6054 	{	10058,	"NFS4ERR_LAYOUTTRYLATER"	    },
6055 	{	10059,	"NFS4ERR_LAYOUTUNAVAILABLE"	    },
6056 	{	10060,	"NFS4ERR_NOMATCHING_LAYOUT"	    },
6057 	{	10061,	"NFS4ERR_RECALLCONFLICT"	    },
6058 	{	10062,	"NFS4ERR_UNKNOWN_LAYOUTTYPE"	    },
6059 	{	10063,	"NFS4ERR_SEQ_MISORDERED"	    },
6060 	{	10064,	"NFS4ERR_SEQUENCE_POS"		    },
6061 	{	10065,	"NFS4ERR_REQ_TOO_BIG"		    },
6062 	{	10066,	"NFS4ERR_REP_TOO_BIG"		    },
6063 	{	10067,	"NFS4ERR_REP_TOO_BIG_TO_CACHE"	    },
6064 	{	10068,	"NFS4ERR_RETRY_UNCACHED_REP"	    },
6065 	{	10069,	"NFS4ERR_UNSAFE_COMPOUND"	    },
6066 	{	10070,	"NFS4ERR_TOO_MANY_OPS"		    },
6067 	{	10071,	"NFS4ERR_OP_NOT_IN_SESSION"	    },
6068 	{	10072,	"NFS4ERR_HASH_ALG_UNSUPP"	    },
6069 	{	10073,	"NFS4ERR_CONN_BINDING_NOT_ENFORCED" },
6070 	{	10074,	"NFS4ERR_CLIENTID_BUSY"		    },
6071 	{	10075,	"NFS4ERR_PNFS_IO_HOLE"		    },
6072 	{	10076,	"NFS4ERR_SEQ_FALSE_RETRY"	    },
6073 	{	10077,	"NFS4ERR_BAD_HIGH_SLOT"		    },
6074 	{	10078,	"NFS4ERR_DEADSESSION"		    },
6075 	{	10079,	"NFS4ERR_ENCR_ALG_UNSUPP"	    },
6076 	{	10080,	"NFS4ERR_PNFS_NO_LAYOUT"	    },
6077 	{	10081,	"NFS4ERR_NOT_ONLY_OP"		    },
6078 	{	10082,	"NFS4ERR_WRONG_CRED"		    },
6079 	{	10083,	"NFS4ERR_WRONG_TYPE"		    },
6080 	{	10084,	"NFS4ERR_DIRDELEG_UNAVAIL"	    },
6081 	{	10085,	"NFS4ERR_REJECT_DELEG"		    },
6082 	{	10086,	"NFS4ERR_RETURNCONFLICT"	    },
6083 	{	10087,	"NFS4ERR_DELEG_REVOKED"		    },
6084 	{	10088,	"NFS4ERR_PARTNER_NOTSUPP"	    },
6085 	{	10089,	"NFS4ERR_PARTNER_NO_AUTH"	    },
6086 	{	10090,	"NFS4ERR_UNION_NOTSUPP"		    },
6087 	{	10091,	"NFS4ERR_OFFLOAD_DENIED"	    },
6088 	{	10092,	"NFS4ERR_WRONG_LFS"		    },
6089 	{	10093,	"NFS4ERR_BADLABEL"		    },
6090 	{	10094,	"NFS4ERR_OFFLOAD_NO_REQS"	    },
6091 	{	10095,	"NFS4ERR_NOXATTR"		    },
6092 	{	10096,	"NFS4ERR_XATTR2BIG"		    },
6093 	{	0,	NULL }
6094 };
6095 static value_string_ext names_nfs4_status_ext = VALUE_STRING_EXT_INIT(names_nfs4_status);
6096 
6097 static const value_string fattr4_names[] = {
6098 #define FATTR4_SUPPORTED_ATTRS     0
6099 	{	FATTR4_SUPPORTED_ATTRS,    "Supported_Attrs"	},
6100 #define FATTR4_TYPE                1
6101 	{	FATTR4_TYPE,               "Type"},
6102 #define FATTR4_FH_EXPIRE_TYPE      2
6103 	{	FATTR4_FH_EXPIRE_TYPE,     "FH_Expire_Type"	},
6104 #define FATTR4_CHANGE              3
6105 	{	FATTR4_CHANGE,             "Change"},
6106 #define FATTR4_SIZE                4
6107 	{	FATTR4_SIZE,	           "Size"	},
6108 #define FATTR4_LINK_SUPPORT        5
6109 	{	FATTR4_LINK_SUPPORT,       "Link_Support"	},
6110 #define FATTR4_SYMLINK_SUPPORT     6
6111 	{	FATTR4_SYMLINK_SUPPORT,    "Symlink_Support"	},
6112 #define FATTR4_NAMED_ATTR          7
6113 	{	FATTR4_NAMED_ATTR,         "Named_Attr"	},
6114 #define FATTR4_FSID                8
6115 	{	FATTR4_FSID,               "FSID"	},
6116 #define FATTR4_UNIQUE_HANDLES      9
6117 	{	FATTR4_UNIQUE_HANDLES,     "Unique_Handles"	},
6118 #define FATTR4_LEASE_TIME          10
6119 	{	FATTR4_LEASE_TIME,         "Lease_Time"	},
6120 #define FATTR4_RDATTR_ERROR        11
6121 	{	FATTR4_RDATTR_ERROR,       "RDAttr_Error"	},
6122 #define FATTR4_ACL                 12
6123 	{	FATTR4_ACL,                "ACL"	},
6124 #define FATTR4_ACLSUPPORT          13
6125 	{	FATTR4_ACLSUPPORT,         "ACLSupport"	},
6126 #define FATTR4_ARCHIVE             14
6127 	{	FATTR4_ARCHIVE,            "Archive"	},
6128 #define FATTR4_CANSETTIME          15
6129 	{	FATTR4_CANSETTIME,         "CanSetTime"	},
6130 #define FATTR4_CASE_INSENSITIVE    16
6131 	{	FATTR4_CASE_INSENSITIVE,   "Case_Insensitive"	},
6132 #define FATTR4_CASE_PRESERVING     17
6133 	{	FATTR4_CASE_PRESERVING,    "Case_Preserving"	},
6134 #define FATTR4_CHOWN_RESTRICTED    18
6135 	{	FATTR4_CHOWN_RESTRICTED,   "Chown_Restricted"	},
6136 #define FATTR4_FILEHANDLE          19
6137 	{	FATTR4_FILEHANDLE,         "Filehandle"	},
6138 #define FATTR4_FILEID              20
6139 	{	FATTR4_FILEID,             "FileId"	},
6140 #define FATTR4_FILES_AVAIL         21
6141 	{	FATTR4_FILES_AVAIL,        "Files_Avail"	},
6142 #define FATTR4_FILES_FREE          22
6143 	{	FATTR4_FILES_FREE,         "Files_Free"	},
6144 #define FATTR4_FILES_TOTAL         23
6145 	{	FATTR4_FILES_TOTAL,        "Files_Total"	},
6146 #define FATTR4_FS_LOCATIONS        24
6147 	{	FATTR4_FS_LOCATIONS,       "FS_Locations"	},
6148 #define FATTR4_HIDDEN              25
6149 	{	FATTR4_HIDDEN,             "Hidden"	},
6150 #define FATTR4_HOMOGENEOUS         26
6151 	{	FATTR4_HOMOGENEOUS,        "Homogeneous"	},
6152 #define FATTR4_MAXFILESIZE         27
6153 	{	FATTR4_MAXFILESIZE,        "MaxFileSize"	},
6154 #define FATTR4_MAXLINK             28
6155 	{	FATTR4_MAXLINK,            "MaxLink"	},
6156 #define FATTR4_MAXNAME             29
6157 	{	FATTR4_MAXNAME,            "MaxName"	},
6158 #define FATTR4_MAXREAD             30
6159 	{	FATTR4_MAXREAD,            "MaxRead"	},
6160 #define FATTR4_MAXWRITE            31
6161 	{	FATTR4_MAXWRITE,           "MaxWrite"	},
6162 #define FATTR4_MIMETYPE            32
6163 	{	FATTR4_MIMETYPE,           "MimeType"	},
6164 #define FATTR4_MODE                33
6165 	{	FATTR4_MODE,               "Mode"	},
6166 #define FATTR4_NO_TRUNC            34
6167 	{	FATTR4_NO_TRUNC,           "No_Trunc"	},
6168 #define FATTR4_NUMLINKS            35
6169 	{	FATTR4_NUMLINKS,           "NumLinks"	},
6170 #define FATTR4_OWNER               36
6171 	{	FATTR4_OWNER,              "Owner"	},
6172 #define FATTR4_OWNER_GROUP         37
6173 	{	FATTR4_OWNER_GROUP,        "Owner_Group"	},
6174 #define FATTR4_QUOTA_AVAIL_HARD    38
6175 	{	FATTR4_QUOTA_AVAIL_HARD,   "Quota_Avail_Hard"	},
6176 #define FATTR4_QUOTA_AVAIL_SOFT    39
6177 	{	FATTR4_QUOTA_AVAIL_SOFT,   "Quota_Avail_Soft"	},
6178 #define FATTR4_QUOTA_USED          40
6179 	{	FATTR4_QUOTA_USED,         "Quota_Used"	},
6180 #define FATTR4_RAWDEV              41
6181 	{	FATTR4_RAWDEV,             "RawDev"	},
6182 #define FATTR4_SPACE_AVAIL         42
6183 	{	FATTR4_SPACE_AVAIL,        "Space_Avail"	},
6184 #define FATTR4_SPACE_FREE          43
6185 	{	FATTR4_SPACE_FREE,         "Space_Free"	},
6186 #define FATTR4_SPACE_TOTAL         44
6187 	{	FATTR4_SPACE_TOTAL,        "Space_Total"	},
6188 #define FATTR4_SPACE_USED          45
6189 	{	FATTR4_SPACE_USED,         "Space_Used"	},
6190 #define FATTR4_SYSTEM              46
6191 	{	FATTR4_SYSTEM,             "System"	},
6192 #define FATTR4_TIME_ACCESS         47
6193 	{	FATTR4_TIME_ACCESS,        "Time_Access"	},
6194 #define FATTR4_TIME_ACCESS_SET     48
6195 	{	FATTR4_TIME_ACCESS_SET,    "Time_Access_Set"	},
6196 #define FATTR4_TIME_BACKUP         49
6197 	{	FATTR4_TIME_BACKUP,        "Time_Backup"	},
6198 #define FATTR4_TIME_CREATE         50
6199 	{	FATTR4_TIME_CREATE,        "Time_Create"	},
6200 #define FATTR4_TIME_DELTA          51
6201 	{	FATTR4_TIME_DELTA,         "Time_Delta"	},
6202 #define FATTR4_TIME_METADATA       52
6203 	{	FATTR4_TIME_METADATA,      "Time_Metadata"	},
6204 #define FATTR4_TIME_MODIFY         53
6205 	{	FATTR4_TIME_MODIFY,        "Time_Modify"	},
6206 #define FATTR4_TIME_MODIFY_SET     54
6207 	{	FATTR4_TIME_MODIFY_SET,    "Time_Modify_Set"	},
6208 #define FATTR4_MOUNTED_ON_FILEID   55
6209 	{	FATTR4_MOUNTED_ON_FILEID,  "Mounted_on_FileId"	},
6210 #define FATTR4_DIR_NOTIF_DELAY     56
6211 	{	FATTR4_DIR_NOTIF_DELAY,    "Dir_Notif_Delay"	},
6212 #define FATTR4_DIRENT_NOTIF_DELAY  57
6213 #define FATTR4_DACL                58
6214 	{	FATTR4_DACL,               "DACL"                },
6215 #define FATTR4_SACL                59
6216 	{	FATTR4_SACL,               "SACL"                },
6217 #define FATTR4_CHANGE_POLICY       60
6218 	{	FATTR4_CHANGE_POLICY,      "Change_Policy"		},
6219 #define FATTR4_FS_STATUS           61
6220 	{	FATTR4_FS_STATUS,          "FS_Status"			},
6221 #define FATTR4_FS_LAYOUT_TYPE      62
6222 	{	FATTR4_FS_LAYOUT_TYPE,     "FS_Layout_Type"		},
6223 #define FATTR4_LAYOUT_HINT         63
6224 	{	FATTR4_LAYOUT_HINT,        "Layout_hint"		},
6225 #define FATTR4_LAYOUT_TYPE         64
6226 	{	FATTR4_LAYOUT_TYPE,        "Layout_type"		},
6227 #define FATTR4_LAYOUT_BLKSIZE      65
6228 	{	FATTR4_LAYOUT_BLKSIZE,     "Layout_blksize"		},
6229 #define FATTR4_LAYOUT_ALIGNMENT    66
6230 	{	FATTR4_LAYOUT_ALIGNMENT,   "Layout_alignment"	},
6231 #define FATTR4_FS_LOCATIONS_INFO   67
6232 	{	FATTR4_FS_LOCATIONS_INFO,  "FS_Locations_info"	},
6233 #define FATTR4_MDSTHRESHOLD        68
6234 	{	FATTR4_MDSTHRESHOLD,       "MDS_Threshold"		},
6235 #define FATTR4_RETENTION_GET       69
6236 	{	FATTR4_RETENTION_GET,      "Retention_Get"		},
6237 #define FATTR4_RETENTION_SET       70
6238 	{	FATTR4_RETENTION_SET,      "Retention_Set"		},
6239 #define FATTR4_RETENTEVT_GET       71
6240 	{	FATTR4_RETENTEVT_GET,      "RetentEvt_Get"		},
6241 #define FATTR4_RETENTEVT_SET       72
6242 	{	FATTR4_RETENTEVT_SET,      "RetentEvt_Set"		},
6243 #define FATTR4_RETENTION_HOLD      73
6244 	{	FATTR4_RETENTION_HOLD,     "Retention_Hold"		},
6245 #define FATTR4_MODE_SET_MASKED     74
6246 	{	FATTR4_MODE_SET_MASKED,    "Mode_Set_Masked"	},
6247 #define FATTR4_SUPPATTR_EXCLCREAT  75
6248 	{	FATTR4_SUPPATTR_EXCLCREAT, "Suppattr_ExclCreat"	},
6249 #define FATTR4_FS_CHARSET_CAP      76
6250 	{	FATTR4_FS_CHARSET_CAP,     "FS_Charset_Cap"		},
6251 #define FATTR4_CLONE_BLOCKSIZE     77
6252 	{	FATTR4_CLONE_BLOCKSIZE,    "Clone_Block_Size"		},
6253 #define FATTR4_SPACE_FREED         78
6254 	{	FATTR4_SPACE_FREED,        "Space_Freed"		},
6255 #define FATTR4_CHANGE_ATTR_TYPE    79
6256 	{	FATTR4_CHANGE_ATTR_TYPE,   "Change_Attr_Type"		},
6257 #define FATTR4_SECURITY_LABEL      80
6258 	{	FATTR4_SECURITY_LABEL,     "Security_Label"		},
6259 #define FATTR4_MODE_UMASK          81
6260 	{	FATTR4_MODE_UMASK,         "Mode_Umask"			},
6261 #define FATTR4_XATTR_SUPPORT       82
6262 	{	FATTR4_XATTR_SUPPORT,      "Xattr_Support"		},
6263 #define FATTR4_OFFLINE             83
6264 	{	FATTR4_OFFLINE,            "Offline"                    },
6265 #define FATTR4_TIME_DELEG_ACCESS   84
6266 	{	FATTR4_TIME_DELEG_ACCESS,  "Time_Deleg_Access"          },
6267 #define FATTR4_TIME_DELEG_MODIFY   85
6268 	{	FATTR4_TIME_DELEG_MODIFY,  "Time_Deleg_Modify"          },
6269 	{	0,	NULL	}
6270 };
6271 static value_string_ext fattr4_names_ext = VALUE_STRING_EXT_INIT(fattr4_names);
6272 
6273 static int
dissect_nfs4_status(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * status)6274 dissect_nfs4_status(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *status)
6275 {
6276 	guint32	    stat;
6277 	proto_item *stat_item;
6278 
6279 	proto_tree_add_item_ret_uint(tree, hf_nfs4_status, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stat);
6280 	stat_item = proto_tree_add_uint(tree, hf_nfs_status, tvb, offset+0, 4, stat);
6281 	proto_item_set_hidden(stat_item);
6282 
6283 	if (status)
6284 		*status = stat;
6285 
6286 	return offset + 4;
6287 }
6288 
6289 
6290 static int
dissect_nfs_utf8string(tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** string_ret)6291 dissect_nfs_utf8string(tvbuff_t *tvb, int offset,
6292 		       proto_tree *tree, int hf, const char **string_ret)
6293 {
6294 	/* TODO: this dissector is subject to change; do not remove */
6295 	return dissect_rpc_string(tvb, tree, hf, offset, string_ret);
6296 }
6297 
6298 
6299 /*
6300  *  Generic function to dissect bitmap4 and optionally its corresponding
6301  *  opaque data.
6302  */
6303 static int
dissect_nfs4_bitmap(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ,nfs4_bitmap_info_t * bitmap_info,nfs4_bitmap_type_t type,const char * name)6304 dissect_nfs4_bitmap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
6305 	rpc_call_info_value *civ, nfs4_bitmap_info_t *bitmap_info, nfs4_bitmap_type_t type,
6306 	const char *name)
6307 {
6308 	int attr_offset;
6309 	int hf_item = -1;
6310 	guint32  i, j;
6311 	guint32  count;
6312 	guint32  bitmap;
6313 	guint32  bit_num;
6314 	guint32  bit_set;
6315 	guint32  num_bitmaps;
6316 	guint32  end_offset;
6317 	guint32  mask_offset;
6318 	guint32  opaque_offset;
6319 	guint32  opaque_length = 0;
6320 	guint32  opaque_padding = 0;
6321 	gboolean no_idx = FALSE;
6322 	gboolean first_attr = FALSE;
6323 	gboolean skip_attr_values = FALSE;
6324 
6325 	header_field_info *hfinfo;
6326 
6327 	proto_item *name_tree   = tree;
6328 	proto_item *bitmap_item = NULL;
6329 	proto_tree *bitmap_tree = NULL;
6330 	proto_item *attr_item   = NULL;
6331 	proto_tree *attr_tree   = NULL;
6332 	proto_item *attr_count  = NULL;
6333 
6334 	/* Get the number of bitmap masks */
6335 	num_bitmaps = tvb_get_ntohl(tvb, offset);
6336 	mask_offset = offset + 4;  /* Offset of first bitmap mask */
6337 	opaque_offset = mask_offset + 4*num_bitmaps;
6338 
6339 	if (type == NFS4_BITMAP_VALUES) {
6340 		/* Get the length of opaque including padding */
6341 		opaque_length = tvb_get_ntohl(tvb, opaque_offset);
6342 		opaque_padding = ((opaque_length % 4) ? (4 - (opaque_length % 4)) : 0);
6343 		opaque_offset += 4;  /* Starting offset of bitmap values */
6344 	}
6345 
6346 	/* Offset after the bitmap mask and values regardless of type */
6347 	end_offset = opaque_offset + opaque_length + opaque_padding;
6348 
6349 	if (name != NULL) {
6350 		/* Add subtree if name is given -- all bitmap data will be
6351 		 * under this main tree */
6352 		name_tree = proto_tree_add_subtree(tree, tvb, offset, end_offset - offset,
6353 							ett_nfs4_bitmap, NULL, name);
6354 	}
6355 
6356 	if (type == NFS4_BITMAP_VALUES && num_bitmaps == 0) {
6357 		expert_add_info(pinfo, name_tree, &ei_protocol_violation);
6358 		return end_offset;
6359 	}
6360 
6361 	if (num_bitmaps > MAX_BITMAPS) {
6362 		proto_tree_add_uint(name_tree, hf_nfs4_huge_bitmap_length, tvb, offset, 4, num_bitmaps);
6363 		expert_add_info(pinfo, name_tree, &ei_nfs_too_many_bitmaps);
6364 		return end_offset;
6365 	} else if (bitmap_info->hf_mask_count) {
6366 		/* Display the number of bitmap masks if the label is given */
6367 		proto_tree_add_uint(name_tree, *bitmap_info->hf_mask_count, tvb, offset, 4, num_bitmaps);
6368 	}
6369 
6370 	/* Count the number of non-zero masks */
6371 	count = 0;
6372 	for (i = 0; i < num_bitmaps; i++) {
6373 		bitmap = tvb_get_ntohl(tvb, mask_offset + 4*i);
6374 		if (bitmap > 0)
6375 			count++;
6376 	}
6377 
6378 	/* If there is only one non-zero bitmap, don't display the bitmap index "[x]". */
6379 	if (count <= 1)
6380 		no_idx = TRUE;
6381 
6382 	/* Set the offset to the first value */
6383 	offset = opaque_offset;
6384 
6385 	/* Show mask label when the number of bitmap masks is zero */
6386 	if (num_bitmaps == 0 && name == NULL && name_tree && bitmap_info->hf_mask_label) {
6387 		/* Get header field to add the mask index to the field name */
6388 		hfinfo = proto_registrar_get_nth(*bitmap_info->hf_mask_label);
6389 		bitmap_tree = proto_tree_add_subtree_format(name_tree, tvb, mask_offset, 0,
6390 						ett_nfs4_bitmap, NULL, "%s:", hfinfo->name);
6391 	}
6392 
6393 	for (i = 0; i < num_bitmaps; i++) {
6394 		bitmap = tvb_get_ntohl(tvb, mask_offset);
6395 
6396 		if (bitmap) {
6397 			if (name_tree && bitmap_info->hf_mask_label) {
6398 				if (no_idx) {
6399 					bitmap_item = proto_tree_add_uint(name_tree, *bitmap_info->hf_mask_label, tvb,
6400 							mask_offset, 4, bitmap);
6401 				} else {
6402 					/* Get header field to add the mask index to the field name */
6403 					hfinfo = proto_registrar_get_nth(*bitmap_info->hf_mask_label);
6404 					bitmap_item = proto_tree_add_uint_format(name_tree, *bitmap_info->hf_mask_label, tvb,
6405 							mask_offset, 4, bitmap, "%s[%u]: 0x%08x", hfinfo->name, i, bitmap);
6406 				}
6407 				bitmap_tree = proto_item_add_subtree(bitmap_item, ett_nfs4_bitmap);
6408 				first_attr = TRUE;
6409 
6410 				if (bitmap_info->hf_item_count) {
6411 					/* Count the number of attribute bits set */
6412 					for (j = 0, count = 0; j < 32; j++)
6413 						count += ((bitmap >> j) & 1);
6414 					hfinfo = proto_registrar_get_nth(*bitmap_info->hf_item_count);
6415 					attr_count = proto_tree_add_uint_format(bitmap_tree, *bitmap_info->hf_item_count, tvb, mask_offset,
6416 							4, count, "%u %s%s", count, hfinfo->name, plurality(count, "", "s"));
6417 					proto_item_set_hidden(attr_count);
6418 					proto_item_set_generated(attr_count);
6419 				}
6420 			}
6421 
6422 			for (j = 0; j < 32; j++) {
6423 				bit_num = 32*i + j;
6424 				bit_set = ((bitmap >> j) & 1);
6425 				if (bit_set) {
6426 					if (bitmap_tree) {
6427 						if (bitmap_info->vse_names_ext) {
6428 							/* Append this attribute name to the 'attr mask' header line */
6429 							proto_item_append_text(bitmap_tree, (first_attr ? " (%s" : ", %s"),
6430 								val_to_str_ext(bit_num, bitmap_info->vse_names_ext, "Unknown: %u"));
6431 							first_attr = FALSE;
6432 						}
6433 
6434 						/* Get correct item label */
6435 						if (bitmap_info->get_item_label)
6436 							hf_item = bitmap_info->get_item_label(bit_num);
6437 						else if (bitmap_info->hf_item_label)
6438 							hf_item = *bitmap_info->hf_item_label;
6439 
6440 						if (hf_item != -1) {
6441 							/* Display label */
6442 							attr_item = proto_tree_add_uint(bitmap_tree, hf_item, tvb, offset, 0, bit_num);
6443 						}
6444 					}
6445 
6446 					attr_offset = offset;
6447 
6448 					if (skip_attr_values && attr_item) {
6449 						/* Skip dissecting anymore attribute values since
6450 						 * a previous attribute value was not dissected */
6451 						attr_tree = proto_item_add_subtree(attr_item, ett_nfs4_bitmap);
6452 						expert_add_info(pinfo, attr_tree, &ei_nfs_bitmap_skip_value);
6453 					} else if (type == NFS4_BITMAP_VALUES && attr_item) {
6454 						/* Display bit value */
6455 						attr_tree = proto_item_add_subtree(attr_item, ett_nfs4_bitmap);
6456 						if (bitmap_info->dissect_battr)
6457 							offset = bitmap_info->dissect_battr(tvb, offset, pinfo, civ,
6458 									attr_tree, attr_item, bit_num, bitmap_info->battr_data);
6459 						if (offset == attr_offset) {
6460 							/* No value was dissected, this attribute is most likely not
6461 							 * supported yet so stop dissecting the rest of the bitmap data */
6462 							expert_add_info(pinfo, attr_tree, &ei_nfs_bitmap_no_dissector);
6463 							skip_attr_values = TRUE;
6464 						}
6465 					}
6466 
6467 					if (attr_item)
6468 						proto_item_set_len(attr_item, offset - attr_offset);
6469 				}
6470 			}
6471 
6472 			if (bitmap_tree && !first_attr)
6473 				proto_item_append_text(bitmap_tree, ")");
6474 		}
6475 		mask_offset += 4;
6476 	}
6477 
6478 	if (type == NFS4_BITMAP_VALUES) {
6479 		count = end_offset - offset;
6480 		if (bitmap_info->hf_btmap_data && offset == (int)opaque_offset) {
6481 			/* Display opaque data */
6482 			offset = dissect_nfsdata(tvb, offset-4, name_tree, *bitmap_info->hf_btmap_data);
6483 		} else if (count == opaque_padding) {
6484 			/* Everything is good, just consume the padding bytes */
6485 			offset += opaque_padding;
6486 		} else if (count > 0) {
6487 			/* There are still bytes remaining from the opaque
6488 			 * just consume the bytes */
6489 			expert_add_info(pinfo, name_tree, &ei_nfs_bitmap_undissected_data);
6490 			offset = dissect_rpc_bytes(tvb, name_tree, hf_nfs4_bitmap_data, offset, count, FALSE, NULL);
6491 		}
6492 	}
6493 
6494 	return offset;
6495 }
6496 
6497 
6498 /*
6499  * When using RPC-over-RDMA, certain opaque data are eligible for DDP
6500  * (direct data placement), so these must be reduced by sending just
6501  * the opaque length with the rest of the NFS packet and the opaque
6502  * data is sent separately using RDMA (RFC 8267).
6503  */
6504 static int
dissect_nfsdata_reduced(rdma_reduce_type_t rtype,tvbuff_t * tvb,int offset,proto_tree * tree,int hf,const char ** name)6505 dissect_nfsdata_reduced(rdma_reduce_type_t rtype, tvbuff_t *tvb, int offset,
6506 			proto_tree *tree, int hf, const char **name)
6507 {
6508 	if (rpcrdma_is_reduced()) {
6509 		/*
6510 		 * The opaque data is reduced so just increment the offset
6511 		 * since there is no actual data yet.
6512 		 */
6513 		offset += 4;
6514 		/* Add offset (from the end) where the opaque data should be */
6515 		rpcrdma_insert_offset(tvb_reported_length_remaining(tvb, offset));
6516 		if (name) {
6517 			/* Return non-NULL string */
6518 			*name = "";
6519 		}
6520 	} else {
6521 		/* No data reduction, dissect the opaque data */
6522 		switch (rtype) {
6523 			case R_UTF8STRING:
6524 				offset = dissect_nfs_utf8string(tvb, offset, tree, hf, name);
6525 				break;
6526 			case R_NFS2_PATH:
6527 				offset = dissect_path(tvb, offset, tree, hf, name);
6528 				break;
6529 			case R_NFS3_PATH:
6530 				offset = dissect_nfs3_path(tvb, offset, tree, hf, name);
6531 				break;
6532 			case R_NFSDATA:
6533 				offset = dissect_nfsdata(tvb, offset, tree, hf);
6534 				break;
6535 		}
6536 	}
6537 	return offset;
6538 }
6539 
6540 
6541 static int
dissect_nfs4_deviceid(tvbuff_t * tvb,int offset,proto_tree * tree)6542 dissect_nfs4_deviceid(tvbuff_t *tvb, int offset, proto_tree *tree)
6543 {
6544 	proto_tree_add_item(tree, hf_nfs4_deviceid, tvb, offset, 16, ENC_NA);
6545 	offset += 16;
6546 	return offset;
6547 }
6548 
6549 
6550 static int
dissect_nfs4_sessionid(tvbuff_t * tvb,int offset,proto_tree * tree)6551 dissect_nfs4_sessionid(tvbuff_t *tvb, int offset, proto_tree *tree)
6552 {
6553 	proto_tree_add_item(tree, hf_nfs4_sessionid, tvb, offset, 16, ENC_NA);
6554 	offset += 16;
6555 	return offset;
6556 }
6557 
6558 
6559 static int
dissect_nfs4_specdata(tvbuff_t * tvb,int offset,proto_tree * tree)6560 dissect_nfs4_specdata(tvbuff_t *tvb, int offset, proto_tree *tree)
6561 {
6562 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_specdata1, offset);
6563 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_specdata2, offset);
6564 	return offset;
6565 }
6566 
6567 static const value_string names_ftype4[] = {
6568 	{	NF4REG,		"NF4REG"	},
6569 	{	NF4DIR,		"NF4DIR"	},
6570 	{	NF4BLK,		"NF4BLK"	},
6571 	{	NF4CHR,		"NF4CHR"	},
6572 	{	NF4LNK,		"NF4LNK"	},
6573 	{	NF4SOCK,	"NF4SOCK"	},
6574 	{	NF4FIFO,	"NF4FIFO"	},
6575 	{	NF4ATTRDIR,	"NF4ATTRDIR"	},
6576 	{	NF4NAMEDATTR,	"NF4NAMEDATTR"	},
6577 	{	0,	NULL }
6578 };
6579 
6580 
6581 static int
dissect_nfs4_lock_owner(tvbuff_t * tvb,int offset,proto_tree * tree)6582 dissect_nfs4_lock_owner(tvbuff_t *tvb, int offset, proto_tree *tree)
6583 {
6584 	proto_tree *newftree;
6585 
6586 	newftree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_nfs4_lock_owner, NULL, "Owner");
6587 	offset   = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
6588 	offset   = dissect_nfsdata(tvb, offset, newftree, hf_nfs4_lock_owner);
6589 
6590 	return offset;
6591 }
6592 
6593 
6594 static int
dissect_nfs4_pathname(tvbuff_t * tvb,int offset,proto_tree * tree)6595 dissect_nfs4_pathname(tvbuff_t *tvb, int offset, proto_tree *tree)
6596 {
6597 	guint32	    comp_count, i;
6598 	proto_item *fitem;
6599 	proto_tree *newftree;
6600 
6601 	fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_pathname_components, tvb, offset, 4, ENC_BIG_ENDIAN, &comp_count);
6602 	offset += 4;
6603 
6604 	newftree = proto_item_add_subtree(fitem, ett_nfs4_pathname);
6605 
6606 	for (i = 0; i < comp_count; i++)
6607 		offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, NULL);
6608 	return offset;
6609 }
6610 
6611 
6612 static int
dissect_nfs4_nfstime(tvbuff_t * tvb,int offset,proto_tree * tree)6613 dissect_nfs4_nfstime(tvbuff_t *tvb, int offset, proto_tree *tree)
6614 {
6615 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_time_seconds, offset);
6616 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_time_nseconds, offset);
6617 
6618 	return offset;
6619 }
6620 
6621 
6622 static const value_string names_time_how4[] = {
6623 #define SET_TO_SERVER_TIME4 0
6624 	{	SET_TO_SERVER_TIME4,	"SET_TO_SERVER_TIME4"	},
6625 #define SET_TO_CLIENT_TIME4 1
6626 	{	SET_TO_CLIENT_TIME4,	"SET_TO_CLIENT_TIME4"	},
6627 	{	0,	NULL	}
6628 };
6629 
6630 static int
dissect_nfs4_settime(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name _U_)6631 dissect_nfs4_settime(tvbuff_t *tvb, int offset,
6632 		     proto_tree *tree, const char *name _U_)
6633 {
6634 	guint32 set_it;
6635 
6636 	proto_tree_add_item_ret_uint(tree, hf_nfs4_time_how4, tvb, offset+0, 4, ENC_BIG_ENDIAN, &set_it);
6637 	offset += 4;
6638 
6639 	if (set_it == SET_TO_CLIENT_TIME4)
6640 		offset = dissect_nfs4_nfstime(tvb, offset, tree);
6641 
6642 	return offset;
6643 }
6644 
6645 
6646 static int
dissect_nfs4_fsid(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)6647 dissect_nfs4_fsid(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
6648 {
6649 	proto_tree *newftree;
6650 
6651 	newftree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_fsid, NULL, name);
6652 	offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_fsid_major, offset);
6653 	offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_fsid_minor, offset);
6654 	return offset;
6655 }
6656 
6657 /* ACE type values  */
6658 static const value_string names_acetype4[] = {
6659 #define ACE4_TYPE_ACCESS_ALLOWED  0x00000000
6660 	{	ACE4_TYPE_ACCESS_ALLOWED, "Access_Allowed"  },
6661 #define ACE4_TYPE_ACCESS_DENIED   0x00000001
6662 	{	ACE4_TYPE_ACCESS_DENIED,  "access_denied" },
6663 #define ACE4_TYPE_SYSTEM_AUDIT    0x00000002
6664 	{	ACE4_TYPE_SYSTEM_AUDIT,   "system_audit" },
6665 #define ACE4_TYPE_SYSTEM_ALARM    0x00000003
6666 	{	ACE4_TYPE_SYSTEM_ALARM,   "system_alarm" },
6667 	{	0,	NULL }
6668 };
6669 
6670 /* ACE flag values */
6671 #define ACE4_FLAG_FILE_INHERIT             0x00000001
6672 #define ACE4_FLAG_DIRECTORY_INHERIT        0x00000002
6673 #define ACE4_FLAG_NO_PROPAGATE_INHERIT     0x00000004
6674 #define ACE4_FLAG_INHERIT_ONLY             0x00000008
6675 #define ACE4_FLAG_SUCCESSFUL_ACCESS        0x00000010
6676 #define ACE4_FLAG_FAILED_ACCESS            0x00000020
6677 #define ACE4_FLAG_IDENTIFIER_GROUP         0x00000040
6678 #define ACE4_FLAG_INHERITED_ACE            0x00000080
6679 
6680 static int
dissect_nfs_aceflags4(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * ace_tree)6681 dissect_nfs_aceflags4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *ace_tree)
6682 {
6683     static int * const flags[] = {
6684         &hf_nfs4_aceflag_file_inherit,
6685         &hf_nfs4_aceflag_dir_inherit,
6686         &hf_nfs4_aceflag_no_prop_inherit,
6687         &hf_nfs4_aceflag_inherit_only,
6688         &hf_nfs4_aceflag_successful_access,
6689         &hf_nfs4_aceflag_failed_access,
6690         &hf_nfs4_aceflag_id_group,
6691         &hf_nfs4_aceflag_inherited_ace,
6692         NULL
6693     };
6694 
6695     proto_tree_add_bitmask(ace_tree, tvb, offset, hf_nfs4_aceflags, ett_nfs4_aceflag, flags, ENC_BIG_ENDIAN);
6696 
6697     offset += 4;
6698     return offset;
6699 }
6700 
6701 
6702 /* ACE4 permissions for files */
6703 static const value_string  acemask4_perms_file[] = {
6704 #define ACE4_READ_DATA             0x00000001
6705 	{	ACE4_READ_DATA,            "Read_Data"  },
6706 #define ACE4_WRITE_DATA            0x00000002
6707 	{	ACE4_WRITE_DATA,           "Write_Data" },
6708 #define ACE4_APPEND_DATA           0x00000004
6709 	{	ACE4_APPEND_DATA,          "Append_Data"  },
6710 	{	0, NULL }
6711 };
6712 /* Abbreviated ACE4 permissions for files */
6713 static const value_string  acemask4_abbrev_perms_file[] = {
6714 	{	ACE4_READ_DATA,            "RdData"  },
6715 	{	ACE4_WRITE_DATA,           "WrData" },
6716 	{	ACE4_APPEND_DATA,          "AppData"  },
6717 	{	0, NULL }
6718 };
6719 
6720 /* ACE4 permissions for dirs */
6721 static const value_string  acemask4_perms_dir[] = {
6722 #define ACE4_LIST_DIRECTORY        0x00000001
6723 	{	ACE4_LIST_DIRECTORY,       "List_Dir" },
6724 #define ACE4_ADD_FILE              0x00000002
6725 	{	ACE4_ADD_FILE,             "Add_File" },
6726 #define ACE4_ADD_SUBDIRECTORY      0x00000004
6727 	{	ACE4_ADD_SUBDIRECTORY,     "Add_Subdir" },
6728 	{	0, NULL }
6729 };
6730 /* Abbreviated ACE4 permissions for dirs */
6731 static const value_string  acemask4_abbrev_perms_dir[] = {
6732 	{	ACE4_LIST_DIRECTORY,       "LstDir" },
6733 	{	ACE4_ADD_FILE,             "AddFile" },
6734 	{	ACE4_ADD_SUBDIRECTORY,     "AddSubD" },
6735 	{	0, NULL }
6736 };
6737 
6738 /* ACE4 permissions for objects of unknown type */
6739 static const value_string  acemask4_perms_unkwn[] = {
6740 	{	ACE4_READ_DATA,            "Read_Data / List_Dir" },
6741 	{	ACE4_WRITE_DATA,           "Write_Data / Add_File" },
6742 	{	ACE4_APPEND_DATA,          "Append_Data / Add_SubDir" },
6743 	{	0, NULL }
6744 };
6745 /* Abbreviated ACE4 permissions for objects of unknown type */
6746 static const value_string  acemask4_abbrev_perms_unkwn[] = {
6747 	{	ACE4_READ_DATA,            "RdData/LstDir" },
6748 	{	ACE4_WRITE_DATA,           "WrData/AddFile" },
6749 	{	ACE4_APPEND_DATA,          "AppData/AddSubD" },
6750 	{	0, NULL }
6751 };
6752 
6753 /* ACE4 permissions for object types 0x8 and above */
6754 static const value_string  acemask4_perms_8_and_above[] = {
6755 #define ACE4_READ_NAMED_ATTRS      0x00000008
6756 	{	ACE4_READ_NAMED_ATTRS,     "Read_Named_Attrs" },
6757 #define ACE4_WRITE_NAMED_ATTRS     0x00000010
6758 	{	ACE4_WRITE_NAMED_ATTRS,    "Write_Named_Attrs" },
6759 #define ACE4_EXECUTE               0x00000020
6760 	{	ACE4_EXECUTE,              "Execute" },
6761 #define ACE4_DELETE_CHILD          0x00000040
6762 	{	ACE4_DELETE_CHILD,         "Delete_Child" },
6763 #define ACE4_READ_ATTRIBUTES       0x00000080
6764 	{	ACE4_READ_ATTRIBUTES,      "Read_Attributes" },
6765 #define ACE4_WRITE_ATTRIBUTES      0x00000100
6766 	{	ACE4_WRITE_ATTRIBUTES,     "Write_Attributes" },
6767 #define ACE4_WRITE_RETENTION       0x00000200
6768 	{	ACE4_WRITE_RETENTION,      "Write_Retention" },
6769 #define ACE4_WRITE_RETENTION_HOLD  0x00000400
6770 	{	ACE4_WRITE_RETENTION_HOLD, "Write_Retention_Hold" },
6771 #define ACE4_DELETE                0x00010000
6772 	{	ACE4_DELETE,               "Delete" },
6773 #define ACE4_READ_ACL              0x00020000
6774 	{	ACE4_READ_ACL,             "Read_ACL" },
6775 #define ACE4_WRITE_ACL             0x00040000
6776 	{	ACE4_WRITE_ACL,            "Write_ACL" },
6777 #define ACE4_WRITE_OWNER           0x00080000
6778 	{	ACE4_WRITE_OWNER,          "Write_Owner" },
6779 #define ACE4_SYNCHRONIZE           0x00100000
6780 	{	ACE4_SYNCHRONIZE,          "Synchronize" },
6781 	{	0, NULL }
6782 };
6783 static value_string_ext acemask4_perms_8_and_above_ext = VALUE_STRING_EXT_INIT(acemask4_perms_8_and_above);
6784 
6785 /* Abbreviated ACE4 permissions for object types 0x8 and above */
6786 static const value_string  acemask4_abbrev_perms_8_and_above[] = {
6787 	{	ACE4_READ_NAMED_ATTRS,     "RdNamAt" },
6788 	{	ACE4_WRITE_NAMED_ATTRS,    "WrNamAt" },
6789 	{	ACE4_EXECUTE,              "Exec" },
6790 	{	ACE4_DELETE_CHILD,         "DelChld" },
6791 	{	ACE4_READ_ATTRIBUTES,      "RdAttrs" },
6792 	{	ACE4_WRITE_ATTRIBUTES,     "WrAttrs" },
6793 	{	ACE4_WRITE_RETENTION,      "WrRet" },
6794 	{	ACE4_WRITE_RETENTION_HOLD, "WrRetHld" },
6795 	{	ACE4_DELETE,               "Del" },
6796 	{	ACE4_READ_ACL,             "RdACL" },
6797 	{	ACE4_WRITE_ACL,            "WrACL" },
6798 	{	ACE4_WRITE_OWNER,          "WrOwn" },
6799 	{	ACE4_SYNCHRONIZE,          "Sync" },
6800 	{	0, NULL }
6801 };
6802 static value_string_ext acemask4_abbrev_perms_8_and_above_ext = VALUE_STRING_EXT_INIT(acemask4_abbrev_perms_8_and_above);
6803 
6804 static int
dissect_nfs4_acemask(tvbuff_t * tvb,int offset,proto_tree * ace_tree,guint32 acetype4,guint32 obj_type)6805 dissect_nfs4_acemask(tvbuff_t *tvb, int offset, proto_tree *ace_tree, guint32 acetype4, guint32 obj_type)
6806 {
6807 	const gchar *type	 = NULL;
6808 	const gchar *atype	 = NULL;
6809 	guint32	     acemask	 = tvb_get_ntohl(tvb, offset);
6810 	guint32	     acemask_bit = 1;
6811 	gboolean     first_perm	 = TRUE;
6812 	proto_item  *acemask_item;
6813 	proto_tree  *acemask_tree;
6814 
6815 	acemask_item = proto_tree_add_uint(ace_tree, hf_nfs4_acemask, tvb, offset, 4, acemask);
6816 	acemask_tree = proto_item_add_subtree(acemask_item, ett_nfs4_acemask);
6817 	proto_item_append_text(acemask_item, "  (");
6818 
6819 	while (acemask_bit <= ACE4_SYNCHRONIZE)
6820 	{
6821 		if (acemask_bit & acemask) {
6822 			if (acemask_bit <= 0x4) {
6823 				if (obj_type) {
6824 					if  (obj_type == NF4REG) {
6825 						type = val_to_str(acemask_bit, acemask4_perms_file, "Unknown: %u");
6826 						atype = val_to_str(acemask_bit, acemask4_abbrev_perms_file, "Unknown: %u");
6827 					} else if (obj_type == NF4DIR) {
6828 						type = val_to_str(acemask_bit, acemask4_perms_dir, "Unknown: %u");
6829 						atype = val_to_str(acemask_bit, acemask4_abbrev_perms_dir, "Unknown: %u");
6830 					}
6831 				} else {
6832 					type = val_to_str(acemask_bit, acemask4_perms_unkwn, "Unknown: %u");
6833 					atype = val_to_str(acemask_bit, acemask4_abbrev_perms_unkwn, "Unknown: %u");
6834 				}
6835 			} else {
6836 				type = val_to_str_ext(acemask_bit, &acemask4_perms_8_and_above_ext, "Unknown: %u");
6837 				atype = val_to_str_ext(acemask_bit, &acemask4_abbrev_perms_8_and_above_ext, "Unknown: %u");
6838 			}
6839 			proto_tree_add_uint_format(acemask_tree, hf_nfs4_ace_permission, tvb, offset, 4,
6840 				acemask_bit, "%s: %s (0x%08x)", val_to_str(acetype4, names_acetype4, "Unknown: %u"), type, acemask_bit);
6841 			proto_item_append_text(acemask_item, first_perm ? "%s" : ", %s", atype);
6842 			first_perm = FALSE;
6843 		}
6844 		acemask_bit <<= 1;
6845 	}
6846 	proto_item_append_text(acemask_item, ")");
6847 
6848 	offset += 4;
6849 
6850 	return offset;
6851 }
6852 
6853 /* Decode exactly one ACE (type, flags, mask, permissions, and who) */
6854 static int
dissect_nfs4_ace(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,int ace_number,guint32 obj_type)6855 dissect_nfs4_ace(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,	proto_tree *tree, int ace_number,
6856 				 guint32 obj_type)
6857 {
6858 	guint32	    acetype4 = 0;
6859 	const char *acetype4_str;
6860 	proto_tree *ace_tree = NULL;
6861 
6862 	if (tree) {
6863 		proto_item *ace_item = NULL;
6864 
6865 		acetype4 = tvb_get_ntohl(tvb, offset);
6866 		acetype4_str = val_to_str(acetype4, names_acetype4, "Unknown: %u");
6867 
6868 		/* Display the ACE type and create a subtree for this ACE */
6869 		if (ace_number == 0) {
6870 			ace_item = proto_tree_add_uint_format(tree, hf_nfs4_acetype, tvb, offset, 4,
6871 				acetype4, "ACE Type: %s (%u)", acetype4_str, acetype4);
6872 		} else {
6873 			ace_item = proto_tree_add_uint_format(tree, hf_nfs4_acetype, tvb, offset, 4,
6874 				acetype4, "%u. ACE Type: %s (%u)", ace_number, acetype4_str, acetype4);
6875 		}
6876 		ace_tree = proto_item_add_subtree(ace_item, ett_nfs4_ace);
6877 	}
6878 
6879 	offset += 4;
6880 
6881 	if (tree) {
6882 		offset = dissect_nfs_aceflags4(tvb, offset, pinfo, ace_tree);
6883 		offset = dissect_nfs4_acemask(tvb, offset, ace_tree, acetype4, obj_type);
6884 	} else {
6885 		offset += 8;
6886 	}
6887 
6888 	offset = dissect_nfs_utf8string(tvb, offset, ace_tree, hf_nfs4_who, NULL);
6889 
6890 	return offset;
6891 }
6892 
6893 #define ACL4_AUTO_INHERIT	0x00000001
6894 #define ACL4_PROTECTED		0x00000002
6895 #define ACL4_DEFAULTED		0x00000004
6896 
6897 static int * const aclflags_fields[] = {
6898 	&hf_nfs4_aclflag_auto_inherit,
6899 	&hf_nfs4_aclflag_protected,
6900 	&hf_nfs4_aclflag_defaulted,
6901 	NULL
6902 };
6903 
6904 static int
dissect_nfs4_aclflags(tvbuff_t * tvb,int offset,proto_tree * tree)6905 dissect_nfs4_aclflags(tvbuff_t *tvb, int offset, proto_tree *tree)
6906 {
6907 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_aclflags,
6908 		ett_nfs4_aclflag, aclflags_fields, ENC_BIG_ENDIAN);
6909 	offset += 4;
6910 
6911 	return offset;
6912 }
6913 
6914 static int
dissect_nfs4_fattr_acl(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_item * attr_item,proto_tree * tree,guint32 obj_type,guint32 attr_num)6915 dissect_nfs4_fattr_acl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_item *attr_item,
6916 		       proto_tree *tree, guint32 obj_type, guint32 attr_num)
6917 {
6918 	guint32 num_aces;
6919 	guint32 ace_number;
6920 
6921 	if (attr_num != FATTR4_ACL)
6922 		offset = dissect_nfs4_aclflags(tvb, offset, tree);
6923 
6924 	num_aces = tvb_get_ntohl(tvb, offset);
6925 	if (tree && num_aces > 0) {
6926 		proto_tree_add_uint(tree, hf_nfs4_num_aces, tvb, offset, 4, num_aces);
6927 		proto_item_append_text(attr_item, " (%u ACEs)", num_aces);
6928 	}
6929 	offset += 4;
6930 
6931 	/* Tree or not, this for loop is required due dissect_nfs_utf8string() call */
6932 	for (ace_number = 1; ace_number<=num_aces; ace_number++)
6933 		offset = dissect_nfs4_ace(tvb, offset, pinfo, tree, ace_number, obj_type);
6934 
6935 	return offset;
6936 }
6937 
6938 #define ACL4_SUPPORT_ALLOW_ACL	0x00000001
6939 #define ACL4_SUPPORT_DENY_ACL	0x00000002
6940 #define ACL4_SUPPORT_AUDIT_ACL	0x00000004
6941 #define ACL4_SUPPORT_ALARM_ACL	0x00000008
6942 
6943 static int * const aclsupport_fields[] = {
6944 	&hf_nfs4_aclsupport_allow_acl,
6945 	&hf_nfs4_aclsupport_deny_acl,
6946 	&hf_nfs4_aclsupport_audit_acl,
6947 	&hf_nfs4_aclsupport_alarm_acl,
6948 	NULL
6949 };
6950 
6951 static int
dissect_nfs4_fattr_aclsupport(tvbuff_t * tvb,int offset,proto_tree * tree)6952 dissect_nfs4_fattr_aclsupport(tvbuff_t *tvb, int offset, proto_tree *tree)
6953 {
6954 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_fattr_aclsupport,
6955 		ett_nfs4_fattr_aclsupport, aclsupport_fields, ENC_BIG_ENDIAN);
6956 	offset += 4;
6957 
6958 	return offset;
6959 }
6960 
6961 static int
dissect_nfs4_fh(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name,guint32 * hash,rpc_call_info_value * civ)6962 dissect_nfs4_fh(tvbuff_t *tvb, int offset, packet_info *pinfo,
6963 		proto_tree *tree, const char *name, guint32 *hash, rpc_call_info_value *civ)
6964 {
6965 	return dissect_nfs3_fh(tvb, offset, pinfo, tree, name, hash, civ);
6966 }
6967 
6968 
6969 static int
dissect_nfs4_server(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)6970 dissect_nfs4_server(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
6971 {
6972 	return dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_server, NULL);
6973 }
6974 
6975 
6976 static int
dissect_nfs4_fs_location(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)6977 dissect_nfs4_fs_location(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
6978 			 proto_tree *tree, void *data _U_)
6979 {
6980 	proto_tree *newftree;
6981 
6982 	newftree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_fs_location, NULL, "fs_location4");
6983 
6984 	offset = dissect_rpc_array(tvb, pinfo, newftree, offset, dissect_nfs4_server, hf_nfs4_servers);
6985 	offset = dissect_nfs4_pathname(tvb, offset, newftree);
6986 
6987 	return offset;
6988 }
6989 
6990 
6991 static int
dissect_nfs4_fs_locations(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,const char * name)6992 dissect_nfs4_fs_locations(tvbuff_t *tvb, packet_info *pinfo, int offset,
6993 			  proto_tree *tree, const char *name)
6994 {
6995 	proto_tree *newftree;
6996 
6997 	newftree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_fs_locations, NULL, name);
6998 
6999 	offset = dissect_nfs4_pathname(tvb, offset, newftree);
7000 
7001 	offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
7002 		dissect_nfs4_fs_location, hf_nfs4_fslocation);
7003 
7004 	return offset;
7005 }
7006 
7007 /* RFC5661 - '14.4. UTF-8 Capabilities' */
7008 #define FSCHARSET_CAP4_CONTAINS_NON_UTF8	0x00000001
7009 #define FSCHARSET_CAP4_ALLOWS_ONLY_UTF8		0x00000002
7010 
7011 static int
dissect_nfs4_fattr_fs_charset_cap(tvbuff_t * tvb,int offset,proto_tree * tree)7012 dissect_nfs4_fattr_fs_charset_cap(tvbuff_t *tvb, int offset, proto_tree *tree)
7013 {
7014 	int * const fs_charset_cap_fields[] = {
7015 		&hf_nfs4_fs_charset_cap_nonutf8,
7016 		&hf_nfs4_fs_charset_cap_utf8,
7017 		NULL
7018 	};
7019 
7020 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_fattr_fs_charset_cap,
7021 		ett_nfs4_fattr_fs_charset_cap, fs_charset_cap_fields, ENC_BIG_ENDIAN);
7022 	offset += 4;
7023 
7024 	return offset;
7025 }
7026 
7027 static int
dissect_nfs4_mode(tvbuff_t * tvb,int offset,proto_tree * tree)7028 dissect_nfs4_mode(tvbuff_t *tvb, int offset, proto_tree *tree)
7029 {
7030 	return dissect_nfs2_mode(tvb, offset, tree);
7031 }
7032 
7033 #define FH4_PERSISTENT 0x00000000
7034 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001
7035 #define FH4_VOLATILE_ANY 0x00000002
7036 #define FH4_VOL_MIGRATION 0x00000004
7037 #define FH4_VOL_RENAME 0x00000008
7038 
7039 static const value_string nfs4_fattr4_fh_expire_type_names[] = {
7040 	{ FH4_PERSISTENT, "FH4_PERSISTENT" },
7041 	{ 0, NULL }
7042 };
7043 
7044 static int * const nfs4_fattr_fh_expire_type_fields[] = {
7045 	&hf_nfs4_fattr_fh_expiry_noexpire_with_open,
7046 	&hf_nfs4_fattr_fh_expiry_volatile_any,
7047 	&hf_nfs4_fattr_fh_expiry_vol_migration,
7048 	&hf_nfs4_fattr_fh_expiry_vol_rename,
7049 	NULL
7050 };
7051 
7052 static int
dissect_nfs4_fattr_fh_expire_type(tvbuff_t * tvb,int offset,proto_tree * tree)7053 dissect_nfs4_fattr_fh_expire_type(tvbuff_t *tvb, int offset, proto_tree *tree)
7054 {
7055 	guint32     expire_type;
7056 
7057 	expire_type = tvb_get_ntohl(tvb, offset + 0);
7058 
7059 	if (expire_type == FH4_PERSISTENT)
7060 		proto_tree_add_item(tree, hf_nfs4_fattr_fh_expire_type, tvb, offset, 4, ENC_BIG_ENDIAN);
7061 	else
7062 		proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_fattr_fh_expire_type,
7063 			ett_nfs4_fattr_fh_expire_type, nfs4_fattr_fh_expire_type_fields,
7064 			ENC_BIG_ENDIAN);
7065 
7066 	offset += 4;
7067 
7068 	return offset;
7069 }
7070 
7071 
7072 static int
dissect_nfs_fs_layout_type(tvbuff_t * tvb,proto_tree * tree,int offset)7073 dissect_nfs_fs_layout_type(tvbuff_t *tvb, proto_tree *tree, int offset)
7074 {
7075 	guint count, i;
7076 
7077 	count = tvb_get_ntohl(tvb, offset);
7078 	offset += 4;
7079 
7080 	for (i = 0; i < count; i++)
7081 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
7082 
7083 	return offset;
7084 }
7085 
7086 
7087 static const value_string th4_names_file[] = {
7088 #define TH4_READ_SIZE             0
7089 	{	TH4_READ_SIZE,		"Read_Size"		},
7090 #define TH4_WRITE_SIZE            1
7091 	{	TH4_WRITE_SIZE,		"Write_Size"		},
7092 #define TH4_READ_IOSIZE           2
7093 	{	TH4_READ_IOSIZE,	"Read_IO_Size"		},
7094 #define TH4_WRITE_IOSIZE          3
7095 	{	TH4_WRITE_IOSIZE,	"Write_IO_Size"		},
7096 	{	0,	NULL	}
7097 };
7098 static value_string_ext th4_names_ext_file = VALUE_STRING_EXT_INIT(th4_names_file);
7099 
7100 
7101 /* Dissect the threshold_item4 bit attribute for the files layout type */
7102 static int
dissect_nfs4_threshold_item_file(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,rpc_call_info_value * civ _U_,proto_tree * attr_tree,proto_item * attr_item _U_,guint32 bit_num,void * battr_data _U_)7103 dissect_nfs4_threshold_item_file(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
7104 		rpc_call_info_value *civ _U_, proto_tree *attr_tree, proto_item *attr_item _U_,
7105 		guint32 bit_num, void *battr_data _U_)
7106 {
7107 	guint64 size;
7108 
7109 	switch (bit_num) {
7110 		case TH4_READ_SIZE:
7111 		case TH4_WRITE_SIZE:
7112 		case TH4_READ_IOSIZE:
7113 		case TH4_WRITE_IOSIZE:
7114 			size = tvb_get_ntoh64(tvb, offset);
7115 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_length, offset);
7116 			proto_item_append_text(attr_tree, " = %" G_GUINT64_FORMAT, size);
7117 			break;
7118 	}
7119 	return offset;
7120 }
7121 
7122 
7123 /* Dissect the threshold_item4 structure */
7124 static int
dissect_nfs4_threshold_item(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,void * data)7125 dissect_nfs4_threshold_item(tvbuff_t *tvb, int offset, packet_info *pinfo,
7126 				proto_tree *tree, void *data)
7127 {
7128 	guint32 layout_type;
7129 	static nfs4_bitmap_info_t *bitmap_info_p;
7130 
7131 	/* Bitmap info for the files layout type */
7132 	static nfs4_bitmap_info_t bitmap_info_files = {
7133 		.vse_names_ext = &th4_names_ext_file,
7134 		.dissect_battr = dissect_nfs4_threshold_item_file,
7135 		.hf_mask_label = &hf_nfs4_mdsthreshold_hint_mask,
7136 		.hf_item_label = &hf_nfs4_mdsthreshold_hint_file,
7137 		.hf_item_count = &hf_nfs4_mdsthreshold_hint_count,
7138 		.hf_mask_count = &hf_nfs4_mdsthreshold_mask_count
7139 	};
7140 
7141 	/* Bitmap info for an unsupported layout type,
7142 	 * just display the bitmap mask and its data */
7143 	static nfs4_bitmap_info_t bitmap_info_default = {
7144 		.hf_mask_label = &hf_nfs4_mdsthreshold_hint_mask,
7145 		.hf_mask_count = &hf_nfs4_mdsthreshold_mask_count,
7146 		.hf_btmap_data = &hf_nfs4_bitmap_data,
7147 	};
7148 
7149 	/* Get layout type */
7150 	layout_type = tvb_get_ntohl(tvb, offset);
7151 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
7152 
7153 	switch (layout_type) {
7154 		case LAYOUT4_NFSV4_1_FILES:
7155 			bitmap_info_p = &bitmap_info_files;
7156 			break;
7157 		default:
7158 			bitmap_info_p = &bitmap_info_default;
7159 			break;
7160 	}
7161 	return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, (rpc_call_info_value *)data, bitmap_info_p, NFS4_BITMAP_VALUES, NULL);
7162 }
7163 
7164 
7165 /* Dissect the fattr4_mdsthreshold structure */
7166 static int
dissect_nfs4_mdsthreshold(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree)7167 dissect_nfs4_mdsthreshold(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree)
7168 {
7169 	int mds_offset = offset;
7170 
7171 	offset = dissect_rpc_array(tvb, pinfo, tree, offset,
7172 		dissect_nfs4_threshold_item, hf_nfs4_mdsthreshold_item);
7173 	proto_item_set_len(tree, offset - mds_offset);
7174 
7175 	return offset;
7176 }
7177 
7178 
7179 static int
dissect_nfs4_security_label(tvbuff_t * tvb,proto_tree * tree,int offset)7180 dissect_nfs4_security_label(tvbuff_t *tvb, proto_tree *tree, int offset)
7181 {
7182 
7183 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_fattr_security_label_lfs, offset);
7184 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_fattr_security_label_pi, offset);
7185 	offset = dissect_nfs_utf8string(tvb, offset, tree,
7186 		hf_nfs4_fattr_security_label_context, NULL);
7187 
7188 	return offset;
7189 }
7190 
7191 static int
dissect_nfs4_mode_umask(tvbuff_t * tvb,proto_tree * tree,int offset)7192 dissect_nfs4_mode_umask(tvbuff_t *tvb, proto_tree *tree, int offset)
7193 {
7194 	offset = dissect_nfs4_mode(tvb, offset, tree);
7195 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_fattr_umask_mask, offset);
7196 	return offset;
7197 }
7198 
7199 #define FATTR4_BITMAP_ONLY 0
7200 #define FATTR4_DISSECT_VALUES 1
7201 
7202 #define CHANGE_TYPE_IS_MONOTONIC_INCR 0
7203 #define CHANGE_TYPE_IS_VERSION_COUNTER 1
7204 #define CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS 2
7205 #define CHANGE_TYPE_IS_TIME_METADATA 3
7206 #define CHANGE_TYPE_IS_UNDEFINED 4
7207 
7208 static const value_string names_nfs_change_attr_types[] =
7209 {
7210 	{	CHANGE_TYPE_IS_MONOTONIC_INCR,	"CHANGE_TYPE_IS_MONOTONIC_INCR"	},
7211 	{	CHANGE_TYPE_IS_VERSION_COUNTER,	"CHANGE_TYPE_IS_VERSION_COUNTER"	},
7212 	{	CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS,	"CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS"	},
7213 	{	CHANGE_TYPE_IS_TIME_METADATA,	"CHANGE_TYPE_IS_TIME_METADATA"	},
7214 	{	CHANGE_TYPE_IS_UNDEFINED,	"CHANGE_TYPE_IS_UNDEFINED"	},
7215 	{	0,	NULL	}
7216 };
7217 
7218 static int
7219 dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ);
7220 
7221 /* Display attribute as either required or recommended */
7222 static int
nfs4_fattr_item_label(guint32 attr_num)7223 nfs4_fattr_item_label(guint32 attr_num)
7224 {
7225 	return (attr_num <= FATTR4_RDATTR_ERROR ||
7226 		attr_num == FATTR4_FILEHANDLE ||
7227 		attr_num == FATTR4_SUPPATTR_EXCLCREAT) ?
7228 		hf_nfs4_reqd_attr: hf_nfs4_reco_attr;
7229 
7230 }
7231 
7232 /* Dissect the value of the attribute given by attr_num */
7233 static int
dissect_nfs4_fattr_value(tvbuff_t * tvb,int offset,packet_info * pinfo,rpc_call_info_value * civ,proto_tree * attr_tree,proto_item * attr_item,guint32 attr_num,void * battr_data)7234 dissect_nfs4_fattr_value(tvbuff_t *tvb, int offset, packet_info *pinfo,
7235 		rpc_call_info_value *civ, proto_tree *attr_tree,
7236 		proto_item *attr_item, guint32 attr_num, void *battr_data)
7237 {
7238 	guint32 *fattr_obj_type_p = (guint32 *)battr_data;
7239 	switch (attr_num) {
7240 		case FATTR4_SUPPORTED_ATTRS:
7241 		case FATTR4_SUPPATTR_EXCLCREAT:
7242 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, attr_tree, FATTR4_BITMAP_ONLY, civ);
7243 			break;
7244 
7245 		case FATTR4_TYPE:
7246 			*fattr_obj_type_p = tvb_get_ntohl(tvb, offset);
7247 			if (attr_tree)
7248 				proto_tree_add_item(attr_tree, hf_nfs4_ftype, tvb, offset, 4,
7249 					ENC_BIG_ENDIAN);
7250 			offset += 4;
7251 			break;
7252 
7253 		case FATTR4_FH_EXPIRE_TYPE:
7254 			offset = dissect_nfs4_fattr_fh_expire_type(tvb,	offset, attr_tree);
7255 			break;
7256 
7257 		case FATTR4_CHANGE:
7258 			offset = dissect_rpc_uint64(tvb, attr_tree,	hf_nfs4_changeid, offset);
7259 			break;
7260 
7261 		case FATTR4_SIZE:
7262 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_size, offset);
7263 			break;
7264 
7265 		case FATTR4_LINK_SUPPORT:
7266 			offset = dissect_rpc_bool(tvb,
7267 				attr_tree, hf_nfs4_fattr_link_support, offset);
7268 			break;
7269 
7270 		case FATTR4_SYMLINK_SUPPORT:
7271 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_symlink_support, offset);
7272 			break;
7273 
7274 		case FATTR4_NAMED_ATTR:
7275 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_named_attr, offset);
7276 			break;
7277 
7278 		case FATTR4_FSID:
7279 			offset = dissect_nfs4_fsid(tvb, offset,	attr_tree, "fattr4_fsid");
7280 			break;
7281 
7282 		case FATTR4_UNIQUE_HANDLES:
7283 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_unique_handles,	offset);
7284 			break;
7285 
7286 		case FATTR4_LEASE_TIME:
7287 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_lease_time, offset);
7288 			break;
7289 
7290 		case FATTR4_RDATTR_ERROR:
7291 			offset = dissect_nfs4_status(tvb, offset, attr_tree, NULL);
7292 			break;
7293 
7294 		case FATTR4_ACL:
7295 		case FATTR4_DACL:
7296 		case FATTR4_SACL:
7297 			offset = dissect_nfs4_fattr_acl(tvb, offset, pinfo, attr_item, attr_tree,
7298 				*fattr_obj_type_p, attr_num);
7299 			break;
7300 
7301 		case FATTR4_ACLSUPPORT:
7302 			offset = dissect_nfs4_fattr_aclsupport(tvb, offset, attr_tree);
7303 			break;
7304 
7305 		case FATTR4_ARCHIVE:
7306 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_archive, offset);
7307 			break;
7308 
7309 		case FATTR4_CANSETTIME:
7310 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_cansettime, offset);
7311 			break;
7312 
7313 		case FATTR4_CASE_INSENSITIVE:
7314 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_case_insensitive, offset);
7315 			break;
7316 
7317 		case FATTR4_CASE_PRESERVING:
7318 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_case_preserving, offset);
7319 			break;
7320 
7321 		case FATTR4_CHOWN_RESTRICTED:
7322 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_chown_restricted, offset);
7323 			break;
7324 
7325 		case FATTR4_FILEID:
7326 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_fileid, offset);
7327 			break;
7328 
7329 		case FATTR4_FILES_AVAIL:
7330 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_files_avail, offset);
7331 			break;
7332 
7333 		case FATTR4_FILEHANDLE:
7334 			offset = dissect_nfs4_fh(tvb, offset, pinfo, attr_tree, "fattr4_filehandle", NULL, civ);
7335 			break;
7336 
7337 		case FATTR4_FILES_FREE:
7338 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_files_free, offset);
7339 			break;
7340 
7341 		case FATTR4_FILES_TOTAL:
7342 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_files_total, offset);
7343 			break;
7344 
7345 		case FATTR4_FS_LOCATIONS:
7346 			offset = dissect_nfs4_fs_locations(tvb, pinfo, offset, attr_tree,
7347 				"fattr4_fs_locations");
7348 			break;
7349 
7350 		case FATTR4_HIDDEN:
7351 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_hidden, offset);
7352 			break;
7353 
7354 		case FATTR4_HOMOGENEOUS:
7355 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_homogeneous, offset);
7356 			break;
7357 
7358 		case FATTR4_MAXFILESIZE:
7359 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_maxfilesize, offset);
7360 			break;
7361 
7362 		case FATTR4_MAXLINK:
7363 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_maxlink, offset);
7364 			break;
7365 
7366 		case FATTR4_MAXNAME:
7367 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_maxname, offset);
7368 			break;
7369 
7370 		case FATTR4_MAXREAD:
7371 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_maxread, offset);
7372 			break;
7373 
7374 		case FATTR4_MAXWRITE:
7375 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_maxwrite, offset);
7376 			break;
7377 
7378 		case FATTR4_MIMETYPE:
7379 			offset = dissect_nfs_utf8string(tvb, offset, attr_tree,	hf_nfs4_fattr_mimetype,
7380 				NULL);
7381 			break;
7382 
7383 		case FATTR4_MODE:
7384 			offset = dissect_nfs4_mode(tvb,	offset, attr_tree);
7385 			break;
7386 
7387 		case FATTR4_NO_TRUNC:
7388 			offset = dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_no_trunc, offset);
7389 			break;
7390 
7391 		case FATTR4_NUMLINKS:
7392 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_numlinks, offset);
7393 			break;
7394 
7395 		case FATTR4_OWNER:
7396 			offset = dissect_nfs_utf8string(tvb, offset, attr_tree,	hf_nfs4_fattr_owner,
7397 				NULL);
7398 			break;
7399 
7400 		case FATTR4_OWNER_GROUP:
7401 			offset = dissect_nfs_utf8string(tvb, offset, attr_tree,
7402 				hf_nfs4_fattr_owner_group, NULL);
7403 			break;
7404 
7405 		case FATTR4_QUOTA_AVAIL_HARD:
7406 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_quota_hard, offset);
7407 			break;
7408 
7409 		case FATTR4_QUOTA_AVAIL_SOFT:
7410 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_quota_soft, offset);
7411 			break;
7412 
7413 		case FATTR4_QUOTA_USED:
7414 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_quota_used, offset);
7415 			break;
7416 
7417 		case FATTR4_RAWDEV:
7418 			offset = dissect_nfs4_specdata(tvb, offset, attr_tree);
7419 			break;
7420 
7421 		case FATTR4_SPACE_AVAIL:
7422 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_avail, offset);
7423 			break;
7424 
7425 		case FATTR4_SPACE_FREE:
7426 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_free, offset);
7427 			break;
7428 
7429 		case FATTR4_SPACE_TOTAL:
7430 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_total, offset);
7431 			break;
7432 
7433 		case FATTR4_SPACE_USED:
7434 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_used, offset);
7435 			break;
7436 
7437 		case FATTR4_SYSTEM:
7438 			if (attr_tree)
7439 				dissect_rpc_bool(tvb, attr_tree, hf_nfs4_fattr_system, offset);
7440 			offset += 4;
7441 			break;
7442 
7443 		case FATTR4_TIME_ACCESS:
7444 		case FATTR4_TIME_BACKUP:
7445 		case FATTR4_TIME_CREATE:
7446 		case FATTR4_TIME_DELTA:
7447 		case FATTR4_TIME_METADATA:
7448 		case FATTR4_TIME_MODIFY:
7449 		case FATTR4_DIR_NOTIF_DELAY:
7450 		case FATTR4_DIRENT_NOTIF_DELAY:
7451 		case FATTR4_TIME_DELEG_ACCESS:
7452 		case FATTR4_TIME_DELEG_MODIFY:
7453 			if (attr_tree)
7454 				dissect_nfs4_nfstime(tvb, offset, attr_tree);
7455 			offset += 12;
7456 			break;
7457 
7458 		case FATTR4_TIME_ACCESS_SET:
7459 		case FATTR4_TIME_MODIFY_SET:
7460 			offset = dissect_nfs4_settime(tvb, offset, attr_tree, "settime4");
7461 			break;
7462 
7463 		case FATTR4_MOUNTED_ON_FILEID:
7464 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_mounted_on_fileid,
7465 						 offset);
7466 			break;
7467 
7468 		case FATTR4_FS_LAYOUT_TYPE:
7469 			offset = dissect_nfs_fs_layout_type(tvb, attr_tree, offset);
7470 			break;
7471 
7472 		case FATTR4_LAYOUT_BLKSIZE:
7473 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_layout_blksize,
7474 						offset);
7475 			break;
7476 
7477 		case FATTR4_MDSTHRESHOLD:
7478 			offset = dissect_nfs4_mdsthreshold(tvb, pinfo, offset, attr_tree);
7479 			break;
7480 
7481 		case FATTR4_CLONE_BLOCKSIZE:
7482 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_clone_blocksize,
7483 						offset);
7484 			break;
7485 
7486 		case FATTR4_SPACE_FREED:
7487 			offset = dissect_rpc_uint64(tvb, attr_tree, hf_nfs4_fattr_space_freed,
7488 						offset);
7489 			break;
7490 
7491 		case FATTR4_CHANGE_ATTR_TYPE:
7492 			offset = dissect_rpc_uint32(tvb, attr_tree, hf_nfs4_fattr_change_attr_type,
7493 						offset);
7494 			break;
7495 
7496 		case FATTR4_SECURITY_LABEL:
7497 			offset = dissect_nfs4_security_label(tvb, attr_tree, offset);
7498 			break;
7499 
7500 		case FATTR4_MODE_UMASK:
7501 			offset = dissect_nfs4_mode_umask(tvb, attr_tree, offset);
7502 			break;
7503 
7504 		case FATTR4_XATTR_SUPPORT:
7505 			offset = dissect_rpc_bool(tvb,
7506 				attr_tree, hf_nfs4_fattr_xattr_support, offset);
7507 			break;
7508 
7509 		case FATTR4_OFFLINE:
7510 			offset = dissect_rpc_bool(tvb,
7511 				attr_tree, hf_nfs4_fattr_offline, offset);
7512 			break;
7513 
7514 		case FATTR4_FS_CHARSET_CAP:
7515 			offset = dissect_nfs4_fattr_fs_charset_cap(tvb, offset, attr_tree);
7516 			break;
7517 
7518 		default:
7519 			break;
7520 	}
7521 
7522 	return offset;
7523 }
7524 
7525 /* Display each attrmask bitmap and optionally dissect the value. */
7526 static int
dissect_nfs4_fattrs(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,int type,rpc_call_info_value * civ)7527 dissect_nfs4_fattrs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int type, rpc_call_info_value *civ)
7528 {
7529 	static guint32 fattr_obj_type = 0;
7530 	nfs4_bitmap_type_t bitmap_type;
7531 	static nfs4_bitmap_info_t bitmap_info = {
7532 		.vse_names_ext  = &fattr4_names_ext,
7533 		.dissect_battr  = dissect_nfs4_fattr_value,
7534 		.battr_data     = &fattr_obj_type,
7535 		.hf_mask_label  = &hf_nfs4_attr_mask,
7536 		.hf_item_count  = &hf_nfs4_attr_count,
7537 		.get_item_label = nfs4_fattr_item_label
7538 	};
7539 
7540 	fattr_obj_type = 0;
7541 	bitmap_type = (type == FATTR4_BITMAP_ONLY) ? NFS4_BITMAP_MASK : NFS4_BITMAP_VALUES;
7542 
7543 	return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, civ, &bitmap_info, bitmap_type, NULL);
7544 }
7545 
7546 static const value_string names_open4_share_access[] = {
7547 #define  OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE     0x0000
7548 	{ OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE, "OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE" },
7549 #define OPEN4_SHARE_ACCESS_READ 0x00000001
7550 	{ OPEN4_SHARE_ACCESS_READ, "OPEN4_SHARE_ACCESS_READ" },
7551 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002
7552 	{ OPEN4_SHARE_ACCESS_WRITE, "OPEN4_SHARE_ACCESS_WRITE" },
7553 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003
7554 	{ OPEN4_SHARE_ACCESS_BOTH, "OPEN4_SHARE_ACCESS_BOTH" },
7555 #define  OPEN4_SHARE_ACCESS_WANT_READ_DELEG        0x0100
7556 	{ OPEN4_SHARE_ACCESS_WANT_READ_DELEG, "OPEN4_SHARE_ACCESS_WANT_READ_DELEG" },
7557 #define  OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG       0x0200
7558 	{ OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG, "OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG" },
7559 #define  OPEN4_SHARE_ACCESS_WANT_ANY_DELEG         0x0300
7560 	{ OPEN4_SHARE_ACCESS_WANT_ANY_DELEG, "OPEN4_SHARE_ACCESS_WANT_ANY_DELEG" },
7561 #define  OPEN4_SHARE_ACCESS_WANT_NO_DELEG          0x0400
7562 	{ OPEN4_SHARE_ACCESS_WANT_NO_DELEG, "OPEN4_SHARE_ACCESS_WANT_NO_DELEG" },
7563 #define  OPEN4_SHARE_ACCESS_WANT_CANCEL            0x0500
7564 	{ OPEN4_SHARE_ACCESS_WANT_CANCEL, "OPEN4_SHARE_ACCESS_WANT_CANCEL" },
7565 #define OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
7566 	{ OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL,
7567 	  "OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL"},
7568 #define OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED  0x20000
7569 	{ OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED,
7570 	 "OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED"},
7571 #define OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS 0x100000
7572 	{OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS,
7573 	 "OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS"},
7574 	{ 0, NULL }
7575 };
7576 static value_string_ext names_open4_share_access_ext = VALUE_STRING_EXT_INIT(names_open4_share_access);
7577 
7578 static int
dissect_nfs4_open_share_access(tvbuff_t * tvb,int offset,proto_tree * tree)7579 dissect_nfs4_open_share_access(tvbuff_t *tvb, int offset, proto_tree *tree)
7580 {
7581 	proto_item *notify_item;
7582 	proto_tree *notify_tree;
7583 	guint	    share_access;
7584 	guint	    want_flags;
7585 	guint	    want_notify_flags;
7586 
7587 	want_notify_flags = tvb_get_ntohl(tvb, offset);
7588 	share_access = want_notify_flags & 0x3;
7589 	want_flags = want_notify_flags & 0xff00;
7590 	want_notify_flags &= 0x130000;
7591 	proto_tree_add_uint(tree, hf_nfs4_open_share_access, tvb, offset, 4, share_access);
7592 	if (want_flags)
7593 		proto_tree_add_uint(tree, hf_nfs4_want_flags, tvb, offset, 4, want_flags);
7594 	if (want_notify_flags) {
7595 		notify_item = proto_tree_add_uint(tree, hf_nfs4_want_notify_flags, tvb, offset, 4, want_notify_flags);
7596 
7597 		notify_tree = proto_item_add_subtree(notify_item, ett_nfs4_want_notify_flags);
7598 		proto_tree_add_item(notify_tree, hf_nfs4_want_signal_deleg_when_resrc_avail, tvb, offset, 4, ENC_BIG_ENDIAN);
7599 		proto_tree_add_item(notify_tree, hf_nfs4_want_push_deleg_when_uncontended, tvb, offset, 4, ENC_BIG_ENDIAN);
7600 	}
7601 	offset += 4;
7602 
7603 	return offset;
7604 }
7605 
7606 static const value_string names_open4_share_deny[] = {
7607 #define OPEN4_SHARE_DENY_NONE 0x00000000
7608 	{ OPEN4_SHARE_DENY_NONE, "OPEN4_SHARE_DENY_NONE" },
7609 #define OPEN4_SHARE_DENY_READ 0x00000001
7610 	{ OPEN4_SHARE_DENY_READ, "OPEN4_SHARE_DENY_READ" },
7611 #define OPEN4_SHARE_DENY_WRITE 0x00000002
7612 	{ OPEN4_SHARE_DENY_WRITE, "OPEN4_SHARE_DENY_WRITE" },
7613 #define OPEN4_SHARE_DENY_BOTH 0x00000003
7614 	{ OPEN4_SHARE_DENY_BOTH, "OPEN4_SHARE_DENY_BOTH" },
7615 	{ 0, NULL }
7616 };
7617 
7618 
7619 static int
dissect_nfs4_open_share_deny(tvbuff_t * tvb,int offset,proto_tree * tree)7620 dissect_nfs4_open_share_deny(tvbuff_t *tvb, int offset, proto_tree *tree)
7621 {
7622 	proto_tree_add_item(tree, hf_nfs4_open_share_deny, tvb, offset, 4, ENC_BIG_ENDIAN);
7623 	offset += 4;
7624 
7625 	return offset;
7626 }
7627 
7628 
7629 static int
dissect_nfs4_open_owner(tvbuff_t * tvb,int offset,proto_tree * tree)7630 dissect_nfs4_open_owner(tvbuff_t *tvb, int offset, proto_tree *tree)
7631 {
7632 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_clientid, offset);
7633 	offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_open_owner);
7634 
7635 	return offset;
7636 }
7637 
7638 
7639 static int
dissect_nfs4_open_claim_delegate_cur(tvbuff_t * tvb,int offset,proto_tree * tree)7640 dissect_nfs4_open_claim_delegate_cur(tvbuff_t *tvb, int offset,
7641 				     proto_tree *tree)
7642 {
7643 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
7644 	offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_component, NULL);
7645 
7646 	return offset;
7647 }
7648 
7649 #define CLAIM_NULL		0
7650 #define CLAIM_PREVIOUS		1
7651 #define CLAIM_DELEGATE_CUR	2
7652 #define CLAIM_DELEGATE_PREV	3
7653 #define CLAIM_FH		4
7654 #define CLAIM_DELEG_CUR_FH	5
7655 #define CLAIM_DELEG_CUR_PREV_FH	6
7656 
7657 static const value_string names_claim_type4[] = {
7658 	{	CLAIM_NULL,		 "CLAIM_NULL"  },
7659 	{	CLAIM_PREVIOUS,		 "CLAIM_PREVIOUS" },
7660 	{	CLAIM_DELEGATE_CUR,	 "CLAIM_DELEGATE_CUR" },
7661 	{	CLAIM_DELEGATE_PREV,	 "CLAIM_DELEGATE_PREV" },
7662 	{	CLAIM_FH,		 "CLAIM_FH" },
7663 	{	CLAIM_DELEG_CUR_FH,	 "CLAIM_DELEG_CUR_FH"},
7664 	{	CLAIM_DELEG_CUR_PREV_FH, "CLAIN_DELEG_CUR_PREV_FH"},
7665 	{	0, NULL }
7666 };
7667 
7668 /* XXX - need a better place to populate name than here, maybe? */
7669 static int
dissect_nfs4_open_claim(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,const char ** name,rpc_call_info_value * civ)7670 dissect_nfs4_open_claim(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
7671 	proto_tree *tree, const char **name, rpc_call_info_value *civ)
7672 {
7673 	guint	    open_claim_type4;
7674 	proto_item *fitem;
7675 	proto_tree *newftree = NULL;
7676 	guint32	    name_offset, name_len;
7677 
7678 	open_claim_type4 = tvb_get_ntohl(tvb, offset);
7679 	fitem = proto_tree_add_uint(tree, hf_nfs4_open_claim_type, tvb,
7680 				    offset+0, 4, open_claim_type4);
7681 	offset += 4;
7682 
7683 	if (open_claim_type4 == CLAIM_NULL) {
7684 		dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, name);
7685 		if (nfs_file_name_snooping) {
7686 
7687 			name_offset = offset+4;
7688 			name_len = tvb_get_ntohl(tvb, offset);
7689 
7690 			nfs_name_snoop_add_name(civ->xid, tvb,
7691 				name_offset, name_len, 0, 0, NULL);
7692 		}
7693 	}
7694 
7695 	newftree = proto_item_add_subtree(fitem, ett_nfs4_open_claim);
7696 
7697 	switch (open_claim_type4)
7698 	{
7699 		case CLAIM_NULL:
7700 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, name);
7701 			break;
7702 
7703 		case CLAIM_PREVIOUS:
7704 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_delegate_type, offset);
7705 			break;
7706 
7707 		case CLAIM_DELEGATE_CUR:
7708 			offset = dissect_nfs4_open_claim_delegate_cur(tvb, offset, newftree);
7709 			break;
7710 
7711 		case CLAIM_DELEGATE_PREV:
7712 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, NULL);
7713 			break;
7714 
7715 		default:
7716 			break;
7717 	}
7718 
7719 	return offset;
7720 }
7721 
7722 static const value_string names_createmode4[] = {
7723 	{	UNCHECKED4,	"UNCHECKED4" },
7724 	{	GUARDED4,	"GUARDED4" },
7725 	{	EXCLUSIVE4,	"EXCLUSIVE4" },
7726 	{	EXCLUSIVE4_1,	"EXCLUSIVE4_1" },
7727 	{	0, NULL }
7728 };
7729 
7730 
7731 static int
dissect_nfs4_createhow(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)7732 dissect_nfs4_createhow(tvbuff_t *tvb, int offset, packet_info *pinfo,
7733 		       proto_tree *tree, rpc_call_info_value *civ)
7734 {
7735 	guint mode;
7736 
7737 	mode = tvb_get_ntohl(tvb, offset);
7738 	proto_tree_add_uint(tree, hf_nfs4_createmode, tvb, offset, 4, mode);
7739 	offset += 4;
7740 
7741 	switch (mode)
7742 	{
7743 	case UNCHECKED4:
7744 	case GUARDED4:
7745 		offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ);
7746 		break;
7747 
7748 	case EXCLUSIVE4:
7749 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
7750 		break;
7751 
7752 	case EXCLUSIVE4_1:
7753 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
7754 		offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_DISSECT_VALUES, civ);
7755 		break;
7756 
7757 	default:
7758 		break;
7759 	}
7760 
7761 	return offset;
7762 }
7763 
7764 
7765 #define OPEN4_NOCREATE				0
7766 #define OPEN4_CREATE				1
7767 static const value_string names_opentype4[] = {
7768 	{	OPEN4_NOCREATE,	"OPEN4_NOCREATE"  },
7769 	{	OPEN4_CREATE,	"OPEN4_CREATE" },
7770 	{	0, NULL }
7771 };
7772 
7773 static int
dissect_nfs4_openflag(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)7774 dissect_nfs4_openflag(tvbuff_t *tvb, int offset, packet_info *pinfo,
7775 	proto_tree *tree, rpc_call_info_value *civ)
7776 {
7777 	guint	    opentype4;
7778 	proto_item *fitem;
7779 	proto_tree *newftree;
7780 
7781 	opentype4 = tvb_get_ntohl(tvb, offset);
7782 	fitem = proto_tree_add_uint(tree, hf_nfs4_opentype, tvb,
7783 		offset+0, 4, opentype4);
7784 	offset += 4;
7785 
7786 	newftree = proto_item_add_subtree(fitem, ett_nfs4_opentype);
7787 
7788 	switch (opentype4)
7789 	{
7790 		case OPEN4_CREATE:
7791 			offset = dissect_nfs4_createhow(tvb, offset, pinfo, newftree, civ);
7792 			break;
7793 
7794 		default:
7795 			break;
7796 	}
7797 
7798 	return offset;
7799 }
7800 
7801 
7802 static int
dissect_nfs4_clientaddr(tvbuff_t * tvb,int offset,proto_tree * tree)7803 dissect_nfs4_clientaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
7804 {
7805 	const char *universal_ip_address = NULL;
7806 	const char *protocol		 = NULL;
7807 	guint	b1, b2, b3, b4, b5, b6, b7, b8, b9, b10;
7808 	guint16 port;
7809 	int	addr_offset;
7810 	guint32 ipv4;
7811 	ws_in6_addr ipv6;
7812 	address addr;
7813 	proto_item* ti;
7814 
7815 	offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_netid, offset, &protocol);
7816 	addr_offset = offset;
7817 	offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_addr, offset, &universal_ip_address);
7818 
7819 	if (strlen(protocol) == 3 && strncmp(protocol, "tcp", 3) == 0) {
7820 		if (universal_ip_address && sscanf(universal_ip_address, "%u.%u.%u.%u.%u.%u",
7821 						   &b1, &b2, &b3, &b4, &b5, &b6) == 6) {
7822 			/* IPv4: h1.h2.h3.h4.p1.p2 */
7823 			port = (b5<<8) | b6;
7824 			ipv4 = g_htonl((b1<<24) | (b2<<16) | (b3<<8) | b4);
7825 			set_address(&addr, AT_IPv4, 4, &ipv4);
7826 			ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, ipv4, "IPv4 address %s, protocol=%s, port=%u",
7827 				address_to_str(wmem_packet_scope(), &addr), protocol, port);
7828 			proto_item_set_generated(ti);
7829 		} else if (universal_ip_address && sscanf(universal_ip_address, "%u.%u",
7830 						   &b1, &b2) == 2) {
7831 			/* Some clients (linux) sometimes send only the port. */
7832 			port = (b1<<8) | b2;
7833 			ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, 0, "ip address NOT SPECIFIED, protocol=%s, port=%u", protocol, port);
7834 			proto_item_set_generated(ti);
7835 		} else if (universal_ip_address && sscanf(universal_ip_address,
7836 						"%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x.%u.%u",
7837 						&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b10) == 10) {
7838 			port = (b9<<8) | b10;
7839 			memset(&ipv6, 0, sizeof(ipv6));
7840 			ipv6.bytes[0] = b1; ipv6.bytes[1] = b2; ipv6.bytes[2] = b3; ipv6.bytes[3] = b4;
7841 			ipv6.bytes[4] = b5; ipv6.bytes[5] = b6; ipv6.bytes[6] = b7; ipv6.bytes[7] = b8;
7842 			set_address(&addr, AT_IPv6, 16, &ipv6);
7843 			ti = proto_tree_add_ipv6_format(tree, hf_nfs4_universal_address_ipv6, tvb, addr_offset, offset-addr_offset, &ipv6, "IPv6 address %s, protocol=%s, port=%u",
7844 				address_to_str(wmem_packet_scope(), &addr), protocol, port);
7845 			proto_item_set_generated(ti);
7846 		} else {
7847 			ti = proto_tree_add_ipv4_format(tree, hf_nfs4_universal_address_ipv4, tvb, addr_offset, offset-addr_offset, 0, "Invalid address");
7848 			proto_item_set_generated(ti);
7849 		}
7850 	}
7851 	return offset;
7852 }
7853 
7854 
7855 static int
dissect_nfs4_cb_client4(tvbuff_t * tvb,int offset,proto_tree * tree)7856 dissect_nfs4_cb_client4(tvbuff_t *tvb, int offset, proto_tree *tree)
7857 {
7858 	proto_tree *cb_location;
7859 	proto_item *fitem;
7860 	int	    old_offset;
7861 
7862 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_cb_program, offset);
7863 	old_offset = offset;
7864 	cb_location = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "cb_location");
7865 
7866 	offset = dissect_nfs4_clientaddr(tvb, offset, cb_location);
7867 	proto_item_set_len(fitem, offset - old_offset);
7868 
7869 	return offset;
7870 }
7871 
7872 
7873 static const value_string names_stable_how4[] = {
7874 #define UNSTABLE4 0
7875 	{	UNSTABLE4,	"UNSTABLE4"	},
7876 #define DATA_SYNC4 1
7877 	{	DATA_SYNC4,	"DATA_SYNC4"	},
7878 #define FILE_SYNC4 2
7879 	{	FILE_SYNC4,	"FILE_SYNC4"	},
7880 	{	0,	NULL	}
7881 };
7882 
7883 static int
dissect_nfs4_stable_how(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)7884 dissect_nfs4_stable_how(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
7885 {
7886 	guint stable_how4;
7887 
7888 	stable_how4 = tvb_get_ntohl(tvb, offset);
7889 	proto_tree_add_uint_format(tree, hf_nfs4_stable_how, tvb,
7890 			offset+0, 4, stable_how4, "%s: %s (%u)", name,
7891 			val_to_str(stable_how4, names_stable_how4, "%u"), stable_how4);
7892 	offset += 4;
7893 
7894 	return offset;
7895 }
7896 
7897 static const value_string names_data_content[] = {
7898 	{	0,	"DATA"  },
7899 	{	1,	"HOLE"  },
7900 	{	0, NULL }
7901 };
7902 
7903 static const value_string names_setxattr_options[] = {
7904 	{	0,	"EITHER"  },
7905 	{	1,	"CREATE"  },
7906 	{	2,	"REPLACE"  },
7907 	{	0, NULL }
7908 };
7909 
7910 static int
dissect_nfs4_listxattr_names(tvbuff_t * tvb,int offset,proto_tree * tree)7911 dissect_nfs4_listxattr_names(tvbuff_t *tvb, int offset, proto_tree *tree)
7912 {
7913 	guint32	    comp_count, i;
7914 	proto_item *fitem;
7915 	proto_tree *newftree;
7916 
7917 	fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_listxattr_names_len, tvb, offset, 4, ENC_BIG_ENDIAN, &comp_count);
7918 	offset += 4;
7919 
7920 	newftree = proto_item_add_subtree(fitem, ett_nfs4_listxattr_names);
7921 
7922 	for (i = 0; i < comp_count; i++)
7923 		offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_xattrkey, NULL);
7924 	return offset;
7925 }
7926 
7927 /* NFSv4 Operations  */
7928 static const value_string names_nfs4_operation[] = {
7929 	{	NFS4_OP_ACCESS,                "ACCESS"  },
7930 	{	NFS4_OP_CLOSE,                 "CLOSE"  },
7931 	{	NFS4_OP_COMMIT,                "COMMIT"  },
7932 	{	NFS4_OP_CREATE,                "CREATE"  },
7933 	{	NFS4_OP_DELEGPURGE,            "DELEGPURGE"  },
7934 	{	NFS4_OP_DELEGRETURN,           "DELEGRETURN"  },
7935 	{	NFS4_OP_GETATTR,               "GETATTR"  },
7936 	{	NFS4_OP_GETFH,                 "GETFH"  },
7937 	{	NFS4_OP_LINK,                  "LINK"  },
7938 	{	NFS4_OP_LOCK,                  "LOCK"  },
7939 	{	NFS4_OP_LOCKT,                 "LOCKT"  },
7940 	{	NFS4_OP_LOCKU,                 "LOCKU"  },
7941 	{	NFS4_OP_LOOKUP,                "LOOKUP"  },
7942 	{	NFS4_OP_LOOKUPP,               "LOOKUPP"  },
7943 	{	NFS4_OP_NVERIFY,               "NVERIFY"  },
7944 	{	NFS4_OP_OPEN,                  "OPEN"  },
7945 	{	NFS4_OP_OPENATTR,              "OPENATTR"  },
7946 	{	NFS4_OP_OPEN_CONFIRM,          "OPEN_CONFIRM"  },
7947 	{	NFS4_OP_OPEN_DOWNGRADE,        "OPEN_DOWNGRADE"  },
7948 	{	NFS4_OP_PUTFH,                 "PUTFH"  },
7949 	{	NFS4_OP_PUTPUBFH,              "PUTPUBFH"  },
7950 	{	NFS4_OP_PUTROOTFH,             "PUTROOTFH"  },
7951 	{	NFS4_OP_READ,                  "READ"  },
7952 	{	NFS4_OP_READDIR,               "READDIR"  },
7953 	{	NFS4_OP_READLINK,              "READLINK"  },
7954 	{	NFS4_OP_REMOVE,                "REMOVE"  },
7955 	{	NFS4_OP_RENAME,                "RENAME"  },
7956 	{	NFS4_OP_RENEW,                 "RENEW"  },
7957 	{	NFS4_OP_RESTOREFH,             "RESTOREFH"  },
7958 	{	NFS4_OP_SAVEFH,                "SAVEFH"  },
7959 	{	NFS4_OP_SECINFO,               "SECINFO"  },
7960 	{	NFS4_OP_SETATTR,               "SETATTR"  },
7961 	{	NFS4_OP_SETCLIENTID,           "SETCLIENTID"  },
7962 	{	NFS4_OP_SETCLIENTID_CONFIRM,   "SETCLIENTID_CONFIRM"  },
7963 	{	NFS4_OP_VERIFY,                "VERIFY"  },
7964 	{	NFS4_OP_WRITE,                 "WRITE"  },
7965 	{	NFS4_OP_RELEASE_LOCKOWNER,     "RELEASE_LOCKOWNER"  },
7966 	{	NFS4_OP_BACKCHANNEL_CTL,       "BACKCHANNEL_CTL"  },
7967 	{	NFS4_OP_BIND_CONN_TO_SESSION,  "BIND_CONN_TO_SESSION"  },
7968 	{	NFS4_OP_EXCHANGE_ID,           "EXCHANGE_ID"  },
7969 	{	NFS4_OP_CREATE_SESSION,        "CREATE_SESSION"  },
7970 	{	NFS4_OP_DESTROY_SESSION,       "DESTROY_SESSION"  },
7971 	{	NFS4_OP_FREE_STATEID,          "FREE_STATEID"  },
7972 	{	NFS4_OP_GET_DIR_DELEGATION,    "GET_DIR_DELEGATION"  },
7973 	{	NFS4_OP_GETDEVINFO,            "GETDEVINFO"  },
7974 	{	NFS4_OP_GETDEVLIST,            "GETDEVLIST"  },
7975 	{	NFS4_OP_LAYOUTCOMMIT,          "LAYOUTCOMMIT"  },
7976 	{	NFS4_OP_LAYOUTGET,             "LAYOUTGET"  },
7977 	{	NFS4_OP_LAYOUTRETURN,          "LAYOUTRETURN"  },
7978 	{	NFS4_OP_SECINFO_NO_NAME,       "SECINFO_NO_NAME"  },
7979 	{	NFS4_OP_SEQUENCE,              "SEQUENCE"  },
7980 	{	NFS4_OP_SET_SSV,               "SET_SSV"  },
7981 	{	NFS4_OP_TEST_STATEID,          "TEST_STATEID"  },
7982 	{	NFS4_OP_WANT_DELEGATION,       "WANT_DELEG"  },
7983 	{	NFS4_OP_DESTROY_CLIENTID,      "DESTROY_CLIENTID"  },
7984 	{	NFS4_OP_RECLAIM_COMPLETE,      "RECLAIM_COMPLETE"  },
7985 	{	NFS4_OP_ALLOCATE,              "ALLOCATE"  },
7986 	{	NFS4_OP_COPY,                  "COPY"  },
7987 	{	NFS4_OP_COPY_NOTIFY,           "COPY_NOTIFY"  },
7988 	{	NFS4_OP_DEALLOCATE,            "DEALLOCATE"  },
7989 	{	NFS4_OP_IO_ADVISE,             "IO_ADVISE"  },
7990 	{	NFS4_OP_LAYOUTERROR,           "LAYOUTERROR"  },
7991 	{	NFS4_OP_LAYOUTSTATS,           "LAYOUTSTATS"  },
7992 	{	NFS4_OP_OFFLOAD_CANCEL,        "OFFLOAD_CANCEL"  },
7993 	{	NFS4_OP_OFFLOAD_STATUS,        "OFFLOAD_STATUS"  },
7994 	{	NFS4_OP_READ_PLUS,             "READ_PLUS"  },
7995 	{	NFS4_OP_SEEK,                  "SEEK"  },
7996 	{	NFS4_OP_WRITE_SAME,            "WRITE_SAME"  },
7997 	{	NFS4_OP_CLONE,                 "CLONE"  },
7998 	{	NFS4_OP_GETXATTR,              "GETXATTR"  },
7999 	{	NFS4_OP_SETXATTR,              "SETXATTR"  },
8000 	{	NFS4_OP_LISTXATTRS,            "LISTXATTRS"  },
8001 	{	NFS4_OP_REMOVEXATTR,           "REMOVEXATTR"  },
8002 	{	NFS4_OP_ILLEGAL,               "ILLEGAL"  },
8003 	{	0, NULL  }
8004 };
8005 
8006 static value_string_ext names_nfs4_operation_ext = VALUE_STRING_EXT_INIT(names_nfs4_operation);
8007 
8008 /* Each subtree number in this array corresponds to the associated item in the above
8009 *  'names_nfs4_operation array[]' array. */
8010 static gint *nfs4_operation_ett[] =
8011 {
8012 	 &ett_nfs4_access ,
8013 	 &ett_nfs4_close ,
8014 	 &ett_nfs4_commit ,
8015 	 &ett_nfs4_create ,
8016 	 &ett_nfs4_delegpurge ,
8017 	 &ett_nfs4_delegreturn ,
8018 	 &ett_nfs4_getattr ,
8019 	 &ett_nfs4_getfh ,
8020 	 &ett_nfs4_link ,
8021 	 &ett_nfs4_lock ,
8022 	 &ett_nfs4_lockt ,
8023 	 &ett_nfs4_locku ,
8024 	 &ett_nfs4_lookup ,
8025 	 &ett_nfs4_lookupp ,
8026 	 &ett_nfs4_nverify ,
8027 	 &ett_nfs4_open ,
8028 	 &ett_nfs4_openattr ,
8029 	 &ett_nfs4_open_confirm ,
8030 	 &ett_nfs4_open_downgrade ,
8031 	 &ett_nfs4_putfh ,
8032 	 &ett_nfs4_putpubfh ,
8033 	 &ett_nfs4_putrootfh ,
8034 	 &ett_nfs4_read ,
8035 	 &ett_nfs4_readdir ,
8036 	 &ett_nfs4_readlink ,
8037 	 &ett_nfs4_remove ,
8038 	 &ett_nfs4_rename ,
8039 	 &ett_nfs4_renew ,
8040 	 &ett_nfs4_restorefh ,
8041 	 &ett_nfs4_savefh ,
8042 	 &ett_nfs4_secinfo ,
8043 	 &ett_nfs4_setattr ,
8044 	 &ett_nfs4_setclientid ,
8045 	 &ett_nfs4_setclientid_confirm ,
8046 	 &ett_nfs4_verify ,
8047 	 &ett_nfs4_write,
8048 	 &ett_nfs4_release_lockowner,
8049 	 &ett_nfs4_backchannel_ctl,
8050 	 &ett_nfs4_bind_conn_to_session,
8051 	 &ett_nfs4_exchange_id,
8052 	 &ett_nfs4_create_session,
8053 	 &ett_nfs4_destroy_session,
8054 	 &ett_nfs4_free_stateid,
8055 	 NULL, /* get dir delegation */
8056 	 &ett_nfs4_getdevinfo,
8057 	 &ett_nfs4_getdevlist,
8058 	 &ett_nfs4_layoutcommit,
8059 	 &ett_nfs4_layoutget,
8060 	 &ett_nfs4_layoutreturn,
8061 	 &ett_nfs4_secinfo_no_name,
8062 	 &ett_nfs4_sequence,
8063 	 NULL, /* set ssv */
8064 	 &ett_nfs4_test_stateid,
8065 	 NULL, /* want delegation */
8066 	 &ett_nfs4_destroy_clientid,
8067 	 &ett_nfs4_reclaim_complete,
8068 	 &ett_nfs4_allocate,
8069 	 &ett_nfs4_copy,
8070 	 &ett_nfs4_copy_notify,
8071 	 &ett_nfs4_deallocate,
8072 	 &ett_nfs4_io_advise,
8073 	 &ett_nfs4_layouterror,
8074 	 &ett_nfs4_layoutstats,
8075 	 &ett_nfs4_offload_cancel,
8076 	 &ett_nfs4_offload_status,
8077 	 &ett_nfs4_read_plus,
8078 	 &ett_nfs4_seek,
8079 	 &ett_nfs4_write_same,
8080 	 &ett_nfs4_clone,
8081 	 &ett_nfs4_getxattr,
8082 	 &ett_nfs4_setxattr,
8083 	 &ett_nfs4_listxattr,
8084 	 &ett_nfs4_removexattr,
8085 };
8086 
8087 
8088 static int
dissect_nfs4_dirlist(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)8089 dissect_nfs4_dirlist(tvbuff_t *tvb, int offset, packet_info *pinfo,
8090 		     proto_tree *tree, rpc_call_info_value *civ)
8091 {
8092 	guint32	    val_follows;
8093 	guint32	    name_len;
8094 	char	   *name;
8095 	proto_tree *dirlist_tree;
8096 	proto_item *eitem;
8097 	proto_tree *entry_tree;
8098 
8099 	dirlist_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_dirlist, NULL, "Directory Listing");
8100 
8101 	while (1)
8102 	{
8103 		val_follows = tvb_get_ntohl(tvb, offset);
8104 		if (val_follows) {
8105 			int start_off = offset;
8106 
8107 			/* Make sure we have 16 bytes (value follows + cookie + name length) */
8108 			name_len = tvb_get_ntohl(tvb, offset + 12);
8109 			tvb_ensure_bytes_exist(tvb, offset, 16 + name_len);
8110 			/*
8111 			* Get the entry name and create subtree of field nfs.name
8112 			*/
8113 			name = (char *)tvb_memcpy(tvb, wmem_alloc(wmem_packet_scope(), name_len+1), offset + 16, name_len);
8114 			name[name_len] = '\0';
8115 
8116 			eitem = proto_tree_add_string_format(
8117 				dirlist_tree, hf_nfs_name, tvb, offset, -1, name, "Entry: %s", name);
8118 			entry_tree = proto_item_add_subtree(eitem, ett_nfs4_dir_entry);
8119 
8120 			/* Value Follows: <Yes|No> */
8121 			proto_tree_add_boolean(entry_tree, hf_nfs4_value_follows, tvb, offset, 4, val_follows);
8122 			offset += 4;
8123 
8124 			/* Directory entry cookie */
8125 			if (entry_tree)
8126 				dissect_rpc_uint64(tvb, entry_tree, hf_nfs4_cookie, offset);
8127 			offset += 8;
8128 
8129 			/* Directory entry name (nfs.entry_name) */
8130 			offset = dissect_nfs_utf8string(tvb, offset, entry_tree, hf_nfs4_dir_entry_name, NULL);
8131 
8132 			/* Attrmask(s) */
8133 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, entry_tree, FATTR4_DISSECT_VALUES, civ);
8134 			proto_item_set_len(eitem, offset - start_off);
8135 		} else {
8136 			break;
8137 		}
8138 	}
8139 	if (dirlist_tree) {
8140 		proto_tree_add_boolean(dirlist_tree, hf_nfs4_value_follows, tvb, offset, 4, val_follows);
8141 		offset += 4;
8142 		/* The last entry in this packet has been reached but do more follow? */
8143 		offset = dissect_rpc_bool(tvb, dirlist_tree, hf_nfs4_dirlist_eof, offset);
8144 	} else {
8145 		offset += 8;
8146 	}
8147 	return offset;
8148 }
8149 
8150 static int
dissect_nfs4_change_info(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)8151 dissect_nfs4_change_info(tvbuff_t *tvb, int offset,
8152 			 proto_tree *tree, const char *name)
8153 {
8154 	proto_tree *newftree;
8155 	proto_tree *fitem;
8156 	int         old_offset = offset;
8157 
8158 	newftree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_change_info, &fitem, name);
8159 
8160 	offset = dissect_rpc_bool(  tvb, newftree, hf_nfs4_change_info_atomic, offset);
8161 	offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_changeid_before,    offset);
8162 	offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_changeid_after,     offset);
8163 	proto_item_set_len(fitem, offset - old_offset);
8164 
8165 	return offset;
8166 }
8167 
8168 
8169 static const value_string names_nfs_lock_type4[] =
8170 {
8171 #define READ_LT 1
8172 	{	READ_LT,	"READ_LT"	},
8173 #define WRITE_LT 2
8174 	{	WRITE_LT,	"WRITE_LT"	},
8175 #define READW_LT 3
8176 	{	READW_LT,	"READW_LT"	},
8177 #define WRITEW_LT 4
8178 	{	WRITEW_LT,	"WRITEW_LT"	},
8179 #define RELEASE_STATE 5
8180 	{	RELEASE_STATE,	"RELEASE_STATE"	},
8181 	{	0,	NULL	}
8182 };
8183 
8184 static int
dissect_nfs4_lockdenied(tvbuff_t * tvb,int offset,proto_tree * tree)8185 dissect_nfs4_lockdenied(tvbuff_t *tvb, int offset, proto_tree *tree)
8186 {
8187 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
8188 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
8189 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_lock_type, offset);
8190 	offset = dissect_nfs4_lock_owner(tvb, offset, tree);
8191 	return offset;
8192 }
8193 
8194 
8195 #define OPEN4_RESULT_CONFIRM		0x00000002
8196 #define OPEN4_RESULT_LOCKTYPE_POSIX	0x00000004
8197 #define OPEN4_RESULT_PRESERVE_UNLINKED	0x00000008
8198 #define OPEN4_RESULT_MAY_NOTIFY_LOCK	0x00000020
8199 
8200 static int * const open4_result_flag_fields[] = {
8201 	&hf_nfs4_open_rflags_confirm,
8202 	&hf_nfs4_open_rflags_locktype_posix,
8203 	&hf_nfs4_open_rflags_preserve_unlinked,
8204 	&hf_nfs4_open_rflags_may_notify_lock,
8205 	NULL
8206 };
8207 
8208 static int
dissect_nfs4_open_rflags(tvbuff_t * tvb,int offset,proto_tree * tree)8209 dissect_nfs4_open_rflags(tvbuff_t *tvb, int offset, proto_tree *tree)
8210 {
8211 	proto_tree_add_bitmask(tree, tvb, offset, hf_nfs4_open_rflags,
8212 			ett_nfs4_open_result_flags, open4_result_flag_fields, ENC_BIG_ENDIAN);
8213 	offset += 4;
8214 
8215 	return offset;
8216 }
8217 
8218 
8219 static int
dissect_nfs4_stateid(tvbuff_t * tvb,int offset,proto_tree * tree,guint16 * hash)8220 dissect_nfs4_stateid(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *hash)
8221 {
8222 	guint16		 stateid_hash;
8223 	guint32		 other_hash;
8224 	proto_item	*sitem, *hitem, *oth_item;
8225 	proto_tree	*stateid_tree;
8226 	int		 old_offset = offset;
8227 
8228 	sitem = proto_tree_add_bytes_format(tree, hf_nfs4_stateid, tvb, offset, 16, NULL, "StateID");
8229 	stateid_tree = proto_item_add_subtree(sitem, ett_nfs4_stateid);
8230 
8231 	stateid_hash = crc16_ccitt_tvb_offset(tvb, offset, 16);
8232 	hitem = proto_tree_add_uint(stateid_tree, hf_nfs4_stateid_hash, tvb, offset, 16, stateid_hash);
8233 	proto_item_set_generated(hitem);
8234 
8235 	offset = dissect_rpc_uint32(tvb, sitem, hf_nfs4_seqid_stateid, offset);
8236 
8237 	proto_tree_add_item(stateid_tree, hf_nfs4_stateid_other, tvb, offset, 12, ENC_NA);
8238 
8239 	other_hash = crc32_ccitt_tvb_offset(tvb, offset, 12);
8240 	oth_item = proto_tree_add_uint(stateid_tree, hf_nfs4_stateid_other_hash, tvb, offset, 12, other_hash);
8241 	proto_item_set_generated(oth_item);
8242 	offset+=12;
8243 
8244 	if (hash)
8245 		*hash = stateid_hash;
8246 
8247 	proto_item_set_len(sitem, offset - old_offset);
8248 
8249 	return offset;
8250 }
8251 
8252 
8253 static int
dissect_nfs4_open_read_delegation(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8254 dissect_nfs4_open_read_delegation(tvbuff_t *tvb, int offset,
8255 			packet_info *pinfo, proto_tree *tree)
8256 {
8257 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8258 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_recall4, offset);
8259 	offset = dissect_nfs4_ace(tvb, offset, pinfo, tree, 0, 0);
8260 
8261 	return offset;
8262 }
8263 
8264 
8265 static int
dissect_nfs4_modified_limit(tvbuff_t * tvb,int offset,proto_tree * tree)8266 dissect_nfs4_modified_limit(tvbuff_t *tvb, int offset, proto_tree *tree)
8267 {
8268 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_num_blocks, offset);
8269 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_bytes_per_block, offset);
8270 
8271 	return offset;
8272 }
8273 
8274 
8275 static int
dissect_nfs4_state_protect_bitmap(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,const char * name)8276 dissect_nfs4_state_protect_bitmap(tvbuff_t *tvb, int offset, packet_info *pinfo,
8277 				proto_tree *tree, const char *name)
8278 {
8279 	static nfs4_bitmap_info_t bitmap_info = {
8280 		.vse_names_ext = &names_nfs4_operation_ext,
8281 		.hf_mask_label = &hf_nfs4_op_mask,
8282 		.hf_item_label = &hf_nfs4_op
8283 	};
8284 
8285 	return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, name);
8286 }
8287 
8288 #define SP4_NONE                                0
8289 #define SP4_MACH_CRED                           1
8290 #define SP4_SSV                                 2
8291 static const value_string names_state_protect_how4[] = {
8292 	{	SP4_NONE,	"SP4_NONE"  },
8293 	{	SP4_MACH_CRED,	"SP4_MACH_CRED" },
8294 	{	SP4_SSV,	"SP4_SSV" },
8295 	{	0,		NULL }
8296 };
8297 
8298 static int
dissect_nfs4_state_protect_ops(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8299 dissect_nfs4_state_protect_ops(tvbuff_t *tvb, int offset,
8300 		packet_info *pinfo, proto_tree *tree)
8301 {
8302 	offset = dissect_nfs4_state_protect_bitmap(tvb, offset, pinfo, tree, "spo_must_enforce");
8303 	offset = dissect_nfs4_state_protect_bitmap(tvb, offset, pinfo, tree, "spo_must_allow");
8304 	return offset;
8305 }
8306 
8307 
8308 static int
dissect_nfs4_sec_oid(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,void * data _U_)8309 dissect_nfs4_sec_oid(tvbuff_t *tvb, int offset, packet_info *pinfo,
8310 				proto_tree *tree, void *data _U_)
8311 {
8312 	return dissect_rpc_opaque_data(tvb, offset, tree, pinfo,
8313 				hf_nfs4_sec_oid, FALSE, 0, FALSE, NULL, NULL);
8314 }
8315 
8316 static int
dissect_nfs4_ssv_sp_parms(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8317 dissect_nfs4_ssv_sp_parms(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
8318 {
8319 	offset = dissect_nfs4_state_protect_ops(tvb, offset, pinfo, tree);
8320 	offset = dissect_rpc_array(tvb, pinfo, tree, offset, dissect_nfs4_sec_oid, hf_nfs4_sp_parms_hash_algs);
8321 	offset = dissect_rpc_array(tvb, pinfo, tree, offset, dissect_nfs4_sec_oid, hf_nfs4_sp_parms_encr_algs);
8322 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_state_protect_window, offset);
8323 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_state_protect_num_gss_handles, offset);
8324 	return offset;
8325 }
8326 
8327 
8328 static int
dissect_nfs4_ssv_prot_info(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8329 dissect_nfs4_ssv_prot_info(tvbuff_t *tvb, int offset,
8330 		packet_info *pinfo, proto_tree *tree)
8331 {
8332 	offset = dissect_nfs4_state_protect_ops(tvb, offset, pinfo, tree);
8333 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_prot_info_hash_alg, offset);
8334 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_prot_info_encr_alg, offset);
8335 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_prot_info_svv_length, offset);
8336 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_prot_info_spi_window, offset);
8337 	offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_gsshandle);
8338 	return offset;
8339 }
8340 
8341 
8342 static int
dissect_nfs4_state_protect_a(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8343 dissect_nfs4_state_protect_a(tvbuff_t *tvb, int offset,
8344 		packet_info *pinfo, proto_tree *tree)
8345 {
8346 	guint stateprotect;
8347 
8348 	proto_tree_add_item_ret_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4, ENC_BIG_ENDIAN, &stateprotect);
8349 	offset += 4;
8350 
8351 	switch (stateprotect) {
8352 		case SP4_NONE:
8353 			break;
8354 		case SP4_MACH_CRED:
8355 			offset = dissect_nfs4_state_protect_ops(tvb, offset, pinfo, tree);
8356 			break;
8357 		case SP4_SSV:
8358 			offset = dissect_nfs4_ssv_sp_parms(tvb, offset, pinfo, tree);
8359 			break;
8360 		default:
8361 			break;
8362 	}
8363 	return offset;
8364 }
8365 
8366 
8367 static int
dissect_nfs4_state_protect_r(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8368 dissect_nfs4_state_protect_r(tvbuff_t *tvb, int offset,
8369 		packet_info *pinfo, proto_tree *tree)
8370 {
8371 	guint stateprotect;
8372 
8373 	proto_tree_add_item_ret_uint(tree, hf_nfs4_state_protect_how, tvb, offset+0, 4,
8374 			    ENC_BIG_ENDIAN, &stateprotect);
8375 	offset += 4;
8376 
8377 	switch (stateprotect) {
8378 		case SP4_NONE:
8379 			break;
8380 		case SP4_MACH_CRED:
8381 			offset = dissect_nfs4_state_protect_ops(tvb, offset, pinfo, tree);
8382 			break;
8383 		case SP4_SSV:
8384 			offset = dissect_nfs4_ssv_prot_info(tvb, offset, pinfo, tree);
8385 			break;
8386 		default:
8387 			break;
8388 	}
8389 	return offset;
8390 }
8391 
8392 
8393 #define NFS_LIMIT_SIZE						1
8394 #define NFS_LIMIT_BLOCKS					2
8395 static const value_string names_limit_by4[] = {
8396 	{	NFS_LIMIT_SIZE,		"NFS_LIMIT_SIZE"  },
8397 	{	NFS_LIMIT_BLOCKS,	"NFS_LIMIT_BLOCKS" },
8398 	{	0,			NULL }
8399 };
8400 
8401 static int
dissect_nfs4_space_limit(tvbuff_t * tvb,int offset,proto_tree * tree)8402 dissect_nfs4_space_limit(tvbuff_t *tvb, int offset,
8403 			 proto_tree *tree)
8404 {
8405 	guint limitby;
8406 
8407 	proto_tree_add_item_ret_uint(tree, hf_nfs4_limit_by, tvb, offset+0, 4, ENC_BIG_ENDIAN, &limitby);
8408 	offset += 4;
8409 
8410 	switch (limitby)
8411 	{
8412 	case NFS_LIMIT_SIZE:
8413 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_filesize,
8414 			offset);
8415 		break;
8416 
8417 	case NFS_LIMIT_BLOCKS:
8418 		offset = dissect_nfs4_modified_limit(tvb, offset, tree);
8419 		break;
8420 
8421 	default:
8422 		break;
8423 	}
8424 
8425 	return offset;
8426 }
8427 
8428 
8429 static int
dissect_nfs4_open_write_delegation(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8430 dissect_nfs4_open_write_delegation(tvbuff_t *tvb, int offset,
8431 	packet_info *pinfo, proto_tree *tree)
8432 {
8433 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8434 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_recall, offset);
8435 	offset = dissect_nfs4_space_limit(tvb, offset, tree);
8436 	offset = dissect_nfs4_ace(tvb, offset, pinfo, tree, 0, 0);
8437 
8438 	return offset;
8439 }
8440 
8441 
8442 #define OPEN_DELEGATE_NONE 0
8443 #define OPEN_DELEGATE_READ 1
8444 #define OPEN_DELEGATE_WRITE 2
8445 #define OPEN_DELEGATE_NONE_EXT 3 /* new to v4.1 */
8446 #define OPEN_DELEGATE_READ_ATTRS_DELEG 4  /* New to V4.2 */
8447 #define OPEN_DELEGATE_WRITE_ATTRS_DELEG 5
8448 static const value_string names_open_delegation_type4[] = {
8449 	{	OPEN_DELEGATE_NONE,	"OPEN_DELEGATE_NONE" },
8450 	{	OPEN_DELEGATE_READ,	"OPEN_DELEGATE_READ" },
8451 	{	OPEN_DELEGATE_WRITE,	"OPEN_DELEGATE_WRITE" },
8452 	{	OPEN_DELEGATE_NONE_EXT, "OPEN_DELEGATE_NONE_EXT"},
8453 	{	OPEN_DELEGATE_READ_ATTRS_DELEG, "OPEN_DELEGATE_READ_ATTRS_DELEG"},
8454 	{	OPEN_DELEGATE_WRITE_ATTRS_DELEG, "OPEN_DELEGATE_WRITE_ATTRS_DELEG"},
8455 	{	0,	NULL }
8456 };
8457 
8458 #define WND4_NOT_WANTED 0
8459 #define WND4_CONTENTION 1
8460 #define WND4_RESOURCE 2
8461 #define WND4_NOT_SUPP_FTYPE 3
8462 #define WND4_WRITE_DELEG_NOT_SUPP_FTYPE 4
8463 #define WND4_NOT_SUPP_UPGRADE 5
8464 #define WND4_NOT_SUPP_DOWNGRADE 6
8465 #define WND4_CANCELLED 7
8466 #define WND4_IS_DIR 8
8467 static const value_string names_why_no_delegation4[] = {
8468 	{	WND4_NOT_WANTED,		 "WND4_NOT_WANTED" },
8469 	{	WND4_CONTENTION,		 "WND4_CONTENTION" },
8470 	{	WND4_RESOURCE,			 "WND4_RESOURCE" },
8471 	{	WND4_NOT_SUPP_FTYPE,		 "WND4_NOT_SUPP_FTYPE" },
8472 	{	WND4_WRITE_DELEG_NOT_SUPP_FTYPE, "WND4_WRITE_DELEG_NOT_SUPP_FTYPE" },
8473 	{	WND4_NOT_SUPP_UPGRADE,		 "WND4_NOT_SUPP_UPGRADE" },
8474 	{	WND4_NOT_SUPP_DOWNGRADE,	 "WND4_NOT_SUPP_DOWNGRADE" },
8475 	{	WND4_CANCELLED,			 "WND4_CANCELLED" },
8476 	{	WND4_IS_DIR,			 "WND4_IS_DIR" },
8477 	{	0,				NULL }
8478 };
8479 
8480 static int
dissect_nfs4_open_delegation(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8481 dissect_nfs4_open_delegation(tvbuff_t *tvb, int offset, packet_info *pinfo,
8482 	proto_tree *tree)
8483 {
8484 	guint delegation_type;
8485 	proto_tree *newftree;
8486 	proto_item *fitem;
8487 
8488 	fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_open_delegation_type, tvb,
8489 		offset+0, 4, ENC_BIG_ENDIAN, &delegation_type);
8490 	newftree = proto_item_add_subtree(fitem, ett_nfs4_open_delegation);
8491 	offset += 4;
8492 
8493 	switch (delegation_type)
8494 	{
8495 		case OPEN_DELEGATE_NONE:
8496 			break;
8497 
8498 		case OPEN_DELEGATE_READ:
8499 		case OPEN_DELEGATE_READ_ATTRS_DELEG:
8500 			offset = dissect_nfs4_open_read_delegation(tvb, offset, pinfo, newftree);
8501 			break;
8502 
8503 		case OPEN_DELEGATE_WRITE:
8504 		case OPEN_DELEGATE_WRITE_ATTRS_DELEG:
8505 			offset = dissect_nfs4_open_write_delegation(tvb, offset, pinfo, newftree);
8506 			break;
8507 		case OPEN_DELEGATE_NONE_EXT:
8508 			proto_tree_add_item(tree, hf_nfs4_why_no_delegation, tvb, offset, 4, ENC_BIG_ENDIAN);
8509 			offset += 4;
8510 			break;
8511 		default:
8512 			break;
8513 	}
8514 
8515 	return offset;
8516 }
8517 
8518 
8519 static int
dissect_nfs_rpcsec_gss_info(tvbuff_t * tvb,int offset,proto_tree * tree)8520 dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, proto_tree *tree)
8521 {
8522 	offset = dissect_nfs4_sec_oid(tvb, offset, NULL, tree, NULL);
8523 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_qop, offset);
8524 	offset = dissect_rpc_uint32(tvb, tree,
8525 		hf_nfs4_secinfo_rpcsec_gss_info_service, offset);
8526 
8527 	return offset;
8528 }
8529 
8530 
8531 static int
dissect_nfs4_open_to_lock_owner(tvbuff_t * tvb,int offset,proto_tree * tree)8532 dissect_nfs4_open_to_lock_owner(tvbuff_t *tvb, int offset, proto_tree *tree)
8533 {
8534 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_seqid, offset);
8535 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8536 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_lock_seqid, offset);
8537 	offset = dissect_nfs4_lock_owner(tvb, offset, tree);
8538 
8539 	return offset;
8540 }
8541 
8542 
8543 static int
dissect_nfs4_exist_lock_owner(tvbuff_t * tvb,int offset,proto_tree * tree)8544 dissect_nfs4_exist_lock_owner(tvbuff_t *tvb, int offset, proto_tree *tree)
8545 {
8546 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8547 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_lock_seqid, offset);
8548 
8549 	return offset;
8550 }
8551 
8552 
8553 static int
dissect_nfs4_locker(tvbuff_t * tvb,int offset,proto_tree * tree)8554 dissect_nfs4_locker(tvbuff_t *tvb, int offset, proto_tree *tree)
8555 {
8556 	guint new_lock_owner;
8557 
8558 	new_lock_owner = tvb_get_ntohl(tvb, offset);
8559 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_new_lock_owner, offset);
8560 
8561 	if (new_lock_owner)
8562 		offset = dissect_nfs4_open_to_lock_owner(tvb, offset, tree);
8563 	else
8564 		offset = dissect_nfs4_exist_lock_owner(tvb, offset, tree);
8565 
8566 	return offset;
8567 }
8568 
8569 static const value_string read_plus_content_names[] = {
8570 #define NFS4_CONTENT_DATA                 0
8571 	{	NFS4_CONTENT_DATA,    "Data"	},
8572 #define NFS4_CONTENT_HOLE             1
8573 	{	NFS4_CONTENT_HOLE,    "Hole"	},
8574 	{	0,	NULL	}
8575 };
8576 static value_string_ext read_plus_content_names_ext = VALUE_STRING_EXT_INIT(read_plus_content_names);
8577 
8578 static int
dissect_nfs4_read_plus_content(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)8579 dissect_nfs4_read_plus_content(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
8580 {
8581 	proto_tree *ss_tree;
8582 	proto_item *ss_fitem;
8583 	guint       type;
8584 
8585 	ss_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_read_plus_content_type,
8586 						tvb, offset, 4, ENC_BIG_ENDIAN, &type);
8587 	ss_tree = proto_item_add_subtree(ss_fitem, ett_nfs4_read_plus_content_sub);
8588 	offset += 4;
8589 
8590 	switch (type) {
8591 		case NFS4_CONTENT_DATA:
8592 			offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
8593 			dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_read_data_length, offset); /* don't change offset */
8594 			offset = dissect_nfsdata(tvb, offset, ss_tree, hf_nfs_data);
8595 			break;
8596 		case NFS4_CONTENT_HOLE:
8597 			offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_offset, offset);
8598 			offset = dissect_rpc_uint64(tvb, ss_tree, hf_nfs4_length, offset);
8599 			break;
8600 		default:
8601 			break;
8602 	}
8603 
8604 	return offset;
8605 }
8606 
8607 static int
dissect_nfs4_client_id(tvbuff_t * tvb,int offset,proto_tree * tree)8608 dissect_nfs4_client_id(tvbuff_t *tvb, int offset, proto_tree *tree)
8609 {
8610 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
8611 	offset = dissect_rpc_data(tvb, tree, hf_nfs4_client_id, offset);
8612 
8613 	return offset;
8614 }
8615 
8616 
8617 static int
dissect_nfs4_newtime(tvbuff_t * tvb,int offset,proto_tree * tree)8618 dissect_nfs4_newtime(tvbuff_t *tvb, int offset, proto_tree *tree)
8619 {
8620 	guint new_time;
8621 
8622 	new_time = tvb_get_ntohl(tvb, offset);
8623 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_newtime, offset);
8624 
8625 	if (new_time) {
8626 		offset = dissect_nfs4_nfstime(tvb, offset, tree);
8627 	}
8628 
8629 	return offset;
8630 }
8631 
8632 
8633 static int
dissect_nfs4_newsize(tvbuff_t * tvb,int offset,proto_tree * tree)8634 dissect_nfs4_newsize(tvbuff_t *tvb, int offset, proto_tree *tree)
8635 {
8636 	guint new_size;
8637 
8638 	new_size = tvb_get_ntohl(tvb, offset);
8639 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_newsize, offset);
8640 
8641 	if (new_size) {
8642 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
8643 	}
8644 
8645 	return offset;
8646 }
8647 
8648 
8649 static int
dissect_nfs4_newoffset(tvbuff_t * tvb,int offset,proto_tree * tree)8650 dissect_nfs4_newoffset(tvbuff_t *tvb, int offset, proto_tree *tree)
8651 {
8652 	guint new_offset;
8653 
8654 	new_offset = tvb_get_ntohl(tvb, offset);
8655 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_newoffset, offset);
8656 
8657 	if (new_offset) {
8658 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
8659 	}
8660 
8661 	return offset;
8662 }
8663 
8664 static const value_string io_advise_names[] = {
8665 #define IO_ADVISE4_NORMAL                 0
8666 	{	IO_ADVISE4_NORMAL,    "Normal"	},
8667 #define IO_ADVISE4_SEQUENTIAL             1
8668 	{	IO_ADVISE4_SEQUENTIAL,    "Sequential"	},
8669 #define IO_ADVISE4_SEQUENTIAL_BACKWARDS   2
8670 	{	IO_ADVISE4_SEQUENTIAL_BACKWARDS,    "Sequential Backwards"	},
8671 #define IO_ADVISE4_RANDOM                 3
8672 	{	IO_ADVISE4_RANDOM,    "Random"	},
8673 #define IO_ADVISE4_WILLNEED               4
8674 	{	IO_ADVISE4_WILLNEED,    "Will Need"	},
8675 #define IO_ADVISE4_WILLNEED_OPPORTUNISTIC 5
8676 	{	IO_ADVISE4_WILLNEED_OPPORTUNISTIC,    "Will Need Opportunistic"	},
8677 #define IO_ADVISE4_DONTNEED               6
8678 	{	IO_ADVISE4_DONTNEED,    "Don't Need"	},
8679 #define IO_ADVISE4_NOREUSE                7
8680 	{	IO_ADVISE4_NOREUSE,    "No Reuse"	},
8681 #define IO_ADVISE4_READ                   8
8682 	{	IO_ADVISE4_READ,    "Read"	},
8683 #define IO_ADVISE4_WRITE                  9
8684 	{	IO_ADVISE4_WRITE,    "Write"	},
8685 #define IO_ADVISE4_INIT_PROXIMITY         10
8686 	{	IO_ADVISE4_INIT_PROXIMITY,    "Init Proximity"	},
8687 	{	0,	NULL	}
8688 };
8689 static value_string_ext io_advise_names_ext = VALUE_STRING_EXT_INIT(io_advise_names);
8690 
8691 static int
dissect_nfs4_io_hints(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree)8692 dissect_nfs4_io_hints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
8693 {
8694 	static nfs4_bitmap_info_t bitmap_info = {
8695 		.vse_names_ext = &io_advise_names_ext,
8696 		.hf_mask_label = &hf_nfs4_io_hints_mask,
8697 		.hf_item_label = &hf_nfs4_io_advise_hint,
8698 		.hf_item_count = &hf_nfs4_io_hint_count,
8699 	};
8700 
8701 	return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, NULL);
8702 }
8703 
8704 static int
dissect_nfs4_app_data_block(tvbuff_t * tvb,int offset,proto_tree * tree,guint32 * hash)8705 dissect_nfs4_app_data_block(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *hash)
8706 {
8707 	proto_item *fitem;
8708 
8709 	guint32     pattern_hash;
8710 	guint       pattern_len;
8711 
8712 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
8713 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_size, offset);
8714 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_block_count, offset);
8715 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_blocknum, offset);
8716 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_blocknum, offset);
8717 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_reloff_pattern, offset);
8718 
8719 	pattern_len = tvb_get_ntohl(tvb, offset);
8720 	offset += 4;
8721 
8722 	pattern_hash = crc32_ccitt_tvb_offset(tvb, offset, pattern_len);
8723 	fitem = proto_tree_add_uint(tree, hf_nfs4_pattern_hash, tvb, offset, pattern_len, pattern_hash);
8724 	proto_item_set_generated(fitem);
8725 	proto_item_set_len(fitem, pattern_len);
8726 
8727 	offset += pattern_len;
8728 
8729 	if (hash)
8730 		*hash = pattern_hash;
8731 
8732 	return offset;
8733 }
8734 
8735 static int
dissect_nfs4_io_time(tvbuff_t * tvb,int offset,proto_tree * tree,const char * timer_mode)8736 dissect_nfs4_io_time(tvbuff_t *tvb, int offset, proto_tree *tree, const char *timer_mode)
8737 {
8738 	proto_tree *newtree;
8739 
8740 	newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_time, NULL, "%s", timer_mode);
8741 	offset = dissect_nfs4_nfstime(tvb, offset, newtree);
8742 
8743 	return offset;
8744 }
8745 
8746 static int
dissect_nfs4_io_latency(tvbuff_t * tvb,int offset,proto_tree * tree,const char * io_mode)8747 dissect_nfs4_io_latency(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
8748 {
8749 	proto_tree *newtree;
8750 
8751 	newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "%s Latency", io_mode);
8752 
8753 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_requested, offset);
8754 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_requested, offset);
8755 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ops_completed, offset);
8756 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_completed, offset);
8757 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_bytes_not_delivered, offset);
8758 
8759 	offset = dissect_nfs4_io_time(tvb, offset, newtree, "Busy time");
8760 	offset = dissect_nfs4_io_time(tvb, offset, newtree, "Completion time");
8761 
8762 	return offset;
8763 }
8764 
8765 static int
dissect_nfs4_io_info(tvbuff_t * tvb,int offset,proto_tree * tree,const char * io_mode)8766 dissect_nfs4_io_info(tvbuff_t *tvb, int offset, proto_tree *tree, const char *io_mode)
8767 {
8768 	proto_tree *newtree;
8769 
8770 	newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_info, NULL, "%s Info", io_mode);
8771 
8772 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_count, offset);
8773 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_io_bytes, offset);
8774 
8775 	return offset;
8776 }
8777 
8778 static int
dissect_nfs4_layoutstats(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ,gboolean has_layout_type)8779 dissect_nfs4_layoutstats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ, gboolean has_layout_type)
8780 {
8781 	guint	    layout_type = LAYOUT4_NO_LAYOUT_TYPE;
8782 	proto_tree *netaddr;
8783 	proto_item *fitem;
8784 	int	    old_offset;
8785 	guint32	    last_fh_hash    = 0;
8786 
8787 	/* FIXME: Are these here or in the caller? Check for layoutcommit */
8788 	offset = dissect_nfs4_io_info(tvb, offset, tree, "Read");
8789 	offset = dissect_nfs4_io_info(tvb, offset, tree, "Write");
8790 	offset = dissect_nfs4_deviceid(tvb, offset, tree);
8791 
8792 	if (has_layout_type) {
8793 		layout_type = tvb_get_ntohl(tvb, offset);
8794 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
8795 	}
8796 
8797 	/* If not flex files layout type eat the rest and move on.. */
8798 	if (!has_layout_type || layout_type == LAYOUT4_FLEX_FILES) {
8799 
8800 		/* NFS Flex Files */
8801 		if (has_layout_type)
8802 			offset += 4; /* Skip past opaque count */
8803 
8804 		/* The netaddr */
8805 		old_offset = offset;
8806 		netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "DS address");
8807 
8808 		offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
8809 		proto_item_set_len(fitem, offset - old_offset);
8810 
8811 		/* The file handle */
8812 		offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "Filehandle", &last_fh_hash, civ);
8813 
8814 		/* Read Latency */
8815 		offset = dissect_nfs4_io_latency(tvb, offset, tree, "Read");
8816 
8817 		/* Write Latency */
8818 		offset = dissect_nfs4_io_latency(tvb, offset, tree, "Write");
8819 
8820 		/* Duration */
8821 		offset = dissect_nfs4_io_time(tvb, offset, tree, "Duration");
8822 
8823 		/* Local? */
8824 		offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_local, offset);
8825 	} else {
8826 		offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_layoutstats);
8827 	}
8828 
8829 	return offset;
8830 }
8831 
8832 static int
dissect_nfs4_ff_io_stats(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)8833 dissect_nfs4_ff_io_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
8834 {
8835 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
8836 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
8837 	offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8838 
8839 	/* Note that we've already determined that we are in the Flex File Layout Type */
8840 	offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, tree, civ, FALSE);
8841 
8842 	return offset;
8843 }
8844 
8845 static int
dissect_nfs4_device_errors(tvbuff_t * tvb,int offset,proto_tree * tree)8846 dissect_nfs4_device_errors(tvbuff_t *tvb, int offset, proto_tree *tree)
8847 {
8848 	proto_item *sub_fitem;
8849 	proto_tree *ss_tree;
8850 	proto_tree *subtree;
8851 	proto_item *ss_fitem;
8852 	guint       i;
8853 	guint       count;
8854 
8855 	guint	    opcode;
8856 
8857 	count = tvb_get_ntohl(tvb, offset);
8858 	sub_fitem = proto_tree_add_item(tree, hf_nfs4_device_error_count,
8859 					tvb, offset, 4, ENC_BIG_ENDIAN);
8860 	offset += 4;
8861 
8862 	subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_device_errors_sub);
8863 	for (i = 0; i < count; i++) {
8864 		ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_device_errors_index,
8865 							tvb, offset+0, 4, i, "Error [%u]", i);
8866 		ss_tree = proto_item_add_subtree(ss_fitem,
8867 						 ett_nfs4_device_errors_sub);
8868 		offset = dissect_nfs4_deviceid(tvb, offset, ss_tree);
8869 		offset = dissect_nfs4_status(tvb, offset, ss_tree, NULL);
8870 
8871 		opcode = tvb_get_ntohl(tvb, offset);
8872 		proto_tree_add_uint(ss_tree, hf_nfs4_io_error_op, tvb, offset, 4, opcode);
8873 		offset += 4;
8874 	}
8875 
8876 	return offset;
8877 }
8878 
8879 static int
dissect_nfs4_ff_io_error(tvbuff_t * tvb,int offset,proto_tree * tree)8880 dissect_nfs4_ff_io_error(tvbuff_t *tvb, int offset, proto_tree *tree)
8881 {
8882 	proto_tree *newtree;
8883 
8884 	/* FIXME */
8885 	newtree = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_nfs4_io_latency, NULL, "IO errors");
8886 
8887 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_offset, offset);
8888 	offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_ff_ioerrs_length, offset);
8889 	offset = dissect_nfs4_stateid(tvb, offset, newtree, NULL);
8890 
8891 	offset = dissect_nfs4_device_errors(tvb, offset, newtree);
8892 
8893 	return offset;
8894 }
8895 
8896 static int
dissect_nfs4_layoutreturn(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)8897 dissect_nfs4_layoutreturn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
8898 {
8899 	guint returntype;
8900 	guint layout_type;
8901 
8902 	proto_item *sub_fitem;
8903 	proto_tree *ss_tree;
8904 	proto_tree *subtree;
8905 	proto_item *ss_fitem;
8906 	guint       i;
8907 	guint       count;
8908 
8909 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_reclaim, offset);
8910 
8911 	layout_type = tvb_get_ntohl(tvb, offset);
8912 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
8913 
8914 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_iomode, offset);
8915 
8916 	returntype = tvb_get_ntohl(tvb, offset);
8917 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_return_type, offset);
8918 	if (returntype == 1) { /* RETURN_FILE */
8919 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
8920 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
8921 		offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8922 
8923 		/* If not flex files layout type eat the rest and move on.. */
8924 		if (layout_type == LAYOUT4_FLEX_FILES) {
8925 			offset += 4; /* Skip past opaque count */
8926 
8927 			/* Get the errors */
8928 			count = tvb_get_ntohl(tvb, offset);
8929 			sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_ioerrs_count,
8930 							tvb, offset, 4, ENC_BIG_ENDIAN);
8931 			offset += 4;
8932 
8933 			subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_ioerrs_sub);
8934 			for (i = 0; i < count; i++) {
8935 				ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_ioerrs_index,
8936 									tvb, offset+0, 4, i, "IO Error [%u]", i);
8937 				ss_tree = proto_item_add_subtree(ss_fitem,
8938 								 ett_nfs4_ff_ioerrs_sub);
8939 
8940 				offset = dissect_nfs4_ff_io_error(tvb, offset, ss_tree);
8941 			}
8942 
8943 			/* Get the stats */
8944 			count = tvb_get_ntohl(tvb, offset);
8945 			sub_fitem = proto_tree_add_item(tree, hf_nfs4_ff_iostats_count,
8946 							tvb, offset, 4, ENC_BIG_ENDIAN);
8947 			offset += 4;
8948 
8949 			subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_ff_iostats_sub);
8950 			for (i = 0; i < count; i++) {
8951 				ss_fitem = proto_tree_add_uint_format(subtree, hf_nfs4_ff_iostats_index,
8952 									tvb, offset+0, 4, i, "IO Stat [%u]", i);
8953 				ss_tree = proto_item_add_subtree(ss_fitem,
8954 								 ett_nfs4_ff_iostats_sub);
8955 
8956 				offset = dissect_nfs4_ff_io_stats(tvb, offset, pinfo, ss_tree, civ);
8957 			}
8958 
8959 		} else {
8960 			offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_lrf_body_content);
8961 		}
8962 	}
8963 
8964 	return offset;
8965 }
8966 
8967 static int
dissect_nfs_layoutreturn_stateid(tvbuff_t * tvb,proto_tree * tree,int offset)8968 dissect_nfs_layoutreturn_stateid(tvbuff_t *tvb, proto_tree *tree, int offset)
8969 {
8970 	guint lrs_present;
8971 
8972 	lrs_present = tvb_get_ntohl(tvb, offset);
8973 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_lrs_present, offset);
8974 
8975 	if (lrs_present) {
8976 		offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
8977 	}
8978 
8979 	return offset;
8980 }
8981 
8982 
8983 static const value_string notify_deviceid_type4[] = {
8984 #define NOTIFY_DEVICEID4_CHANGE      1
8985 	{	NOTIFY_DEVICEID4_CHANGE, "Change" },
8986 #define NOTIFY_DEVICEID4_DELETE      2
8987 	{	NOTIFY_DEVICEID4_DELETE, "Delete" },
8988 	{	0,	NULL	}
8989 };
8990 static value_string_ext notify_deviceid_type4_ext = VALUE_STRING_EXT_INIT(notify_deviceid_type4);
8991 
8992 
8993 static int
dissect_nfs4_notification_bitmap(tvbuff_t * tvb,proto_tree * tree,packet_info * pinfo,int offset)8994 dissect_nfs4_notification_bitmap(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset)
8995 {
8996 	static nfs4_bitmap_info_t bitmap_info = {
8997 		.vse_names_ext = &notify_deviceid_type4_ext,
8998 		.hf_mask_label = &hf_nfs4_notification_mask,
8999 		.hf_item_label = &hf_nfs4_notification_type,
9000 	};
9001 
9002 	return dissect_nfs4_bitmap(tvb, offset, pinfo, tree, NULL, &bitmap_info, NFS4_BITMAP_MASK, NULL);
9003 }
9004 
9005 
9006 static int
dissect_nfs4_devices_file(tvbuff_t * tvb,int offset,proto_tree * tree)9007 dissect_nfs4_devices_file(tvbuff_t *tvb, int offset, proto_tree *tree)
9008 {
9009 	guint i, j;
9010 	guint32 num_indices, num_multipath, num_addr;
9011 
9012 	/* disect indices */
9013 	num_indices = tvb_get_ntohl(tvb, offset);
9014 	offset += 4;
9015 	for (i = 0; i < num_indices; i++) {
9016 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_deviceidx, offset);
9017 	}
9018 
9019 	num_multipath = tvb_get_ntohl(tvb, offset);
9020 	offset += 4;
9021 	for (i = 0; i < num_multipath; i++) {
9022 		num_addr = tvb_get_ntohl(tvb, offset);
9023 		offset += 4;
9024 		for (j = 0; j < num_addr; j++) {
9025 			offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_netid, offset, NULL);
9026 			offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_addr, offset, NULL);
9027 		}
9028 	}
9029 
9030 	return offset;
9031 }
9032 
9033 static int
dissect_nfs4_devices_flexfile(tvbuff_t * tvb,int offset,proto_tree * tree)9034 dissect_nfs4_devices_flexfile(tvbuff_t *tvb, int offset, proto_tree *tree)
9035 {
9036 	guint i;
9037 	guint32 num_addr;
9038 	guint32 num_vers;
9039 
9040 	/* disect indices */
9041 	num_addr = tvb_get_ntohl(tvb, offset);
9042 	offset += 4;
9043 	for (i = 0; i < num_addr; i++) {
9044 		offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_netid, offset,
9045 					    NULL);
9046 		offset = dissect_rpc_string(tvb, tree, hf_nfs4_r_addr, offset,
9047 					    NULL);
9048 	}
9049 
9050 	num_vers = tvb_get_ntohl(tvb, offset);
9051 	offset += 4;
9052 
9053 	for (i = 0; i < num_vers; i++) {
9054 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_version, offset);
9055 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_minorversion,
9056 				    offset);
9057 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_rsize,
9058 				    offset);
9059 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_ff_wsize,
9060 				    offset);
9061 		offset = dissect_rpc_bool(tvb, tree, hf_nfs4_ff_tightly_coupled,
9062 				  offset);
9063 	}
9064 
9065 	return offset;
9066 }
9067 
9068 static const value_string scsi_vol_type_names[] = {
9069 #define PNFS_SCSI_VOLUME_SLICE	1
9070 	{	PNFS_SCSI_VOLUME_SLICE,		"Slice" },
9071 #define PNFS_SCSI_VOLUME_CONCAT	2
9072 	{	PNFS_SCSI_VOLUME_CONCAT,	"Concat" },
9073 #define PNFS_SCSI_VOLUME_STRIPE	3
9074 	{	PNFS_SCSI_VOLUME_STRIPE,	"Stripe" },
9075 #define PNFS_SCSI_VOLUME_BASE	4
9076 	{	PNFS_SCSI_VOLUME_BASE,		"Base" },
9077 	{	0,	NULL }
9078 };
9079 
9080 static const value_string scsi_vpd_designator_type_names[] = {
9081 #define PS_DESIGNATOR_T10	1
9082 	{	PS_DESIGNATOR_T10,	"T10" },
9083 #define PS_DESIGNATOR_EUI64	2
9084 	{	PS_DESIGNATOR_EUI64,	"EUI64" },
9085 #define PS_DESIGNATOR_NAA	3
9086 	{	PS_DESIGNATOR_NAA,	"NAA" },
9087 #define PS_DESIGNATOR_NAME	8
9088 	{	PS_DESIGNATOR_NAME,	"Name" },
9089 	{	0,	NULL }
9090 };
9091 
9092 static const value_string scsi_vpd_code_set_names[] = {
9093 #define PS_CODE_SET_BINARY	1
9094 	{	PS_CODE_SET_BINARY,	"binary" },
9095 #define PS_CODE_SET_ASCII	2
9096 	{	PS_CODE_SET_ASCII,	"ASCII" },
9097 #define PS_CODE_SET_UTF8	3
9098 	{	PS_CODE_SET_UTF8,	"UTF8" },
9099 	{	0,	NULL }
9100 };
9101 
9102 static const value_string scsi_extent_state_names[] = {
9103 #define PNFS_SCSI_EXT_READ_WRITE_DATA	   0
9104 	{	PNFS_SCSI_EXT_READ_WRITE_DATA,	"READ_WRITE_DATA" },
9105 #define PNFS_SCSI_EXT_READ_DATA		   1
9106 	{	PNFS_SCSI_EXT_READ_DATA,	"READ_DATA" },
9107 #define PNFS_SCSI_EXT_INVALID_DATA	   2
9108 	{	PNFS_SCSI_EXT_INVALID_DATA,	"INVALID_DATA" },
9109 #define PNFS_SCSI_EXT_NONE_DATA		   3
9110 	{	PNFS_SCSI_EXT_NONE_DATA,	"NONE_DATA" },
9111 	{	0,	NULL }
9112 };
9113 
9114 static int
dissect_nfs4_devices_scsi_base_volume(tvbuff_t * tvb,int offset,proto_tree * tree)9115 dissect_nfs4_devices_scsi_base_volume(tvbuff_t *tvb, int offset, proto_tree *tree)
9116 {
9117 	guint32 desig_len;
9118 
9119 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_devaddr_scsi_vpd_code_set, offset);
9120 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_devaddr_scsi_vpd_designator_type, offset);
9121 
9122 	desig_len = tvb_get_ntohl(tvb, offset);
9123 	offset += 4;
9124 	proto_tree_add_item(tree, hf_nfs4_devaddr_scsi_vpd_designator,
9125 		tvb, offset, desig_len, ENC_NA);
9126 	offset += desig_len;
9127 
9128 	proto_tree_add_item(tree, hf_nfs4_devaddr_scsi_private_key,
9129 		tvb, offset, 8, ENC_NA);
9130 	offset += 8;
9131 
9132 	return offset;
9133 }
9134 
9135 static int
dissect_nfs4_vol_indices(tvbuff_t * tvb,int offset,proto_tree * tree)9136 dissect_nfs4_vol_indices(tvbuff_t *tvb, int offset, proto_tree *tree)
9137 {
9138 	guint i;
9139 	guint32 num_vols;
9140 	proto_item *indices_item;
9141 	proto_tree *indices_tree;
9142 
9143 	num_vols = tvb_get_ntohl(tvb, offset);
9144 	offset += 4;
9145 	if (num_vols == 0)
9146 		return offset;
9147 
9148 	indices_tree = proto_tree_add_subtree_format(tree, tvb, offset, 0,
9149 				ett_nfs4_scsi_layout_vol_indices, &indices_item,
9150 				"volume indices");
9151 	for (i = 0; i < num_vols; i++) {
9152 		proto_tree_add_item(indices_tree, hf_nfs4_devaddr_scsi_vol_ref_index,
9153 				tvb, offset, 4, ENC_BIG_ENDIAN);
9154 	}
9155 	return offset;
9156 }
9157 
9158 static int
dissect_nfs4_devices_scsi(tvbuff_t * tvb,int offset,proto_tree * tree)9159 dissect_nfs4_devices_scsi(tvbuff_t *tvb, int offset, proto_tree *tree)
9160 {
9161 	guint i;
9162 	proto_item *vol_item;
9163 	proto_tree *vol_tree;
9164 	int old_offset = offset;
9165 	guint32 num_vols;
9166 	guint32 vol_type;
9167 
9168 	num_vols = tvb_get_ntohl(tvb, offset);
9169 	offset += 4;
9170 
9171 	for (i = 0; i < num_vols; i++) {
9172 
9173 	vol_type = tvb_get_ntohl(tvb, offset);
9174 	vol_item = proto_tree_add_item(tree, hf_nfs4_devaddr_scsi_vol_type, tvb, offset, 4, ENC_BIG_ENDIAN);
9175 	vol_tree = proto_item_add_subtree(vol_item, ett_nfs4_scsi_layout_vol);
9176 	offset += 4;
9177 	proto_tree_add_uint(vol_tree, hf_nfs4_devaddr_scsi_vol_index, tvb, offset, 0, i);
9178 	switch (vol_type)
9179 	{
9180 	case PNFS_SCSI_VOLUME_SLICE:
9181 		proto_tree_add_item(vol_tree, hf_nfs4_devaddr_ssv_start, tvb, offset, 4, ENC_BIG_ENDIAN);
9182 		proto_tree_add_item(vol_tree, hf_nfs4_devaddr_ssv_length, tvb, offset, 4, ENC_BIG_ENDIAN);
9183 		proto_tree_add_item(vol_tree, hf_nfs4_devaddr_scsi_vol_ref_index, tvb, offset, 4, ENC_BIG_ENDIAN);
9184 		break;
9185 	case PNFS_SCSI_VOLUME_CONCAT:
9186 		offset = dissect_nfs4_vol_indices(tvb, offset, vol_tree);
9187 		break;
9188 	case PNFS_SCSI_VOLUME_STRIPE:
9189 		proto_tree_add_item(vol_tree, hf_nfs4_devaddr_ssv_stripe_unit, tvb, offset, 4, ENC_BIG_ENDIAN);
9190 		offset = dissect_nfs4_vol_indices(tvb, offset, vol_tree);
9191 		break;
9192 	case PNFS_SCSI_VOLUME_BASE:
9193 		offset = dissect_nfs4_devices_scsi_base_volume(tvb, offset, vol_tree);
9194 		break;
9195 	}
9196 
9197 	proto_item_set_len(vol_item, offset - old_offset);
9198 	old_offset = offset;
9199 	}
9200 
9201 	return offset;
9202 }
9203 
9204 
9205 static int
dissect_nfs4_test_stateid_arg(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)9206 dissect_nfs4_test_stateid_arg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
9207 {
9208 	return dissect_nfs4_stateid(tvb, offset, tree, NULL);
9209 }
9210 
9211 
9212 static int
dissect_nfs4_test_stateid_res(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)9213 dissect_nfs4_test_stateid_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
9214 {
9215 	return dissect_nfs4_status(tvb, offset, tree, NULL);
9216 }
9217 
9218 static int
dissect_nfs4_netloc(tvbuff_t * tvb,int offset,proto_tree * tree)9219 dissect_nfs4_netloc(tvbuff_t *tvb, int offset, proto_tree *tree)
9220 {
9221 	guint netloc_type;
9222 	proto_tree *netaddr;
9223 	int old_offset;
9224 	proto_item *fitem;
9225 
9226 	/* netloc type */
9227 	netloc_type = tvb_get_ntohl(tvb, offset);
9228 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_netloc_type, offset);
9229 
9230 	switch (netloc_type) {
9231 	case NL4_NAME:
9232 		offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_name, NULL);
9233 		break;
9234 	case NL4_URL:
9235 		offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_nl_url, NULL);
9236 		break;
9237 	case NL4_NETADDR:
9238 		old_offset = offset;
9239 		netaddr = proto_tree_add_subtree(tree, tvb, offset, 0, ett_nfs4_clientaddr, &fitem, "netaddr");
9240 
9241 		offset = dissect_nfs4_clientaddr(tvb, offset, netaddr);
9242 		proto_item_set_len(fitem, offset - old_offset);
9243 		break;
9244 	default:
9245 		/* back up to re-read the length field when treating as
9246 		 * opaque */
9247 		offset -= 4;
9248 		offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_netloc);
9249 		break;
9250 	}
9251 
9252 	return offset;
9253 }
9254 
9255 static int
dissect_nfs4_copy_reqs(tvbuff_t * tvb,int offset,proto_tree * tree)9256 dissect_nfs4_copy_reqs(tvbuff_t *tvb, int offset, proto_tree *tree)
9257 {
9258 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_consecutive, offset);
9259 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_synchronous, offset);
9260 
9261 	return offset;
9262 }
9263 
9264 static int
dissect_nfs4_write_response(tvbuff_t * tvb,int offset,proto_tree * tree)9265 dissect_nfs4_write_response(tvbuff_t *tvb, int offset, proto_tree *tree)
9266 {
9267 	proto_item *sub_fitem;
9268 	proto_tree *ss_tree;
9269 	proto_tree *subtree;
9270 	proto_item *ss_fitem;
9271 	guint       i;
9272 	guint32	    count;
9273 
9274 	/* Number of callback stateids */
9275 	sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_callback_stateids,
9276 			tvb, offset, 4, ENC_BIG_ENDIAN, &count);
9277 	offset += 4;
9278 
9279 	subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_callback_stateids_sub);
9280 	for (i = 0; i < count; i++) {
9281 		ss_fitem = proto_tree_add_item(subtree,
9282 				hf_nfs4_callback_stateids_index,
9283 				tvb, offset, 4, i);
9284 
9285 		ss_tree = proto_item_add_subtree(ss_fitem,
9286 				ett_nfs4_callback_stateids_sub);
9287 		offset = dissect_nfs4_stateid(tvb, offset, ss_tree, NULL);
9288 	}
9289 
9290 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
9291 	offset = dissect_nfs4_stable_how(tvb, offset, tree, "committed");
9292 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_verifier, offset);
9293 
9294 	return offset;
9295 }
9296 
9297 static int
dissect_nfs4_source_servers(tvbuff_t * tvb,int offset,proto_tree * tree)9298 dissect_nfs4_source_servers(tvbuff_t *tvb, int offset, proto_tree *tree)
9299 {
9300 	proto_item *sub_fitem;
9301 	proto_tree *ss_tree;
9302 	proto_tree *subtree;
9303 	proto_item *ss_fitem;
9304 	guint       i;
9305 	guint32	    source_servers;
9306 
9307 	/* Number of source servers */
9308 	sub_fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_source_servers,
9309 			tvb, offset, 4, ENC_BIG_ENDIAN, &source_servers);
9310 	offset += 4;
9311 
9312 	subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_source_servers_sub);
9313 	for (i = 0; i < source_servers; i++) {
9314 		ss_fitem = proto_tree_add_item(subtree,
9315 				hf_nfs4_source_server_index,
9316 				tvb, offset, 4, i);
9317 
9318 		ss_tree = proto_item_add_subtree(ss_fitem,
9319 				ett_nfs4_source_servers_sub);
9320 
9321 		offset = dissect_nfs4_netloc(tvb, offset, ss_tree);
9322 	}
9323 
9324 	return offset;
9325 }
9326 
9327 static int
dissect_nfs4_deviceaddr(tvbuff_t * tvb,int offset,proto_tree * tree)9328 dissect_nfs4_deviceaddr(tvbuff_t *tvb, int offset, proto_tree *tree)
9329 {
9330 	guint layout_type;
9331 
9332 	/* layout type */
9333 	layout_type = tvb_get_ntohl(tvb, offset);
9334 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
9335 
9336 	/* skip length */
9337 	offset+=4;
9338 
9339 	switch (layout_type) {
9340 	case LAYOUT4_NFSV4_1_FILES:
9341 		offset = dissect_nfs4_devices_file(tvb, offset, tree);
9342 		break;
9343 	case LAYOUT4_FLEX_FILES:
9344 		offset = dissect_nfs4_devices_flexfile(tvb, offset, tree);
9345 		break;
9346 	case LAYOUT4_SCSI:
9347 		offset = dissect_nfs4_devices_scsi(tvb, offset, tree);
9348 	break;
9349 	default:
9350 		/* back up to re-read the length field when treating as
9351 		 * opaque */
9352 		offset -= 4;
9353 		offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_getdevinfo);
9354 		break;
9355 	}
9356 
9357 	return offset;
9358 }
9359 
9360 
9361 static int
dissect_nfs4_devicelist(tvbuff_t * tvb,int offset,proto_tree * tree)9362 dissect_nfs4_devicelist(tvbuff_t *tvb, int offset, proto_tree *tree)
9363 {
9364 	guint count;
9365 	guint i;
9366 
9367 	count = tvb_get_ntohl(tvb, offset);
9368 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_devicenum, offset);
9369 	for (i = 0; i < count; i++)
9370 		offset = dissect_nfs4_deviceid(tvb, offset, tree);
9371 
9372 	return offset;
9373 }
9374 
9375 
9376 static int
dissect_rpc_serverowner4(tvbuff_t * tvb,int offset,proto_tree * tree)9377 dissect_rpc_serverowner4(tvbuff_t *tvb, int offset, proto_tree *tree)
9378 {
9379 	offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_minorid, offset);
9380 	offset = dissect_nfsdata(tvb, offset, tree, hf_nfs4_majorid);
9381 	return offset;
9382 }
9383 
9384 
9385 static int
dissect_rpc_chanattrs4(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)9386 dissect_rpc_chanattrs4(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
9387 {
9388 	proto_tree *chan_attrs_tree;
9389 	guint i, count, rdma_ird_len;
9390 
9391 	rdma_ird_len = tvb_get_ntohl(tvb, offset + 24);
9392 	count = 28 + rdma_ird_len * 4;
9393 
9394 	chan_attrs_tree = proto_tree_add_subtree(tree, tvb, offset, count, ett_nfs4_chan_attrs, NULL, name);
9395 
9396 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_padsize, offset);
9397 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_maxreqsize, offset);
9398 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_maxrespsize, offset);
9399 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_maxrespsizecached, offset);
9400 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_maxops, offset);
9401 	offset = dissect_rpc_uint32(tvb, chan_attrs_tree, hf_nfs4_maxreqs, offset);
9402 	offset += 4;
9403 	for (i = 0; i < rdma_ird_len; i++) {
9404 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_rdmachanattrs, offset);
9405 	}
9406 	return offset;
9407 }
9408 
9409 
9410 static int
dissect_rpc_nfs_impl_id4(tvbuff_t * tvb,int offset,proto_tree * tree,const char * name)9411 dissect_rpc_nfs_impl_id4(tvbuff_t *tvb, int offset, proto_tree *tree, const char *name)
9412 {
9413 	proto_tree *impl_id_tree;
9414 	guint i, count;
9415 
9416 	count = tvb_get_ntohl(tvb, offset);
9417 	impl_id_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_nfs4_clientowner, NULL, name);
9418 	offset += 4;
9419 
9420 	for (i = 0; i < count; i++) {
9421 		proto_tree *date_tree;
9422 
9423 		offset = dissect_nfs_utf8string(tvb, offset, impl_id_tree, hf_nfs4_nii_domain, NULL);
9424 		offset = dissect_nfs_utf8string(tvb, offset, impl_id_tree, hf_nfs4_nii_name, NULL);
9425 
9426 		date_tree = proto_tree_add_subtree(impl_id_tree, tvb, offset, 12, ett_nfs4_clientowner, NULL, "Build timestamp(nii_date)");
9427 		offset = dissect_nfs4_nfstime(tvb, offset, date_tree);
9428 	}
9429 	return offset;
9430 }
9431 
9432 
9433 static int
dissect_rpc_secparms4(tvbuff_t * tvb,int offset,proto_tree * tree)9434 dissect_rpc_secparms4(tvbuff_t *tvb, int offset, proto_tree *tree)
9435 {
9436 	guint count, i;
9437 
9438 	count = tvb_get_ntohl(tvb, offset);
9439 	offset += 4;
9440 
9441 	for (i = 0; i < count; i++) {
9442 		guint j, flavor = tvb_get_ntohl(tvb, offset);
9443 		offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_flavor, offset);
9444 
9445 		switch (flavor) {
9446 		case 1: { /* AUTH_SYS */
9447 			guint count2;
9448 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_stamp, offset);
9449 			offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_machinename, NULL);
9450 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_uid, offset);
9451 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_gid, offset);
9452 			count2 = tvb_get_ntohl(tvb, offset);
9453 			offset += 4;
9454 			for (j = 0; j < count2; j++) {
9455 				offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_gid, offset);
9456 			}
9457 			break;
9458 		}
9459 		case 6: /* RPCSEC_GSS */
9460 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_service, offset);
9461 			proto_item_append_text(tree, ", Handle from server");
9462 			offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
9463 			proto_item_append_text(tree, ", Handle from client");
9464 			offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
9465 			break;
9466 		default:
9467 			break;
9468 		}
9469 	}
9470 	return offset;
9471 }
9472 
9473 static int
dissect_nfs4_layoutget(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)9474 dissect_nfs4_layoutget(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
9475 {
9476 	guint	    layout_type;
9477 	guint	    sub_num;
9478 	guint	    nfl_util;
9479 	guint	    lo_seg_count;
9480 	guint	    i, j, k, lo_seg;
9481 	proto_tree *newtree;
9482 	proto_item *sub_fitem;
9483 	proto_tree *subtree;
9484 	proto_tree *nfl_item;
9485 	proto_tree *nfl_tree;
9486 
9487 	static int * const layout_flags[] = {
9488 		&hf_nfs4_ff_layout_flags_no_layoutcommit,
9489 		&hf_nfs4_ff_layout_flags_no_io_thru_mds,
9490 		&hf_nfs4_ff_layout_flags_no_read_io,
9491 		NULL
9492 	};
9493 
9494 	lo_seg_count = tvb_get_ntohl(tvb, offset);
9495 
9496 	newtree = proto_tree_add_subtree_format(tree, tvb, offset, 4, ett_nfs4_layoutseg, NULL,
9497 											"Layout Segment (count: %u)", lo_seg_count);
9498 	offset += 4;
9499 
9500 	for (lo_seg = 0; lo_seg < lo_seg_count; lo_seg++) {
9501 		offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_offset, offset);
9502 		offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_length, offset);
9503 
9504 		offset = dissect_rpc_uint32(tvb, newtree, hf_nfs4_iomode, offset);
9505 
9506 		layout_type = tvb_get_ntohl(tvb, offset);
9507 		offset = dissect_rpc_uint32(tvb, newtree, hf_nfs4_layout_type, offset);
9508 
9509 		/* If not files layout type eat the rest and move on.. */
9510 		if (layout_type == LAYOUT4_NFSV4_1_FILES) {
9511 			/* NFS Files */
9512 			offset += 4; /* Skip past opaque count */
9513 
9514 			offset = dissect_nfs4_deviceid(tvb, offset, newtree);
9515 
9516 			/* Get nfl_util and break it down into its components */
9517 			nfl_util = tvb_get_ntohl(tvb, offset);
9518 			nfl_item = proto_tree_add_uint(newtree, hf_nfs4_nfl_util, tvb, offset, 4, nfl_util);
9519 			nfl_tree = proto_item_add_subtree(nfl_item, ett_nfs4_nfl_util);
9520 			proto_tree_add_uint(nfl_tree, hf_nfs4_nfl_util_stripe_size, tvb, offset, 4, nfl_util&NFL4_UFLG_STRIPE_UNIT_SIZE_MASK);
9521 			proto_tree_add_uint(nfl_tree, hf_nfs4_nfl_util_commit_thru_mds, tvb, offset+3, 1, (nfl_util&NFL4_UFLG_COMMIT_THRU_MDS?1:0));
9522 			proto_tree_add_uint(nfl_tree, hf_nfs4_nfl_util_dense, tvb, offset+3, 1, (nfl_util&NFL4_UFLG_DENSE?1:0));
9523 			offset += 4;
9524 
9525 			offset = dissect_rpc_uint32(tvb, newtree,
9526 					hf_nfs4_nfl_first_stripe_index, offset);
9527 			offset = dissect_rpc_uint64(tvb, newtree,
9528 					hf_nfs4_offset, offset);
9529 
9530 			sub_num = tvb_get_ntohl(tvb, offset); /* Len of FH list */
9531 
9532 			sub_fitem = proto_tree_add_item(newtree, hf_nfs4_nfl_fhs,
9533 					tvb, offset, 4, ENC_BIG_ENDIAN);
9534 			offset += 4;
9535 
9536 			subtree = proto_item_add_subtree(sub_fitem,
9537 					ett_nfs4_layoutseg_sub);
9538 			for (i = 0; i < sub_num; i++)
9539 				offset = dissect_nfs4_fh(tvb, offset, pinfo,
9540 						subtree, "lo_filehandle", NULL,
9541 						civ);
9542 		} else if (layout_type == LAYOUT4_FLEX_FILES) {
9543 			guint	ds_count, fh_count;
9544 			proto_item *ds_item, *mirrors_item, *subitem;
9545 			proto_tree *ds_tree, *mirrors_tree;
9546 			int end_offset = offset;
9547 			int mirror_start_offset, ds_start_offset;
9548 
9549 			/* NFS Flex Files */
9550 			end_offset += tvb_get_ntohl(tvb, offset) + 4;
9551 			offset += 4; /* Skip past opaque count */
9552 
9553 			/* stripe unit */
9554 			offset = dissect_rpc_uint64(tvb, newtree, hf_nfs4_stripeunit, offset);
9555 
9556 			/* Len of mirror list */
9557 			sub_num = tvb_get_ntohl(tvb, offset);
9558 			mirrors_item = proto_tree_add_uint_format(newtree, hf_nfs4_nfl_mirrors,
9559 				tvb, offset, 4, sub_num, "Mirrors (%u)", sub_num);
9560 			offset += 4;
9561 
9562 			mirrors_tree = proto_item_add_subtree(mirrors_item, ett_nfs4_layoutseg_sub);
9563 
9564 			for (i = 0; i < sub_num; i++) {
9565 
9566 				mirror_start_offset = offset;
9567 				subtree = proto_tree_add_subtree_format(mirrors_tree, tvb, offset, -1,
9568 						ett_nfs4_layoutseg_sub, &subitem,
9569 						"Mirror: %u", i);
9570 
9571 				/* data server count */
9572 				ds_count = tvb_get_ntohl(tvb, offset);
9573 				offset += 4;
9574 
9575 				for (j = 0; j < ds_count; j++) {
9576 					ds_start_offset = offset;
9577 					ds_tree = proto_tree_add_subtree_format(subtree, tvb, offset, -1,
9578 							ett_nfs4_layoutseg_sub, &ds_item,
9579 							"Data Server: %u", j);
9580 
9581 					offset = dissect_nfs4_deviceid(tvb, offset,
9582 							ds_tree);
9583 					offset = dissect_rpc_uint32(tvb, ds_tree,
9584 							hf_nfs4_mirror_eff, offset);
9585 					offset = dissect_nfs4_stateid(tvb, offset,
9586 							ds_tree, NULL);
9587 
9588 					fh_count = tvb_get_ntohl(tvb, offset);
9589 					offset += 4;
9590 
9591 					for (k = 0; k < fh_count; k++)
9592 						offset = dissect_nfs4_fh(tvb, offset,
9593 							pinfo, ds_tree, "fh", NULL, civ);
9594 
9595 					offset = dissect_nfs_utf8string(tvb, offset,
9596 							ds_tree, hf_nfs4_ff_synthetic_owner,
9597 							NULL);
9598 					offset = dissect_nfs_utf8string(tvb, offset,
9599 							ds_tree, hf_nfs4_ff_synthetic_owner_group,
9600 							NULL);
9601 
9602 					proto_item_set_len(ds_item, offset - ds_start_offset);
9603 				}
9604 
9605 				proto_item_set_len(subitem, offset - mirror_start_offset);
9606 			}
9607 
9608 			proto_tree_add_bitmask(newtree, tvb, offset, hf_nfs4_ff_layout_flags,
9609 						ett_nfs4_ff_layout_flags, layout_flags, ENC_BIG_ENDIAN);
9610 			offset += 4;
9611 
9612 			if (offset + 4 <= end_offset)
9613 				offset = dissect_rpc_uint32(tvb, newtree,
9614 						hf_nfs4_ff_stats_collect_hint,
9615 						offset);
9616 		} else if (layout_type == LAYOUT4_SCSI) {
9617 			guint	ext_count;
9618 			proto_tree *ext_tree;
9619 
9620 			offset += 4; /* Skip past opaque count */
9621 
9622 			ext_count = tvb_get_ntohl(tvb, offset);
9623 
9624 			subtree = proto_tree_add_subtree_format(newtree, tvb, offset, 4,
9625 						ett_nfs4_layoutseg_sub, NULL, "SCSI Extents (count: %u)",
9626 						ext_count);
9627 			offset +=4;
9628 
9629 			for (i = 0; i < ext_count; i++) {
9630 				ext_tree = proto_tree_add_subtree_format(subtree, tvb, offset, 4,
9631 							ett_nfs4_layoutseg_sub, NULL, "extent %u", i);
9632 				offset = dissect_nfs4_deviceid(tvb, offset, ext_tree);
9633 				offset = dissect_rpc_uint64(tvb, ext_tree,
9634 							hf_nfs4_scsil_ext_file_offset, offset);
9635 				offset = dissect_rpc_uint64(tvb, ext_tree,
9636 							hf_nfs4_scsil_ext_length, offset);
9637 				offset = dissect_rpc_uint64(tvb, ext_tree,
9638 							hf_nfs4_scsil_ext_vol_offset, offset);
9639 				offset = dissect_rpc_uint32(tvb, ext_tree,
9640 							hf_nfs4_scsil_ext_state, offset);
9641 			}
9642 		} else {
9643 			offset = dissect_nfsdata(tvb, offset, newtree, hf_nfs4_layout);
9644 			continue;
9645 		}
9646 	}
9647 	return offset;
9648 }
9649 
9650 
9651 static int
dissect_nfs_create_session_flags(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_csa)9652 dissect_nfs_create_session_flags(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_csa)
9653 {
9654 	int * const flags[] = {
9655 		&hf_nfs4_create_session_flags_persist,
9656 		&hf_nfs4_create_session_flags_conn_back_chan,
9657 		&hf_nfs4_create_session_flags_conn_rdma,
9658 		NULL
9659 	};
9660 
9661 	proto_tree_add_bitmask(tree, tvb, offset, hf_csa, ett_nfs4_create_session_flags, flags, ENC_BIG_ENDIAN);
9662 	offset += 4;
9663 
9664 	return offset;
9665 }
9666 
9667 
9668 enum channel_dir_from_client4 {
9669 	CDFC4_FORE = 0x1,
9670 	CDFC4_BACK = 0x2,
9671 	CDFC4_FORE_OR_BOTH = 0x3,
9672 	CDFC4_BACK_OR_BOTH = 0x7
9673 };
9674 
9675 static const value_string names_channel_dir_from_client[] = {
9676 	{ CDFC4_FORE,		"CDFC4_FORE" },
9677 	{ CDFC4_BACK,		"CDFC4_BACK" },
9678 	{ CDFC4_FORE_OR_BOTH,	"CDFC4_FORE_OR_BOTH" },
9679 	{ CDFC4_BACK_OR_BOTH,	"CDFC4_BACK_OR_BOTH" },
9680 	{ 0, NULL }
9681 };
9682 
9683 enum channel_dir_from_server4 {
9684 	CDFS4_FORE = 0x1,
9685 	CDFS4_BACK = 0x2,
9686 	CDFS4_BOTH = 0x3
9687 };
9688 
9689 static const value_string names_channel_dir_from_server[] = {
9690 	{ CDFS4_FORE,	"CDFS4_FORE" },
9691 	{ CDFS4_BACK,	"CDFS4_BACK" },
9692 	{ CDFS4_BOTH,	"CDFS4_BOTH" },
9693 	{ 0, NULL }
9694 };
9695 
9696 #define SECINFO_STYLE4_CURRENT_FH 0
9697 #define SECINFO_STYLE4_PARENT 1
9698 static const value_string names_secinfo_style4[] = {
9699 	{ SECINFO_STYLE4_CURRENT_FH,	"SECINFO_STYLE4_CURRENT_FH" },
9700 	{ SECINFO_STYLE4_PARENT,	"SECINFO_STYLE4_PARENT"     },
9701 	{ 0, NULL }
9702 };
9703 
9704 typedef struct _nfs4_operation_summary {
9705 		guint32	       opcode;
9706 		gboolean       iserror;
9707 		wmem_strbuf_t *optext;
9708 } nfs4_operation_summary;
9709 
9710 
9711 /*
9712  To try to determine which NFSv4 operations are most important in a
9713   request, we categorize the operations into different "tiers".
9714 
9715  All operations falling into the highest tier (where 1 is highest, 5
9716   is lowest) are considered to be the "most significant" operations.
9717   This information is useful for display purposes, filtering, and for
9718   response time calculations.
9719 
9720  For example, virtually all NFSv4 requests include a GETATTR.  But in
9721   a request with PUTFH; CLOSE; GETATTR operations, CLOSE is the
9722   significant operation.
9723 
9724  In a request with PUTFH; GETATTR operations, GETATTR is the
9725   significant operation.  CLOSE has higher tier than GETATTR, which is
9726   in a higher tier than PUTFH.
9727 
9728  In practice this seems to be a very reliable method of determining
9729   the most significant operation(s).
9730  */
9731 
9732 static int nfs4_operation_tiers[] = {
9733 		 1 /* 0 */ ,
9734 		 1 /* 1 */ ,
9735 		 1 /* 2 */ ,
9736 		 2 /* 3, NFS4_OP_ACCESS */ ,
9737 		 1 /* 4, NFS4_OP_CLOSE */,
9738 		 1 /* 5, NFS4_OP_COMMIT	*/,
9739 		 1 /* 6, NFS4_OP_CREATE	*/,
9740 		 1 /* 7, NFS4_OP_DELEGPURGE	*/,
9741 		 1 /* 8, NFS4_OP_DELEGRETURN */,
9742 		 3 /* 9, NFS4_OP_GETATTR */,
9743 		 4 /* 10, NFS4_OP_GETFH	*/,
9744 		 1 /* 11, NFS4_OP_LINK	*/,
9745 		 1 /* 12, NFS4_OP_LOCK */,
9746 		 1 /* 13, NFS4_OP_LOCKT	*/,
9747 		 1 /* 14, NFS4_OP_LOCKU	*/,
9748 		 1 /* 15, NFS4_OP_LOOKUP */,
9749 		 1 /* 16, NFS4_OP_LOOKUPP */,
9750 		 2 /* 17, NFS4_OP_NVERIFY */,
9751 		 1 /* 18, NFS4_OP_OPEN */,
9752 		 1 /* 19, NFS4_OP_OPENATTR */,
9753 		 1 /* 20, NFS4_OP_OPEN_CONFIRM */,
9754 		 1 /* 21, NFS4_OP_OPEN_DOWNGRADE */,
9755 		 4 /* 22, NFS4_OP_PUTFH	*/,
9756 		 3 /* 23, NFS4_OP_PUTPUBFH	*/,
9757 		 3 /* 24, NFS4_OP_PUTROOTFH	*/,
9758 		 1 /* 25, NFS4_OP_READ	*/,
9759 		 1 /* 26, NFS4_OP_READDIR */,
9760 		 1 /* 27, NFS4_OP_READLINK	*/,
9761 		 1 /* 28, NFS4_OP_REMOVE */,
9762 		 1 /* 29, NFS4_OP_RENAME */,
9763 		 1 /* 30, NFS4_OP_RENEW	*/,
9764 		 4 /* 31, NFS4_OP_RESTOREFH	*/,
9765 		 4 /* 32, NFS4_OP_SAVEFH */,
9766 		 1 /* 33, NFS4_OP_SECINFO */,
9767 		 1 /* 34, NFS4_OP_SETATTR */,
9768 		 1 /* 35, NFS4_OP_SETCLIENTID */,
9769 		 1 /* 36, NFS4_OP_SETCLIENTID_CONFIRM */,
9770 		 1 /* 37, NFS4_OP_VERIFY */,
9771 		 1 /* 38, NFS4_OP_WRITE	*/,
9772 		 1 /* 39, NFS4_OP_RELEASE_LOCKOWNER	*/,
9773 			/* Minor version 1 */
9774 		 1 /* 40, NFS4_OP_BACKCHANNEL_CTL */,
9775 		 1 /* 41, NFS4_OP_BIND_CONN_TO_SESSION */,
9776 		 1 /* 42, NFS4_OP_EXCHANGE_ID */,
9777 		 1 /* 43, NFS4_OP_CREATE_SESSION */,
9778 		 1 /* 44, NFS4_OP_DESTROY_SESSION */,
9779 		 1 /* 45, NFS4_OP_FREE_STATEID */,
9780 		 1 /* 46, NFS4_OP_GET_DIR_DELEGATION */,
9781 		 1 /* 47, NFS4_OP_GETDEVINFO */,
9782 		 1 /* 48, NFS4_OP_GETDEVLIST */,
9783 		 1 /* 49, NFS4_OP_LAYOUTCOMMIT */,
9784 		 1 /* 50, NFS4_OP_LAYOUTGET */,
9785 		 1 /* 51, NFS4_OP_LAYOUTRETURN */,
9786 		 1 /* 52, NFS4_OP_SECINFO_NO_NAME */,
9787 		 4 /* 53, NFS4_OP_SEQUENCE */,
9788 		 1 /* 54, NFS4_OP_SET_SSV */,
9789 		 1 /* 55, NFS4_OP_TEST_STATEID */,
9790 		 1 /* 56, NFS4_OP_WANT_DELEGATION  */,
9791 		 1 /* 57, NFS4_OP_DESTROY_CLIENTID  */,
9792 		 1 /* 58, NFS4_OP_RECLAIM_COMPLETE */,
9793 			/* Minor version 2 */
9794 		 1 /* 59, NFS4_OP_ALLOCATE */,
9795 		 1 /* 60, NFS4_OP_COPY */,
9796 		 1 /* 61, NFS4_OP_COPY_NOTIFY */,
9797 		 1 /* 62, NFS4_OP_DEALLOCATE */,
9798 		 1 /* 63, NFS4_OP_IO_ADVISE */,
9799 		 1 /* 64, NFS4_OP_LAYOUTERROR */,
9800 		 1 /* 65, NFS4_OP_LAYOUTSTATS */,
9801 		 1 /* 66, NFS4_OP_OFFLOAD_CANCEL */,
9802 		 1 /* 67, NFS4_OP_OFFLOAD_STATUS */,
9803 		 1 /* 68, NFS4_OP_READ_PLUS */,
9804 		 1 /* 69, NFS4_OP_SEEK */,
9805 		 1 /* 70, NFS4_OP_WRITE_SAME */,
9806 		 1 /* 71, NFS4_OP_CLONE */,
9807 		 1 /* 72, NFS4_OP_GETXATTR */,
9808 		 1 /* 73, NFS4_OP_SETXATTR */,
9809 		 1 /* 74, NFS4_OP_LISTXATTRS */,
9810 		 1 /* 75, NFS4_OP_REMOVEXATTR */,
9811 };
9812 
9813 #define NFS4_OPERATION_TIER(op) \
9814 	((op) < G_N_ELEMENTS(nfs4_operation_tiers) ? nfs4_operation_tiers[(op)] : 0)
9815 
9816 static int * const nfs4_exchid_flags[] = {
9817 	&hf_nfs4_exchid_flags_confirmed_r,
9818 	&hf_nfs4_exchid_flags_upd_conf_rec_a,
9819 	&hf_nfs4_exchid_flags_pnfs_ds,
9820 	&hf_nfs4_exchid_flags_pnfs_mds,
9821 	&hf_nfs4_exchid_flags_non_pnfs,
9822 	&hf_nfs4_exchid_flags_bind_princ,
9823 	&hf_nfs4_exchid_flags_moved_migr,
9824 	&hf_nfs4_exchid_flags_moved_refer,
9825 	NULL
9826 };
9827 
9828 static int
dissect_nfs4_request_op(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)9829 dissect_nfs4_request_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
9830 {
9831 	const char *name	    = NULL;
9832 	const char *source_name	    = NULL;
9833 	const char *dest_name	    = NULL;
9834 	const char *opname	    = NULL;
9835 	guint	    opcode;
9836 	guint	    highest_tier    = 5;
9837 	guint	    current_tier    = 5;
9838 	guint	    first_operation = 1;
9839 	/*guint name_offset = 0;*/
9840 	guint16	    sid_hash;
9841 	guint64	    clientid        = 0;
9842 	guint32	    ops;
9843 	guint32	    ops_counter;
9844 	guint32	    summary_counter;
9845 	guint32	    string_length;
9846 	guint32	    last_fh_hash    = 0;
9847 	guint32	    saved_fh_hash   = 0;
9848 	guint32	    length;
9849 	guint32	    hash;
9850 	guint64	    length64;
9851 	guint64	    file_offset;
9852 	proto_item *fitem;
9853 	proto_tree *ftree;
9854 	proto_tree *newftree	    = NULL;
9855 	nfs4_operation_summary *op_summary;
9856 	guint16     dst_sid_hash;
9857 	guint64     dst_file_offset;
9858 
9859 	ops = tvb_get_ntohl(tvb, offset+0);
9860 
9861 	fitem = proto_tree_add_uint_format(tree, hf_nfs4_ops_count, tvb, offset+0, 4, ops,
9862 		"Operations (count: %u)", ops);
9863 	offset += 4;
9864 
9865 #define MAX_NFSV4_OPS 128
9866 	if (ops > MAX_NFSV4_OPS) {
9867 		/*  Limit the number of operations to something "reasonable."
9868 		 *  This is an arbitrary number to keep us from attempting to
9869 		 *  allocate too much memory below.
9870 		 */
9871 		expert_add_info(pinfo, fitem, &ei_nfs_too_many_ops);
9872 		ops = MAX_NFSV4_OPS;
9873 	}
9874 
9875 	op_summary = wmem_alloc0_array(wmem_packet_scope(), nfs4_operation_summary, ops);
9876 
9877 	ftree = proto_item_add_subtree(fitem, ett_nfs4_request_op);
9878 
9879 	if (ops)
9880 		proto_item_append_text(proto_tree_get_parent(tree), ", Ops(%d):", ops);
9881 
9882 	for (ops_counter=0; ops_counter<ops; ops_counter++)
9883 	{
9884 		op_summary[ops_counter].optext = wmem_strbuf_new(wmem_packet_scope(), "");
9885 		opcode = tvb_get_ntohl(tvb, offset);
9886 		op_summary[ops_counter].opcode = opcode;
9887 
9888 		fitem = proto_tree_add_uint(ftree, hf_nfs4_op, tvb, offset, 4, opcode);
9889 
9890 		/* the opcodes are not contiguous */
9891 		if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_LAST_OP)
9892 		&&  opcode != NFS4_OP_ILLEGAL)
9893 			break;
9894 
9895 		/* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
9896 		if (opcode == NFS4_OP_ILLEGAL) {
9897 			newftree = proto_item_add_subtree(fitem, ett_nfs4_illegal);
9898 		} else if (nfs4_operation_ett[opcode - 3]) {
9899 			newftree = proto_item_add_subtree(fitem, *nfs4_operation_ett[opcode - 3]);
9900 		} else {
9901 			break;
9902 		}
9903 
9904 		opname = val_to_str_ext_const(opcode, &names_nfs4_operation_ext, "Unknown");
9905 		offset += 4;
9906 
9907 		wmem_strbuf_append_printf(op_summary[ops_counter].optext, "%s", opname);
9908 
9909 		proto_item_append_text(proto_tree_get_parent(tree),
9910 			"%s%s", ops_counter ? ", " : " ", opname);
9911 		proto_item_append_text(proto_tree_get_parent(ftree),
9912 			"%s%s", ops_counter ? ", " : ": ", opname);
9913 
9914 		switch (opcode)
9915 		{
9916 		case NFS4_OP_ACCESS:
9917 			{
9918 				guint32 *acc_request, amask;
9919 
9920 				/* Get access mask to check and save it for comparison in the reply. */
9921 				amask = tvb_get_ntohl(tvb, offset);
9922 				acc_request = (guint32 *)wmem_memdup(wmem_file_scope(),  &amask, sizeof(guint32));
9923 				civ->private_data = acc_request;
9924 
9925 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash);
9926 				display_access_items(tvb, offset, pinfo, fitem, amask, 'C', 4,
9927 					op_summary[ops_counter].optext, "Check") ;
9928 				offset+=4;
9929 			}
9930 			break;
9931 
9932 		case NFS4_OP_CLOSE:
9933 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
9934 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
9935 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " StateID: 0x%04x", sid_hash);
9936 			break;
9937 
9938 		case NFS4_OP_COMMIT:
9939 			file_offset = tvb_get_ntoh64(tvb, offset);
9940 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
9941 			length = tvb_get_ntohl(tvb, offset);
9942 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
9943 			wmem_strbuf_append_printf (op_summary[ops_counter].optext,
9944 				" FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Len: %u",
9945 				last_fh_hash, file_offset, length);
9946 
9947 			break;
9948 
9949 		case NFS4_OP_CREATE:
9950 			{
9951 				guint create_type;
9952 
9953 				create_type = tvb_get_ntohl(tvb, offset);
9954 				offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_ftype, offset);
9955 
9956 				switch (create_type)
9957 				{
9958 				case NF4LNK:
9959 					offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_linktext, NULL);
9960 					break;
9961 
9962 				case NF4BLK:
9963 				case NF4CHR:
9964 					offset = dissect_nfs4_specdata(tvb, offset, newftree);
9965 					break;
9966 
9967 				case NF4SOCK:
9968 				case NF4FIFO:
9969 				case NF4DIR:
9970 					break;
9971 
9972 				default:
9973 					break;
9974 				}
9975 
9976 				offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, NULL);
9977 				offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
9978 			}
9979 			break;
9980 
9981 		case NFS4_OP_DELEGPURGE:
9982 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
9983 			break;
9984 
9985 		case NFS4_OP_DELEGRETURN:
9986 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
9987 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " StateID: 0x%04x", sid_hash);
9988 			break;
9989 
9990 		case NFS4_OP_GETATTR:
9991 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ);
9992 
9993 			if (last_fh_hash != 0)
9994 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash);
9995 
9996 			break;
9997 
9998 		case NFS4_OP_GETFH:
9999 			last_fh_hash = 0;
10000 			break;
10001 
10002 		case NFS4_OP_LINK:
10003 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, NULL);
10004 			break;
10005 
10006 		case NFS4_OP_LOCK:
10007 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_lock_type, offset);
10008 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_lock_reclaim, offset);
10009 			file_offset = tvb_get_ntoh64(tvb, offset);
10010 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10011 			length64 = tvb_get_ntoh64(tvb, offset);
10012 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10013 			offset = dissect_nfs4_locker(tvb, offset, newftree);
10014 			if (length64 == G_GUINT64_CONSTANT(0xffffffffffffffff))
10015 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10016 					" FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: <End of File>",
10017 					last_fh_hash, file_offset);
10018 			else
10019 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10020 					" FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: %"G_GINT64_MODIFIER"u ",
10021 					last_fh_hash, file_offset, length64);
10022 			break;
10023 
10024 		case NFS4_OP_LOCKT:
10025 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_lock_type, offset);
10026 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10027 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10028 			offset = dissect_nfs4_lock_owner(tvb, offset, newftree);
10029 			break;
10030 
10031 		case NFS4_OP_LOCKU:
10032 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_lock_type, offset);
10033 			offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_seqid, offset);
10034 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10035 			file_offset = tvb_get_ntoh64(tvb, offset);
10036 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10037 			length64 = tvb_get_ntoh64(tvb, offset);
10038 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10039 			if (length64 == G_GUINT64_CONSTANT(0xffffffffffffffff))
10040 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10041 					" FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: <End of File>",
10042 					last_fh_hash, file_offset);
10043 			else
10044 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10045 					" FH: 0x%08x Offset: %"G_GINT64_MODIFIER"u Length: %"G_GINT64_MODIFIER"u ",
10046 					last_fh_hash, file_offset, length64);
10047 			break;
10048 
10049 		case NFS4_OP_LOOKUP:
10050 			/*name_offset = offset;*/
10051 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &name);
10052 			if (nfs_file_name_snooping) {
10053 				nfs_name_snoop_add_name(civ->xid, tvb,
10054 										/*name_offset, strlen(name), */
10055 										0, 0,
10056 										0, 0, name);
10057 			}
10058 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " ");
10059 			if (last_fh_hash != 0)
10060 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash);
10061 			if (name != NULL)
10062 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "%s", name);
10063 			break;
10064 
10065 		case NFS4_OP_LOOKUPP:
10066 			break;
10067 
10068 		case NFS4_OP_NVERIFY:
10069 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
10070 			if (last_fh_hash != 0)
10071 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash);
10072 			break;
10073 
10074 		case NFS4_OP_OPEN:
10075 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10076 			offset = dissect_nfs4_open_share_access(tvb, offset, newftree);
10077 			offset = dissect_nfs4_open_share_deny(tvb, offset, newftree);
10078 			offset = dissect_nfs4_open_owner(tvb, offset, newftree);
10079 			offset = dissect_nfs4_openflag(tvb, offset, pinfo, newftree, civ);
10080 			offset = dissect_nfs4_open_claim(tvb, offset, pinfo, newftree, &name, civ);
10081 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " ");
10082 			if (last_fh_hash != 0)
10083 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash);
10084 			if (name != NULL)
10085 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "%s", name);
10086 			break;
10087 
10088 		case NFS4_OP_OPENATTR:
10089 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_attr_dir_create, offset);
10090 			break;
10091 
10092 		case NFS4_OP_OPEN_CONFIRM:
10093 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10094 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10095 			break;
10096 
10097 		case NFS4_OP_OPEN_DOWNGRADE:
10098 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10099 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10100 			offset = dissect_nfs4_open_share_access(tvb, offset, newftree);
10101 			offset = dissect_nfs4_open_share_deny(tvb, offset, newftree);
10102 			break;
10103 
10104 		case NFS4_OP_PUTFH:
10105 			offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", &last_fh_hash, civ);
10106 			break;
10107 
10108 		case NFS4_OP_PUTPUBFH:
10109 		case NFS4_OP_PUTROOTFH:
10110 			break;
10111 
10112 		case NFS4_OP_READ:
10113 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10114 			file_offset = tvb_get_ntoh64(tvb, offset);
10115 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10116 			length = tvb_get_ntohl(tvb, offset);
10117 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
10118 			if (sid_hash != 0)
10119 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10120 					" StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
10121 					sid_hash, file_offset, length);
10122 			break;
10123 
10124 		case NFS4_OP_READDIR:
10125 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie, offset);
10126 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie_verf,	offset);
10127 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_dircount, offset);
10128 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_maxcount, offset);
10129 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ);
10130 			if (last_fh_hash != 0)
10131 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash);
10132 			break;
10133 
10134 		case NFS4_OP_READLINK:
10135 			break;
10136 
10137 		case NFS4_OP_TEST_STATEID:
10138 			offset = dissect_rpc_array(tvb, pinfo, newftree, offset, dissect_nfs4_test_stateid_arg, hf_nfs4_test_stateid_arg);
10139 			break;
10140 
10141 		case NFS4_OP_DESTROY_CLIENTID:
10142 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
10143 			break;
10144 		case NFS4_OP_RECLAIM_COMPLETE:
10145 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_reclaim_one_fs, offset);
10146 			break;
10147 
10148 		case NFS4_OP_REMOVE:
10149 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &name);
10150 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " ");
10151 			if (last_fh_hash != 0)
10152 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "DH: 0x%08x/", last_fh_hash);
10153 			if (name != NULL)
10154 				wmem_strbuf_append_printf (op_summary[ops_counter].optext, "%s", name);
10155 			break;
10156 
10157 		case NFS4_OP_RENAME:
10158 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &source_name);
10159 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_component, &dest_name);
10160 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " From: %s To: %s",
10161 				source_name ? source_name : "Unknown", dest_name ? dest_name : "Unknown");
10162 			break;
10163 
10164 		case NFS4_OP_RENEW:
10165 			clientid = tvb_get_ntoh64(tvb, offset);
10166 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
10167 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " CID: 0x%016"G_GINT64_MODIFIER"x", clientid);
10168 
10169 			break;
10170 
10171 		case NFS4_OP_RESTOREFH:
10172 			last_fh_hash = saved_fh_hash;
10173 			break;
10174 
10175 		case NFS4_OP_SAVEFH:
10176 			saved_fh_hash = last_fh_hash;
10177 			break;
10178 
10179 		case NFS4_OP_SECINFO:
10180 			offset = dissect_nfs_utf8string(tvb, offset, newftree,
10181 				hf_nfs4_component, NULL);
10182 			break;
10183 
10184 		case NFS4_OP_SECINFO_NO_NAME:
10185 			proto_tree_add_item(newftree, hf_nfs4_secinfo_style, tvb, offset, 4, ENC_BIG_ENDIAN);
10186 			offset += 4;
10187 			break;
10188 
10189 		case NFS4_OP_SETATTR:
10190 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10191 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
10192 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " FH: 0x%08x", last_fh_hash);
10193 			break;
10194 
10195 		case NFS4_OP_SETCLIENTID:
10196 			{
10197 				proto_tree *client_tree = NULL;
10198 				proto_tree *callback_tree = NULL;
10199 
10200 				client_tree = proto_tree_add_subtree(newftree, tvb, offset, 0, ett_nfs4_client_id, NULL, "client");
10201 
10202 				offset = dissect_nfs4_client_id(tvb, offset, client_tree);
10203 
10204 				callback_tree = proto_tree_add_subtree(newftree, tvb, offset, 0, ett_nfs4_cb_client, NULL, "callback");
10205 
10206 				offset = dissect_nfs4_cb_client4(tvb, offset, callback_tree);
10207 
10208 				offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_callback_ident,
10209 					offset);
10210 			}
10211 			break;
10212 
10213 		case NFS4_OP_SETCLIENTID_CONFIRM:
10214 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
10215 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset);
10216 			break;
10217 
10218 		case NFS4_OP_VERIFY:
10219 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
10220 			break;
10221 
10222 		case NFS4_OP_WRITE:
10223 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10224 			file_offset = tvb_get_ntoh64(tvb, offset);
10225 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10226 			offset = dissect_nfs4_stable_how(tvb, offset, newftree, "stable");
10227 			string_length = tvb_get_ntohl(tvb, offset+0);
10228 			dissect_rpc_uint32(tvb, newftree, hf_nfs4_write_data_length, offset); /* don't change offset */
10229 			offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
10230 			if (sid_hash != 0)
10231 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10232 					" StateID: 0x%04x Offset: %"G_GINT64_MODIFIER"u Len: %u",
10233 					sid_hash, file_offset, string_length);
10234 			break;
10235 
10236 		case NFS4_OP_RELEASE_LOCKOWNER:
10237 			offset = dissect_nfs4_lock_owner(tvb, offset, newftree);
10238 			break;
10239 
10240 			/* Minor Version 1 */
10241 		case NFS4_OP_BACKCHANNEL_CTL:
10242 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_cb_program, offset);
10243 			offset = dissect_rpc_secparms4(tvb, offset, newftree);
10244 			break;
10245 		case NFS4_OP_BIND_CONN_TO_SESSION:
10246 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10247 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_bctsa_dir, offset);
10248 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_bctsa_use_conn_in_rdma_mode, offset);
10249 			break;
10250 
10251 		case NFS4_OP_EXCHANGE_ID:
10252 			{
10253 			proto_tree *eia_clientowner_tree;
10254 
10255 			eia_clientowner_tree = proto_tree_add_subtree(newftree, tvb, offset, 0, ett_nfs4_clientowner, NULL, "eia_clientowner");
10256 			offset = dissect_rpc_uint64(tvb, eia_clientowner_tree, hf_nfs4_verifier, offset);
10257 			offset = dissect_nfsdata(tvb, offset, eia_clientowner_tree, hf_nfs_data);
10258 
10259 			proto_tree_add_bitmask(eia_clientowner_tree, tvb, offset, hf_nfs4_exchid_call_flags, ett_nfs4_exchangeid_call_flags, nfs4_exchid_flags, ENC_BIG_ENDIAN);
10260 			offset += 4;
10261 
10262 			offset = dissect_nfs4_state_protect_a(tvb, offset, pinfo, newftree);
10263 			offset = dissect_rpc_nfs_impl_id4(tvb, offset, newftree, "eia_client_impl_id");
10264 			}
10265 			break;
10266 
10267 		case NFS4_OP_CREATE_SESSION:
10268 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
10269 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10270 			offset = dissect_nfs_create_session_flags(tvb, offset, newftree,
10271 				hf_nfs4_create_session_flags_csa);
10272 			offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_fore_chan_attrs");
10273 			offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csa_back_chan_attrs");
10274 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_cb_program, offset);
10275 			offset = dissect_rpc_secparms4(tvb, offset, newftree);
10276 			break;
10277 
10278 		case NFS4_OP_DESTROY_SESSION:
10279 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10280 			break;
10281 		case NFS4_OP_FREE_STATEID:
10282 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10283 			wmem_strbuf_append_printf(op_summary[ops_counter].optext, " StateID: 0x%04x", sid_hash);
10284 			break;
10285 
10286 			/* pNFS */
10287 		case NFS4_OP_LAYOUTGET:
10288 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_layout_avail, offset);
10289 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
10290 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_iomode, offset);
10291 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10292 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10293 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length_minlength, offset);
10294 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10295 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_maxcount,
10296 										offset);
10297 			break;
10298 
10299 		case NFS4_OP_LAYOUTCOMMIT:
10300 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10301 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10302 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_reclaim, offset);
10303 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10304 			offset = dissect_nfs4_newoffset(tvb, offset, newftree);
10305 			offset = dissect_nfs4_newtime(tvb, offset, newftree);
10306 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
10307 			offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs4_layoutupdate);
10308 			break;
10309 
10310 		case NFS4_OP_LAYOUTRETURN:
10311 			offset = dissect_nfs4_layoutreturn(tvb, offset, pinfo, newftree, civ);
10312 			break;
10313 
10314 		case NFS4_OP_GETDEVINFO:
10315 			offset = dissect_nfs4_deviceid(tvb, offset, newftree);
10316 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
10317 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_maxcount, offset);
10318 			offset = dissect_nfs4_notification_bitmap(tvb, newftree, pinfo, offset);
10319 			break;
10320 
10321 		case NFS4_OP_GETDEVLIST:
10322 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_layout_type, offset);
10323 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count_maxcount, offset);
10324 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie, offset);
10325 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie_verf,	offset);
10326 			break;
10327 
10328 		case NFS4_OP_SEQUENCE:
10329 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10330 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10331 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_slotid, offset);
10332 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_high_slotid, offset);
10333 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_cachethis, offset);
10334 			break;
10335 
10336 		case NFS4_OP_ALLOCATE:
10337 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10338 			file_offset = tvb_get_ntoh64(tvb, offset);
10339 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10340 			length64 = tvb_get_ntoh64(tvb, offset);
10341 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10342 			if (sid_hash != 0)
10343 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10344 					" StateID: 0x%04x"
10345 					" Offset: %" G_GINT64_MODIFIER "u"
10346 					" Len: %" G_GINT64_MODIFIER "u",
10347 					sid_hash, file_offset, length64);
10348 			break;
10349 
10350 		case NFS4_OP_COPY:
10351 
10352 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10353 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
10354 			file_offset = tvb_get_ntoh64(tvb, offset);
10355 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10356 			dst_file_offset = tvb_get_ntoh64(tvb, offset);
10357 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10358 			length64 = tvb_get_ntoh64(tvb, offset);
10359 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10360 			if (sid_hash != 0)
10361 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10362 					" Src StateID: 0x%04x"
10363 					" Offset: %" G_GINT64_MODIFIER "u"
10364 					" Len: %" G_GINT64_MODIFIER "u",
10365 					sid_hash, file_offset, length64);
10366 
10367 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_consecutive, offset);
10368 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_synchronous, offset);
10369 
10370 			/* FIXME: Report consecutive and sync? */
10371 
10372 			if (dst_sid_hash != 0)
10373 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10374 					" Dst StateID: 0x%04x"
10375 					" Offset: %" G_GINT64_MODIFIER "u",
10376 					dst_sid_hash, dst_file_offset);
10377 
10378 			offset = dissect_nfs4_source_servers(tvb, offset, newftree);
10379 			break;
10380 
10381 		case NFS4_OP_COPY_NOTIFY:
10382 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10383 			if (sid_hash != 0)
10384 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10385 					" StateID: 0x%04x",
10386 					sid_hash);
10387 
10388 			offset = dissect_nfs4_netloc(tvb, offset, newftree);
10389 
10390 			break;
10391 
10392 		case NFS4_OP_DEALLOCATE:
10393 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10394 			file_offset = tvb_get_ntoh64(tvb, offset);
10395 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10396 			length64 = tvb_get_ntoh64(tvb, offset);
10397 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10398 			if (sid_hash != 0)
10399 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10400 					" StateID: 0x%04x"
10401 					" Offset: %" G_GINT64_MODIFIER "u"
10402 					" Len: %" G_GINT64_MODIFIER "u",
10403 					sid_hash, file_offset, length64);
10404 			break;
10405 
10406 		case NFS4_OP_IO_ADVISE:
10407 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10408 			file_offset = tvb_get_ntoh64(tvb, offset);
10409 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10410 			length64 = tvb_get_ntoh64(tvb, offset);
10411 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10412 			if (sid_hash != 0)
10413 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10414 					" StateID: 0x%04x"
10415 					" Offset: %" G_GINT64_MODIFIER "u"
10416 					" Len: %" G_GINT64_MODIFIER "u",
10417 					sid_hash, file_offset, length64);
10418 			offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
10419 			break;
10420 
10421 		case NFS4_OP_OFFLOAD_CANCEL:
10422 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10423 			if (sid_hash != 0)
10424 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10425 					" StateID: 0x%04x",
10426 					sid_hash);
10427 			break;
10428 
10429 		case NFS4_OP_OFFLOAD_STATUS:
10430 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10431 			if (sid_hash != 0)
10432 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10433 					" StateID: 0x%04x",
10434 					sid_hash);
10435 			break;
10436 
10437 		case NFS4_OP_READ_PLUS:
10438 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10439 			file_offset = tvb_get_ntoh64(tvb, offset);
10440 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10441 			length = tvb_get_ntohl(tvb, offset);
10442 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
10443 			if (sid_hash != 0)
10444 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10445 					" StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
10446 					sid_hash, file_offset, length);
10447 			break;
10448 
10449 		case NFS4_OP_LAYOUTERROR:
10450 			file_offset = tvb_get_ntoh64(tvb, offset);
10451 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10452 			length = tvb_get_ntohl(tvb, offset);
10453 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10454 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10455 			if (sid_hash != 0)
10456 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10457 					" StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
10458 					sid_hash, file_offset, length);
10459 			offset = dissect_nfs4_device_errors(tvb, offset, newftree);
10460 			break;
10461 
10462 		case NFS4_OP_LAYOUTSTATS:
10463 			file_offset = tvb_get_ntoh64(tvb, offset);
10464 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10465 			length = tvb_get_ntohl(tvb, offset);
10466 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10467 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10468 			if (sid_hash != 0)
10469 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10470 					" StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u Len: %u",
10471 					sid_hash, file_offset, length);
10472 			offset = dissect_nfs4_layoutstats(tvb, offset, pinfo, newftree, civ, TRUE);
10473 			break;
10474 
10475 		case NFS4_OP_SEEK:
10476 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10477 			file_offset = tvb_get_ntoh64(tvb, offset);
10478 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10479 			proto_tree_add_item(newftree, hf_nfs4_seek_data_content, tvb,
10480 						offset, 4, ENC_BIG_ENDIAN);
10481 			offset += 4;
10482 			if (sid_hash != 0)
10483 				wmem_strbuf_append_printf(op_summary[ops_counter].optext,
10484 					" StateID: 0x%04x Offset: %" G_GINT64_MODIFIER "u",
10485 					sid_hash, file_offset);
10486 			break;
10487 
10488 		case NFS4_OP_WRITE_SAME:
10489 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10490 			offset = dissect_nfs4_stable_how(tvb, offset, newftree, "stable");
10491 			offset = dissect_nfs4_app_data_block(tvb, offset, newftree, &hash);
10492 			wmem_strbuf_append_printf(op_summary[ops_counter].optext,
10493 				"Pattern Hash: 0x%08x", hash);
10494 
10495 			break;
10496 
10497 		case NFS4_OP_CLONE:
10498 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10499 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &dst_sid_hash);
10500 			file_offset = tvb_get_ntoh64(tvb, offset);
10501 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10502 			dst_file_offset = tvb_get_ntoh64(tvb, offset);
10503 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
10504 			length64 = tvb_get_ntoh64(tvb, offset);
10505 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
10506 			if (sid_hash != 0)
10507 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10508 					" Src StateID: 0x%04x"
10509 					" Offset: %" G_GINT64_MODIFIER "u"
10510 					" Len: %" G_GINT64_MODIFIER "u",
10511 					sid_hash, file_offset, length64);
10512 
10513 			if (dst_sid_hash != 0)
10514 				wmem_strbuf_append_printf (op_summary[ops_counter].optext,
10515 					" Dst StateID: 0x%04x"
10516 					" Offset: %" G_GINT64_MODIFIER "u",
10517 					dst_sid_hash, dst_file_offset);
10518 
10519 			break;
10520 
10521 		case NFS4_OP_GETXATTR:
10522 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_xattrkey, NULL);
10523 			break;
10524 
10525 		case NFS4_OP_SETXATTR:
10526 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_setxattr_options, offset);
10527 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_xattrkey, NULL);
10528 			offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
10529 			break;
10530 
10531 		case NFS4_OP_LISTXATTRS:
10532 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_listxattr_cookie, offset);
10533 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_listxattr_maxcount, offset);
10534 			break;
10535 
10536 		case NFS4_OP_REMOVEXATTR:
10537 			offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs4_xattrkey, NULL);
10538 			break;
10539 
10540 		/* In theory, it's possible to get this opcode */
10541 		case NFS4_OP_ILLEGAL:
10542 			break;
10543 
10544 		default:
10545 			break;
10546 		}
10547 	}
10548 
10549 	/* Detect which tiers are present in this packet */
10550 	for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
10551 	{
10552 		current_tier = NFS4_OPERATION_TIER(op_summary[summary_counter].opcode);
10553 		if (current_tier < highest_tier)
10554 			highest_tier = current_tier;
10555 	}
10556 
10557 	/* Display packet summary */
10558 	for (summary_counter=0; summary_counter < ops_counter; summary_counter++)
10559 	{
10560 		guint main_opcode;
10561 		proto_item *main_op_item = NULL;
10562 
10563 		main_opcode = op_summary[summary_counter].opcode;
10564 		current_tier = NFS4_OPERATION_TIER(op_summary[summary_counter].opcode);
10565 
10566 		/* Display summary info only for operations that are "most significant".
10567 		   Controlled by a user option. */
10568 		if (current_tier == highest_tier || !display_major_nfs4_ops) {
10569 			if (current_tier == highest_tier) {
10570 				const char *main_opname = NULL;
10571 
10572 				/* Display a filterable field of the most significant operations in all cases. */
10573 				main_opname = val_to_str_ext_const(main_opcode, &names_nfs4_operation_ext, "Unknown");
10574 				main_op_item = proto_tree_add_uint_format_value(tree, hf_nfs4_main_opcode, tvb, 0, 0,
10575 							      main_opcode, "%s (%u)", main_opname, main_opcode);
10576 				proto_item_set_generated(main_op_item);
10577 			}
10578 
10579 			if (first_operation == 0)
10580 				/* Seperator between operation text */
10581 				col_append_str(pinfo->cinfo, COL_INFO, " |");
10582 
10583 			if (wmem_strbuf_get_len(op_summary[summary_counter].optext) > 0)
10584 				col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
10585 					wmem_strbuf_get_str(op_summary[summary_counter].optext));
10586 
10587 			first_operation = 0;
10588 		}
10589 	}
10590 
10591 	return offset;
10592 }
10593 
10594 
10595 static int
dissect_nfs4_compound_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)10596 dissect_nfs4_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
10597 {
10598 	const char *tag = NULL;
10599 	int offset = 0;
10600 
10601 	offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
10602 	/*
10603 	 * Display the NFSv4 tag.  If it is empty, string generator will have returned "<EMPTY>",
10604 	 * in which case don't display anything */
10605 	if (nfs_display_v4_tag && strncmp(tag, "<EMPTY>", 7) != 0)
10606 		col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tag);
10607 
10608 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_minorversion, offset);
10609 	offset = dissect_nfs4_request_op(tvb, offset, pinfo, tree, (rpc_call_info_value*)data);
10610 
10611 	return offset;
10612 }
10613 
10614 
10615 static int
dissect_nfs4_secinfo_res(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)10616 dissect_nfs4_secinfo_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
10617 	proto_tree *tree, void *data _U_)
10618 {
10619 	guint flavor;
10620 	proto_item *fitem;
10621 	proto_tree *secftree;
10622 
10623 	fitem = proto_tree_add_item_ret_uint(tree, hf_nfs4_secinfo_flavor, tvb, offset, 4,
10624 		ENC_BIG_ENDIAN, &flavor);
10625 	offset += 4;
10626 
10627 	switch (flavor)
10628 	{
10629 		case RPCSEC_GSS:
10630 			secftree = proto_item_add_subtree(fitem, ett_nfs4_secinfo_flavor_info);
10631 			offset = dissect_nfs_rpcsec_gss_info(tvb, offset, secftree);
10632 			break;
10633 
10634 		default:
10635 			break;
10636 	}
10637 
10638 	return offset;
10639 }
10640 
10641 
10642 static int
dissect_nfs4_offload_status_res(tvbuff_t * tvb,int offset,proto_tree * tree)10643 dissect_nfs4_offload_status_res(tvbuff_t *tvb, int offset, proto_tree *tree)
10644 {
10645 	proto_item *sub_fitem;
10646 	proto_tree *ss_tree;
10647 	proto_tree *subtree;
10648 	proto_item *ss_fitem;
10649 	guint       i;
10650 	guint32	    count;
10651 
10652 	/* Number of osr_complete status */
10653 	sub_fitem = proto_tree_add_item_ret_uint(tree,
10654 			hf_nfs4_num_offload_status, tvb, offset, 4,
10655 			ENC_BIG_ENDIAN, &count);
10656 	offset += 4;
10657 
10658 	subtree = proto_item_add_subtree(sub_fitem, ett_nfs4_osr_complete_sub);
10659 	for (i = 0; i < count; i++) {
10660 		ss_fitem = proto_tree_add_item(subtree,
10661 				hf_nfs4_offload_status_index,
10662 				tvb, offset, 4, ENC_BIG_ENDIAN);
10663 
10664 		ss_tree = proto_item_add_subtree(ss_fitem,
10665 				ett_nfs4_osr_complete_sub);
10666 
10667 		offset = dissect_rpc_uint32(tvb, ss_tree, hf_nfs4_status, offset);
10668 	}
10669 
10670 	return offset;
10671 }
10672 
10673 static int
dissect_nfs4_response_op(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)10674 dissect_nfs4_response_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
10675 {
10676 	guint	    highest_tier    = 5;
10677 	guint	    current_tier    = 5;
10678 	guint	    first_operation = 1;
10679 	guint16	    sid_hash	    = 0;
10680 	guint32	    last_fh_hash    = 0;
10681 	guint32	    ops, ops_counter;
10682 	guint32	    summary_counter;
10683 	guint32	    opcode, status;
10684 	const char *opname;
10685 	proto_item *fitem, *ti;
10686 	proto_tree *ftree	    = NULL;
10687 	proto_tree *newftree	    = NULL;
10688 	nfs4_operation_summary *op_summary;
10689 
10690 	ops = tvb_get_ntohl(tvb, offset+0);
10691 
10692 	fitem = proto_tree_add_uint_format(tree, hf_nfs4_ops_count, tvb, offset+0, 4, ops,
10693 		"Operations (count: %u)", ops);
10694 	offset += 4;
10695 
10696 	if (ops > MAX_NFSV4_OPS) {
10697 		expert_add_info(pinfo, fitem, &ei_nfs_too_many_ops);
10698 		ops = MAX_NFSV4_OPS;
10699 	}
10700 
10701 	op_summary = wmem_alloc0_array(wmem_packet_scope(), nfs4_operation_summary, ops);
10702 
10703 	ftree = proto_item_add_subtree(fitem, ett_nfs4_response_op);
10704 
10705 	proto_item_append_text(tree, ", Ops(%d):", ops);
10706 
10707 	for (ops_counter = 0; ops_counter < ops; ops_counter++)
10708 	{
10709 		op_summary[ops_counter].optext = wmem_strbuf_new(wmem_packet_scope(), "");
10710 		opcode = tvb_get_ntohl(tvb, offset);
10711 		op_summary[ops_counter].iserror = FALSE;
10712 		op_summary[ops_counter].opcode = opcode;
10713 
10714 		/* sanity check for bogus packets */
10715 		if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_LAST_OP) &&
10716 			(opcode != NFS4_OP_ILLEGAL))
10717 			break;
10718 
10719 		fitem = proto_tree_add_uint(ftree, hf_nfs4_op, tvb, offset, 4, opcode);
10720 
10721 		/* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
10722 		if (opcode == NFS4_OP_ILLEGAL) {
10723 			newftree = proto_item_add_subtree(fitem, ett_nfs4_illegal);
10724 		} else if (nfs4_operation_ett[opcode - 3]) {
10725 			newftree = proto_item_add_subtree(fitem, *nfs4_operation_ett[opcode - 3]);
10726 		} else {
10727 			break;
10728 		}
10729 
10730 		opname = val_to_str_ext_const(opcode, &names_nfs4_operation_ext, "Unknown");
10731 		offset += 4;
10732 		wmem_strbuf_append_printf (op_summary[ops_counter].optext, "%s", opname);
10733 
10734 		offset = dissect_nfs4_status(tvb, offset, newftree, &status);
10735 		if (status != NFS4_OK) {
10736 			proto_item_append_text(tree, " %s(%s)", opname,
10737 				val_to_str_ext(status, &names_nfs4_status_ext, "Unknown error: %u"));
10738 		} else {
10739 			proto_item_append_text(tree, " %s", opname);
10740 		}
10741 
10742 		/*
10743 		 * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT,
10744 		 * NFS4_OP_SETATTR, NFS4_OP_SETCLIENTID, and NFS4_OP_COPY, all other
10745 		 * ops do *not* return data with the failed status code.
10746 		 */
10747 		if (status != NFS4_OK
10748 		&& opcode != NFS4_OP_LOCK
10749 		&& opcode != NFS4_OP_LOCKT
10750 		&& opcode != NFS4_OP_SETATTR
10751 		&& opcode != NFS4_OP_SETCLIENTID
10752 		&& opcode != NFS4_OP_COPY) {
10753 			op_summary[ops_counter].iserror = TRUE;
10754 			continue;
10755 		}
10756 
10757 		/* These parsing routines are only executed if the status is NFS4_OK */
10758 		switch (opcode)
10759 		{
10760 		case NFS4_OP_ACCESS:
10761 			offset = dissect_access_reply(tvb, offset, pinfo, fitem, 4,	op_summary[ops_counter].optext, civ);
10762 			break;
10763 
10764 		case NFS4_OP_CLOSE:
10765 			ti = proto_tree_add_item(newftree, hf_nfs4_stateid, tvb, offset, 16, ENC_NA);
10766 			expert_add_info(pinfo, ti, &ei_nfs4_stateid_deprecated);
10767 			offset += 16;
10768 			break;
10769 
10770 		case NFS4_OP_COMMIT:
10771 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset);
10772 			break;
10773 
10774 		case NFS4_OP_CREATE:
10775 			offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info");
10776 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ);
10777 			break;
10778 
10779 		case NFS4_OP_GETATTR:
10780 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
10781 			break;
10782 
10783 		case NFS4_OP_GETFH:
10784 			offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "Filehandle", &last_fh_hash, civ);
10785 			break;
10786 
10787 		case NFS4_OP_LINK:
10788 			offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info");
10789 			break;
10790 
10791 		case NFS4_OP_LOCK:
10792 		case NFS4_OP_LOCKT:
10793 			if (status == NFS4_OK)
10794 			{
10795 				if (opcode == NFS4_OP_LOCK)
10796 					offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10797 			}
10798 			else
10799 			if (status == NFS4ERR_DENIED)
10800 				offset = dissect_nfs4_lockdenied(tvb, offset, newftree);
10801 			break;
10802 
10803 		case NFS4_OP_LOCKU:
10804 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10805 			break;
10806 
10807 		case NFS4_OP_OPEN:
10808 			offset = dissect_nfs4_stateid(tvb, offset, newftree, &sid_hash);
10809 			offset = dissect_nfs4_change_info(tvb, offset, newftree,
10810 				"change_info");
10811 			offset = dissect_nfs4_open_rflags(tvb, offset, newftree);
10812 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ);
10813 			offset = dissect_nfs4_open_delegation(tvb, offset, pinfo, newftree);
10814 			wmem_strbuf_append_printf (op_summary[ops_counter].optext, " StateID: 0x%04x", sid_hash);
10815 			break;
10816 
10817 		case NFS4_OP_OPEN_CONFIRM:
10818 		case NFS4_OP_OPEN_DOWNGRADE:
10819 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10820 			break;
10821 
10822 		case NFS4_OP_RESTOREFH:
10823 		case NFS4_OP_SAVEFH:
10824 		case NFS4_OP_PUTFH:
10825 			break;
10826 
10827 		case NFS4_OP_READ:
10828 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
10829 			dissect_rpc_uint32(tvb, newftree, hf_nfs4_read_data_length, offset); /* don't change offset */
10830 			offset = dissect_nfsdata_reduced(R_NFSDATA, tvb, offset, newftree, hf_nfs_data, NULL);
10831 			break;
10832 
10833 		case NFS4_OP_READDIR:
10834 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset);
10835 			offset = dissect_nfs4_dirlist(tvb, offset, pinfo, newftree, civ);
10836 			break;
10837 
10838 		case NFS4_OP_READLINK:
10839 			offset = dissect_nfsdata_reduced(R_UTF8STRING, tvb, offset, newftree, hf_nfs4_linktext, NULL);
10840 			break;
10841 
10842 		case NFS4_OP_RECLAIM_COMPLETE:
10843 			break;
10844 
10845 		case NFS4_OP_REMOVE:
10846 			offset = dissect_nfs4_change_info(tvb, offset, newftree, "change_info");
10847 			break;
10848 
10849 		case NFS4_OP_RENAME:
10850 			offset = dissect_nfs4_change_info(tvb, offset, newftree, "source_cinfo");
10851 			offset = dissect_nfs4_change_info(tvb, offset, newftree, "target_cinfo");
10852 			break;
10853 
10854 		case NFS4_OP_SECINFO:
10855 		case NFS4_OP_SECINFO_NO_NAME:
10856 			offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
10857 				dissect_nfs4_secinfo_res, hf_nfs4_secinfo_arr);
10858 			break;
10859 
10860 		case NFS4_OP_SETATTR:
10861 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_BITMAP_ONLY, civ);
10862 			break;
10863 
10864 		case NFS4_OP_SETCLIENTID:
10865 			if (status == NFS4_OK) {
10866 				offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid,
10867 					offset);
10868 				offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier,
10869 					offset);
10870 			} else if (status == NFS4ERR_CLID_INUSE)
10871 				/*
10872 				 * XXX: below function actually assumes
10873 				 * this is for a callback.  Fix:
10874 				 */
10875 				offset = dissect_nfs4_clientaddr(tvb, offset, newftree);
10876 			break;
10877 
10878 		case NFS4_OP_WRITE:
10879 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_count, offset);
10880 			offset = dissect_nfs4_stable_how(tvb, offset, newftree,	"committed");
10881 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_verifier, offset);
10882 			break;
10883 
10884 			/* Minor Version 1 */
10885 		case NFS4_OP_BIND_CONN_TO_SESSION:
10886 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10887 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_bctsr_dir, offset);
10888 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_bctsr_use_conn_in_rdma_mode, offset);
10889 			break;
10890 
10891 		case NFS4_OP_EXCHANGE_ID: {
10892 				proto_tree *eir_server_owner_tree = NULL;
10893 
10894 				offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_clientid, offset);
10895 				offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10896 
10897 				proto_tree_add_bitmask(newftree, tvb, offset, hf_nfs4_exchid_reply_flags, ett_nfs4_exchangeid_reply_flags, nfs4_exchid_flags, ENC_BIG_ENDIAN);
10898 				offset += 4;
10899 
10900 				offset = dissect_nfs4_state_protect_r(tvb, offset, pinfo, newftree);
10901 
10902 				eir_server_owner_tree = proto_tree_add_subtree(newftree, tvb, offset, 0, ett_nfs4_server_owner, NULL, "eir_server_owner");
10903 				offset = dissect_rpc_serverowner4(tvb, offset, eir_server_owner_tree);
10904 				offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs4_serverscope4);
10905 				offset = dissect_rpc_nfs_impl_id4(tvb, offset, newftree, "eir_server_impl_id");
10906 			}
10907 			break;
10908 		case NFS4_OP_CREATE_SESSION:
10909 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10910 			offset = dissect_rpc_uint32(tvb, newftree,
10911 					hf_nfs4_seqid, offset);
10912 			offset = dissect_nfs_create_session_flags(tvb, offset, newftree,
10913 				hf_nfs4_create_session_flags_csr);
10914 			offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csr_fore_chan_attrs");
10915 			offset = dissect_rpc_chanattrs4(tvb, offset, newftree, "csr_back_chan_attrs");
10916 			break;
10917 
10918 		case NFS4_OP_DESTROY_SESSION:
10919 			break;
10920 		case NFS4_OP_FREE_STATEID:
10921 			break;
10922 		case NFS4_OP_TEST_STATEID:
10923 			offset = dissect_rpc_array(tvb, pinfo, newftree, offset, dissect_nfs4_test_stateid_res, hf_nfs4_test_stateid_res);
10924 			break;
10925 
10926 		case NFS4_OP_LAYOUTGET:
10927 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_return_on_close,
10928 									  offset);
10929 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10930 			offset = dissect_nfs4_layoutget(tvb, offset, pinfo, newftree, civ);
10931 			break;
10932 
10933 		case NFS4_OP_LAYOUTCOMMIT:
10934 			offset = dissect_nfs4_newsize(tvb, offset, newftree);
10935 			break;
10936 
10937 		case NFS4_OP_LAYOUTRETURN:
10938 			offset = dissect_nfs_layoutreturn_stateid(tvb, newftree, offset);
10939 			break;
10940 
10941 		case NFS4_OP_GETDEVINFO:
10942 			offset = dissect_nfs4_deviceaddr(tvb, offset, newftree);
10943 			offset = dissect_nfs4_notification_bitmap(tvb, newftree, pinfo, offset);
10944 			break;
10945 
10946 		case NFS4_OP_GETDEVLIST:
10947 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie, offset);
10948 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_cookie_verf,	offset);
10949 			offset = dissect_nfs4_devicelist(tvb, offset, newftree);
10950 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
10951 			break;
10952 
10953 		case NFS4_OP_SEQUENCE:
10954 			{
10955 			static int * const sequence_flags[] = {
10956 				&hf_nfs4_sequence_status_flags_cb_path_down,
10957 				&hf_nfs4_sequence_status_flags_cb_gss_contexts_expiring,
10958 				&hf_nfs4_sequence_status_flags_cb_gss_contexts_expired,
10959 				&hf_nfs4_sequence_status_flags_expired_all_state_revoked,
10960 				&hf_nfs4_sequence_status_flags_expired_some_state_revoked,
10961 				&hf_nfs4_sequence_status_flags_admin_state_revoked,
10962 				&hf_nfs4_sequence_status_flags_recallable_state_revoked,
10963 				&hf_nfs4_sequence_status_flags_lease_moved,
10964 				&hf_nfs4_sequence_status_flags_restart_reclaim_needed,
10965 				&hf_nfs4_sequence_status_flags_cb_path_down_session,
10966 				&hf_nfs4_sequence_status_flags_backchannel_fault,
10967 				&hf_nfs4_sequence_status_flags_devid_changed,
10968 				&hf_nfs4_sequence_status_flags_devid_deleted,
10969 				NULL
10970 			};
10971 
10972 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
10973 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
10974 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_slotid, offset);
10975 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_high_slotid, offset);
10976 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_target_high_slotid, offset);
10977 			proto_tree_add_bitmask(newftree, tvb, offset, hf_nfs4_sequence_status_flags, ett_nfs4_sequence_status_flags, sequence_flags, ENC_BIG_ENDIAN);
10978 			offset += 4;
10979 			}
10980 			break;
10981 
10982 		case NFS4_OP_ALLOCATE:
10983 			break;
10984 
10985 		case NFS4_OP_COPY:
10986 
10987 			if (status == NFS4_OK) {
10988 				offset = dissect_nfs4_write_response(tvb, offset, newftree);
10989 				offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
10990 			} else if (status == NFS4ERR_OFFLOAD_NO_REQS)
10991 				offset = dissect_nfs4_copy_reqs(tvb, offset, newftree);
10992 
10993 			break;
10994 
10995 		case NFS4_OP_COPY_NOTIFY:
10996 
10997 			offset = dissect_nfs4_nfstime(tvb, offset, newftree);
10998 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
10999 			offset = dissect_nfs4_source_servers(tvb, offset, newftree);
11000 
11001 			break;
11002 
11003 		case NFS4_OP_DEALLOCATE:
11004 			break;
11005 
11006 		case NFS4_OP_OFFLOAD_CANCEL:
11007 			break;
11008 
11009 		case NFS4_OP_IO_ADVISE:
11010 			offset = dissect_nfs4_io_hints(tvb, offset, pinfo, tree);
11011 			break;
11012 
11013 		case NFS4_OP_OFFLOAD_STATUS:
11014 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_length, offset);
11015 			offset = dissect_nfs4_offload_status_res(tvb, offset, newftree);
11016 			break;
11017 
11018 		case NFS4_OP_READ_PLUS:
11019 			if (status == NFS4_OK) {
11020 				offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
11021 				offset = dissect_rpc_array(tvb, pinfo, newftree, offset, dissect_nfs4_read_plus_content, hf_nfs4_read_plus_contents);
11022 			}
11023 			break;
11024 
11025 		case NFS4_OP_LAYOUTERROR:
11026 			break;
11027 
11028 		case NFS4_OP_LAYOUTSTATS:
11029 			break;
11030 
11031 		case NFS4_OP_SEEK:
11032 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_eof, offset);
11033 			offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_offset, offset);
11034 			break;
11035 
11036 		case NFS4_OP_WRITE_SAME:
11037 			if (status == NFS4_OK) {
11038 				offset = dissect_nfs4_write_response(tvb, offset, newftree);
11039 			}
11040 			break;
11041 
11042 		case NFS4_OP_CLONE:
11043 			break;
11044 
11045 		case NFS4_OP_GETXATTR:
11046 			if (status == NFS4_OK) {
11047 				offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
11048 			}
11049 			break;
11050 
11051 		case NFS4_OP_SETXATTR:
11052 			if (status == NFS4_OK) {
11053 				offset = dissect_nfs4_change_info(tvb, offset, newftree, "cinfo");
11054 			}
11055 			break;
11056 
11057 		case NFS4_OP_LISTXATTRS:
11058 			if (status == NFS4_OK) {
11059 				offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_listxattr_cookie, offset);
11060 				offset = dissect_nfs4_listxattr_names(tvb, offset, newftree);
11061 				offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_listxattr_eof, offset);
11062 			}
11063 			break;
11064 
11065 		case NFS4_OP_REMOVEXATTR:
11066 			if (status == NFS4_OK) {
11067 				offset = dissect_nfs4_change_info(tvb, offset, newftree, "cinfo");
11068 			}
11069 			break;
11070 
11071 		default:
11072 			break;
11073 		}
11074 	}
11075 
11076 	/* Detect which tiers are present in this packet */
11077 	for (summary_counter = 0; summary_counter < ops_counter; summary_counter++)
11078 	{
11079 		current_tier = NFS4_OPERATION_TIER(op_summary[summary_counter].opcode);
11080 		if (current_tier < highest_tier)
11081 			highest_tier = current_tier;
11082 	}
11083 
11084 	/* Display packet summary */
11085 	for (summary_counter = 0; summary_counter < ops_counter; summary_counter++)
11086 	{
11087 		guint main_opcode;
11088 		proto_item *main_op_item = NULL;
11089 
11090 		main_opcode = op_summary[summary_counter].opcode;
11091 		current_tier = NFS4_OPERATION_TIER(op_summary[summary_counter].opcode);
11092 
11093 		/* Display summary info only for operations that are "most significant".
11094 		 Controlled by a user option.
11095 		 Display summary info for operations that return an error as well.  */
11096 		if (current_tier == highest_tier
11097 		|| !display_major_nfs4_ops
11098 		|| op_summary[summary_counter].iserror == TRUE)
11099 		{
11100 			if (current_tier == highest_tier) {
11101 				const char *main_opname = NULL;
11102 
11103 				/* Display a filterable field of the most significant operations in all cases. */
11104 				main_opname = val_to_str_ext_const(main_opcode, &names_nfs4_operation_ext, "Unknown");
11105 				main_op_item = proto_tree_add_uint_format_value(tree, hf_nfs4_main_opcode, tvb, 0, 0,
11106 									main_opcode, "%s (%u)", main_opname, main_opcode);
11107 				proto_item_set_generated(main_op_item);
11108 			}
11109 
11110 			if (first_operation == 0)
11111 				/* Seperator between operation text */
11112 				col_append_str(pinfo->cinfo, COL_INFO, " |");
11113 
11114 			if (wmem_strbuf_get_len(op_summary[summary_counter].optext) > 0)
11115 				col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
11116 					wmem_strbuf_get_str(op_summary[summary_counter].optext));
11117 			first_operation = 0;
11118 		}
11119 	}
11120 
11121 	return offset;
11122 }
11123 
11124 
11125 static int
dissect_nfs4_compound_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)11126 dissect_nfs4_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
11127 	proto_tree *tree, void *data)
11128 {
11129 	guint32	    status;
11130 	const char *tag = NULL;
11131 	int offset = 0;
11132 
11133 	offset = dissect_nfs4_status(tvb, offset, tree, &status);
11134 	offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
11135 	/*
11136 	* Display the NFSv4 tag. If it is empty, string generator will have returned "<EMPTY>", in
11137 	* which case don't display anything */
11138 	if (nfs_display_v4_tag && strncmp(tag, "<EMPTY>", 7) != 0)
11139 		col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tag);
11140 
11141 	offset = dissect_nfs4_response_op(tvb, offset, pinfo, tree, (rpc_call_info_value*)data);
11142 
11143 	if (status != NFS4_OK)
11144 		col_append_fstr(pinfo->cinfo, COL_INFO, " Status: %s",
11145 				val_to_str_ext(status, &names_nfs4_status_ext, "Unknown error: %u"));
11146 
11147 	return offset;
11148 }
11149 
11150 
11151 /* proc number, "proc name", dissect_request, dissect_reply */
11152 static const vsff nfs3_proc[] = {
11153 	{ 0,	"NULL",		/* OK */
11154 	dissect_nfs3_null_call,		dissect_nfs3_null_reply },
11155 	{ 1,	"GETATTR",	/* OK */
11156 	dissect_nfs3_getattr_call,	dissect_nfs3_getattr_reply },
11157 	{ 2,	"SETATTR",	/* OK */
11158 	dissect_nfs3_setattr_call,	dissect_nfs3_setattr_reply },
11159 	{ 3,	"LOOKUP",	/* OK */
11160 	dissect_nfs3_lookup_call,	dissect_nfs3_lookup_reply },
11161 	{ 4,	"ACCESS",	/* OK */
11162 	dissect_nfs3_access_call,	dissect_nfs3_access_reply },
11163 	{ 5,	"READLINK",	/* OK */
11164 	dissect_nfs3_readlink_call,	dissect_nfs3_readlink_reply },
11165 	{ 6,	"READ",		/* OK */
11166 	dissect_nfs3_read_call,		dissect_nfs3_read_reply },
11167 	{ 7,	"WRITE",	/* OK */
11168 	dissect_nfs3_write_call,	dissect_nfs3_write_reply },
11169 	{ 8,	"CREATE",	/* OK */
11170 	dissect_nfs3_create_call,	dissect_nfs3_create_reply },
11171 	{ 9,	"MKDIR",	/* OK */
11172 	dissect_nfs3_mkdir_call,	dissect_nfs3_mkdir_reply },
11173 	{ 10,	"SYMLINK",	/* OK */
11174 	dissect_nfs3_symlink_call,	dissect_nfs3_symlink_reply },
11175 	{ 11,	"MKNOD",	/* OK */
11176 	dissect_nfs3_mknod_call,	dissect_nfs3_mknod_reply },
11177 	{ 12,	"REMOVE",	/* OK */
11178 	dissect_nfs3_remove_call,	dissect_nfs3_remove_reply },
11179 	{ 13,	"RMDIR",	/* OK */
11180 	dissect_nfs3_rmdir_call,	dissect_nfs3_rmdir_reply },
11181 	{ 14,	"RENAME",	/* OK */
11182 	dissect_nfs3_rename_call,	dissect_nfs3_rename_reply },
11183 	{ 15,	"LINK",		/* OK */
11184 	dissect_nfs3_link_call,		dissect_nfs3_link_reply },
11185 	{ 16,	"READDIR",	/* OK */
11186 	dissect_nfs3_readdir_call,	dissect_nfs3_readdir_reply },
11187 	{ 17,	"READDIRPLUS",	/* OK */
11188 	dissect_nfs3_readdirplus_call,	dissect_nfs3_readdirplus_reply },
11189 	{ 18,	"FSSTAT",	/* OK */
11190 	dissect_nfs3_fsstat_call,	dissect_nfs3_fsstat_reply },
11191 	{ 19,	"FSINFO",	/* OK */
11192 	dissect_nfs3_fsinfo_call,	dissect_nfs3_fsinfo_reply },
11193 	{ 20,	"PATHCONF",	/* OK */
11194 	dissect_nfs3_pathconf_call,	dissect_nfs3_pathconf_reply },
11195 	{ 21,	"COMMIT",	/* OK */
11196 	dissect_nfs3_commit_call,	dissect_nfs3_commit_reply },
11197 	{ 0,	NULL,	NULL,	NULL }
11198 };
11199 
11200 static const value_string nfs3_proc_vals[] = {
11201 	{ 0,	"NULL" },
11202 	{ 1,	"GETATTR" },
11203 	{ 2,	"SETATTR" },
11204 	{ 3,	"LOOKUP" },
11205 	{ 4,	"ACCESS" },
11206 	{ 5,	"READLINK" },
11207 	{ 6,	"READ" },
11208 	{ 7,	"WRITE" },
11209 	{ 8,	"CREATE" },
11210 	{ 9,	"MKDIR" },
11211 	{ 10,	"SYMLINK" },
11212 	{ 11,	"MKNOD" },
11213 	{ 12,	"REMOVE" },
11214 	{ 13,	"RMDIR" },
11215 	{ 14,	"RENAME" },
11216 	{ 15,	"LINK" },
11217 	{ 16,	"READDIR" },
11218 	{ 17,	"READDIRPLUS" },
11219 	{ 18,	"FSSTAT" },
11220 	{ 19,	"FSINFO" },
11221 	{ 20,	"PATHCONF" },
11222 	{ 21,	"COMMIT" },
11223 	{ 0,	NULL }
11224 };
11225 static value_string_ext nfs3_proc_vals_ext = VALUE_STRING_EXT_INIT(nfs3_proc_vals);
11226 
11227 /* End of NFS Version 3 */
11228 
11229 
11230 /* the call to dissect_nfs3_null_call & dissect_nfs3_null_reply is
11231  * intentional.  The V4 NULLPROC is the same as V3.
11232  */
11233 static const vsff nfs4_proc[] = {
11234 	{ 0, "NULL",
11235 	dissect_nfs3_null_call,		dissect_nfs3_null_reply },
11236 	{ 1, "COMPOUND",
11237 	dissect_nfs4_compound_call, dissect_nfs4_compound_reply },
11238 	{ 0, NULL, NULL, NULL }
11239 };
11240 
11241 static const value_string nfs4_proc_vals[] = {
11242 	{ 0, "NULL" },
11243 	{ 1, "COMPOUND" },
11244 	{ 0, NULL }
11245 };
11246 
11247 static const rpc_prog_vers_info nfs_vers_info[] = {
11248 	{ 2, nfs2_proc, &hf_nfs2_procedure },
11249 	{ 3, nfs3_proc, &hf_nfs3_procedure },
11250 	{ 4, nfs4_proc, &hf_nfs4_procedure },
11251 };
11252 
11253 /*
11254  * Union of the NFSv2, NFSv3, and NFSv4 status codes.
11255  * Used for the "nfs.status" hidden field and in packet-nfsacl.c.
11256  */
11257 static const value_string names_nfs_nfsstat[] = {
11258 	{    0,	 "OK"				     },
11259 	{    1,	 "ERR_PERM"			     },
11260 	{    2,	 "ERR_NOENT"			     },
11261 	{    5,	 "ERR_IO"			     },
11262 	{    6,	 "ERR_NXIO"			     },
11263 	{    11, "ERR_EAGAIN"			     },
11264 	{    13, "ERR_ACCESS"			     },
11265 	{    17, "ERR_EXIST"			     },
11266 	{    18, "ERR_XDEV"			     },
11267 	{    19, "ERR_NODEV"			     },
11268 	{    20, "ERR_NOTDIR"			     },
11269 	{    21, "ERR_ISDIR"			     },
11270 	{    22, "ERR_INVAL"			     },
11271 	{    26, "ERR_TXTBSY"			     },
11272 	{    27, "ERR_FBIG"			     },
11273 	{    28, "ERR_NOSPC"			     },
11274 	{    30, "ERR_ROFS"			     },
11275 	{    31, "ERR_MLINK"			     },
11276 	{    45, "ERR_OPNOTSUPP"		     },
11277 	{    63, "ERR_NAMETOOLONG"		     },
11278 	{    66, "ERR_NOTEMPTY"			     },
11279 	{    69, "ERR_DQUOT"			     },
11280 	{    70, "ERR_STALE"			     },
11281 	{    71, "ERR_REMOTE"			     },
11282 	{    99, "ERR_WFLUSH"			     },
11283 	{ 10001, "ERR_BADHANDLE"		     },
11284 	{ 10002, "ERR_NOT_SYNC"			     },
11285 	{ 10003, "ERR_BAD_COOKIE"		     },
11286 	{ 10004, "ERR_NOTSUPP"			     },
11287 	{ 10005, "ERR_TOOSMALL"			     },
11288 	{ 10006, "ERR_SERVERFAULT"		     },
11289 	{ 10007, "ERR_BADTYPE"			     },
11290 	{ 10008, "ERR_DELAY"			     },
11291 	{ 10009, "ERR_SAME"			     },
11292 	{ 10010, "ERR_DENIED"			     },
11293 	{ 10011, "ERR_EXPIRED"			     },
11294 	{ 10012, "ERR_LOCKED"			     },
11295 	{ 10013, "ERR_GRACE"			     },
11296 	{ 10014, "ERR_FHEXPIRED"		     },
11297 	{ 10015, "ERR_SHARE_DENIED"		     },
11298 	{ 10016, "ERR_WRONGSEC"			     },
11299 	{ 10017, "ERR_CLID_INUSE"		     },
11300 	{ 10018, "ERR_RESOURCE"			     },
11301 	{ 10019, "ERR_MOVED"			     },
11302 	{ 10020, "ERR_NOFILEHANDLE"		     },
11303 	{ 10021, "ERR_MINOR_VERS_MISMATCH"	     },
11304 	{ 10022, "ERR_STALE_CLIENTID"		     },
11305 	{ 10023, "ERR_STALE_STATEID"		     },
11306 	{ 10024, "ERR_OLD_STATEID"		     },
11307 	{ 10025, "ERR_BAD_STATEID"		     },
11308 	{ 10026, "ERR_BAD_SEQID"		     },
11309 	{ 10027, "ERR_NOT_SAME"			     },
11310 	{ 10028, "ERR_LOCK_RANGE"		     },
11311 	{ 10029, "ERR_SYMLINK"			     },
11312 	{ 10030, "ERR_READDIR_NOSPC"		     },
11313 	{ 10031, "ERR_LEASE_MOVED"		     },
11314 	{ 10032, "ERR_ATTRNOTSUPP"		     },
11315 	{ 10033, "ERR_NO_GRACE"			     },
11316 	{ 10034, "ERR_RECLAIM_BAD"		     },
11317 	{ 10035, "ERR_RECLAIM_CONFLICT"		     },
11318 	{ 10036, "ERR_BADXDR"			     },
11319 	{ 10037, "ERR_LOCKS_HELD"		     },
11320 	{ 10038, "ERR_OPENMODE"			     },
11321 	{ 10039, "ERR_BADOWNER"			     },
11322 	{ 10040, "ERR_BADCHAR"			     },
11323 	{ 10041, "ERR_BADNAME"			     },
11324 	{ 10042, "ERR_BAD_RANGE"		     },
11325 	{ 10043, "ERR_LOCK_NOTSUPP"		     },
11326 	{ 10044, "ERR_OP_ILLEGAL"		     },
11327 	{ 10045, "ERR_DEADLOCK"			     },
11328 	{ 10046, "ERR_FILE_OPEN"		     },
11329 	{ 10047, "ERR_ADMIN_REVOKED"		     },
11330 	{ 10048, "ERR_CB_PATH_DOWN"		     },
11331 	{ 10049, "ERR_REPLAY_ME_or_BADIOMODE"	     },
11332 	{ 10050, "ERR_BADLAYOUT"		     },
11333 	{ 10051, "ERR_BAD_SESSION_DIGEST"	     },
11334 	{ 10052, "ERR_BADSESSION"		     },
11335 	{ 10053, "ERR_BADSLOT"			     },
11336 	{ 10054, "ERR_COMPLETE_ALREADY"		     },
11337 	{ 10055, "ERR_CONN_NOT_BOUND_TO_SESSION"     },
11338 	{ 10056, "ERR_DELEG_ALREADY_WANTED"	     },
11339 	{ 10057, "ERR_BACK_CHAN_BUSY"		     },
11340 	{ 10058, "ERR_LAYOUTTRYLATER"		     },
11341 	{ 10059, "ERR_LAYOUTUNAVAILABLE"	     },
11342 	{ 10060, "ERR_NOMATCHING_LAYOUT"	     },
11343 	{ 10061, "ERR_RECALLCONFLICT"		     },
11344 	{ 10062, "ERR_UNKNOWN_LAYOUTTYPE"	     },
11345 	{ 10063, "ERR_SEQ_MISORDERED"		     },
11346 	{ 10064, "ERR_SEQUENCE_POS"		     },
11347 	{ 10065, "ERR_REQ_TOO_BIG"		     },
11348 	{ 10066, "ERR_REP_TOO_BIG"		     },
11349 	{ 10067, "ERR_REP_TOO_BIG_TO_CACHE"	     },
11350 	{ 10068, "ERR_RETRY_UNCACHED_REP"	     },
11351 	{ 10069, "ERR_UNSAFE_COMPOUND"		     },
11352 	{ 10070, "ERR_TOO_MANY_OPS"		     },
11353 	{ 10071, "ERR_OP_NOT_IN_SESSION"	     },
11354 	{ 10072, "ERR_HASH_ALG_UNSUPP"		     },
11355 	{ 10073, "NFS4ERR_CONN_BINDING_NOT_ENFORCED" },
11356 	{ 10074, "ERR_CLIENTID_BUSY"		     },
11357 	{ 10075, "ERR_PNFS_IO_HOLE"		     },
11358 	{ 10076, "ERR_SEQ_FALSE_RETRY"		     },
11359 	{ 10077, "ERR_BAD_HIGH_SLOT"		     },
11360 	{ 10078, "ERR_DEADSESSION"		     },
11361 	{ 10079, "ERR_ENCR_ALG_UNSUPP"		     },
11362 	{ 10080, "ERR_PNFS_NO_LAYOUT"		     },
11363 	{ 10081, "ERR_NOT_ONLY_OP"		     },
11364 	{ 10082, "ERR_WRONG_CRED"		     },
11365 	{ 10083, "ERR_WRONG_TYPE"		     },
11366 	{ 10084, "ERR_DIRDELEG_UNAVAIL"		     },
11367 	{ 10085, "ERR_REJECT_DELEG"		     },
11368 	{ 10086, "ERR_RETURNCONFLICT"		     },
11369 	{ 10087, "ERR_DELEG_REVOKED"		     },
11370 	{ 10088, "ERR_PARTNER_NOTSUPP"		     },
11371 	{ 10089, "ERR_PARTNER_NO_AUTH"		     },
11372 	{ 10090, "ERR_UNION_NOTSUPP"		     },
11373 	{ 10091, "ERR_OFFLOAD_DENIED"		     },
11374 	{ 10092, "ERR_WRONG_LFS"		     },
11375 	{ 10093, "ERR_BADLABEL"			     },
11376 	{ 10094, "ERR_OFFLOAD_NO_REQS"		     },
11377 	{ 0,	NULL }
11378 };
11379 static value_string_ext names_nfs_nfsstat_ext = VALUE_STRING_EXT_INIT(names_nfs_nfsstat);
11380 
11381 static const value_string iomode_names[] = {
11382 	{ 1, "IOMODE_READ" },
11383 	{ 2, "IOMODE_RW"   },
11384 	{ 3, "IOMODE_ANY"  },
11385 	{ 0, NULL }
11386 };
11387 
11388 #if 0
11389 static const value_string stripetype_names[] = {
11390 	{ 1, "STRIPE_SPARSE" },
11391 	{ 2, "STRIPE_DENSE"  },
11392 	{ 0, NULL }
11393 };
11394 #endif
11395 
11396 static const value_string netloctype_names[] = {
11397 	{ NL4_NAME, "NL4_NAME" },
11398 	{ NL4_URL, "NL4_URL"  },
11399 	{ NL4_NETADDR, "NL4_NETADDR"  },
11400 	{ 0, NULL }
11401 };
11402 
11403 static const value_string layouttype_names[] = {
11404 	{ 1, "LAYOUT4_NFSV4_1_FILES" },
11405 	{ 2, "LAYOUT4_OSD2_OBJECTS"  },
11406 	{ 3, "LAYOUT4_BLOCK_VOLUME"  },
11407 	{ 4, "LAYOUT4_FLEX_FILES"  },
11408 	{ 5, "LAYOUT4_SCSI"  },
11409 	{ 0, NULL }
11410 };
11411 
11412 static const value_string layoutreturn_names[] = {
11413 	{ 1, "RETURN_FILE" },
11414 	{ 2, "RETURN_FSID" },
11415 	{ 3, "RETURN_ALL"  },
11416 	{ 0, NULL }
11417 };
11418 
11419 static const value_string nfs_fh_obj_id[] = {
11420 	{ 1, "NF4REG"      },
11421 	{ 2, "NF4DIR"      },
11422 	{ 3, "NF4BLK"      },
11423 	{ 4, "NF4CHR"      },
11424 	{ 5, "NF4LNK"      },
11425 	{ 6, "NF4SOCK"     },
11426 	{ 7, "NF4FIFO"     },
11427 	{ 8, "NF4ATTRDIR"  },
11428 	{ 9, "NF4NAMEDATTR"},
11429 	{ 0, NULL }
11430 };
11431 
11432 static const true_false_string nfs4_ro_boolean = {
11433 	"object is read only",
11434 	"object is *not* read-only"
11435 };
11436 
11437 static const value_string layoutrecall_names[] = {
11438 	{ 1, "RECALL_FILE" },
11439 	{ 2, "RECALL_FSID" },
11440 	{ 3, "RECALL_ALL"  },
11441 	{ 0, NULL }
11442 };
11443 
11444 /* NFS Callback */
11445 static int hf_nfs4_cb_procedure = -1;
11446 static int hf_nfs4_cb_op = -1;
11447 static int hf_nfs4_cb_truncate = -1;
11448 static int hf_nfs4_cb_layoutrecall_type = -1;
11449 static int hf_nfs4_cb_clorachanged = -1;
11450 
11451 static gint ett_nfs4_cb_request_op = -1;
11452 static gint ett_nfs4_cb_resop = -1;
11453 static gint ett_nfs4_cb_getattr = -1;
11454 static gint ett_nfs4_cb_recall = -1;
11455 static gint ett_nfs4_cb_layoutrecall = -1;
11456 static gint ett_nfs4_cb_pushdeleg = -1;
11457 static gint ett_nfs4_cb_recallany = -1;
11458 static gint ett_nfs4_cb_recallableobjavail = -1;
11459 static gint ett_nfs4_cb_recallslot = -1;
11460 static gint ett_nfs4_cb_sequence = -1;
11461 static gint ett_nfs4_cb_wantscancelled = -1;
11462 static gint ett_nfs4_cb_notifylock = -1;
11463 static gint ett_nfs4_cb_notifydeviceid = -1;
11464 static gint ett_nfs4_cb_notify = -1;
11465 static gint ett_nfs4_cb_reflists = -1;
11466 static gint ett_nfs4_cb_refcalls = -1;
11467 static gint ett_nfs4_cb_illegal = -1;
11468 
11469 static const value_string names_nfs_cb_operation[] = {
11470 	{ NFS4_OP_CB_GETATTR,		   "CB_GETATTR" },
11471 	{ NFS4_OP_CB_RECALL,		   "CB_RECALL"	},
11472 	{ NFS4_OP_CB_LAYOUTRECALL,	   "CB_LAYOUTRECALL" },
11473 	{ NFS4_OP_CB_NOTIFY,		   "CB_NOTIFY" },
11474 	{ NFS4_OP_CB_PUSH_DELEG,	   "CB_PUSH_DELEG" },
11475 	{ NFS4_OP_CB_RECALL_ANY,	   "CB_RECALL_ANY" },
11476 	{ NFS4_OP_CB_RECALLABLE_OBJ_AVAIL, "CB_RECALLABLE_OBJ_AVAIL" },
11477 	{ NFS4_OP_CB_RECALL_SLOT,	   "CB_RECALL_SLOT"},
11478 	{ NFS4_OP_CB_SEQUENCE,		   "CB_SEQUENCE" },
11479 	{ NFS4_OP_CB_WANTS_CANCELLED,	   "CB_WANTS_CANCELLED" },
11480 	{ NFS4_OP_CB_NOTIFY_LOCK,	   "CB_NOTIFY_LOCK" },
11481 	{ NFS4_OP_CB_NOTIFY_DEVICEID,	   "CB_NOTIFY_DEVICEID" },
11482 	{ NFS4_OP_CB_OFFLOAD,		   "CB_OFFLOAD" },
11483 	{ NFS4_OP_CB_ILLEGAL,		   "CB_ILLEGAL"},
11484 	{ 0,	NULL }
11485 };
11486 static value_string_ext names_nfs_cb_operation_ext = VALUE_STRING_EXT_INIT(names_nfs_cb_operation);
11487 
11488 static gint *nfs4_cb_operation_ett[] =
11489 {
11490 	&ett_nfs4_cb_getattr,
11491 	&ett_nfs4_cb_recall,
11492 	&ett_nfs4_cb_layoutrecall,
11493 	&ett_nfs4_cb_notify,
11494 	&ett_nfs4_cb_pushdeleg,
11495 	&ett_nfs4_cb_recallany,
11496 	&ett_nfs4_cb_recallableobjavail,
11497 	&ett_nfs4_cb_recallslot,
11498 	&ett_nfs4_cb_sequence,
11499 	&ett_nfs4_cb_wantscancelled,
11500 	&ett_nfs4_cb_notifylock,
11501 	&ett_nfs4_cb_notifydeviceid,
11502 	&ett_nfs4_cb_illegal
11503 };
11504 
11505 static int
dissect_nfs4_cb_referring_calls(tvbuff_t * tvb,int offset,proto_tree * tree)11506 dissect_nfs4_cb_referring_calls(tvbuff_t *tvb, int offset, proto_tree *tree)
11507 {
11508 	guint	    num_reflists, num_refcalls, i, j;
11509 	proto_tree *rl_tree, *rc_tree;
11510 
11511 	num_reflists = tvb_get_ntohl(tvb, offset);
11512 	rl_tree = proto_tree_add_subtree_format(tree, tvb, offset, 4,
11513 			ett_nfs4_cb_reflists, NULL, "referring call lists (count: %u)", num_reflists);
11514 	offset += 4;
11515 
11516 	for (i = 0; i < num_reflists; i++) {
11517 		offset = dissect_nfs4_sessionid(tvb, offset, rl_tree);
11518 		num_refcalls = tvb_get_ntohl(tvb, offset);
11519 		rc_tree = proto_tree_add_subtree_format(rl_tree, tvb, offset, 4,
11520 				ett_nfs4_cb_refcalls, NULL, "referring calls (count: %u)", num_refcalls);
11521 		offset += 4;
11522 		for (j = 0; j < num_refcalls; j++) {
11523 			offset = dissect_rpc_uint32(tvb, rc_tree, hf_nfs4_seqid, offset);
11524 			offset = dissect_rpc_uint32(tvb, rc_tree, hf_nfs4_slotid, offset);
11525 		}
11526 	}
11527 
11528 	return offset;
11529 }
11530 
11531 static int
dissect_nfs4_cb_layoutrecall(tvbuff_t * tvb,int offset,proto_tree * tree,packet_info * pinfo,rpc_call_info_value * civ)11532 dissect_nfs4_cb_layoutrecall(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, rpc_call_info_value *civ)
11533 {
11534 	guint recall_type;
11535 
11536 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_layout_type, offset);
11537 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_iomode, offset);
11538 	offset = dissect_rpc_bool(tvb, tree, hf_nfs4_cb_clorachanged, offset);
11539 
11540 	recall_type = tvb_get_ntohl(tvb, offset);
11541 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_cb_layoutrecall_type, offset);
11542 
11543 	if (recall_type == 1) { /* RECALL_FILE */
11544 		offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, civ);
11545 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_offset, offset);
11546 		offset = dissect_rpc_uint64(tvb, tree, hf_nfs4_length, offset);
11547 		offset = dissect_nfs4_stateid(tvb, offset, tree, NULL);
11548 	} else if (recall_type == 2) { /* RECALL_FSID */
11549 		offset = dissect_nfs4_fsid(tvb, offset, tree, "fsid");
11550 	}
11551 
11552 	return offset;
11553 }
11554 
11555 
11556 static int
dissect_nfs4_cb_request(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)11557 dissect_nfs4_cb_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
11558 {
11559 	guint32	    ops, ops_counter;
11560 	guint32	    status;
11561 	guint	    opcode;
11562 	proto_item *fitem;
11563 	proto_tree *ftree;
11564 	proto_tree *newftree = NULL;
11565 
11566 	ops = tvb_get_ntohl(tvb, offset+0);
11567 
11568 	ftree = proto_tree_add_subtree_format(tree, tvb, offset, 4, ett_nfs4_cb_request_op, NULL, "Operations (count: %u)", ops);
11569 	offset += 4;
11570 
11571 	for (ops_counter=0; ops_counter<ops; ops_counter++)
11572 	{
11573 		opcode = tvb_get_ntohl(tvb, offset);
11574 		col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s", ops_counter == 0?' ':';',
11575 				val_to_str_ext_const(opcode, &names_nfs_cb_operation_ext, "Unknown"));
11576 
11577 		fitem = proto_tree_add_uint(ftree, hf_nfs4_cb_op, tvb, offset, 4, opcode);
11578 		offset += 4;
11579 
11580 	/* the opcodes are not contiguous */
11581 		if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
11582 		    (opcode != NFS4_OP_CB_ILLEGAL))
11583 			break;
11584 
11585 	/* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
11586 		if (opcode == NFS4_OP_CB_ILLEGAL)
11587 			newftree = proto_item_add_subtree(fitem, ett_nfs4_cb_illegal);
11588 		else if (nfs4_cb_operation_ett[opcode - 3])
11589 			newftree = proto_item_add_subtree(fitem, *nfs4_cb_operation_ett[opcode - 3]);
11590 		else
11591 			break;
11592 
11593 		switch (opcode)
11594 		{
11595 		case NFS4_OP_CB_RECALL:
11596 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
11597 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_cb_truncate, offset);
11598 			offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ);
11599 			break;
11600 		case NFS4_OP_CB_GETATTR:
11601 			offset = dissect_nfs4_fh(tvb, offset, pinfo, tree, "FileHandle", NULL, civ);
11602 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, tree, FATTR4_BITMAP_ONLY, civ);
11603 			break;
11604 		case NFS4_OP_CB_LAYOUTRECALL:
11605 			offset = dissect_nfs4_cb_layoutrecall(tvb, offset, newftree, pinfo, civ);
11606 			break;
11607 		case NFS4_OP_CB_NOTIFY:
11608 		case NFS4_OP_CB_PUSH_DELEG:
11609 		case NFS4_OP_CB_RECALL_ANY:
11610 		case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL:
11611 		case NFS4_OP_CB_RECALL_SLOT:
11612 			break;
11613 		case NFS4_OP_CB_SEQUENCE:
11614 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
11615 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
11616 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_slotid, offset);
11617 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_high_slotid, offset);
11618 			offset = dissect_rpc_bool(tvb, newftree, hf_nfs4_cachethis, offset);
11619 			offset = dissect_nfs4_cb_referring_calls(tvb, offset, newftree);
11620 			break;
11621 		case NFS4_OP_CB_WANTS_CANCELLED:
11622 			break;
11623 		case NFS4_OP_CB_NOTIFY_LOCK:
11624 			offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ);
11625 			offset = dissect_nfs4_lock_owner(tvb, offset, newftree);
11626 			break;
11627 		case NFS4_OP_CB_NOTIFY_DEVICEID:
11628 			break;
11629 		case NFS4_OP_CB_OFFLOAD:
11630 			offset = dissect_nfs4_fh(tvb, offset, pinfo, newftree, "FileHandle", NULL, civ);
11631 			offset = dissect_nfs4_stateid(tvb, offset, newftree, NULL);
11632 			offset = dissect_nfs4_status(tvb, offset, newftree, &status);
11633 			if (status == NFS4_OK) {
11634 				offset = dissect_nfs4_write_response(tvb, offset, newftree);
11635 			} else {
11636 				offset = dissect_rpc_uint64(tvb, newftree, hf_nfs4_bytes_copied, offset);
11637 			}
11638 			break;
11639 		case NFS4_OP_ILLEGAL:
11640 			break;
11641 		default:
11642 			break;
11643 		}
11644 	}
11645 
11646 	return offset;
11647 }
11648 
11649 
11650 static int
dissect_nfs4_cb_compound_call(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)11651 dissect_nfs4_cb_compound_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
11652 {
11653 	const char *tag = NULL;
11654 	int offset = 0;
11655 
11656 	offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
11657 
11658 	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tag);
11659 
11660 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_minorversion, offset);
11661 	offset = dissect_rpc_uint32(tvb, tree, hf_nfs4_callback_ident, offset);
11662 	offset = dissect_nfs4_cb_request(tvb, offset, pinfo, tree, (rpc_call_info_value*)data);
11663 
11664 	return offset;
11665 }
11666 
11667 
11668 static int
dissect_nfs4_cb_resp_op(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,rpc_call_info_value * civ)11669 dissect_nfs4_cb_resp_op(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value *civ)
11670 {
11671 	guint32	    ops, ops_counter;
11672 	guint32	    opcode;
11673 	proto_item *fitem;
11674 	proto_tree *ftree;
11675 	proto_tree *newftree = NULL;
11676 	guint32	    status;
11677 
11678 	ops   = tvb_get_ntohl(tvb, offset+0);
11679 	ftree = proto_tree_add_subtree_format(tree, tvb, offset, 4, ett_nfs4_cb_resop, NULL, "Operations (count: %u)", ops);
11680 	offset += 4;
11681 
11682 	for (ops_counter = 0; ops_counter < ops; ops_counter++)
11683 	{
11684 		opcode = tvb_get_ntohl(tvb, offset);
11685 
11686 		/* sanity check for bogus packets */
11687 		if ((opcode < NFS4_OP_CB_GETATTR || opcode > NFS4_OP_CB_OFFLOAD) &&
11688 			(opcode != NFS4_OP_ILLEGAL))
11689 			break;
11690 
11691 		col_append_fstr(pinfo->cinfo, COL_INFO, "%c%s",	ops_counter == 0 ? ' ' : ';',
11692 				val_to_str_ext_const(opcode, &names_nfs_cb_operation_ext, "Unknown"));
11693 
11694 		fitem = proto_tree_add_uint(ftree, hf_nfs4_cb_op, tvb, offset, 4, opcode);
11695 		offset += 4;
11696 
11697 		/* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
11698 		if (opcode == NFS4_OP_ILLEGAL)
11699 			newftree = proto_item_add_subtree(fitem, ett_nfs4_illegal);
11700 		else if (nfs4_cb_operation_ett[opcode - 3])
11701 			newftree = proto_item_add_subtree(fitem, *nfs4_cb_operation_ett[opcode - 3]);
11702 		else
11703 			break;
11704 
11705 		offset = dissect_nfs4_status(tvb, offset, newftree, &status);
11706 
11707 		/* are there any ops that return data with a failure (?) */
11708 		if (status != NFS4_OK)
11709 			continue;
11710 
11711 		/* These parsing routines are only executed if the status is NFS4_OK */
11712 		switch (opcode)
11713 		{
11714 		case NFS4_OP_CB_RECALL:
11715 			break;
11716 		case NFS4_OP_CB_GETATTR:
11717 			offset = dissect_nfs4_fattrs(tvb, offset, pinfo, newftree, FATTR4_DISSECT_VALUES, civ);
11718 			break;
11719 		case NFS4_OP_CB_LAYOUTRECALL:
11720 			break;
11721 		case NFS4_OP_CB_NOTIFY:
11722 		case NFS4_OP_CB_PUSH_DELEG:
11723 		case NFS4_OP_CB_RECALL_ANY:
11724 		case NFS4_OP_CB_RECALLABLE_OBJ_AVAIL:
11725 		case NFS4_OP_CB_RECALL_SLOT:
11726 			break;
11727 		case NFS4_OP_CB_SEQUENCE:
11728 			offset = dissect_nfs4_sessionid(tvb, offset, newftree);
11729 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_seqid, offset);
11730 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_slotid, offset);
11731 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_high_slotid, offset);
11732 			offset = dissect_rpc_uint32(tvb, newftree, hf_nfs4_target_high_slotid, offset);
11733 			break;
11734 		case NFS4_OP_CB_WANTS_CANCELLED:
11735 		case NFS4_OP_CB_NOTIFY_LOCK:
11736 		case NFS4_OP_CB_NOTIFY_DEVICEID:
11737 		case NFS4_OP_CB_OFFLOAD:
11738 			break;
11739 		case NFS4_OP_ILLEGAL:
11740 			break;
11741 		default:
11742 			break;
11743 		}
11744 	}
11745 
11746 	return offset;
11747 }
11748 
11749 
11750 static int
dissect_nfs4_cb_compound_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)11751 dissect_nfs4_cb_compound_reply(tvbuff_t *tvb, packet_info *pinfo,
11752 			      proto_tree *tree, void *data)
11753 {
11754 	guint32	    status;
11755 	const char *tag	= NULL;
11756 	int offset = 0;
11757 
11758 	offset = dissect_nfs4_status(tvb, offset, tree, &status);
11759 	offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs4_tag, &tag);
11760 	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", tag);
11761 
11762 	offset = dissect_nfs4_cb_resp_op(tvb, offset, pinfo, tree, (rpc_call_info_value*)data);
11763 
11764 	return offset;
11765 }
11766 
11767 
11768 static const vsff nfs_cb_proc[] = {
11769 	{ 0, "CB_NULL",
11770 	  dissect_nfs3_null_call, dissect_nfs3_null_reply },
11771 	{ 1, "CB_COMPOUND",
11772 	  dissect_nfs4_cb_compound_call, dissect_nfs4_cb_compound_reply },
11773 	{ 0, NULL, NULL, NULL }
11774 };
11775 
11776 static const value_string nfs_cb_proc_vals[] = {
11777 	{ 0, "CB_NULL" },
11778 	{ 1, "CB_COMPOUND" },
11779 	{ 0, NULL }
11780 };
11781 
11782 /*
11783  * The version should be 4, but some Linux kernels set this field to 1.
11784  * "Temporarily" accommodate these servers.
11785  */
11786 static const rpc_prog_vers_info nfs_cb_vers_info[] = {
11787 	{ 1, nfs_cb_proc, &hf_nfs4_cb_procedure },
11788 	{ 4, nfs_cb_proc, &hf_nfs4_cb_procedure },
11789 };
11790 
11791 void
proto_register_nfs(void)11792 proto_register_nfs(void)
11793 {
11794 	static hf_register_info hf[] = {
11795 		{ &hf_nfs2_procedure, {
11796 			"V2 Procedure", "nfs.procedure_v2", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
11797 			&nfs2_proc_vals_ext, 0, NULL, HFILL }},
11798 		{ &hf_nfs3_procedure, {
11799 			"V3 Procedure", "nfs.procedure_v3", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
11800 			&nfs3_proc_vals_ext, 0, NULL, HFILL }},
11801 		{ &hf_nfs4_procedure, {
11802 			"V4 Procedure", "nfs.procedure_v4", FT_UINT32, BASE_DEC,
11803 			VALS(nfs4_proc_vals), 0, NULL, HFILL }},
11804 #if 0
11805 		{ &hf_nfs4_impl_id_len, {
11806 			"Implementation ID length", "nfs.impl_id4.length", FT_UINT32, BASE_DEC,
11807 			NULL, 0, NULL, HFILL }},
11808 #endif
11809 		{ &hf_nfs_fh_length, {
11810 			"length", "nfs.fh.length", FT_UINT32, BASE_DEC,
11811 			NULL, 0, "file handle length", HFILL }},
11812 		{ &hf_nfs_fh_hash, {
11813 			"hash (CRC-32)", "nfs.fh.hash", FT_UINT32, BASE_HEX,
11814 			NULL, 0, "file handle hash", HFILL }},
11815 
11816 
11817 		{ &hf_nfs_fh_mount_fileid, {
11818 			"fileid", "nfs.fh.mount.fileid", FT_UINT32, BASE_DEC,
11819 			NULL, 0, "mount point fileid", HFILL }},
11820 		{ &hf_nfs_fh_mount_generation, {
11821 			"generation", "nfs.fh.mount.generation", FT_UINT32, BASE_HEX,
11822 			NULL, 0, "mount point generation", HFILL }},
11823 		{ &hf_nfs_fh_flags, {
11824 			"Flags", "nfs.fh.flags", FT_UINT16, BASE_HEX,
11825 			NULL, 0, "file handle flags", HFILL }},
11826 		{ &hf_nfs_fh_snapid, {
11827 			"snapid", "nfs.fh.snapid", FT_UINT8, BASE_DEC,
11828 			NULL, 0, "snapshot ID", HFILL }},
11829 		{ &hf_nfs_fh_unused, {
11830 			"unused", "nfs.fh.unused", FT_UINT8, BASE_DEC,
11831 			NULL, 0, NULL, HFILL }},
11832 		{ &hf_nfs_fh_fileid, {
11833 			"fileid", "nfs.fh.fileid", FT_UINT32, BASE_DEC,
11834 			NULL, 0, "file ID", HFILL }},
11835 		{ &hf_nfs_fh_generation, {
11836 			"generation", "nfs.fh.generation", FT_UINT32, BASE_HEX,
11837 			NULL, 0, "inode generation", HFILL }},
11838 		{ &hf_nfs_fh_fsid, {
11839 			"file system ID", "nfs.fh.fsid", FT_UINT32, BASE_CUSTOM,
11840 			CF_FUNC(nfs_fmt_fsid), 0, NULL, HFILL }},
11841 		{ &hf_nfs_fh_export_fileid, {
11842 			"fileid", "nfs.fh.export.fileid", FT_UINT32, BASE_DEC,
11843 			NULL, 0, "export point fileid", HFILL }},
11844 		{ &hf_nfs_fh_export_generation, {
11845 			"generation", "nfs.fh.export.generation", FT_UINT32, BASE_HEX,
11846 			NULL, 0, "export point generation", HFILL }},
11847 		{ &hf_nfs_fh_export_snapid, {
11848 			"snapid", "nfs.fh.export.snapid", FT_UINT8, BASE_DEC,
11849 			NULL, 0, "export point snapid", HFILL }},
11850 		{ &hf_nfs_fh_exportid, {
11851 			"exportid", "nfs.fh.exportid", FT_GUID, BASE_NONE,
11852 			NULL, 0, "Gluster/NFS exportid", HFILL }},
11853 		{ &hf_nfs_fh_handle_type, {
11854 			"Handle type", "nfs.fh.handletype", FT_UINT32, BASE_DEC,
11855 			VALS(handle_type_strings), 0, "v4 handle type", HFILL }},
11856 		{ &hf_nfs_fh_file_flag_mntpoint, {
11857 			"mount point", "nfs.fh.file.flag.mntpoint", FT_BOOLEAN, 16,
11858 			TFS(&tfs_set_notset), 0x0001, "file flag: mountpoint", HFILL }},
11859 		{ &hf_nfs_fh_file_flag_snapdir, {
11860 			"snapdir", "nfs.fh.file.flag.snapdir", FT_BOOLEAN, 16,
11861 			TFS(&tfs_set_notset), 0x0002, "file flag: snapdir", HFILL }},
11862 		{ &hf_nfs_fh_file_flag_snapdir_ent, {
11863 			"snapdir_ent", "nfs.fh.file.flag.snadir_ent", FT_BOOLEAN, 16,
11864 			TFS(&tfs_set_notset), 0x0004, "file flag: snapdir_ent", HFILL }},
11865 		{ &hf_nfs_fh_file_flag_empty, {
11866 			"empty", "nfs.fh.file.flag.empty", FT_BOOLEAN, 16,
11867 			TFS(&tfs_set_notset), 0x0008, "file flag: empty", HFILL }},
11868 		{ &hf_nfs_fh_file_flag_vbn_access, {
11869 			"vbn_access", "nfs.fh.file.flag.vbn_access", FT_BOOLEAN, 16,
11870 			TFS(&tfs_set_notset), 0x0010, "file flag: vbn_access", HFILL }},
11871 		{ &hf_nfs_fh_file_flag_multivolume, {
11872 			"multivolume", "nfs.fh.file.flag.multivolume", FT_BOOLEAN, 16,
11873 			TFS(&tfs_set_notset), 0x0020, "file flag: multivolume", HFILL }},
11874 		{ &hf_nfs_fh_file_flag_metadata, {
11875 			"metadata", "nfs.fh.file.flag.metadata", FT_BOOLEAN, 16,
11876 			TFS(&tfs_set_notset), 0x0040, "file flag: metadata", HFILL }},
11877 		{ &hf_nfs_fh_file_flag_orphan, {
11878 			"orphan", "nfs.fh.file.flag.orphan", FT_BOOLEAN, 16,
11879 			TFS(&tfs_set_notset), 0x0080, "file flag: orphan", HFILL }},
11880 		{ &hf_nfs_fh_file_flag_foster, {
11881 			"foster", "nfs.fh.file.flag.foster", FT_BOOLEAN, 16,
11882 			TFS(&tfs_set_notset), 0x0100, "file flag: foster", HFILL }},
11883 		{ &hf_nfs_fh_file_flag_named_attr, {
11884 			"named_attr", "nfs.fh.file.flag.named_attr", FT_BOOLEAN, 16,
11885 			TFS(&tfs_set_notset), 0x0200, "file flag: named_attr", HFILL }},
11886 		{ &hf_nfs_fh_file_flag_exp_snapdir, {
11887 			"exp_snapdir", "nfs.fh.file.flag.exp_snapdir", FT_BOOLEAN, 16,
11888 			TFS(&tfs_set_notset), 0x0400, "file flag: exp_snapdir", HFILL }},
11889 		{ &hf_nfs_fh_file_flag_vfiler, {
11890 			"vfiler", "nfs.fh.file.flag.vfiler", FT_BOOLEAN, 16,
11891 			TFS(&tfs_set_notset), 0x0800, "file flag: vfiler", HFILL }},
11892 		{ &hf_nfs_fh_file_flag_aggr, {
11893 			"aggr", "nfs.fh.file.flag.aggr", FT_BOOLEAN, 16,
11894 			TFS(&tfs_set_notset), 0x1000, "file flag: aggr", HFILL }},
11895 		{ &hf_nfs_fh_file_flag_striped, {
11896 			"striped", "nfs.fh.file.flag.striped", FT_BOOLEAN, 16,
11897 			TFS(&tfs_set_notset), 0x2000, "file flag: striped", HFILL }},
11898 		{ &hf_nfs_fh_file_flag_private, {
11899 			"private", "nfs.fh.file.flag.private", FT_BOOLEAN, 16,
11900 			TFS(&tfs_set_notset), 0x4000, "file flag: private", HFILL }},
11901 		{ &hf_nfs_fh_file_flag_next_gen, {
11902 			"next_gen", "nfs.fh.file.flag.next_gen", FT_BOOLEAN, 16,
11903 			TFS(&tfs_set_notset), 0x8000, "file flag: next_gen", HFILL }},
11904 		{ &hf_nfs_fh_fsid_major16_mask, {
11905 			"major", "nfs.fh.fsid.major", FT_UINT16, BASE_DEC,
11906 			NULL, 0xFF00, "major file system ID", HFILL }},
11907 		{ &hf_nfs_fh_fsid_minor16_mask, {
11908 			"minor", "nfs.fh.fsid.minor", FT_UINT16, BASE_DEC,
11909 			NULL, 0x00FF, "minor file system ID", HFILL }},
11910 		{ &hf_nfs_fh_fsid_major16, {
11911 			"major", "nfs.fh.fsid.major", FT_UINT16, BASE_DEC,
11912 			NULL, 0x0, "major file system ID", HFILL }},
11913 		{ &hf_nfs_fh_fsid_minor16, {
11914 			"minor", "nfs.fh.fsid.minor", FT_UINT16, BASE_DEC,
11915 			NULL, 0x0, "minor file system ID", HFILL }},
11916 		{ &hf_nfs_fh_fsid_major32, {
11917 			"major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
11918 			NULL, 0xfffc, "major file system ID", HFILL }},
11919 		{ &hf_nfs_fh_fsid_minor32, {
11920 			"minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
11921 			NULL, 0x03ffff, "minor file system ID", HFILL }},
11922 		{ &hf_nfs_fh_fsid_inode, {
11923 			"inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
11924 			NULL, 0, "file system inode", HFILL }},
11925 		{ &hf_nfs_fh_gfid, {
11926 			"gfid", "nfs.fh.gfid", FT_GUID, BASE_NONE,
11927 			NULL, 0, "Gluster/NFS GFID", HFILL }},
11928 		{ &hf_nfs_fh_xfsid_major, {
11929 			"exported major", "nfs.fh.xfsid.major", FT_UINT16, BASE_DEC,
11930 			NULL, 0xFF00, "exported major file system ID", HFILL }},
11931 		{ &hf_nfs_fh_xfsid_minor, {
11932 			"exported minor", "nfs.fh.xfsid.minor", FT_UINT16, BASE_DEC,
11933 			NULL, 0x00FF, "exported minor file system ID", HFILL }},
11934 		{ &hf_nfs_fh_fstype, {
11935 			"file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
11936 			NULL, 0, NULL, HFILL }},
11937 		{ &hf_nfs_fh_fn, {
11938 			"file number", "nfs.fh.fn", FT_UINT32, BASE_DEC,
11939 			NULL, 0, NULL, HFILL }},
11940 		{ &hf_nfs_fh_fn_len, {
11941 			"length", "nfs.fh.fn.len", FT_UINT32, BASE_DEC,
11942 			NULL, 0, "file number length", HFILL }},
11943 		{ &hf_nfs_fh_fn_inode, {
11944 			"inode", "nfs.fh.fn.inode", FT_UINT32, BASE_DEC,
11945 			NULL, 0, "file number inode", HFILL }},
11946 		{ &hf_nfs_fh_fn_generation, {
11947 			"generation", "nfs.fh.fn.generation", FT_UINT32, BASE_DEC,
11948 			NULL, 0, "file number generation", HFILL }},
11949 		{ &hf_nfs_fh_xfn, {
11950 			"exported file number", "nfs.fh.xfn", FT_UINT32, BASE_DEC,
11951 			NULL, 0, NULL, HFILL }},
11952 		{ &hf_nfs_fh_xfn_len, {
11953 			"length", "nfs.fh.xfn.len", FT_UINT32, BASE_DEC,
11954 			NULL, 0, "exported file number length", HFILL }},
11955 		{ &hf_nfs_fh_xfn_inode, {
11956 			"exported inode", "nfs.fh.xfn.inode", FT_UINT32, BASE_DEC,
11957 			NULL, 0, "exported file number inode", HFILL }},
11958 		{ &hf_nfs_fh_xfn_generation, {
11959 			"generation", "nfs.fh.xfn.generation", FT_UINT32, BASE_DEC,
11960 			NULL, 0, "exported file number generation", HFILL }},
11961 		{ &hf_nfs_fh_dentry, {
11962 			"dentry", "nfs.fh.dentry", FT_UINT32, BASE_HEX,
11963 			NULL, 0, "dentry (cookie)", HFILL }},
11964 #if 0
11965 		{ &hf_nfs_fh_dev, {
11966 			"device", "nfs.fh.dev", FT_UINT32, BASE_DEC,
11967 			NULL, 0, NULL, HFILL }},
11968 #endif
11969 #if 0
11970 		{ &hf_nfs_fh_xdev, {
11971 			"exported device", "nfs.fh.xdev", FT_UINT32, BASE_DEC,
11972 			NULL, 0, NULL, HFILL }},
11973 #endif
11974 		{ &hf_nfs_fh_dirinode, {
11975 			"directory inode", "nfs.fh.dirinode", FT_UINT32, BASE_DEC,
11976 			NULL, 0, NULL, HFILL }},
11977 		{ &hf_nfs_fh_pinode, {
11978 			"pseudo inode", "nfs.fh.pinode", FT_UINT32, BASE_HEX,
11979 			NULL, 0, NULL, HFILL }},
11980 		{ &hf_nfs_fh_hp_len, {
11981 			"length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
11982 			NULL, 0, "hash path length", HFILL }},
11983 		{ &hf_nfs_fh_hp_key, {
11984 			"key", "nfs.fh.hp.key", FT_BYTES, BASE_NONE,
11985 			NULL, 0, NULL, HFILL }},
11986 		{ &hf_nfs_fh_version, {
11987 			"version", "nfs.fh.version", FT_UINT8, BASE_DEC,
11988 			NULL, 0, "file handle layout version", HFILL }},
11989 		{ &hf_nfs_fh_auth_type, {
11990 			"auth_type", "nfs.fh.auth_type", FT_UINT8, BASE_DEC,
11991 			VALS(auth_type_names), 0, "authentication type", HFILL }},
11992 		{ &hf_nfs_fh_fsid_type, {
11993 			"fsid_type", "nfs.fh.fsid_type", FT_UINT8, BASE_DEC,
11994 			VALS(fsid_type_names), 0, "file system ID type", HFILL }},
11995 		{ &hf_nfs_fh_fileid_type, {
11996 			"fileid_type", "nfs.fh.fileid_type", FT_UINT8, BASE_DEC,
11997 			VALS(fileid_type_names), 0, "file ID type", HFILL }},
11998 		{ &hf_nfs_fh_obj_id, {
11999 			"Object type", "nfs.fh.obj.id", FT_UINT32, BASE_DEC,
12000 			VALS(nfs_fh_obj_id), 0, "Object ID", HFILL }},
12001 		{ &hf_nfs_fh_ro_node, {
12002 			"RO_node", "nfs.fh.ro.node", FT_BOOLEAN, BASE_NONE,
12003 			TFS(&nfs4_ro_boolean), 0, "Read Only Node", HFILL }},
12004 		{ &hf_nfs_fh_obj, {
12005 			"Object info", "nfs.fh.obj.info", FT_BYTES, BASE_NONE,
12006 			NULL, 0, "File/Dir/Object Info", HFILL }},
12007 		{ &hf_nfs_fh_obj_fsid, {
12008 			"obj_fsid", "nfs.fh.obj.fsid", FT_UINT32, BASE_DEC,
12009 			NULL, 0, "File system ID of the object", HFILL }},
12010 		{ &hf_nfs_fh_obj_kindid, {
12011 			"obj_kindid", "nfs.fh.obj.kindid", FT_UINT16, BASE_DEC,
12012 			NULL, 0, "KindID of the object", HFILL }},
12013 		{ &hf_nfs_fh_obj_treeid, {
12014 			"obj_treeid", "nfs.fh.obj.treeid", FT_UINT16, BASE_DEC,
12015 			NULL, 0, "TreeID of the object", HFILL }},
12016 		{ &hf_nfs_fh_obj_inode, {
12017 			"obj_inode", "nfs.fh.obj.inode", FT_UINT32, BASE_DEC,
12018 			NULL, 0, "Inode of the object", HFILL }},
12019 		{ &hf_nfs_fh_obj_gen, {
12020 			"obj_gen", "nfs.fh.obj.gen", FT_UINT32, BASE_DEC,
12021 			NULL, 0, "Generation ID of the object", HFILL }},
12022 		{ &hf_nfs_fh_ex, {
12023 			"Export info", "nfs.fh.ex.info", FT_BYTES, BASE_NONE,
12024 			NULL, 0, "Export Info (16 bytes)", HFILL }},
12025 		{ &hf_nfs_fh_ex_fsid, {
12026 			"ex_fsid", "nfs.fh.ex.fsid", FT_UINT32, BASE_DEC,
12027 			NULL, 0, "File system ID of the object", HFILL }},
12028 		{ &hf_nfs_fh_ex_kindid, {
12029 			"ex_kindid", "nfs.fh.ex.kindid", FT_UINT16, BASE_DEC,
12030 			NULL, 0, "KindID of the object", HFILL }},
12031 		{ &hf_nfs_fh_ex_treeid, {
12032 			"ex_treeid", "nfs.fh.ex.treeid", FT_UINT16, BASE_DEC,
12033 			NULL, 0, "TreeID of the object", HFILL }},
12034 		{ &hf_nfs_fh_ex_inode, {
12035 			"ex_inode", "nfs.fh.ex.inode", FT_UINT32, BASE_DEC,
12036 			NULL, 0, "Inode of the object", HFILL }},
12037 		{ &hf_nfs_fh_ex_gen, {
12038 			"ex_gen", "nfs.fh.ex.gen", FT_UINT32, BASE_DEC,
12039 			NULL, 0, "Generation ID of the object", HFILL }},
12040 		{ &hf_nfs_fh_flag, {
12041 			"flag", "nfs.fh.flag", FT_UINT32, BASE_HEX,
12042 			NULL, 0, "file handle flag", HFILL }},
12043 		{ &hf_nfs_fh_endianness, {
12044 			"endianness", "nfs.fh.endianness", FT_BOOLEAN, BASE_NONE,
12045 			TFS(&tfs_endianness), 0x0, "server native endianness", HFILL }},
12046 		{ &hf_nfs_fh_dc_opaque, {
12047 			"fh opaque data", "nfs.fh.dc.opaque", FT_BYTES, BASE_NONE,
12048 			NULL, 0, NULL, HFILL }},
12049 		{ &hf_nfs_fh_dc_exportid, {
12050 			"export_id", "nfs.fh.dc.exportid", FT_UINT32, BASE_HEX,
12051 			NULL, 0, NULL, HFILL }},
12052 		{ &hf_nfs_fh_dc_handle_type, {
12053 			"fh type", "nfs.fh.dc.type", FT_UINT8, BASE_DEC,
12054 			VALS(dcache_handle_types), 0, NULL, HFILL }},
12055 		{ &hf_nfs4_fh_pd_share, {
12056 			"shareid", "nfs.fh.pd.shareid", FT_UINT32, BASE_DEC,
12057 			NULL, 0, NULL, HFILL }},
12058 		{ &hf_nfs4_fh_pd_flags, {
12059 			"flags", "nfs.fh.pd.flags", FT_UINT32, BASE_HEX,
12060 			NULL, 0, NULL, HFILL }},
12061 		{ &hf_nfs4_fh_pd_flags_reserved, {
12062 			"reserved", "nfs.fh.pd.flags.reserved", FT_UINT32, BASE_HEX,
12063 			NULL, PD_RESERVED_MASK, NULL, HFILL }},
12064 		{ &hf_nfs4_fh_pd_flags_version, {
12065 			"version", "nfs.fh.pd.flags.version", FT_UINT32, BASE_DEC,
12066 			NULL, PD_VERSION_MASK, NULL, HFILL }},
12067 		{ &hf_nfs4_fh_pd_sites, {
12068 			"sites", "nfs.fh.pd.sites", FT_UINT64, BASE_HEX,
12069 			NULL, 0, NULL, HFILL }},
12070 		{ &hf_nfs4_fh_pd_sites_inum, {
12071 			"inum", "nfs.fh.pd.sites.inum", FT_UINT64, BASE_HEX,
12072 			NULL, PD_INUM_MASK, NULL, HFILL }},
12073 		{ &hf_nfs4_fh_pd_sites_siteid, {
12074 			"siteid", "nfs.fh.pd.sites.siteid", FT_UINT16, BASE_DEC,
12075 			NULL, PD_SITEID_MASK, NULL, HFILL }},
12076 		{ &hf_nfs4_fh_pd_spaces, {
12077 			"spaces", "nfs.fh.pd.spaces", FT_UINT64, BASE_HEX,
12078 			NULL, 0, NULL, HFILL }},
12079 		{ &hf_nfs4_fh_pd_spaces_snapid, {
12080 			"snapid", "nfs.fh.pd.spaces.snapid", FT_UINT16, BASE_HEX,
12081 			NULL, PD_SNAPID_MASK, NULL, HFILL }},
12082 		{ &hf_nfs4_fh_pd_spaces_container, {
12083 			"container", "nfs.fh.pd.spaces.container", FT_UINT64, BASE_DEC,
12084 			NULL, PD_CONTAINER_MASK, NULL, HFILL }},
12085 		{ &hf_nfs4_fh_pd_container, {
12086 			"container", "nfs.fh.pd.container", FT_UINT64, BASE_DEC,
12087 			NULL, 0, NULL, HFILL }},
12088 		{ &hf_nfs4_fh_pd_inum, {
12089 			"inum", "nfs.fh.pd.inum", FT_UINT64, BASE_DEC,
12090 			NULL, 0, NULL, HFILL }},
12091 		{ &hf_nfs2_status, {
12092 			"Status", "nfs.status2", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12093 			&names_nfs2_stat_ext, 0, "Reply status", HFILL }},
12094 		{ &hf_nfs_full_name, {
12095 			"Full Name", "nfs.full_name", FT_STRING, BASE_NONE,
12096 			NULL, 0, NULL, HFILL }},
12097 		{ &hf_nfs_name, {
12098 			"Name", "nfs.name", FT_STRING, BASE_NONE,
12099 			NULL, 0, NULL, HFILL }},
12100 		{ &hf_nfs2_readlink_data, {
12101 			"Data", "nfs.readlink.data", FT_STRING, BASE_NONE,
12102 			NULL, 0, "Symbolic Link Data", HFILL }},
12103 		{ &hf_nfs2_read_offset, {
12104 			"Offset", "nfs.read.offset", FT_UINT32, BASE_DEC,
12105 			NULL, 0, "Read Offset", HFILL }},
12106 		{ &hf_nfs2_read_count, {
12107 			"Count", "nfs.read.count", FT_UINT32, BASE_DEC,
12108 			NULL, 0, "Read Count", HFILL }},
12109 		{ &hf_nfs2_read_totalcount, {
12110 			"Total Count", "nfs.read.totalcount", FT_UINT32, BASE_DEC,
12111 			NULL, 0, "Total Count (obsolete)", HFILL }},
12112 		{ &hf_nfs_data, {
12113 			"Data", "nfs.data", FT_BYTES, BASE_NONE,
12114 			NULL, 0, NULL, HFILL }},
12115 		{ &hf_nfs4_read_data_length, {
12116 			"Read length", "nfs.read.data_length", FT_UINT32, BASE_DEC,
12117 			NULL, 0, "Length of read response", HFILL }},
12118 		{ &hf_nfs4_write_data_length, {
12119 			"Write length", "nfs.write.data_length", FT_UINT32, BASE_DEC,
12120 			NULL, 0, "Length of write request", HFILL }},
12121 		{ &hf_nfs2_write_beginoffset, {
12122 			"Begin Offset", "nfs.write.beginoffset", FT_UINT32, BASE_DEC,
12123 			NULL, 0, "Begin offset (obsolete)", HFILL }},
12124 		{ &hf_nfs2_write_offset, {
12125 			"Offset", "nfs.write.offset", FT_UINT32, BASE_DEC,
12126 			NULL, 0, NULL, HFILL }},
12127 		{ &hf_nfs2_write_totalcount, {
12128 			"Total Count", "nfs.write.totalcount", FT_UINT32, BASE_DEC,
12129 			NULL, 0, "Total Count (obsolete)", HFILL }},
12130 		{ &hf_nfs_symlink_to, {
12131 			"To", "nfs.symlink.to", FT_STRING, BASE_NONE,
12132 			NULL, 0, "Symbolic link destination name", HFILL }},
12133 		{ &hf_nfs2_readdir_cookie, {
12134 			"Cookie", "nfs.readdir.cookie", FT_UINT32, BASE_DEC,
12135 			NULL, 0, "Directory Cookie", HFILL }},
12136 		{ &hf_nfs2_readdir_count, {
12137 			"Count", "nfs.readdir.count", FT_UINT32, BASE_DEC,
12138 			NULL, 0, "Directory Count", HFILL }},
12139 
12140 		{ &hf_nfs_readdir_entry, {
12141 			"Entry", "nfs.readdir.entry", FT_NONE, BASE_NONE,
12142 			NULL, 0, "Directory Entry", HFILL }},
12143 
12144 		{ &hf_nfs2_readdir_entry_fileid, {
12145 			"File ID", "nfs.readdir.entry.fileid", FT_UINT32, BASE_DEC,
12146 			NULL, 0, NULL, HFILL }},
12147 
12148 		{ &hf_nfs2_readdir_entry_name, {
12149 			"Name", "nfs.readdir.entry.name", FT_STRING, BASE_NONE,
12150 			NULL, 0, NULL, HFILL }},
12151 
12152 		{ &hf_nfs2_readdir_entry_cookie, {
12153 			"Cookie", "nfs.readdir.entry.cookie", FT_UINT32, BASE_DEC,
12154 			NULL, 0, "Directory Cookie", HFILL }},
12155 
12156 		{ &hf_nfs3_readdir_entry_fileid, {
12157 			"File ID", "nfs.readdir.entry3.fileid", FT_UINT64, BASE_DEC,
12158 			NULL, 0, NULL, HFILL }},
12159 
12160 		{ &hf_nfs3_readdir_entry_name, {
12161 			"Name", "nfs.readdir.entry3.name", FT_STRING, BASE_NONE,
12162 			NULL, 0, NULL, HFILL }},
12163 
12164 		{ &hf_nfs3_readdir_entry_cookie, {
12165 			"Cookie", "nfs.readdir.entry3.cookie", FT_UINT64, BASE_DEC,
12166 			NULL, 0, "Directory Cookie", HFILL }},
12167 
12168 		{ &hf_nfs3_readdirplus_entry_fileid, {
12169 			"File ID", "nfs.readdirplus.entry.fileid", FT_UINT64, BASE_DEC,
12170 			NULL, 0, NULL, HFILL }},
12171 
12172 		{ &hf_nfs3_readdirplus_entry_name, {
12173 			"Name", "nfs.readdirplus.entry.name", FT_STRING, BASE_NONE,
12174 			NULL, 0, NULL, HFILL }},
12175 
12176 		{ &hf_nfs3_readdirplus_entry_cookie, {
12177 			"Cookie", "nfs.readdirplus.entry.cookie", FT_UINT64, BASE_DEC,
12178 			NULL, 0, "Directory Cookie", HFILL }},
12179 
12180 		{ &hf_nfs_readdir_eof, {
12181 			"EOF", "nfs.readdir.eof", FT_UINT32, BASE_DEC,
12182 			NULL, 0, NULL, HFILL }},
12183 
12184 		{ &hf_nfs2_statfs_tsize, {
12185 			"Transfer Size", "nfs.statfs.tsize", FT_UINT32, BASE_DEC,
12186 			NULL, 0, NULL, HFILL }},
12187 		{ &hf_nfs2_statfs_bsize, {
12188 			"Block Size", "nfs.statfs.bsize", FT_UINT32, BASE_DEC,
12189 			NULL, 0, NULL, HFILL }},
12190 		{ &hf_nfs2_statfs_blocks, {
12191 			"Total Blocks", "nfs.statfs.blocks", FT_UINT32, BASE_DEC,
12192 			NULL, 0, NULL, HFILL }},
12193 		{ &hf_nfs2_statfs_bfree, {
12194 			"Free Blocks", "nfs.statfs.bfree", FT_UINT32, BASE_DEC,
12195 			NULL, 0, NULL, HFILL }},
12196 		{ &hf_nfs2_statfs_bavail, {
12197 			"Available Blocks", "nfs.statfs.bavail", FT_UINT32, BASE_DEC,
12198 			NULL, 0, NULL, HFILL }},
12199 		{ &hf_nfs3_ftype, {
12200 			"Type", "nfs.type", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12201 			&names_nfs_ftype3_ext, 0, "File Type", HFILL }},
12202 		{ &hf_nfs3_status, {
12203 			"Status", "nfs.status3", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12204 			&names_nfs3_status_ext, 0, "Reply status", HFILL }},
12205 		{ &hf_nfs3_read_eof, {
12206 			"EOF", "nfs.read.eof", FT_BOOLEAN, BASE_NONE,
12207 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12208 		{ &hf_nfs3_write_stable, {
12209 			"Stable", "nfs.write.stable", FT_UINT32, BASE_DEC,
12210 			VALS(names_stable_how), 0, NULL, HFILL }},
12211 		{ &hf_nfs3_write_committed, {
12212 			"Committed", "nfs.write.committed", FT_UINT32, BASE_DEC,
12213 			VALS(names_stable_how), 0, NULL, HFILL }},
12214 		{ &hf_nfs3_createmode, {
12215 			"Create Mode", "nfs.createmode", FT_UINT32, BASE_DEC,
12216 			VALS(names_createmode3), 0, NULL, HFILL }},
12217 		{ &hf_nfs3_fsstat_invarsec, {
12218 			"invarsec", "nfs.fsstat.invarsec", FT_UINT32, BASE_DEC,
12219 			NULL, 0, "probable number of seconds of file system invariance", HFILL }},
12220 		{ &hf_nfs3_fsinfo_rtmax, {
12221 			"rtmax", "nfs.fsinfo.rtmax", FT_UINT32, BASE_DEC,
12222 			NULL, 0, "maximum READ request", HFILL }},
12223 		{ &hf_nfs3_fsinfo_rtpref, {
12224 			"rtpref", "nfs.fsinfo.rtpref", FT_UINT32, BASE_DEC,
12225 			NULL, 0, "Preferred READ request size", HFILL }},
12226 		{ &hf_nfs3_fsinfo_rtmult, {
12227 			"rtmult", "nfs.fsinfo.rtmult", FT_UINT32, BASE_DEC,
12228 			NULL, 0, "Suggested READ multiple", HFILL }},
12229 		{ &hf_nfs3_fsinfo_wtmax, {
12230 			"wtmax", "nfs.fsinfo.wtmax", FT_UINT32, BASE_DEC,
12231 			NULL, 0, "Maximum WRITE request size", HFILL }},
12232 		{ &hf_nfs3_fsinfo_wtpref, {
12233 			"wtpref", "nfs.fsinfo.wtpref", FT_UINT32, BASE_DEC,
12234 			NULL, 0, "Preferred WRITE request size", HFILL }},
12235 		{ &hf_nfs3_fsinfo_wtmult, {
12236 			"wtmult", "nfs.fsinfo.wtmult", FT_UINT32, BASE_DEC,
12237 			NULL, 0, "Suggested WRITE multiple", HFILL }},
12238 		{ &hf_nfs3_fsinfo_dtpref, {
12239 			"dtpref", "nfs.fsinfo.dtpref", FT_UINT32, BASE_DEC,
12240 			NULL, 0, "Preferred READDIR request", HFILL }},
12241 		{ &hf_nfs3_fsinfo_maxfilesize, {
12242 			"maxfilesize", "nfs.fsinfo.maxfilesize", FT_UINT64, BASE_DEC,
12243 			NULL, 0, "Maximum file size", HFILL }},
12244 		{ &hf_nfs3_fsinfo_properties, {
12245 			"Properties", "nfs.fsinfo.properties", FT_UINT32, BASE_HEX,
12246 			NULL, 0, "File System Properties", HFILL }},
12247 		{ &hf_nfs3_fsinfo_properties_setattr, {
12248 			"SETATTR can set time on server", "nfs.fsinfo.properties.setattr", FT_BOOLEAN, 32,
12249 			TFS(&tfs_yes_no), FSF3_CANSETTIME, NULL, HFILL }},
12250 		{ &hf_nfs3_fsinfo_properties_pathconf, {
12251 			"PATHCONF", "nfs.fsinfo.properties.pathconf", FT_BOOLEAN, 32,
12252 			TFS(&tfs_nfs_pathconf), FSF3_HOMOGENEOUS, NULL, HFILL }},
12253 		{ &hf_nfs3_fsinfo_properties_symlinks, {
12254 			"File System supports symbolic links", "nfs.fsinfo.properties.symlinks", FT_BOOLEAN, 32,
12255 			TFS(&tfs_yes_no), FSF3_SYMLINK, NULL, HFILL }},
12256 		{ &hf_nfs3_fsinfo_properties_hardlinks, {
12257 			"File System supports hard links", "nfs.fsinfo.properties.hardlinks", FT_BOOLEAN, 32,
12258 			TFS(&tfs_yes_no), FSF3_LINK, NULL, HFILL }},
12259 		{ &hf_nfs3_pathconf_linkmax, {
12260 			"linkmax", "nfs.pathconf.linkmax", FT_UINT32, BASE_DEC,
12261 			NULL, 0, "Maximum number of hard links", HFILL }},
12262 		{ &hf_nfs3_pathconf_name_max, {
12263 			"name_max", "nfs.pathconf.name_max", FT_UINT32, BASE_DEC,
12264 			NULL, 0, "Maximum file name length", HFILL }},
12265 		{ &hf_nfs3_pathconf_no_trunc, {
12266 			"no_trunc", "nfs.pathconf.no_trunc", FT_BOOLEAN, BASE_NONE,
12267 			TFS(&tfs_yes_no), 0x0, "No long file name truncation", HFILL }},
12268 		{ &hf_nfs3_pathconf_chown_restricted, {
12269 			"chown_restricted", "nfs.pathconf.chown_restricted", FT_BOOLEAN, BASE_NONE,
12270 			TFS(&tfs_yes_no), 0x0, "chown is restricted to root", HFILL }},
12271 		{ &hf_nfs3_pathconf_case_insensitive, {
12272 			"case_insensitive", "nfs.pathconf.case_insensitive", FT_BOOLEAN, BASE_NONE,
12273 			TFS(&tfs_yes_no), 0x0, "file names are treated case insensitive", HFILL }},
12274 		{ &hf_nfs3_pathconf_case_preserving, {
12275 			"case_preserving", "nfs.pathconf.case_preserving", FT_BOOLEAN, BASE_NONE,
12276 			TFS(&tfs_yes_no), 0x0, "file name cases are preserved", HFILL }},
12277 
12278 #if 0
12279 		{ &hf_nfs2_fattr_type, {
12280 			"type", "nfs.fattr.type", FT_UINT32, BASE_DEC,
12281 			NULL, 0, NULL, HFILL }},
12282 #endif
12283 
12284 		{ &hf_nfs2_fattr_nlink, {
12285 			"nlink", "nfs.fattr.nlink", FT_UINT32, BASE_DEC,
12286 			NULL, 0, NULL, HFILL }},
12287 
12288 		{ &hf_nfs2_fattr_uid, {
12289 			"uid", "nfs.fattr.uid", FT_UINT32, BASE_DEC,
12290 			NULL, 0, NULL, HFILL }},
12291 
12292 		{ &hf_nfs2_fattr_gid, {
12293 			"gid", "nfs.fattr.gid", FT_UINT32, BASE_DEC,
12294 			NULL, 0, NULL, HFILL }},
12295 
12296 		{ &hf_nfs2_fattr_size, {
12297 			"size", "nfs.fattr.size", FT_UINT32, BASE_DEC,
12298 			NULL, 0, NULL, HFILL }},
12299 
12300 		{ &hf_nfs2_fattr_blocksize, {
12301 			"blocksize", "nfs.fattr.blocksize", FT_UINT32, BASE_DEC,
12302 			NULL, 0, NULL, HFILL }},
12303 
12304 		{ &hf_nfs2_fattr_rdev, {
12305 			"rdev", "nfs.fattr.rdev", FT_UINT32, BASE_DEC,
12306 			NULL, 0, NULL, HFILL }},
12307 
12308 		{ &hf_nfs2_fattr_blocks, {
12309 			"blocks", "nfs.fattr.blocks", FT_UINT32, BASE_DEC,
12310 			NULL, 0, NULL, HFILL }},
12311 
12312 		{ &hf_nfs2_fattr_fsid, {
12313 			"fsid", "nfs.fattr.fsid", FT_UINT32, BASE_HEX,
12314 			NULL, 0, NULL, HFILL }},
12315 
12316 		{ &hf_nfs2_fattr_fileid, {
12317 			"fileid", "nfs.fattr.fileid", FT_UINT32, BASE_DEC,
12318 			NULL, 0, NULL, HFILL }},
12319 
12320 		{ &hf_nfs3_fattr_type, {
12321 			"Type", "nfs.fattr3.type", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12322 			&names_nfs_ftype3_ext, 0, NULL, HFILL }},
12323 
12324 		{ &hf_nfs3_fattr_nlink, {
12325 			"nlink", "nfs.fattr3.nlink", FT_UINT32, BASE_DEC,
12326 			NULL, 0, NULL, HFILL }},
12327 
12328 		{ &hf_nfs3_fattr_uid, {
12329 			"uid", "nfs.fattr3.uid", FT_UINT32, BASE_DEC,
12330 			NULL, 0, NULL, HFILL }},
12331 
12332 		{ &hf_nfs3_fattr_gid, {
12333 			"gid", "nfs.fattr3.gid", FT_UINT32, BASE_DEC,
12334 			NULL, 0, NULL, HFILL }},
12335 
12336 		{ &hf_nfs3_fattr_size, {
12337 			"size", "nfs.fattr3.size", FT_UINT64, BASE_DEC,
12338 			NULL, 0, NULL, HFILL }},
12339 
12340 		{ &hf_nfs3_fattr_used, {
12341 			"used", "nfs.fattr3.used", FT_UINT64, BASE_DEC,
12342 			NULL, 0, NULL, HFILL }},
12343 
12344 #if 0
12345 		{ &hf_nfs3_fattr_rdev, {
12346 			"rdev", "nfs.fattr3.rdev", FT_UINT32, BASE_DEC,
12347 			NULL, 0, NULL, HFILL }},
12348 #endif
12349 
12350 		{ &hf_nfs3_fattr_fsid, {
12351 			"fsid", "nfs.fattr3.fsid", FT_UINT64, BASE_HEX_DEC,
12352 			NULL, 0, NULL, HFILL }},
12353 
12354 		{ &hf_nfs3_fattr_fileid, {
12355 			"fileid", "nfs.fattr3.fileid", FT_UINT64, BASE_DEC,
12356 			NULL, 0, NULL, HFILL }},
12357 
12358 		{ &hf_nfs3_wcc_attr_size, {
12359 			"size", "nfs.wcc_attr.size", FT_UINT64, BASE_DEC,
12360 			NULL, 0, NULL, HFILL }},
12361 
12362 		{ &hf_nfs3_set_size, {
12363 			"size", "nfs.set_size", FT_UINT64, BASE_DEC,
12364 			NULL, 0, NULL, HFILL }},
12365 
12366 		{ &hf_nfs3_uid, {
12367 			"uid", "nfs.uid3", FT_UINT32, BASE_DEC,
12368 			NULL, 0, NULL, HFILL }},
12369 
12370 		{ &hf_nfs3_gid, {
12371 			"gid", "nfs.gid3", FT_UINT32, BASE_DEC,
12372 			NULL, 0, NULL, HFILL }},
12373 
12374 		{ &hf_nfs3_cookie, {
12375 			"cookie", "nfs.cookie3", FT_UINT64, BASE_DEC,
12376 			NULL, 0, NULL, HFILL }},
12377 
12378 		{ &hf_nfs3_offset, {
12379 			"offset", "nfs.offset3", FT_UINT64, BASE_DEC,
12380 			NULL, 0, NULL, HFILL }},
12381 
12382 		{ &hf_nfs3_count, {
12383 			"count", "nfs.count3", FT_UINT32, BASE_DEC,
12384 			NULL, 0, NULL, HFILL }},
12385 
12386 		{ &hf_nfs3_count_maxcount, {
12387 			"maxcount", "nfs.count3_maxcount", FT_UINT32, BASE_DEC,
12388 			NULL, 0, NULL, HFILL }},
12389 
12390 		{ &hf_nfs3_count_dircount, {
12391 			"dircount", "nfs.count3_dircount", FT_UINT32, BASE_DEC,
12392 			NULL, 0, NULL, HFILL }},
12393 
12394 		{ &hf_nfs3_fsstat_resok_tbytes, {
12395 			"Total bytes", "nfs.fsstat3_resok.tbytes", FT_UINT64, BASE_DEC,
12396 			NULL, 0, NULL, HFILL }},
12397 
12398 		{ &hf_nfs3_fsstat_resok_fbytes, {
12399 			"Free bytes", "nfs.fsstat3_resok.fbytes", FT_UINT64, BASE_DEC,
12400 			NULL, 0, NULL, HFILL }},
12401 
12402 		{ &hf_nfs3_fsstat_resok_abytes, {
12403 			"Available free bytes", "nfs.fsstat3_resok.abytes", FT_UINT64, BASE_DEC,
12404 			NULL, 0, NULL, HFILL }},
12405 
12406 		{ &hf_nfs3_fsstat_resok_tfiles, {
12407 			"Total file slots", "nfs.fsstat3_resok.tfiles", FT_UINT64, BASE_DEC,
12408 			NULL, 0, NULL, HFILL }},
12409 
12410 		{ &hf_nfs3_fsstat_resok_ffiles, {
12411 			"Free file slots", "nfs.fsstat3_resok.ffiles", FT_UINT64, BASE_DEC,
12412 			NULL, 0, NULL, HFILL }},
12413 
12414 		{ &hf_nfs3_fsstat_resok_afiles, {
12415 			"Available free file slots", "nfs.fsstat3_resok.afiles", FT_UINT64, BASE_DEC,
12416 			NULL, 0, NULL, HFILL }},
12417 
12418 		/* NFSv4 */
12419 
12420 		{ &hf_nfs4_status, {
12421 			"Status", "nfs.nfsstat4", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12422 			&names_nfs4_status_ext, 0, "Reply status", HFILL }},
12423 
12424 		{ &hf_nfs4_op, {
12425 			"Opcode", "nfs.opcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12426 			&names_nfs4_operation_ext, 0, NULL, HFILL }},
12427 
12428 		{ &hf_nfs4_op_mask, {
12429 			"op_mask", "nfs.op_mask", FT_UINT32, BASE_HEX,
12430 			NULL, 0, "Operation Mask", HFILL }},
12431 
12432 		{ &hf_nfs4_main_opcode, {
12433 			"Main Opcode", "nfs.main_opcode", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
12434 			&names_nfs4_operation_ext, 0, "Main Operation number", HFILL }},
12435 
12436 		{ &hf_nfs4_linktext, {
12437 			"Link Contents", "nfs.symlink.linktext", FT_STRING, BASE_NONE,
12438 			NULL, 0, "Symbolic link contents", HFILL }},
12439 
12440 		{ &hf_nfs4_dir_entry_name, {
12441 			"Name", "nfs.entry_name", FT_STRING, BASE_NONE,
12442 			NULL, 0, "Directory entry name", HFILL }},
12443 
12444 		{ &hf_nfs4_pathname_components, {
12445 			"pathname components", "nfs.pathname.component.count", FT_UINT32, BASE_DEC,
12446 			NULL, 0, "Number of Pathname component", HFILL }},
12447 
12448 		{ &hf_nfs4_component, {
12449 			"Name", "nfs.pathname.component", FT_STRING, BASE_NONE,
12450 			NULL, 0, "Pathname component", HFILL }},
12451 
12452 		{ &hf_nfs4_tag, {
12453 			"Tag", "nfs.tag", FT_STRING, BASE_NONE,
12454 			NULL, 0, NULL, HFILL }},
12455 
12456 		{ &hf_nfs4_ops_count, {
12457 			"Operations", "nfs.ops.count", FT_UINT32, BASE_DEC,
12458 			NULL, 0, "Number of Operations", HFILL }},
12459 
12460 		{ &hf_nfs4_clientid, {
12461 			"clientid", "nfs.clientid", FT_UINT64, BASE_HEX,
12462 			NULL, 0, "Client ID", HFILL }},
12463 
12464 #if 0
12465 		{ &hf_nfs4_ace, {
12466 			"ace", "nfs.ace", FT_STRING, BASE_NONE,
12467 			NULL, 0, "Access Control Entry", HFILL }},
12468 #endif
12469 
12470 		{ &hf_nfs4_recall, {
12471 			"Recall", "nfs.recall", FT_BOOLEAN, BASE_NONE,
12472 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12473 
12474 		{ &hf_nfs4_open_claim_type, {
12475 			"Claim Type", "nfs.open.claim_type", FT_UINT32, BASE_DEC,
12476 			VALS(names_claim_type4), 0, NULL, HFILL }},
12477 
12478 		{ &hf_nfs4_opentype, {
12479 			"Open Type", "nfs.open.opentype", FT_UINT32, BASE_DEC,
12480 			VALS(names_opentype4), 0, NULL, HFILL }},
12481 
12482 		{ &hf_nfs4_state_protect_how, {
12483 			"eia_state_protect", "nfs.exchange_id.state_protect", FT_UINT32, BASE_DEC,
12484 			VALS(names_state_protect_how4), 0, "State Protect How", HFILL }},
12485 
12486 		{ &hf_nfs4_limit_by, {
12487 			"Space Limit", "nfs.open.limit_by", FT_UINT32, BASE_DEC,
12488 			VALS(names_limit_by4), 0, "Limit By", HFILL }},
12489 
12490 		{ &hf_nfs4_open_delegation_type, {
12491 			"Delegation Type", "nfs.open.delegation_type", FT_UINT32, BASE_DEC,
12492 			VALS(names_open_delegation_type4), 0, NULL, HFILL }},
12493 
12494 		{ &hf_nfs4_why_no_delegation, {
12495 			"why no delegation", "nfs.open.why_no_delegation", FT_UINT32, BASE_DEC,
12496 			VALS(names_why_no_delegation4), 0, NULL, HFILL }},
12497 
12498 		{ &hf_nfs4_secinfo_style, {
12499 			"Secinfo Style", "nfs.secinfo.style", FT_UINT32, BASE_DEC,
12500 			VALS(names_secinfo_style4), 0, NULL, HFILL }},
12501 
12502 		{ &hf_nfs4_ftype, {
12503 			"ftype4", "nfs.nfs_ftype4", FT_UINT32, BASE_DEC,
12504 			VALS(names_ftype4), 0, NULL, HFILL }},
12505 
12506 		{ &hf_nfs4_change_info_atomic, {
12507 			"Atomic", "nfs.change_info.atomic", FT_BOOLEAN, BASE_NONE,
12508 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12509 
12510 		{ &hf_nfs4_open_share_access, {
12511 			"share_access", "nfs.open4.share_access", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
12512 			&names_open4_share_access_ext, 0, NULL, HFILL }},
12513 
12514 		{ &hf_nfs4_open_share_deny, {
12515 			"share_deny", "nfs.open4.share_deny", FT_UINT32, BASE_DEC,
12516 			VALS(names_open4_share_deny), 0, NULL, HFILL }},
12517 
12518 		{ &hf_nfs4_want_flags, {
12519 			"wants", "nfs.want", FT_UINT32, BASE_HEX | BASE_EXT_STRING,
12520 			&names_open4_share_access_ext, 0, NULL, HFILL }},
12521 
12522 		{ &hf_nfs4_want_notify_flags, {
12523 			"want notification", "nfs.want_notification", FT_UINT32, BASE_HEX,
12524 			NULL, 0, NULL, HFILL }},
12525 
12526 		{ &hf_nfs4_want_signal_deleg_when_resrc_avail, {
12527 			"want_signal_deleg_when_resrc_avail",
12528 			"nfs.want_notification.when_resrc_avail", FT_BOOLEAN, 32,
12529 			TFS(&tfs_set_notset), OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL, NULL, HFILL }},
12530 
12531 		{ &hf_nfs4_want_push_deleg_when_uncontended, {
12532 			"want_push_deleg_when_uncontended",
12533 			"nfs.want_push_deleg_when_uncontended", FT_BOOLEAN, 32,
12534 			TFS(&tfs_set_notset), OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED, NULL, HFILL }},
12535 
12536 		{ &hf_nfs4_want_deleg_timestamps, {
12537 			"want_deleg_timestamps",
12538 			"nfs.want_deleg_timestamps", FT_BOOLEAN, 32,
12539 			TFS(&tfs_set_notset), OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS, NULL, HFILL }},
12540 
12541 		{ &hf_nfs4_seqid, {
12542 			"seqid", "nfs.seqid", FT_UINT32, BASE_HEX,
12543 			NULL, 0, "Sequence ID", HFILL }},
12544 
12545 		{ &hf_nfs4_lock_seqid, {
12546 			"lock_seqid", "nfs.lock_seqid", FT_UINT32, BASE_HEX,
12547 			NULL, 0, "Lock Sequence ID", HFILL }},
12548 
12549 		{ &hf_nfs4_reqd_attr, {
12550 			"reqd_attr", "nfs.attr", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
12551 			&fattr4_names_ext, 0, "Required Attribute", HFILL }},
12552 
12553 		{ &hf_nfs4_reco_attr, {
12554 			"reco_attr", "nfs.attr", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
12555 			&fattr4_names_ext, 0, "Recommended Attribute", HFILL }},
12556 
12557 		{ &hf_nfs4_attr_mask, {
12558 			"Attr mask", "nfs.attr_mask", FT_UINT32, BASE_HEX,
12559 			NULL, 0, "Attribute mask", HFILL }},
12560 
12561 		{ &hf_nfs4_attr_count, {
12562 			"Attr count", "nfs.attr_count", FT_UINT32, BASE_DEC,
12563 			NULL, 0, NULL, HFILL }},
12564 
12565 		{ &hf_nfs4_set_it_value_follows,	{
12566 			"set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
12567 			VALS(value_follows), 0, "How To Set Time", HFILL }},
12568 
12569 		{ &hf_nfs4_time_how,	{
12570 			"set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
12571 			VALS(time_how), 0, "How To Set Time", HFILL }},
12572 
12573 		{ &hf_nfs4_time_how4,	{
12574 			"set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
12575 			VALS(names_time_how4), 0, "How To Set Time", HFILL }},
12576 
12577 		{ &hf_nfs4_fattr_link_support, {
12578 			"fattr4_link_support", "nfs.fattr4_link_support", FT_BOOLEAN, BASE_NONE,
12579 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12580 
12581 		{ &hf_nfs4_fattr_symlink_support, {
12582 			"fattr4_symlink_support", "nfs.fattr4_symlink_support", FT_BOOLEAN, BASE_NONE,
12583 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12584 
12585 		{ &hf_nfs4_fattr_named_attr, {
12586 			"fattr4_named_attr", "nfs.fattr4_named_attr", FT_BOOLEAN, BASE_NONE,
12587 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12588 
12589 		{ &hf_nfs4_fattr_unique_handles, {
12590 			"fattr4_unique_handles", "nfs.fattr4_unique_handles", FT_BOOLEAN, BASE_NONE,
12591 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12592 
12593 		{ &hf_nfs4_fattr_archive, {
12594 			"fattr4_archive", "nfs.fattr4_archive", FT_BOOLEAN, BASE_NONE,
12595 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12596 
12597 		{ &hf_nfs4_fattr_cansettime, {
12598 			"fattr4_cansettime", "nfs.fattr4_cansettime", FT_BOOLEAN, BASE_NONE,
12599 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12600 
12601 		{ &hf_nfs4_fattr_case_insensitive, {
12602 			"fattr4_case_insensitive", "nfs.fattr4_case_insensitive", FT_BOOLEAN, BASE_NONE,
12603 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12604 
12605 		{ &hf_nfs4_fattr_case_preserving, {
12606 			"fattr4_case_preserving", "nfs.fattr4_case_preserving", FT_BOOLEAN, BASE_NONE,
12607 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12608 
12609 		{ &hf_nfs4_fattr_chown_restricted, {
12610 			"fattr4_chown_restricted", "nfs.fattr4_chown_restricted", FT_BOOLEAN, BASE_NONE,
12611 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12612 
12613 		{ &hf_nfs4_fattr_fh_expire_type, {
12614 			"fattr4_fh_expire_type", "nfs.fattr4_fh_expire_type", FT_UINT32, BASE_HEX,
12615 			VALS(nfs4_fattr4_fh_expire_type_names), 0, NULL, HFILL }},
12616 
12617 		{ &hf_nfs4_fattr_fh_expiry_noexpire_with_open, {
12618 			"noexpire_with_open", "nfs.fattr4_fh_expire_type.noexpire_with_open",
12619 			FT_BOOLEAN, 32,
12620 			NULL, FH4_NOEXPIRE_WITH_OPEN, NULL, HFILL }},
12621 		{ &hf_nfs4_fattr_fh_expiry_volatile_any, {
12622 			"volatile_any", "nfs.fattr4_fh_expire_type.volatile_any",
12623 			FT_BOOLEAN, 32,
12624 			NULL, FH4_NOEXPIRE_WITH_OPEN, NULL, HFILL }},
12625 		{ &hf_nfs4_fattr_fh_expiry_vol_migration, {
12626 			"vol_migration", "nfs.fattr4_fh_expire_type.vol_migration",
12627 			FT_BOOLEAN, 32,
12628 			NULL, FH4_NOEXPIRE_WITH_OPEN, NULL, HFILL }},
12629 		{ &hf_nfs4_fattr_fh_expiry_vol_rename, {
12630 			"vol_rename", "nfs.fattr4_fh_expire_type.vol_rename",
12631 			FT_BOOLEAN, 32,
12632 			NULL, FH4_NOEXPIRE_WITH_OPEN, NULL, HFILL }},
12633 
12634 		{ &hf_nfs4_fattr_hidden, {
12635 			"fattr4_hidden", "nfs.fattr4_hidden", FT_BOOLEAN, BASE_NONE,
12636 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12637 
12638 		{ &hf_nfs4_fattr_homogeneous, {
12639 			"fattr4_homogeneous", "nfs.fattr4_homogeneous", FT_BOOLEAN, BASE_NONE,
12640 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12641 
12642 		{ &hf_nfs4_fattr_mimetype, {
12643 			"fattr4_mimetype", "nfs.fattr4_mimetype", FT_STRING, BASE_NONE,
12644 			NULL, 0, NULL, HFILL }},
12645 
12646 		{ &hf_nfs4_fattr_no_trunc, {
12647 			"fattr4_no_trunc", "nfs.fattr4_no_trunc", FT_BOOLEAN, BASE_NONE,
12648 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12649 
12650 		{ &hf_nfs4_fattr_system, {
12651 			"fattr4_system", "nfs.fattr4_system", FT_BOOLEAN, BASE_NONE,
12652 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12653 
12654 		{ &hf_nfs4_who, {
12655 			"Who", "nfs.who", FT_STRING, BASE_NONE,
12656 			NULL, 0, NULL, HFILL }},
12657 
12658 		{ &hf_nfs4_server, {
12659 			"server", "nfs.server", FT_STRING, BASE_NONE,
12660 			NULL, 0, NULL, HFILL }},
12661 
12662 		{ &hf_nfs4_servers, {
12663 			"servers", "nfs.servers", FT_NONE, BASE_NONE,
12664 			NULL, 0, NULL, HFILL }},
12665 
12666 		{ &hf_nfs4_fslocation, {
12667 			"fs_location4", "nfs.fattr4.fs_location", FT_NONE, BASE_NONE,
12668 			NULL, 0, NULL, HFILL }},
12669 
12670 		{ &hf_nfs4_fattr_owner, {
12671 			"fattr4_owner", "nfs.fattr4_owner", FT_STRING, BASE_NONE,
12672 			NULL, 0, NULL, HFILL }},
12673 
12674 		{ &hf_nfs4_fattr_owner_group, {
12675 			"fattr4_owner_group", "nfs.fattr4_owner_group", FT_STRING, BASE_NONE,
12676 			NULL, 0, NULL, HFILL }},
12677 
12678 		{ &hf_nfs4_stable_how, {
12679 			"stable_how4", "nfs.stable_how4", FT_UINT32, BASE_DEC,
12680 			VALS(names_stable_how4), 0, NULL, HFILL }},
12681 
12682 		{ &hf_nfs4_dirlist_eof, {
12683 			"EOF", "nfs.dirlist4.eof", FT_BOOLEAN, BASE_NONE,
12684 			TFS(&tfs_yes_no), 0x0, "There are no more entries", HFILL }},
12685 
12686 		/* StateID */
12687 		{ &hf_nfs4_stateid,{
12688 			"StateID", "nfs.stateid", FT_BYTES, BASE_NONE,
12689 			NULL, 0, NULL, HFILL }},
12690 		{ &hf_nfs4_stateid_hash,{
12691 			"StateID Hash", "nfs.stateid.hash", FT_UINT16, BASE_HEX,
12692 			NULL, 0, "CRC-16 hash", HFILL }},
12693 		{ &hf_nfs4_seqid_stateid, {
12694 			"StateID seqid", "nfs.stateid.seqid", FT_UINT32, BASE_DEC,
12695 			NULL, 0, NULL, HFILL }},
12696 		{ &hf_nfs4_stateid_other,{
12697 			"StateID Other", "nfs.stateid.other", FT_BYTES, BASE_NONE,
12698 			NULL, 0, "Unique component of StateID", HFILL }},
12699 		{ &hf_nfs4_stateid_other_hash,{
12700 			"StateID Other hash", "nfs.stateid.other_hash", FT_UINT32, BASE_HEX,
12701 			NULL, 0, "CRC-32 hash", HFILL }},
12702 
12703 		{ &hf_nfs4_offset, {
12704 			"offset", "nfs.offset4", FT_UINT64, BASE_DEC,
12705 			NULL, 0, NULL, HFILL }},
12706 
12707 		{ &hf_nfs4_specdata1, {
12708 			"specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
12709 			NULL, 0, NULL, HFILL }},
12710 
12711 		{ &hf_nfs4_specdata2, {
12712 			"specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
12713 			NULL, 0, NULL, HFILL }},
12714 
12715 		{ &hf_nfs4_lock_type, {
12716 			"locktype", "nfs.locktype4", FT_UINT32, BASE_DEC,
12717 			VALS(names_nfs_lock_type4), 0, NULL, HFILL }},
12718 
12719 		{ &hf_nfs4_open_rflags, {
12720 			"result flags", "nfs.open_rflags", FT_UINT32, BASE_HEX,
12721 			NULL, 0, NULL, HFILL }},
12722 
12723 		{ &hf_nfs4_open_rflags_confirm, {
12724 			"confirm", "nfs.open_rflags.confirm",
12725 			FT_BOOLEAN, 32,
12726 			NULL, OPEN4_RESULT_CONFIRM, NULL, HFILL }},
12727 
12728 		{ &hf_nfs4_open_rflags_locktype_posix, {
12729 			"locktype posix", "nfs.open_rflags.locktype_posix",
12730 			FT_BOOLEAN, 32,
12731 			NULL, OPEN4_RESULT_LOCKTYPE_POSIX, NULL, HFILL }},
12732 
12733 		{ &hf_nfs4_open_rflags_preserve_unlinked, {
12734 			"preserve unlinked", "nfs.open_rflags.preserve_unlinked",
12735 			FT_BOOLEAN, 32,
12736 			NULL, OPEN4_RESULT_PRESERVE_UNLINKED, NULL, HFILL }},
12737 
12738 		{ &hf_nfs4_open_rflags_may_notify_lock, {
12739 			"may notify lock", "nfs.open_rflags.may_notify_lock",
12740 			FT_BOOLEAN, 32,
12741 			NULL, OPEN4_RESULT_MAY_NOTIFY_LOCK, NULL, HFILL }},
12742 
12743 		{ &hf_nfs4_reclaim, {
12744 			"reclaim", "nfs.reclaim4", FT_BOOLEAN, BASE_NONE,
12745 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12746 
12747 		{ &hf_nfs4_length, {
12748 			"length", "nfs.length4", FT_UINT64, BASE_DEC,
12749 			NULL, 0, NULL, HFILL }},
12750 
12751 		{ &hf_nfs4_changeid, {
12752 			"changeid", "nfs.changeid4", FT_UINT64, BASE_DEC,
12753 			NULL, 0, NULL, HFILL }},
12754 
12755 		{ &hf_nfs4_changeid_before, {
12756 			"changeid (before)", "nfs.changeid4.before", FT_UINT64, BASE_DEC,
12757 			NULL, 0, NULL, HFILL }},
12758 
12759 		{ &hf_nfs4_changeid_after, {
12760 			"changeid (after)", "nfs.changeid4.after", FT_UINT64, BASE_DEC,
12761 			NULL, 0, NULL, HFILL }},
12762 
12763 		{ &hf_nfs4_time_seconds, {
12764 			"seconds", "nfs.nfstime4.seconds", FT_UINT64, BASE_DEC,
12765 			NULL, 0, NULL, HFILL }},
12766 
12767 		{ &hf_nfs4_time_nseconds, {
12768 			"nseconds", "nfs.nfstime4.nseconds", FT_UINT32, BASE_DEC,
12769 			NULL, 0, NULL, HFILL }},
12770 
12771 		{ &hf_nfs4_fsid_major, {
12772 			"fsid4.major", "nfs.fsid4.major", FT_UINT64, BASE_DEC,
12773 			NULL, 0, NULL, HFILL }},
12774 
12775 		{ &hf_nfs4_fsid_minor, {
12776 			"fsid4.minor", "nfs.fsid4.minor", FT_UINT64, BASE_DEC,
12777 			NULL, 0, NULL, HFILL }},
12778 
12779 		{ &hf_nfs4_acetype, {
12780 			"acetype", "nfs.acetype4", FT_UINT32, BASE_DEC,
12781 			VALS(names_acetype4), 0, NULL, HFILL }},
12782 
12783 		{ &hf_nfs4_aceflags, {
12784 			"ACE flags", "nfs.aceflags4", FT_UINT32, BASE_HEX,
12785 			NULL, 0, NULL, HFILL }},
12786 
12787 		{ &hf_nfs4_aceflag_file_inherit, {
12788 			"File_Inherit", "nfs.aceflag4.file_inherit", FT_BOOLEAN, 32,
12789 			TFS(&tfs_yes_no), ACE4_FLAG_FILE_INHERIT, NULL, HFILL }},
12790 
12791 		{ &hf_nfs4_aceflag_dir_inherit, {
12792 			"Directory_Inherit", "nfs.aceflag4.dir_inherit", FT_BOOLEAN, 32,
12793 			TFS(&tfs_yes_no), ACE4_FLAG_DIRECTORY_INHERIT, NULL, HFILL }},
12794 
12795 		{ &hf_nfs4_aceflag_no_prop_inherit, {
12796 			"No_Propagate_Inherit", "nfs.aceflag4.no_prop_inherit", FT_BOOLEAN, 32,
12797 			TFS(&tfs_yes_no), ACE4_FLAG_NO_PROPAGATE_INHERIT, NULL, HFILL }},
12798 
12799 		{ &hf_nfs4_aceflag_inherit_only, {
12800 			"Inherit_Only", "nfs.aceflag4.inherit_only", FT_BOOLEAN, 32,
12801 			TFS(&tfs_yes_no), ACE4_FLAG_INHERIT_ONLY, NULL, HFILL }},
12802 
12803 		{ &hf_nfs4_aceflag_successful_access, {
12804 			"Successful_Access", "nfs.aceflag4.successful_access", FT_BOOLEAN, 32,
12805 			TFS(&tfs_yes_no), ACE4_FLAG_SUCCESSFUL_ACCESS, NULL, HFILL }},
12806 
12807 		{ &hf_nfs4_aceflag_failed_access, {
12808 			"Failed_access", "nfs.aceflag4.failed_access", FT_BOOLEAN, 32,
12809 			TFS(&tfs_yes_no), ACE4_FLAG_FAILED_ACCESS, NULL, HFILL }},
12810 
12811 		{ &hf_nfs4_aceflag_id_group, {
12812 			"Identifier_Group", "nfs.aceflag4.id_group", FT_BOOLEAN, 32,
12813 			TFS(&tfs_yes_no), ACE4_FLAG_IDENTIFIER_GROUP, NULL, HFILL }},
12814 
12815 		{ &hf_nfs4_aceflag_inherited_ace, {
12816 			"Inherited_ACE", "nfs.aceflag4.inherited_ace", FT_BOOLEAN, 32,
12817 			TFS(&tfs_yes_no), ACE4_FLAG_INHERITED_ACE, NULL, HFILL }},
12818 
12819 		{ &hf_nfs4_acemask, {
12820 			"ACE mask", "nfs.acemask4", FT_UINT32, BASE_HEX,
12821 			NULL, 0, NULL, HFILL }},
12822 
12823 		{ &hf_nfs4_ace_permission, {
12824 			"perm", "nfs.ace_perm4", FT_UINT32, BASE_HEX,
12825 			NULL, 0, NULL, HFILL }},
12826 
12827 		{ &hf_nfs4_fattr_size, {
12828 			"size", "nfs.fattr4.size", FT_UINT64, BASE_DEC,
12829 			NULL, 0, NULL, HFILL }},
12830 
12831 		{ &hf_nfs4_fattr_lease_time, {
12832 			"lease_time", "nfs.fattr4.lease_time", FT_UINT32, BASE_DEC,
12833 			NULL, 0, "Duration of the lease at server in seconds", HFILL }},
12834 
12835 		{ &hf_nfs4_fattr_aclsupport, {
12836 			"aclsupport", "nfs.fattr4.aclsupport", FT_UINT32, BASE_DEC,
12837 			NULL, 0, NULL, HFILL }},
12838 
12839 		{ &hf_nfs4_aclsupport_allow_acl, {
12840 			"ALLOW", "nfs.fattr4.aclsupport.allow_acl", FT_BOOLEAN, 32,
12841 			NULL, ACL4_SUPPORT_ALLOW_ACL, NULL, HFILL }},
12842 
12843 		{ &hf_nfs4_aclsupport_deny_acl, {
12844 			"DENY", "nfs.fattr4.aclsupport.deny_acl", FT_BOOLEAN, 32,
12845 			NULL, ACL4_SUPPORT_DENY_ACL, NULL, HFILL }},
12846 
12847 		{ &hf_nfs4_aclsupport_audit_acl, {
12848 			"AUDIT", "nfs.fattr4.aclsupport.audit_acl", FT_BOOLEAN, 32,
12849 			NULL, ACL4_SUPPORT_AUDIT_ACL, NULL, HFILL }},
12850 
12851 		{ &hf_nfs4_aclsupport_alarm_acl, {
12852 			"ALARM", "nfs.fattr4.aclsupport.alarm_acl", FT_BOOLEAN, 32,
12853 			NULL, ACL4_SUPPORT_ALARM_ACL, NULL, HFILL }},
12854 
12855 		{ &hf_nfs4_fattr_fileid, {
12856 			"fileid", "nfs.fattr4.fileid", FT_UINT64, BASE_DEC,
12857 			NULL, 0, NULL, HFILL }},
12858 
12859 		{ &hf_nfs4_fattr_files_avail, {
12860 			"files_avail", "nfs.fattr4.files_avail", FT_UINT64, BASE_DEC,
12861 			NULL, 0, NULL, HFILL }},
12862 
12863 		{ &hf_nfs4_fattr_files_free, {
12864 			"files_free", "nfs.fattr4.files_free", FT_UINT64, BASE_DEC,
12865 			NULL, 0, NULL, HFILL }},
12866 
12867 		{ &hf_nfs4_fattr_files_total, {
12868 			"files_total", "nfs.fattr4.files_total", FT_UINT64, BASE_DEC,
12869 			NULL, 0, NULL, HFILL }},
12870 
12871 		{ &hf_nfs4_fattr_maxfilesize, {
12872 			"maxfilesize", "nfs.fattr4.maxfilesize", FT_UINT64, BASE_DEC,
12873 			NULL, 0, NULL, HFILL }},
12874 
12875 		{ &hf_nfs4_fattr_maxlink, {
12876 			"maxlink", "nfs.fattr4.maxlink", FT_UINT32, BASE_DEC,
12877 			NULL, 0, NULL, HFILL }},
12878 
12879 		{ &hf_nfs4_fattr_maxname, {
12880 			"maxname", "nfs.fattr4.maxname", FT_UINT32, BASE_DEC,
12881 			NULL, 0, NULL, HFILL }},
12882 
12883 		{ &hf_nfs4_fattr_numlinks, {
12884 			"numlinks", "nfs.fattr4.numlinks", FT_UINT32, BASE_DEC,
12885 			NULL, 0, NULL, HFILL }},
12886 
12887 		{ &hf_nfs4_delegate_type, {
12888 			"delegate_type", "nfs.delegate_type", FT_UINT32, BASE_DEC,
12889 			NULL, 0, NULL, HFILL }},
12890 
12891 		{ &hf_nfs4_secinfo_flavor, {
12892 			"flavor", "nfs.secinfo.flavor", FT_UINT32, BASE_DEC,
12893 			VALS(rpc_auth_flavor), 0, NULL, HFILL }},
12894 
12895 		{ &hf_nfs4_num_blocks, {
12896 			"num_blocks", "nfs.num_blocks", FT_UINT32, BASE_DEC,
12897 			NULL, 0, NULL, HFILL }},
12898 
12899 		{ &hf_nfs4_bytes_per_block, {
12900 			"bytes_per_block", "nfs.bytes_per_block", FT_UINT32, BASE_DEC,
12901 			NULL, 0, NULL, HFILL }},
12902 
12903 		{ &hf_nfs4_eof, {
12904 			"eof", "nfs.eof", FT_UINT32, BASE_DEC,
12905 			NULL, 0, NULL, HFILL }},
12906 
12907 		{ &hf_nfs4_fattr_maxread, {
12908 			"maxread", "nfs.fattr4.maxread", FT_UINT64, BASE_DEC,
12909 			NULL, 0, NULL, HFILL }},
12910 
12911 		{ &hf_nfs4_fattr_maxwrite, {
12912 			"maxwrite", "nfs.fattr4.maxwrite", FT_UINT64, BASE_DEC,
12913 			NULL, 0, NULL, HFILL }},
12914 
12915 		{ &hf_nfs4_fattr_quota_hard, {
12916 			"quota_hard", "nfs.fattr4.quota_hard", FT_UINT64, BASE_DEC,
12917 			NULL, 0, NULL, HFILL }},
12918 
12919 		{ &hf_nfs4_fattr_quota_soft, {
12920 			"quota_soft", "nfs.fattr4.quota_soft", FT_UINT64, BASE_DEC,
12921 			NULL, 0, NULL, HFILL }},
12922 
12923 		{ &hf_nfs4_fattr_quota_used, {
12924 			"quota_used", "nfs.fattr4.quota_used", FT_UINT64, BASE_DEC,
12925 			NULL, 0, NULL, HFILL }},
12926 
12927 		{ &hf_nfs4_fattr_space_avail, {
12928 			"space_avail", "nfs.fattr4.space_avail", FT_UINT64, BASE_DEC,
12929 			NULL, 0, NULL, HFILL }},
12930 
12931 		{ &hf_nfs4_fattr_space_free, {
12932 			"space_free", "nfs.fattr4.space_free", FT_UINT64, BASE_DEC,
12933 			NULL, 0, NULL, HFILL }},
12934 
12935 		{ &hf_nfs4_fattr_space_total, {
12936 			"space_total", "nfs.fattr4.space_total", FT_UINT64, BASE_DEC,
12937 			NULL, 0, NULL, HFILL }},
12938 
12939 		{ &hf_nfs4_fattr_space_used, {
12940 			"space_used", "nfs.fattr4.space_used", FT_UINT64, BASE_DEC,
12941 			NULL, 0, NULL, HFILL }},
12942 
12943 		{ &hf_nfs4_fattr_mounted_on_fileid, {
12944 			"fileid", "nfs.fattr4.mounted_on_fileid", FT_UINT64, BASE_HEX,
12945 			NULL, 0, NULL, HFILL }},
12946 
12947 		{ &hf_nfs4_fattr_layout_blksize, {
12948 			"blksize", "nfs.fattr4.layout_blksize", FT_UINT32, BASE_DEC,
12949 			NULL, 0, NULL, HFILL }},
12950 
12951 		{ &hf_nfs4_mdsthreshold_item, {
12952 			"threshold_item4", "nfs.fattr4.threshold_item", FT_NONE, BASE_NONE,
12953 			NULL, 0, NULL, HFILL }},
12954 
12955 		{ &hf_nfs4_mdsthreshold_hint_mask, {
12956 			"hint mask", "nfs.fattr4.threshold_item.hint_mask", FT_UINT32, BASE_HEX,
12957 			NULL, 0, "MDS threshold hint mask", HFILL }},
12958 
12959 		{ &hf_nfs4_mdsthreshold_hint_count, {
12960 			"hint", "nfs.fattr4.threshold_item.hint_count", FT_UINT32, BASE_DEC,
12961 			NULL, 0, "MDS threshold hint count", HFILL }},
12962 
12963 		{ &hf_nfs4_mdsthreshold_mask_count, {
12964 			"number of masks", "nfs.fattr4.threshold_item.mask_count", FT_UINT32, BASE_DEC,
12965 			NULL, 0, "MDS threshold hint mask count", HFILL }},
12966 
12967 		{ &hf_nfs4_mdsthreshold_hint_file, {
12968 			"hint", "nfs.fattr4.threshold_item.hint", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
12969 			&th4_names_ext_file, 0, "MDS threshold hint", HFILL }},
12970 
12971 		{ &hf_nfs4_fattr_security_label_lfs, {
12972 			"label_format", "nfs.fattr4.security_label.lfs", FT_UINT32, BASE_DEC,
12973 			NULL, 0, NULL, HFILL }},
12974 
12975 		{ &hf_nfs4_fattr_umask_mask, {
12976 			"umask", "nfs.fattr4.umask", FT_UINT32, BASE_OCT,
12977 			NULL, 0, NULL, HFILL }},
12978 
12979 		{ &hf_nfs4_fattr_xattr_support, {
12980 			"fattr4_xattr_support", "nfs.fattr4_xattr_support", FT_BOOLEAN, BASE_NONE,
12981 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12982 
12983 		{ &hf_nfs4_fattr_offline, {
12984 			"fattr4_offline", "nfs.fattr4_offline", FT_BOOLEAN, BASE_NONE,
12985 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
12986 
12987 		{ &hf_nfs4_fattr_security_label_pi, {
12988 			"policy_id", "nfs.fattr4.security_label.pi", FT_UINT32, BASE_DEC,
12989 			NULL, 0, NULL, HFILL }},
12990 
12991 		{ &hf_nfs4_fattr_security_label_context, {
12992 			"context", "nfs.fattr4.security_label.context", FT_STRING, BASE_NONE,
12993 			NULL, 0, NULL, HFILL }},
12994 
12995 		{ &hf_nfs4_fattr_fs_charset_cap, {
12996 			"fs_charset_cap", "nfs.fattr4.fs_charset_cap", FT_UINT32, BASE_HEX,
12997 			NULL, 0, NULL, HFILL }},
12998 
12999 		{ &hf_nfs4_fs_charset_cap_nonutf8, {
13000 			"CONTAINS_NON_UTF8", "nfs.fattr4.fs_charset_cap.nonutf8", FT_BOOLEAN, 32,
13001 			NULL, FSCHARSET_CAP4_CONTAINS_NON_UTF8, NULL, HFILL }},
13002 
13003 		{ &hf_nfs4_fs_charset_cap_utf8, {
13004 			"ALLOWS_ONLY_UTF8", "nfs.fattr4.fs_charset_cap.utf8", FT_BOOLEAN, 32,
13005 			NULL, FSCHARSET_CAP4_ALLOWS_ONLY_UTF8, NULL, HFILL }},
13006 
13007 		{ &hf_nfs4_verifier, {
13008 			"verifier", "nfs.verifier4", FT_UINT64, BASE_HEX,
13009 			NULL, 0, NULL, HFILL }},
13010 
13011 		{ &hf_nfs4_value_follows, {
13012 			"Value Follows", "nfs.value_follows", FT_BOOLEAN, BASE_NONE,
13013 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13014 
13015 		{ &hf_nfs4_cookie, {
13016 			"cookie", "nfs.cookie4", FT_UINT64, BASE_DEC,
13017 			NULL, 0, NULL, HFILL }},
13018 
13019 		{ &hf_nfs4_cookie_verf, {
13020 			"cookie_verf", "nfs.cookie_verf4", FT_UINT64, BASE_DEC,
13021 			NULL, 0, NULL, HFILL }},
13022 
13023 #if 0
13024 		{ &hf_nfs4_cb_location, {
13025 			"cb_location", "nfs.cb_location", FT_UINT32, BASE_DEC,
13026 			NULL, 0, NULL, HFILL }},
13027 #endif
13028 
13029 		{ &hf_nfs4_cb_program, {
13030 			"cb_program", "nfs.cb_program", FT_UINT32, BASE_HEX,
13031 			NULL, 0, NULL, HFILL }},
13032 
13033 		{ &hf_nfs4_recall4, {
13034 			"recall", "nfs.recall4", FT_BOOLEAN, BASE_NONE,
13035 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13036 
13037 		{ &hf_nfs4_filesize, {
13038 			"filesize", "nfs.filesize", FT_UINT64, BASE_DEC,
13039 			NULL, 0, NULL, HFILL }},
13040 
13041 		{ &hf_nfs4_count, {
13042 			"count", "nfs.count4", FT_UINT32, BASE_DEC,
13043 			NULL, 0, NULL, HFILL }},
13044 
13045 		{ &hf_nfs4_count_dircount, {
13046 			"dircount", "nfs.dircount", FT_UINT32, BASE_DEC,
13047 			NULL, 0, NULL, HFILL }},
13048 
13049 		{ &hf_nfs4_count_maxcount, {
13050 			"maxcount", "nfs.maxcount", FT_UINT32, BASE_DEC,
13051 			NULL, 0, NULL, HFILL }},
13052 
13053 		{ &hf_nfs4_minorversion, {
13054 			"minorversion", "nfs.minorversion", FT_UINT32, BASE_DEC,
13055 			NULL, 0, NULL, HFILL }},
13056 
13057 		{ &hf_nfs_atime, {
13058 			"atime", "nfs.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
13059 			NULL, 0, "Access Time", HFILL }},
13060 
13061 		{ &hf_nfs_atime_sec, {
13062 			"seconds", "nfs.atime.sec", FT_UINT32, BASE_DEC,
13063 			NULL, 0, "Access Time, Seconds", HFILL }},
13064 
13065 		{ &hf_nfs_atime_nsec, {
13066 			"nano seconds", "nfs.atime.nsec", FT_UINT32, BASE_DEC,
13067 			NULL, 0, "Access Time, Nano-seconds", HFILL }},
13068 
13069 		{ &hf_nfs_atime_usec, {
13070 			"micro seconds", "nfs.atime.usec", FT_UINT32, BASE_DEC,
13071 			NULL, 0, "Access Time, Micro-seconds", HFILL }},
13072 
13073 		{ &hf_nfs_mtime, {
13074 			"mtime", "nfs.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
13075 			NULL, 0, "Modify Time", HFILL }},
13076 
13077 		{ &hf_nfs_mtime_sec, {
13078 			"seconds", "nfs.mtime.sec", FT_UINT32, BASE_DEC,
13079 			NULL, 0, "Modify Seconds", HFILL }},
13080 
13081 		{ &hf_nfs_mtime_nsec, {
13082 			"nano seconds", "nfs.mtime.nsec", FT_UINT32, BASE_DEC,
13083 			NULL, 0, "Modify Time, Nano-seconds", HFILL }},
13084 
13085 		{ &hf_nfs_mtime_usec, {
13086 			"micro seconds", "nfs.mtime.usec", FT_UINT32, BASE_DEC,
13087 			NULL, 0, "Modify Time, Micro-seconds", HFILL }},
13088 
13089 		{ &hf_nfs_ctime, {
13090 			"ctime", "nfs.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
13091 			NULL, 0, "Creation Time", HFILL }},
13092 
13093 		{ &hf_nfs_ctime_sec, {
13094 			"seconds", "nfs.ctime.sec", FT_UINT32, BASE_DEC,
13095 			NULL, 0, "Creation Time, Seconds", HFILL }},
13096 
13097 		{ &hf_nfs_ctime_nsec, {
13098 			"nano seconds", "nfs.ctime.nsec", FT_UINT32, BASE_DEC,
13099 			NULL, 0, "Creation Time, Nano-seconds", HFILL }},
13100 
13101 		{ &hf_nfs_ctime_usec, {
13102 			"micro seconds", "nfs.ctime.usec", FT_UINT32, BASE_DEC,
13103 			NULL, 0, "Creation Time, Micro-seconds", HFILL }},
13104 
13105 		{ &hf_nfs_dtime, {
13106 			"time delta", "nfs.dtime", FT_RELATIVE_TIME, BASE_NONE,
13107 			NULL, 0, NULL, HFILL }},
13108 
13109 		{ &hf_nfs_dtime_sec, {
13110 			"seconds", "nfs.dtime.sec", FT_UINT32, BASE_DEC,
13111 			NULL, 0, "Time Delta, Seconds", HFILL }},
13112 
13113 		{ &hf_nfs_dtime_nsec, {
13114 			"nano seconds", "nfs.dtime.nsec", FT_UINT32, BASE_DEC,
13115 			NULL, 0, "Time Delta, Nano-seconds", HFILL }},
13116 
13117 		{ &hf_nfs4_open_owner, {
13118 			"owner", "nfs.open_owner4", FT_BYTES, BASE_NONE,
13119 			NULL, 0, NULL, HFILL }},
13120 
13121 		{ &hf_nfs4_lock_owner, {
13122 			"owner", "nfs.lock_owner4", FT_BYTES, BASE_NONE,
13123 			NULL, 0, NULL, HFILL }},
13124 
13125 		{ &hf_nfs4_createmode, {
13126 			"Create Mode", "nfs.createmode4", FT_UINT32, BASE_DEC,
13127 			VALS(names_createmode4), 0, NULL, HFILL }},
13128 
13129 		{ &hf_nfs4_secinfo_rpcsec_gss_info_service, {
13130 			"service", "nfs.secinfo.rpcsec_gss_info.service", FT_UINT32, BASE_DEC,
13131 			VALS(rpc_authgss_svc), 0, NULL, HFILL }},
13132 
13133 		{ &hf_nfs4_attr_dir_create, {
13134 			"attribute dir create", "nfs.openattr4.createdir", FT_BOOLEAN, BASE_NONE,
13135 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13136 
13137 		{ &hf_nfs4_new_lock_owner, {
13138 			"new lock owner?", "nfs.lock.locker.new_lock_owner", FT_BOOLEAN, BASE_NONE,
13139 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13140 
13141 		{ &hf_nfs4_lock_reclaim, {
13142 			"reclaim?", "nfs.lock.reclaim", FT_BOOLEAN, BASE_NONE,
13143 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13144 
13145 		{ &hf_nfs4_sec_oid, {
13146 			"oid", "nfs.secinfo.flavor_info.rpcsec_gss_info.oid", FT_BYTES, BASE_NONE,
13147 			NULL, 0, NULL, HFILL }},
13148 
13149 		{ &hf_nfs4_qop, {
13150 			"qop", "nfs.secinfo.flavor_info.rpcsec_gss_info.qop", FT_UINT32, BASE_DEC,
13151 			NULL, 0, NULL, HFILL }},
13152 
13153 		{ &hf_nfs4_client_id, {
13154 			"id", "nfs.nfs_client_id4.id", FT_BYTES, BASE_NONE,
13155 			NULL, 0, NULL, HFILL }},
13156 
13157 		{ &hf_nfs4_aclflags, {
13158 			"ACL flags", "nfs.acl.flags", FT_UINT32, BASE_DEC,
13159 			NULL, 0, NULL, HFILL }},
13160 
13161 		{ &hf_nfs4_aclflag_auto_inherit, {
13162 			"AUTO_INHERIT", "nfs.acl.flags.auto_inherit", FT_BOOLEAN, 32,
13163 			NULL, ACL4_AUTO_INHERIT, NULL, HFILL }},
13164 
13165 		{ &hf_nfs4_aclflag_protected, {
13166 			"PROTECTED", "nfs.acl.flags.protected", FT_BOOLEAN, 32,
13167 			NULL, ACL4_PROTECTED, NULL, HFILL }},
13168 
13169 		{ &hf_nfs4_aclflag_defaulted, {
13170 			"DEFAULTED", "nfs.acl.flags.defaulted", FT_BOOLEAN, 32,
13171 			NULL, ACL4_DEFAULTED, NULL, HFILL }},
13172 
13173 		{ &hf_nfs4_num_aces, {
13174 			"ACE count", "nfs.num_aces", FT_UINT32, BASE_DEC,
13175 			NULL, 0, "Number of ACEs", HFILL }},
13176 
13177 		{ &hf_nfs4_callback_ident, {
13178 			"callback_ident", "nfs.callback.ident", FT_UINT32, BASE_HEX,
13179 			NULL, 0, "Callback Identifier", HFILL }},
13180 
13181 		{ &hf_nfs4_gsshandle, {
13182 			"gsshandle4", "nfs.gsshandle4", FT_BYTES, BASE_NONE,
13183 			NULL, 0, NULL, HFILL }},
13184 
13185 		{ &hf_nfs4_r_netid, {
13186 			"r_netid", "nfs.r_netid", FT_STRING, BASE_NONE,
13187 			NULL, 0, NULL, HFILL }},
13188 
13189 		{ &hf_nfs4_r_addr, {
13190 			"r_addr", "nfs.r_addr", FT_STRING, BASE_NONE,
13191 			NULL, 0, NULL, HFILL }},
13192 
13193 		{ &hf_nfs_fh_fhandle_data, {
13194 			"FileHandle", "nfs.fhandle", FT_BYTES, BASE_NONE,
13195 			NULL, 0, "Opaque nfs filehandle", HFILL }},
13196 
13197 		{ &hf_nfs4_secinfo_arr, {
13198 			"Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
13199 			NULL, 0, NULL, HFILL }},
13200 
13201 		{ &hf_nfs3_gxfh_utlfield, {
13202 			"utility", "nfs.gxfh3.utility", FT_UINT8, BASE_HEX,
13203 			NULL, 0, NULL, HFILL }},
13204 
13205 		{ &hf_nfs3_gxfh_utlfield_tree, {
13206 			"tree R/W", "nfs.gxfh3.utlfield.tree", FT_BOOLEAN, 8,
13207 			TFS(&tfs_read_write), NFS3GX_FH_TREE_MASK, NULL, HFILL }},
13208 
13209 		{ &hf_nfs3_gxfh_utlfield_jun, {
13210 			"broken junction", "nfs.gxfh3.utlfield.junction", FT_BOOLEAN, 8,
13211 			TFS(&tfs_yes_no), NFS3GX_FH_JUN_MASK, NULL, HFILL }},
13212 
13213 		{ &hf_nfs3_gxfh_utlfield_ver, {
13214 			"file handle version", "nfs.gxfh3.utlfield.version", FT_UINT8, BASE_HEX,
13215 			NULL, NFS3GX_FH_VER_MASK, NULL, HFILL }},
13216 
13217 		{ &hf_nfs3_gxfh_volcnt, {
13218 			"volume count", "nfs.gxfh3.volcnt", FT_UINT8, BASE_HEX_DEC,
13219 			NULL, 0, NULL, HFILL }},
13220 
13221 		{ &hf_nfs3_gxfh_epoch, {
13222 			"epoch", "nfs.gxfh3.epoch", FT_UINT16, BASE_HEX_DEC,
13223 			NULL, 0, NULL, HFILL }},
13224 
13225 		{ &hf_nfs3_gxfh_ldsid, {
13226 			"local dsid", "nfs.gxfh3.ldsid", FT_UINT32, BASE_HEX_DEC,
13227 			NULL, 0, NULL, HFILL }},
13228 
13229 		{ &hf_nfs3_gxfh_cid, {
13230 			"cluster id", "nfs.gxfh3.cid", FT_UINT16, BASE_HEX_DEC,
13231 			NULL, 0, NULL, HFILL }},
13232 
13233 		{ &hf_nfs3_gxfh_resv, {
13234 			"reserved", "nfs.gxfh3.reserved", FT_UINT16, BASE_HEX_DEC,
13235 			NULL, 0, NULL, HFILL }},
13236 
13237 		{ &hf_nfs3_gxfh_sfhflags, {
13238 			"flags", "nfs.gxfh3.sfhflags", FT_UINT8, BASE_HEX,
13239 			NULL, 0, NULL, HFILL }},
13240 
13241 		{ &hf_nfs3_gxfh_sfhflags_resv1, {
13242 			"reserved", "nfs.gxfh3.sfhflags.reserve1", FT_UINT8, BASE_HEX,
13243 			NULL, SPINNP_FH_FLAG_RESV1, NULL, HFILL }},
13244 
13245 		{ &hf_nfs3_gxfh_sfhflags_resv2, {
13246 			"reserved", "nfs.gxfh3.sfhflags.reserv2", FT_UINT8, BASE_HEX,
13247 			NULL, SPINNP_FH_FLAG_RESV2, NULL, HFILL }},
13248 
13249 		{ &hf_nfs3_gxfh_sfhflags_ontap7G, {
13250 			"ontap-7g", "nfs.gxfh3.sfhflags.ontap7g", FT_UINT8, BASE_HEX,
13251 			NULL, SPINNP_FH_FLAG_ONTAP_MASK, NULL, HFILL }},
13252 
13253 		{ &hf_nfs3_gxfh_sfhflags_ontapGX, {
13254 			"ontap-gx", "nfs.gxfh3.sfhflags.ontapgx", FT_UINT8, BASE_HEX,
13255 			NULL, SPINNP_FH_FLAG_ONTAP_MASK, NULL, HFILL }},
13256 
13257 		{ &hf_nfs3_gxfh_sfhflags_striped, {
13258 			"striped", "nfs.gxfh3.sfhflags.striped", FT_BOOLEAN, 8,
13259 			TFS(&tfs_set_notset), SPINNP_FH_FLAG_STRIPED_MASK, NULL, HFILL }},
13260 
13261 		{ &hf_nfs3_gxfh_sfhflags_empty, {
13262 			"empty", "nfs.gxfh3.sfhflags.empty", FT_BOOLEAN, 8,
13263 			TFS(&tfs_set_notset), SPINNP_FH_FLAG_EMPTY_MASK, NULL, HFILL }},
13264 
13265 		{ &hf_nfs3_gxfh_sfhflags_snapdirent, {
13266 			"snap dir ent", "nfs.gxfh3.sfhflags.snapdirent", FT_BOOLEAN, 8,
13267 			TFS(&tfs_set_notset), SPINNP_FH_FLAG_SNAPDIR_ENT_MASK, NULL, HFILL }},
13268 
13269 		{ &hf_nfs3_gxfh_sfhflags_snapdir, {
13270 			"snap dir", "nfs.gxfh3.sfhflags.snapdir", FT_BOOLEAN, 8,
13271 			TFS(&tfs_set_notset), SPINNP_FH_FLAG_SNAPDIR_MASK, NULL, HFILL }},
13272 
13273 		{ &hf_nfs3_gxfh_sfhflags_streamdir, {
13274 			"stream dir", "nfs.gxfh3.sfhflags.streamdir", FT_BOOLEAN, 8,
13275 			TFS(&tfs_set_notset), SPINNP_FH_FLAG_STREAMDIR_MASK, NULL, HFILL }},
13276 
13277 		{ &hf_nfs3_gxfh_spinfid, {
13278 			"spin file id", "nfs.gxfh3.spinfid", FT_UINT32, BASE_HEX_DEC,
13279 			NULL, 0, NULL, HFILL }},
13280 
13281 		{ &hf_nfs3_gxfh_spinfuid, {
13282 			"spin file unique id", "nfs.gxfh3.spinfuid", FT_UINT32, BASE_HEX_DEC,
13283 			NULL, 0, NULL, HFILL }},
13284 
13285 		{ &hf_nfs3_gxfh_exportptid, {
13286 			"export point id", "nfs.gxfh3.exportptid", FT_UINT32, BASE_HEX_DEC,
13287 			NULL, 0, NULL, HFILL }},
13288 
13289 		{ &hf_nfs3_gxfh_exportptuid, {
13290 			"export point unique id", "nfs.gxfh3.exportptuid", FT_UINT32, BASE_HEX_DEC,
13291 			NULL, 0, NULL, HFILL }},
13292 
13293 		{ &hf_nfs3_verifier, {
13294 			"Verifier", "nfs.verifier", FT_BYTES, BASE_NONE,
13295 			NULL, 0, NULL, HFILL }},
13296 
13297 		{ &hf_nfs3_specdata1, {
13298 			"specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
13299 			NULL, 0, NULL, HFILL }},
13300 
13301 		{ &hf_nfs3_specdata2, {
13302 			"specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
13303 			NULL, 0, NULL, HFILL }},
13304 
13305 		{ &hf_nfs3_attributes_follow, {
13306 			"attributes_follow", "nfs.attributes_follow", FT_UINT32, BASE_DEC,
13307 			VALS(value_follows), 0, NULL, HFILL }},
13308 
13309 		{ &hf_nfs3_handle_follow, {
13310 			"handle_follow", "nfs.handle_follow", FT_UINT32, BASE_DEC,
13311 			VALS(value_follows), 0, NULL, HFILL }},
13312 
13313 		{ &hf_nfs3_sattrguard3, {
13314 			"check", "nfs.sattrguard3", FT_UINT32, BASE_DEC,
13315 			VALS(value_follows), 0, NULL, HFILL }},
13316 
13317 		{ &hf_nfs4_length_minlength, {
13318 			"min length", "nfs.minlength4", FT_UINT64, BASE_DEC,
13319 			NULL, 0, NULL, HFILL }},
13320 
13321 		{ &hf_nfs4_layout_type, {
13322 			"layout type", "nfs.layouttype", FT_UINT32, BASE_DEC,
13323 			VALS(layouttype_names), 0, NULL, HFILL }},
13324 
13325 		{ &hf_nfs4_layout_return_type, {
13326 			"return type", "nfs.returntype", FT_UINT32, BASE_DEC,
13327 			VALS(layoutreturn_names), 0, NULL, HFILL }},
13328 
13329 		{ &hf_nfs4_lrf_body_content, {
13330 			"lrf_body_content", "nfs.lrf_body_content", FT_BYTES, BASE_NONE,
13331 			NULL, 0, NULL, HFILL }},
13332 
13333 		{ &hf_nfs4_iomode, {
13334 			"IO mode", "nfs.iomode", FT_UINT32, BASE_DEC,
13335 			VALS(iomode_names), 0, NULL, HFILL }},
13336 
13337 #if 0
13338 		{ &hf_nfs4_stripetype, {
13339 			"stripe type", "nfs.stripetype", FT_UINT32, BASE_DEC,
13340 			VALS(stripetype_names), 0, NULL, HFILL }},
13341 #endif
13342 
13343 		{ &hf_nfs4_stripeunit, {
13344 			"stripe unit", "nfs.stripeunit", FT_UINT64, BASE_DEC,
13345 			NULL, 0, NULL, HFILL }},
13346 
13347 #if 0
13348 		{ &hf_nfs4_util, {
13349 			"util", "nfs.util", FT_UINT32, BASE_DEC,
13350 			NULL, 0, NULL, HFILL }},
13351 #endif
13352 
13353 #if 0
13354 		{ &hf_nfs4_first_stripe_idx, {
13355 			"first stripe index", "nfs.stripeindex", FT_UINT32, BASE_DEC,
13356 			NULL, 0, NULL, HFILL }},
13357 #endif
13358 
13359 #if 0
13360 		{ &hf_nfs4_pattern_offset, {
13361 			"layout pattern offset", "nfs.patternoffset", FT_UINT64, BASE_DEC,
13362 			NULL, 0, NULL, HFILL }},
13363 #endif
13364 
13365 		{ &hf_nfs4_notification_mask, {
13366 			"notify_mask", "nfs.notify_mask", FT_UINT32, BASE_HEX,
13367 			NULL, 0, NULL, HFILL }},
13368 
13369 		{ &hf_nfs4_notification_type, {
13370 			"notify_type", "nfs.notify_type", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
13371 			&notify_deviceid_type4_ext, 0, NULL, HFILL }},
13372 
13373 		{ &hf_nfs4_newtime, {
13374 			"new time?", "nfs.newtime", FT_BOOLEAN, BASE_NONE,
13375 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13376 
13377 		{ &hf_nfs4_newoffset, {
13378 			"new offset?", "nfs.newoffset", FT_BOOLEAN, BASE_NONE,
13379 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13380 
13381 		{ &hf_nfs4_newsize, {
13382 			"new size?", "nfs.newsize", FT_BOOLEAN, BASE_NONE,
13383 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13384 
13385 		{ &hf_nfs4_layout_avail, {
13386 			"layout available?", "nfs.layoutavail", FT_BOOLEAN, BASE_NONE,
13387 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13388 
13389 #if 0
13390 		{ &hf_nfs4_mdscommit, {
13391 			"MDS commit?", "nfs.mdscommit", FT_BOOLEAN, BASE_NONE,
13392 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13393 #endif
13394 
13395 		{ &hf_nfs4_layoutupdate, {
13396 			"layout update", "nfs.layoutupdate", FT_BYTES, BASE_NONE,
13397 			NULL, 0, NULL, HFILL }},
13398 
13399 		{ &hf_nfs4_deviceid, {
13400 			"device ID", "nfs.deviceid", FT_BYTES, BASE_NONE,
13401 			NULL, 0, NULL, HFILL }},
13402 
13403 		{ &hf_nfs4_devicenum, {
13404 			"num devices", "nfs.devicenum4", FT_UINT32, BASE_DEC,
13405 			NULL, 0, NULL, HFILL }},
13406 
13407 		{ &hf_nfs4_deviceidx, {
13408 			"device index", "nfs.deviceidx", FT_UINT32, BASE_DEC,
13409 			NULL, 0, NULL, HFILL }},
13410 
13411 		{ &hf_nfs4_layout, {
13412 			"layout", "nfs.layout", FT_BYTES, BASE_NONE,
13413 			NULL, 0, NULL, HFILL }},
13414 
13415 #if 0
13416 		{ &hf_nfs4_layout_count, {
13417 			"layout", "nfs.layoutcount", FT_UINT32, BASE_DEC,
13418 			NULL, 0, "layout count", HFILL }},
13419 #endif
13420 
13421 
13422 #if 0
13423 		{ &hf_nfs4_stripedevs, {
13424 			"stripe devs", "nfs.stripedevs", FT_UINT32, BASE_DEC,
13425 			NULL, 0, NULL, HFILL }},
13426 #endif
13427 
13428 #if 0
13429 		{ &hf_nfs4_devaddr, {
13430 			"device addr", "nfs.devaddr", FT_BYTES, BASE_NONE,
13431 			NULL, 0, NULL, HFILL }},
13432 #endif
13433 
13434 		{ &hf_nfs4_devaddr_ssv_start, {
13435 			"slice start", "nfs.devaddr.ssv_start", FT_UINT32, BASE_DEC,
13436 			NULL, 0, NULL, HFILL }},
13437 
13438 		{ &hf_nfs4_devaddr_ssv_length, {
13439 			"slice length", "nfs.devaddr.ssv_length", FT_UINT32, BASE_DEC,
13440 			NULL, 0, NULL, HFILL }},
13441 
13442 		{ &hf_nfs4_devaddr_scsi_vol_type, {
13443 			"SCSI volume type", "nfs.devaddr.scsi_volume_type", FT_UINT32, BASE_DEC,
13444 			VALS(scsi_vol_type_names), 0, NULL, HFILL }},
13445 
13446 		{ &hf_nfs4_devaddr_scsi_vol_index, {
13447 			"volume index", "nfs.devaddr.scsi_volume_index", FT_UINT32, BASE_DEC,
13448 			NULL, 0, NULL, HFILL }},
13449 
13450 		{ &hf_nfs4_devaddr_scsi_vol_ref_index, {
13451 			"volume index ref", "nfs.devaddr.scsi_volume_ref_index", FT_UINT32, BASE_DEC,
13452 			NULL, 0, NULL, HFILL }},
13453 
13454 		{ &hf_nfs4_devaddr_ssv_stripe_unit, {
13455 			"stripe size", "nfs.devaddr.ssv_stripe_unit", FT_UINT32, BASE_DEC,
13456 			NULL, 0, NULL, HFILL }},
13457 
13458 		{ &hf_nfs4_devaddr_scsi_vpd_code_set, {
13459 			"VPD code set", "nfs.devaddr.scsi_vpd_code_set", FT_UINT32, BASE_DEC,
13460 			VALS(scsi_vpd_code_set_names), 0, NULL, HFILL }},
13461 
13462 		{ &hf_nfs4_devaddr_scsi_vpd_designator_type, {
13463 			"VPD designator type", "nfs.devaddr.scsi_vpd_designator_type", FT_UINT32, BASE_DEC,
13464 			VALS(scsi_vpd_designator_type_names), 0, NULL, HFILL }},
13465 
13466 		{ &hf_nfs4_devaddr_scsi_vpd_designator, {
13467 			"VPD designator", "nfs.devaddr.scsi_vpd_designator",
13468 			FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
13469 
13470 		{ &hf_nfs4_devaddr_scsi_private_key, {
13471 			"private key", "nfs.devaddr.scsi_private_key",
13472 			FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
13473 
13474 		{ &hf_nfs4_scsil_ext_file_offset, {
13475 			"file offset", "nfs.scsil_ext_file_offset", FT_UINT64, BASE_DEC,
13476 			NULL, 0, NULL, HFILL }},
13477 
13478 		{ &hf_nfs4_scsil_ext_length, {
13479 			"length", "nfs.scsil_ext_length", FT_UINT64, BASE_DEC,
13480 			NULL, 0, NULL, HFILL }},
13481 
13482 		{ &hf_nfs4_scsil_ext_vol_offset, {
13483 			"volume offset", "nfs.scsill_ext_vol_offset", FT_UINT64, BASE_DEC,
13484 			NULL, 0, NULL, HFILL }},
13485 
13486 		{ &hf_nfs4_scsil_ext_state, {
13487 			"extent state", "nfs.scsil_ext_state", FT_UINT32, BASE_DEC,
13488 			VALS(scsi_extent_state_names), 0, NULL, HFILL }},
13489 
13490 		{ &hf_nfs4_return_on_close, {
13491 			"return on close?", "nfs.retclose4", FT_BOOLEAN, BASE_NONE,
13492 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13493 
13494 		{ &hf_nfs4_nfl_mirrors, {
13495 			"Mirror", "nfs.nfl_mirrors", FT_UINT32, BASE_DEC,
13496 			NULL, 0, NULL, HFILL }},
13497 
13498 		{ &hf_nfs4_nfl_util, {
13499 			"nfl_util", "nfs.nfl_util", FT_UINT32, BASE_HEX,
13500 			NULL, 0, NULL, HFILL }},
13501 
13502 		{ &hf_nfs4_nfl_util_stripe_size, {
13503 			"stripe size", "nfs.nfl_util.stripe_size", FT_UINT32, BASE_DEC,
13504 			NULL, 0, NULL, HFILL }},
13505 
13506 		{ &hf_nfs4_nfl_util_commit_thru_mds, {
13507 			"commit thru mds", "nfs.nfl_util.commit_thru_mds", FT_UINT32, BASE_DEC,
13508 			NULL, 0, NULL, HFILL }},
13509 
13510 		{ &hf_nfs4_nfl_util_dense, {
13511 			"dense layout", "nfs.nfl_util.dense", FT_UINT32, BASE_DEC,
13512 			NULL, 0, NULL, HFILL }},
13513 
13514 		{ &hf_nfs4_nfl_fhs, {
13515 			"file handles", "nfs.nfl_fhs", FT_UINT32, BASE_HEX,
13516 			NULL, 0, NULL, HFILL }},
13517 
13518 		{ &hf_nfs4_mirror_eff, {
13519 			"mirror efficiency", "nfs.nff_mirror_eff", FT_UINT32, BASE_HEX,
13520 			NULL, 0, NULL, HFILL }},
13521 
13522 		{ &hf_nfs4_nfl_first_stripe_index, {
13523 			"first stripe to use index", "nfs.nfl_first_stripe_index", FT_UINT32, BASE_DEC,
13524 			NULL, 0, NULL, HFILL }},
13525 
13526 		{ &hf_nfs4_slotid, {
13527 			"slot id", "nfs.slotid", FT_UINT32, BASE_DEC,
13528 			NULL, 0, NULL, HFILL }},
13529 
13530 		{ &hf_nfs4_high_slotid, {
13531 			"high slot id", "nfs.high_slotid", FT_UINT32, BASE_DEC,
13532 			NULL, 0, NULL, HFILL }},
13533 		{ &hf_nfs4_target_high_slotid, {
13534 			"target high slot id", "nfs.target_high_slotid", FT_UINT32, BASE_DEC,
13535 			NULL, 0, NULL, HFILL }},
13536 
13537 		{ &hf_nfs4_serverscope4, {
13538 			"server scope", "nfs.scope", FT_BYTES, BASE_NONE,
13539 			NULL, 0, NULL, HFILL }},
13540 
13541 		{ &hf_nfs4_minorid, {
13542 			"minor ID", "nfs.minorid4", FT_UINT64, BASE_DEC,
13543 			NULL, 0, NULL, HFILL }},
13544 
13545 		{ &hf_nfs4_majorid, {
13546 			"major ID", "nfs.majorid4", FT_BYTES, BASE_NONE,
13547 			NULL, 0, NULL, HFILL }},
13548 
13549 		{ &hf_nfs4_padsize, {
13550 			"hdr pad size", "nfs.padsize4", FT_UINT32, BASE_DEC,
13551 			NULL, 0, NULL, HFILL }},
13552 
13553 #if 0
13554 		{ &hf_nfs4_cbrenforce, {
13555 			"binding enforce?", "nfs.cbrenforce4", FT_BOOLEAN, BASE_NONE,
13556 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13557 #endif
13558 
13559 #if 0
13560 		{ &hf_nfs4_hashalg, {
13561 			"hash alg", "nfs.hashalg4", FT_UINT32, BASE_DEC,
13562 			NULL, 0, NULL, HFILL }},
13563 #endif
13564 
13565 #if 0
13566 		{ &hf_nfs4_ssvlen, {
13567 			"ssv len", "nfs.ssvlen4", FT_UINT32, BASE_DEC,
13568 			NULL, 0, NULL, HFILL }},
13569 #endif
13570 
13571 		{ &hf_nfs4_maxreqsize, {
13572 			"max req size", "nfs.maxreqsize4", FT_UINT32, BASE_DEC,
13573 			NULL, 0, NULL, HFILL }},
13574 
13575 		{ &hf_nfs4_maxrespsize, {
13576 			"max resp size", "nfs.maxrespsize4", FT_UINT32, BASE_DEC,
13577 			NULL, 0, NULL, HFILL }},
13578 
13579 		{ &hf_nfs4_maxrespsizecached, {
13580 			"max resp size cached", "nfs.maxrespsizecached4", FT_UINT32, BASE_DEC,
13581 			NULL, 0, NULL, HFILL }},
13582 
13583 		{ &hf_nfs4_maxops, {
13584 			"max ops", "nfs.maxops4", FT_UINT32, BASE_DEC,
13585 			NULL, 0, NULL, HFILL }},
13586 
13587 		{ &hf_nfs4_maxreqs, {
13588 			"max reqs", "nfs.maxreqs4", FT_UINT32, BASE_DEC,
13589 			NULL, 0, NULL, HFILL }},
13590 
13591 		{ &hf_nfs4_rdmachanattrs, {
13592 			"RDMA chan attrs", "nfs.rdmachanattrs4", FT_UINT32, BASE_DEC,
13593 			NULL, 0, NULL, HFILL }},
13594 
13595 		{ &hf_nfs4_machinename, {
13596 			"machine name", "nfs.machinename4", FT_STRING, BASE_NONE,
13597 			NULL, 0, NULL, HFILL }},
13598 
13599 		{ &hf_nfs4_flavor, {
13600 			"flavor", "nfs.flavor4", FT_UINT32, BASE_DEC,
13601 			NULL, 0, NULL, HFILL }},
13602 
13603 		{ &hf_nfs4_stamp, {
13604 			"stamp", "nfs.stamp4", FT_UINT32, BASE_DEC,
13605 			NULL, 0, NULL, HFILL }},
13606 
13607 		{ &hf_nfs4_uid, {
13608 			"uid", "nfs.uid4", FT_UINT32, BASE_DEC,
13609 			NULL, 0, NULL, HFILL }},
13610 
13611 		{ &hf_nfs4_gid, {
13612 			"gid", "nfs.gid4", FT_UINT32, BASE_DEC,
13613 			NULL, 0, NULL, HFILL }},
13614 
13615 		{ &hf_nfs4_service, {
13616 			"gid", "nfs.service4", FT_UINT32, BASE_DEC,
13617 			NULL, 0, NULL, HFILL }},
13618 
13619 		{ &hf_nfs_access_check,
13620 			{ "Check access", "nfs.access_check",
13621 			FT_UINT8, BASE_HEX,
13622 			NULL, 0x0,
13623 			"Access type(s) to be checked", HFILL }
13624 		},
13625 		{ &hf_nfs_access_supported,
13626 			{ "Supported types (of requested)", "nfs.access_supported",
13627 			FT_UINT8, BASE_HEX,
13628 			NULL, 0x0,
13629 			"Access types (of those requested) that the server can reliably verify", HFILL }
13630 		},
13631 		{ &hf_nfs_access_rights,
13632 			{ "Access rights (of requested)", "nfs.access_rights",
13633 			FT_UINT8, BASE_HEX,
13634 			NULL, 0x0,
13635 			"Access rights for the types requested", HFILL }
13636 		},
13637 		{ &hf_nfs_access_supp_read,
13638 			{ "0x001 READ", "nfs.access_supp_read",
13639 			FT_BOOLEAN, 8,
13640 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_READ,
13641 			NULL, HFILL }
13642 		},
13643 		{ &hf_nfs_access_supp_lookup,
13644 			{ "0x002 LOOKUP", "nfs.access_supp_lookup",
13645 			FT_BOOLEAN, 8,
13646 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_LOOKUP,
13647 			NULL, HFILL }
13648 		},
13649 		{ &hf_nfs_access_supp_modify,
13650 			{ "0x004 MODIFY", "nfs.access_supp_modify",
13651 			FT_BOOLEAN, 8,
13652 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_MODIFY,
13653 			NULL, HFILL }
13654 		},
13655 		{ &hf_nfs_access_supp_extend,
13656 			{ "0x008 EXTEND", "nfs.access_supp_extend",
13657 			FT_BOOLEAN, 8,
13658 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_EXTEND,
13659 			NULL, HFILL }
13660 		},
13661 		{ &hf_nfs_access_supp_delete,
13662 			{ "0x010 DELETE", "nfs.access_supp_delete",
13663 			FT_BOOLEAN, 8,
13664 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_DELETE,
13665 			NULL, HFILL }
13666 		},
13667 		{ &hf_nfs_access_supp_execute,
13668 			{ "0x020 EXECUTE", "nfs.access_supp_execute",
13669 			FT_BOOLEAN, 8,
13670 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_EXECUTE,
13671 			NULL, HFILL }
13672 		},
13673 		{ &hf_nfs_access_supp_xattr_read,
13674 			{ "0x040 XATTR READ", "nfs.access_supp_xattr_read",
13675 			FT_BOOLEAN, 8,
13676 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_XATTR_READ,
13677 			NULL, HFILL }
13678 		},
13679 		{ &hf_nfs_access_supp_xattr_write,
13680 			{ "0x080 XATTR WRITE", "nfs.access_supp_xattr_write",
13681 			FT_BOOLEAN, 8,
13682 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_XATTR_WRITE,
13683 			NULL, HFILL }
13684 		},
13685 		{ &hf_nfs_access_supp_xattr_list,
13686 			{ "0x100 XATTR LIST", "nfs.access_supp_xattr_list",
13687 			FT_BOOLEAN, 8,
13688 			TFS(&tfs_access_supp), NFS_ACCESS_MASK_XATTR_LIST,
13689 			NULL, HFILL }
13690 		},
13691 		{ &hf_nfs_access_read,
13692 			{ "0x001 READ", "nfs.access_read",
13693 			FT_BOOLEAN, 8,
13694 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_READ,
13695 			NULL, HFILL }
13696 		},
13697 		{ &hf_nfs_access_lookup,
13698 			{ "0x002 LOOKUP", "nfs.access_lookup",
13699 			FT_BOOLEAN, 8,
13700 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_LOOKUP,
13701 			NULL, HFILL }
13702 		},
13703 		{ &hf_nfs_access_modify,
13704 			{ "0x004 MODIFY", "nfs.access_modify",
13705 			FT_BOOLEAN, 8,
13706 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_MODIFY,
13707 			NULL, HFILL }
13708 		},
13709 		{ &hf_nfs_access_extend,
13710 			{ "0x008 EXTEND", "nfs.access_extend",
13711 			FT_BOOLEAN, 8,
13712 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_EXTEND,
13713 			NULL, HFILL }
13714 		},
13715 		{ &hf_nfs_access_delete,
13716 			{ "0x010 DELETE", "nfs.access_delete",
13717 			FT_BOOLEAN, 8,
13718 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_DELETE,
13719 			NULL, HFILL }
13720 		},
13721 		{ &hf_nfs_access_execute,
13722 			{ "0x020 EXECUTE", "nfs.access_execute",
13723 			FT_BOOLEAN, 8,
13724 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_EXECUTE,
13725 			NULL, HFILL }
13726 		},
13727 		{ &hf_nfs_access_xattr_read,
13728 			{ "0x040 XATTR READ", "nfs.access_xattr_read",
13729 			FT_BOOLEAN, 8,
13730 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_XATTR_READ,
13731 			NULL, HFILL }
13732 		},
13733 		{ &hf_nfs_access_xattr_write,
13734 			{ "0x080 XATTR WRITE", "nfs.access_xattr_write",
13735 			FT_BOOLEAN, 8,
13736 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_XATTR_WRITE,
13737 			NULL, HFILL }
13738 		},
13739 		{ &hf_nfs_access_xattr_list,
13740 			{ "0x100 XATTR LIST", "nfs.access_xattr_list",
13741 			FT_BOOLEAN, 8,
13742 			TFS(&tfs_access_rights), NFS_ACCESS_MASK_XATTR_LIST,
13743 			NULL, HFILL }
13744 		},
13745 		{ &hf_nfs_access_denied,
13746 			{ "Access Denied", "nfs.access_denied",
13747 			FT_BOOLEAN, BASE_NONE,
13748 			NULL, 0x0,
13749 			"True if access has been denied to one or more of the requested types", HFILL }
13750 		},
13751 		{ &hf_nfs4_sessionid, {
13752 			"sessionid", "nfs.session_id4", FT_BYTES, BASE_NONE,
13753 			NULL, 0, NULL, HFILL }},
13754 		{ &hf_nfs4_exchid_call_flags, {
13755 			"flags", "nfs.exchange_id.call_flags", FT_UINT32, BASE_HEX,
13756 			NULL, 0, NULL, HFILL}},
13757 		{ &hf_nfs4_exchid_reply_flags, {
13758 			"flags", "nfs.exchange_id.reply_flags", FT_UINT32, BASE_HEX,
13759 			NULL, 0, NULL, HFILL}},
13760 		{ &hf_nfs4_exchid_flags_moved_refer, {
13761 			"EXCHGID4_FLAG_SUPP_MOVED_REFER", "nfs.exchange_id.flags.moved_refer", FT_BOOLEAN, 32,
13762 			TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
13763 		{ &hf_nfs4_exchid_flags_moved_migr, {
13764 			"EXCHGID4_FLAG_SUPP_MOVED_MIGR", "nfs.exchange_id.flags.moved_migr", FT_BOOLEAN, 32,
13765 			TFS(&tfs_set_notset), 0x00000002, NULL, HFILL}},
13766 		{ &hf_nfs4_exchid_flags_bind_princ, {
13767 			"EXCHGID4_FLAG_BIND_PRINC_STATEID", "nfs.exchange_id.flags.bind_princ", FT_BOOLEAN, 32,
13768 			TFS(&tfs_set_notset), 0x00000100, NULL, HFILL}},
13769 		{ &hf_nfs4_exchid_flags_non_pnfs, {
13770 			"EXCHGID4_FLAG_USE_NON_PNFS", "nfs.exchange_id.flags.non_pnfs", FT_BOOLEAN, 32,
13771 			TFS(&tfs_set_notset), 0x00010000, NULL, HFILL}},
13772 		{ &hf_nfs4_exchid_flags_pnfs_mds, {
13773 			"EXCHGID4_FLAG_USE_PNFS_MDS", "nfs.exchange_id.flags.pnfs_mds", FT_BOOLEAN, 32,
13774 			TFS(&tfs_set_notset), 0x00020000, NULL, HFILL}},
13775 		{ &hf_nfs4_exchid_flags_pnfs_ds, {
13776 			"EXCHGID4_FLAG_USE_PNFS_DS", "nfs.exchange_id.flags.pnfs_ds", FT_BOOLEAN, 32,
13777 			TFS(&tfs_set_notset), 0x00040000, NULL, HFILL}},
13778 		{ &hf_nfs4_exchid_flags_upd_conf_rec_a, {
13779 			"EXCHGID4_FLAG_UPD_CONFIRMED_REC_A", "nfs.exchange_id.flags.confirmed_rec_a",
13780 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x40000000, NULL, HFILL}},
13781 		{ &hf_nfs4_exchid_flags_confirmed_r, {
13782 			"EXCHGID4_FLAG_CONFIRMED_R", "nfs.exchange_id.flags.confirmed_r", FT_BOOLEAN, 32,
13783 			TFS(&tfs_set_notset), 0x80000000, NULL, HFILL}},
13784 		{ &hf_nfs4_sp_parms_hash_algs, {
13785 			"State Protect hash algorithms", "nfs.sp_parms4_hash_algs", FT_NONE, BASE_NONE,
13786 			NULL, 0, NULL, HFILL }},
13787 		{ &hf_nfs4_sp_parms_encr_algs, {
13788 			"State Protect encryption algorithms", "nfs.sp_parms4_encr_algs", FT_NONE, BASE_NONE,
13789 			NULL, 0, NULL, HFILL }},
13790 		{ &hf_nfs4_prot_info_hash_alg, {
13791 			"Prot Info hash algorithm", "nfs.prot_info4_hash_alg", FT_UINT32, BASE_HEX,
13792 			NULL, 0, NULL, HFILL }},
13793 		{ &hf_nfs4_prot_info_encr_alg, {
13794 			"Prot Info encryption algorithm", "nfs.prot_info4_encr_alg", FT_UINT32, BASE_HEX,
13795 			NULL, 0, NULL, HFILL }},
13796 		{ &hf_nfs4_prot_info_svv_length, {
13797 			"Prot Info svv_length", "nfs.prot_info4_svv_length", FT_UINT32, BASE_HEX,
13798 			NULL, 0, NULL, HFILL }},
13799 		{ &hf_nfs4_prot_info_spi_window, {
13800 			"Prot Info spi window", "nfs.prot_info4_spi_window", FT_UINT32, BASE_HEX,
13801 			NULL, 0, NULL, HFILL }},
13802 		{ &hf_nfs4_state_protect_window, {
13803 			"State Protect window", "nfs.state_protect_window", FT_UINT32, BASE_HEX,
13804 			NULL, 0, NULL, HFILL }},
13805 		{ &hf_nfs4_state_protect_num_gss_handles, {
13806 			"State Protect num gss handles", "nfs.state_protect_num_gss_handles", FT_UINT32, BASE_HEX,
13807 			NULL, 0, NULL, HFILL }},
13808 		{ &hf_nfs4_nii_domain, {
13809 			"Implementor DNS domain name(nii_domain)", "nfs.nii_domain4", FT_STRING, BASE_NONE,
13810 			NULL, 0, NULL, HFILL }},
13811 		{ &hf_nfs4_nii_name, {
13812 			"Implementation product name(nii_name)", "nfs.nii_name4", FT_STRING, BASE_NONE,
13813 			NULL, 0, NULL, HFILL }},
13814 		{ &hf_nfs4_create_session_flags_csa, {
13815 			"csa_flags", "nfs.create_session_flags", FT_UINT32, BASE_HEX,
13816 			NULL, 0, NULL, HFILL }},
13817 		{ &hf_nfs4_create_session_flags_csr, {
13818 			"csr_flags", "nfs.create_session_flags", FT_UINT32, BASE_HEX,
13819 			NULL, 0, NULL, HFILL }},
13820 		{ &hf_nfs4_create_session_flags_persist, {
13821 			"CREATE_SESSION4_FLAG_PERSIST", "nfs.create_session.flags.persist", FT_BOOLEAN, 32,
13822 			TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
13823 		{ &hf_nfs4_create_session_flags_conn_back_chan, {
13824 			"CREATE_SESSION4_FLAG_CONN_BACK_CHAN", "nfs.create_session.flags.conn_back_chan",
13825 			FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000002, NULL, HFILL}},
13826 		{ &hf_nfs4_create_session_flags_conn_rdma, {
13827 			"CREATE_SESSION4_FLAG_CONN_RDMA", "nfs.create_session.flags.conn_rdma",
13828 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x00000004, NULL, HFILL}},
13829 		{ &hf_nfs4_cachethis, {
13830 			"cache this?", "nfs.cachethis4", FT_BOOLEAN, BASE_NONE,
13831 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13832 		{ &hf_nfs4_reclaim_one_fs, {
13833 			"reclaim one fs?", "nfs.reclaim_one_fs4", FT_BOOLEAN,
13834 			BASE_NONE, TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13835 		{ &hf_nfs4_cb_procedure, {
13836 		   "CB Procedure", "nfs.cb_procedure", FT_UINT32, BASE_DEC,
13837 			VALS(nfs_cb_proc_vals), 0, NULL, HFILL }},
13838 		{ &hf_nfs4_cb_op, {
13839 		    "Opcode", "nfs.cb.operation", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
13840 		    &names_nfs_cb_operation_ext, 0, NULL, HFILL }},
13841 		{ &hf_nfs4_lrs_present, {
13842 			"StateID present?", "nfs.lrs_present", FT_BOOLEAN, BASE_NONE,
13843 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
13844 		{ &hf_nfs4_cb_truncate, {
13845 		    "Truncate?", "nfs.truncate", FT_BOOLEAN, BASE_NONE,
13846 		    TFS(&tfs_yes_no), 0, NULL, HFILL }},
13847 		{ &hf_nfs4_cb_layoutrecall_type, {
13848 			"recall type", "nfs.recalltype", FT_UINT32, BASE_DEC,
13849 			VALS(layoutrecall_names), 0, NULL, HFILL }},
13850 		{ &hf_nfs4_cb_clorachanged, {
13851 			"Clora changed", "nfs.clorachanged", FT_BOOLEAN, BASE_NONE,
13852 			TFS(&tfs_yes_no), 0, NULL, HFILL }},
13853 
13854 		{ &hf_nfs4_bctsa_dir, {
13855 			"bctsa_dir", "nfs.bctsa_dir", FT_UINT32, BASE_HEX,
13856 			VALS(names_channel_dir_from_client), 0, NULL, HFILL }},
13857 		{ &hf_nfs4_bctsa_use_conn_in_rdma_mode, {
13858 			"bctsa_use_conn_in_rdma_mode", "nfs.bctsa_use_conn_in_rdma_mode", FT_BOOLEAN, BASE_NONE,
13859 			NULL, 0, NULL, HFILL }},
13860 		{ &hf_nfs4_bctsr_dir, {
13861 			"bctsr_dir", "nfs.bctsr_dir", FT_UINT32, BASE_HEX,
13862 			VALS(names_channel_dir_from_server), 0, NULL, HFILL }},
13863 		{ &hf_nfs4_bctsr_use_conn_in_rdma_mode, {
13864 			"bctsr_use_conn_in_rdma_mode", "nfs.bctsr_use_conn_in_rdma_mode", FT_BOOLEAN, BASE_NONE,
13865 			NULL, 0, NULL, HFILL }},
13866 
13867 		{ &hf_nfs3_mode, {
13868 			"Mode", "nfs.mode3", FT_UINT32, BASE_OCT,
13869 			NULL, 0, NULL, HFILL }},
13870 
13871 		{ &hf_nfs3_mode_suid, {
13872 			"S_ISUID", "nfs.mode3.suid", FT_BOOLEAN, 32,
13873 			TFS(&tfs_yes_no), 0x800, NULL, HFILL }},
13874 
13875 		{ &hf_nfs3_mode_sgid, {
13876 			"S_ISGID", "nfs.mode3.sgid", FT_BOOLEAN, 32,
13877 			TFS(&tfs_yes_no), 0x400, NULL, HFILL }},
13878 
13879 		{ &hf_nfs3_mode_sticky, {
13880 			"S_ISVTX", "nfs.mode3.sticky", FT_BOOLEAN, 32,
13881 			TFS(&tfs_yes_no), 0x200, NULL, HFILL }},
13882 
13883 		{ &hf_nfs3_mode_rusr, {
13884 			"S_IRUSR", "nfs.mode3.rusr", FT_BOOLEAN, 32,
13885 			TFS(&tfs_yes_no), 0x100, NULL, HFILL }},
13886 
13887 		{ &hf_nfs3_mode_wusr, {
13888 			"S_IWUSR", "nfs.mode3.wusr", FT_BOOLEAN, 32,
13889 			TFS(&tfs_yes_no), 0x080, NULL, HFILL }},
13890 
13891 		{ &hf_nfs3_mode_xusr, {
13892 			"S_IXUSR", "nfs.mode3.xusr", FT_BOOLEAN, 32,
13893 			TFS(&tfs_yes_no), 0x040, NULL, HFILL }},
13894 
13895 		{ &hf_nfs3_mode_rgrp, {
13896 			"S_IRGRP", "nfs.mode3.rgrp", FT_BOOLEAN, 32,
13897 			TFS(&tfs_yes_no), 0x020, NULL, HFILL }},
13898 
13899 		{ &hf_nfs3_mode_wgrp, {
13900 			"S_IWGRP", "nfs.mode3.wgrp", FT_BOOLEAN, 32,
13901 			TFS(&tfs_yes_no), 0x010, NULL, HFILL }},
13902 
13903 		{ &hf_nfs3_mode_xgrp, {
13904 			"S_IXGRP", "nfs.mode3.xgrp", FT_BOOLEAN, 32,
13905 			TFS(&tfs_yes_no), 0x008, NULL, HFILL }},
13906 
13907 		{ &hf_nfs3_mode_roth, {
13908 			"S_IROTH", "nfs.mode3.roth", FT_BOOLEAN, 32,
13909 			TFS(&tfs_yes_no), 0x004, NULL, HFILL }},
13910 
13911 		{ &hf_nfs3_mode_woth, {
13912 			"S_IWOTH", "nfs.mode3.woth", FT_BOOLEAN, 32,
13913 			TFS(&tfs_yes_no), 0x002, NULL, HFILL }},
13914 
13915 		{ &hf_nfs3_mode_xoth, {
13916 			"S_IXOTH", "nfs.mode3.xoth", FT_BOOLEAN, 32,
13917 			TFS(&tfs_yes_no), 0x001, NULL, HFILL }},
13918 
13919 		{ &hf_nfs2_ftype, {
13920 			"type", "nfs.ftype", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
13921 			&nfs2_ftype_ext, 0, NULL, HFILL }},
13922 
13923 		{ &hf_nfs2_mode, {
13924 			"mode", "nfs.mode", FT_UINT32, BASE_OCT,
13925 			NULL, 0, NULL, HFILL }},
13926 
13927 		{ &hf_nfs2_mode_name, {
13928 			"Name", "nfs.mode.name", FT_UINT32, BASE_DEC,
13929 			VALS(nfs2_mode_names), 0160000, NULL, HFILL }},
13930 
13931 		{ &hf_nfs2_mode_set_user_id, {
13932 			"Set user id on exec", "nfs.mode.set_user_id", FT_BOOLEAN, 32,
13933 			TFS(&tfs_yes_no), 04000, NULL, HFILL }},
13934 
13935 		{ &hf_nfs2_mode_set_group_id, {
13936 			"Set group id on exec", "nfs.mode.set_group_id", FT_BOOLEAN, 32,
13937 			TFS(&tfs_yes_no), 02000, NULL, HFILL }},
13938 
13939 		{ &hf_nfs2_mode_save_swap_text, {
13940 			"Save swapped text even after use", "nfs.mode.save_swap_text", FT_BOOLEAN, 32,
13941 			TFS(&tfs_yes_no), 01000, NULL, HFILL }},
13942 
13943 		{ &hf_nfs2_mode_read_owner, {
13944 			"Read permission for owner", "nfs.mode.read_owner", FT_BOOLEAN, 32,
13945 			TFS(&tfs_yes_no), 0400, NULL, HFILL }},
13946 
13947 		{ &hf_nfs2_mode_write_owner, {
13948 			"Write permission for owner", "nfs.mode.write_owner", FT_BOOLEAN, 32,
13949 			TFS(&tfs_yes_no), 0200, NULL, HFILL }},
13950 
13951 		{ &hf_nfs2_mode_exec_owner, {
13952 			"Execute permission for owner", "nfs.mode.exec_owner", FT_BOOLEAN, 32,
13953 			TFS(&tfs_yes_no), 0100, NULL, HFILL }},
13954 
13955 		{ &hf_nfs2_mode_read_group, {
13956 			"Read permission for group", "nfs.mode.read_group", FT_BOOLEAN, 32,
13957 			TFS(&tfs_yes_no), 040, NULL, HFILL }},
13958 
13959 		{ &hf_nfs2_mode_write_group, {
13960 			"Write permission for group", "nfs.mode.write_group", FT_BOOLEAN, 32,
13961 			TFS(&tfs_yes_no), 020, NULL, HFILL }},
13962 
13963 		{ &hf_nfs2_mode_exec_group, {
13964 			"Execute permission for group", "nfs.mode.exec_group", FT_BOOLEAN, 32,
13965 			TFS(&tfs_yes_no), 010, NULL, HFILL }},
13966 
13967 		{ &hf_nfs2_mode_read_other, {
13968 			"Read permission for others", "nfs.mode.read_other", FT_BOOLEAN, 32,
13969 			TFS(&tfs_yes_no), 04, NULL, HFILL }},
13970 
13971 		{ &hf_nfs2_mode_write_other, {
13972 			"Write permission for others", "nfs.mode.write_other", FT_BOOLEAN, 32,
13973 			TFS(&tfs_yes_no), 02, NULL, HFILL }},
13974 
13975 		{ &hf_nfs2_mode_exec_other, {
13976 			"Execute permission for others", "nfs.mode.exec_other", FT_BOOLEAN, 32,
13977 			TFS(&tfs_yes_no), 01, NULL, HFILL }},
13978 
13979 		{ &hf_nfs4_sequence_status_flags, {
13980 			"status flags", "nfs.sequence.flags", FT_UINT32, BASE_HEX,
13981 			NULL, 0, NULL, HFILL }},
13982 
13983 		{ &hf_nfs4_sequence_status_flags_cb_path_down, {
13984 			"SEQ4_STATUS_CB_PATH_DOWN", "nfs.sequence.flags.cb_path_down", FT_BOOLEAN, 32,
13985 			TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
13986 
13987 		{ &hf_nfs4_sequence_status_flags_cb_gss_contexts_expiring, {
13988 			"SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING", "nfs.sequence.flags.cb_gss_contexts_expiring",
13989 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x00000002, NULL, HFILL}},
13990 
13991 		{ &hf_nfs4_sequence_status_flags_cb_gss_contexts_expired, {
13992 			"SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED", "nfs.sequence.flags.cb_gss_contexts_expired",
13993 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x00000004, NULL, HFILL}},
13994 
13995 		{ &hf_nfs4_sequence_status_flags_expired_all_state_revoked, {
13996 			"SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED", "nfs.sequence.flags.expired_all_state_revoked",
13997 			FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000008, NULL, HFILL}},
13998 
13999 		{ &hf_nfs4_sequence_status_flags_expired_some_state_revoked, {
14000 			"SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED", "nfs.sequence.flags.expired_some_state_revoked",
14001 			FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000010, NULL, HFILL}},
14002 
14003 		{ &hf_nfs4_sequence_status_flags_admin_state_revoked, {
14004 			"SEQ4_STATUS_ADMIN_STATE_REVOKED", "nfs.sequence.flags.admin_state_revoked",
14005 			FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000020, NULL, HFILL}},
14006 
14007 		{ &hf_nfs4_sequence_status_flags_recallable_state_revoked, {
14008 			"SEQ4_STATUS_RECALLABLE_STATE_REVOKED", "nfs.sequence.flags.recallable_state_revoked",
14009 			FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00000040, NULL, HFILL}},
14010 
14011 		{ &hf_nfs4_sequence_status_flags_lease_moved, {
14012 			"SEQ4_STATUS_LEASE_MOVED", "nfs.sequence.flags.lease_moved", FT_BOOLEAN, 32,
14013 			TFS(&tfs_set_notset), 0x00000080, NULL, HFILL}},
14014 
14015 		{ &hf_nfs4_sequence_status_flags_restart_reclaim_needed, {
14016 			"SEQ4_STATUS_RESTART_RECLAIM_NEEDED", "nfs.sequence.flags.restart_reclaim_needed",
14017 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x00000100, NULL, HFILL}},
14018 
14019 		{ &hf_nfs4_sequence_status_flags_cb_path_down_session, {
14020 			"SEQ4_STATUS_CB_PATH_DOWN_SESSION", "nfs.sequence.flags.cb_path_down_session",
14021 			FT_BOOLEAN, 32,	TFS(&tfs_set_notset), 0x00000200, NULL, HFILL}},
14022 
14023 		{ &hf_nfs4_sequence_status_flags_backchannel_fault, {
14024 			"SEQ4_STATUS_BACKCHANNEL_FAULT", "nfs.sequence.flags.backchannel_fault", FT_BOOLEAN, 32,
14025 			TFS(&tfs_set_notset), 0x00000400, NULL, HFILL}},
14026 
14027 		{ &hf_nfs4_sequence_status_flags_devid_changed, {
14028 			"SEQ4_STATUS_DEVID_CHANGED", "nfs.sequence.flags.devid_changed", FT_BOOLEAN, 32,
14029 			TFS(&tfs_set_notset), 0x00000800, NULL, HFILL}},
14030 
14031 		{ &hf_nfs4_sequence_status_flags_devid_deleted, {
14032 			"SEQ4_STATUS_DEVID_DELETED", "nfs.sequence.flags.devid_deleted", FT_BOOLEAN, 32,
14033 			TFS(&tfs_set_notset), 0x00001000, NULL, HFILL}},
14034 
14035 		{ &hf_nfs4_test_stateid_arg, {
14036 			"StateID List", "nfs.test_stateid.stateids",
14037 			FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL}},
14038 
14039 		{ &hf_nfs4_test_stateid_res, {
14040 			"StateID Result List", "nfs.test_stateid.results",
14041 			FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL}},
14042 
14043 		{ &hf_nfs4_seek_data_content, {
14044 			"data content", "nfs.data_content", FT_UINT32, BASE_DEC,
14045 			VALS(names_data_content), 0, NULL, HFILL }},
14046 
14047 		{ &hf_nfs4_bitmap_data, {
14048 			"Undissected bitmap data", "nfs.bitmap_data", FT_BYTES, BASE_NONE,
14049 			NULL, 0, NULL, HFILL }},
14050 
14051 		{ &hf_nfs4_huge_bitmap_length, {
14052 			"Huge bitmap length", "nfs.huge_bitmap_length", FT_UINT32, BASE_DEC,
14053 			NULL, 0, NULL, HFILL }},
14054 
14055 		{ &hf_nfs4_universal_address_ipv4, {
14056 			"universal_address", "nfs.universal_address.ipv4", FT_IPv4, BASE_NONE,
14057 			NULL, 0, NULL, HFILL }},
14058 
14059 		{ &hf_nfs4_universal_address_ipv6, {
14060 			"universal_address", "nfs.universal_address.ipv6", FT_IPv6, BASE_NONE,
14061 			NULL, 0, NULL, HFILL }},
14062 
14063 		{ &hf_nfs4_getdevinfo, {
14064 			"dev info", "nfs.devinfo", FT_BYTES,
14065 			BASE_NONE, NULL, 0, NULL, HFILL }},
14066 
14067 		{ &hf_nfs4_ff_version, {
14068 			"version", "nfs.ff.version", FT_UINT32, BASE_DEC,
14069 			NULL, 0, NULL, HFILL }},
14070 
14071 		{ &hf_nfs4_ff_minorversion, {
14072 			"minorversion", "nfs.ff.minorversion", FT_UINT32,
14073 			BASE_DEC, NULL, 0, NULL, HFILL }},
14074 
14075 		{ &hf_nfs4_ff_rsize, {
14076 			"max_rsize", "nfs.ff.rsize", FT_UINT32,
14077 			BASE_DEC, NULL, 0, NULL, HFILL }},
14078 
14079 		{ &hf_nfs4_ff_wsize, {
14080 			"max_wsize", "nfs.ff.wsize", FT_UINT32,
14081 			BASE_DEC, NULL, 0, NULL, HFILL }},
14082 
14083 		{ &hf_nfs4_ff_tightly_coupled, {
14084                         "tightly coupled", "nfs.ff.tightly_coupled",
14085 			FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
14086 			NULL, HFILL }},
14087 
14088 		{ &hf_nfs4_ff_layout_flags, {
14089 			"layout flags", "nfs.ff.layout_flags", FT_UINT32, BASE_HEX,
14090 			NULL, 0, NULL, HFILL }},
14091 
14092 		{ &hf_nfs4_ff_synthetic_owner, {
14093 			"synthetic owner", "nfs.ff.synthetic_owner", FT_STRING, BASE_NONE,
14094 			NULL, 0, NULL, HFILL }},
14095 
14096 		{ &hf_nfs4_ff_synthetic_owner_group, {
14097 			"synthetic group", "nfs.ff.synthetic_owner_group", FT_STRING, BASE_NONE,
14098 			NULL, 0, NULL, HFILL }},
14099 
14100 		{ &hf_nfs4_ff_layout_flags_no_layoutcommit, {
14101 			"FLAG_NO_LAYOUTCOMMIT", "nfs.ff.layout_flags.no_layoutcommit", FT_BOOLEAN, 32,
14102 			TFS(&tfs_set_notset), 0x00000001, NULL, HFILL}},
14103 
14104 		{ &hf_nfs4_ff_layout_flags_no_io_thru_mds, {
14105 			"FLAG_NO_IO_THRU_MDS", "nfs.ff.layout_flags.no_io_thru_mds", FT_BOOLEAN, 32,
14106 			TFS(&tfs_set_notset), 0x00000002, NULL, HFILL}},
14107 
14108 		{ &hf_nfs4_ff_layout_flags_no_read_io, {
14109 			"FLAG_NO_READ_IO", "nfs.ff.layout_flags.no_read_io", FT_BOOLEAN, 32,
14110 			TFS(&tfs_set_notset), 0x00000004, NULL, HFILL}},
14111 
14112 		{ &hf_nfs4_ff_stats_collect_hint, {
14113 			"stats collect hint", "nfs.ff.stats_collect_hint", FT_UINT32, BASE_DEC,
14114 			NULL, 0, "Layoutstats sampling period hint, Seconds", HFILL }},
14115 
14116 		{ &hf_nfs4_fattr_clone_blocksize, {
14117 			"clone block size", "nfs.fattr4.clone_block_size", FT_UINT32, BASE_DEC,
14118 			NULL, 0, NULL, HFILL }},
14119 
14120 		{ &hf_nfs4_fattr_space_freed, {
14121 			"space freed", "nfs.fattr4.space_freed", FT_UINT64, BASE_DEC,
14122 			NULL, 0, NULL, HFILL }},
14123 
14124 		{ &hf_nfs4_fattr_change_attr_type, {
14125 			"change attr type", "nfs.fattr4.change_attr_type", FT_UINT32, BASE_DEC,
14126 			VALS(names_nfs_change_attr_types), 0, NULL, HFILL }},
14127 
14128 		{ &hf_nfs4_callback_stateids, {
14129 			"Callback StateIds", "nfs.callback_ids", FT_UINT32, BASE_DEC,
14130 			NULL, 0, NULL, HFILL }},
14131 
14132 		{ &hf_nfs4_callback_stateids_index, {
14133 			"Callback Id", "nfs.ff.callback_id_index", FT_UINT32, BASE_DEC,
14134 			NULL, 0, NULL, HFILL }},
14135 
14136 		{ &hf_nfs4_num_offload_status, {
14137 			"Number of offload status", "nfs.num_offload_status", FT_UINT32, BASE_DEC,
14138 			NULL, 0, NULL, HFILL }},
14139 
14140 		{ &hf_nfs4_offload_status_index, {
14141 			"nfsstat4", "nfs.offload_status", FT_UINT32, BASE_DEC,
14142 			NULL, 0, NULL, HFILL }},
14143 
14144 		{ &hf_nfs4_consecutive, {
14145 			"copy consecutively?", "nfs.consecutive", FT_BOOLEAN, BASE_NONE,
14146 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
14147 
14148 		{ &hf_nfs4_netloc, {
14149 			"net loc", "nfs.netloc", FT_BYTES,
14150 			BASE_NONE, NULL, 0, NULL, HFILL }},
14151 
14152 		{ &hf_nfs4_netloc_type, {
14153 			"netloc type", "nfs.netloctype", FT_UINT32, BASE_DEC,
14154 			VALS(netloctype_names), 0, NULL, HFILL }},
14155 
14156 		{ &hf_nfs4_nl_name, {
14157 			"net loc name", "nfs.nl_name", FT_STRING, BASE_NONE,
14158 			NULL, 0, NULL, HFILL }},
14159 
14160 		{ &hf_nfs4_nl_url, {
14161 			"net loc url", "nfs.nl_url", FT_STRING, BASE_NONE,
14162 			NULL, 0, NULL, HFILL }},
14163 
14164 		{ &hf_nfs4_source_servers, {
14165 			"Source Server count", "nfs.source_servers", FT_UINT32, BASE_DEC,
14166 			NULL, 0, NULL, HFILL }},
14167 
14168 		{ &hf_nfs4_source_server_index, {
14169 			"Source Server", "nfs.ff.source_server_index", FT_UINT32, BASE_DEC,
14170 			NULL, 0, NULL, HFILL }},
14171 
14172 		{ &hf_nfs4_synchronous, {
14173 			"copy synchronous?", "nfs.synchronous", FT_BOOLEAN, BASE_NONE,
14174 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
14175 
14176 		{ &hf_nfs4_io_hints_mask, {
14177 			"Hint mask", "nfs.hint.mask", FT_UINT32, BASE_HEX,
14178 			NULL, 0, NULL, HFILL }},
14179 
14180 		{ &hf_nfs4_io_hint_count, {
14181 			"Hint count", "nfs.hint.count", FT_UINT32, BASE_DEC,
14182 			NULL, 0, NULL, HFILL }},
14183 
14184 		{ &hf_nfs4_io_advise_hint, {
14185 			"Hint", "nfs.hint.hint", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
14186 			&io_advise_names_ext, 0, NULL, HFILL }},
14187 
14188 		{ &hf_nfs4_bytes_copied, {
14189 			"bytes copied", "nfs.bytes_copied", FT_UINT64, BASE_DEC,
14190 			NULL, 0, NULL, HFILL }},
14191 
14192 		{ &hf_nfs4_read_plus_contents, {
14193 			"Contents", "nfs.contents",
14194 			FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
14195 
14196 		{ &hf_nfs4_read_plus_content_type, {
14197 			"Content Type", "nfs.content.type", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
14198 			&read_plus_content_names_ext, 0, NULL, HFILL }},
14199 
14200 		{ &hf_nfs4_block_size, {
14201 			"Content index", "nfs.content.index", FT_UINT32, BASE_DEC,
14202 			NULL, 0, NULL, HFILL }},
14203 
14204 		{ &hf_nfs4_block_count, {
14205 			"Number of Blocks", "nfs.adb.block.count", FT_UINT32, BASE_DEC,
14206 			NULL, 0, NULL, HFILL }},
14207 
14208 		{ &hf_nfs4_reloff_blocknum, {
14209 			"Relative Offset Block Number", "nfs.adb.block.reloff_num", FT_UINT32, BASE_DEC,
14210 			NULL, 0, NULL, HFILL }},
14211 
14212 		{ &hf_nfs4_blocknum, {
14213 			"Block Number", "nfs.adb.block.num", FT_UINT32, BASE_DEC,
14214 			NULL, 0, NULL, HFILL }},
14215 
14216 		{ &hf_nfs4_reloff_pattern, {
14217 			"Relative Offset Pattern", "nfs.adb.pattern.reloff", FT_UINT32, BASE_DEC,
14218 			NULL, 0, NULL, HFILL }},
14219 
14220 		{ &hf_nfs4_pattern_hash, {
14221 			"hash (CRC-32)", "nfs.adb.pattern_hash", FT_UINT32, BASE_HEX,
14222 			NULL, 0, "ADB pattern hash", HFILL }},
14223 
14224 		{ &hf_nfs4_xattrkey, {
14225 			"Name", "nfs.xattr.key", FT_STRING, BASE_NONE,
14226 			NULL, 0, "Xattr key", HFILL }},
14227 
14228 		{ &hf_nfs4_setxattr_options, {
14229 			"setxattr options", "nfs.setxattr.options", FT_UINT32, BASE_DEC,
14230 			VALS(names_setxattr_options), 0, NULL, HFILL }},
14231 
14232 		{ &hf_nfs4_listxattr_maxcount, {
14233 			"maxcount", "nfs.lisxtattr.maxcount", FT_UINT32, BASE_DEC,
14234 			NULL, 0, "Lixtxattr maxcount", HFILL }},
14235 
14236 		{ &hf_nfs4_listxattr_cookie, {
14237 			"cookie", "nfs.lisxtattr.cookie", FT_UINT64, BASE_DEC,
14238 			NULL, 0, "Lixtxattr cookie", HFILL }},
14239 
14240 		{ &hf_nfs4_listxattr_names_len, {
14241 			"xattr names count", "nfs.listxattr.names.count", FT_UINT32, BASE_DEC,
14242 			NULL, 0, "Number of xattrkey names", HFILL }},
14243 
14244 		{ &hf_nfs4_listxattr_eof, {
14245 			"eof", "nfs.lisxtattr.eof", FT_UINT32, BASE_DEC,
14246 			NULL, 0, "Lixtxattr eof", HFILL }},
14247 
14248 		{ &hf_nfs4_ff_local, {
14249 			"client used cache?", "nfs.ff.local", FT_BOOLEAN, BASE_NONE,
14250 			TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
14251 
14252 		{ &hf_nfs4_io_count, {
14253 			"count", "nfs.io_count", FT_UINT64, BASE_DEC,
14254 			NULL, 0, NULL, HFILL }},
14255 
14256 		{ &hf_nfs4_io_bytes, {
14257 			"bytes", "nfs.io_bytes", FT_UINT64, BASE_DEC,
14258 			NULL, 0, NULL, HFILL }},
14259 
14260 		{ &hf_nfs4_ff_ops_requested, {
14261 			"ops requested", "nfs.ff.ops_requested", FT_UINT64, BASE_DEC,
14262 			NULL, 0, NULL, HFILL }},
14263 
14264 		{ &hf_nfs4_ff_bytes_requested, {
14265 			"bytes requested", "nfs.ff.bytes_requested", FT_UINT64, BASE_DEC,
14266 			NULL, 0, NULL, HFILL }},
14267 
14268 		{ &hf_nfs4_ff_ops_completed, {
14269 			"ops completed", "nfs.ff.ops_completed", FT_UINT64, BASE_DEC,
14270 			NULL, 0, NULL, HFILL }},
14271 
14272 		{ &hf_nfs4_ff_bytes_completed, {
14273 			"bytes completed", "nfs.ff.bytes_completed", FT_UINT64, BASE_DEC,
14274 			NULL, 0, NULL, HFILL }},
14275 
14276 		{ &hf_nfs4_ff_bytes_not_delivered, {
14277 			"bytes not delivered", "nfs.ff.bytes_not_delivered", FT_UINT64, BASE_DEC,
14278 			NULL, 0, NULL, HFILL }},
14279 
14280 		{ &hf_nfs4_layoutstats, {
14281 			"Layout Stats", "nfs.layoutstats", FT_BYTES, BASE_NONE,
14282 			NULL, 0, NULL, HFILL }},
14283 
14284 		{ &hf_nfs4_device_error_count, {
14285 			"Device Error count", "nfs.device_error_count", FT_UINT32, BASE_DEC,
14286 			NULL, 0, NULL, HFILL }},
14287 
14288 		{ &hf_nfs4_device_errors_index, {
14289 			"Device Error index", "nfs.device_errors_index", FT_UINT32, BASE_DEC,
14290 			NULL, 0, NULL, HFILL }},
14291 
14292 		{ &hf_nfs4_ff_ioerrs_count, {
14293 			"IO Errors count", "nfs.ff.ioerrs_count", FT_UINT32, BASE_DEC,
14294 			NULL, 0, NULL, HFILL }},
14295 
14296 		{ &hf_nfs4_ff_ioerrs_index, {
14297 			"IO Errors index", "nfs.ff.ioerrs_index", FT_UINT32, BASE_DEC,
14298 			NULL, 0, NULL, HFILL }},
14299 
14300 		{ &hf_nfs4_ff_ioerrs_length, {
14301 			"length", "nfs.ff.ioerrs_length", FT_UINT64, BASE_DEC,
14302 			NULL, 0, NULL, HFILL }},
14303 
14304 		{ &hf_nfs4_ff_ioerrs_offset, {
14305 			"offset", "nfs.ff.ioerrs_offset", FT_UINT64, BASE_DEC,
14306 			NULL, 0, NULL, HFILL }},
14307 
14308 		{ &hf_nfs4_ff_iostats_count, {
14309 			"IO Stats count", "nfs.ff.iostats_count", FT_UINT32, BASE_DEC,
14310 			NULL, 0, NULL, HFILL }},
14311 
14312 		{ &hf_nfs4_ff_iostats_index, {
14313 			"IO Stats index", "nfs.ff.iostats_index", FT_UINT32, BASE_DEC,
14314 			NULL, 0, NULL, HFILL }},
14315 
14316 		{ &hf_nfs4_io_error_op, {
14317 			"OP", "nfs.ff_ioerrs_op", FT_UINT32, BASE_DEC|BASE_EXT_STRING,
14318 			&names_nfs4_operation_ext, 0, NULL, HFILL }},
14319 
14320 	/* Hidden field for v2, v3, and v4 status */
14321 		{ &hf_nfs_status, {
14322 			"Status", "nfs.status", FT_UINT32, BASE_DEC | BASE_EXT_STRING,
14323 			&names_nfs_nfsstat_ext, 0, "Reply status", HFILL }}
14324 	};
14325 
14326 	static gint *ett[] = {
14327 		&ett_nfs,
14328 		&ett_nfs_fh_encoding,
14329 		&ett_nfs_fh_fsid,
14330 		&ett_nfs_fh_file,
14331 		&ett_nfs_fh_mount,
14332 		&ett_nfs_fh_export,
14333 		&ett_nfs_fh_xfsid,
14334 		&ett_nfs_fh_fn,
14335 		&ett_nfs_fh_xfn,
14336 		&ett_nfs_fh_hp,
14337 		&ett_nfs_fh_auth,
14338 		&ett_nfs_fhandle,
14339 		&ett_nfs_timeval,
14340 		&ett_nfs_fattr,
14341 		&ett_nfs_fh_obj,
14342 		&ett_nfs_fh_ex,
14343 		&ett_nfs_readdir_entry,
14344 		&ett_nfs_utf8string,
14345 
14346 		&ett_nfs2_mode,
14347 		&ett_nfs2_sattr,
14348 		&ett_nfs2_diropargs,
14349 
14350 		&ett_nfs3_gxfh_utlfield,
14351 		&ett_nfs3_gxfh_sfhfield,
14352 		&ett_nfs3_gxfh_sfhflags,
14353 		&ett_nfs3_mode,
14354 		&ett_nfs3_specdata,
14355 		&ett_nfs3_fh,
14356 		&ett_nfs3_nfstime,
14357 		&ett_nfs3_fattr,
14358 		&ett_nfs3_post_op_fh,
14359 		&ett_nfs3_sattr,
14360 		&ett_nfs3_diropargs,
14361 		&ett_nfs3_sattrguard,
14362 		&ett_nfs3_set_mode,
14363 		&ett_nfs3_set_uid,
14364 		&ett_nfs3_set_gid,
14365 		&ett_nfs3_set_size,
14366 		&ett_nfs3_set_atime,
14367 		&ett_nfs3_set_mtime,
14368 		&ett_nfs3_pre_op_attr,
14369 		&ett_nfs3_post_op_attr,
14370 		&ett_nfs3_wcc_attr,
14371 		&ett_nfs3_wcc_data,
14372 		&ett_nfs3_access,
14373 		&ett_nfs3_fsinfo_properties,
14374 
14375 		&ett_nfs4_fh_file,
14376 		&ett_nfs4_fh_file_flags,
14377 		&ett_nfs4_fh_export,
14378 		&ett_nfs4_compound_call,
14379 		&ett_nfs4_request_op,
14380 		&ett_nfs4_response_op,
14381 		&ett_nfs4_access,
14382 		&ett_nfs4_access_supp,
14383 		&ett_nfs4_close,
14384 		&ett_nfs4_commit,
14385 		&ett_nfs4_create,
14386 		&ett_nfs4_delegpurge,
14387 		&ett_nfs4_delegreturn,
14388 		&ett_nfs4_getattr,
14389 		&ett_nfs4_getattr_args,
14390 		&ett_nfs4_getattr_resp,
14391 		&ett_nfs4_resok4,
14392 		&ett_nfs4_obj_attrs,
14393 		&ett_nfs4_fattr_new_attr_vals,
14394 		&ett_nfs4_fattr4_attrmask,
14395 		&ett_nfs4_attribute,
14396 		&ett_nfs4_getfh,
14397 		&ett_nfs4_link,
14398 		&ett_nfs4_lock,
14399 		&ett_nfs4_lockt,
14400 		&ett_nfs4_locku,
14401 		&ett_nfs4_lookup,
14402 		&ett_nfs4_lookupp,
14403 		&ett_nfs4_nverify,
14404 		&ett_nfs4_open,
14405 		&ett_nfs4_openattr,
14406 		&ett_nfs4_open_confirm,
14407 		&ett_nfs4_open_downgrade,
14408 		&ett_nfs4_putfh,
14409 		&ett_nfs4_putpubfh,
14410 		&ett_nfs4_putrootfh,
14411 		&ett_nfs4_read,
14412 		&ett_nfs4_readdir,
14413 		&ett_nfs4_readlink,
14414 		&ett_nfs4_test_stateid,
14415 		&ett_nfs4_destroy_clientid,
14416 		&ett_nfs4_reclaim_complete,
14417 		&ett_nfs4_remove,
14418 		&ett_nfs4_rename,
14419 		&ett_nfs4_renew,
14420 		&ett_nfs4_restorefh,
14421 		&ett_nfs4_savefh,
14422 		&ett_nfs4_setattr,
14423 		&ett_nfs4_setclientid,
14424 		&ett_nfs4_setclientid_confirm,
14425 		&ett_nfs4_verify,
14426 		&ett_nfs4_write,
14427 		&ett_nfs4_release_lockowner,
14428 		&ett_nfs4_backchannel_ctl,
14429 		&ett_nfs4_bind_conn_to_session,
14430 		&ett_nfs4_exchange_id,
14431 		&ett_nfs4_create_session,
14432 		&ett_nfs4_destroy_session,
14433 		&ett_nfs4_free_stateid,
14434 		&ett_nfs4_secinfo_no_name,
14435 		&ett_nfs4_sequence,
14436 		&ett_nfs4_layoutget,
14437 		&ett_nfs4_layoutcommit,
14438 		&ett_nfs4_layoutreturn,
14439 		&ett_nfs4_getdevinfo,
14440 		&ett_nfs4_getdevlist,
14441 		&ett_nfs4_seek,
14442 		&ett_nfs4_allocate,
14443 		&ett_nfs4_deallocate,
14444 		&ett_nfs4_illegal,
14445 		&ett_nfs4_verifier,
14446 		&ett_nfs4_dirlist,
14447 		&ett_nfs4_dir_entry,
14448 		&ett_nfs4_pathname,
14449 		&ett_nfs4_change_info,
14450 		&ett_nfs4_open_delegation,
14451 		&ett_nfs4_open_claim,
14452 		&ett_nfs4_opentype,
14453 		&ett_nfs4_lock_owner,
14454 		&ett_nfs4_cb_client,
14455 		&ett_nfs4_client_id,
14456 		&ett_nfs4_clientowner,
14457 		&ett_nfs4_exchangeid_call_flags,
14458 		&ett_nfs4_exchangeid_reply_flags,
14459 		&ett_nfs4_server_owner,
14460 		&ett_nfs4_bitmap,
14461 		&ett_nfs4_attr_request,
14462 		&ett_nfs4_fattr,
14463 		&ett_nfs4_fsid,
14464 		&ett_nfs4_fs_locations,
14465 		&ett_nfs4_fs_location,
14466 		&ett_nfs4_open_result_flags,
14467 		&ett_nfs4_secinfo,
14468 		&ett_nfs4_secinfo_flavor_info,
14469 		&ett_nfs4_stateid,
14470 		&ett_nfs4_fattr_fh_expire_type,
14471 		&ett_nfs4_fattr_aclsupport,
14472 		&ett_nfs4_fattr_fs_charset_cap,
14473 		&ett_nfs4_aclflag,
14474 		&ett_nfs4_ace,
14475 		&ett_nfs4_clientaddr,
14476 		&ett_nfs4_aceflag,
14477 		&ett_nfs4_acemask,
14478 		&ett_nfs4_slotid,
14479 		&ett_nfs4_sr_status,
14480 		&ett_nfs4_serverscope,
14481 		&ett_nfs4_minorid,
14482 		&ett_nfs4_majorid,
14483 		&ett_nfs4_persist,
14484 		&ett_nfs4_backchan,
14485 		&ett_nfs4_rdmamode,
14486 		&ett_nfs4_padsize,
14487 		&ett_nfs4_cbrenforce,
14488 		&ett_nfs4_hashalg,
14489 		&ett_nfs4_ssvlen,
14490 		&ett_nfs4_maxreqsize,
14491 		&ett_nfs4_maxrespsize,
14492 		&ett_nfs4_maxrespsizecached,
14493 		&ett_nfs4_maxops,
14494 		&ett_nfs4_maxreqs,
14495 		&ett_nfs4_streamchanattrs,
14496 		&ett_nfs4_rdmachanattrs,
14497 		&ett_nfs4_machinename,
14498 		&ett_nfs4_flavor,
14499 		&ett_nfs4_stamp,
14500 		&ett_nfs4_uid,
14501 		&ett_nfs4_gid,
14502 		&ett_nfs4_service,
14503 		&ett_nfs4_sessionid,
14504 		&ett_nfs4_layoutseg,
14505 		&ett_nfs4_layoutseg_sub,
14506 		&ett_nfs4_nfl_util,
14507 		&ett_nfs4_cb_request_op,
14508 		&ett_nfs4_cb_resop,
14509 		&ett_nfs4_cb_getattr,
14510 		&ett_nfs4_cb_recall,
14511 		&ett_nfs4_cb_layoutrecall,
14512 		&ett_nfs4_cb_pushdeleg,
14513 		&ett_nfs4_cb_recallany,
14514 		&ett_nfs4_cb_recallableobjavail,
14515 		&ett_nfs4_cb_recallslot,
14516 		&ett_nfs4_cb_sequence,
14517 		&ett_nfs4_cb_wantscancelled,
14518 		&ett_nfs4_cb_notifylock,
14519 		&ett_nfs4_cb_notifydeviceid,
14520 		&ett_nfs4_cb_notify,
14521 		&ett_nfs4_cb_reflists,
14522 		&ett_nfs4_cb_refcalls,
14523 		&ett_nfs4_cb_illegal,
14524 		&ett_nfs4_chan_attrs,
14525 		&ett_nfs4_create_session_flags,
14526 		&ett_nfs4_sequence_status_flags,
14527 		&ett_nfs4_want_notify_flags,
14528 		&ett_nfs4_ff_layout_flags,
14529 		&ett_nfs4_scsi_layout_vol,
14530 		&ett_nfs4_scsi_layout_vol_indices,
14531 		&ett_nfs4_layoutstats,
14532 		&ett_nfs4_io_info,
14533 		&ett_nfs4_io_latency,
14534 		&ett_nfs4_io_time,
14535 		&ett_nfs4_callback_stateids_sub,
14536 		&ett_nfs4_source_servers_sub,
14537 		&ett_nfs4_copy,
14538 		&ett_nfs4_copy_notify,
14539 		&ett_nfs4_device_errors_sub,
14540 		&ett_nfs4_layouterror,
14541 		&ett_nfs4_ff_ioerrs_sub,
14542 		&ett_nfs4_ff_iostats_sub,
14543 		&ett_nfs4_clone,
14544 		&ett_nfs4_getxattr,
14545 		&ett_nfs4_setxattr,
14546 		&ett_nfs4_listxattr,
14547 		&ett_nfs4_removexattr,
14548 		&ett_nfs4_offload_cancel,
14549 		&ett_nfs4_offload_status,
14550 		&ett_nfs4_osr_complete_sub,
14551 		&ett_nfs4_io_advise,
14552 		&ett_nfs4_read_plus,
14553 		&ett_nfs4_read_plus_content_sub,
14554 		&ett_nfs4_write_same,
14555 		&ett_nfs4_fh_pd_flags,
14556 		&ett_nfs4_fh_pd_sites,
14557 		&ett_nfs4_fh_pd_spaces,
14558 		&ett_nfs4_listxattr_names
14559 
14560 	};
14561 
14562 	static ei_register_info ei[] = {
14563 		{ &ei_nfs_too_many_ops, { "nfs.too_many_ops", PI_PROTOCOL, PI_NOTE, "Too many operations", EXPFILL }},
14564 		{ &ei_nfs_not_vnx_file, { "nfs.not_vnx_file", PI_UNDECODED, PI_WARN, "Not a Celerra|VNX file handle", EXPFILL }},
14565 		{ &ei_protocol_violation, { "nfs.protocol_violation", PI_PROTOCOL, PI_WARN,
14566 			"Per RFCs 3530 and 5661 an attribute mask is required but was not provided.", EXPFILL }},
14567 		{ &ei_nfs_too_many_bitmaps, { "nfs.too_many_bitmaps", PI_PROTOCOL, PI_NOTE, "Too many bitmap array items", EXPFILL }},
14568 		{ &ei_nfs_bitmap_no_dissector, { "nfs.bitmap_no_dissector", PI_PROTOCOL, PI_WARN,
14569 			"Unknown dissector for bitmap attribute", EXPFILL }},
14570 		{ &ei_nfs_bitmap_skip_value, { "nfs.bitmap_skip_value", PI_PROTOCOL, PI_WARN,
14571 			"Not dissecting value since a previous value was not dissected", EXPFILL }},
14572 		{ &ei_nfs_bitmap_undissected_data, { "nfs.bitmap_undissected_data", PI_PROTOCOL, PI_WARN,
14573 			"There is some bitmap data left undissected", EXPFILL }},
14574 		{ &ei_nfs4_stateid_deprecated, { "nfs.stateid.deprecated", PI_PROTOCOL, PI_WARN, "State ID deprecated in CLOSE responses [RFC7530 16.2.5]", EXPFILL }},
14575 		{ &ei_nfs_file_system_cycle, { "nfs.file_system_cycle", PI_PROTOCOL, PI_WARN, "Possible file system cycle detected", EXPFILL }},
14576 	};
14577 
14578 	module_t *nfs_module;
14579 	expert_module_t* expert_nfs;
14580 
14581 	proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
14582 
14583 	/* "protocols" registered just for Decode As */
14584 	proto_nfs_unknown = proto_register_protocol_in_name_only("Unknown", "unknown", "nfs.unknown", proto_nfs, FT_PROTOCOL);
14585 	proto_nfs_svr4 = proto_register_protocol_in_name_only("SVR4", "svr4", "nfs.svr4", proto_nfs, FT_PROTOCOL);
14586 	proto_nfs_knfsd_le = proto_register_protocol_in_name_only("KNFSD_LE", "knfsd_le", "nfs.knfsd_le", proto_nfs, FT_PROTOCOL);
14587 	proto_nfs_nfsd_le = proto_register_protocol_in_name_only("NFSD_LE", "nfsd_le", "nfs.nfsd_le", proto_nfs, FT_PROTOCOL);
14588 	proto_nfs_knfsd_new = proto_register_protocol_in_name_only("KNFSD_NEW", "knfsd_new", "nfs.knfsd_new", proto_nfs, FT_PROTOCOL);
14589 	proto_nfs_ontap_v3 = proto_register_protocol_in_name_only("ONTAP_V3", "ontap_v3", "nfs.ontap_v3", proto_nfs, FT_PROTOCOL);
14590 	proto_nfs_ontap_v4 = proto_register_protocol_in_name_only("ONTAP_V4", "ontap_v4", "nfs.ontap_v4", proto_nfs, FT_PROTOCOL);
14591 	proto_nfs_ontap_gx_v3 = proto_register_protocol_in_name_only("ONTAP_GX_V3", "ontap_gx_v3", "nfs.ontap_gx_v3", proto_nfs, FT_PROTOCOL);
14592 	proto_nfs_celerra_vnx = proto_register_protocol_in_name_only("CELERRA_VNX", "celerra_vnx", "nfs.celerra_vnx", proto_nfs, FT_PROTOCOL);
14593 	proto_nfs_gluster = proto_register_protocol_in_name_only("GLUSTER", "gluster", "nfs.gluster", proto_nfs, FT_PROTOCOL);
14594 	proto_nfs_dcache = proto_register_protocol_in_name_only("dCache", "dcache", "nfs.dcache", proto_nfs, FT_PROTOCOL);
14595 	proto_nfs_primary_data = proto_register_protocol_in_name_only("Primary_Data", "pd", "nfs.primary_data", proto_nfs, FT_PROTOCOL);
14596 
14597 	/* "protocols" registered just for ONC-RPC Service Response Time */
14598 	proto_nfs_cb = proto_register_protocol_in_name_only("Network File System CB", "NFS CB", "nfs.cb", proto_nfs, FT_PROTOCOL);
14599 
14600 	proto_register_field_array(proto_nfs, hf, array_length(hf));
14601 	proto_register_subtree_array(ett, array_length(ett));
14602 	expert_nfs = expert_register_protocol(proto_nfs);
14603 	expert_register_field_array(expert_nfs, ei, array_length(ei));
14604 
14605 	nfs_module = prefs_register_protocol(proto_nfs, NULL);
14606 	prefs_register_bool_preference(nfs_module, "file_name_snooping",
14607 				       "Snoop FH to filename mappings",
14608 				       "Whether the dissector should snoop the FH to"
14609 				       " filename mappings by looking inside certain packets",
14610 				       &nfs_file_name_snooping);
14611 	prefs_register_bool_preference(nfs_module, "file_full_name_snooping",
14612 				       "Snoop full path to filenames",
14613 				       "Whether the dissector should snoop the full pathname"
14614 				       " for files for matching FH's",
14615 				       &nfs_file_name_full_snooping);
14616 	prefs_register_bool_preference(nfs_module, "fhandle_find_both_reqrep",
14617 				       "Fhandle filters finds both request/response",
14618 				       "With this option display filters for nfs fhandles"
14619 				       " (nfs.fh.{name|full_name|hash}) will find both the request"
14620 				       " and response packets for a RPC call, even if the actual"
14621 				       " fhandle is only present in one of the packets",
14622 				       &nfs_fhandle_reqrep_matching);
14623 	prefs_register_bool_preference(nfs_module, "display_nfsv4_tag",
14624 				       "Display NFSv4 tag in info Column",
14625 				       "When enabled, this option will print the NFSv4 tag"
14626 				       " (if one exists) in the Info column in the Summary pane",
14627 					&nfs_display_v4_tag);
14628 	prefs_register_bool_preference(nfs_module, "display_major_nfsv4_ops",
14629 				       "Display only 'significant' NFSv4 Operations in info Column",
14630 				       "When enabled, shows only the significant NFSv4 Operations"
14631 				       " in the info column.  Others (like GETFH, PUTFH, etc) are not displayed",
14632 					&display_major_nfs4_ops);
14633 
14634 	prefs_register_obsolete_preference(nfs_module, "default_fhandle_type");
14635 
14636 	nfs_name_snoop_known    = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
14637 	nfs_file_handles        = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
14638 	nfs_fhandle_frame_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
14639 	register_init_routine(nfs_name_snoop_init);
14640 	register_cleanup_routine(nfs_name_snoop_cleanup);
14641 
14642 	nfs_fhandle_table = register_decode_as_next_proto(proto_nfs, "nfs_fhandle.type",
14643 								"NFS File Handle types", nfs_prompt);
14644 }
14645 
14646 
14647 void
proto_reg_handoff_nfs(void)14648 proto_reg_handoff_nfs(void)
14649 {
14650 	dissector_handle_t fhandle_handle;
14651 
14652 	/* Register the protocol as RPC */
14653 	rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs,
14654 	    G_N_ELEMENTS(nfs_vers_info), nfs_vers_info);
14655 
14656 	/* Register the CB protocol as RPC */
14657 	rpc_init_prog(proto_nfs_cb, NFS_CB_PROGRAM, ett_nfs,
14658 	    G_N_ELEMENTS(nfs_cb_vers_info), nfs_cb_vers_info);
14659 
14660 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_SVR4, proto_nfs_svr4);
14661 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14662 
14663 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_LE, proto_nfs_knfsd_le);
14664 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14665 
14666 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_NFSD_LE, proto_nfs_nfsd_le);
14667 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14668 
14669 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_LINUX_KNFSD_NEW, proto_nfs_knfsd_new);
14670 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14671 
14672 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP, proto_nfs_ontap_v3);
14673 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14674 
14675 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_V4, proto_nfs_ontap_v4);
14676 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14677 
14678 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_NETAPP_GX_v3, proto_nfs_ontap_gx_v3);
14679 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14680 
14681 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_CELERRA_VNX, proto_nfs_celerra_vnx);
14682 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14683 
14684 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_GLUSTER, proto_nfs_gluster);
14685 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14686 
14687 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_DCACHE, proto_nfs_dcache);
14688 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14689 
14690 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_PRIMARY_DATA, proto_nfs_primary_data);
14691 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14692 
14693 	fhandle_handle = create_dissector_handle(dissect_fhandle_data_unknown, proto_nfs_unknown);
14694 	dissector_add_for_decode_as("nfs_fhandle.type", fhandle_handle);
14695 }
14696 
14697 /*
14698  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
14699  *
14700  * Local variables:
14701  * c-basic-offset: 8
14702  * tab-width: 8
14703  * indent-tabs-mode: t
14704  * End:
14705  *
14706  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
14707  * :indentSize=8:tabSize=8:noTabs=false:
14708  */
14709