HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-mount.c
blobae2d6fa0c6b0bf1983f5e8940760f948d6156502
1 /* packet-mount.c
2 * Routines for mount dissection
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copied from packet-smb.c
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <string.h>
31 #include <epan/exceptions.h>
32 #include <epan/to_str.h>
33 #include "packet-rpc.h"
34 #include "packet-mount.h"
35 #include "packet-nfs.h"
39 static int proto_mount = -1;
40 static int proto_sgi_mount = -1;
41 static int hf_mount_procedure_v1 = -1;
42 static int hf_mount_procedure_v2 = -1;
43 static int hf_mount_procedure_v3 = -1;
44 static int hf_sgi_mount_procedure_v1 = -1;
45 static int hf_mount_path = -1;
46 static int hf_mount3_status = -1;
47 static int hf_mount_mountlist_hostname = -1;
48 static int hf_mount_mountlist_directory = -1;
49 static int hf_mount_mountlist = -1;
50 static int hf_mount_groups_group = -1;
51 static int hf_mount_groups = -1;
52 static int hf_mount_exportlist_directory = -1;
53 static int hf_mount_exportlist = -1;
54 static int hf_mount_has_options = -1;
55 static int hf_mount_options = -1;
56 static int hf_mount_pathconf_link_max = -1;
57 static int hf_mount_pathconf_max_canon = -1;
58 static int hf_mount_pathconf_max_input = -1;
59 static int hf_mount_pathconf_name_max = -1;
60 static int hf_mount_pathconf_path_max = -1;
61 static int hf_mount_pathconf_pipe_buf = -1;
62 static int hf_mount_pathconf_vdisable = -1;
63 static int hf_mount_pathconf_mask = -1;
64 static int hf_mount_pathconf_error_all = -1;
65 static int hf_mount_pathconf_error_link_max = -1;
66 static int hf_mount_pathconf_error_max_canon = -1;
67 static int hf_mount_pathconf_error_max_input = -1;
68 static int hf_mount_pathconf_error_name_max = -1;
69 static int hf_mount_pathconf_error_path_max = -1;
70 static int hf_mount_pathconf_error_pipe_buf = -1;
71 static int hf_mount_pathconf_chown_restricted = -1;
72 static int hf_mount_pathconf_no_trunc = -1;
73 static int hf_mount_pathconf_error_vdisable = -1;
74 static int hf_mount_statvfs_bsize = -1;
75 static int hf_mount_statvfs_frsize = -1;
76 static int hf_mount_statvfs_blocks = -1;
77 static int hf_mount_statvfs_bfree = -1;
78 static int hf_mount_statvfs_bavail = -1;
79 static int hf_mount_statvfs_files = -1;
80 static int hf_mount_statvfs_ffree = -1;
81 static int hf_mount_statvfs_favail = -1;
82 static int hf_mount_statvfs_fsid = -1;
83 static int hf_mount_statvfs_basetype = -1;
84 static int hf_mount_statvfs_flag = -1;
85 static int hf_mount_statvfs_flag_rdonly = -1;
86 static int hf_mount_statvfs_flag_nosuid = -1;
87 static int hf_mount_statvfs_flag_notrunc = -1;
88 static int hf_mount_statvfs_flag_nodev = -1;
89 static int hf_mount_statvfs_flag_grpid = -1;
90 static int hf_mount_statvfs_flag_local = -1;
91 static int hf_mount_statvfs_namemax = -1;
92 static int hf_mount_statvfs_fstr = -1;
93 static int hf_mount_flavors = -1;
94 static int hf_mount_flavor = -1;
96 static gint ett_mount = -1;
97 static gint ett_mount_mountlist = -1;
98 static gint ett_mount_groups = -1;
99 static gint ett_mount_exportlist = -1;
100 static gint ett_mount_pathconf_mask = -1;
101 static gint ett_mount_statvfs_flag = -1;
103 #define MAX_GROUP_NAME_LIST 128
104 static char group_name_list[MAX_GROUP_NAME_LIST];
105 static int group_names_len;
107 /* RFC 1813, Page 107 */
108 static const value_string mount3_mountstat3[] =
110 { 0, "OK" },
111 { 1, "ERR_PERM" },
112 { 2, "ERR_NOENT" },
113 { 5, "ERR_IO" },
114 { 13, "ERR_ACCESS" },
115 { 20, "ERR_NOTDIR" },
116 { 22, "ERR_INVAL" },
117 { 63, "ERR_NAMETOOLONG" },
118 { 10004, "ERR_NOTSUPP" },
119 { 10006, "ERR_SERVERFAULT" },
120 { 0, NULL }
124 /* RFC 1094, Page 24 */
125 /* This function dissects fhstatus for v1 and v2 of the mount protocol.
126 * Formally, hf_mount3_status only define the status codes returned by version
127 * 3 of the protocol.
128 * Though not formally defined in the standard, we use the same
129 * value-to-string mappings as version 3 since we belive that this mapping
130 * is consistant with most v1 and v2 implementations.
132 static int
133 dissect_fhstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value* civ)
135 gint32 status;
137 status=tvb_get_ntohl(tvb,offset);
138 offset = dissect_rpc_uint32(tvb,tree,hf_mount3_status,offset);
140 switch (status) {
141 case 0:
142 offset = dissect_fhandle(tvb,offset,pinfo,tree,"fhandle", NULL, civ);
143 break;
144 default:
145 /* void */
146 col_append_fstr(
147 pinfo->cinfo, COL_INFO, " Error:%s",
148 val_to_str(status, mount3_mountstat3,
149 "Unknown (0x%08X)"));
150 break;
153 return offset;
157 static int
158 dissect_mount_dirpath_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
159 proto_tree *tree, void* data)
161 const char *mountpoint=NULL;
163 if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
164 rpc_call_info_value *civ=(rpc_call_info_value *)data;
166 if(civ->request && (civ->proc==1)){
167 const gchar *host;
168 unsigned char *name;
169 guint32 len;
170 unsigned char *ptr;
172 host=ip_to_str((guint8 *)pinfo->dst.data);
173 len=tvb_get_ntohl(tvb, offset);
174 if (len >= ITEM_LABEL_LENGTH)
175 THROW(ReportedBoundsError);
177 name=(unsigned char *)g_malloc(strlen(host)+1+len+1+200);
178 ptr=name;
179 memcpy(ptr, host, strlen(host));
180 ptr+=strlen(host);
181 *ptr++=':';
182 tvb_memcpy(tvb, ptr, offset+4, len);
183 ptr+=len;
184 *ptr=0;
186 nfs_name_snoop_add_name(civ->xid, tvb, -1, (gint)strlen(name), 0, 0, name);
190 offset = dissect_rpc_string(tvb,tree,hf_mount_path,offset,&mountpoint);
191 col_append_fstr(pinfo->cinfo, COL_INFO," %s", mountpoint);
193 return offset;
197 /* RFC 1094, Page 25,26 */
198 static int
199 dissect_mount1_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data)
201 offset = dissect_fhstatus(tvb,offset,pinfo,tree,(rpc_call_info_value*)data);
203 return offset;
208 /* RFC 1094, Page 26 */
209 /* RFC 1813, Page 110 */
210 static int
211 dissect_mountlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
213 proto_item* lock_item = NULL;
214 proto_tree* lock_tree = NULL;
215 int old_offset = offset;
216 const char* hostname;
217 const char* directory;
219 if (tree) {
220 lock_item = proto_tree_add_item(tree, hf_mount_mountlist, tvb,
221 offset, -1, ENC_NA);
222 if (lock_item)
223 lock_tree = proto_item_add_subtree(lock_item, ett_mount_mountlist);
226 offset = dissect_rpc_string(tvb, lock_tree,
227 hf_mount_mountlist_hostname, offset, &hostname);
228 offset = dissect_rpc_string(tvb, lock_tree,
229 hf_mount_mountlist_directory, offset, &directory);
231 if (lock_item) {
232 /* now we have a nicer string */
233 proto_item_set_text(lock_item, "Mount List Entry: %s:%s", hostname, directory);
234 /* now we know, that mountlist is shorter */
235 proto_item_set_len(lock_item, offset - old_offset);
238 return offset;
242 /* RFC 1094, Page 26 */
243 /* RFC 1813, Page 110 */
244 static int
245 dissect_mount_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data _U_)
247 offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_mountlist);
249 return offset;
254 /* RFC 1094, Page 26 */
255 /* RFC 1813, Page 110 */
256 static int
257 dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
259 int str_len;
261 if (group_names_len < MAX_GROUP_NAME_LIST - 5) {
262 str_len=tvb_get_nstringz(tvb,offset+4,
263 MAX_GROUP_NAME_LIST-5-group_names_len,
264 group_name_list+group_names_len);
265 if((group_names_len>=(MAX_GROUP_NAME_LIST-5))||(str_len<0)){
266 g_snprintf(group_name_list+(MAX_GROUP_NAME_LIST-5), 5, "...");
267 group_names_len=MAX_GROUP_NAME_LIST - 1;
268 } else {
269 group_names_len+=str_len;
270 group_name_list[group_names_len++]=' ';
272 group_name_list[group_names_len]=0;
275 offset = dissect_rpc_string(tvb, tree,
276 hf_mount_groups_group, offset, NULL);
278 return offset;
282 /* RFC 1094, Page 26 */
283 /* RFC 1813, Page 113 */
284 static int
285 dissect_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data _U_)
287 proto_item* exportlist_item = NULL;
288 proto_tree* exportlist_tree = NULL;
289 int old_offset = offset;
290 int groups_offset;
291 proto_item* groups_item = NULL;
292 proto_item* groups_tree = NULL;
293 const char* directory;
295 group_name_list[0]=0;
296 group_names_len=0;
297 if (tree) {
298 exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, tvb, offset, -1, ENC_NA);
299 exportlist_tree = proto_item_add_subtree(exportlist_item, ett_mount_exportlist);
302 offset = dissect_rpc_string(tvb, exportlist_tree,
303 hf_mount_exportlist_directory, offset, &directory);
304 groups_offset = offset;
306 if (tree) {
307 groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, tvb,
308 offset, -1, ENC_NA);
309 if (groups_item)
310 groups_tree = proto_item_add_subtree(groups_item, ett_mount_groups);
313 offset = dissect_rpc_list(tvb, pinfo, groups_tree, offset, dissect_group);
314 if (groups_item) {
315 /* mark empty lists */
316 if (offset - groups_offset == 4) {
317 proto_item_set_text(groups_item, "Groups: empty");
320 /* now we know, that groups is shorter */
321 proto_item_set_len(groups_item, offset - groups_offset);
324 if (exportlist_item) {
325 /* now we have a nicer string */
326 proto_item_set_text(exportlist_item, "Export List Entry: %s -> %s", directory,group_name_list);
327 /* now we know, that exportlist is shorter */
328 proto_item_set_len(exportlist_item, offset - old_offset);
331 return offset;
335 /* RFC 1094, Page 26 */
336 /* RFC 1813, Page 113 */
337 static int
338 dissect_mount_export_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data _U_)
340 offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_exportlist);
342 return offset;
346 #define OFFS_MASK 32 /* offset of the "pc_mask" field */
348 #define PC_ERROR_ALL 0x0001
349 #define PC_ERROR_LINK_MAX 0x0002
350 #define PC_ERROR_MAX_CANON 0x0004
351 #define PC_ERROR_MAX_INPUT 0x0008
352 #define PC_ERROR_NAME_MAX 0x0010
353 #define PC_ERROR_PATH_MAX 0x0020
354 #define PC_ERROR_PIPE_BUF 0x0040
355 #define PC_CHOWN_RESTRICTED 0x0080
356 #define PC_NO_TRUNC 0x0100
357 #define PC_ERROR_VDISABLE 0x0200
359 static const true_false_string tos_error_all = {
360 "All info invalid",
361 "Some or all info valid"
364 static const true_false_string tos_error_link_max = {
365 "LINK_MAX invalid",
366 "LINK_MAX valid"
369 static const true_false_string tos_error_max_canon = {
370 "MAX_CANON invalid",
371 "MAX_CANON valid"
374 static const true_false_string tos_error_max_input = {
375 "MAX_INPUT invalid",
376 "MAX_INPUT valid"
379 static const true_false_string tos_error_name_max = {
380 "NAME_MAX invalid",
381 "NAME_MAX valid"
384 static const true_false_string tos_error_path_max = {
385 "PATH_MAX invalid",
386 "PATH_MAX valid"
389 static const true_false_string tos_error_pipe_buf = {
390 "PIPE_BUF invalid",
391 "PIPE_BUF valid"
394 static const true_false_string tos_chown_restricted = {
395 "Only a privileged user can change the ownership of a file",
396 "Users may give away their own files"
399 static const true_false_string tos_no_trunc = {
400 "File names that are too long will get an error",
401 "File names that are too long will be truncated"
404 static const true_false_string tos_error_vdisable = {
405 "VDISABLE invalid",
406 "VDISABLE valid"
410 static int
411 dissect_mount_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
413 guint32 pc_mask;
414 proto_item *lock_item;
415 proto_tree *lock_tree;
418 * Extract the mask first, so we know which other fields the
419 * server was able to return to us.
421 pc_mask = tvb_get_ntohl(tvb, offset+OFFS_MASK) & 0xffff;
422 if (!(pc_mask & (PC_ERROR_LINK_MAX|PC_ERROR_ALL))) {
423 if (tree) {
424 dissect_rpc_uint32(tvb,tree,hf_mount_pathconf_link_max,offset);
427 offset += 4;
429 if (!(pc_mask & (PC_ERROR_MAX_CANON|PC_ERROR_ALL))) {
430 if (tree) {
431 proto_tree_add_item(tree,
432 hf_mount_pathconf_max_canon,tvb,offset+2,2,
433 tvb_get_ntohs(tvb,offset)&0xffff);
436 offset += 4;
438 if (!(pc_mask & (PC_ERROR_MAX_INPUT|PC_ERROR_ALL))) {
439 if (tree) {
440 proto_tree_add_item(tree,
441 hf_mount_pathconf_max_input,tvb,offset+2,2,
442 tvb_get_ntohs(tvb,offset)&0xffff);
445 offset += 4;
447 if (!(pc_mask & (PC_ERROR_NAME_MAX|PC_ERROR_ALL))) {
448 if (tree) {
449 proto_tree_add_item(tree,
450 hf_mount_pathconf_name_max,tvb,offset+2,2,
451 tvb_get_ntohs(tvb,offset)&0xffff);
454 offset += 4;
456 if (!(pc_mask & (PC_ERROR_PATH_MAX|PC_ERROR_ALL))) {
457 if (tree) {
458 proto_tree_add_item(tree,
459 hf_mount_pathconf_path_max,tvb,offset+2,2,
460 tvb_get_ntohs(tvb,offset)&0xffff);
463 offset += 4;
465 if (!(pc_mask & (PC_ERROR_PIPE_BUF|PC_ERROR_ALL))) {
466 if (tree) {
467 proto_tree_add_item(tree,
468 hf_mount_pathconf_pipe_buf,tvb,offset+2,2,
469 tvb_get_ntohs(tvb,offset)&0xffff);
472 offset += 4;
474 offset += 4; /* skip "pc_xxx" pad field */
476 if (!(pc_mask & (PC_ERROR_VDISABLE|PC_ERROR_ALL))) {
477 if (tree) {
478 proto_tree_add_item(tree,
479 hf_mount_pathconf_vdisable,tvb,offset+3,1,
480 tvb_get_ntohs(tvb,offset)&0xffff);
483 offset += 4;
486 if (tree) {
487 lock_item = proto_tree_add_item(tree, hf_mount_pathconf_mask, tvb,
488 offset+2, 2, ENC_BIG_ENDIAN);
490 lock_tree = proto_item_add_subtree(lock_item, ett_mount_pathconf_mask);
491 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_all, tvb,
492 offset + 2, 2, pc_mask);
494 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_link_max, tvb,
495 offset + 2, 2, pc_mask);
496 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_canon, tvb,
497 offset + 2, 2, pc_mask);
498 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_input, tvb,
499 offset + 2, 2, pc_mask);
500 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_name_max, tvb,
501 offset + 2, 2, pc_mask);
502 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_path_max, tvb,
503 offset + 2, 2, pc_mask);
504 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_pipe_buf, tvb,
505 offset + 2, 2, pc_mask);
506 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_chown_restricted, tvb,
507 offset + 2, 2, pc_mask);
508 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_no_trunc, tvb,
509 offset + 2, 2, pc_mask);
510 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_vdisable, tvb,
511 offset + 2, 2, pc_mask);
514 offset += 8;
515 return offset;
519 /* RFC 1813, Page 107 */
520 static int
521 dissect_mountstat3(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int offset, int hfindex, guint32 *status)
523 guint32 mountstat3;
525 mountstat3 = tvb_get_ntohl(tvb, offset);
526 if(mountstat3){
527 col_append_fstr(
528 pinfo->cinfo, COL_INFO, " Error:%s",
529 val_to_str(mountstat3, mount3_mountstat3,
530 "Unknown (0x%08X)"));
533 offset = dissect_rpc_uint32(tvb,tree,hfindex,offset);
534 *status = mountstat3;
535 return offset;
538 /* RFC 1831, Page 109 */
539 static int
540 dissect_mount3_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data)
542 guint32 status;
543 guint32 auth_flavors;
544 guint32 auth_flavor;
545 guint32 auth_flavor_i;
547 offset = dissect_mountstat3(pinfo,tvb,tree,offset,hf_mount3_status,&status);
549 switch (status) {
550 case 0:
551 offset = dissect_nfs3_fh(tvb,offset,pinfo,tree,"fhandle",NULL,(rpc_call_info_value*)data);
553 auth_flavors = tvb_get_ntohl(tvb, offset);
554 proto_tree_add_uint(tree,hf_mount_flavors, tvb,
555 offset, 4, auth_flavors);
556 offset += 4;
557 for (auth_flavor_i = 0 ; auth_flavor_i < auth_flavors ; auth_flavor_i++) {
558 auth_flavor = tvb_get_ntohl(tvb, offset);
559 proto_tree_add_uint(tree,hf_mount_flavor, tvb,
560 offset, 4, auth_flavor);
561 offset += 4;
563 break;
564 default:
565 /* void */
566 break;
569 return offset;
572 static int
573 dissect_sgi_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
575 proto_item* exportlist_item = NULL;
576 proto_tree* exportlist_tree = NULL;
577 int old_offset = offset;
578 const char* directory, *options;
580 if (tree) {
581 exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist,
582 tvb, offset, -1, ENC_NA);
583 if (exportlist_item)
584 exportlist_tree = proto_item_add_subtree(exportlist_item,
585 ett_mount_exportlist);
588 offset = dissect_rpc_string(tvb, exportlist_tree,
589 hf_mount_exportlist_directory, offset, &directory);
591 offset = dissect_rpc_bool(tvb, exportlist_tree,
592 hf_mount_has_options, offset);
594 offset = dissect_rpc_string(tvb, exportlist_tree, hf_mount_options,
595 offset, &options);
597 if (exportlist_item) {
598 /* now we have a nicer string */
599 proto_item_set_text(exportlist_item,
600 "Export List Entry: %s %s", directory,
601 options);
602 /* now we know, that exportlist is shorter */
603 proto_item_set_len(exportlist_item, offset - old_offset);
606 return offset;
609 static int
610 dissect_mount_exportlist_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data _U_)
612 offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_sgi_exportlist);
614 return offset;
617 #define ST_RDONLY 0x00000001
618 #define ST_NOSUID 0x00000002
619 #define ST_NOTRUNC 0x00000004
620 #define ST_NODEV 0x20000000
621 #define ST_GRPID 0x40000000
622 #define ST_LOCAL 0x80000000
624 static const true_false_string tos_st_rdonly = {
625 "Read-only file system",
626 "Read/Write file system"
629 static const true_false_string tos_st_nosuid = {
630 "Does not support setuid/setgid semantics",
631 "Supports setuid/setgid semantics"
634 static const true_false_string tos_st_notrunc = {
635 "Does not truncate filenames longer than NAME_MAX",
636 "Truncates filenames longer than NAME_MAX"
639 static const true_false_string tos_st_nodev = {
640 "Disallows opening of device files",
641 "Allows opening of device files"
644 static const true_false_string tos_st_grpid = {
645 "Group ID assigned from directory",
646 "Group ID not assigned from directory"
649 static const true_false_string tos_st_local = {
650 "File system is local",
651 "File system is not local"
654 static int
655 dissect_mount_statvfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
657 proto_item *flag_item;
658 proto_tree *flag_tree;
659 guint32 statvfs_flags;
661 statvfs_flags = tvb_get_ntohl(tvb, offset+52);
662 if (tree) {
663 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bsize, offset);
665 offset += 4;
666 if (tree) {
667 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_frsize, offset);
669 offset += 4;
670 if (tree) {
671 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_blocks, offset);
673 offset += 4;
674 if (tree) {
675 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bfree, offset);
677 offset += 4;
678 if (tree) {
679 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bavail, offset);
681 offset += 4;
682 if (tree) {
683 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_files, offset);
685 offset += 4;
686 if (tree) {
687 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_ffree, offset);
689 offset += 4;
690 if (tree) {
691 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_favail, offset);
693 offset += 4;
694 if (tree) {
695 dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_basetype, offset,
696 16, TRUE, NULL);
698 offset += 16;
699 if (tree) {
700 dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_fstr, offset,
701 32, FALSE, NULL);
703 offset += 32;
704 if (tree) {
705 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_fsid, offset);
707 offset += 4;
709 if (tree) {
710 flag_item = proto_tree_add_item(tree, hf_mount_statvfs_flag,
711 tvb, offset, 4, ENC_BIG_ENDIAN);
712 if (flag_item) {
713 flag_tree = proto_item_add_subtree(flag_item,
714 ett_mount_statvfs_flag);
715 proto_tree_add_boolean(flag_tree,
716 hf_mount_statvfs_flag_rdonly, tvb, offset, 4,
717 statvfs_flags);
718 proto_tree_add_boolean(flag_tree,
719 hf_mount_statvfs_flag_nosuid, tvb, offset, 4,
720 statvfs_flags);
721 proto_tree_add_boolean(flag_tree,
722 hf_mount_statvfs_flag_notrunc, tvb, offset, 4,
723 statvfs_flags);
724 proto_tree_add_boolean(flag_tree,
725 hf_mount_statvfs_flag_nodev, tvb, offset, 4,
726 statvfs_flags);
727 proto_tree_add_boolean(flag_tree,
728 hf_mount_statvfs_flag_grpid, tvb, offset, 4,
729 statvfs_flags);
730 proto_tree_add_boolean(flag_tree,
731 hf_mount_statvfs_flag_local, tvb, offset, 4,
732 statvfs_flags);
736 offset += 4;
737 if (tree) {
738 dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_namemax, offset);
740 offset += 4;
742 return offset;
745 /* proc number, "proc name", dissect_request, dissect_reply */
746 /* NULL as function pointer means: type of arguments is "void". */
748 /* Mount protocol version 1, RFC 1094 */
749 static const vsff mount1_proc[] = {
750 { 0, "NULL", NULL, NULL },
751 { MOUNTPROC_MNT, "MNT",
752 dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
753 { MOUNTPROC_DUMP, "DUMP",
754 NULL, dissect_mount_dump_reply },
755 { MOUNTPROC_UMNT, "UMNT",
756 dissect_mount_dirpath_call, NULL },
757 { MOUNTPROC_UMNTALL, "UMNTALL",
758 NULL, NULL },
759 { MOUNTPROC_EXPORT, "EXPORT",
760 NULL, dissect_mount_export_reply },
761 { MOUNTPROC_EXPORTALL, "EXPORTALL",
762 NULL, dissect_mount_export_reply },
763 { 0, NULL, NULL, NULL }
765 static const value_string mount1_proc_vals[] = {
766 { 0, "NULL" },
767 { MOUNTPROC_MNT, "MNT" },
768 { MOUNTPROC_DUMP, "DUMP" },
769 { MOUNTPROC_UMNT, "UMNT" },
770 { MOUNTPROC_UMNTALL, "UMNTALL" },
771 { MOUNTPROC_EXPORT, "EXPORT" },
772 { MOUNTPROC_EXPORTALL, "EXPORTALL" },
773 { 0, NULL }
775 /* end of mount version 1 */
778 /* Mount protocol version 2, private communication from somebody at Sun;
779 mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
780 POSIX "pathconf()" call. */
781 static const vsff mount2_proc[] = {
782 { 0, "NULL", NULL, NULL },
783 { MOUNTPROC_MNT, "MNT",
784 dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
785 { MOUNTPROC_DUMP, "DUMP",
786 NULL, dissect_mount_dump_reply },
787 { MOUNTPROC_UMNT, "UMNT",
788 dissect_mount_dirpath_call, NULL },
789 { MOUNTPROC_UMNTALL, "UMNTALL",
790 NULL, NULL },
791 { MOUNTPROC_EXPORT, "EXPORT",
792 NULL, dissect_mount_export_reply },
793 { MOUNTPROC_EXPORTALL, "EXPORTALL",
794 NULL, dissect_mount_export_reply },
795 { MOUNTPROC_PATHCONF, "PATHCONF",
796 dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
797 { 0, NULL, NULL, NULL }
799 static const value_string mount2_proc_vals[] = {
800 { 0, "NULL" },
801 { MOUNTPROC_MNT, "MNT" },
802 { MOUNTPROC_DUMP, "DUMP" },
803 { MOUNTPROC_UMNT, "UMNT" },
804 { MOUNTPROC_UMNTALL, "UMNTALL" },
805 { MOUNTPROC_EXPORT, "EXPORT" },
806 { MOUNTPROC_EXPORTALL, "EXPORTALL" },
807 { MOUNTPROC_PATHCONF, "PATHCONF" },
808 { 0, NULL }
810 /* end of mount version 2 */
813 /* Mount protocol version 3, RFC 1813 */
814 static const vsff mount3_proc[] = {
815 { 0, "NULL", NULL, NULL },
816 { MOUNTPROC_MNT, "MNT",
817 dissect_mount_dirpath_call, dissect_mount3_mnt_reply },
818 { MOUNTPROC_DUMP, "DUMP",
819 NULL, dissect_mount_dump_reply },
820 { MOUNTPROC_UMNT, "UMNT",
821 dissect_mount_dirpath_call, NULL },
822 { MOUNTPROC_UMNTALL, "UMNTALL",
823 NULL, NULL },
824 { MOUNTPROC_EXPORT, "EXPORT",
825 NULL, dissect_mount_export_reply },
826 { 0, NULL, NULL, NULL }
828 static const value_string mount3_proc_vals[] = {
829 { 0, "NULL" },
830 { MOUNTPROC_MNT, "MNT" },
831 { MOUNTPROC_DUMP, "DUMP" },
832 { MOUNTPROC_UMNT, "UMNT" },
833 { MOUNTPROC_UMNTALL, "UMNTALL" },
834 { MOUNTPROC_EXPORT, "EXPORT" },
835 { 0, NULL }
837 /* end of Mount protocol version 3 */
839 /* SGI mount protocol version 1; actually the same as v1 plus
840 MOUNTPROC_EXPORTLIST and MOUNTPROC_STATVFS */
842 static const vsff sgi_mount1_proc[] = {
843 { 0, "NULL", NULL, NULL },
844 { MOUNTPROC_MNT, "MNT",
845 dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
846 { MOUNTPROC_DUMP, "DUMP",
847 NULL, dissect_mount_dump_reply },
848 { MOUNTPROC_UMNT, "UMNT",
849 dissect_mount_dirpath_call, NULL },
850 { MOUNTPROC_UMNTALL, "UMNTALL",
851 NULL, NULL },
852 { MOUNTPROC_EXPORT, "EXPORT",
853 NULL, dissect_mount_export_reply },
854 { MOUNTPROC_EXPORTALL, "EXPORTALL",
855 NULL, dissect_mount_export_reply },
856 { MOUNTPROC_EXPORTLIST,"EXPORTLIST",
857 NULL, dissect_mount_exportlist_reply },
858 { MOUNTPROC_STATVFS, "STATVFS",
859 dissect_mount_dirpath_call, dissect_mount_statvfs_reply },
860 { 0, NULL, NULL, NULL }
862 static const value_string sgi_mount1_proc_vals[] = {
863 { 0, "NULL" },
864 { MOUNTPROC_MNT, "MNT" },
865 { MOUNTPROC_DUMP, "DUMP" },
866 { MOUNTPROC_UMNT, "UMNT" },
867 { MOUNTPROC_UMNTALL, "UMNTALL" },
868 { MOUNTPROC_EXPORT, "EXPORT" },
869 { MOUNTPROC_EXPORTALL, "EXPORTALL" },
870 { MOUNTPROC_EXPORTLIST, "EXPORTLIST" },
871 { MOUNTPROC_STATVFS, "STATVFS" },
872 { 0, NULL }
874 /* end of SGI mount protocol version 1 */
876 void
877 proto_register_mount(void)
879 static hf_register_info hf[] = {
880 { &hf_mount_procedure_v1, {
881 "V1 Procedure", "mount.procedure_v1", FT_UINT32, BASE_DEC,
882 VALS(mount1_proc_vals), 0, NULL, HFILL }},
883 { &hf_mount_procedure_v2, {
884 "V2 Procedure", "mount.procedure_v2", FT_UINT32, BASE_DEC,
885 VALS(mount2_proc_vals), 0, NULL, HFILL }},
886 { &hf_mount_procedure_v3, {
887 "V3 Procedure", "mount.procedure_v3", FT_UINT32, BASE_DEC,
888 VALS(mount3_proc_vals), 0, NULL, HFILL }},
889 { &hf_sgi_mount_procedure_v1, {
890 "SGI V1 procedure", "mount.procedure_sgi_v1", FT_UINT32, BASE_DEC,
891 VALS(sgi_mount1_proc_vals), 0, NULL, HFILL }},
892 { &hf_mount_path, {
893 "Path", "mount.path", FT_STRING, BASE_NONE,
894 NULL, 0, NULL, HFILL }},
895 { &hf_mount3_status, {
896 "Status", "mount.status", FT_UINT32, BASE_DEC,
897 VALS(mount3_mountstat3), 0, NULL, HFILL }},
898 { &hf_mount_mountlist_hostname, {
899 "Hostname", "mount.dump.hostname", FT_STRING, BASE_NONE,
900 NULL, 0, NULL, HFILL }},
901 { &hf_mount_mountlist_directory, {
902 "Directory", "mount.dump.directory", FT_STRING, BASE_NONE,
903 NULL, 0, NULL, HFILL }},
904 { &hf_mount_mountlist, {
905 "Mount List Entry", "mount.dump.entry", FT_NONE, BASE_NONE,
906 NULL, 0, NULL, HFILL }},
907 { &hf_mount_groups_group, {
908 "Group", "mount.export.group", FT_STRING, BASE_NONE,
909 NULL, 0, NULL, HFILL }},
910 { &hf_mount_groups, {
911 "Groups", "mount.export.groups", FT_NONE, BASE_NONE,
912 NULL, 0, NULL, HFILL }},
913 { &hf_mount_has_options, {
914 "Has options", "mount.export.has_options", FT_UINT32,
915 BASE_DEC, NULL, 0, NULL, HFILL }},
916 { &hf_mount_options, {
917 "Options", "mount.export.options", FT_STRING, BASE_NONE,
918 NULL, 0, NULL, HFILL }},
919 { &hf_mount_exportlist_directory, {
920 "Directory", "mount.export.directory", FT_STRING, BASE_NONE,
921 NULL, 0, NULL, HFILL }},
922 { &hf_mount_exportlist, {
923 "Export List Entry", "mount.export.entry", FT_NONE, BASE_NONE,
924 NULL, 0, NULL, HFILL }},
925 { &hf_mount_pathconf_link_max, {
926 "Maximum number of links to a file", "mount.pathconf.link_max",
927 FT_UINT32, BASE_DEC,
928 NULL, 0, "Maximum number of links allowed to a file", HFILL }},
929 { &hf_mount_pathconf_max_canon, {
930 "Maximum terminal input line length", "mount.pathconf.max_canon",
931 FT_UINT16, BASE_DEC,
932 NULL, 0, "Max tty input line length", HFILL }},
933 { &hf_mount_pathconf_max_input, {
934 "Terminal input buffer size", "mount.pathconf.max_input",
935 FT_UINT16, BASE_DEC,
936 NULL, 0, NULL, HFILL }},
937 { &hf_mount_pathconf_name_max, {
938 "Maximum file name length", "mount.pathconf.name_max",
939 FT_UINT16, BASE_DEC,
940 NULL, 0, NULL, HFILL }},
941 { &hf_mount_pathconf_path_max, {
942 "Maximum path name length", "mount.pathconf.path_max",
943 FT_UINT16, BASE_DEC,
944 NULL, 0, NULL, HFILL }},
945 { &hf_mount_pathconf_pipe_buf, {
946 "Pipe buffer size", "mount.pathconf.pipe_buf",
947 FT_UINT16, BASE_DEC,
948 NULL, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL }},
949 { &hf_mount_pathconf_vdisable, {
950 "VDISABLE character", "mount.pathconf.vdisable_char",
951 FT_UINT8, BASE_HEX,
952 NULL, 0, "Character value to disable a terminal special character", HFILL }},
953 { &hf_mount_pathconf_mask, {
954 "Reply error/status bits", "mount.pathconf.mask",
955 FT_UINT16, BASE_HEX,
956 NULL, 0, "Bit mask with error and status bits", HFILL }},
957 { &hf_mount_pathconf_error_all, {
958 "ERROR_ALL", "mount.pathconf.mask.error_all",
959 FT_BOOLEAN, 16, TFS(&tos_error_all),
960 PC_ERROR_ALL, NULL, HFILL }},
961 { &hf_mount_pathconf_error_link_max, {
962 "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
963 FT_BOOLEAN, 16, TFS(&tos_error_link_max),
964 PC_ERROR_LINK_MAX, NULL, HFILL }},
965 { &hf_mount_pathconf_error_max_canon, {
966 "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
967 FT_BOOLEAN, 16, TFS(&tos_error_max_canon),
968 PC_ERROR_MAX_CANON, NULL, HFILL }},
969 { &hf_mount_pathconf_error_max_input, {
970 "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
971 FT_BOOLEAN, 16, TFS(&tos_error_max_input),
972 PC_ERROR_MAX_INPUT, NULL, HFILL }},
973 { &hf_mount_pathconf_error_name_max, {
974 "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
975 FT_BOOLEAN, 16, TFS(&tos_error_name_max),
976 PC_ERROR_NAME_MAX, NULL, HFILL }},
977 { &hf_mount_pathconf_error_path_max, {
978 "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
979 FT_BOOLEAN, 16, TFS(&tos_error_path_max),
980 PC_ERROR_PATH_MAX, NULL, HFILL }},
981 { &hf_mount_pathconf_error_pipe_buf, {
982 "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
983 FT_BOOLEAN, 16, TFS(&tos_error_pipe_buf),
984 PC_ERROR_PIPE_BUF, NULL, HFILL }},
985 { &hf_mount_pathconf_chown_restricted, {
986 "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
987 FT_BOOLEAN, 16, TFS(&tos_chown_restricted),
988 PC_CHOWN_RESTRICTED, NULL, HFILL }},
989 { &hf_mount_pathconf_no_trunc, {
990 "NO_TRUNC", "mount.pathconf.mask.no_trunc",
991 FT_BOOLEAN, 16, TFS(&tos_no_trunc),
992 PC_NO_TRUNC, NULL, HFILL }},
993 { &hf_mount_pathconf_error_vdisable, {
994 "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
995 FT_BOOLEAN, 16, TFS(&tos_error_vdisable),
996 PC_ERROR_VDISABLE, NULL, HFILL }},
997 { &hf_mount_statvfs_bsize, {
998 "Block size", "mount.statvfs.f_bsize",
999 FT_UINT32, BASE_DEC, NULL, 0,
1000 "File system block size", HFILL }},
1001 { &hf_mount_statvfs_frsize, {
1002 "Fragment size", "mount.statvfs.f_frsize",
1003 FT_UINT32, BASE_DEC, NULL, 0,
1004 "File system fragment size", HFILL }},
1005 { &hf_mount_statvfs_blocks, {
1006 "Blocks", "mount.statvfs.f_blocks",
1007 FT_UINT32, BASE_DEC, NULL, 0,
1008 "Total fragment sized blocks", HFILL }},
1009 { &hf_mount_statvfs_bfree, {
1010 "Blocks Free", "mount.statvfs.f_bfree",
1011 FT_UINT32, BASE_DEC, NULL, 0,
1012 "Free fragment sized blocks", HFILL }},
1013 { &hf_mount_statvfs_bavail, {
1014 "Blocks Available", "mount.statvfs.f_bavail",
1015 FT_UINT32, BASE_DEC, NULL, 0,
1016 "Available fragment sized blocks", HFILL }},
1017 { &hf_mount_statvfs_files, {
1018 "Files", "mount.statvfs.f_files",
1019 FT_UINT32, BASE_DEC, NULL, 0,
1020 "Total files/inodes", HFILL }},
1021 { &hf_mount_statvfs_ffree, {
1022 "Files Free", "mount.statvfs.f_ffree",
1023 FT_UINT32, BASE_DEC, NULL, 0,
1024 "Free files/inodes", HFILL }},
1025 { &hf_mount_statvfs_favail, {
1026 "Files Available", "mount.statvfs.f_favail",
1027 FT_UINT32, BASE_DEC, NULL, 0,
1028 "Available files/inodes", HFILL }},
1029 { &hf_mount_statvfs_fsid, {
1030 "File system ID", "mount.statvfs.f_fsid",
1031 FT_UINT32, BASE_DEC, NULL, 0,
1032 "File system identifier", HFILL }},
1033 { &hf_mount_statvfs_basetype, {
1034 "Type", "mount.statvfs.f_basetype",
1035 FT_STRING, BASE_NONE, NULL, 0,
1036 "File system type", HFILL }},
1037 { &hf_mount_statvfs_flag, {
1038 "Flags", "mount.statvfs.f_flag",
1039 FT_UINT32, BASE_HEX, NULL, 0,
1040 "Flags bit-mask", HFILL }},
1041 { &hf_mount_statvfs_flag_rdonly, {
1042 "ST_RDONLY", "mount.statvfs.f_flag.st_rdonly",
1043 FT_BOOLEAN, 32, TFS(&tos_st_rdonly), ST_RDONLY,
1044 NULL, HFILL }},
1045 { &hf_mount_statvfs_flag_nosuid, {
1046 "ST_NOSUID", "mount.statvfs.f_flag.st_nosuid",
1047 FT_BOOLEAN, 32, TFS(&tos_st_nosuid), ST_NOSUID,
1048 NULL, HFILL }},
1049 { &hf_mount_statvfs_flag_notrunc, {
1050 "ST_NOTRUNC", "mount.statvfs.f_flag.st_notrunc",
1051 FT_BOOLEAN, 32, TFS(&tos_st_notrunc), ST_NOTRUNC,
1052 NULL, HFILL }},
1053 { &hf_mount_statvfs_flag_nodev, {
1054 "ST_NODEV", "mount.statvfs.f_flag.st_nodev",
1055 FT_BOOLEAN, 32, TFS(&tos_st_nodev), ST_NODEV,
1056 NULL, HFILL }},
1057 { &hf_mount_statvfs_flag_grpid, {
1058 "ST_GRPID", "mount.statvfs.f_flag.st_grpid",
1059 FT_BOOLEAN, 32, TFS(&tos_st_grpid), ST_GRPID,
1060 NULL, HFILL }},
1061 { &hf_mount_statvfs_flag_local, {
1062 "ST_LOCAL", "mount.statvfs.f_flag.st_local",
1063 FT_BOOLEAN, 32, TFS(&tos_st_local), ST_LOCAL,
1064 NULL, HFILL }},
1065 { &hf_mount_statvfs_namemax, {
1066 "Maximum file name length", "mount.statvfs.f_namemax",
1067 FT_UINT32, BASE_DEC, NULL, 0,
1068 NULL, HFILL }},
1069 { &hf_mount_statvfs_fstr, {
1070 "File system specific string", "mount.statvfs.f_fstr",
1071 FT_BYTES, BASE_NONE, NULL, 0,
1072 NULL, HFILL }},
1073 { &hf_mount_flavors, {
1074 "Flavors", "mount.flavors", FT_UINT32, BASE_DEC,
1075 NULL, 0, NULL, HFILL }},
1076 { &hf_mount_flavor, {
1077 "Flavor", "mount.flavor", FT_UINT32, BASE_DEC,
1078 VALS(rpc_auth_flavor), 0, NULL, HFILL }},
1080 static gint *ett[] = {
1081 &ett_mount,
1082 &ett_mount_mountlist,
1083 &ett_mount_groups,
1084 &ett_mount_exportlist,
1085 &ett_mount_pathconf_mask,
1086 &ett_mount_statvfs_flag,
1089 proto_mount = proto_register_protocol("Mount Service", "MOUNT",
1090 "mount");
1091 proto_sgi_mount = proto_register_protocol("SGI Mount Service",
1092 "SGI MOUNT", "sgimount");
1093 proto_register_field_array(proto_mount, hf, array_length(hf));
1094 proto_register_subtree_array(ett, array_length(ett));
1097 void
1098 proto_reg_handoff_mount(void)
1100 /* Register the protocol as RPC */
1101 rpc_init_prog(proto_mount, MOUNT_PROGRAM, ett_mount);
1102 rpc_init_prog(proto_sgi_mount, SGI_MOUNT_PROGRAM, ett_mount);
1103 /* Register the procedure tables */
1104 rpc_init_proc_table(MOUNT_PROGRAM, 1, mount1_proc, hf_mount_procedure_v1);
1105 rpc_init_proc_table(MOUNT_PROGRAM, 2, mount2_proc, hf_mount_procedure_v2);
1106 rpc_init_proc_table(MOUNT_PROGRAM, 3, mount3_proc, hf_mount_procedure_v3);
1107 rpc_init_proc_table(SGI_MOUNT_PROGRAM, 1, sgi_mount1_proc, hf_sgi_mount_procedure_v1);