2 * Routines for mount dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * Copied from packet-smb.c
10 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/exceptions.h>
17 #include <epan/to_str.h>
18 #include <epan/strutil.h>
20 #include <wsutil/array.h>
21 #include "packet-mount.h"
22 #include "packet-nfs.h"
24 void proto_register_mount(void);
25 void proto_reg_handoff_mount(void);
27 static int proto_mount
;
28 static int proto_sgi_mount
;
29 static int hf_mount_procedure_v1
;
30 static int hf_mount_procedure_v2
;
31 static int hf_mount_procedure_v3
;
32 static int hf_sgi_mount_procedure_v1
;
33 static int hf_mount_path
;
34 static int hf_mount3_status
;
35 static int hf_mount_mountlist_hostname
;
36 static int hf_mount_mountlist_directory
;
37 static int hf_mount_mountlist
;
38 static int hf_mount_groups_group
;
39 static int hf_mount_groups
;
40 static int hf_mount_exportlist_directory
;
41 static int hf_mount_exportlist
;
42 static int hf_mount_has_options
;
43 static int hf_mount_options
;
44 static int hf_mount_pathconf_link_max
;
45 static int hf_mount_pathconf_max_canon
;
46 static int hf_mount_pathconf_max_input
;
47 static int hf_mount_pathconf_name_max
;
48 static int hf_mount_pathconf_path_max
;
49 static int hf_mount_pathconf_pipe_buf
;
50 static int hf_mount_pathconf_vdisable
;
51 static int hf_mount_pathconf_mask
;
52 static int hf_mount_pathconf_error_all
;
53 static int hf_mount_pathconf_error_link_max
;
54 static int hf_mount_pathconf_error_max_canon
;
55 static int hf_mount_pathconf_error_max_input
;
56 static int hf_mount_pathconf_error_name_max
;
57 static int hf_mount_pathconf_error_path_max
;
58 static int hf_mount_pathconf_error_pipe_buf
;
59 static int hf_mount_pathconf_chown_restricted
;
60 static int hf_mount_pathconf_no_trunc
;
61 static int hf_mount_pathconf_error_vdisable
;
62 static int hf_mount_statvfs_bsize
;
63 static int hf_mount_statvfs_frsize
;
64 static int hf_mount_statvfs_blocks
;
65 static int hf_mount_statvfs_bfree
;
66 static int hf_mount_statvfs_bavail
;
67 static int hf_mount_statvfs_files
;
68 static int hf_mount_statvfs_ffree
;
69 static int hf_mount_statvfs_favail
;
70 static int hf_mount_statvfs_fsid
;
71 static int hf_mount_statvfs_basetype
;
72 static int hf_mount_statvfs_flag
;
73 static int hf_mount_statvfs_flag_rdonly
;
74 static int hf_mount_statvfs_flag_nosuid
;
75 static int hf_mount_statvfs_flag_notrunc
;
76 static int hf_mount_statvfs_flag_nodev
;
77 static int hf_mount_statvfs_flag_grpid
;
78 static int hf_mount_statvfs_flag_local
;
79 static int hf_mount_statvfs_namemax
;
80 static int hf_mount_statvfs_fstr
;
81 static int hf_mount_flavors
;
82 static int hf_mount_flavor
;
85 static int ett_mount_mountlist
;
86 static int ett_mount_groups
;
87 static int ett_mount_exportlist
;
88 static int ett_mount_pathconf_mask
;
89 static int ett_mount_statvfs_flag
;
91 /* RFC 1813, Page 107 */
92 static const value_string mount3_mountstat3
[] =
101 { 63, "ERR_NAMETOOLONG" },
102 { 10004, "ERR_NOTSUPP" },
103 { 10006, "ERR_SERVERFAULT" },
108 /* RFC 1094, Page 24 */
109 /* This function dissects fhstatus for v1 and v2 of the mount protocol.
110 * Formally, hf_mount3_status only define the status codes returned by version
112 * Though not formally defined in the standard, we use the same
113 * value-to-string mappings as version 3 since we believe that this mapping
114 * is consistent with most v1 and v2 implementations.
117 dissect_fhstatus(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, rpc_call_info_value
* civ
)
121 status
=tvb_get_ntohl(tvb
,offset
);
122 offset
= dissect_rpc_uint32(tvb
,tree
,hf_mount3_status
,offset
);
126 offset
= dissect_fhandle(tvb
,offset
,pinfo
,tree
,"fhandle", NULL
, civ
);
131 pinfo
->cinfo
, COL_INFO
, " Error:%s",
132 val_to_str(status
, mount3_mountstat3
,
133 "Unknown (0x%08X)"));
142 dissect_mount_dirpath_call(tvbuff_t
*tvb
, packet_info
*pinfo
,
143 proto_tree
*tree
, void* data
)
145 const char *mountpoint
=NULL
;
148 if((!pinfo
->fd
->visited
) && nfs_file_name_snooping
){
149 rpc_call_info_value
*civ
=(rpc_call_info_value
*)data
;
151 if(civ
->request
&& (civ
->proc
==1)){
154 len_field
= tvb_get_ntohl(tvb
, offset
);
155 if (len_field
< ITEM_LABEL_LENGTH
) {
157 int addr_len
, name_len
;
159 name
= address_to_str(pinfo
->pool
, &pinfo
->dst
);
160 addr_len
= (int)strlen(name
);
161 /* IP address, colon, path, terminating 0 */
162 name_len
= addr_len
+ 1 + len_field
+ 1;
164 name
= (char *)wmem_realloc(pinfo
->pool
,
165 (void *)name
, name_len
);
166 ptr
= name
+ addr_len
;
168 tvb_memcpy(tvb
, ptr
, offset
+4, len_field
);
172 nfs_name_snoop_add_name(civ
->xid
, tvb
, -1, name_len
, 0, 0, name
);
177 offset
= dissect_rpc_string(tvb
,tree
,hf_mount_path
,offset
,&mountpoint
);
178 col_append_fstr(pinfo
->cinfo
, COL_INFO
," %s", mountpoint
);
184 /* RFC 1094, Page 25,26 */
186 dissect_mount1_mnt_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
188 return dissect_fhstatus(tvb
,0,pinfo
,tree
,(rpc_call_info_value
*)data
);
193 /* RFC 1094, Page 26 */
194 /* RFC 1813, Page 110 */
196 dissect_mountlist(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
198 proto_item
* lock_item
;
199 proto_tree
* lock_tree
;
200 int old_offset
= offset
;
201 const char* hostname
;
202 const char* directory
;
204 lock_item
= proto_tree_add_item(tree
, hf_mount_mountlist
, tvb
,
207 lock_tree
= proto_item_add_subtree(lock_item
, ett_mount_mountlist
);
209 offset
= dissect_rpc_string(tvb
, lock_tree
,
210 hf_mount_mountlist_hostname
, offset
, &hostname
);
211 offset
= dissect_rpc_string(tvb
, lock_tree
,
212 hf_mount_mountlist_directory
, offset
, &directory
);
215 /* now we have a nicer string */
216 proto_item_set_text(lock_item
, "Mount List Entry: %s:%s", hostname
, directory
);
217 /* now we know, that mountlist is shorter */
218 proto_item_set_len(lock_item
, offset
- old_offset
);
225 /* RFC 1094, Page 26 */
226 /* RFC 1813, Page 110 */
228 dissect_mount_dump_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
230 return dissect_rpc_list(tvb
, pinfo
, tree
, 0,
231 dissect_mountlist
, NULL
);
236 /* RFC 1094, Page 26 */
237 /* RFC 1813, Page 110 */
239 dissect_group(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data
)
241 wmem_strbuf_t
*group_name_list
= (wmem_strbuf_t
*)data
;
242 const char *group_name
;
244 offset
= dissect_rpc_string(tvb
, tree
,
245 hf_mount_groups_group
, offset
, &group_name
);
246 if (wmem_strbuf_get_len(group_name_list
) != 0)
247 wmem_strbuf_append_c(group_name_list
, ' ');
248 wmem_strbuf_append(group_name_list
, group_name
);
254 /* RFC 1094, Page 26 */
255 /* RFC 1813, Page 113 */
257 dissect_exportlist(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
259 proto_item
* exportlist_item
= NULL
;
260 proto_tree
* exportlist_tree
= NULL
;
261 int old_offset
= offset
;
263 proto_item
* groups_item
= NULL
;
264 proto_item
* groups_tree
= NULL
;
265 const char* directory
;
266 wmem_strbuf_t
* group_name_list_strbuf
;
267 const char* group_name_list
;
270 exportlist_item
= proto_tree_add_item(tree
, hf_mount_exportlist
, tvb
, offset
, -1, ENC_NA
);
271 exportlist_tree
= proto_item_add_subtree(exportlist_item
, ett_mount_exportlist
);
274 offset
= dissect_rpc_string(tvb
, exportlist_tree
,
275 hf_mount_exportlist_directory
, offset
, &directory
);
276 groups_offset
= offset
;
278 groups_item
= proto_tree_add_item(exportlist_tree
, hf_mount_groups
, tvb
, offset
, -1, ENC_NA
);
279 groups_tree
= proto_item_add_subtree(groups_item
, ett_mount_groups
);
281 group_name_list_strbuf
= wmem_strbuf_new(pinfo
->pool
, "");
282 offset
= dissect_rpc_list(tvb
, pinfo
, groups_tree
, offset
,
283 dissect_group
, (void *)group_name_list_strbuf
);
285 /* mark empty lists */
286 if (offset
- groups_offset
== 4) {
287 proto_item_set_text(groups_item
, "Groups: empty");
290 /* now we know, that groups is shorter */
291 proto_item_set_len(groups_item
, offset
- groups_offset
);
294 group_name_list
= wmem_strbuf_finalize(group_name_list_strbuf
);
296 if (exportlist_item
) {
297 /* now we have a nicer string */
298 proto_item_set_text(exportlist_item
,
299 "Export List Entry: %s -> %s",
300 format_text(pinfo
->pool
, directory
, strlen(directory
)),
301 format_text(pinfo
->pool
, group_name_list
, strlen(group_name_list
)));
302 /* now we know, that exportlist is shorter */
303 proto_item_set_len(exportlist_item
, offset
- old_offset
);
310 /* RFC 1094, Page 26 */
311 /* RFC 1813, Page 113 */
313 dissect_mount_export_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
315 return dissect_rpc_list(tvb
, pinfo
, tree
, 0,
316 dissect_exportlist
, NULL
);
320 #define OFFS_MASK 32 /* offset of the "pc_mask" field */
322 #define PC_ERROR_ALL 0x0001
323 #define PC_ERROR_LINK_MAX 0x0002
324 #define PC_ERROR_MAX_CANON 0x0004
325 #define PC_ERROR_MAX_INPUT 0x0008
326 #define PC_ERROR_NAME_MAX 0x0010
327 #define PC_ERROR_PATH_MAX 0x0020
328 #define PC_ERROR_PIPE_BUF 0x0040
329 #define PC_CHOWN_RESTRICTED 0x0080
330 #define PC_NO_TRUNC 0x0100
331 #define PC_ERROR_VDISABLE 0x0200
333 static const true_false_string tos_error_all
= {
335 "Some or all info valid"
338 static const true_false_string tos_error_link_max
= {
343 static const true_false_string tos_error_max_canon
= {
348 static const true_false_string tos_error_max_input
= {
353 static const true_false_string tos_error_name_max
= {
358 static const true_false_string tos_error_path_max
= {
363 static const true_false_string tos_error_pipe_buf
= {
368 static const true_false_string tos_chown_restricted
= {
369 "Only a privileged user can change the ownership of a file",
370 "Users may give away their own files"
373 static const true_false_string tos_no_trunc
= {
374 "File names that are too long will get an error",
375 "File names that are too long will be truncated"
378 static const true_false_string tos_error_vdisable
= {
385 dissect_mount_pathconf_reply(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
388 static int * const flags
[] = {
389 &hf_mount_pathconf_error_all
,
390 &hf_mount_pathconf_error_link_max
,
391 &hf_mount_pathconf_error_max_canon
,
392 &hf_mount_pathconf_error_max_input
,
393 &hf_mount_pathconf_error_name_max
,
394 &hf_mount_pathconf_error_path_max
,
395 &hf_mount_pathconf_error_pipe_buf
,
396 &hf_mount_pathconf_chown_restricted
,
397 &hf_mount_pathconf_no_trunc
,
398 &hf_mount_pathconf_error_vdisable
,
404 * Extract the mask first, so we know which other fields the
405 * server was able to return to us.
407 pc_mask
= tvb_get_ntohl(tvb
, offset
+OFFS_MASK
) & 0xffff;
408 if (!(pc_mask
& (PC_ERROR_LINK_MAX
|PC_ERROR_ALL
))) {
409 dissect_rpc_uint32(tvb
,tree
,hf_mount_pathconf_link_max
,offset
);
413 if (!(pc_mask
& (PC_ERROR_MAX_CANON
|PC_ERROR_ALL
))) {
414 proto_tree_add_item(tree
,
415 hf_mount_pathconf_max_canon
,tvb
,offset
+2,2,
416 tvb_get_ntohs(tvb
,offset
)&0xffff);
420 if (!(pc_mask
& (PC_ERROR_MAX_INPUT
|PC_ERROR_ALL
))) {
421 proto_tree_add_item(tree
,
422 hf_mount_pathconf_max_input
,tvb
,offset
+2,2,
423 tvb_get_ntohs(tvb
,offset
)&0xffff);
427 if (!(pc_mask
& (PC_ERROR_NAME_MAX
|PC_ERROR_ALL
))) {
428 proto_tree_add_item(tree
,
429 hf_mount_pathconf_name_max
,tvb
,offset
+2,2,
430 tvb_get_ntohs(tvb
,offset
)&0xffff);
434 if (!(pc_mask
& (PC_ERROR_PATH_MAX
|PC_ERROR_ALL
))) {
435 proto_tree_add_item(tree
,
436 hf_mount_pathconf_path_max
,tvb
,offset
+2,2,
437 tvb_get_ntohs(tvb
,offset
)&0xffff);
441 if (!(pc_mask
& (PC_ERROR_PIPE_BUF
|PC_ERROR_ALL
))) {
442 proto_tree_add_item(tree
,
443 hf_mount_pathconf_pipe_buf
,tvb
,offset
+2,2,
444 tvb_get_ntohs(tvb
,offset
)&0xffff);
448 offset
+= 4; /* skip "pc_xxx" pad field */
450 if (!(pc_mask
& (PC_ERROR_VDISABLE
|PC_ERROR_ALL
))) {
451 proto_tree_add_item(tree
,
452 hf_mount_pathconf_vdisable
,tvb
,offset
+3,1,
453 tvb_get_ntohs(tvb
,offset
)&0xffff);
457 proto_tree_add_bitmask(tree
, tvb
, offset
+2, hf_mount_pathconf_mask
, ett_mount_pathconf_mask
, flags
, ENC_BIG_ENDIAN
);
464 /* RFC 1813, Page 107 */
466 dissect_mountstat3(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tree
, int offset
, int hfindex
, uint32_t *status
)
470 mountstat3
= tvb_get_ntohl(tvb
, offset
);
473 pinfo
->cinfo
, COL_INFO
, " Error:%s",
474 val_to_str(mountstat3
, mount3_mountstat3
,
475 "Unknown (0x%08X)"));
478 offset
= dissect_rpc_uint32(tvb
,tree
,hfindex
,offset
);
479 *status
= mountstat3
;
483 /* RFC 1831, Page 109 */
485 dissect_mount3_mnt_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
488 uint32_t auth_flavors
;
489 uint32_t auth_flavor
;
490 uint32_t auth_flavor_i
;
493 offset
= dissect_mountstat3(pinfo
,tvb
,tree
,offset
,hf_mount3_status
,&status
);
497 offset
= dissect_nfs3_fh(tvb
,offset
,pinfo
,tree
,"fhandle",NULL
,(rpc_call_info_value
*)data
);
499 auth_flavors
= tvb_get_ntohl(tvb
, offset
);
500 proto_tree_add_uint(tree
,hf_mount_flavors
, tvb
,
501 offset
, 4, auth_flavors
);
503 for (auth_flavor_i
= 0 ; auth_flavor_i
< auth_flavors
; auth_flavor_i
++) {
504 auth_flavor
= tvb_get_ntohl(tvb
, offset
);
505 proto_tree_add_uint(tree
,hf_mount_flavor
, tvb
,
506 offset
, 4, auth_flavor
);
519 dissect_sgi_exportlist(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
521 proto_item
* exportlist_item
= NULL
;
522 proto_tree
* exportlist_tree
= NULL
;
523 int old_offset
= offset
;
524 const char* directory
, *options
;
527 exportlist_item
= proto_tree_add_item(tree
, hf_mount_exportlist
,
528 tvb
, offset
, -1, ENC_NA
);
530 exportlist_tree
= proto_item_add_subtree(exportlist_item
,
531 ett_mount_exportlist
);
534 offset
= dissect_rpc_string(tvb
, exportlist_tree
,
535 hf_mount_exportlist_directory
, offset
, &directory
);
537 offset
= dissect_rpc_bool(tvb
, exportlist_tree
,
538 hf_mount_has_options
, offset
);
540 offset
= dissect_rpc_string(tvb
, exportlist_tree
, hf_mount_options
,
543 if (exportlist_item
) {
544 /* now we have a nicer string */
545 proto_item_set_text(exportlist_item
,
546 "Export List Entry: %s %s", directory
,
548 /* now we know, that exportlist is shorter */
549 proto_item_set_len(exportlist_item
, offset
- old_offset
);
556 dissect_mount_exportlist_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
558 return dissect_rpc_list(tvb
, pinfo
, tree
, 0,
559 dissect_sgi_exportlist
, NULL
);
562 #define ST_RDONLY 0x00000001
563 #define ST_NOSUID 0x00000002
564 #define ST_NOTRUNC 0x00000004
565 #define ST_NODEV 0x20000000
566 #define ST_GRPID 0x40000000
567 #define ST_LOCAL 0x80000000
569 static const true_false_string tos_st_rdonly
= {
570 "Read-only file system",
571 "Read/Write file system"
574 static const true_false_string tos_st_nosuid
= {
575 "Does not support setuid/setgid semantics",
576 "Supports setuid/setgid semantics"
579 static const true_false_string tos_st_notrunc
= {
580 "Does not truncate filenames longer than NAME_MAX",
581 "Truncates filenames longer than NAME_MAX"
584 static const true_false_string tos_st_nodev
= {
585 "Disallows opening of device files",
586 "Allows opening of device files"
589 static const true_false_string tos_st_grpid
= {
590 "Group ID assigned from directory",
591 "Group ID not assigned from directory"
594 static const true_false_string tos_st_local
= {
595 "File system is local",
596 "File system is not local"
600 dissect_mount_statvfs_reply(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
602 static int * const flags
[] = {
603 &hf_mount_statvfs_flag_rdonly
,
604 &hf_mount_statvfs_flag_nosuid
,
605 &hf_mount_statvfs_flag_notrunc
,
606 &hf_mount_statvfs_flag_nodev
,
607 &hf_mount_statvfs_flag_grpid
,
608 &hf_mount_statvfs_flag_local
,
613 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_bsize
, offset
);
616 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_frsize
, offset
);
619 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_blocks
, offset
);
622 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_bfree
, offset
);
625 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_bavail
, offset
);
628 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_files
, offset
);
631 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_ffree
, offset
);
634 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_favail
, offset
);
637 dissect_rpc_bytes(tvb
, tree
, hf_mount_statvfs_basetype
, offset
,
641 dissect_rpc_bytes(tvb
, tree
, hf_mount_statvfs_fstr
, offset
, 32, false, NULL
);
644 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_fsid
, offset
);
647 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_mount_statvfs_flag
, ett_mount_statvfs_flag
, flags
, ENC_BIG_ENDIAN
);
650 dissect_rpc_uint32(tvb
, tree
, hf_mount_statvfs_namemax
, offset
);
656 /* proc number, "proc name", dissect_request, dissect_reply */
658 /* Mount protocol version 1, RFC 1094 */
659 static const vsff mount1_proc
[] = {
661 dissect_rpc_void
, dissect_rpc_void
},
662 { MOUNTPROC_MNT
, "MNT",
663 dissect_mount_dirpath_call
, dissect_mount1_mnt_reply
},
664 { MOUNTPROC_DUMP
, "DUMP",
665 dissect_rpc_void
, dissect_mount_dump_reply
},
666 { MOUNTPROC_UMNT
, "UMNT",
667 dissect_mount_dirpath_call
, dissect_rpc_void
},
668 { MOUNTPROC_UMNTALL
, "UMNTALL",
669 dissect_rpc_void
, dissect_rpc_void
},
670 { MOUNTPROC_EXPORT
, "EXPORT",
671 dissect_rpc_void
, dissect_mount_export_reply
},
672 { MOUNTPROC_EXPORTALL
, "EXPORTALL",
673 dissect_rpc_void
, dissect_mount_export_reply
},
674 { 0, NULL
, NULL
, NULL
}
676 static const value_string mount1_proc_vals
[] = {
678 { MOUNTPROC_MNT
, "MNT" },
679 { MOUNTPROC_DUMP
, "DUMP" },
680 { MOUNTPROC_UMNT
, "UMNT" },
681 { MOUNTPROC_UMNTALL
, "UMNTALL" },
682 { MOUNTPROC_EXPORT
, "EXPORT" },
683 { MOUNTPROC_EXPORTALL
, "EXPORTALL" },
686 /* end of mount version 1 */
689 /* Mount protocol version 2, private communication from somebody at Sun;
690 mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
691 POSIX "pathconf()" call. */
692 static const vsff mount2_proc
[] = {
694 dissect_rpc_void
, dissect_rpc_void
},
695 { MOUNTPROC_MNT
, "MNT",
696 dissect_mount_dirpath_call
, dissect_mount1_mnt_reply
},
697 { MOUNTPROC_DUMP
, "DUMP",
698 dissect_rpc_void
, dissect_mount_dump_reply
},
699 { MOUNTPROC_UMNT
, "UMNT",
700 dissect_mount_dirpath_call
, dissect_rpc_void
},
701 { MOUNTPROC_UMNTALL
, "UMNTALL",
702 dissect_rpc_void
, dissect_rpc_void
},
703 { MOUNTPROC_EXPORT
, "EXPORT",
704 dissect_rpc_void
, dissect_mount_export_reply
},
705 { MOUNTPROC_EXPORTALL
, "EXPORTALL",
706 dissect_rpc_void
, dissect_mount_export_reply
},
707 { MOUNTPROC_PATHCONF
, "PATHCONF",
708 dissect_mount_dirpath_call
, dissect_mount_pathconf_reply
},
709 { 0, NULL
, NULL
, NULL
}
711 static const value_string mount2_proc_vals
[] = {
713 { MOUNTPROC_MNT
, "MNT" },
714 { MOUNTPROC_DUMP
, "DUMP" },
715 { MOUNTPROC_UMNT
, "UMNT" },
716 { MOUNTPROC_UMNTALL
, "UMNTALL" },
717 { MOUNTPROC_EXPORT
, "EXPORT" },
718 { MOUNTPROC_EXPORTALL
, "EXPORTALL" },
719 { MOUNTPROC_PATHCONF
, "PATHCONF" },
722 /* end of mount version 2 */
725 /* Mount protocol version 3, RFC 1813 */
726 static const vsff mount3_proc
[] = {
728 dissect_rpc_void
, dissect_rpc_void
},
729 { MOUNTPROC_MNT
, "MNT",
730 dissect_mount_dirpath_call
, dissect_mount3_mnt_reply
},
731 { MOUNTPROC_DUMP
, "DUMP",
732 dissect_rpc_void
, dissect_mount_dump_reply
},
733 { MOUNTPROC_UMNT
, "UMNT",
734 dissect_mount_dirpath_call
, dissect_rpc_void
},
735 { MOUNTPROC_UMNTALL
, "UMNTALL",
736 dissect_rpc_void
, dissect_rpc_void
},
737 { MOUNTPROC_EXPORT
, "EXPORT",
738 dissect_rpc_void
, dissect_mount_export_reply
},
739 { 0, NULL
, NULL
, NULL
}
741 static const value_string mount3_proc_vals
[] = {
743 { MOUNTPROC_MNT
, "MNT" },
744 { MOUNTPROC_DUMP
, "DUMP" },
745 { MOUNTPROC_UMNT
, "UMNT" },
746 { MOUNTPROC_UMNTALL
, "UMNTALL" },
747 { MOUNTPROC_EXPORT
, "EXPORT" },
750 /* end of Mount protocol version 3 */
752 static const rpc_prog_vers_info mount_vers_info
[] = {
753 { 1, mount1_proc
, &hf_mount_procedure_v1
},
754 { 2, mount2_proc
, &hf_mount_procedure_v2
},
755 { 3, mount3_proc
, &hf_mount_procedure_v3
},
758 /* SGI mount protocol version 1; actually the same as v1 plus
759 MOUNTPROC_EXPORTLIST and MOUNTPROC_STATVFS */
761 static const vsff sgi_mount1_proc
[] = {
763 dissect_rpc_void
, dissect_rpc_void
},
764 { MOUNTPROC_MNT
, "MNT",
765 dissect_mount_dirpath_call
, dissect_mount1_mnt_reply
},
766 { MOUNTPROC_DUMP
, "DUMP",
767 dissect_rpc_void
, dissect_mount_dump_reply
},
768 { MOUNTPROC_UMNT
, "UMNT",
769 dissect_mount_dirpath_call
, dissect_rpc_void
},
770 { MOUNTPROC_UMNTALL
, "UMNTALL",
771 dissect_rpc_void
, dissect_rpc_void
},
772 { MOUNTPROC_EXPORT
, "EXPORT",
773 dissect_rpc_void
, dissect_mount_export_reply
},
774 { MOUNTPROC_EXPORTALL
, "EXPORTALL",
775 dissect_rpc_void
, dissect_mount_export_reply
},
776 { MOUNTPROC_EXPORTLIST
,"EXPORTLIST",
777 dissect_rpc_void
, dissect_mount_exportlist_reply
},
778 { MOUNTPROC_STATVFS
, "STATVFS",
779 dissect_mount_dirpath_call
, dissect_mount_statvfs_reply
},
780 { 0, NULL
, NULL
, NULL
}
782 static const value_string sgi_mount1_proc_vals
[] = {
784 { MOUNTPROC_MNT
, "MNT" },
785 { MOUNTPROC_DUMP
, "DUMP" },
786 { MOUNTPROC_UMNT
, "UMNT" },
787 { MOUNTPROC_UMNTALL
, "UMNTALL" },
788 { MOUNTPROC_EXPORT
, "EXPORT" },
789 { MOUNTPROC_EXPORTALL
, "EXPORTALL" },
790 { MOUNTPROC_EXPORTLIST
, "EXPORTLIST" },
791 { MOUNTPROC_STATVFS
, "STATVFS" },
794 /* end of SGI mount protocol version 1 */
796 static const rpc_prog_vers_info sgi_mount_vers_info
[] = {
797 { 1, sgi_mount1_proc
, &hf_sgi_mount_procedure_v1
},
801 proto_register_mount(void)
803 static hf_register_info hf
[] = {
804 { &hf_mount_procedure_v1
, {
805 "V1 Procedure", "mount.procedure_v1", FT_UINT32
, BASE_DEC
,
806 VALS(mount1_proc_vals
), 0, NULL
, HFILL
}},
807 { &hf_mount_procedure_v2
, {
808 "V2 Procedure", "mount.procedure_v2", FT_UINT32
, BASE_DEC
,
809 VALS(mount2_proc_vals
), 0, NULL
, HFILL
}},
810 { &hf_mount_procedure_v3
, {
811 "V3 Procedure", "mount.procedure_v3", FT_UINT32
, BASE_DEC
,
812 VALS(mount3_proc_vals
), 0, NULL
, HFILL
}},
813 { &hf_sgi_mount_procedure_v1
, {
814 "SGI V1 procedure", "mount.procedure_sgi_v1", FT_UINT32
, BASE_DEC
,
815 VALS(sgi_mount1_proc_vals
), 0, NULL
, HFILL
}},
817 "Path", "mount.path", FT_STRING
, BASE_NONE
,
818 NULL
, 0, NULL
, HFILL
}},
819 { &hf_mount3_status
, {
820 "Status", "mount.status", FT_UINT32
, BASE_DEC
,
821 VALS(mount3_mountstat3
), 0, NULL
, HFILL
}},
822 { &hf_mount_mountlist_hostname
, {
823 "Hostname", "mount.dump.hostname", FT_STRING
, BASE_NONE
,
824 NULL
, 0, NULL
, HFILL
}},
825 { &hf_mount_mountlist_directory
, {
826 "Directory", "mount.dump.directory", FT_STRING
, BASE_NONE
,
827 NULL
, 0, NULL
, HFILL
}},
828 { &hf_mount_mountlist
, {
829 "Mount List Entry", "mount.dump.entry", FT_NONE
, BASE_NONE
,
830 NULL
, 0, NULL
, HFILL
}},
831 { &hf_mount_groups_group
, {
832 "Group", "mount.export.group", FT_STRING
, BASE_NONE
,
833 NULL
, 0, NULL
, HFILL
}},
834 { &hf_mount_groups
, {
835 "Groups", "mount.export.groups", FT_NONE
, BASE_NONE
,
836 NULL
, 0, NULL
, HFILL
}},
837 { &hf_mount_has_options
, {
838 "Has options", "mount.export.has_options", FT_UINT32
,
839 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
840 { &hf_mount_options
, {
841 "Options", "mount.export.options", FT_STRING
, BASE_NONE
,
842 NULL
, 0, NULL
, HFILL
}},
843 { &hf_mount_exportlist_directory
, {
844 "Directory", "mount.export.directory", FT_STRING
, BASE_NONE
,
845 NULL
, 0, NULL
, HFILL
}},
846 { &hf_mount_exportlist
, {
847 "Export List Entry", "mount.export.entry", FT_NONE
, BASE_NONE
,
848 NULL
, 0, NULL
, HFILL
}},
849 { &hf_mount_pathconf_link_max
, {
850 "Maximum number of links to a file", "mount.pathconf.link_max",
852 NULL
, 0, "Maximum number of links allowed to a file", HFILL
}},
853 { &hf_mount_pathconf_max_canon
, {
854 "Maximum terminal input line length", "mount.pathconf.max_canon",
856 NULL
, 0, "Max tty input line length", HFILL
}},
857 { &hf_mount_pathconf_max_input
, {
858 "Terminal input buffer size", "mount.pathconf.max_input",
860 NULL
, 0, NULL
, HFILL
}},
861 { &hf_mount_pathconf_name_max
, {
862 "Maximum file name length", "mount.pathconf.name_max",
864 NULL
, 0, NULL
, HFILL
}},
865 { &hf_mount_pathconf_path_max
, {
866 "Maximum path name length", "mount.pathconf.path_max",
868 NULL
, 0, NULL
, HFILL
}},
869 { &hf_mount_pathconf_pipe_buf
, {
870 "Pipe buffer size", "mount.pathconf.pipe_buf",
872 NULL
, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL
}},
873 { &hf_mount_pathconf_vdisable
, {
874 "VDISABLE character", "mount.pathconf.vdisable_char",
876 NULL
, 0, "Character value to disable a terminal special character", HFILL
}},
877 { &hf_mount_pathconf_mask
, {
878 "Reply error/status bits", "mount.pathconf.mask",
880 NULL
, 0, "Bit mask with error and status bits", HFILL
}},
881 { &hf_mount_pathconf_error_all
, {
882 "ERROR_ALL", "mount.pathconf.mask.error_all",
883 FT_BOOLEAN
, 16, TFS(&tos_error_all
),
884 PC_ERROR_ALL
, NULL
, HFILL
}},
885 { &hf_mount_pathconf_error_link_max
, {
886 "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
887 FT_BOOLEAN
, 16, TFS(&tos_error_link_max
),
888 PC_ERROR_LINK_MAX
, NULL
, HFILL
}},
889 { &hf_mount_pathconf_error_max_canon
, {
890 "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
891 FT_BOOLEAN
, 16, TFS(&tos_error_max_canon
),
892 PC_ERROR_MAX_CANON
, NULL
, HFILL
}},
893 { &hf_mount_pathconf_error_max_input
, {
894 "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
895 FT_BOOLEAN
, 16, TFS(&tos_error_max_input
),
896 PC_ERROR_MAX_INPUT
, NULL
, HFILL
}},
897 { &hf_mount_pathconf_error_name_max
, {
898 "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
899 FT_BOOLEAN
, 16, TFS(&tos_error_name_max
),
900 PC_ERROR_NAME_MAX
, NULL
, HFILL
}},
901 { &hf_mount_pathconf_error_path_max
, {
902 "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
903 FT_BOOLEAN
, 16, TFS(&tos_error_path_max
),
904 PC_ERROR_PATH_MAX
, NULL
, HFILL
}},
905 { &hf_mount_pathconf_error_pipe_buf
, {
906 "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
907 FT_BOOLEAN
, 16, TFS(&tos_error_pipe_buf
),
908 PC_ERROR_PIPE_BUF
, NULL
, HFILL
}},
909 { &hf_mount_pathconf_chown_restricted
, {
910 "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
911 FT_BOOLEAN
, 16, TFS(&tos_chown_restricted
),
912 PC_CHOWN_RESTRICTED
, NULL
, HFILL
}},
913 { &hf_mount_pathconf_no_trunc
, {
914 "NO_TRUNC", "mount.pathconf.mask.no_trunc",
915 FT_BOOLEAN
, 16, TFS(&tos_no_trunc
),
916 PC_NO_TRUNC
, NULL
, HFILL
}},
917 { &hf_mount_pathconf_error_vdisable
, {
918 "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
919 FT_BOOLEAN
, 16, TFS(&tos_error_vdisable
),
920 PC_ERROR_VDISABLE
, NULL
, HFILL
}},
921 { &hf_mount_statvfs_bsize
, {
922 "Block size", "mount.statvfs.f_bsize",
923 FT_UINT32
, BASE_DEC
, NULL
, 0,
924 "File system block size", HFILL
}},
925 { &hf_mount_statvfs_frsize
, {
926 "Fragment size", "mount.statvfs.f_frsize",
927 FT_UINT32
, BASE_DEC
, NULL
, 0,
928 "File system fragment size", HFILL
}},
929 { &hf_mount_statvfs_blocks
, {
930 "Blocks", "mount.statvfs.f_blocks",
931 FT_UINT32
, BASE_DEC
, NULL
, 0,
932 "Total fragment sized blocks", HFILL
}},
933 { &hf_mount_statvfs_bfree
, {
934 "Blocks Free", "mount.statvfs.f_bfree",
935 FT_UINT32
, BASE_DEC
, NULL
, 0,
936 "Free fragment sized blocks", HFILL
}},
937 { &hf_mount_statvfs_bavail
, {
938 "Blocks Available", "mount.statvfs.f_bavail",
939 FT_UINT32
, BASE_DEC
, NULL
, 0,
940 "Available fragment sized blocks", HFILL
}},
941 { &hf_mount_statvfs_files
, {
942 "Files", "mount.statvfs.f_files",
943 FT_UINT32
, BASE_DEC
, NULL
, 0,
944 "Total files/inodes", HFILL
}},
945 { &hf_mount_statvfs_ffree
, {
946 "Files Free", "mount.statvfs.f_ffree",
947 FT_UINT32
, BASE_DEC
, NULL
, 0,
948 "Free files/inodes", HFILL
}},
949 { &hf_mount_statvfs_favail
, {
950 "Files Available", "mount.statvfs.f_favail",
951 FT_UINT32
, BASE_DEC
, NULL
, 0,
952 "Available files/inodes", HFILL
}},
953 { &hf_mount_statvfs_fsid
, {
954 "File system ID", "mount.statvfs.f_fsid",
955 FT_UINT32
, BASE_DEC
, NULL
, 0,
956 "File system identifier", HFILL
}},
957 { &hf_mount_statvfs_basetype
, {
958 "Type", "mount.statvfs.f_basetype",
959 FT_STRING
, BASE_NONE
, NULL
, 0,
960 "File system type", HFILL
}},
961 { &hf_mount_statvfs_flag
, {
962 "Flags", "mount.statvfs.f_flag",
963 FT_UINT32
, BASE_HEX
, NULL
, 0,
964 "Flags bit-mask", HFILL
}},
965 { &hf_mount_statvfs_flag_rdonly
, {
966 "ST_RDONLY", "mount.statvfs.f_flag.st_rdonly",
967 FT_BOOLEAN
, 32, TFS(&tos_st_rdonly
), ST_RDONLY
,
969 { &hf_mount_statvfs_flag_nosuid
, {
970 "ST_NOSUID", "mount.statvfs.f_flag.st_nosuid",
971 FT_BOOLEAN
, 32, TFS(&tos_st_nosuid
), ST_NOSUID
,
973 { &hf_mount_statvfs_flag_notrunc
, {
974 "ST_NOTRUNC", "mount.statvfs.f_flag.st_notrunc",
975 FT_BOOLEAN
, 32, TFS(&tos_st_notrunc
), ST_NOTRUNC
,
977 { &hf_mount_statvfs_flag_nodev
, {
978 "ST_NODEV", "mount.statvfs.f_flag.st_nodev",
979 FT_BOOLEAN
, 32, TFS(&tos_st_nodev
), ST_NODEV
,
981 { &hf_mount_statvfs_flag_grpid
, {
982 "ST_GRPID", "mount.statvfs.f_flag.st_grpid",
983 FT_BOOLEAN
, 32, TFS(&tos_st_grpid
), ST_GRPID
,
985 { &hf_mount_statvfs_flag_local
, {
986 "ST_LOCAL", "mount.statvfs.f_flag.st_local",
987 FT_BOOLEAN
, 32, TFS(&tos_st_local
), ST_LOCAL
,
989 { &hf_mount_statvfs_namemax
, {
990 "Maximum file name length", "mount.statvfs.f_namemax",
991 FT_UINT32
, BASE_DEC
, NULL
, 0,
993 { &hf_mount_statvfs_fstr
, {
994 "File system specific string", "mount.statvfs.f_fstr",
995 FT_BYTES
, BASE_NONE
, NULL
, 0,
997 { &hf_mount_flavors
, {
998 "Flavors", "mount.flavors", FT_UINT32
, BASE_DEC
,
999 NULL
, 0, NULL
, HFILL
}},
1000 { &hf_mount_flavor
, {
1001 "Flavor", "mount.flavor", FT_UINT32
, BASE_DEC
,
1002 VALS(rpc_auth_flavor
), 0, NULL
, HFILL
}},
1004 static int *ett
[] = {
1006 &ett_mount_mountlist
,
1008 &ett_mount_exportlist
,
1009 &ett_mount_pathconf_mask
,
1010 &ett_mount_statvfs_flag
,
1013 proto_mount
= proto_register_protocol("Mount Service", "MOUNT",
1015 proto_sgi_mount
= proto_register_protocol("SGI Mount Service",
1016 "SGI MOUNT", "sgimount");
1017 proto_register_field_array(proto_mount
, hf
, array_length(hf
));
1018 proto_register_subtree_array(ett
, array_length(ett
));
1022 proto_reg_handoff_mount(void)
1024 /* Register the protocols as RPC */
1025 rpc_init_prog(proto_mount
, MOUNT_PROGRAM
, ett_mount
,
1026 G_N_ELEMENTS(mount_vers_info
), mount_vers_info
);
1027 rpc_init_prog(proto_sgi_mount
, SGI_MOUNT_PROGRAM
, ett_mount
,
1028 G_N_ELEMENTS(sgi_mount_vers_info
), sgi_mount_vers_info
);
1032 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1037 * indent-tabs-mode: t
1040 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1041 * :indentSize=8:tabSize=8:noTabs=false: