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