New tap for tethereal: io statistics that provides frames/bytes counts for frames...
[obnox/wireshark/wip.git] / packet-mount.c
1 /* packet-mount.c
2  * Routines for mount dissection
3  *
4  * $Id: packet-mount.c,v 1.35 2002/11/01 00:48:38 sahlberg Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * Copied from packet-smb.c
11  *
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.
16  *
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.
21  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31
32 #include <string.h>
33
34 #include "packet-rpc.h"
35 #include "packet-mount.h"
36 #include "packet-nfs.h"
37
38
39 static int proto_mount = -1;
40 static int hf_mount_procedure_v1 = -1;
41 static int hf_mount_procedure_v2 = -1;
42 static int hf_mount_procedure_v3 = -1;
43 static int hf_mount_path = -1;
44 static int hf_mount3_status = -1;
45 static int hf_mount_mountlist_hostname = -1;
46 static int hf_mount_mountlist_directory = -1;
47 static int hf_mount_mountlist = -1;
48 static int hf_mount_groups_group = -1;
49 static int hf_mount_groups = -1;
50 static int hf_mount_exportlist_directory = -1;
51 static int hf_mount_exportlist = -1;
52 static int hf_mount_pathconf_link_max = -1;
53 static int hf_mount_pathconf_max_canon = -1;
54 static int hf_mount_pathconf_max_input = -1;
55 static int hf_mount_pathconf_name_max = -1;
56 static int hf_mount_pathconf_path_max = -1;
57 static int hf_mount_pathconf_pipe_buf = -1;
58 static int hf_mount_pathconf_vdisable = -1;
59 static int hf_mount_pathconf_mask = -1;
60 static int hf_mount_pathconf_error_all = -1;
61 static int hf_mount_pathconf_error_link_max = -1;
62 static int hf_mount_pathconf_error_max_canon = -1;
63 static int hf_mount_pathconf_error_max_input = -1;
64 static int hf_mount_pathconf_error_name_max = -1;
65 static int hf_mount_pathconf_error_path_max = -1;
66 static int hf_mount_pathconf_error_pipe_buf = -1;
67 static int hf_mount_pathconf_chown_restricted = -1;
68 static int hf_mount_pathconf_no_trunc = -1;
69 static int hf_mount_pathconf_error_vdisable = -1;
70 static int hf_mount_flavors = -1;
71 static int hf_mount_flavor = -1;
72
73 static gint ett_mount = -1;
74 static gint ett_mount_mountlist = -1;
75 static gint ett_mount_groups = -1;
76 static gint ett_mount_exportlist = -1;
77 static gint ett_mount_pathconf_mask = -1;
78
79 #define MAX_GROUP_NAME_LIST 128
80 static char group_name_list[MAX_GROUP_NAME_LIST];
81 static int  group_names_len;
82
83 /* RFC 1094, Page 24 */
84 /* This function dissects fhstatus for v1 and v2 of the mount protocol.
85  * Formally, hf_mount3_status only define the status codes returned by version
86  * 3 of the protocol.
87  * Though not formally defined in the standard, we use the same
88  * value-to-string mappings as version 3 since we belive that this mapping
89  * is consistant with most v1 and v2 implementations.
90  */
91 static int
92 dissect_fhstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
93 {
94         gint32 status;
95
96         status=tvb_get_ntohl(tvb,offset);
97         offset = dissect_rpc_uint32(tvb,tree,hf_mount3_status,offset);
98
99         switch (status) {
100                 case 0:
101                         offset = dissect_fhandle(tvb,offset,pinfo,tree,"fhandle");
102                 break;
103                 default:
104                         /* void */
105                 break;
106         }
107
108         return offset;
109 }
110
111
112 static int
113 dissect_mount_dirpath_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
114                 proto_tree *tree)
115 {
116         if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
117                 rpc_call_info_value *civ=pinfo->private_data;
118
119                 if(civ->request && (civ->proc==1)){
120                         unsigned char *host, *name;
121                         unsigned const char *dir;
122                         int len;
123
124                         host=ip_to_str(pinfo->dst.data);
125                         len=tvb_get_ntohl(tvb, offset);
126
127                         dir=tvb_get_ptr(tvb, offset+4, len);
128                         if(dir){
129                                 unsigned char *ptr;
130                                 name=g_malloc(strlen(host)+1+len+1+200);
131                                 ptr=name;
132                                 memcpy(ptr, host, strlen(host));
133                                 ptr+=strlen(host);
134                                 *ptr++=':';
135                                 memcpy(ptr, dir, len);
136                                 ptr+=len;
137                                 *ptr=0;
138
139                                 nfs_name_snoop_add_name(civ->xid, tvb, -1, strlen(name), 0, 0, name);
140                         }
141                 }
142         }
143
144         if ( tree )
145         {
146                 offset = dissect_rpc_string(tvb,tree,hf_mount_path,offset,NULL);
147         }
148
149         return offset;
150 }
151
152
153 /* RFC 1094, Page 25,26 */
154 static int
155 dissect_mount1_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
156 {
157         offset = dissect_fhstatus(tvb,offset,pinfo,tree);
158
159         return offset;
160 }
161
162
163
164 /* RFC 1094, Page 26 */
165 /* RFC 1813, Page 110 */
166 static int
167 dissect_mountlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
168 {
169         proto_item* lock_item = NULL;
170         proto_tree* lock_tree = NULL;
171         int old_offset = offset;
172         char* hostname;
173         char* directory;
174
175         if (tree) {
176                 lock_item = proto_tree_add_item(tree, hf_mount_mountlist, tvb,
177                                         offset, -1, FALSE);
178                 if (lock_item)
179                         lock_tree = proto_item_add_subtree(lock_item, ett_mount_mountlist);
180         }
181
182         offset = dissect_rpc_string(tvb, lock_tree,
183                         hf_mount_mountlist_hostname, offset, &hostname);
184         offset = dissect_rpc_string(tvb, lock_tree,
185                         hf_mount_mountlist_directory, offset, &directory);
186
187         if (lock_item) {
188                 /* now we have a nicer string */
189                 proto_item_set_text(lock_item, "Mount List Entry: %s:%s", hostname, directory);
190                 /* now we know, that mountlist is shorter */
191                 proto_item_set_len(lock_item, offset - old_offset);
192         }
193         g_free(hostname);
194         g_free(directory);
195
196         return offset;
197 }
198
199
200 /* RFC 1094, Page 26 */
201 /* RFC 1813, Page 110 */
202 static int
203 dissect_mount_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
204 {
205         offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_mountlist);
206
207         return offset;
208 }
209
210
211
212 /* RFC 1094, Page 26 */
213 /* RFC 1813, Page 110 */
214 static int
215 dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
216 {
217         int len,str_len;
218         len=tvb_get_ntohl(tvb,offset);
219         str_len=tvb_get_nstringz(tvb,offset+4,
220                 MAX_GROUP_NAME_LIST-5-group_names_len,
221                 group_name_list+group_names_len);
222         if((group_names_len>=(MAX_GROUP_NAME_LIST-5))||(str_len<0)){
223                 strcpy(group_name_list+(MAX_GROUP_NAME_LIST-5),"...");
224                 group_names_len=MAX_GROUP_NAME_LIST-1;
225         } else {
226                 group_names_len+=str_len;
227                 group_name_list[group_names_len++]=' ';
228         }
229         group_name_list[group_names_len]=0;
230
231         offset = dissect_rpc_string(tvb, tree,
232                         hf_mount_groups_group, offset, NULL);
233
234         return offset;
235 }
236
237
238 /* RFC 1094, Page 26 */
239 /* RFC 1813, Page 113 */
240 static int
241 dissect_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
242 {
243         proto_item* exportlist_item = NULL;
244         proto_tree* exportlist_tree = NULL;
245         int old_offset = offset;
246         int groups_offset;
247         proto_item* groups_item = NULL;
248         proto_item* groups_tree = NULL;
249         char* directory;
250
251         group_name_list[0]=0;
252         group_names_len=0;
253         if (tree) {
254                 exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, tvb,
255                                         offset, -1, FALSE);
256                 if (exportlist_item)
257                         exportlist_tree = proto_item_add_subtree(exportlist_item, ett_mount_exportlist);
258         }
259
260         offset = dissect_rpc_string(tvb, exportlist_tree,
261                         hf_mount_exportlist_directory, offset, &directory);
262         groups_offset = offset;
263
264         if (tree) {
265                 groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, tvb,
266                                         offset, -1, FALSE);
267                 if (groups_item)
268                         groups_tree = proto_item_add_subtree(groups_item, ett_mount_groups);
269         }
270
271         offset = dissect_rpc_list(tvb, pinfo, groups_tree, offset, dissect_group);
272         if (groups_item) {
273                 /* mark empty lists */
274                 if (offset - groups_offset == 4) {
275                         proto_item_set_text(groups_item, "Groups: empty");
276                 }
277
278                 /* now we know, that groups is shorter */
279                 proto_item_set_len(groups_item, offset - groups_offset);
280         }
281
282         if (exportlist_item) {
283                 /* now we have a nicer string */
284                 proto_item_set_text(exportlist_item, "Export List Entry: %s -> %s", directory,group_name_list);
285                 /* now we know, that exportlist is shorter */
286                 proto_item_set_len(exportlist_item, offset - old_offset);
287         }
288         g_free(directory);
289
290         return offset;
291 }
292
293
294 /* RFC 1094, Page 26 */
295 /* RFC 1813, Page 113 */
296 static int
297 dissect_mount_export_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
298 {
299         offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_exportlist);
300
301         return offset;
302 }
303
304
305 #define OFFS_MASK       32      /* offset of the "pc_mask" field */
306
307 #define PC_ERROR_ALL            0x0001
308 #define PC_ERROR_LINK_MAX       0x0002
309 #define PC_ERROR_MAX_CANON      0x0004
310 #define PC_ERROR_MAX_INPUT      0x0008
311 #define PC_ERROR_NAME_MAX       0x0010
312 #define PC_ERROR_PATH_MAX       0x0020
313 #define PC_ERROR_PIPE_BUF       0x0040
314 #define PC_CHOWN_RESTRICTED     0x0080
315 #define PC_NO_TRUNC             0x0100
316 #define PC_ERROR_VDISABLE       0x0200
317
318 static const true_false_string tos_error_all = {
319   "All info invalid",
320   "Some or all info valid"
321 };
322
323 static const true_false_string tos_error_link_max = {
324   "LINK_MAX invalid",
325   "LINK_MAX valid"
326 };
327
328 static const true_false_string tos_error_max_canon = {
329   "MAX_CANON invalid",
330   "MAX_CANON valid"
331 };
332
333 static const true_false_string tos_error_max_input = {
334   "MAX_INPUT invalid",
335   "MAX_INPUT valid"
336 };
337
338 static const true_false_string tos_error_name_max = {
339   "NAME_MAX invalid",
340   "NAME_MAX valid"
341 };
342
343 static const true_false_string tos_error_path_max = {
344   "PATH_MAX invalid",
345   "PATH_MAX valid"
346 };
347
348 static const true_false_string tos_error_pipe_buf = {
349   "PIPE_BUF invalid",
350   "PIPE_BUF valid"
351 };
352
353 static const true_false_string tos_chown_restricted = {
354   "Only a privileged user can change the ownership of a file",
355   "Users may give away their own files"
356 };
357
358 static const true_false_string tos_no_trunc = {
359   "File names that are too long will get an error",
360   "File names that are too long will be truncated"
361 };
362
363 static const true_false_string tos_error_vdisable = {
364   "VDISABLE invalid",
365   "VDISABLE valid"
366 };
367
368
369 static int
370 dissect_mount_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
371 {
372         int saved_offset;
373         guint32 pc_mask;
374         proto_item *lock_item;
375         proto_tree *lock_tree;
376
377         saved_offset=offset;
378         /*
379          * Extract the mask first, so we know which other fields the
380          * server was able to return to us.
381          */
382         pc_mask = tvb_get_ntohl(tvb, offset+OFFS_MASK) & 0xffff;
383         if (!(pc_mask & (PC_ERROR_LINK_MAX|PC_ERROR_ALL))) {
384                 if (tree) {
385                         dissect_rpc_uint32(tvb,tree,hf_mount_pathconf_link_max,offset);
386                 }
387         }
388         offset += 4;
389
390         if (!(pc_mask & (PC_ERROR_MAX_CANON|PC_ERROR_ALL))) {
391                 if (tree) {
392                         proto_tree_add_item(tree,
393                                 hf_mount_pathconf_max_canon,tvb,offset+2,2,
394                                 tvb_get_ntohs(tvb,offset)&0xffff);
395                 }
396         }
397         offset += 4;
398
399         if (!(pc_mask & (PC_ERROR_MAX_INPUT|PC_ERROR_ALL))) {
400                 if (tree) {
401                         proto_tree_add_item(tree,
402                                 hf_mount_pathconf_max_input,tvb,offset+2,2,
403                                 tvb_get_ntohs(tvb,offset)&0xffff);
404                 }
405         }
406         offset += 4;
407
408         if (!(pc_mask & (PC_ERROR_NAME_MAX|PC_ERROR_ALL))) {
409                 if (tree) {
410                         proto_tree_add_item(tree,
411                                 hf_mount_pathconf_name_max,tvb,offset+2,2,
412                                 tvb_get_ntohs(tvb,offset)&0xffff);
413                 }
414         }
415         offset += 4;
416
417         if (!(pc_mask & (PC_ERROR_PATH_MAX|PC_ERROR_ALL))) {
418                 if (tree) {
419                         proto_tree_add_item(tree,
420                                 hf_mount_pathconf_path_max,tvb,offset+2,2,
421                                 tvb_get_ntohs(tvb,offset)&0xffff);
422                 }
423         }
424         offset += 4;
425
426         if (!(pc_mask & (PC_ERROR_PIPE_BUF|PC_ERROR_ALL))) {
427                 if (tree) {
428                         proto_tree_add_item(tree,
429                                 hf_mount_pathconf_pipe_buf,tvb,offset+2,2,
430                                 tvb_get_ntohs(tvb,offset)&0xffff);
431                 }
432         }
433         offset += 4;
434
435         offset += 4;    /* skip "pc_xxx" pad field */
436
437         if (!(pc_mask & (PC_ERROR_VDISABLE|PC_ERROR_ALL))) {
438                 if (tree) {
439                         proto_tree_add_item(tree,
440                                 hf_mount_pathconf_vdisable,tvb,offset+3,1,
441                                 tvb_get_ntohs(tvb,offset)&0xffff);
442                 }
443         }
444         offset += 4;
445
446
447         if (tree) {
448                 lock_item = proto_tree_add_item(tree, hf_mount_pathconf_mask, tvb,
449                                         offset+2, 2, FALSE);
450
451                 lock_tree = proto_item_add_subtree(lock_item, ett_mount_pathconf_mask);
452                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_all, tvb,
453                     offset + 2, 2, pc_mask);
454
455                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_link_max, tvb,
456                     offset + 2, 2, pc_mask);
457                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_canon, tvb,
458                     offset + 2, 2, pc_mask);
459                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_input, tvb,
460                     offset + 2, 2, pc_mask);
461                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_name_max, tvb,
462                     offset + 2, 2, pc_mask);
463                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_path_max, tvb,
464                     offset + 2, 2, pc_mask);
465                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_pipe_buf, tvb,
466                     offset + 2, 2, pc_mask);
467                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_chown_restricted, tvb,
468                     offset + 2, 2, pc_mask);
469                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_no_trunc, tvb,
470                     offset + 2, 2, pc_mask);
471                 proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_vdisable, tvb,
472                     offset + 2, 2, pc_mask);
473         }
474
475         offset += 8;
476         return offset;
477 }
478
479 /* RFC 1813, Page 107 */
480 static const value_string mount3_mountstat3[] =
481 {
482         {       0,      "OK" },
483         {       1,      "ERR_PERM" },
484         {       2,      "ERR_NOENT" },
485         {       5,      "ERR_IO" },
486         {       13,     "ERR_ACCESS" },
487         {       20,     "ERR_NOTDIR" },
488         {       22,     "ERR_INVAL" },
489         {       63,     "ERR_NAMETOOLONG" },
490         {       10004,  "ERR_NOTSUPP" },
491         {       10006,  "ERR_SERVERFAULT" },
492         {       0,      NULL }
493 };
494
495
496 /* RFC 1813, Page 107 */
497 static int
498 dissect_mountstat3(tvbuff_t *tvb, proto_tree *tree, int offset, int hfindex, guint32 *status)
499 {
500         guint32 mountstat3;
501
502         mountstat3 = tvb_get_ntohl(tvb, offset);
503
504         offset = dissect_rpc_uint32(tvb,tree,hfindex,offset);
505         *status = mountstat3;
506         return offset;
507 }
508
509 /* RFC 1831, Page 109 */
510 static int
511 dissect_mount3_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
512 {
513         guint32 status;
514         guint32 auth_flavors;
515         guint32 auth_flavor;
516         guint32 auth_flavor_i;
517
518         offset = dissect_mountstat3(tvb,tree,offset,hf_mount3_status,&status);
519
520         switch (status) {
521                 case 0:
522                         offset = dissect_nfs_fh3(tvb,offset,pinfo,tree,"fhandle");
523
524                         auth_flavors = tvb_get_ntohl(tvb, offset);
525                         proto_tree_add_uint(tree,hf_mount_flavors, tvb,
526                                 offset, 4, auth_flavors);
527                         offset += 4;
528                         for (auth_flavor_i = 0 ; auth_flavor_i < auth_flavors ; auth_flavor_i++) {
529                                 auth_flavor = tvb_get_ntohl(tvb, offset);
530                                 proto_tree_add_uint(tree,hf_mount_flavor, tvb,
531                                         offset, 4, auth_flavor);
532                                 offset += 4;
533                         }
534                 break;
535                 default:
536                         /* void */
537                 break;
538         }
539
540         return offset;
541 }
542
543
544 /* proc number, "proc name", dissect_request, dissect_reply */
545 /* NULL as function pointer means: type of arguments is "void". */
546
547 /* Mount protocol version 1, RFC 1094 */
548 static const vsff mount1_proc[] = {
549     { 0, "NULL", NULL, NULL },
550     { MOUNTPROC_MNT,        "MNT",
551                 dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
552     { MOUNTPROC_DUMP,       "DUMP",
553                 NULL, dissect_mount_dump_reply },
554     { MOUNTPROC_UMNT,      "UMNT",
555                 dissect_mount_dirpath_call, NULL },
556     { MOUNTPROC_UMNTALL,   "UMNTALL",
557                 NULL, NULL },
558     { MOUNTPROC_EXPORT,    "EXPORT",
559                 NULL, dissect_mount_export_reply },
560     { MOUNTPROC_EXPORTALL, "EXPORTALL",
561                 NULL, dissect_mount_export_reply },
562     { 0, NULL, NULL, NULL }
563 };
564 static const value_string mount1_proc_vals[] = {
565     { 0, "NULL" },
566     { MOUNTPROC_MNT,       "MNT" },
567     { MOUNTPROC_DUMP,      "DUMP" },
568     { MOUNTPROC_UMNT,      "UMNT" },
569     { MOUNTPROC_UMNTALL,   "UMNTALL" },
570     { MOUNTPROC_EXPORT,    "EXPORT" },
571     { MOUNTPROC_EXPORTALL, "EXPORTALL" },
572     { 0, NULL }
573 };
574 /* end of mount version 1 */
575
576
577 /* Mount protocol version 2, private communication from somebody at Sun;
578    mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
579    POSIX "pathconf()" call. */
580 static const vsff mount2_proc[] = {
581     { 0, "NULL", NULL, NULL },
582     { MOUNTPROC_MNT,        "MNT",
583                 dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
584     { MOUNTPROC_DUMP,       "DUMP",
585                 NULL, dissect_mount_dump_reply },
586     { MOUNTPROC_UMNT,      "UMNT",
587                 dissect_mount_dirpath_call, NULL },
588     { MOUNTPROC_UMNTALL,   "UMNTALL",
589                 NULL, NULL },
590     { MOUNTPROC_EXPORT,    "EXPORT",
591                 NULL, dissect_mount_export_reply },
592     { MOUNTPROC_EXPORTALL, "EXPORTALL",
593                 NULL, dissect_mount_export_reply },
594     { MOUNTPROC_PATHCONF,  "PATHCONF",
595                 dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
596     { 0, NULL, NULL, NULL }
597 };
598 static const value_string mount2_proc_vals[] = {
599     { 0, "NULL" },
600     { MOUNTPROC_MNT,       "MNT" },
601     { MOUNTPROC_DUMP,      "DUMP" },
602     { MOUNTPROC_UMNT,      "UMNT" },
603     { MOUNTPROC_UMNTALL,   "UMNTALL" },
604     { MOUNTPROC_EXPORT,    "EXPORT" },
605     { MOUNTPROC_EXPORTALL, "EXPORTALL" },
606     { MOUNTPROC_PATHCONF,  "PATHCONF" },
607     { 0, NULL }
608 };
609 /* end of mount version 2 */
610
611
612 /* Mount protocol version 3, RFC 1813 */
613 static const vsff mount3_proc[] = {
614         { 0, "NULL", NULL, NULL },
615         { MOUNTPROC_MNT, "MNT",
616                 dissect_mount_dirpath_call, dissect_mount3_mnt_reply },
617         { MOUNTPROC_DUMP, "DUMP",
618                 NULL, dissect_mount_dump_reply },
619         { MOUNTPROC_UMNT, "UMNT",
620                 dissect_mount_dirpath_call, NULL },
621         { MOUNTPROC_UMNTALL, "UMNTALL",
622                 NULL, NULL },
623         { MOUNTPROC_EXPORT, "EXPORT",
624                 NULL, dissect_mount_export_reply },
625         { 0, NULL, NULL, NULL }
626 };
627 static const value_string mount3_proc_vals[] = {
628         { 0, "NULL" },
629         { MOUNTPROC_MNT, "MNT" },
630         { MOUNTPROC_DUMP, "DUMP" },
631         { MOUNTPROC_UMNT, "UMNT" },
632         { MOUNTPROC_UMNTALL, "UMNTALL" },
633         { MOUNTPROC_EXPORT, "EXPORT" },
634         { 0, NULL }
635 };
636 /* end of Mount protocol version 3 */
637
638
639 void
640 proto_register_mount(void)
641 {
642         static hf_register_info hf[] = {
643                 { &hf_mount_procedure_v1, {
644                         "V1 Procedure", "mount.procedure_v1", FT_UINT32, BASE_DEC,
645                         VALS(mount1_proc_vals), 0, "V1 Procedure", HFILL }},
646                 { &hf_mount_procedure_v2, {
647                         "V2 Procedure", "mount.procedure_v2", FT_UINT32, BASE_DEC,
648                         VALS(mount2_proc_vals), 0, "V2 Procedure", HFILL }},
649                 { &hf_mount_procedure_v3, {
650                         "V3 Procedure", "mount.procedure_v3", FT_UINT32, BASE_DEC,
651                         VALS(mount3_proc_vals), 0, "V3 Procedure", HFILL }},
652                 { &hf_mount_path, {
653                         "Path", "mount.path", FT_STRING, BASE_DEC,
654                         NULL, 0, "Path", HFILL }},
655                 { &hf_mount3_status, {
656                         "Status", "mount.status", FT_UINT32, BASE_DEC,
657                         VALS(mount3_mountstat3), 0, "Status", HFILL }},
658                 { &hf_mount_mountlist_hostname, {
659                         "Hostname", "mount.dump.hostname", FT_STRING, BASE_DEC,
660                         NULL, 0, "Hostname", HFILL }},
661                 { &hf_mount_mountlist_directory, {
662                         "Directory", "mount.dump.directory", FT_STRING, BASE_DEC,
663                         NULL, 0, "Directory", HFILL }},
664                 { &hf_mount_mountlist, {
665                         "Mount List Entry", "mount.dump.entry", FT_NONE, 0,
666                         NULL, 0, "Mount List Entry", HFILL }},
667                 { &hf_mount_groups_group, {
668                         "Group", "mount.export.group", FT_STRING, BASE_DEC,
669                         NULL, 0, "Group", HFILL }},
670                 { &hf_mount_groups, {
671                         "Groups", "mount.export.groups", FT_NONE, 0,
672                         NULL, 0, "Groups", HFILL }},
673                 { &hf_mount_exportlist_directory, {
674                         "Directory", "mount.export.directory", FT_STRING, BASE_DEC,
675                         NULL, 0, "Directory", HFILL }},
676                 { &hf_mount_exportlist, {
677                         "Export List Entry", "mount.export.entry", FT_NONE, 0,
678                         NULL, 0, "Export List Entry", HFILL }},
679                 { &hf_mount_pathconf_link_max, {
680                         "Maximum number of links to a file", "mount.pathconf.link_max",
681                         FT_UINT32, BASE_DEC,
682                         NULL, 0, "Maximum number of links allowed to a file", HFILL }},
683                 { &hf_mount_pathconf_max_canon, {
684                         "Maximum terminal input line length", "mount.pathconf.max_canon",
685                         FT_UINT16, BASE_DEC,
686                         NULL, 0, "Max tty input line length", HFILL }},
687                 { &hf_mount_pathconf_max_input, {
688                         "Terminal input buffer size", "mount.pathconf.max_input",
689                         FT_UINT16, BASE_DEC,
690                         NULL, 0, "Terminal input buffer size", HFILL }},
691                 { &hf_mount_pathconf_name_max, {
692                         "Maximum file name length", "mount.pathconf.name_max",
693                         FT_UINT16, BASE_DEC,
694                         NULL, 0, "Maximum file name length", HFILL }},
695                 { &hf_mount_pathconf_path_max, {
696                         "Maximum path name length", "mount.pathconf.path_max",
697                         FT_UINT16, BASE_DEC,
698                         NULL, 0, "Maximum path name length", HFILL }},
699                 { &hf_mount_pathconf_pipe_buf, {
700                         "Pipe buffer size", "mount.pathconf.pipe_buf",
701                         FT_UINT16, BASE_DEC,
702                         NULL, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL }},
703                 { &hf_mount_pathconf_vdisable, {
704                         "VDISABLE character", "mount.pathconf.vdisable_char",
705                         FT_UINT8, BASE_HEX,
706                         NULL, 0, "Character value to disable a terminal special character", HFILL }},
707                 { &hf_mount_pathconf_mask, {
708                         "Reply error/status bits", "mount.pathconf.mask",
709                         FT_UINT16, BASE_HEX,
710                         NULL, 0, "Bit mask with error and status bits", HFILL }},
711                 { &hf_mount_pathconf_error_all, {
712                         "ERROR_ALL",    "mount.pathconf.mask.error_all",
713                         FT_BOOLEAN, 16, TFS(&tos_error_all),
714                         PC_ERROR_ALL, "", HFILL }},
715                 { &hf_mount_pathconf_error_link_max, {
716                         "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
717                         FT_BOOLEAN, 16, TFS(&tos_error_link_max),
718                         PC_ERROR_LINK_MAX, "", HFILL }},
719                 { &hf_mount_pathconf_error_max_canon, {
720                         "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
721                         FT_BOOLEAN, 16, TFS(&tos_error_max_canon),
722                         PC_ERROR_MAX_CANON, "", HFILL }},
723                 { &hf_mount_pathconf_error_max_input, {
724                         "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
725                         FT_BOOLEAN, 16, TFS(&tos_error_max_input),
726                         PC_ERROR_MAX_INPUT, "", HFILL }},
727                 { &hf_mount_pathconf_error_name_max, {
728                         "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
729                         FT_BOOLEAN, 16, TFS(&tos_error_name_max),
730                         PC_ERROR_NAME_MAX, "", HFILL }},
731                 { &hf_mount_pathconf_error_path_max, {
732                         "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
733                         FT_BOOLEAN, 16, TFS(&tos_error_path_max),
734                         PC_ERROR_PATH_MAX, "", HFILL }},
735                 { &hf_mount_pathconf_error_pipe_buf, {
736                         "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
737                         FT_BOOLEAN, 16, TFS(&tos_error_pipe_buf),
738                         PC_ERROR_PIPE_BUF, "", HFILL }},
739                 { &hf_mount_pathconf_chown_restricted, {
740                         "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
741                         FT_BOOLEAN, 16, TFS(&tos_chown_restricted),
742                         PC_CHOWN_RESTRICTED, "", HFILL }},
743                 { &hf_mount_pathconf_no_trunc, {
744                         "NO_TRUNC", "mount.pathconf.mask.no_trunc",
745                         FT_BOOLEAN, 16, TFS(&tos_no_trunc),
746                         PC_NO_TRUNC, "", HFILL }},
747                 { &hf_mount_pathconf_error_vdisable, {
748                         "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
749                         FT_BOOLEAN, 16, TFS(&tos_error_vdisable),
750                         PC_ERROR_VDISABLE, "", HFILL }},
751                 { &hf_mount_flavors, {
752                         "Flavors", "mount.flavors", FT_UINT32, BASE_DEC,
753                         NULL, 0, "Flavors", HFILL }},
754                 { &hf_mount_flavor, {
755                         "Flavor", "mount.flavor", FT_UINT32, BASE_DEC,
756                         VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
757         };
758         static gint *ett[] = {
759                 &ett_mount,
760                 &ett_mount_mountlist,
761                 &ett_mount_groups,
762                 &ett_mount_exportlist,
763                 &ett_mount_pathconf_mask,
764         };
765
766         proto_mount = proto_register_protocol("Mount Service", "MOUNT", "mount");
767         proto_register_field_array(proto_mount, hf, array_length(hf));
768         proto_register_subtree_array(ett, array_length(ett));
769 }
770
771 void
772 proto_reg_handoff_mount(void)
773 {
774         /* Register the protocol as RPC */
775         rpc_init_prog(proto_mount, MOUNT_PROGRAM, ett_mount);
776         /* Register the procedure tables */
777         rpc_init_proc_table(MOUNT_PROGRAM, 1, mount1_proc, hf_mount_procedure_v1);
778         rpc_init_proc_table(MOUNT_PROGRAM, 2, mount2_proc, hf_mount_procedure_v2);
779         rpc_init_proc_table(MOUNT_PROGRAM, 3, mount3_proc, hf_mount_procedure_v3);
780 }