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