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