cdma2k : fix no previous prototype for function 'proto_[register|reg_handoff]_cdma2k...
[metze/wireshark/wip.git] / epan / dissectors / packet-mount.c
1 /* packet-mount.c
2  * Routines for mount dissection
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * Copied from packet-smb.c
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12
13 #include "config.h"
14
15
16 #include <epan/exceptions.h>
17 #include <epan/to_str.h>
18 #include "packet-mount.h"
19 #include "packet-nfs.h"
20
21 void proto_register_mount(void);
22 void proto_reg_handoff_mount(void);
23
24 static int proto_mount = -1;
25 static int proto_sgi_mount = -1;
26 static int hf_mount_procedure_v1 = -1;
27 static int hf_mount_procedure_v2 = -1;
28 static int hf_mount_procedure_v3 = -1;
29 static int hf_sgi_mount_procedure_v1 = -1;
30 static int hf_mount_path = -1;
31 static int hf_mount3_status = -1;
32 static int hf_mount_mountlist_hostname = -1;
33 static int hf_mount_mountlist_directory = -1;
34 static int hf_mount_mountlist = -1;
35 static int hf_mount_groups_group = -1;
36 static int hf_mount_groups = -1;
37 static int hf_mount_exportlist_directory = -1;
38 static int hf_mount_exportlist = -1;
39 static int hf_mount_has_options = -1;
40 static int hf_mount_options = -1;
41 static int hf_mount_pathconf_link_max = -1;
42 static int hf_mount_pathconf_max_canon = -1;
43 static int hf_mount_pathconf_max_input = -1;
44 static int hf_mount_pathconf_name_max = -1;
45 static int hf_mount_pathconf_path_max = -1;
46 static int hf_mount_pathconf_pipe_buf = -1;
47 static int hf_mount_pathconf_vdisable = -1;
48 static int hf_mount_pathconf_mask = -1;
49 static int hf_mount_pathconf_error_all = -1;
50 static int hf_mount_pathconf_error_link_max = -1;
51 static int hf_mount_pathconf_error_max_canon = -1;
52 static int hf_mount_pathconf_error_max_input = -1;
53 static int hf_mount_pathconf_error_name_max = -1;
54 static int hf_mount_pathconf_error_path_max = -1;
55 static int hf_mount_pathconf_error_pipe_buf = -1;
56 static int hf_mount_pathconf_chown_restricted = -1;
57 static int hf_mount_pathconf_no_trunc = -1;
58 static int hf_mount_pathconf_error_vdisable = -1;
59 static int hf_mount_statvfs_bsize = -1;
60 static int hf_mount_statvfs_frsize = -1;
61 static int hf_mount_statvfs_blocks = -1;
62 static int hf_mount_statvfs_bfree = -1;
63 static int hf_mount_statvfs_bavail = -1;
64 static int hf_mount_statvfs_files = -1;
65 static int hf_mount_statvfs_ffree = -1;
66 static int hf_mount_statvfs_favail = -1;
67 static int hf_mount_statvfs_fsid = -1;
68 static int hf_mount_statvfs_basetype = -1;
69 static int hf_mount_statvfs_flag = -1;
70 static int hf_mount_statvfs_flag_rdonly = -1;
71 static int hf_mount_statvfs_flag_nosuid = -1;
72 static int hf_mount_statvfs_flag_notrunc = -1;
73 static int hf_mount_statvfs_flag_nodev = -1;
74 static int hf_mount_statvfs_flag_grpid = -1;
75 static int hf_mount_statvfs_flag_local = -1;
76 static int hf_mount_statvfs_namemax = -1;
77 static int hf_mount_statvfs_fstr = -1;
78 static int hf_mount_flavors = -1;
79 static int hf_mount_flavor = -1;
80
81 static gint ett_mount = -1;
82 static gint ett_mount_mountlist = -1;
83 static gint ett_mount_groups = -1;
84 static gint ett_mount_exportlist = -1;
85 static gint ett_mount_pathconf_mask = -1;
86 static gint ett_mount_statvfs_flag = -1;
87
88 #define MAX_GROUP_NAME_LIST 128
89 static char group_name_list[MAX_GROUP_NAME_LIST];
90 static int  group_names_len;
91
92 /* RFC 1813, Page 107 */
93 static const value_string mount3_mountstat3[] =
94 {
95         {       0,      "OK" },
96         {       1,      "ERR_PERM" },
97         {       2,      "ERR_NOENT" },
98         {       5,      "ERR_IO" },
99         {       13,     "ERR_ACCESS" },
100         {       20,     "ERR_NOTDIR" },
101         {       22,     "ERR_INVAL" },
102         {       63,     "ERR_NAMETOOLONG" },
103         {       10004,  "ERR_NOTSUPP" },
104         {       10006,  "ERR_SERVERFAULT" },
105         {       0,      NULL }
106 };
107
108
109 /* RFC 1094, Page 24 */
110 /* This function dissects fhstatus for v1 and v2 of the mount protocol.
111  * Formally, hf_mount3_status only define the status codes returned by version
112  * 3 of the protocol.
113  * Though not formally defined in the standard, we use the same
114  * value-to-string mappings as version 3 since we believe that this mapping
115  * is consistant with most v1 and v2 implementations.
116  */
117 static int
118 dissect_fhstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, rpc_call_info_value* civ)
119 {
120         gint32 status;
121
122         status=tvb_get_ntohl(tvb,offset);
123         offset = dissect_rpc_uint32(tvb,tree,hf_mount3_status,offset);
124
125         switch (status) {
126                 case 0:
127                         offset = dissect_fhandle(tvb,offset,pinfo,tree,"fhandle", NULL, civ);
128                 break;
129                 default:
130                         /* void */
131                         col_append_fstr(
132                                         pinfo->cinfo, COL_INFO, " Error:%s",
133                                         val_to_str(status, mount3_mountstat3,
134                                             "Unknown (0x%08X)"));
135                 break;
136         }
137
138         return offset;
139 }
140
141
142 static int
143 dissect_mount_dirpath_call(tvbuff_t *tvb, packet_info *pinfo,
144                 proto_tree *tree, void* data)
145 {
146         const char *mountpoint=NULL;
147         int offset = 0;
148
149         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
150                 rpc_call_info_value *civ=(rpc_call_info_value *)data;
151
152                 if(civ->request && (civ->proc==1)){
153                         guint32 len_field;
154
155                         len_field = tvb_get_ntohl(tvb, offset);
156                         if (len_field < ITEM_LABEL_LENGTH) {
157                                 gchar *name, *ptr;
158                                 int addr_len, name_len;
159
160                                 name = address_to_str(wmem_packet_scope(), &pinfo->dst);
161                                 addr_len = (int)strlen(name);
162                                 /* IP address, colon, path, terminating 0 */
163                                 name_len = addr_len + 1 + len_field + 1;
164
165                                 name = (gchar *)wmem_realloc(wmem_packet_scope(),
166                                                 (void *)name, name_len);
167                                 ptr = name + addr_len;
168                                 *ptr++ = ':';
169                                 tvb_memcpy(tvb, ptr, offset+4, len_field);
170                                 ptr += len_field;
171                                 *ptr = 0;
172
173                                 nfs_name_snoop_add_name(civ->xid, tvb, -1, name_len, 0, 0, name);
174                         }
175                 }
176         }
177
178         offset = dissect_rpc_string(tvb,tree,hf_mount_path,offset,&mountpoint);
179         col_append_fstr(pinfo->cinfo, COL_INFO," %s", mountpoint);
180
181         return offset;
182 }
183
184
185 /* RFC 1094, Page 25,26 */
186 static int
187 dissect_mount1_mnt_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
188 {
189         return dissect_fhstatus(tvb,0,pinfo,tree,(rpc_call_info_value*)data);
190 }
191
192
193
194 /* RFC 1094, Page 26 */
195 /* RFC 1813, Page 110 */
196 static int
197 dissect_mountlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
198 {
199         proto_item* lock_item;
200         proto_tree* lock_tree;
201         int old_offset = offset;
202         const char* hostname;
203         const char* directory;
204
205         lock_item = proto_tree_add_item(tree, hf_mount_mountlist, tvb,
206                                         offset, -1, ENC_NA);
207
208         lock_tree = proto_item_add_subtree(lock_item, ett_mount_mountlist);
209
210         offset = dissect_rpc_string(tvb, lock_tree,
211                         hf_mount_mountlist_hostname, offset, &hostname);
212         offset = dissect_rpc_string(tvb, lock_tree,
213                         hf_mount_mountlist_directory, offset, &directory);
214
215         if (lock_item) {
216                 /* now we have a nicer string */
217                 proto_item_set_text(lock_item, "Mount List Entry: %s:%s", hostname, directory);
218                 /* now we know, that mountlist is shorter */
219                 proto_item_set_len(lock_item, offset - old_offset);
220         }
221
222         return offset;
223 }
224
225
226 /* RFC 1094, Page 26 */
227 /* RFC 1813, Page 110 */
228 static int
229 dissect_mount_dump_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
230 {
231         return dissect_rpc_list(tvb, pinfo, tree, 0,
232                 dissect_mountlist, NULL);
233 }
234
235
236
237 /* RFC 1094, Page 26 */
238 /* RFC 1813, Page 110 */
239 static int
240 dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
241 {
242         int str_len;
243
244         if (group_names_len < MAX_GROUP_NAME_LIST - 5) {
245                 str_len=tvb_get_nstringz(tvb,offset+4,
246                         MAX_GROUP_NAME_LIST-5-group_names_len,
247                         group_name_list+group_names_len);
248                 if((group_names_len>=(MAX_GROUP_NAME_LIST-5))||(str_len<0)){
249                         g_snprintf(group_name_list+(MAX_GROUP_NAME_LIST-5), 5, "...");
250                         group_names_len=MAX_GROUP_NAME_LIST - 1;
251                 } else {
252                         group_names_len+=str_len;
253                         group_name_list[group_names_len++]=' ';
254                 }
255                 group_name_list[group_names_len]=0;
256         }
257
258         offset = dissect_rpc_string(tvb, tree,
259                         hf_mount_groups_group, offset, NULL);
260
261         return offset;
262 }
263
264
265 /* RFC 1094, Page 26 */
266 /* RFC 1813, Page 113 */
267 static int
268 dissect_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data _U_)
269 {
270         proto_item* exportlist_item = NULL;
271         proto_tree* exportlist_tree = NULL;
272         int old_offset = offset;
273         int groups_offset;
274         proto_item* groups_item = NULL;
275         proto_item* groups_tree = NULL;
276         const char* directory;
277
278         group_name_list[0]=0;
279         group_names_len=0;
280         if (tree) {
281                 exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, tvb, offset, -1, ENC_NA);
282                 exportlist_tree = proto_item_add_subtree(exportlist_item, ett_mount_exportlist);
283         }
284
285         offset = dissect_rpc_string(tvb, exportlist_tree,
286                         hf_mount_exportlist_directory, offset, &directory);
287         groups_offset = offset;
288
289         groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, tvb, offset, -1, ENC_NA);
290         groups_tree = proto_item_add_subtree(groups_item, ett_mount_groups);
291
292
293         offset = dissect_rpc_list(tvb, pinfo, groups_tree, offset,
294                 dissect_group, NULL);
295         if (groups_item) {
296                 /* mark empty lists */
297                 if (offset - groups_offset == 4) {
298                         proto_item_set_text(groups_item, "Groups: empty");
299                 }
300
301                 /* now we know, that groups is shorter */
302                 proto_item_set_len(groups_item, offset - groups_offset);
303         }
304
305         if (exportlist_item) {
306                 /* now we have a nicer string */
307                 proto_item_set_text(exportlist_item, "Export List Entry: %s -> %s", directory,group_name_list);
308                 /* now we know, that exportlist is shorter */
309                 proto_item_set_len(exportlist_item, offset - old_offset);
310         }
311
312         return offset;
313 }
314
315
316 /* RFC 1094, Page 26 */
317 /* RFC 1813, Page 113 */
318 static int
319 dissect_mount_export_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
320 {
321         return dissect_rpc_list(tvb, pinfo, tree, 0,
322                 dissect_exportlist, NULL);
323 }
324
325
326 #define OFFS_MASK       32      /* offset of the "pc_mask" field */
327
328 #define PC_ERROR_ALL            0x0001
329 #define PC_ERROR_LINK_MAX       0x0002
330 #define PC_ERROR_MAX_CANON      0x0004
331 #define PC_ERROR_MAX_INPUT      0x0008
332 #define PC_ERROR_NAME_MAX       0x0010
333 #define PC_ERROR_PATH_MAX       0x0020
334 #define PC_ERROR_PIPE_BUF       0x0040
335 #define PC_CHOWN_RESTRICTED     0x0080
336 #define PC_NO_TRUNC             0x0100
337 #define PC_ERROR_VDISABLE       0x0200
338
339 static const true_false_string tos_error_all = {
340         "All info invalid",
341         "Some or all info valid"
342 };
343
344 static const true_false_string tos_error_link_max = {
345         "LINK_MAX invalid",
346         "LINK_MAX valid"
347 };
348
349 static const true_false_string tos_error_max_canon = {
350         "MAX_CANON invalid",
351         "MAX_CANON valid"
352 };
353
354 static const true_false_string tos_error_max_input = {
355         "MAX_INPUT invalid",
356         "MAX_INPUT valid"
357 };
358
359 static const true_false_string tos_error_name_max = {
360         "NAME_MAX invalid",
361         "NAME_MAX valid"
362 };
363
364 static const true_false_string tos_error_path_max = {
365         "PATH_MAX invalid",
366         "PATH_MAX valid"
367 };
368
369 static const true_false_string tos_error_pipe_buf = {
370         "PIPE_BUF invalid",
371         "PIPE_BUF valid"
372 };
373
374 static const true_false_string tos_chown_restricted = {
375         "Only a privileged user can change the ownership of a file",
376         "Users may give away their own files"
377 };
378
379 static const true_false_string tos_no_trunc = {
380         "File names that are too long will get an error",
381         "File names that are too long will be truncated"
382 };
383
384 static const true_false_string tos_error_vdisable = {
385         "VDISABLE invalid",
386         "VDISABLE valid"
387 };
388
389
390 static int
391 dissect_mount_pathconf_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
392 {
393         guint32 pc_mask;
394         static const int * flags[] = {
395                 &hf_mount_pathconf_error_all,
396                 &hf_mount_pathconf_error_link_max,
397                 &hf_mount_pathconf_error_max_canon,
398                 &hf_mount_pathconf_error_max_input,
399                 &hf_mount_pathconf_error_name_max,
400                 &hf_mount_pathconf_error_path_max,
401                 &hf_mount_pathconf_error_pipe_buf,
402                 &hf_mount_pathconf_chown_restricted,
403                 &hf_mount_pathconf_no_trunc,
404                 &hf_mount_pathconf_error_vdisable,
405                 NULL
406         };
407         int offset = 0;
408
409         /*
410          * Extract the mask first, so we know which other fields the
411          * server was able to return to us.
412          */
413         pc_mask = tvb_get_ntohl(tvb, offset+OFFS_MASK) & 0xffff;
414         if (!(pc_mask & (PC_ERROR_LINK_MAX|PC_ERROR_ALL))) {
415                 dissect_rpc_uint32(tvb,tree,hf_mount_pathconf_link_max,offset);
416         }
417         offset += 4;
418
419         if (!(pc_mask & (PC_ERROR_MAX_CANON|PC_ERROR_ALL))) {
420                 proto_tree_add_item(tree,
421                                 hf_mount_pathconf_max_canon,tvb,offset+2,2,
422                                 tvb_get_ntohs(tvb,offset)&0xffff);
423         }
424         offset += 4;
425
426         if (!(pc_mask & (PC_ERROR_MAX_INPUT|PC_ERROR_ALL))) {
427                 proto_tree_add_item(tree,
428                                 hf_mount_pathconf_max_input,tvb,offset+2,2,
429                                 tvb_get_ntohs(tvb,offset)&0xffff);
430         }
431         offset += 4;
432
433         if (!(pc_mask & (PC_ERROR_NAME_MAX|PC_ERROR_ALL))) {
434                 proto_tree_add_item(tree,
435                                 hf_mount_pathconf_name_max,tvb,offset+2,2,
436                                 tvb_get_ntohs(tvb,offset)&0xffff);
437         }
438         offset += 4;
439
440         if (!(pc_mask & (PC_ERROR_PATH_MAX|PC_ERROR_ALL))) {
441                 proto_tree_add_item(tree,
442                                 hf_mount_pathconf_path_max,tvb,offset+2,2,
443                                 tvb_get_ntohs(tvb,offset)&0xffff);
444         }
445         offset += 4;
446
447         if (!(pc_mask & (PC_ERROR_PIPE_BUF|PC_ERROR_ALL))) {
448                 proto_tree_add_item(tree,
449                                 hf_mount_pathconf_pipe_buf,tvb,offset+2,2,
450                                 tvb_get_ntohs(tvb,offset)&0xffff);
451         }
452         offset += 4;
453
454         offset += 4;    /* skip "pc_xxx" pad field */
455
456         if (!(pc_mask & (PC_ERROR_VDISABLE|PC_ERROR_ALL))) {
457                 proto_tree_add_item(tree,
458                                 hf_mount_pathconf_vdisable,tvb,offset+3,1,
459                                 tvb_get_ntohs(tvb,offset)&0xffff);
460         }
461         offset += 4;
462
463         proto_tree_add_bitmask(tree, tvb, offset+2, hf_mount_pathconf_mask, ett_mount_pathconf_mask, flags, ENC_BIG_ENDIAN);
464
465         offset += 8;
466         return offset;
467 }
468
469
470 /* RFC 1813, Page 107 */
471 static int
472 dissect_mountstat3(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int offset, int hfindex, guint32 *status)
473 {
474         guint32 mountstat3;
475
476         mountstat3 = tvb_get_ntohl(tvb, offset);
477         if(mountstat3){
478                 col_append_fstr(
479                                 pinfo->cinfo, COL_INFO, " Error:%s",
480                                 val_to_str(mountstat3, mount3_mountstat3,
481                                     "Unknown (0x%08X)"));
482         }
483
484         offset = dissect_rpc_uint32(tvb,tree,hfindex,offset);
485         *status = mountstat3;
486         return offset;
487 }
488
489 /* RFC 1831, Page 109 */
490 static int
491 dissect_mount3_mnt_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
492 {
493         guint32 status;
494         guint32 auth_flavors;
495         guint32 auth_flavor;
496         guint32 auth_flavor_i;
497         int offset = 0;
498
499         offset = dissect_mountstat3(pinfo,tvb,tree,offset,hf_mount3_status,&status);
500
501         switch (status) {
502                 case 0:
503                         offset = dissect_nfs3_fh(tvb,offset,pinfo,tree,"fhandle",NULL,(rpc_call_info_value*)data);
504
505                         auth_flavors = tvb_get_ntohl(tvb, offset);
506                         proto_tree_add_uint(tree,hf_mount_flavors, tvb,
507                                 offset, 4, auth_flavors);
508                         offset += 4;
509                         for (auth_flavor_i = 0 ; auth_flavor_i < auth_flavors ; auth_flavor_i++) {
510                                 auth_flavor = tvb_get_ntohl(tvb, offset);
511                                 proto_tree_add_uint(tree,hf_mount_flavor, tvb,
512                                         offset, 4, auth_flavor);
513                                 offset += 4;
514                         }
515                 break;
516                 default:
517                         /* void */
518                 break;
519         }
520
521         return offset;
522 }
523
524 static int
525 dissect_sgi_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
526 {
527         proto_item* exportlist_item = NULL;
528         proto_tree* exportlist_tree = NULL;
529         int old_offset = offset;
530         const char* directory, *options;
531
532         if (tree) {
533                 exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist,
534                                         tvb, offset, -1, ENC_NA);
535                 if (exportlist_item)
536                         exportlist_tree = proto_item_add_subtree(exportlist_item,
537                                                 ett_mount_exportlist);
538         }
539
540         offset = dissect_rpc_string(tvb, exportlist_tree,
541                         hf_mount_exportlist_directory, offset, &directory);
542
543         offset = dissect_rpc_bool(tvb, exportlist_tree,
544                         hf_mount_has_options, offset);
545
546         offset = dissect_rpc_string(tvb, exportlist_tree, hf_mount_options,
547                          offset, &options);
548
549         if (exportlist_item) {
550                 /* now we have a nicer string */
551                 proto_item_set_text(exportlist_item,
552                         "Export List Entry: %s %s", directory,
553                         options);
554                 /* now we know, that exportlist is shorter */
555                 proto_item_set_len(exportlist_item, offset - old_offset);
556         }
557
558         return offset;
559 }
560
561 static int
562 dissect_mount_exportlist_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
563 {
564         return dissect_rpc_list(tvb, pinfo, tree, 0,
565                 dissect_sgi_exportlist, NULL);
566 }
567
568 #define ST_RDONLY       0x00000001
569 #define ST_NOSUID       0x00000002
570 #define ST_NOTRUNC      0x00000004
571 #define ST_NODEV        0x20000000
572 #define ST_GRPID        0x40000000
573 #define ST_LOCAL        0x80000000
574
575 static const true_false_string tos_st_rdonly = {
576         "Read-only file system",
577         "Read/Write file system"
578 };
579
580 static const true_false_string tos_st_nosuid = {
581         "Does not support setuid/setgid semantics",
582         "Supports setuid/setgid semantics"
583 };
584
585 static const true_false_string tos_st_notrunc = {
586         "Does not truncate filenames longer than NAME_MAX",
587         "Truncates filenames longer than NAME_MAX"
588 };
589
590 static const true_false_string tos_st_nodev = {
591         "Disallows opening of device files",
592         "Allows opening of device files"
593 };
594
595 static const true_false_string tos_st_grpid = {
596         "Group ID assigned from directory",
597         "Group ID not assigned from directory"
598 };
599
600 static const true_false_string tos_st_local = {
601         "File system is local",
602         "File system is not local"
603 };
604
605 static int
606 dissect_mount_statvfs_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
607 {
608         static const int * flags[] = {
609                 &hf_mount_statvfs_flag_rdonly,
610                 &hf_mount_statvfs_flag_nosuid,
611                 &hf_mount_statvfs_flag_notrunc,
612                 &hf_mount_statvfs_flag_nodev,
613                 &hf_mount_statvfs_flag_grpid,
614                 &hf_mount_statvfs_flag_local,
615                 NULL
616         };
617         int offset = 0;
618
619         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bsize, offset);
620         offset += 4;
621
622         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_frsize, offset);
623         offset += 4;
624
625         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_blocks, offset);
626         offset += 4;
627
628         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bfree, offset);
629         offset += 4;
630
631         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bavail, offset);
632         offset += 4;
633
634         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_files, offset);
635         offset += 4;
636
637         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_ffree, offset);
638         offset += 4;
639
640         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_favail, offset);
641         offset += 4;
642
643         dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_basetype, offset,
644                         16, TRUE, NULL);
645         offset += 16;
646
647         dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_fstr, offset, 32, FALSE, NULL);
648         offset += 32;
649
650         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_fsid, offset);
651         offset += 4;
652
653         proto_tree_add_bitmask(tree, tvb, offset, hf_mount_statvfs_flag, ett_mount_statvfs_flag, flags, ENC_BIG_ENDIAN);
654         offset += 4;
655
656         dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_namemax, offset);
657         offset += 4;
658
659         return offset;
660 }
661
662 /* proc number, "proc name", dissect_request, dissect_reply */
663
664 /* Mount protocol version 1, RFC 1094 */
665 static const vsff mount1_proc[] = {
666         { 0, "NULL",
667           dissect_rpc_void, dissect_rpc_void },
668         { MOUNTPROC_MNT,        "MNT",
669           dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
670         { MOUNTPROC_DUMP,       "DUMP",
671           dissect_rpc_void, dissect_mount_dump_reply },
672         { MOUNTPROC_UMNT,      "UMNT",
673           dissect_mount_dirpath_call, dissect_rpc_void },
674         { MOUNTPROC_UMNTALL,   "UMNTALL",
675           dissect_rpc_void, dissect_rpc_void },
676         { MOUNTPROC_EXPORT,    "EXPORT",
677           dissect_rpc_void, dissect_mount_export_reply },
678         { MOUNTPROC_EXPORTALL, "EXPORTALL",
679           dissect_rpc_void, dissect_mount_export_reply },
680         { 0, NULL, NULL, NULL }
681 };
682 static const value_string mount1_proc_vals[] = {
683         { 0, "NULL" },
684         { MOUNTPROC_MNT,       "MNT" },
685         { MOUNTPROC_DUMP,      "DUMP" },
686         { MOUNTPROC_UMNT,      "UMNT" },
687         { MOUNTPROC_UMNTALL,   "UMNTALL" },
688         { MOUNTPROC_EXPORT,    "EXPORT" },
689         { MOUNTPROC_EXPORTALL, "EXPORTALL" },
690         { 0, NULL }
691 };
692 /* end of mount version 1 */
693
694
695 /* Mount protocol version 2, private communication from somebody at Sun;
696    mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
697    POSIX "pathconf()" call. */
698 static const vsff mount2_proc[] = {
699         { 0,                    "NULL",
700           dissect_rpc_void, dissect_rpc_void },
701         { MOUNTPROC_MNT,        "MNT",
702           dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
703         { MOUNTPROC_DUMP,       "DUMP",
704           dissect_rpc_void, dissect_mount_dump_reply },
705         { MOUNTPROC_UMNT,      "UMNT",
706           dissect_mount_dirpath_call, dissect_rpc_void },
707         { MOUNTPROC_UMNTALL,   "UMNTALL",
708           dissect_rpc_void, dissect_rpc_void },
709         { MOUNTPROC_EXPORT,    "EXPORT",
710           dissect_rpc_void, dissect_mount_export_reply },
711         { MOUNTPROC_EXPORTALL, "EXPORTALL",
712           dissect_rpc_void, dissect_mount_export_reply },
713         { MOUNTPROC_PATHCONF,  "PATHCONF",
714           dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
715         { 0, NULL, NULL, NULL }
716 };
717 static const value_string mount2_proc_vals[] = {
718         { 0, "NULL" },
719         { MOUNTPROC_MNT,       "MNT" },
720         { MOUNTPROC_DUMP,      "DUMP" },
721         { MOUNTPROC_UMNT,      "UMNT" },
722         { MOUNTPROC_UMNTALL,   "UMNTALL" },
723         { MOUNTPROC_EXPORT,    "EXPORT" },
724         { MOUNTPROC_EXPORTALL, "EXPORTALL" },
725         { MOUNTPROC_PATHCONF,  "PATHCONF" },
726         { 0, NULL }
727 };
728 /* end of mount version 2 */
729
730
731 /* Mount protocol version 3, RFC 1813 */
732 static const vsff mount3_proc[] = {
733         { 0, "NULL",
734                 dissect_rpc_void, dissect_rpc_void },
735         { MOUNTPROC_MNT, "MNT",
736                 dissect_mount_dirpath_call, dissect_mount3_mnt_reply },
737         { MOUNTPROC_DUMP, "DUMP",
738                 dissect_rpc_void, dissect_mount_dump_reply },
739         { MOUNTPROC_UMNT, "UMNT",
740                 dissect_mount_dirpath_call, dissect_rpc_void },
741         { MOUNTPROC_UMNTALL, "UMNTALL",
742                 dissect_rpc_void, dissect_rpc_void },
743         { MOUNTPROC_EXPORT, "EXPORT",
744                 dissect_rpc_void, dissect_mount_export_reply },
745         { 0, NULL, NULL, NULL }
746 };
747 static const value_string mount3_proc_vals[] = {
748         { 0, "NULL" },
749         { MOUNTPROC_MNT, "MNT" },
750         { MOUNTPROC_DUMP, "DUMP" },
751         { MOUNTPROC_UMNT, "UMNT" },
752         { MOUNTPROC_UMNTALL, "UMNTALL" },
753         { MOUNTPROC_EXPORT, "EXPORT" },
754         { 0, NULL }
755 };
756 /* end of Mount protocol version 3 */
757
758 static const rpc_prog_vers_info mount_vers_info[] = {
759         { 1, mount1_proc, &hf_mount_procedure_v1 },
760         { 2, mount2_proc, &hf_mount_procedure_v2 },
761         { 3, mount3_proc, &hf_mount_procedure_v3 },
762 };
763
764 /* SGI mount protocol version 1; actually the same as v1 plus
765    MOUNTPROC_EXPORTLIST and MOUNTPROC_STATVFS */
766
767 static const vsff sgi_mount1_proc[] = {
768         { 0, "NULL",
769           dissect_rpc_void, dissect_rpc_void },
770         { MOUNTPROC_MNT,        "MNT",
771           dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
772         { MOUNTPROC_DUMP,       "DUMP",
773           dissect_rpc_void, dissect_mount_dump_reply },
774         { MOUNTPROC_UMNT,      "UMNT",
775           dissect_mount_dirpath_call, dissect_rpc_void },
776         { MOUNTPROC_UMNTALL,   "UMNTALL",
777           dissect_rpc_void, dissect_rpc_void },
778         { MOUNTPROC_EXPORT,    "EXPORT",
779           dissect_rpc_void, dissect_mount_export_reply },
780         { MOUNTPROC_EXPORTALL, "EXPORTALL",
781           dissect_rpc_void, dissect_mount_export_reply },
782         { MOUNTPROC_EXPORTLIST,"EXPORTLIST",
783           dissect_rpc_void, dissect_mount_exportlist_reply },
784         { MOUNTPROC_STATVFS,   "STATVFS",
785           dissect_mount_dirpath_call, dissect_mount_statvfs_reply },
786         { 0, NULL, NULL, NULL }
787 };
788 static const value_string sgi_mount1_proc_vals[] = {
789         { 0, "NULL" },
790         { MOUNTPROC_MNT,        "MNT" },
791         { MOUNTPROC_DUMP,       "DUMP" },
792         { MOUNTPROC_UMNT,       "UMNT" },
793         { MOUNTPROC_UMNTALL,    "UMNTALL" },
794         { MOUNTPROC_EXPORT,     "EXPORT" },
795         { MOUNTPROC_EXPORTALL,  "EXPORTALL" },
796         { MOUNTPROC_EXPORTLIST, "EXPORTLIST" },
797         { MOUNTPROC_STATVFS,    "STATVFS" },
798         { 0, NULL }
799 };
800 /* end of SGI mount protocol version 1 */
801
802 static const rpc_prog_vers_info sgi_mount_vers_info[] = {
803         { 1, sgi_mount1_proc, &hf_sgi_mount_procedure_v1 },
804 };
805
806 void
807 proto_register_mount(void)
808 {
809         static hf_register_info hf[] = {
810                 { &hf_mount_procedure_v1, {
811                         "V1 Procedure", "mount.procedure_v1", FT_UINT32, BASE_DEC,
812                         VALS(mount1_proc_vals), 0, NULL, HFILL }},
813                 { &hf_mount_procedure_v2, {
814                         "V2 Procedure", "mount.procedure_v2", FT_UINT32, BASE_DEC,
815                         VALS(mount2_proc_vals), 0, NULL, HFILL }},
816                 { &hf_mount_procedure_v3, {
817                         "V3 Procedure", "mount.procedure_v3", FT_UINT32, BASE_DEC,
818                         VALS(mount3_proc_vals), 0, NULL, HFILL }},
819                 { &hf_sgi_mount_procedure_v1, {
820                         "SGI V1 procedure", "mount.procedure_sgi_v1", FT_UINT32, BASE_DEC,
821                         VALS(sgi_mount1_proc_vals), 0, NULL, HFILL }},
822                 { &hf_mount_path, {
823                         "Path", "mount.path", FT_STRING, BASE_NONE,
824                         NULL, 0, NULL, HFILL }},
825                 { &hf_mount3_status, {
826                         "Status", "mount.status", FT_UINT32, BASE_DEC,
827                         VALS(mount3_mountstat3), 0, NULL, HFILL }},
828                 { &hf_mount_mountlist_hostname, {
829                         "Hostname", "mount.dump.hostname", FT_STRING, BASE_NONE,
830                         NULL, 0, NULL, HFILL }},
831                 { &hf_mount_mountlist_directory, {
832                         "Directory", "mount.dump.directory", FT_STRING, BASE_NONE,
833                         NULL, 0, NULL, HFILL }},
834                 { &hf_mount_mountlist, {
835                         "Mount List Entry", "mount.dump.entry", FT_NONE, BASE_NONE,
836                         NULL, 0, NULL, HFILL }},
837                 { &hf_mount_groups_group, {
838                         "Group", "mount.export.group", FT_STRING, BASE_NONE,
839                         NULL, 0, NULL, HFILL }},
840                 { &hf_mount_groups, {
841                         "Groups", "mount.export.groups", FT_NONE, BASE_NONE,
842                         NULL, 0, NULL, HFILL }},
843                 { &hf_mount_has_options, {
844                         "Has options", "mount.export.has_options", FT_UINT32,
845                          BASE_DEC, NULL, 0, NULL, HFILL }},
846                 { &hf_mount_options, {
847                         "Options", "mount.export.options", FT_STRING, BASE_NONE,
848                         NULL, 0, NULL, HFILL }},
849                 { &hf_mount_exportlist_directory, {
850                         "Directory", "mount.export.directory", FT_STRING, BASE_NONE,
851                         NULL, 0, NULL, HFILL }},
852                 { &hf_mount_exportlist, {
853                         "Export List Entry", "mount.export.entry", FT_NONE, BASE_NONE,
854                         NULL, 0, NULL, HFILL }},
855                 { &hf_mount_pathconf_link_max, {
856                         "Maximum number of links to a file", "mount.pathconf.link_max",
857                         FT_UINT32, BASE_DEC,
858                         NULL, 0, "Maximum number of links allowed to a file", HFILL }},
859                 { &hf_mount_pathconf_max_canon, {
860                         "Maximum terminal input line length", "mount.pathconf.max_canon",
861                         FT_UINT16, BASE_DEC,
862                         NULL, 0, "Max tty input line length", HFILL }},
863                 { &hf_mount_pathconf_max_input, {
864                         "Terminal input buffer size", "mount.pathconf.max_input",
865                         FT_UINT16, BASE_DEC,
866                         NULL, 0, NULL, HFILL }},
867                 { &hf_mount_pathconf_name_max, {
868                         "Maximum file name length", "mount.pathconf.name_max",
869                         FT_UINT16, BASE_DEC,
870                         NULL, 0, NULL, HFILL }},
871                 { &hf_mount_pathconf_path_max, {
872                         "Maximum path name length", "mount.pathconf.path_max",
873                         FT_UINT16, BASE_DEC,
874                         NULL, 0, NULL, HFILL }},
875                 { &hf_mount_pathconf_pipe_buf, {
876                         "Pipe buffer size", "mount.pathconf.pipe_buf",
877                         FT_UINT16, BASE_DEC,
878                         NULL, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL }},
879                 { &hf_mount_pathconf_vdisable, {
880                         "VDISABLE character", "mount.pathconf.vdisable_char",
881                         FT_UINT8, BASE_HEX,
882                         NULL, 0, "Character value to disable a terminal special character", HFILL }},
883                 { &hf_mount_pathconf_mask, {
884                         "Reply error/status bits", "mount.pathconf.mask",
885                         FT_UINT16, BASE_HEX,
886                         NULL, 0, "Bit mask with error and status bits", HFILL }},
887                 { &hf_mount_pathconf_error_all, {
888                         "ERROR_ALL",    "mount.pathconf.mask.error_all",
889                         FT_BOOLEAN, 16, TFS(&tos_error_all),
890                         PC_ERROR_ALL, NULL, HFILL }},
891                 { &hf_mount_pathconf_error_link_max, {
892                         "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
893                         FT_BOOLEAN, 16, TFS(&tos_error_link_max),
894                         PC_ERROR_LINK_MAX, NULL, HFILL }},
895                 { &hf_mount_pathconf_error_max_canon, {
896                         "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
897                         FT_BOOLEAN, 16, TFS(&tos_error_max_canon),
898                         PC_ERROR_MAX_CANON, NULL, HFILL }},
899                 { &hf_mount_pathconf_error_max_input, {
900                         "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
901                         FT_BOOLEAN, 16, TFS(&tos_error_max_input),
902                         PC_ERROR_MAX_INPUT, NULL, HFILL }},
903                 { &hf_mount_pathconf_error_name_max, {
904                         "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
905                         FT_BOOLEAN, 16, TFS(&tos_error_name_max),
906                         PC_ERROR_NAME_MAX, NULL, HFILL }},
907                 { &hf_mount_pathconf_error_path_max, {
908                         "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
909                         FT_BOOLEAN, 16, TFS(&tos_error_path_max),
910                         PC_ERROR_PATH_MAX, NULL, HFILL }},
911                 { &hf_mount_pathconf_error_pipe_buf, {
912                         "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
913                         FT_BOOLEAN, 16, TFS(&tos_error_pipe_buf),
914                         PC_ERROR_PIPE_BUF, NULL, HFILL }},
915                 { &hf_mount_pathconf_chown_restricted, {
916                         "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
917                         FT_BOOLEAN, 16, TFS(&tos_chown_restricted),
918                         PC_CHOWN_RESTRICTED, NULL, HFILL }},
919                 { &hf_mount_pathconf_no_trunc, {
920                         "NO_TRUNC", "mount.pathconf.mask.no_trunc",
921                         FT_BOOLEAN, 16, TFS(&tos_no_trunc),
922                         PC_NO_TRUNC, NULL, HFILL }},
923                 { &hf_mount_pathconf_error_vdisable, {
924                         "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
925                         FT_BOOLEAN, 16, TFS(&tos_error_vdisable),
926                         PC_ERROR_VDISABLE, NULL, HFILL }},
927                 { &hf_mount_statvfs_bsize, {
928                         "Block size", "mount.statvfs.f_bsize",
929                         FT_UINT32, BASE_DEC, NULL, 0,
930                         "File system block size", HFILL }},
931                 { &hf_mount_statvfs_frsize, {
932                         "Fragment size", "mount.statvfs.f_frsize",
933                         FT_UINT32, BASE_DEC, NULL, 0,
934                         "File system fragment size", HFILL }},
935                 { &hf_mount_statvfs_blocks, {
936                         "Blocks", "mount.statvfs.f_blocks",
937                         FT_UINT32, BASE_DEC, NULL, 0,
938                         "Total fragment sized blocks", HFILL }},
939                 { &hf_mount_statvfs_bfree, {
940                         "Blocks Free", "mount.statvfs.f_bfree",
941                         FT_UINT32, BASE_DEC, NULL, 0,
942                         "Free fragment sized blocks", HFILL }},
943                 { &hf_mount_statvfs_bavail, {
944                         "Blocks Available", "mount.statvfs.f_bavail",
945                         FT_UINT32, BASE_DEC, NULL, 0,
946                         "Available fragment sized blocks", HFILL }},
947                 { &hf_mount_statvfs_files, {
948                         "Files", "mount.statvfs.f_files",
949                         FT_UINT32, BASE_DEC, NULL, 0,
950                         "Total files/inodes", HFILL }},
951                 { &hf_mount_statvfs_ffree, {
952                         "Files Free", "mount.statvfs.f_ffree",
953                         FT_UINT32, BASE_DEC, NULL, 0,
954                         "Free files/inodes", HFILL }},
955                 { &hf_mount_statvfs_favail, {
956                         "Files Available", "mount.statvfs.f_favail",
957                         FT_UINT32, BASE_DEC, NULL, 0,
958                         "Available files/inodes",  HFILL }},
959                 { &hf_mount_statvfs_fsid, {
960                         "File system ID", "mount.statvfs.f_fsid",
961                         FT_UINT32, BASE_DEC, NULL, 0,
962                         "File system identifier", HFILL }},
963                 { &hf_mount_statvfs_basetype, {
964                         "Type", "mount.statvfs.f_basetype",
965                         FT_STRING, BASE_NONE, NULL, 0,
966                         "File system type", HFILL }},
967                 { &hf_mount_statvfs_flag, {
968                         "Flags", "mount.statvfs.f_flag",
969                         FT_UINT32, BASE_HEX, NULL, 0,
970                         "Flags bit-mask", HFILL }},
971                 { &hf_mount_statvfs_flag_rdonly, {
972                         "ST_RDONLY", "mount.statvfs.f_flag.st_rdonly",
973                         FT_BOOLEAN, 32, TFS(&tos_st_rdonly), ST_RDONLY,
974                         NULL, HFILL }},
975                 { &hf_mount_statvfs_flag_nosuid, {
976                         "ST_NOSUID", "mount.statvfs.f_flag.st_nosuid",
977                         FT_BOOLEAN, 32, TFS(&tos_st_nosuid), ST_NOSUID,
978                         NULL, HFILL }},
979                 { &hf_mount_statvfs_flag_notrunc, {
980                         "ST_NOTRUNC", "mount.statvfs.f_flag.st_notrunc",
981                         FT_BOOLEAN, 32, TFS(&tos_st_notrunc), ST_NOTRUNC,
982                         NULL, HFILL }},
983                 { &hf_mount_statvfs_flag_nodev, {
984                         "ST_NODEV", "mount.statvfs.f_flag.st_nodev",
985                          FT_BOOLEAN, 32, TFS(&tos_st_nodev), ST_NODEV,
986                         NULL, HFILL }},
987                 { &hf_mount_statvfs_flag_grpid, {
988                         "ST_GRPID", "mount.statvfs.f_flag.st_grpid",
989                         FT_BOOLEAN, 32, TFS(&tos_st_grpid), ST_GRPID,
990                         NULL, HFILL }},
991                 { &hf_mount_statvfs_flag_local, {
992                         "ST_LOCAL", "mount.statvfs.f_flag.st_local",
993                         FT_BOOLEAN, 32, TFS(&tos_st_local), ST_LOCAL,
994                         NULL, HFILL }},
995                 { &hf_mount_statvfs_namemax, {
996                         "Maximum file name length", "mount.statvfs.f_namemax",
997                         FT_UINT32, BASE_DEC, NULL, 0,
998                         NULL, HFILL }},
999                 { &hf_mount_statvfs_fstr, {
1000                         "File system specific string", "mount.statvfs.f_fstr",
1001                         FT_BYTES, BASE_NONE, NULL, 0,
1002                         NULL, HFILL }},
1003                 { &hf_mount_flavors, {
1004                         "Flavors", "mount.flavors", FT_UINT32, BASE_DEC,
1005                         NULL, 0, NULL, HFILL }},
1006                 { &hf_mount_flavor, {
1007                         "Flavor", "mount.flavor", FT_UINT32, BASE_DEC,
1008                         VALS(rpc_auth_flavor), 0, NULL, HFILL }},
1009         };
1010         static gint *ett[] = {
1011                 &ett_mount,
1012                 &ett_mount_mountlist,
1013                 &ett_mount_groups,
1014                 &ett_mount_exportlist,
1015                 &ett_mount_pathconf_mask,
1016                 &ett_mount_statvfs_flag,
1017         };
1018
1019         proto_mount = proto_register_protocol("Mount Service", "MOUNT",
1020             "mount");
1021         proto_sgi_mount = proto_register_protocol("SGI Mount Service",
1022             "SGI MOUNT", "sgimount");
1023         proto_register_field_array(proto_mount, hf, array_length(hf));
1024         proto_register_subtree_array(ett, array_length(ett));
1025 }
1026
1027 void
1028 proto_reg_handoff_mount(void)
1029 {
1030         /* Register the protocols as RPC */
1031         rpc_init_prog(proto_mount, MOUNT_PROGRAM, ett_mount,
1032             G_N_ELEMENTS(mount_vers_info), mount_vers_info);
1033         rpc_init_prog(proto_sgi_mount, SGI_MOUNT_PROGRAM, ett_mount,
1034             G_N_ELEMENTS(sgi_mount_vers_info), sgi_mount_vers_info);
1035 }
1036
1037 /*
1038  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1039  *
1040  * Local variables:
1041  * c-basic-offset: 8
1042  * tab-width: 8
1043  * indent-tabs-mode: t
1044  * End:
1045  *
1046  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1047  * :indentSize=8:tabSize=8:noTabs=false:
1048  */