Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-portmap.c
1 /* packet-portmap.c
2  * Routines for portmap dissection
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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
33 #include "packet-rpc.h"
34 #include "packet-portmap.h"
35 #include <epan/ipproto.h>
36 #include <epan/conversation.h>
37 #include <epan/packet_info.h>
38
39 /*
40  * See:
41  *
42  *      RFC 1833, "Binding Protocols for ONC RPC Version 2".
43  */
44
45 static int proto_portmap = -1;
46 static int hf_portmap_procedure_v1 = -1;
47 static int hf_portmap_procedure_v2 = -1;
48 static int hf_portmap_procedure_v3 = -1;
49 static int hf_portmap_procedure_v4 = -1;
50 static int hf_portmap_proto = -1;
51 static int hf_portmap_prog = -1;
52 static int hf_portmap_proc = -1;
53 static int hf_portmap_version = -1;
54 static int hf_portmap_port = -1;
55 static int hf_portmap_answer = -1;
56 static int hf_portmap_args = -1;
57 static int hf_portmap_result = -1;
58 static int hf_portmap_rpcb = -1;
59 static int hf_portmap_rpcb_prog = -1;
60 static int hf_portmap_rpcb_version = -1;
61 static int hf_portmap_rpcb_netid = -1;
62 static int hf_portmap_rpcb_addr = -1;
63 static int hf_portmap_rpcb_owner = -1;
64 static int hf_portmap_uaddr = -1;
65
66
67 static gint ett_portmap = -1;
68 static gint ett_portmap_rpcb = -1;
69 static gint ett_portmap_entry = -1;
70
71 static dissector_handle_t rpc_handle;
72
73 /* Dissect a getport call */
74 static int
75 dissect_getport_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
76         proto_tree *tree)
77 {
78         guint32 proto, version;
79         guint32 prog;
80         const char *prog_name;
81         const char *proto_name;
82
83         /* make sure we remember protocol type until the reply packet */
84         if(!pinfo->fd->flags.visited){
85                 rpc_call_info_value *rpc_call=pinfo->private_data;
86                 if(rpc_call){
87                         proto = tvb_get_ntohl(tvb, offset+8);
88                         if(proto==IP_PROTO_UDP){  /* only do this for UDP */
89                                 rpc_call->private_data=(void *)PT_UDP;
90                         }
91                 }
92         }
93
94         /* program */
95         prog = tvb_get_ntohl(tvb, offset+0);
96         prog_name = rpc_prog_name(prog);
97         proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
98                 offset, 4, prog, "Program: %s (%u)",
99                 prog_name, prog);
100         if (check_col(pinfo->cinfo, COL_INFO)) {
101                 col_append_fstr(pinfo->cinfo, COL_INFO,  " %s(%u)", prog_name, prog);
102
103         }
104         proto_item_append_text(tree, " GETPORT Call %s(%u)", prog_name, prog);
105
106         /* version */
107         version = tvb_get_ntohl(tvb, offset+4);
108         proto_tree_add_item(tree, hf_portmap_version, tvb,
109                 offset+4, 4, FALSE);
110         if (check_col(pinfo->cinfo, COL_INFO)) {
111                 col_append_fstr(pinfo->cinfo, COL_INFO,  " V:%d", version);
112
113         }
114         proto_item_append_text(tree, " Version:%d", version);
115
116
117         /* protocol */
118         proto = tvb_get_ntohl(tvb, offset+8);
119         proto_name = ipprotostr(proto);
120         proto_tree_add_uint_format(tree, hf_portmap_proto, tvb,
121                 offset+8, 4, proto, "Proto: %s (%u)", proto_name, proto);
122         if (check_col(pinfo->cinfo, COL_INFO)) {
123                 col_append_fstr(pinfo->cinfo, COL_INFO,  " %s", proto_name);
124
125         }
126         proto_item_append_text(tree, " %s", proto_name);
127
128         /* port */
129         proto_tree_add_item(tree, hf_portmap_port, tvb,
130                 offset+12, 4, FALSE);
131
132         return offset+16;
133 }
134
135 static int
136 dissect_getport_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
137         proto_tree *tree)
138 {
139         guint32 portx;
140
141         /* we might have learnt a <ipaddr><protocol><port> mapping for ONC-RPC*/
142         if(!pinfo->fd->flags.visited){
143                 rpc_call_info_value *rpc_call=pinfo->private_data;
144                 /* only do this for UDP, TCP does not need anything like this */
145                 if(rpc_call && (GPOINTER_TO_UINT(rpc_call->private_data)==PT_UDP) ){
146                         guint32 port;
147                         port=tvb_get_ntohl(tvb, offset);
148                         if(port){
149                                 conversation_t *conv;
150                                 conv=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, (port_type)rpc_call->private_data, port, 0, NO_ADDR_B|NO_PORT_B);
151                                 if(!conv){
152                                         conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, (port_type)rpc_call->private_data, port, 0, NO_ADDR2|NO_PORT2);
153                                 }
154                                 conversation_set_dissector(conv, rpc_handle);
155                         }
156                 }
157         }
158
159         portx = tvb_get_ntohl(tvb, offset);
160         offset = dissect_rpc_uint32(tvb, tree, hf_portmap_port,
161             offset);
162         proto_item_append_text(tree, " GETPORT Reply Port:%d", portx);
163         if(portx){
164                 if (check_col(pinfo->cinfo, COL_INFO)) {
165                         col_append_fstr(pinfo->cinfo, COL_INFO,  " Port:%d", portx);
166                 }
167                 proto_item_append_text(tree, " Port:%d", portx);
168         } else {
169                 col_append_str(pinfo->cinfo, COL_INFO,  " PROGRAM_NOT_AVAILABLE");
170                 proto_item_append_text(tree, " PROGRAM_NOT_AVAILABLE");
171         }
172
173         return offset;
174 }
175
176 /* Dissect a 'set' call */
177 static int
178 dissect_set_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
179         proto_tree *tree)
180 {
181         guint32 proto;
182         guint32 prog;
183
184         if ( tree )
185         {
186                 prog = tvb_get_ntohl(tvb, offset+0);
187                 proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
188                         offset, 4, prog, "Program: %s (%d)",
189                         rpc_prog_name(prog), prog);
190                 proto_tree_add_item(tree, hf_portmap_version, tvb,
191                         offset+4, 4, FALSE);
192
193                 proto = tvb_get_ntohl(tvb, offset+8);
194                 proto_tree_add_uint_format(tree, hf_portmap_proto,tvb,
195                         offset+8, 4, proto, "Proto: %s (%d)", ipprotostr(proto), proto);
196
197                 proto_tree_add_item(tree, hf_portmap_port, tvb,
198                         offset+12, 4, FALSE);
199         }
200
201         return offset+16;
202 }
203
204 /* Dissect a 'unset' call */
205 static int
206 dissect_unset_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
207         proto_tree *tree)
208 {
209         guint32 proto;
210         guint32 prog;
211
212         if ( tree )
213         {
214                 prog = tvb_get_ntohl(tvb, offset+0);
215                 proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
216                         offset, 4, prog, "Program: %s (%d)",
217                         rpc_prog_name(prog), prog);
218                 proto_tree_add_item(tree, hf_portmap_version, tvb,
219                         offset+4, 4, FALSE);
220
221                 proto = tvb_get_ntohl(tvb, offset+8);
222                 proto_tree_add_uint(tree, hf_portmap_proto, tvb,
223                         offset+8, 4, proto);
224
225                 proto_tree_add_item(tree, hf_portmap_port, tvb,
226                         offset+12, 4, FALSE);
227         }
228
229         return offset+16;
230 }
231
232 static int
233 dissect_set_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
234         proto_tree *tree)
235 {
236         offset = dissect_rpc_bool(tvb, tree, hf_portmap_answer,
237             offset);
238         return offset;
239 }
240
241 static int
242 dissect_dump_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
243         proto_tree *tree)
244 {
245         int prog, version, proto, port;
246         proto_item *ti, *subtree;
247
248         prog = tvb_get_ntohl(tvb, offset+0);
249         version = tvb_get_ntohl(tvb, offset+4);
250         proto = tvb_get_ntohl(tvb, offset+8);
251         port = tvb_get_ntohl(tvb, offset+12);
252         if ( tree )
253         {
254                 ti = proto_tree_add_text(tree, tvb, offset, 16,
255                         "Map Entry: %s (%u) V%d",
256                         rpc_prog_name(prog), prog, version);
257                 subtree = proto_item_add_subtree(ti, ett_portmap_entry);
258
259                 proto_tree_add_uint_format(subtree, hf_portmap_prog, tvb,
260                         offset+0, 4, prog,
261                         "Program: %s (%u)", rpc_prog_name(prog), prog);
262                 proto_tree_add_uint(subtree, hf_portmap_version, tvb,
263                         offset+4, 4, version);
264                 proto_tree_add_uint_format(subtree, hf_portmap_proto, tvb,
265                         offset+8, 4, proto,
266                         "Protocol: %s (0x%02x)", ipprotostr(proto), proto);
267                 proto_tree_add_uint(subtree, hf_portmap_port, tvb,
268                         offset+12, 4, port);
269         }
270         offset += 16;
271         return offset;
272 }
273
274 static int
275 dissect_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
276         proto_tree *tree)
277 {
278         offset = dissect_rpc_list(tvb, pinfo, tree, offset,
279                 dissect_dump_entry);
280         return offset;
281 }
282
283 /* Dissect a callit call */
284 static int
285 dissect_callit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
286         proto_tree *tree)
287 {
288         guint32 prog, vers, proc;
289
290         prog = tvb_get_ntohl(tvb, offset+0);
291         if ( tree )
292         {
293                 proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
294                         offset, 4, prog, "Program: %s (%u)",
295                         rpc_prog_name(prog), prog);
296         }
297
298         vers = tvb_get_ntohl(tvb, offset+4);
299         if ( tree )
300         {
301                 proto_tree_add_uint(tree, hf_portmap_version, tvb,
302                         offset+4, 4, vers);
303         }
304
305         proc = tvb_get_ntohl(tvb, offset+8);
306         if ( tree )
307         {
308                 proto_tree_add_uint_format(tree, hf_portmap_proc, tvb,
309                         offset+8, 4, proc, "Procedure: %s (%u)",
310                         rpc_proc_name(prog, vers, proc), proc);
311         }
312
313         offset += 12;
314
315         /* Dissect the arguments for this procedure.
316            Make the columns non-writable, so the dissector won't change
317            them out from under us. */
318         col_set_writable(pinfo->cinfo, FALSE);
319         offset = dissect_rpc_indir_call(tvb, pinfo, tree, offset,
320                 hf_portmap_args, prog, vers, proc);
321
322         return offset;
323 }
324
325 /* Dissect a callit reply */
326 static int
327 dissect_callit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
328         proto_tree *tree)
329 {
330         if ( tree )
331         {
332                 proto_tree_add_item(tree, hf_portmap_port, tvb,
333                         offset, 4, FALSE);
334         }
335         offset += 4;
336
337         /* Dissect the result of this procedure.
338            Make the columns non-writable, so the dissector won't change
339            them out from under us. */
340         col_set_writable(pinfo->cinfo, FALSE);
341         offset = dissect_rpc_indir_reply(tvb, pinfo, tree, offset,
342                 hf_portmap_result, hf_portmap_prog, hf_portmap_version,
343                 hf_portmap_proc);
344
345         return offset;
346 }
347
348 /* proc number, "proc name", dissect_request, dissect_reply */
349 /* NULL as function pointer means: type of arguments is "void". */
350 static const vsff portmap1_proc[] = {
351         { PORTMAPPROC_NULL,     "NULL",         NULL,   NULL },
352         { PORTMAPPROC_SET,      "SET",          NULL,   NULL },
353         { PORTMAPPROC_UNSET,    "UNSET",        NULL,   NULL },
354         { PORTMAPPROC_GETPORT,  "GETPORT",      NULL,   NULL },
355         { PORTMAPPROC_DUMP,     "DUMP",         NULL,   NULL },
356         { PORTMAPPROC_CALLIT,   "CALLIT",       NULL,   NULL },
357         { 0,                    NULL,           NULL,   NULL }
358 };
359 static const value_string portmap1_proc_vals[] = {
360         { PORTMAPPROC_NULL,     "NULL" },
361         { PORTMAPPROC_SET,      "SET" },
362         { PORTMAPPROC_UNSET,    "UNSET" },
363         { PORTMAPPROC_GETPORT,  "GETPORT" },
364         { PORTMAPPROC_DUMP,     "DUMP" },
365         { PORTMAPPROC_CALLIT,   "CALLIT" },
366         { 0,                    NULL }
367 };
368 /* end of Portmap version 1 */
369
370 static const vsff portmap2_proc[] = {
371         { PORTMAPPROC_NULL, "NULL",
372                 NULL, NULL },
373         { PORTMAPPROC_SET, "SET",
374                 dissect_set_call, dissect_set_reply },
375         { PORTMAPPROC_UNSET, "UNSET",
376                 dissect_unset_call, dissect_set_reply },
377         { PORTMAPPROC_GETPORT,  "GETPORT",
378                 dissect_getport_call, dissect_getport_reply },
379         { PORTMAPPROC_DUMP, "DUMP",
380                 NULL, dissect_dump_reply },
381         { PORTMAPPROC_CALLIT, "CALLIT",
382                 dissect_callit_call, dissect_callit_reply },
383         { 0, NULL, NULL, NULL }
384 };
385 static const value_string portmap2_proc_vals[] = {
386         { PORTMAPPROC_NULL, "NULL" },
387         { PORTMAPPROC_SET, "SET" },
388         { PORTMAPPROC_UNSET, "UNSET" },
389         { PORTMAPPROC_GETPORT,  "GETPORT" },
390         { PORTMAPPROC_DUMP, "DUMP" },
391         { PORTMAPPROC_CALLIT, "CALLIT" },
392         { 0, NULL }
393 };
394 /* end of Portmap version 2 */
395
396
397 /* RFC 1833, Page 3 */
398 static int
399 dissect_rpcb(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
400 {
401         proto_item* rpcb_item = NULL;
402         proto_tree* rpcb_tree = NULL;
403         int old_offset = offset;
404         guint32 prog;
405
406         if (tree) {
407                 rpcb_item = proto_tree_add_item(tree, hf_portmap_rpcb, tvb,
408                         offset, -1, ENC_NA);
409                 if (rpcb_item)
410                         rpcb_tree = proto_item_add_subtree(rpcb_item, ett_portmap_rpcb);
411         }
412
413         prog = tvb_get_ntohl(tvb, offset);
414         if (rpcb_tree)
415                 proto_tree_add_uint_format(rpcb_tree, hf_portmap_rpcb_prog, tvb,
416                         offset, 4, prog,
417                         "Program: %s (%u)", rpc_prog_name(prog), prog);
418         offset += 4;
419
420         offset = dissect_rpc_uint32(tvb, rpcb_tree,
421             hf_portmap_rpcb_version, offset);
422         offset = dissect_rpc_string(tvb, rpcb_tree,
423             hf_portmap_rpcb_netid, offset, NULL);
424         offset = dissect_rpc_string(tvb, rpcb_tree,
425             hf_portmap_rpcb_addr, offset, NULL);
426         offset = dissect_rpc_string(tvb, rpcb_tree,
427             hf_portmap_rpcb_owner, offset, NULL);
428
429         /* now we know, that rpcb is shorter */
430         if (rpcb_item) {
431                 proto_item_set_len(rpcb_item, offset - old_offset);
432         }
433
434         return offset;
435 }
436
437
438
439 /* RFC 1833, Page 7 */
440 static int
441 dissect_rpcb3_getaddr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
442         proto_tree *tree)
443 {
444         offset = dissect_rpcb(tvb, offset, pinfo, tree);
445
446         return offset;
447 }
448
449
450 /* RFC 1833, Page 7 */
451 static int
452 dissect_rpcb3_getaddr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
453         proto_tree *tree)
454 {
455         offset = dissect_rpc_string(tvb, tree,
456             hf_portmap_uaddr, offset, NULL);
457
458         return offset;
459 }
460
461
462 /* RFC 1833, Page 7 */
463 static int
464 dissect_rpcb3_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
465         proto_tree *tree)
466 {
467         offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_rpcb);
468         return offset;
469 }
470
471 /* RFC 1833, page 4 */
472 static int
473 dissect_rpcb_rmtcallres(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
474         proto_tree *tree)
475 {
476         /* Dissect the remote universal address. */
477         offset = dissect_rpc_string(tvb, tree,
478             hf_portmap_rpcb_addr, offset, NULL);
479
480         /* Dissect the result of this procedure.
481            Make the columns non-writable, so the dissector won't change
482            them out from under us. */
483         col_set_writable(pinfo->cinfo, FALSE);
484         offset = dissect_rpc_indir_reply(tvb, pinfo, tree, offset,
485                 hf_portmap_result, hf_portmap_prog, hf_portmap_version,
486                 hf_portmap_proc);
487
488         return offset;
489 }
490
491
492 /* Portmapper version 3, RFC 1833, Page 7 */
493 static const vsff portmap3_proc[] = {
494         { RPCBPROC_NULL,        "NULL",
495                 NULL, NULL },
496         { RPCBPROC_SET,         "SET",
497                 NULL, NULL },
498         { RPCBPROC_UNSET,       "UNSET",
499                 NULL, NULL },
500         { RPCBPROC_GETADDR,     "GETADDR",
501                 dissect_rpcb3_getaddr_call, dissect_rpcb3_getaddr_reply},
502         { RPCBPROC_DUMP,        "DUMP",
503                 NULL, dissect_rpcb3_dump_reply },
504         { RPCBPROC_CALLIT,      "CALLIT",
505                 dissect_callit_call, dissect_rpcb_rmtcallres },
506         { RPCBPROC_GETTIME,     "GETTIME",
507                 NULL, NULL },
508         { RPCBPROC_UADDR2TADDR, "UADDR2TADDR",
509                 NULL, NULL },
510         { RPCBPROC_TADDR2UADDR, "TADDR2UADDR",
511                 NULL, NULL },
512         { 0, NULL, NULL, NULL }
513 };
514 static const value_string portmap3_proc_vals[] = {
515         { RPCBPROC_NULL,        "NULL" },
516         { RPCBPROC_SET,         "SET" },
517         { RPCBPROC_UNSET,       "UNSET" },
518         { RPCBPROC_GETADDR,     "GETADDR" },
519         { RPCBPROC_DUMP,        "DUMP" },
520         { RPCBPROC_CALLIT,      "CALLIT" },
521         { RPCBPROC_GETTIME,     "GETTIME" },
522         { RPCBPROC_UADDR2TADDR, "UADDR2TADDR" },
523         { RPCBPROC_TADDR2UADDR, "TADDR2UADDR" },
524         { 0, NULL }
525 };
526 /* end of Portmap version 3 */
527
528
529 /* Portmapper version 4, RFC 1833, Page 8 */
530 static const vsff portmap4_proc[] = {
531         { RPCBPROC_NULL,        "NULL",
532                 NULL, NULL },
533         { RPCBPROC_SET,         "SET",
534                 NULL, NULL },
535         { RPCBPROC_UNSET,       "UNSET",
536                 NULL, NULL },
537         { RPCBPROC_GETADDR,     "GETADDR",
538                 dissect_rpcb3_getaddr_call, dissect_rpcb3_getaddr_reply},
539         { RPCBPROC_DUMP,        "DUMP",
540                 NULL, dissect_rpcb3_dump_reply },
541         { RPCBPROC_BCAST,       "BCAST",
542                 dissect_callit_call, dissect_rpcb_rmtcallres },
543         { RPCBPROC_GETTIME,     "GETTIME",
544                 NULL, NULL },
545         { RPCBPROC_UADDR2TADDR, "UADDR2TADDR",
546                 NULL, NULL },
547         { RPCBPROC_TADDR2UADDR, "TADDR2UADDR",
548                 NULL, NULL },
549         { RPCBPROC_GETVERSADDR, "GETVERSADDR",
550                 NULL, NULL },
551         { RPCBPROC_INDIRECT,    "INDIRECT",
552                 dissect_callit_call, dissect_rpcb_rmtcallres },
553         { RPCBPROC_GETADDRLIST, "GETADDRLIST",
554                 NULL, NULL },
555         { RPCBPROC_GETSTAT,     "GETSTAT",
556                 NULL, NULL },
557         { 0, NULL, NULL, NULL }
558 };
559 static const value_string portmap4_proc_vals[] = {
560         { RPCBPROC_NULL,        "NULL" },
561         { RPCBPROC_SET,         "SET" },
562         { RPCBPROC_UNSET,       "UNSET" },
563         { RPCBPROC_GETADDR,     "GETADDR" },
564         { RPCBPROC_DUMP,        "DUMP" },
565         { RPCBPROC_BCAST,       "BCAST" },
566         { RPCBPROC_GETTIME,     "GETTIME" },
567         { RPCBPROC_UADDR2TADDR, "UADDR2TADDR" },
568         { RPCBPROC_TADDR2UADDR, "TADDR2UADDR" },
569         { RPCBPROC_GETVERSADDR, "GETVERSADDR" },
570         { RPCBPROC_INDIRECT,    "INDIRECT" },
571         { RPCBPROC_GETADDRLIST, "GETADDRLIST" },
572         { RPCBPROC_GETSTAT,     "GETSTAT" },
573         { 0, NULL }
574 };
575 /* end of Portmap version 4 */
576
577 void
578 proto_register_portmap(void)
579 {
580         static hf_register_info hf[] = {
581                 { &hf_portmap_procedure_v1, {
582                         "V1 Procedure", "portmap.procedure_v1", FT_UINT32, BASE_DEC,
583                         VALS(portmap1_proc_vals), 0, NULL, HFILL }},
584                 { &hf_portmap_procedure_v2, {
585                         "V2 Procedure", "portmap.procedure_v2", FT_UINT32, BASE_DEC,
586                         VALS(portmap2_proc_vals), 0, NULL, HFILL }},
587                 { &hf_portmap_procedure_v3, {
588                         "V3 Procedure", "portmap.procedure_v3", FT_UINT32, BASE_DEC,
589                         VALS(portmap3_proc_vals), 0, NULL, HFILL }},
590                 { &hf_portmap_procedure_v4, {
591                         "V4 Procedure", "portmap.procedure_v4", FT_UINT32, BASE_DEC,
592                         VALS(portmap4_proc_vals), 0, NULL, HFILL }},
593                 { &hf_portmap_prog, {
594                         "Program", "portmap.prog", FT_UINT32, BASE_DEC,
595                         NULL, 0, NULL, HFILL }},
596                 { &hf_portmap_port, {
597                         "Port", "portmap.port", FT_UINT32, BASE_DEC,
598                         NULL, 0, NULL, HFILL }},
599                 { &hf_portmap_proc, {
600                         "Procedure", "portmap.proc", FT_UINT32, BASE_DEC,
601                         NULL, 0, NULL, HFILL }},
602                 { &hf_portmap_proto, {
603                         "Protocol", "portmap.proto", FT_UINT32, BASE_DEC,
604                         NULL, 0, NULL, HFILL }},
605                 { &hf_portmap_version, {
606                         "Version", "portmap.version", FT_UINT32, BASE_DEC,
607                         NULL, 0, NULL, HFILL }},
608                 { &hf_portmap_answer, {
609                         "Answer", "portmap.answer", FT_BOOLEAN, BASE_NONE,
610                         NULL, 0x0, NULL, HFILL }},
611                 { &hf_portmap_args, {
612                         "Arguments", "portmap.args", FT_BYTES, BASE_NONE,
613                         NULL, 0, NULL, HFILL }},
614                 { &hf_portmap_result, {
615                         "Result", "portmap.result", FT_BYTES, BASE_NONE,
616                         NULL, 0, NULL, HFILL }},
617                 { &hf_portmap_rpcb, {
618                         "RPCB", "portmap.rpcb", FT_NONE, BASE_NONE,
619                         NULL, 0, NULL, HFILL }},
620                 { &hf_portmap_rpcb_prog, {
621                         "Program", "portmap.rpcb.prog", FT_UINT32, BASE_DEC,
622                         NULL, 0, NULL, HFILL }},
623                 { &hf_portmap_rpcb_version, {
624                         "Version", "portmap.rpcb.version", FT_UINT32, BASE_DEC,
625                         NULL, 0, NULL, HFILL }},
626                 { &hf_portmap_rpcb_netid, {
627                         "Network Id", "portmap.rpcb.netid", FT_STRING, BASE_NONE,
628                         NULL, 0, NULL, HFILL }},
629                 { &hf_portmap_rpcb_addr, {      /* address in rpcb structure in request */
630                         "Universal Address", "portmap.rpcb.addr", FT_STRING, BASE_NONE,
631                         NULL, 0, NULL, HFILL }},
632                 { &hf_portmap_rpcb_owner, {
633                         "Owner of this Service", "portmap.rpcb.owner", FT_STRING, BASE_NONE,
634                         NULL, 0, NULL, HFILL }},
635                 { &hf_portmap_uaddr, {  /* address in RPCBPROC_GETADDR reply */
636                         "Universal Address", "portmap.uaddr", FT_STRING, BASE_NONE,
637                         NULL, 0, NULL, HFILL }},
638         };
639         static gint *ett[] = {
640                 &ett_portmap,
641                 &ett_portmap_rpcb,
642                 &ett_portmap_entry
643         };
644
645         proto_portmap = proto_register_protocol("Portmap", "Portmap", "portmap");
646         proto_register_field_array(proto_portmap, hf, array_length(hf));
647         proto_register_subtree_array(ett, array_length(ett));
648 }
649
650 void
651 proto_reg_handoff_portmap(void)
652 {
653         /* Register the protocol as RPC */
654         rpc_init_prog(proto_portmap, PORTMAP_PROGRAM, ett_portmap);
655         /* Register the procedure tables */
656         rpc_init_proc_table(PORTMAP_PROGRAM, 1, portmap1_proc, hf_portmap_procedure_v1);
657         rpc_init_proc_table(PORTMAP_PROGRAM, 2, portmap2_proc, hf_portmap_procedure_v2);
658         rpc_init_proc_table(PORTMAP_PROGRAM, 3, portmap3_proc, hf_portmap_procedure_v3);
659         rpc_init_proc_table(PORTMAP_PROGRAM, 4, portmap4_proc, hf_portmap_procedure_v4);
660         rpc_handle = find_dissector("rpc");
661 }