Catch ReportedBoundsError exceptions when dissecting an RPC-over-TCP
[obnox/wireshark/wip.git] / packet-rpc.c
1 /* packet-rpc.c
2  * Routines for rpc dissection
3  * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
4  * 
5  * $Id: packet-rpc.c,v 1.79 2002/01/07 00:59:26 guy Exp $
6  * 
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * Copied from packet-smb.c
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <glib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "packet.h"
41 #include "conversation.h"
42 #include "packet-rpc.h"
43 #include "packet-frame.h"
44 #include "prefs.h"
45
46 /*
47  * See:
48  *
49  *      RFC 1831, "RPC: Remote Procedure Call Protocol Specification
50  *      Version 2";
51  *
52  *      RFC 1832, "XDR: External Data Representation Standard";
53  *
54  *      RFC 2203, "RPCSEC_GSS Protocol Specification".
55  *
56  * See also
57  *
58  *      RFC 2695, "Authentication Mechanisms for ONC RPC"
59  *
60  *      although we don't currently dissect AUTH_DES or AUTH_KERB.
61  */
62
63 #define RPC_RM_FRAGLEN  0x7fffffffL
64
65 /* desegmentation of RPC over TCP */
66 static gboolean rpc_desegment = TRUE;
67
68 static struct true_false_string yesno = { "Yes", "No" };
69
70
71 static const value_string rpc_msg_type[] = {
72         { RPC_CALL, "Call" },
73         { RPC_REPLY, "Reply" },
74         { 0, NULL }
75 };
76
77 static const value_string rpc_reply_state[] = {
78         { MSG_ACCEPTED, "accepted" },
79         { MSG_DENIED, "denied" },
80         { 0, NULL }
81 };
82
83 const value_string rpc_auth_flavor[] = {
84         { AUTH_NULL, "AUTH_NULL" },
85         { AUTH_UNIX, "AUTH_UNIX" },
86         { AUTH_SHORT, "AUTH_SHORT" },
87         { AUTH_DES, "AUTH_DES" },
88         { RPCSEC_GSS, "RPCSEC_GSS" },
89         { 0, NULL }
90 };
91
92 static const value_string rpc_authgss_proc[] = {
93         { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
94         { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
95         { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
96         { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
97         { 0, NULL }
98 };
99
100 value_string rpc_authgss_svc[] = {
101         { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
102         { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
103         { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
104         { 0, NULL }
105 };
106
107 static const value_string rpc_accept_state[] = {
108         { SUCCESS, "RPC executed successfully" },
109         { PROG_UNAVAIL, "remote hasn't exported program" },
110         { PROG_MISMATCH, "remote can't support version #" },
111         { PROC_UNAVAIL, "program can't support procedure" },
112         { GARBAGE_ARGS, "procedure can't decode params" },
113         { 0, NULL }
114 };
115
116 static const value_string rpc_reject_state[] = {
117         { RPC_MISMATCH, "RPC_MISMATCH" },
118         { AUTH_ERROR, "AUTH_ERROR" },
119         { 0, NULL }
120 };
121
122 static const value_string rpc_auth_state[] = {
123         { AUTH_BADCRED, "bad credential (seal broken)" },
124         { AUTH_REJECTEDCRED, "client must begin new session" },
125         { AUTH_BADVERF, "bad verifier (seal broken)" },
126         { AUTH_REJECTEDVERF, "verifier expired or replayed" },
127         { AUTH_TOOWEAK, "rejected for security reasons" },
128         { RPCSEC_GSSCREDPROB, "GSS credential problem" },
129         { RPCSEC_GSSCTXPROB, "GSS context problem" },
130         { 0, NULL }
131 };
132
133 static const value_string rpc_authdes_namekind[] = {
134         { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
135         { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
136         { 0, NULL }
137 };
138
139 /* the protocol number */
140 static int proto_rpc = -1;
141 static int hf_rpc_lastfrag = -1;
142 static int hf_rpc_fraglen = -1;
143 static int hf_rpc_xid = -1;
144 static int hf_rpc_msgtype = -1;
145 static int hf_rpc_version = -1;
146 static int hf_rpc_version_min = -1;
147 static int hf_rpc_version_max = -1;
148 static int hf_rpc_program = -1;
149 static int hf_rpc_programversion = -1;
150 static int hf_rpc_programversion_min = -1;
151 static int hf_rpc_programversion_max = -1;
152 static int hf_rpc_procedure = -1;
153 static int hf_rpc_auth_flavor = -1;
154 static int hf_rpc_auth_length = -1;
155 static int hf_rpc_auth_machinename = -1;
156 static int hf_rpc_auth_stamp = -1;
157 static int hf_rpc_auth_uid = -1;
158 static int hf_rpc_auth_gid = -1;
159 static int hf_rpc_authgss_v = -1;
160 static int hf_rpc_authgss_proc = -1;
161 static int hf_rpc_authgss_seq = -1;
162 static int hf_rpc_authgss_svc = -1;
163 static int hf_rpc_authgss_ctx = -1;
164 static int hf_rpc_authgss_major = -1;
165 static int hf_rpc_authgss_minor = -1;
166 static int hf_rpc_authgss_window = -1;
167 static int hf_rpc_authgss_token = -1;
168 static int hf_rpc_authgss_data_length = -1;
169 static int hf_rpc_authgss_data = -1;
170 static int hf_rpc_authgss_checksum = -1;
171 static int hf_rpc_authdes_namekind = -1;
172 static int hf_rpc_authdes_netname = -1;
173 static int hf_rpc_authdes_convkey = -1;
174 static int hf_rpc_authdes_window = -1;
175 static int hf_rpc_authdes_nickname = -1;
176 static int hf_rpc_authdes_timestamp = -1;
177 static int hf_rpc_authdes_windowverf = -1;
178 static int hf_rpc_authdes_timeverf = -1;
179 static int hf_rpc_state_accept = -1;
180 static int hf_rpc_state_reply = -1;
181 static int hf_rpc_state_reject = -1;
182 static int hf_rpc_state_auth = -1;
183 static int hf_rpc_dup = -1;
184 static int hf_rpc_call_dup = -1;
185 static int hf_rpc_reply_dup = -1;
186 static int hf_rpc_value_follows = -1;
187 static int hf_rpc_array_len = -1;
188 static int hf_rpc_time = -1;
189
190 static gint ett_rpc = -1;
191 static gint ett_rpc_string = -1;
192 static gint ett_rpc_cred = -1;
193 static gint ett_rpc_verf = -1;
194 static gint ett_rpc_gids = -1;
195 static gint ett_rpc_gss_data = -1;
196 static gint ett_rpc_array = -1;
197
198 static dissector_handle_t rpc_tcp_handle;
199 static dissector_handle_t rpc_handle;
200 static dissector_handle_t data_handle;
201
202 /* Hash table with info on RPC program numbers */
203 static GHashTable *rpc_progs;
204
205 /* Hash table with info on RPC procedure numbers */
206 static GHashTable *rpc_procs;
207
208 typedef struct _rpc_proc_info_key {
209         guint32 prog;
210         guint32 vers;
211         guint32 proc;
212 } rpc_proc_info_key;
213
214 typedef struct _rpc_proc_info_value {
215         gchar           *name;
216         dissect_function_t *dissect_call;
217         dissect_function_t *dissect_reply;
218 } rpc_proc_info_value;
219
220 typedef struct _rpc_prog_info_key {
221         guint32 prog;
222 } rpc_prog_info_key;
223
224 typedef struct _rpc_prog_info_value {
225         int proto;
226         int ett;
227         char* progname;
228 } rpc_prog_info_value;
229
230 static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
231 static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
232
233 /***********************************/
234 /* Hash array with procedure names */
235 /***********************************/
236
237 /* compare 2 keys */
238 gint
239 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
240 {
241         rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
242         rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
243
244         return ((key1->prog == key2->prog && 
245                 key1->vers == key2->vers &&
246                 key1->proc == key2->proc) ?
247         TRUE : FALSE);
248 }
249
250 /* calculate a hash key */
251 guint
252 rpc_proc_hash(gconstpointer k)
253 {
254         rpc_proc_info_key* key = (rpc_proc_info_key*) k;
255
256         return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
257 }
258
259
260 /* insert some entries */
261 void
262 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
263 {
264         const vsff *proc;
265
266         for (proc = proc_table ; proc->strptr!=NULL; proc++) {
267                 rpc_proc_info_key *key;
268                 rpc_proc_info_value *value;
269
270                 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
271                 key->prog = prog;
272                 key->vers = vers;
273                 key->proc = proc->value;
274
275                 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
276                 value->name = proc->strptr;
277                 value->dissect_call = proc->dissect_call;
278                 value->dissect_reply = proc->dissect_reply;
279
280                 g_hash_table_insert(rpc_procs,key,value);
281         }
282 }
283
284 /*      return the name associated with a previously registered procedure. */
285 char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
286 {
287         rpc_proc_info_key key;
288         rpc_proc_info_value *value;
289         char *procname;
290         static char procname_static[20];
291
292         key.prog = prog;
293         key.vers = vers;
294         key.proc = proc;
295
296         if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
297                 procname = value->name;
298         else {
299                 /* happens only with strange program versions or
300                    non-existing dissectors */
301                 sprintf(procname_static, "proc-%u", key.proc);
302                 procname = procname_static;
303         }
304         return procname;
305 }
306
307 /*----------------------------------------*/
308 /* end of Hash array with procedure names */
309 /*----------------------------------------*/
310
311
312 /*********************************/
313 /* Hash array with program names */
314 /*********************************/
315
316 /* compare 2 keys */
317 gint
318 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
319 {
320         rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
321         rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
322
323         return ((key1->prog == key2->prog) ?
324         TRUE : FALSE);
325 }
326
327
328 /* calculate a hash key */
329 guint
330 rpc_prog_hash(gconstpointer k)
331 {
332         rpc_prog_info_key* key = (rpc_prog_info_key*) k;
333
334         return (key->prog);
335 }
336
337
338 void
339 rpc_init_prog(int proto, guint32 prog, int ett)
340 {
341         rpc_prog_info_key *key;
342         rpc_prog_info_value *value;
343
344         key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
345         key->prog = prog;
346
347         value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
348         value->proto = proto;
349         value->ett = ett;
350         value->progname = proto_get_protocol_short_name(proto);
351
352         g_hash_table_insert(rpc_progs,key,value);
353 }
354
355 /*      return the name associated with a previously registered program. This
356         should probably eventually be expanded to use the rpc YP/NIS map
357         so that it can give names for programs not handled by ethereal */
358 char *rpc_prog_name(guint32 prog)
359 {
360         char *progname = NULL;
361         rpc_prog_info_key       rpc_prog_key;
362         rpc_prog_info_value     *rpc_prog;
363
364         rpc_prog_key.prog = prog;
365         if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
366                 progname = "Unknown";
367         }
368         else {
369                 progname = rpc_prog->progname;
370         }
371         return progname;
372 }
373
374
375 /*--------------------------------------*/
376 /* end of Hash array with program names */
377 /*--------------------------------------*/
378
379 typedef struct _rpc_call_info_key {
380         guint32 xid;
381         conversation_t *conversation;
382 } rpc_call_info_key;
383
384 static GMemChunk *rpc_call_info_key_chunk;
385
386 typedef enum {
387         FLAVOR_UNKNOWN,         /* authentication flavor unknown */
388         FLAVOR_NOT_GSSAPI,      /* flavor isn't GSSAPI */
389         FLAVOR_GSSAPI_NO_INFO,  /* flavor is GSSAPI, procedure & service unknown */
390         FLAVOR_GSSAPI           /* flavor is GSSAPI, procedure & service known */
391 } flavor_t;
392
393 typedef struct _rpc_call_info_value {
394         guint32 req_num;        /* frame number of first request seen */
395         guint32 rep_num;        /* frame number of first reply seen */
396         guint32 prog;
397         guint32 vers;
398         guint32 proc;
399         flavor_t flavor;
400         guint32 gss_proc;
401         guint32 gss_svc;
402         rpc_proc_info_value*    proc_info;
403         nstime_t req_time;
404 } rpc_call_info_value;
405
406 static GMemChunk *rpc_call_info_value_chunk;
407
408 static GHashTable *rpc_calls;
409
410 static GHashTable *rpc_indir_calls;
411
412 /* compare 2 keys */
413 gint
414 rpc_call_equal(gconstpointer k1, gconstpointer k2)
415 {
416         rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
417         rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
418
419         return (key1->xid == key2->xid &&
420             key1->conversation == key2->conversation);
421 }
422
423
424 /* calculate a hash key */
425 guint
426 rpc_call_hash(gconstpointer k)
427 {
428         rpc_call_info_key* key = (rpc_call_info_key*) k;
429
430         return key->xid + (guint32)(key->conversation);
431 }
432
433
434 unsigned int
435 rpc_roundup(unsigned int a)
436 {
437         unsigned int mod = a % 4;
438         return a + ((mod)? 4-mod : 0);
439 }
440
441
442 int
443 dissect_rpc_bool(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
444 int hfindex, int offset)
445 {
446         if (tree)
447                 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
448         return offset + 4;
449 }
450
451
452 int
453 dissect_rpc_uint32(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
454 int hfindex, int offset)
455 {
456         if (tree)
457                 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
458         return offset + 4;
459 }
460
461
462 int
463 dissect_rpc_uint64(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
464 int hfindex, int offset)
465 {
466         header_field_info       *hfinfo;
467
468         hfinfo = proto_registrar_get_nth(hfindex);
469         g_assert(hfinfo->type == FT_UINT64);
470         if (tree)
471                 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
472
473         return offset + 8;
474 }
475
476
477 static int
478 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
479     proto_tree *tree, int hfindex, gboolean string_data,
480     char **string_buffer_ret)
481 {
482         proto_item *string_item = NULL;
483         proto_tree *string_tree = NULL;
484         int old_offset = offset;
485
486         int length_truncated = 0;
487
488         int string_truncated = 0;
489         guint32 string_length = 0;
490         guint32 string_length_full;
491         guint32 string_length_packet;
492         guint32 string_length_copy = 0;
493
494         int fill_truncated = 0;
495         guint32 fill_length  = 0;
496         guint32 fill_length_packet  = 0;
497         guint32 fill_length_copy  = 0;
498
499         char *string_buffer = NULL;
500         char *string_buffer_print = NULL;
501
502         string_length = tvb_get_ntohl(tvb,offset+0);
503         string_length_full = rpc_roundup(string_length);
504         /* XXX - just let the tvbuff stuff throw an exception? */
505         string_length_packet = tvb_length_remaining(tvb, offset + 4);
506         if (string_length_packet < string_length) {
507                 /* truncated string */
508                 string_truncated = 1;
509                 string_length_copy = string_length_packet;
510                 fill_truncated = 2;
511                 fill_length = 0;
512                 fill_length_packet = 0;
513                 fill_length_copy = 0;
514         }
515         else {
516                 /* full string data */
517                 string_truncated = 0;
518                 string_length_copy = string_length;
519                 fill_length = string_length_full - string_length;
520                 /* XXX - just let the tvbuff stuff throw an exception? */
521                 fill_length_packet = tvb_length_remaining(tvb,
522                     offset + 4 + string_length);
523                 if (fill_length_packet < fill_length) {
524                         /* truncated fill bytes */
525                         fill_length_copy = fill_length_packet;
526                         fill_truncated = 1;
527                 }
528                 else {
529                         /* full fill bytes */
530                         fill_length_copy = fill_length;
531                         fill_truncated = 0;
532                 }
533         }
534         string_buffer = (char*)g_malloc(string_length_copy + 
535                         (string_data ? 1 : 0));
536         tvb_memcpy(tvb,string_buffer,offset+4,string_length_copy);
537         if (string_data)
538                 string_buffer[string_length_copy] = '\0';
539
540         /* calculate a nice printable string */
541         if (string_length) {
542                 if (string_length != string_length_copy) {
543                         if (string_data) {
544                                 /* alloc maximum data area */
545                                 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
546                                 /* copy over the data */
547                                 memcpy(string_buffer_print,string_buffer,string_length_copy);
548                                 /* append a 0 byte for sure printing */
549                                 string_buffer_print[string_length_copy] = '\0';
550                                 /* append <TRUNCATED> */
551                                 /* This way, we get the TRUNCATED even
552                                    in the case of totally wrong packets,
553                                    where \0 are inside the string.
554                                    TRUNCATED will appear at the
555                                    first \0 or at the end (where we 
556                                    put the securing \0).
557                                 */
558                                 strcat(string_buffer_print,"<TRUNCATED>");
559                         }
560                         else {
561                                 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
562                         }
563                 }
564                 else {
565                         if (string_data) {
566                                 string_buffer_print = g_strdup(string_buffer);
567                         }
568                         else {
569                                 string_buffer_print = g_strdup("<DATA>");
570                         }
571                 }
572         }
573         else {
574                 string_buffer_print = g_strdup("<EMPTY>");
575         }
576
577         if (tree) {
578                 string_item = proto_tree_add_text(tree, tvb,offset+0, tvb_length_remaining(tvb, offset),
579                         "%s: %s", proto_registrar_get_name(hfindex), string_buffer_print);
580                 if (string_data) {
581                         proto_tree_add_string_hidden(tree, hfindex, tvb, offset+4,
582                                 string_length_copy, string_buffer);
583                 }
584                 if (string_item) {
585                         string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
586                 }
587         }
588         if (length_truncated) {
589                 if (string_tree)
590                         proto_tree_add_text(string_tree, tvb,
591                                 offset, tvb_length_remaining(tvb, offset),
592                                 "length: <TRUNCATED>");
593                 offset = tvb_length(tvb);
594         } else {
595                 if (string_tree)
596                         proto_tree_add_text(string_tree, tvb,offset+0,4,
597                                 "length: %u", string_length);
598                 offset += 4;
599
600                 if (string_tree) {
601                         if (string_data) {
602                                 proto_tree_add_string_format(string_tree,
603                                     hfindex, tvb, offset, string_length_copy,
604                                         string_buffer_print, 
605                                         "contents: %s", string_buffer_print);
606                         } else {
607                                 proto_tree_add_bytes_format(string_tree,
608                                     hfindex, tvb, offset, string_length_copy,
609                                         string_buffer_print, 
610                                         "contents: %s", string_buffer_print);
611                         }
612                 }
613                 offset += string_length_copy;
614                 if (fill_length) {
615                         if (string_tree) {
616                                 if (fill_truncated) {
617                                         proto_tree_add_text(string_tree, tvb,
618                                         offset,fill_length_copy,
619                                         "fill bytes: opaque data<TRUNCATED>");
620                                 }
621                                 else {
622                                         proto_tree_add_text(string_tree, tvb,
623                                         offset,fill_length_copy,
624                                         "fill bytes: opaque data");
625                                 }
626                         }
627                         offset += fill_length_copy;
628                 }
629         }
630         
631         if (string_item) {
632                 proto_item_set_len(string_item, offset - old_offset);
633         }
634
635         if (string_buffer       != NULL) g_free (string_buffer      );
636         if (string_buffer_print != NULL) {
637                 if (string_buffer_ret != NULL)
638                         *string_buffer_ret = string_buffer_print;
639                 else
640                         g_free (string_buffer_print);
641         }
642         return offset;
643 }
644
645
646 int
647 dissect_rpc_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
648     int hfindex, int offset, char **string_buffer_ret)
649 {
650         offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree,
651             hfindex, TRUE, string_buffer_ret);
652         return offset;
653 }
654
655
656 int
657 dissect_rpc_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
658     int hfindex, int offset)
659 {
660         offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree, hfindex,
661             FALSE, NULL);
662
663         return offset;
664 }
665
666
667 int
668 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
669         int offset, dissect_function_t *rpc_list_dissector)
670 {
671         guint32 value_follows;
672
673         while (1) {
674                 value_follows = tvb_get_ntohl(tvb, offset+0);
675                 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
676                         offset+0, 4, value_follows);
677                 offset += 4;
678                 if (value_follows == 1) {
679                         offset = rpc_list_dissector(tvb, offset, pinfo, tree);
680                 }
681                 else {
682                         break;
683                 }
684         }
685
686         return offset;
687 }
688
689 int
690 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
691         int offset, dissect_function_t *rpc_array_dissector,
692         int hfindex)
693 {
694         proto_item* lock_item;
695         proto_tree* lock_tree;
696         guint32 num;
697         int old_offset = offset;
698
699         num = tvb_get_ntohl(tvb, offset);
700
701         if( num == 0 ){
702                 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
703                         "no values");
704                 offset += 4;
705
706                 return offset;
707         }
708
709         lock_item = proto_tree_add_item(tree, hfindex, tvb, offset,
710                         0, FALSE);
711
712         lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);   
713
714         offset = dissect_rpc_uint32(tvb, pinfo, lock_tree,
715                         hf_rpc_array_len, offset);
716
717         while (num--) {
718                 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
719         }
720
721         proto_item_set_len(lock_item, offset-old_offset);
722         return offset;
723 }
724
725 static int
726 dissect_rpc_authunix_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
727 {
728         guint stamp;
729         guint uid;
730         guint gid;
731         guint gids_count;
732         guint gids_i;
733         guint gids_entry;
734         proto_item *gitem;
735         proto_tree *gtree = NULL;
736
737         stamp = tvb_get_ntohl(tvb,offset+0);
738         if (tree)
739                 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
740                         offset+0, 4, stamp);
741         offset += 4;
742
743         offset = dissect_rpc_string(tvb, pinfo, tree,
744                         hf_rpc_auth_machinename, offset, NULL);
745
746         uid = tvb_get_ntohl(tvb,offset+0);
747         if (tree)
748                 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
749                         offset+0, 4, uid);
750         offset += 4;
751
752         gid = tvb_get_ntohl(tvb,offset+0);
753         if (tree)
754                 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
755                         offset+0, 4, gid);
756         offset += 4;
757
758         gids_count = tvb_get_ntohl(tvb,offset+0);
759         if (tree) {
760                 gitem = proto_tree_add_text(tree, tvb,
761                         offset, 4+gids_count*4, "Auxiliary GIDs");
762                 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
763         }
764         offset += 4;
765         
766         for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
767                 gids_entry = tvb_get_ntohl(tvb,offset+0);
768                 if (gtree)
769                 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
770                         offset, 4, gids_entry);
771                 offset+=4;
772         }
773         /* how can I NOW change the gitem to print a list with
774                 the first 16 gids? */
775
776         return offset;
777 }
778
779 static int
780 dissect_rpc_authgss_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
781 {
782         guint agc_v;
783         guint agc_proc;
784         guint agc_seq;
785         guint agc_svc;
786
787         agc_v = tvb_get_ntohl(tvb, offset+0);
788         if (tree)
789                 proto_tree_add_uint(tree, hf_rpc_authgss_v,
790                                     tvb, offset+0, 4, agc_v);
791         offset += 4;
792         
793         agc_proc = tvb_get_ntohl(tvb, offset+0);
794         if (tree)
795                 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
796                                     tvb, offset+0, 4, agc_proc);
797         offset += 4;
798         
799         agc_seq = tvb_get_ntohl(tvb, offset+0);
800         if (tree)
801                 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
802                                     tvb, offset+0, 4, agc_seq);
803         offset += 4;
804         
805         agc_svc = tvb_get_ntohl(tvb, offset+0);
806         if (tree)
807                 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
808                                     tvb, offset+0, 4, agc_svc);
809         offset += 4;
810         
811         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
812                         offset);
813         
814         return offset;
815 }
816
817 int
818 dissect_rpc_authdes_desblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
819 int hfindex, int offset)
820 {
821         guint32 value_low;
822         guint32 value_high;
823
824         value_high = tvb_get_ntohl(tvb, offset + 0);
825         value_low  = tvb_get_ntohl(tvb, offset + 4);
826
827         if (tree) {
828                 proto_tree_add_text(tree, tvb, offset, 8,
829                         "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high, 
830                         value_low);
831         }
832
833         return offset + 8;
834 }
835
836 static int
837 dissect_rpc_authdes_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
838 {
839         guint adc_namekind;
840         guint window = 0;
841         guint nickname = 0;
842
843         adc_namekind = tvb_get_ntohl(tvb, offset+0);
844         if (tree)
845                 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
846                                     tvb, offset+0, 4, adc_namekind);
847         offset += 4;
848
849         switch(adc_namekind)
850         {
851         case AUTHDES_NAMEKIND_FULLNAME:
852                 offset = dissect_rpc_string(tvb, pinfo, tree, 
853                         hf_rpc_authdes_netname, offset, NULL);
854                 offset = dissect_rpc_authdes_desblock(tvb, pinfo, tree,
855                         hf_rpc_authdes_convkey, offset);
856                 window = tvb_get_ntohl(tvb, offset+0);
857                 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
858                         window);
859                 offset += 4;
860                 break;
861
862         case AUTHDES_NAMEKIND_NICKNAME:
863                 nickname = tvb_get_ntohl(tvb, offset+0);
864                 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
865                         window);
866                 offset += 4;
867                 break;
868         }
869
870         return offset;
871 }
872
873 static int
874 dissect_rpc_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
875 {
876         guint flavor;
877         guint length;
878
879         proto_item *citem;
880         proto_tree *ctree;
881
882         flavor = tvb_get_ntohl(tvb,offset+0);
883         length = tvb_get_ntohl(tvb,offset+4);
884         length = rpc_roundup(length);
885
886         if (tree) {
887                 citem = proto_tree_add_text(tree, tvb, offset,
888                                             8+length, "Credentials");
889                 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
890                 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
891                                     offset+0, 4, flavor);
892                 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
893                                     offset+4, 4, length);
894
895                 switch (flavor) {
896                 case AUTH_UNIX:
897                         dissect_rpc_authunix_cred(tvb, pinfo, ctree, offset+8);
898                         break;
899                 /*
900                 case AUTH_SHORT:
901
902                 break;
903                 */
904                 case AUTH_DES:
905                         dissect_rpc_authdes_cred(tvb, pinfo, ctree, offset+8);
906                         break;
907                         
908                 case RPCSEC_GSS:
909                         dissect_rpc_authgss_cred(tvb, pinfo, ctree, offset+8);
910                         break;
911                 default:
912                         if (length)
913                                 proto_tree_add_text(ctree, tvb, offset+8,
914                                                     length,"opaque data");
915                 break;
916                 }
917         }
918         offset += 8 + length;
919
920         return offset;
921 }
922
923 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
924  * verifier we're decoding (CALL or REPLY).
925  */
926 static int
927 dissect_rpc_verf(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset, int msg_type)
928 {
929         guint flavor;
930         guint length;
931         
932         proto_item *vitem;
933         proto_tree *vtree;
934
935         flavor = tvb_get_ntohl(tvb,offset+0);
936         length = tvb_get_ntohl(tvb,offset+4);
937         length = rpc_roundup(length);
938
939         if (tree) {
940                 vitem = proto_tree_add_text(tree, tvb, offset,
941                                             8+length, "Verifier");
942                 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
943                 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
944                                     offset+0, 4, flavor);
945
946                 switch (flavor) {
947                 case AUTH_UNIX:
948                         proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
949                                             offset+4, 4, length);
950                         dissect_rpc_authunix_cred(tvb, pinfo, vtree, offset+8);
951                         break;
952                 case AUTH_DES:
953                         proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
954                                 offset+4, 4, length);
955
956                         if (msg_type == RPC_CALL)
957                         {
958                                 guint window;
959
960                                 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
961                                         hf_rpc_authdes_timestamp, offset+8);
962                                 window = tvb_get_ntohl(tvb, offset+16);
963                                 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb, 
964                                         offset+16, 4, window);
965                         }
966                         else
967                         {
968                                 /* must be an RPC_REPLY */
969                                 guint nickname;
970
971                                 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
972                                         hf_rpc_authdes_timeverf, offset+8);
973                                 nickname = tvb_get_ntohl(tvb, offset+16);
974                                 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb, 
975                                         offset+16, 4, nickname);
976                         }
977                         break;
978                 case RPCSEC_GSS:
979                         dissect_rpc_data(tvb, pinfo, vtree,
980                                 hf_rpc_authgss_checksum, offset+4);
981                         break;
982                 default:
983                         proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
984                                             offset+4, 4, length);
985                         if (length)
986                                 proto_tree_add_text(vtree, tvb, offset+8,
987                                                     length, "opaque data");
988                         break;
989                 }
990         }
991         offset += 8 + length;
992
993         return offset;
994 }
995
996 static int
997 dissect_rpc_authgss_initarg(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
998 {
999         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1000                         offset);
1001         return offset;
1002 }
1003
1004 static int
1005 dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
1006 {
1007         int major, minor, window;
1008         
1009         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
1010                         offset);
1011         
1012         major = tvb_get_ntohl(tvb,offset+0);
1013         if (tree)
1014                 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1015                                     offset+0, 4, major);
1016         offset += 4;
1017
1018         minor = tvb_get_ntohl(tvb,offset+0);
1019         if (tree)
1020                 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1021                                     offset+0, 4, minor);
1022         offset += 4;
1023
1024         window = tvb_get_ntohl(tvb,offset+0);
1025         if (tree)
1026                 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1027                                     offset+0, 4, window);
1028         offset += 4;
1029
1030         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1031                         offset);
1032
1033         return offset;
1034 }
1035
1036
1037 static int
1038 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1039         int offset, dissect_function_t* dissect_function, const char *progname)
1040 {
1041         const char *saved_proto;
1042
1043         if (dissect_function != NULL) {
1044                 /* set the current protocol name */
1045                 saved_proto = pinfo->current_proto;
1046                 if (progname != NULL)
1047                         pinfo->current_proto = progname;
1048
1049                 /* call the dissector for the next level */
1050                 offset = dissect_function(tvb, offset, pinfo, tree);
1051
1052                 /* restore the protocol name */
1053                 pinfo->current_proto = saved_proto;
1054         }
1055
1056         return offset;
1057 }
1058
1059
1060 static int
1061 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1062         proto_tree *tree, int offset,
1063         dissect_function_t* dissect_function,
1064         const char *progname)
1065 {
1066         guint32 length, seq;
1067         
1068         proto_item *gitem;
1069         proto_tree *gtree = NULL;
1070
1071         length = tvb_get_ntohl(tvb, offset+0);
1072         length = rpc_roundup(length);
1073         seq = tvb_get_ntohl(tvb, offset+4);
1074
1075         if (tree) {
1076                 gitem = proto_tree_add_text(tree, tvb, offset,
1077                                             4+length, "GSS Data");
1078                 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1079                 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1080                                     tvb, offset+0, 4, length);
1081                 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1082                                     tvb, offset+4, 4, seq);
1083         }
1084         offset += 8;
1085
1086         if (dissect_function != NULL) {
1087                 /* offset = */
1088                 call_dissect_function(tvb, pinfo, gtree, offset,
1089                                       dissect_function, progname);
1090         }
1091         offset += length - 4;
1092         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_checksum,
1093                         offset);
1094         return offset;
1095 }
1096
1097
1098 static int
1099 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1100 {
1101         offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_data,
1102                         offset);
1103         return offset;
1104 }
1105
1106 /*
1107  * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1108  * dissector.
1109  *
1110  * Record this call in a hash table, similar to the hash table for
1111  * direct calls, so we can find it when dissecting an indirect call reply.
1112  */
1113 int
1114 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1115     int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1116 {
1117         conversation_t* conversation;
1118         static address null_address = { AT_NONE, 0, NULL };
1119         rpc_proc_info_key key;
1120         rpc_proc_info_value *value;
1121         rpc_call_info_value *rpc_call;
1122         rpc_call_info_key rpc_call_key;
1123         rpc_call_info_key *new_rpc_call_key;
1124         dissect_function_t *dissect_function = NULL;
1125
1126         key.prog = prog;
1127         key.vers = vers;
1128         key.proc = proc;
1129         if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1130                 dissect_function = value->dissect_call;
1131
1132                 /* Keep track of the address and port whence the call came,
1133                    and the port to which the call is being sent, so that
1134                    we can match up calls with replies.
1135
1136                    If the transport is connection-oriented (we check, for
1137                    now, only for "pinfo->ptype" of PT_TCP), we take
1138                    into account the address from which the call was sent
1139                    and the address to which the call was sent, because
1140                    the addresses of the two endpoints should be the same
1141                    for all calls and replies.
1142
1143                    If the transport is connectionless, we don't worry
1144                    about the address to which the call was sent and from
1145                    which the reply was sent, because there's no
1146                    guarantee that the reply will come from the address
1147                    to which the call was sent. */
1148                 if (pinfo->ptype == PT_TCP) {
1149                         conversation = find_conversation(&pinfo->src,
1150                             &pinfo->dst, pinfo->ptype, pinfo->srcport,
1151                             pinfo->destport, 0);
1152                 } else {
1153                         /*
1154                          * XXX - can we just use NO_ADDR_B?  Unfortunately,
1155                          * you currently still have to pass a non-null
1156                          * pointer for the second address argument even
1157                          * if you do that.
1158                          */
1159                         conversation = find_conversation(&pinfo->src,
1160                             &null_address, pinfo->ptype, pinfo->srcport,
1161                             pinfo->destport, 0);
1162                 }
1163                 if (conversation == NULL) {
1164                         /* It's not part of any conversation - create a new
1165                            one.
1166
1167                            XXX - this should never happen, as we should've
1168                            created a conversation for it in the RPC
1169                            dissector. */
1170                         if (pinfo->ptype == PT_TCP) {
1171                                 conversation = conversation_new(&pinfo->src,
1172                                     &pinfo->dst, pinfo->ptype, pinfo->srcport,
1173                                     pinfo->destport, 0);
1174                         } else {
1175                                 conversation = conversation_new(&pinfo->src,
1176                                     &null_address, pinfo->ptype, pinfo->srcport,
1177                                     pinfo->destport, 0);
1178                         }
1179                 }
1180
1181                 /* Make the dissector for this conversation the non-heuristic
1182                    RPC dissector. */
1183                 conversation_set_dissector(conversation,
1184                     (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1185
1186                 /* Prepare the key data.
1187
1188                    Dissectors for RPC procedure calls and replies shouldn't
1189                    create new tvbuffs, and we don't create one ourselves,
1190                    so we should have been handed the tvbuff for this RPC call;
1191                    as such, the XID is at offset 0 in this tvbuff. */
1192                 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1193                 rpc_call_key.conversation = conversation;
1194
1195                 /* look up the request */
1196                 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1197                 if (rpc_call == NULL) {
1198                         /* We didn't find it; create a new entry.
1199                            Prepare the value data.
1200                            Not all of it is needed for handling indirect
1201                            calls, so we set a bunch of items to 0. */
1202                         new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1203                         *new_rpc_call_key = rpc_call_key;
1204                         rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1205                         rpc_call->req_num = 0;
1206                         rpc_call->rep_num = 0;
1207                         rpc_call->prog = prog;
1208                         rpc_call->vers = vers;
1209                         rpc_call->proc = proc;
1210
1211                         /*
1212                          * XXX - what about RPCSEC_GSS?
1213                          * Do we have to worry about it?
1214                          */
1215                         rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1216                         rpc_call->gss_proc = 0;
1217                         rpc_call->gss_svc = 0;
1218                         rpc_call->proc_info = value;
1219                         /* store it */
1220                         g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1221                             rpc_call);
1222                 }
1223         }
1224         else {
1225                 /* We don't know the procedure.
1226                    Happens only with strange program versions or
1227                    non-existing dissectors.
1228                    Just show the arguments as opaque data. */
1229                 offset = dissect_rpc_data(tvb, pinfo, tree, args_id,
1230                     offset);
1231                 return offset;
1232         }
1233
1234         if ( tree )
1235         {
1236                 proto_tree_add_text(tree, tvb, offset, 4,
1237                         "Argument length: %u",
1238                         tvb_get_ntohl(tvb, offset));
1239         }
1240         offset += 4;
1241
1242         /* Dissect the arguments */
1243         offset = call_dissect_function(tvb, pinfo, tree, offset,
1244                         dissect_function, NULL);
1245         return offset;
1246 }
1247
1248 /*
1249  * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1250  * dissector.
1251  */
1252 int
1253 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1254     int offset, int result_id, int prog_id, int vers_id, int proc_id)
1255 {
1256         conversation_t* conversation;
1257         static address null_address = { AT_NONE, 0, NULL };
1258         rpc_call_info_key rpc_call_key;
1259         rpc_call_info_value *rpc_call;
1260         char *procname = NULL;
1261         char procname_static[20];
1262         dissect_function_t *dissect_function = NULL;
1263
1264         /* Look for the matching call in the hash table of indirect
1265            calls.  A reply must match a call that we've seen, and the
1266            reply must be sent to the same port and address that the
1267            call came from, and must come from the port to which the
1268            call was sent.
1269
1270            If the transport is connection-oriented (we check, for
1271            now, only for "pinfo->ptype" of PT_TCP), we take
1272            into account the address from which the call was sent
1273            and the address to which the call was sent, because
1274            the addresses of the two endpoints should be the same
1275            for all calls and replies.
1276
1277            If the transport is connectionless, we don't worry
1278            about the address to which the call was sent and from
1279            which the reply was sent, because there's no
1280            guarantee that the reply will come from the address
1281            to which the call was sent. */
1282         if (pinfo->ptype == PT_TCP) {
1283                 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1284                     pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1285         } else {
1286                 /*
1287                  * XXX - can we just use NO_ADDR_B?  Unfortunately,
1288                  * you currently still have to pass a non-null
1289                  * pointer for the second address argument even
1290                  * if you do that.
1291                  */
1292                 conversation = find_conversation(&null_address, &pinfo->dst,
1293                     pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1294         }
1295         if (conversation == NULL) {
1296                 /* We haven't seen an RPC call for that conversation,
1297                    so we can't check for a reply to that call.
1298                    Just show the reply stuff as opaque data. */
1299                 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1300                     offset);
1301                 return offset;
1302         }
1303
1304         /* The XIDs of the call and reply must match. */
1305         rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1306         rpc_call_key.conversation = conversation;
1307         rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1308         if (rpc_call == NULL) {
1309                 /* The XID doesn't match a call from that
1310                    conversation, so it's probably not an RPC reply.
1311                    Just show the reply stuff as opaque data. */
1312                 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1313                     offset);
1314                 return offset;
1315         }
1316
1317         if (rpc_call->proc_info != NULL) {
1318                 dissect_function = rpc_call->proc_info->dissect_reply;
1319                 if (rpc_call->proc_info->name != NULL) {
1320                         procname = rpc_call->proc_info->name;
1321                 }
1322                 else {
1323                         sprintf(procname_static, "proc-%u", rpc_call->proc);
1324                         procname = procname_static;
1325                 }
1326         }
1327         else {
1328 #if 0
1329                 dissect_function = NULL;
1330 #endif
1331                 sprintf(procname_static, "proc-%u", rpc_call->proc);
1332                 procname = procname_static;
1333         }
1334
1335         if ( tree )
1336         {
1337                 /* Put the program, version, and procedure into the tree. */
1338                 proto_tree_add_uint_format(tree, prog_id, tvb,
1339                         0, 0, rpc_call->prog, "Program: %s (%u)",
1340                         rpc_prog_name(rpc_call->prog), rpc_call->prog);
1341                 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1342                 proto_tree_add_uint_format(tree, proc_id, tvb,
1343                         0, 0, rpc_call->proc, "Procedure: %s (%u)",
1344                         procname, rpc_call->proc);
1345         }
1346
1347         if (dissect_function == NULL) {
1348                 /* We don't know how to dissect the reply procedure.
1349                    Just show the reply stuff as opaque data. */
1350                 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1351                     offset);
1352                 return offset;
1353         }
1354
1355         if (tree) {
1356                 /* Put the length of the reply value into the tree. */
1357                 proto_tree_add_text(tree, tvb, offset, 4,
1358                         "Argument length: %u",
1359                         tvb_get_ntohl(tvb, offset));
1360         }
1361         offset += 4;
1362
1363         /* Dissect the return value */
1364         offset = call_dissect_function(tvb, pinfo, tree, offset,
1365                         dissect_function, NULL);
1366         return offset;
1367 }
1368
1369 /*
1370  * Just mark this as a continuation of an earlier packet.
1371  */
1372 static void
1373 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1374 {
1375         proto_item *rpc_item;
1376         proto_tree *rpc_tree;
1377
1378         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1379                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1380         if (check_col(pinfo->cinfo, COL_INFO))
1381                 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1382
1383         if (tree) {
1384                 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1385                                 tvb_length(tvb), FALSE);
1386                 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1387                 proto_tree_add_text(rpc_tree, tvb, 0, tvb_length(tvb),
1388                     "Continuation data");
1389         }
1390 }
1391
1392 static gboolean
1393 dissect_rpc_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1394     proto_tree *tree, gboolean use_rm, guint32 rpc_rm)
1395 {
1396         guint32 msg_type;
1397         rpc_call_info_key rpc_call_key;
1398         rpc_call_info_value *rpc_call = NULL;
1399         rpc_prog_info_value *rpc_prog = NULL;
1400         rpc_prog_info_key rpc_prog_key;
1401
1402         unsigned int xid;
1403         unsigned int rpcvers;
1404         unsigned int prog = 0;
1405         unsigned int vers = 0;
1406         unsigned int proc = 0;
1407         flavor_t flavor = FLAVOR_UNKNOWN;
1408         unsigned int gss_proc = 0;
1409         unsigned int gss_svc = 0;
1410         int     proto = 0;
1411         int     ett = 0;
1412
1413         unsigned int reply_state;
1414         unsigned int accept_state;
1415         unsigned int reject_state;
1416
1417         char *msg_type_name = NULL;
1418         char *progname = NULL;
1419         char *procname = NULL;
1420         static char procname_static[20];
1421
1422         unsigned int vers_low;
1423         unsigned int vers_high;
1424
1425         unsigned int auth_state;
1426
1427         proto_item *rpc_item=NULL;
1428         proto_tree *rpc_tree = NULL;
1429
1430         proto_item *pitem=NULL;
1431         proto_tree *ptree = NULL;
1432         int offset_old = offset;
1433
1434         rpc_call_info_key       *new_rpc_call_key;
1435         rpc_proc_info_key       key;
1436         rpc_proc_info_value     *value = NULL;
1437         conversation_t* conversation;
1438         static address null_address = { AT_NONE, 0, NULL };
1439         nstime_t ns;
1440
1441         dissect_function_t *dissect_function = NULL;
1442
1443         /*
1444          * Check to see whether this looks like an RPC call or reply.
1445          */
1446         if (!tvb_bytes_exist(tvb, offset, 8)) {
1447                 /* Captured data in packet isn't enough to let us tell. */
1448                 return FALSE;
1449         }
1450
1451         /* both directions need at least this */
1452         msg_type = tvb_get_ntohl(tvb, offset + 4);
1453
1454         switch (msg_type) {
1455
1456         case RPC_CALL:
1457                 /* check for RPC call */
1458                 if (!tvb_bytes_exist(tvb, offset, 16)) {
1459                         /* Captured data in packet isn't enough to let us
1460                            tell. */
1461                         return FALSE;
1462                 }
1463
1464                 /* XID can be anything, we don't check it.
1465                    We already have the message type.
1466                    Check whether an RPC version number of 2 is in the
1467                    location where it would be, and that an RPC program
1468                    number we know about is in the location where it would be. */
1469                 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1470                 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1471                     ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1472                        == NULL)) {
1473                         /* They're not, so it's probably not an RPC call. */
1474                         return FALSE;
1475                 }
1476                 break;
1477
1478         case RPC_REPLY:
1479                 /* Check for RPC reply.  A reply must match a call that
1480                    we've seen, and the reply must be sent to the same
1481                    port and address that the call came from, and must
1482                    come from the port to which the call was sent.
1483
1484                    If the transport is connection-oriented (we check, for
1485                    now, only for "pinfo->ptype" of PT_TCP), we take
1486                    into account the address from which the call was sent
1487                    and the address to which the call was sent, because
1488                    the addresses of the two endpoints should be the same
1489                    for all calls and replies.
1490
1491                    If the transport is connectionless, we don't worry
1492                    about the address to which the call was sent and from
1493                    which the reply was sent, because there's no
1494                    guarantee that the reply will come from the address
1495                    to which the call was sent. */
1496                 if (pinfo->ptype == PT_TCP) {
1497                         conversation = find_conversation(&pinfo->src,
1498                             &pinfo->dst, pinfo->ptype, pinfo->srcport,
1499                             pinfo->destport, 0);
1500                 } else {
1501                         /*
1502                          * XXX - can we just use NO_ADDR_B?  Unfortunately,
1503                          * you currently still have to pass a non-null
1504                          * pointer for the second address argument even
1505                          * if you do that.
1506                          */
1507                         conversation = find_conversation(&null_address,
1508                             &pinfo->dst, pinfo->ptype, pinfo->srcport,
1509                             pinfo->destport, 0);
1510                 }
1511                 if (conversation == NULL) {
1512                         /* We haven't seen an RPC call for that conversation,
1513                            so we can't check for a reply to that call. */
1514                         return FALSE;
1515                 }
1516
1517                 /* The XIDs of the call and reply must match. */
1518                 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1519                 rpc_call_key.conversation = conversation;
1520                 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1521                 if (rpc_call == NULL) {
1522                         /* The XID doesn't match a call from that
1523                            conversation, so it's probably not an RPC reply. */
1524                         return FALSE;
1525                 }
1526                 break;
1527
1528         default:
1529                 /* The putative message type field contains neither
1530                    RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1531                    reply. */
1532                 return FALSE;
1533         }
1534
1535         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1536                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1537         if (check_col(pinfo->cinfo, COL_INFO))
1538                 col_clear(pinfo->cinfo, COL_INFO);
1539
1540         if (tree) {
1541                 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1542                                 tvb_length(tvb), FALSE);
1543                 if (rpc_item) {
1544                         rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1545                 }
1546         }
1547
1548         if (use_rm && rpc_tree) {
1549                 proto_tree_add_boolean(rpc_tree,hf_rpc_lastfrag, tvb,
1550                         offset-4, 4, (rpc_rm >> 31) & 0x1);
1551                 proto_tree_add_uint(rpc_tree,hf_rpc_fraglen, tvb,
1552                         offset-4, 4, rpc_rm & RPC_RM_FRAGLEN);
1553         }
1554
1555         xid      = tvb_get_ntohl(tvb, offset + 0);
1556         if (rpc_tree) {
1557                 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1558                         offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1559         }
1560
1561         msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1562         if (rpc_tree) {
1563                 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1564                         offset+4, 4, msg_type);
1565         }
1566
1567         offset += 8;
1568
1569         switch (msg_type) {
1570
1571         case RPC_CALL:
1572                 /* we know already the proto-entry, the ETT-const,
1573                    and "rpc_prog" */
1574                 proto = rpc_prog->proto;
1575                 ett = rpc_prog->ett;
1576                 progname = rpc_prog->progname;
1577
1578                 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1579                 if (rpc_tree) {
1580                         proto_tree_add_uint(rpc_tree,
1581                                 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1582                 }
1583
1584                 prog = tvb_get_ntohl(tvb, offset + 4);
1585                 
1586                 if (rpc_tree) {
1587                         proto_tree_add_uint_format(rpc_tree,
1588                                 hf_rpc_program, tvb, offset+4, 4, prog,
1589                                 "Program: %s (%u)", progname, prog);
1590                 }
1591                 
1592                 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1593                         /* Set the protocol name to the underlying
1594                            program name. */
1595                         col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1596                 }
1597
1598                 vers = tvb_get_ntohl(tvb, offset+8);
1599                 if (rpc_tree) {
1600                         proto_tree_add_uint(rpc_tree,
1601                                 hf_rpc_programversion, tvb, offset+8, 4, vers);
1602                 }
1603
1604                 proc = tvb_get_ntohl(tvb, offset+12);
1605
1606                 key.prog = prog;
1607                 key.vers = vers;
1608                 key.proc = proc;
1609
1610                 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1611                         dissect_function = value->dissect_call;
1612                         procname = value->name;
1613                 }
1614                 else {
1615                         /* happens only with strange program versions or
1616                            non-existing dissectors */
1617 #if 0
1618                         dissect_function = NULL;
1619 #endif
1620                         sprintf(procname_static, "proc-%u", proc);
1621                         procname = procname_static;
1622                 }
1623                 
1624                 if (rpc_tree) {
1625                         proto_tree_add_uint_format(rpc_tree,
1626                                 hf_rpc_procedure, tvb, offset+12, 4, proc,
1627                                 "Procedure: %s (%u)", procname, proc);
1628                 }
1629
1630                 if (check_col(pinfo->cinfo, COL_INFO)) {
1631                         col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1632                                 vers,
1633                                 procname,
1634                                 msg_type_name,
1635                                 xid);
1636                 }
1637
1638                 /* Check for RPCSEC_GSS */
1639                 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1640                         switch (tvb_get_ntohl(tvb, offset+16)) {
1641
1642                         case RPCSEC_GSS:
1643                                 /*
1644                                  * It's GSS-API authentication...
1645                                  */
1646                                 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1647                                         /*
1648                                          * ...and we have the procedure
1649                                          * and service information for it.
1650                                          */
1651                                         flavor = FLAVOR_GSSAPI;
1652                                         gss_proc = tvb_get_ntohl(tvb, offset+28);
1653                                         gss_svc = tvb_get_ntohl(tvb, offset+36);
1654                                 } else {
1655                                         /*
1656                                          * ...but the procedure and service
1657                                          * information isn't available.
1658                                          */
1659                                         flavor = FLAVOR_GSSAPI_NO_INFO;
1660                                 }
1661                                 break;
1662
1663                         default:
1664                                 /*
1665                                  * It's not GSS-API authentication.
1666                                  */
1667                                 flavor = FLAVOR_NOT_GSSAPI;
1668                                 break;
1669                         }
1670                 }
1671
1672                 /* Keep track of the address and port whence the call came,
1673                    and the port to which the call is being sent, so that
1674                    we can match up calls with replies.
1675
1676                    If the transport is connection-oriented (we check, for
1677                    now, only for "pinfo->ptype" of PT_TCP), we take
1678                    into account the address from which the call was sent
1679                    and the address to which the call was sent, because
1680                    the addresses of the two endpoints should be the same
1681                    for all calls and replies.
1682
1683                    If the transport is connectionless, we don't worry
1684                    about the address to which the call was sent and from
1685                    which the reply was sent, because there's no
1686                    guarantee that the reply will come from the address
1687                    to which the call was sent. */
1688                 if (pinfo->ptype == PT_TCP) {
1689                         conversation = find_conversation(&pinfo->src,
1690                             &pinfo->dst, pinfo->ptype, pinfo->srcport,
1691                             pinfo->destport, 0);
1692                 } else {
1693                         /*
1694                          * XXX - can we just use NO_ADDR_B?  Unfortunately,
1695                          * you currently still have to pass a non-null
1696                          * pointer for the second address argument even
1697                          * if you do that.
1698                          */
1699                         conversation = find_conversation(&pinfo->src,
1700                             &null_address, pinfo->ptype, pinfo->srcport,
1701                             pinfo->destport, 0);
1702                 }
1703                 if (conversation == NULL) {
1704                         /* It's not part of any conversation - create a new
1705                            one. */
1706                         if (pinfo->ptype == PT_TCP) {
1707                                 conversation = conversation_new(&pinfo->src,
1708                                     &pinfo->dst, pinfo->ptype, pinfo->srcport,
1709                                     pinfo->destport, 0);
1710                         } else {
1711                                 conversation = conversation_new(&pinfo->src,
1712                                     &null_address, pinfo->ptype, pinfo->srcport,
1713                                     pinfo->destport, 0);
1714                         }
1715                 }
1716
1717                 /* Make the dissector for this conversation the non-heuristic
1718                    RPC dissector. */
1719                 conversation_set_dissector(conversation,
1720                     (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1721
1722                 /* prepare the key data */
1723                 rpc_call_key.xid = xid;
1724                 rpc_call_key.conversation = conversation;
1725
1726                 /* look up the request */
1727                 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1728                 if (rpc_call != NULL) {
1729                         /* We've seen a request with this XID, with the same
1730                            source and destination, before - but was it
1731                            *this* request? */
1732                         if (pinfo->fd->num != rpc_call->req_num) {
1733                                 /* No, so it's a duplicate request.
1734                                    Mark it as such. */
1735                                 if (check_col(pinfo->cinfo, COL_INFO)) {
1736                                         col_append_fstr(pinfo->cinfo, COL_INFO,
1737                                                 " dup XID 0x%x", xid);
1738                                         if (rpc_tree) {
1739                                                 proto_tree_add_uint_hidden(rpc_tree,
1740                                                         hf_rpc_dup, tvb, 0,0, xid);
1741                                                 proto_tree_add_uint_hidden(rpc_tree,
1742                                                         hf_rpc_call_dup, tvb, 0,0, xid);
1743                                         }
1744                                 }
1745                         }
1746                 }
1747                 else {
1748                         /* Prepare the value data.
1749                            "req_num" and "rep_num" are frame numbers;
1750                            frame numbers are 1-origin, so we use 0
1751                            to mean "we don't yet know in which frame
1752                            the reply for this call appears". */
1753                         new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1754                         *new_rpc_call_key = rpc_call_key;
1755                         rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1756                         rpc_call->req_num = pinfo->fd->num;
1757                         rpc_call->rep_num = 0;
1758                         rpc_call->prog = prog;
1759                         rpc_call->vers = vers;
1760                         rpc_call->proc = proc;
1761                         rpc_call->flavor = flavor;
1762                         rpc_call->gss_proc = gss_proc;
1763                         rpc_call->gss_svc = gss_svc;
1764                         rpc_call->proc_info = value;
1765                         rpc_call->req_time.secs=pinfo->fd->abs_secs;
1766                         rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
1767
1768                         /* store it */
1769                         g_hash_table_insert(rpc_calls, new_rpc_call_key,
1770                             rpc_call);
1771                 }
1772
1773                 offset += 16;
1774
1775                 offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset);
1776                 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1777
1778                 /* go to the next dissector */
1779
1780                 break;  /* end of RPC call */
1781
1782         case RPC_REPLY:
1783                 /* we know already the type from the calling routine,
1784                    and we already have "rpc_call" set above. */
1785                 prog = rpc_call->prog;
1786                 vers = rpc_call->vers;
1787                 proc = rpc_call->proc;
1788                 flavor = rpc_call->flavor;
1789                 gss_proc = rpc_call->gss_proc;
1790                 gss_svc = rpc_call->gss_svc;
1791
1792                 /* Indicate the frame to which this is a reply. */
1793                 proto_tree_add_text(rpc_tree, tvb, 0, 0,
1794                     "This is a reply to a request in frame %u",
1795                     rpc_call->req_num);
1796                 ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
1797                 ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
1798                 if(ns.nsecs<0){
1799                         ns.nsecs+=1000000000;
1800                         ns.secs--;
1801                 }
1802                 proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
1803                                 &ns);
1804
1805
1806
1807                 if (rpc_call->proc_info != NULL) {
1808                         dissect_function = rpc_call->proc_info->dissect_reply;
1809                         if (rpc_call->proc_info->name != NULL) {
1810                                 procname = rpc_call->proc_info->name;
1811                         }
1812                         else {
1813                                 sprintf(procname_static, "proc-%u", proc);
1814                                 procname = procname_static;
1815                         }
1816                 }
1817                 else {
1818 #if 0
1819                         dissect_function = NULL;
1820 #endif
1821                         sprintf(procname_static, "proc-%u", proc);
1822                         procname = procname_static;
1823                 }
1824
1825                 rpc_prog_key.prog = prog;
1826                 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1827                         proto = 0;
1828                         ett = 0;
1829                         progname = "Unknown";
1830                 }
1831                 else {
1832                         proto = rpc_prog->proto;
1833                         ett = rpc_prog->ett;
1834                         progname = rpc_prog->progname;
1835
1836                         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1837                                 /* Set the protocol name to the underlying
1838                                    program name. */
1839                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1840                         }
1841                 }
1842
1843                 if (check_col(pinfo->cinfo, COL_INFO)) {
1844                         col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1845                                 vers,
1846                                 procname,
1847                                 msg_type_name,
1848                                 xid);
1849                 }
1850
1851                 if (rpc_tree) {
1852                         proto_tree_add_uint_format(rpc_tree,
1853                                 hf_rpc_program, tvb, 0, 0, prog,
1854                                 "Program: %s (%u)", progname, prog);
1855                         proto_tree_add_uint(rpc_tree,
1856                                 hf_rpc_programversion, tvb, 0, 0, vers);
1857                         proto_tree_add_uint_format(rpc_tree,
1858                                 hf_rpc_procedure, tvb, 0, 0, proc,
1859                                 "Procedure: %s (%u)", procname, proc);
1860                 }
1861
1862                 if (rpc_call->rep_num == 0) {
1863                         /* We have not yet seen a reply to that call, so
1864                            this must be the first reply; remember its
1865                            frame number. */
1866                         rpc_call->rep_num = pinfo->fd->num;
1867                 } else {
1868                         /* We have seen a reply to this call - but was it
1869                            *this* reply? */
1870                         if (rpc_call->rep_num != pinfo->fd->num) {
1871                                 /* No, so it's a duplicate reply.
1872                                    Mark it as such. */
1873                                 if (check_col(pinfo->cinfo, COL_INFO)) {
1874                                         col_append_fstr(pinfo->cinfo, COL_INFO,
1875                                                 " dup XID 0x%x", xid);
1876                                         if (rpc_tree) {
1877                                                 proto_tree_add_uint_hidden(rpc_tree,
1878                                                         hf_rpc_dup, tvb, 0,0, xid);
1879                                                 proto_tree_add_uint_hidden(rpc_tree,
1880                                                         hf_rpc_reply_dup, tvb, 0,0, xid);
1881                                         }
1882                                 }
1883                         }
1884                 }
1885
1886                 reply_state = tvb_get_ntohl(tvb,offset+0);
1887                 if (rpc_tree) {
1888                         proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
1889                                 offset+0, 4, reply_state);
1890                 }
1891                 offset += 4;
1892
1893                 if (reply_state == MSG_ACCEPTED) {
1894                         offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1895                         accept_state = tvb_get_ntohl(tvb,offset+0);
1896                         if (rpc_tree) {
1897                                 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
1898                                         offset+0, 4, accept_state);
1899                         }
1900                         offset += 4;
1901                         switch (accept_state) {
1902
1903                         case SUCCESS:
1904                                 /* go to the next dissector */
1905                                 break;
1906
1907                         case PROG_MISMATCH:
1908                                 vers_low = tvb_get_ntohl(tvb,offset+0);
1909                                 vers_high = tvb_get_ntohl(tvb,offset+4);
1910                                 if (rpc_tree) {
1911                                         proto_tree_add_uint(rpc_tree,
1912                                                 hf_rpc_programversion_min,
1913                                                 tvb, offset+0, 4, vers_low);
1914                                         proto_tree_add_uint(rpc_tree,
1915                                                 hf_rpc_programversion_max,
1916                                                 tvb, offset+4, 4, vers_high);
1917                                 }
1918                                 offset += 8;
1919                                 break;
1920
1921                         default:
1922                                 /* void */
1923                                 break;
1924                         }
1925                 } else if (reply_state == MSG_DENIED) {
1926                         reject_state = tvb_get_ntohl(tvb,offset+0);
1927                         if (rpc_tree) {
1928                                 proto_tree_add_uint(rpc_tree,
1929                                         hf_rpc_state_reject, tvb, offset+0, 4,
1930                                         reject_state);
1931                         }
1932                         offset += 4;
1933
1934                         if (reject_state==RPC_MISMATCH) {
1935                                 vers_low = tvb_get_ntohl(tvb,offset+0);
1936                                 vers_high = tvb_get_ntohl(tvb,offset+4);
1937                                 if (rpc_tree) {
1938                                         proto_tree_add_uint(rpc_tree,
1939                                                 hf_rpc_version_min,
1940                                                 tvb, offset+0, 4, vers_low);
1941                                         proto_tree_add_uint(rpc_tree,
1942                                                 hf_rpc_version_max,
1943                                                 tvb, offset+4, 4, vers_high);
1944                                 }
1945                                 offset += 8;
1946                         } else if (reject_state==AUTH_ERROR) {
1947                                 auth_state = tvb_get_ntohl(tvb,offset+0);
1948                                 if (rpc_tree) {
1949                                         proto_tree_add_uint(rpc_tree,
1950                                                 hf_rpc_state_auth, tvb, offset+0, 4,
1951                                                 auth_state);
1952                                 }
1953                                 offset += 4;
1954                         }
1955                 } 
1956                 break; /* end of RPC reply */
1957
1958         default:
1959                 /*
1960                  * The switch statement at the top returned if
1961                  * this was neither an RPC call nor a reply.
1962                  */
1963                 g_assert_not_reached();
1964         }
1965
1966         /* now we know, that RPC was shorter */
1967         if (rpc_item) {
1968                 proto_item_set_len(rpc_item, offset - offset_old);
1969         }
1970
1971         /* create here the program specific sub-tree */
1972         if (tree) {
1973                 pitem = proto_tree_add_item(tree, proto, tvb,
1974                                 offset, tvb_length(tvb) - offset, FALSE);
1975                 if (pitem) {
1976                         ptree = proto_item_add_subtree(pitem, ett);
1977                 }
1978
1979                 if (ptree) {
1980                         proto_tree_add_uint(ptree,
1981                                 hf_rpc_programversion, tvb, 0, 0, vers);
1982                         proto_tree_add_uint_format(ptree,
1983                                 hf_rpc_procedure, tvb, 0, 0, proc,
1984                                 "Procedure: %s (%u)", procname, proc);
1985                 }
1986         }
1987
1988         if (!proto_is_protocol_enabled(proto))
1989                 dissect_function = NULL;
1990
1991         /*
1992          * Handle RPCSEC_GSS specially.
1993          */
1994         switch (flavor) {
1995
1996         case FLAVOR_UNKNOWN:
1997                 /*
1998                  * We don't know the authentication flavor, so we can't
1999                  * dissect the payload.
2000                  */
2001                 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2002                     "Unknown authentication flavor - cannot dissect");
2003                 return TRUE;
2004
2005         case FLAVOR_NOT_GSSAPI:
2006                 /*
2007                  * It's not GSS-API authentication.  Just dissect the
2008                  * payload.
2009                  */
2010                 offset = call_dissect_function(tvb, pinfo, ptree, offset,
2011                                 dissect_function, progname);
2012                 break;
2013
2014         case FLAVOR_GSSAPI_NO_INFO:
2015                 /*
2016                  * It's GSS-API authentication, but we don't have the
2017                  * procedure and service information, so we can't dissect
2018                  * the payload.
2019                  */
2020                 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2021                     "GSS-API authentication, but procedure and service unknown - cannot dissect");
2022                 return TRUE;
2023
2024         case FLAVOR_GSSAPI:
2025                 /*
2026                  * It's GSS-API authentication, and we have the procedure
2027                  * and service information; process the GSS-API stuff,
2028                  * and process the payload if there is any.
2029                  */
2030                 switch (gss_proc) {
2031
2032                 case RPCSEC_GSS_INIT:
2033                 case RPCSEC_GSS_CONTINUE_INIT:
2034                         if (msg_type == RPC_CALL) {
2035                                 offset = dissect_rpc_authgss_initarg(tvb,
2036                                         pinfo, ptree, offset);
2037                         }
2038                         else {
2039                                 offset = dissect_rpc_authgss_initres(tvb,
2040                                         pinfo, ptree, offset);
2041                         }
2042                         break;
2043
2044                 case RPCSEC_GSS_DATA:
2045                         if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2046                                 offset = call_dissect_function(tvb, 
2047                                                 pinfo, ptree, offset,
2048                                                 dissect_function,
2049                                                 progname);
2050                         }
2051                         else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2052                                 offset = dissect_rpc_authgss_integ_data(tvb,
2053                                                 pinfo, ptree, offset,
2054                                                 dissect_function,
2055                                                 progname);
2056                         }
2057                         else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2058                                 offset = dissect_rpc_authgss_priv_data(tvb,
2059                                                 pinfo, ptree, offset);
2060                         }
2061                         break;
2062
2063                 default:
2064                         break;
2065                 }
2066         }
2067
2068         /* dissect any remaining bytes (incomplete dissection) as pure data in
2069            the ptree */
2070         call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, ptree);
2071
2072         return TRUE;
2073 }
2074
2075 static gboolean
2076 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2077 {
2078         return dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0);
2079 }
2080
2081 static void
2082 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2083 {
2084         if (!dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0))
2085                 dissect_rpc_continuation(tvb, pinfo, tree);
2086 }
2087
2088 /*
2089  * Can return:
2090  *
2091  *      NEED_MORE_DATA, if we don't have enough data to dissect anything;
2092  *
2093  *      IS_RPC, if we dissected at least one message in its entirety
2094  *      as RPC;
2095  *
2096  *      IS_NOT_RPC, if we found no RPC message.
2097  */
2098 typedef enum {
2099         NEED_MORE_DATA,
2100         IS_RPC,
2101         IS_NOT_RPC
2102 } rpc_tcp_return_t;
2103
2104 static rpc_tcp_return_t
2105 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2106     gboolean is_heur)
2107 {
2108         volatile int offset = 0;
2109         guint32 rpc_rm;
2110         volatile gboolean saw_rpc = FALSE;
2111         volatile gint32 len;
2112         gint32 seglen;
2113         gint tvb_len, tvb_reported_len;
2114         tvbuff_t *msg_tvb;
2115         const char *saved_proto;
2116
2117         while (tvb_reported_length_remaining(tvb, offset) != 0) {
2118                 /*
2119                  * XXX - we need to handle records that don't have the "last
2120                  * fragment" bit set, and reassemble fragments.
2121                  */
2122
2123                 /* the first 4 bytes are special in "record marking mode" */
2124                 if (!tvb_bytes_exist(tvb, offset, 4)) {
2125                         /*
2126                          * XXX - we should somehow arrange to handle
2127                          * a record mark split across TCP segments.
2128                          */
2129                         return saw_rpc ? IS_RPC : IS_NOT_RPC;
2130                 }
2131                 rpc_rm = tvb_get_ntohl(tvb, offset);
2132
2133                 len = rpc_rm&RPC_RM_FRAGLEN;
2134
2135                 /*
2136                  * XXX - reject fragments bigger than 2 megabytes.
2137                  * This is arbitrary, but should at least prevent
2138                  * some crashes from either packets with really
2139                  * large RPC-over-TCP fragments or from stuff that's
2140                  * not really RPC.
2141                  */
2142                 if (len > 2*1024*1024)
2143                         return saw_rpc ? IS_RPC : IS_NOT_RPC;
2144                 if (rpc_desegment) {
2145                         seglen = tvb_length_remaining(tvb, offset + 4);
2146
2147                         if (len > seglen && pinfo->can_desegment) {
2148                                 /*
2149                                  * This frame doesn't have all of the
2150                                  * data for this message, but we can do
2151                                  * reassembly on it.
2152                                  *
2153                                  * If this is a heuristic dissector, just
2154                                  * return IS_NOT_RPC - we don't want to try
2155                                  * to get more data, as that's too likely
2156                                  * to cause us to misidentify this as
2157                                  * RPC.
2158                                  *
2159                                  * If this isn't a heuristic dissector,
2160                                  * we've already identified this conversation
2161                                  * as containing RPC data, as we saw RPC
2162                                  * data in previous frames.  Try to get
2163                                  * more data.
2164                                  */
2165                                 if (is_heur)
2166                                         return IS_NOT_RPC;
2167                                 else {
2168                                         pinfo->desegment_offset = offset;
2169                                         pinfo->desegment_len = len - seglen;
2170                                         return NEED_MORE_DATA;
2171                                 }
2172                         }
2173                 }
2174                 len += 4;       /* include record mark */
2175                 tvb_len = tvb_length_remaining(tvb, offset);
2176                 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2177                 if (tvb_len > len)
2178                         tvb_len = len;
2179                 if (tvb_reported_len > len)
2180                         tvb_reported_len = len;
2181                 msg_tvb = tvb_new_subset(tvb, offset, tvb_len,
2182                     tvb_reported_len);
2183
2184                 /*
2185                  * Catch the ReportedBoundsError exception; if this
2186                  * particular message happens to get a ReportedBoundsError
2187                  * exception, that doesn't mean that we should stop
2188                  * dissecting RPC messages within this frame or chunk
2189                  * of reassembled data.
2190                  *
2191                  * If it gets a BoundsError, we can stop, as there's
2192                  * nothing more to see, so we just re-throw it.
2193                  */
2194                 saved_proto = pinfo->current_proto;
2195                 TRY {
2196                         if (!dissect_rpc_message(msg_tvb, 4, pinfo, tree,
2197                             TRUE, rpc_rm))
2198                                 break;
2199                 }
2200                 CATCH(BoundsError) {
2201                         RETHROW;
2202                 }
2203                 CATCH(ReportedBoundsError) {
2204                         if (check_col(pinfo->cinfo, COL_INFO)) {
2205                                 col_append_str(pinfo->cinfo, COL_INFO,
2206                                     "[Malformed Packet]");
2207                         }
2208                         proto_tree_add_protocol_format(tree, proto_malformed,
2209                             tvb, 0, 0, "[Malformed Packet: %s]",
2210                             pinfo->current_proto );
2211                         pinfo->current_proto = saved_proto;
2212                 }
2213                 ENDTRY;
2214                 offset += len;
2215                 saw_rpc = TRUE;
2216         }
2217         return saw_rpc ? IS_RPC : IS_NOT_RPC;
2218 }
2219
2220 static gboolean
2221 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2222 {
2223         switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
2224
2225         case IS_RPC:
2226                 return TRUE;
2227
2228         case IS_NOT_RPC:
2229                 return FALSE;
2230
2231         default:
2232                 /* "Can't happen" */
2233                 g_assert_not_reached();
2234                 return FALSE;
2235         }
2236 }
2237
2238 static void
2239 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2240 {
2241         if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
2242                 dissect_rpc_continuation(tvb, pinfo, tree);
2243 }
2244
2245 /* Discard any state we've saved. */
2246 static void
2247 rpc_init_protocol(void)
2248 {
2249         if (rpc_calls != NULL)
2250                 g_hash_table_destroy(rpc_calls);
2251         if (rpc_indir_calls != NULL)
2252                 g_hash_table_destroy(rpc_indir_calls);
2253         if (rpc_call_info_key_chunk != NULL)
2254                 g_mem_chunk_destroy(rpc_call_info_key_chunk);
2255         if (rpc_call_info_value_chunk != NULL)
2256                 g_mem_chunk_destroy(rpc_call_info_value_chunk);
2257
2258         rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2259         rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2260         rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
2261             sizeof(rpc_call_info_key),
2262             200 * sizeof(rpc_call_info_key),
2263             G_ALLOC_ONLY);
2264         rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
2265             sizeof(rpc_call_info_value),
2266             200 * sizeof(rpc_call_info_value),
2267             G_ALLOC_ONLY);
2268 }
2269
2270 /* will be called once from register.c at startup time */
2271 void
2272 proto_register_rpc(void)
2273 {
2274         static hf_register_info hf[] = {
2275                 { &hf_rpc_lastfrag, {
2276                         "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, BASE_NONE,
2277                         &yesno, 0, "Last Fragment", HFILL }},
2278                 { &hf_rpc_fraglen, {
2279                         "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
2280                         NULL, 0, "Fragment Length", HFILL }},
2281                 { &hf_rpc_xid, {
2282                         "XID", "rpc.xid", FT_UINT32, BASE_HEX,
2283                         NULL, 0, "XID", HFILL }},
2284                 { &hf_rpc_msgtype, {
2285                         "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
2286                         VALS(rpc_msg_type), 0, "Message Type", HFILL }},
2287                 { &hf_rpc_state_reply, {
2288                         "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
2289                         VALS(rpc_reply_state), 0, "Reply State", HFILL }},
2290                 { &hf_rpc_state_accept, {
2291                         "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
2292                         VALS(rpc_accept_state), 0, "Accept State", HFILL }},
2293                 { &hf_rpc_state_reject, {
2294                         "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
2295                         VALS(rpc_reject_state), 0, "Reject State", HFILL }},
2296                 { &hf_rpc_state_auth, {
2297                         "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
2298                         VALS(rpc_auth_state), 0, "Auth State", HFILL }},
2299                 { &hf_rpc_version, {
2300                         "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
2301                         NULL, 0, "RPC Version", HFILL }},
2302                 { &hf_rpc_version_min, {
2303                         "RPC Version (Minimum)", "rpc.version.min", FT_UINT32, 
2304                         BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2305                 { &hf_rpc_version_max, {
2306                         "RPC Version (Maximum)", "rpc.version.max", FT_UINT32, 
2307                         BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
2308                 { &hf_rpc_program, {
2309                         "Program", "rpc.program", FT_UINT32, BASE_DEC,
2310                         NULL, 0, "Program", HFILL }},
2311                 { &hf_rpc_programversion, {
2312                         "Program Version", "rpc.programversion", FT_UINT32, 
2313                         BASE_DEC, NULL, 0, "Program Version", HFILL }},
2314                 { &hf_rpc_programversion_min, {
2315                         "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32, 
2316                         BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2317                 { &hf_rpc_programversion_max, {
2318                         "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32, 
2319                         BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
2320                 { &hf_rpc_procedure, {
2321                         "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
2322                         NULL, 0, "Procedure", HFILL }},
2323                 { &hf_rpc_auth_flavor, {
2324                         "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
2325                         VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
2326                 { &hf_rpc_auth_length, {
2327                         "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
2328                         NULL, 0, "Length", HFILL }},
2329                 { &hf_rpc_auth_stamp, {
2330                         "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
2331                         NULL, 0, "Stamp", HFILL }},
2332                 { &hf_rpc_auth_uid, {
2333                         "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
2334                         NULL, 0, "UID", HFILL }},
2335                 { &hf_rpc_auth_gid, {
2336                         "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
2337                         NULL, 0, "GID", HFILL }},
2338                 { &hf_rpc_authgss_v, {
2339                         "GSS Version", "rpc.authgss.version", FT_UINT32,
2340                         BASE_DEC, NULL, 0, "GSS Version", HFILL }},
2341                 { &hf_rpc_authgss_proc, {
2342                         "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
2343                         BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
2344                 { &hf_rpc_authgss_seq, {
2345                         "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
2346                         BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
2347                 { &hf_rpc_authgss_svc, {
2348                         "GSS Service", "rpc.authgss.service", FT_UINT32,
2349                         BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
2350                 { &hf_rpc_authgss_ctx, {
2351                         "GSS Context", "rpc.authgss.context", FT_BYTES,
2352                         BASE_HEX, NULL, 0, "GSS Context", HFILL }},
2353                 { &hf_rpc_authgss_major, {
2354                         "GSS Major Status", "rpc.authgss.major", FT_UINT32,
2355                         BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
2356                 { &hf_rpc_authgss_minor, {
2357                         "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
2358                         BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
2359                 { &hf_rpc_authgss_window, {
2360                         "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
2361                         BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
2362                 { &hf_rpc_authgss_token, {
2363                         "GSS Token", "rpc.authgss.token", FT_BYTES,
2364                         BASE_HEX, NULL, 0, "GSS Token", HFILL }},
2365                 { &hf_rpc_authgss_data_length, {
2366                         "Length", "rpc.authgss.data.length", FT_UINT32,
2367                         BASE_DEC, NULL, 0, "Length", HFILL }},
2368                 { &hf_rpc_authgss_data, {
2369                         "GSS Data", "rpc.authgss.data", FT_BYTES,
2370                         BASE_HEX, NULL, 0, "GSS Data", HFILL }},
2371                 { &hf_rpc_authgss_checksum, {
2372                         "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
2373                         BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
2374                 { &hf_rpc_authdes_namekind, {
2375                         "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
2376                         VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
2377                 { &hf_rpc_authdes_netname, {
2378                         "Netname", "rpc.authdes.netname", FT_STRING,
2379                         BASE_DEC, NULL, 0, "Netname", HFILL }},
2380                 { &hf_rpc_authdes_convkey, {
2381                         "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
2382                         BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
2383                 { &hf_rpc_authdes_window, {
2384                         "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
2385                         BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
2386                 { &hf_rpc_authdes_nickname, {
2387                         "Nickname", "rpc.authdes.nickname", FT_UINT32, 
2388                         BASE_HEX, NULL, 0, "Nickname", HFILL }},
2389                 { &hf_rpc_authdes_timestamp, {
2390                         "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
2391                         BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
2392                 { &hf_rpc_authdes_windowverf, {
2393                         "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
2394                         BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
2395                 { &hf_rpc_authdes_timeverf, {
2396                         "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
2397                         BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
2398                 { &hf_rpc_auth_machinename, {
2399                         "Machine Name", "rpc.auth.machinename", FT_STRING, 
2400                         BASE_DEC, NULL, 0, "Machine Name", HFILL }},
2401                 { &hf_rpc_dup, {
2402                         "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
2403                         NULL, 0, "Duplicate Transaction", HFILL }},
2404                 { &hf_rpc_call_dup, {
2405                         "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
2406                         NULL, 0, "Duplicate Call", HFILL }},
2407                 { &hf_rpc_reply_dup, {
2408                         "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
2409                         NULL, 0, "Duplicate Reply", HFILL }},
2410                 { &hf_rpc_value_follows, {
2411                         "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
2412                         &yesno, 0, "Value Follows", HFILL }},
2413                 { &hf_rpc_array_len, {
2414                         "num", "rpc.array.len", FT_UINT32, BASE_DEC,
2415                         NULL, 0, "Length of RPC array", HFILL }},
2416
2417                 { &hf_rpc_time, {
2418                         "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
2419                         NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
2420
2421         };
2422         static gint *ett[] = {
2423                 &ett_rpc,
2424                 &ett_rpc_string,
2425                 &ett_rpc_cred,
2426                 &ett_rpc_verf,
2427                 &ett_rpc_gids,
2428                 &ett_rpc_gss_data,
2429                 &ett_rpc_array,
2430         };
2431         module_t *rpc_module;
2432
2433         proto_rpc = proto_register_protocol("Remote Procedure Call",
2434             "RPC", "rpc");
2435         proto_register_field_array(proto_rpc, hf, array_length(hf));
2436         proto_register_subtree_array(ett, array_length(ett));
2437         register_init_routine(&rpc_init_protocol);
2438         rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
2439         rpc_handle = create_dissector_handle(dissect_rpc, proto_rpc);
2440         rpc_module = prefs_register_protocol(proto_rpc, NULL);
2441         prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
2442                 "Desegment all RPC over TCP commands",
2443                 "Whether the RPC dissector should desegment all RPC over TCP commands",
2444                 &rpc_desegment);
2445
2446         /*
2447          * Init the hash tables.  Dissectors for RPC protocols must
2448          * have a "handoff registration" routine that registers the
2449          * protocol with RPC; they must not do it in their protocol
2450          * registration routine, as their protocol registration
2451          * routine might be called before this routine is called and
2452          * thus might be called before the hash tables are initialized,
2453          * but it's guaranteed that all protocol registration routines
2454          * will be called before any handoff registration routines
2455          * are called.
2456          */
2457         rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
2458         rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
2459 }
2460
2461 void
2462 proto_reg_handoff_rpc(void)
2463 {
2464         heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
2465         heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
2466         data_handle = find_dissector("data");
2467 }