2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.74 2001/10/29 21:13:08 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-smb.c
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.
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.
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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
41 #include "conversation.h"
42 #include "packet-rpc.h"
48 * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
51 * RFC 1832, "XDR: External Data Representation Standard";
53 * RFC 2203, "RPCSEC_GSS Protocol Specification".
57 * RFC 2695, "Authentication Mechanisms for ONC RPC"
59 * although we don't currently dissect AUTH_DES or AUTH_KERB.
62 #define RPC_RM_FRAGLEN 0x7fffffffL
64 /* desegmentation of RPC over TCP */
65 static gboolean rpc_desegment = TRUE;
67 static struct true_false_string yesno = { "Yes", "No" };
70 static const value_string rpc_msg_type[] = {
72 { RPC_REPLY, "Reply" },
76 static const value_string rpc_reply_state[] = {
77 { MSG_ACCEPTED, "accepted" },
78 { MSG_DENIED, "denied" },
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" },
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" },
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" },
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" },
115 static const value_string rpc_reject_state[] = {
116 { RPC_MISMATCH, "RPC_MISMATCH" },
117 { AUTH_ERROR, "AUTH_ERROR" },
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" },
132 static const value_string rpc_authdes_namekind[] = {
133 { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
134 { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
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;
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;
196 /* Hash table with info on RPC program numbers */
197 static GHashTable *rpc_progs;
199 /* Hash table with info on RPC procedure numbers */
200 static GHashTable *rpc_procs;
202 typedef struct _rpc_proc_info_key {
208 typedef struct _rpc_proc_info_value {
210 dissect_function_t *dissect_call;
211 dissect_function_t *dissect_reply;
212 } rpc_proc_info_value;
214 typedef struct _rpc_prog_info_key {
218 typedef struct _rpc_prog_info_value {
222 } rpc_prog_info_value;
224 static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
225 static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
227 /***********************************/
228 /* Hash array with procedure names */
229 /***********************************/
233 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
235 rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
236 rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
238 return ((key1->prog == key2->prog &&
239 key1->vers == key2->vers &&
240 key1->proc == key2->proc) ?
244 /* calculate a hash key */
246 rpc_proc_hash(gconstpointer k)
248 rpc_proc_info_key* key = (rpc_proc_info_key*) k;
250 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
254 /* insert some entries */
256 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
260 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
261 rpc_proc_info_key *key;
262 rpc_proc_info_value *value;
264 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
267 key->proc = proc->value;
269 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
270 value->name = proc->strptr;
271 value->dissect_call = proc->dissect_call;
272 value->dissect_reply = proc->dissect_reply;
274 g_hash_table_insert(rpc_procs,key,value);
278 /* return the name associated with a previously registered procedure. */
279 char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
281 rpc_proc_info_key key;
282 rpc_proc_info_value *value;
284 static char procname_static[20];
290 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
291 procname = value->name;
293 /* happens only with strange program versions or
294 non-existing dissectors */
295 sprintf(procname_static, "proc-%u", key.proc);
296 procname = procname_static;
301 /*----------------------------------------*/
302 /* end of Hash array with procedure names */
303 /*----------------------------------------*/
306 /*********************************/
307 /* Hash array with program names */
308 /*********************************/
312 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
314 rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
315 rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
317 return ((key1->prog == key2->prog) ?
322 /* calculate a hash key */
324 rpc_prog_hash(gconstpointer k)
326 rpc_prog_info_key* key = (rpc_prog_info_key*) k;
333 rpc_init_prog(int proto, guint32 prog, int ett)
335 rpc_prog_info_key *key;
336 rpc_prog_info_value *value;
338 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
341 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
342 value->proto = proto;
344 value->progname = proto_get_protocol_short_name(proto);
346 g_hash_table_insert(rpc_progs,key,value);
349 /* return the name associated with a previously registered program. This
350 should probably eventually be expanded to use the rpc YP/NIS map
351 so that it can give names for programs not handled by ethereal */
352 char *rpc_prog_name(guint32 prog)
354 char *progname = NULL;
355 rpc_prog_info_key rpc_prog_key;
356 rpc_prog_info_value *rpc_prog;
358 rpc_prog_key.prog = prog;
359 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
360 progname = "Unknown";
363 progname = rpc_prog->progname;
369 /*--------------------------------------*/
370 /* end of Hash array with program names */
371 /*--------------------------------------*/
373 typedef struct _rpc_call_info_key {
375 conversation_t *conversation;
378 static GMemChunk *rpc_call_info_key_chunk;
381 FLAVOR_UNKNOWN, /* authentication flavor unknown */
382 FLAVOR_NOT_GSSAPI, /* flavor isn't GSSAPI */
383 FLAVOR_GSSAPI_NO_INFO, /* flavor is GSSAPI, procedure & service unknown */
384 FLAVOR_GSSAPI /* flavor is GSSAPI, procedure & service known */
387 typedef struct _rpc_call_info_value {
388 guint32 req_num; /* frame number of first request seen */
389 guint32 rep_num; /* frame number of first reply seen */
396 rpc_proc_info_value* proc_info;
397 } rpc_call_info_value;
399 static GMemChunk *rpc_call_info_value_chunk;
401 static GHashTable *rpc_calls;
403 static GHashTable *rpc_indir_calls;
407 rpc_call_equal(gconstpointer k1, gconstpointer k2)
409 rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
410 rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
412 return (key1->xid == key2->xid &&
413 key1->conversation == key2->conversation);
417 /* calculate a hash key */
419 rpc_call_hash(gconstpointer k)
421 rpc_call_info_key* key = (rpc_call_info_key*) k;
423 return key->xid + (guint32)(key->conversation);
428 rpc_roundup(unsigned int a)
430 unsigned int mod = a % 4;
431 return a + ((mod)? 4-mod : 0);
436 dissect_rpc_bool(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
437 int hfindex, int offset)
440 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
446 dissect_rpc_uint32(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
447 int hfindex, int offset)
450 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
456 dissect_rpc_uint64(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
457 int hfindex, int offset)
459 header_field_info *hfinfo;
461 hfinfo = proto_registrar_get_nth(hfindex);
462 g_assert(hfinfo->type == FT_UINT64);
464 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
471 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
472 proto_tree *tree, int hfindex, gboolean string_data,
473 char **string_buffer_ret)
475 proto_item *string_item = NULL;
476 proto_tree *string_tree = NULL;
477 int old_offset = offset;
479 int length_truncated = 0;
481 int string_truncated = 0;
482 guint32 string_length = 0;
483 guint32 string_length_full;
484 guint32 string_length_packet;
485 guint32 string_length_copy = 0;
487 int fill_truncated = 0;
488 guint32 fill_length = 0;
489 guint32 fill_length_packet = 0;
490 guint32 fill_length_copy = 0;
492 char *string_buffer = NULL;
493 char *string_buffer_print = NULL;
495 string_length = tvb_get_ntohl(tvb,offset+0);
496 string_length_full = rpc_roundup(string_length);
497 /* XXX - just let the tvbuff stuff throw an exception? */
498 string_length_packet = tvb_length_remaining(tvb, offset + 4);
499 if (string_length_packet < string_length) {
500 /* truncated string */
501 string_truncated = 1;
502 string_length_copy = string_length_packet;
505 fill_length_packet = 0;
506 fill_length_copy = 0;
509 /* full string data */
510 string_truncated = 0;
511 string_length_copy = string_length;
512 fill_length = string_length_full - string_length;
513 /* XXX - just let the tvbuff stuff throw an exception? */
514 fill_length_packet = tvb_length_remaining(tvb,
515 offset + 4 + string_length);
516 if (fill_length_packet < fill_length) {
517 /* truncated fill bytes */
518 fill_length_copy = fill_length_packet;
522 /* full fill bytes */
523 fill_length_copy = fill_length;
527 string_buffer = (char*)g_malloc(string_length_copy +
528 (string_data ? 1 : 0));
529 tvb_memcpy(tvb,string_buffer,offset+4,string_length_copy);
531 string_buffer[string_length_copy] = '\0';
533 /* calculate a nice printable string */
535 if (string_length != string_length_copy) {
537 /* alloc maximum data area */
538 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
539 /* copy over the data */
540 memcpy(string_buffer_print,string_buffer,string_length_copy);
541 /* append a 0 byte for sure printing */
542 string_buffer_print[string_length_copy] = '\0';
543 /* append <TRUNCATED> */
544 /* This way, we get the TRUNCATED even
545 in the case of totally wrong packets,
546 where \0 are inside the string.
547 TRUNCATED will appear at the
548 first \0 or at the end (where we
549 put the securing \0).
551 strcat(string_buffer_print,"<TRUNCATED>");
554 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
559 string_buffer_print = g_strdup(string_buffer);
562 string_buffer_print = g_strdup("<DATA>");
567 string_buffer_print = g_strdup("<EMPTY>");
571 string_item = proto_tree_add_text(tree, tvb,offset+0, tvb_length_remaining(tvb, offset),
572 "%s: %s", proto_registrar_get_name(hfindex), string_buffer_print);
574 proto_tree_add_string_hidden(tree, hfindex, tvb, offset+4,
575 string_length_copy, string_buffer);
578 string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
581 if (length_truncated) {
583 proto_tree_add_text(string_tree, tvb,
584 offset, tvb_length_remaining(tvb, offset),
585 "length: <TRUNCATED>");
586 offset = tvb_length(tvb);
589 proto_tree_add_text(string_tree, tvb,offset+0,4,
590 "length: %u", string_length);
595 proto_tree_add_string_format(string_tree,
596 hfindex, tvb, offset, string_length_copy,
598 "contents: %s", string_buffer_print);
600 proto_tree_add_bytes_format(string_tree,
601 hfindex, tvb, offset, string_length_copy,
603 "contents: %s", string_buffer_print);
606 offset += string_length_copy;
609 if (fill_truncated) {
610 proto_tree_add_text(string_tree, tvb,
611 offset,fill_length_copy,
612 "fill bytes: opaque data<TRUNCATED>");
615 proto_tree_add_text(string_tree, tvb,
616 offset,fill_length_copy,
617 "fill bytes: opaque data");
620 offset += fill_length_copy;
625 proto_item_set_len(string_item, offset - old_offset);
628 if (string_buffer != NULL) g_free (string_buffer );
629 if (string_buffer_print != NULL) {
630 if (string_buffer_ret != NULL)
631 *string_buffer_ret = string_buffer_print;
633 g_free (string_buffer_print);
640 dissect_rpc_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
641 int hfindex, int offset, char **string_buffer_ret)
643 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree,
644 hfindex, TRUE, string_buffer_ret);
650 dissect_rpc_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
651 int hfindex, int offset)
653 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree, hfindex,
661 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
662 int offset, dissect_function_t *rpc_list_dissector)
664 guint32 value_follows;
667 value_follows = tvb_get_ntohl(tvb, offset+0);
668 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
669 offset+0, 4, value_follows);
671 if (value_follows == 1) {
672 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
683 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
684 int offset, dissect_function_t *rpc_array_dissector,
687 proto_item* lock_item;
688 proto_tree* lock_tree;
690 int old_offset = offset;
692 num = tvb_get_ntohl(tvb, offset);
695 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
702 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset,
705 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
707 offset = dissect_rpc_uint32(tvb, pinfo, lock_tree,
708 hf_rpc_array_len, offset);
711 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
714 proto_item_set_len(lock_item, offset-old_offset);
719 dissect_rpc_authunix_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
728 proto_tree *gtree = NULL;
730 stamp = tvb_get_ntohl(tvb,offset+0);
732 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
736 offset = dissect_rpc_string(tvb, pinfo, tree,
737 hf_rpc_auth_machinename, offset, NULL);
739 uid = tvb_get_ntohl(tvb,offset+0);
741 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
745 gid = tvb_get_ntohl(tvb,offset+0);
747 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
751 gids_count = tvb_get_ntohl(tvb,offset+0);
753 gitem = proto_tree_add_text(tree, tvb,
754 offset, 4+gids_count*4, "Auxiliary GIDs");
755 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
759 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
760 gids_entry = tvb_get_ntohl(tvb,offset+0);
762 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
763 offset, 4, gids_entry);
766 /* how can I NOW change the gitem to print a list with
767 the first 16 gids? */
773 dissect_rpc_authgss_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
780 agc_v = tvb_get_ntohl(tvb, offset+0);
782 proto_tree_add_uint(tree, hf_rpc_authgss_v,
783 tvb, offset+0, 4, agc_v);
786 agc_proc = tvb_get_ntohl(tvb, offset+0);
788 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
789 tvb, offset+0, 4, agc_proc);
792 agc_seq = tvb_get_ntohl(tvb, offset+0);
794 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
795 tvb, offset+0, 4, agc_seq);
798 agc_svc = tvb_get_ntohl(tvb, offset+0);
800 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
801 tvb, offset+0, 4, agc_svc);
804 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
811 dissect_rpc_authdes_desblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
812 int hfindex, int offset)
817 value_high = tvb_get_ntohl(tvb, offset + 0);
818 value_low = tvb_get_ntohl(tvb, offset + 4);
821 proto_tree_add_text(tree, tvb, offset, 8,
822 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
830 dissect_rpc_authdes_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
836 adc_namekind = tvb_get_ntohl(tvb, offset+0);
838 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
839 tvb, offset+0, 4, adc_namekind);
844 case AUTHDES_NAMEKIND_FULLNAME:
845 offset = dissect_rpc_string(tvb, pinfo, tree,
846 hf_rpc_authdes_netname, offset, NULL);
847 offset = dissect_rpc_authdes_desblock(tvb, pinfo, tree,
848 hf_rpc_authdes_convkey, offset);
849 window = tvb_get_ntohl(tvb, offset+0);
850 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
855 case AUTHDES_NAMEKIND_NICKNAME:
856 nickname = tvb_get_ntohl(tvb, offset+0);
857 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
867 dissect_rpc_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
875 flavor = tvb_get_ntohl(tvb,offset+0);
876 length = tvb_get_ntohl(tvb,offset+4);
877 length = rpc_roundup(length);
880 citem = proto_tree_add_text(tree, tvb, offset,
881 8+length, "Credentials");
882 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
883 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
884 offset+0, 4, flavor);
885 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
886 offset+4, 4, length);
890 dissect_rpc_authunix_cred(tvb, pinfo, ctree, offset+8);
898 dissect_rpc_authdes_cred(tvb, pinfo, ctree, offset+8);
902 dissect_rpc_authgss_cred(tvb, pinfo, ctree, offset+8);
906 proto_tree_add_text(ctree, tvb, offset+8,
907 length,"opaque data");
911 offset += 8 + length;
916 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
917 * verifier we're decoding (CALL or REPLY).
920 dissect_rpc_verf(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset, int msg_type)
928 flavor = tvb_get_ntohl(tvb,offset+0);
929 length = tvb_get_ntohl(tvb,offset+4);
930 length = rpc_roundup(length);
933 vitem = proto_tree_add_text(tree, tvb, offset,
934 8+length, "Verifier");
935 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
936 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
937 offset+0, 4, flavor);
941 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
942 offset+4, 4, length);
943 dissect_rpc_authunix_cred(tvb, pinfo, vtree, offset+8);
946 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
947 offset+4, 4, length);
949 if (msg_type == RPC_CALL)
953 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
954 hf_rpc_authdes_timestamp, offset+8);
955 window = tvb_get_ntohl(tvb, offset+16);
956 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
957 offset+16, 4, window);
961 /* must be an RPC_REPLY */
964 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
965 hf_rpc_authdes_timeverf, offset+8);
966 nickname = tvb_get_ntohl(tvb, offset+16);
967 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
968 offset+16, 4, nickname);
972 dissect_rpc_data(tvb, pinfo, vtree,
973 hf_rpc_authgss_checksum, offset+4);
976 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
977 offset+4, 4, length);
979 proto_tree_add_text(vtree, tvb, offset+8,
980 length, "opaque data");
984 offset += 8 + length;
990 dissect_rpc_authgss_initarg(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
992 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
998 dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
1000 int major, minor, window;
1002 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
1005 major = tvb_get_ntohl(tvb,offset+0);
1007 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1008 offset+0, 4, major);
1011 minor = tvb_get_ntohl(tvb,offset+0);
1013 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1014 offset+0, 4, minor);
1017 window = tvb_get_ntohl(tvb,offset+0);
1019 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1020 offset+0, 4, window);
1023 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1031 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1032 int offset, dissect_function_t* dissect_function, const char *progname)
1034 const char *saved_proto;
1036 if (dissect_function != NULL) {
1037 /* set the current protocol name */
1038 saved_proto = pinfo->current_proto;
1039 if (progname != NULL)
1040 pinfo->current_proto = progname;
1042 /* call the dissector for the next level */
1043 offset = dissect_function(tvb, offset, pinfo, tree);
1045 /* restore the protocol name */
1046 pinfo->current_proto = saved_proto;
1054 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1055 proto_tree *tree, int offset,
1056 dissect_function_t* dissect_function,
1057 const char *progname)
1059 guint32 length, seq;
1062 proto_tree *gtree = NULL;
1064 length = tvb_get_ntohl(tvb, offset+0);
1065 length = rpc_roundup(length);
1066 seq = tvb_get_ntohl(tvb, offset+4);
1069 gitem = proto_tree_add_text(tree, tvb, offset,
1070 4+length, "GSS Data");
1071 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1072 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1073 tvb, offset+0, 4, length);
1074 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1075 tvb, offset+4, 4, seq);
1079 if (dissect_function != NULL) {
1081 call_dissect_function(tvb, pinfo, gtree, offset,
1082 dissect_function, progname);
1084 offset += length - 4;
1085 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_checksum,
1092 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1094 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_data,
1100 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1103 * Record this call in a hash table, similar to the hash table for
1104 * direct calls, so we can find it when dissecting an indirect call reply.
1107 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1108 int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1110 conversation_t* conversation;
1111 static address null_address = { AT_NONE, 0, NULL };
1112 rpc_proc_info_key key;
1113 rpc_proc_info_value *value;
1114 rpc_call_info_value *rpc_call;
1115 rpc_call_info_key rpc_call_key;
1116 rpc_call_info_key *new_rpc_call_key;
1117 dissect_function_t *dissect_function = NULL;
1122 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1123 dissect_function = value->dissect_call;
1125 /* Keep track of the address and port whence the call came,
1126 and the port to which the call is being sent, so that
1127 we can match up calls with replies.
1129 If the transport is connection-oriented (we check, for
1130 now, only for "pinfo->ptype" of PT_TCP), we take
1131 into account the address from which the call was sent
1132 and the address to which the call was sent, because
1133 the addresses of the two endpoints should be the same
1134 for all calls and replies.
1136 If the transport is connectionless, we don't worry
1137 about the address to which the call was sent and from
1138 which the reply was sent, because there's no
1139 guarantee that the reply will come from the address
1140 to which the call was sent. */
1141 if (pinfo->ptype == PT_TCP) {
1142 conversation = find_conversation(&pinfo->src,
1143 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1144 pinfo->destport, 0);
1147 * XXX - can we just use NO_ADDR_B? Unfortunately,
1148 * you currently still have to pass a non-null
1149 * pointer for the second address argument even
1152 conversation = find_conversation(&pinfo->src,
1153 &null_address, pinfo->ptype, pinfo->srcport,
1154 pinfo->destport, 0);
1156 if (conversation == NULL) {
1157 /* It's not part of any conversation - create a new
1160 XXX - this should never happen, as we should've
1161 created a conversation for it in the RPC
1163 if (pinfo->ptype == PT_TCP) {
1164 conversation = conversation_new(&pinfo->src,
1165 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1166 pinfo->destport, 0);
1168 conversation = conversation_new(&pinfo->src,
1169 &null_address, pinfo->ptype, pinfo->srcport,
1170 pinfo->destport, 0);
1174 /* Make the dissector for this conversation the non-heuristic
1176 conversation_set_dissector(conversation,
1177 (pinfo->ptype == PT_TCP) ? dissect_rpc_tcp : dissect_rpc);
1179 /* Prepare the key data.
1181 Dissectors for RPC procedure calls and replies shouldn't
1182 create new tvbuffs, and we don't create one ourselves,
1183 so we should have been handed the tvbuff for this RPC call;
1184 as such, the XID is at offset 0 in this tvbuff. */
1185 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1186 rpc_call_key.conversation = conversation;
1188 /* look up the request */
1189 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1190 if (rpc_call == NULL) {
1191 /* We didn't find it; create a new entry.
1192 Prepare the value data.
1193 Not all of it is needed for handling indirect
1194 calls, so we set a bunch of items to 0. */
1195 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1196 *new_rpc_call_key = rpc_call_key;
1197 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1198 rpc_call->req_num = 0;
1199 rpc_call->rep_num = 0;
1200 rpc_call->prog = prog;
1201 rpc_call->vers = vers;
1202 rpc_call->proc = proc;
1205 * XXX - what about RPCSEC_GSS?
1206 * Do we have to worry about it?
1208 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1209 rpc_call->gss_proc = 0;
1210 rpc_call->gss_svc = 0;
1211 rpc_call->proc_info = value;
1213 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1218 /* We don't know the procedure.
1219 Happens only with strange program versions or
1220 non-existing dissectors.
1221 Just show the arguments as opaque data. */
1222 offset = dissect_rpc_data(tvb, pinfo, tree, args_id,
1229 proto_tree_add_text(tree, tvb, offset, 4,
1230 "Argument length: %u",
1231 tvb_get_ntohl(tvb, offset));
1235 /* Dissect the arguments */
1236 offset = call_dissect_function(tvb, pinfo, tree, offset,
1237 dissect_function, NULL);
1242 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1246 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1247 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1249 conversation_t* conversation;
1250 static address null_address = { AT_NONE, 0, NULL };
1251 rpc_call_info_key rpc_call_key;
1252 rpc_call_info_value *rpc_call;
1253 char *procname = NULL;
1254 char procname_static[20];
1255 dissect_function_t *dissect_function = NULL;
1257 /* Look for the matching call in the hash table of indirect
1258 calls. A reply must match a call that we've seen, and the
1259 reply must be sent to the same port and address that the
1260 call came from, and must come from the port to which the
1263 If the transport is connection-oriented (we check, for
1264 now, only for "pinfo->ptype" of PT_TCP), we take
1265 into account the address from which the call was sent
1266 and the address to which the call was sent, because
1267 the addresses of the two endpoints should be the same
1268 for all calls and replies.
1270 If the transport is connectionless, we don't worry
1271 about the address to which the call was sent and from
1272 which the reply was sent, because there's no
1273 guarantee that the reply will come from the address
1274 to which the call was sent. */
1275 if (pinfo->ptype == PT_TCP) {
1276 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1277 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1280 * XXX - can we just use NO_ADDR_B? Unfortunately,
1281 * you currently still have to pass a non-null
1282 * pointer for the second address argument even
1285 conversation = find_conversation(&null_address, &pinfo->dst,
1286 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1288 if (conversation == NULL) {
1289 /* We haven't seen an RPC call for that conversation,
1290 so we can't check for a reply to that call.
1291 Just show the reply stuff as opaque data. */
1292 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1297 /* The XIDs of the call and reply must match. */
1298 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1299 rpc_call_key.conversation = conversation;
1300 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1301 if (rpc_call == NULL) {
1302 /* The XID doesn't match a call from that
1303 conversation, so it's probably not an RPC reply.
1304 Just show the reply stuff as opaque data. */
1305 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1310 if (rpc_call->proc_info != NULL) {
1311 dissect_function = rpc_call->proc_info->dissect_reply;
1312 if (rpc_call->proc_info->name != NULL) {
1313 procname = rpc_call->proc_info->name;
1316 sprintf(procname_static, "proc-%u", rpc_call->proc);
1317 procname = procname_static;
1322 dissect_function = NULL;
1324 sprintf(procname_static, "proc-%u", rpc_call->proc);
1325 procname = procname_static;
1330 /* Put the program, version, and procedure into the tree. */
1331 proto_tree_add_uint_format(tree, prog_id, tvb,
1332 0, 0, rpc_call->prog, "Program: %s (%u)",
1333 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1334 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1335 proto_tree_add_uint_format(tree, proc_id, tvb,
1336 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1337 procname, rpc_call->proc);
1340 if (dissect_function == NULL) {
1341 /* We don't know how to dissect the reply procedure.
1342 Just show the reply stuff as opaque data. */
1343 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1349 /* Put the length of the reply value into the tree. */
1350 proto_tree_add_text(tree, tvb, offset, 4,
1351 "Argument length: %u",
1352 tvb_get_ntohl(tvb, offset));
1356 /* Dissect the return value */
1357 offset = call_dissect_function(tvb, pinfo, tree, offset,
1358 dissect_function, NULL);
1363 * Just mark this as a continuation of an earlier packet.
1366 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1368 proto_item *rpc_item;
1369 proto_tree *rpc_tree;
1371 if (check_col(pinfo->fd, COL_PROTOCOL))
1372 col_set_str(pinfo->fd, COL_PROTOCOL, "RPC");
1373 if (check_col(pinfo->fd, COL_INFO))
1374 col_set_str(pinfo->fd, COL_INFO, "Continuation");
1377 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1378 tvb_length(tvb), FALSE);
1379 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1380 proto_tree_add_text(rpc_tree, tvb, 0, tvb_length(tvb),
1381 "Continuation data");
1386 dissect_rpc_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1387 proto_tree *tree, gboolean use_rm, guint32 rpc_rm)
1390 rpc_call_info_key rpc_call_key;
1391 rpc_call_info_value *rpc_call = NULL;
1392 rpc_prog_info_value *rpc_prog = NULL;
1393 rpc_prog_info_key rpc_prog_key;
1396 unsigned int rpcvers;
1397 unsigned int prog = 0;
1398 unsigned int vers = 0;
1399 unsigned int proc = 0;
1400 flavor_t flavor = FLAVOR_UNKNOWN;
1401 unsigned int gss_proc = 0;
1402 unsigned int gss_svc = 0;
1406 unsigned int reply_state;
1407 unsigned int accept_state;
1408 unsigned int reject_state;
1410 char *msg_type_name = NULL;
1411 char *progname = NULL;
1412 char *procname = NULL;
1413 static char procname_static[20];
1415 unsigned int vers_low;
1416 unsigned int vers_high;
1418 unsigned int auth_state;
1420 proto_item *rpc_item=NULL;
1421 proto_tree *rpc_tree = NULL;
1423 proto_item *pitem=NULL;
1424 proto_tree *ptree = NULL;
1425 int offset_old = offset;
1427 rpc_call_info_key *new_rpc_call_key;
1428 rpc_proc_info_key key;
1429 rpc_proc_info_value *value = NULL;
1430 conversation_t* conversation;
1431 static address null_address = { AT_NONE, 0, NULL };
1433 dissect_function_t *dissect_function = NULL;
1436 * Check to see whether this looks like an RPC call or reply.
1438 if (!tvb_bytes_exist(tvb, offset, 8)) {
1439 /* Captured data in packet isn't enough to let us tell. */
1443 /* both directions need at least this */
1444 msg_type = tvb_get_ntohl(tvb, offset + 4);
1449 /* check for RPC call */
1450 if (!tvb_bytes_exist(tvb, offset, 16)) {
1451 /* Captured data in packet isn't enough to let us
1456 /* XID can be anything, we don't check it.
1457 We already have the message type.
1458 Check whether an RPC version number of 2 is in the
1459 location where it would be, and that an RPC program
1460 number we know about is in the locaton where it would be. */
1461 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1462 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1463 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1465 /* They're not, so it's probably not an RPC call. */
1471 /* Check for RPC reply. A reply must match a call that
1472 we've seen, and the reply must be sent to the same
1473 port and address that the call came from, and must
1474 come from the port to which the call was sent.
1476 If the transport is connection-oriented (we check, for
1477 now, only for "pinfo->ptype" of PT_TCP), we take
1478 into account the address from which the call was sent
1479 and the address to which the call was sent, because
1480 the addresses of the two endpoints should be the same
1481 for all calls and replies.
1483 If the transport is connectionless, we don't worry
1484 about the address to which the call was sent and from
1485 which the reply was sent, because there's no
1486 guarantee that the reply will come from the address
1487 to which the call was sent. */
1488 if (pinfo->ptype == PT_TCP) {
1489 conversation = find_conversation(&pinfo->src,
1490 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1491 pinfo->destport, 0);
1494 * XXX - can we just use NO_ADDR_B? Unfortunately,
1495 * you currently still have to pass a non-null
1496 * pointer for the second address argument even
1499 conversation = find_conversation(&null_address,
1500 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1501 pinfo->destport, 0);
1503 if (conversation == NULL) {
1504 /* We haven't seen an RPC call for that conversation,
1505 so we can't check for a reply to that call. */
1509 /* The XIDs of the call and reply must match. */
1510 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1511 rpc_call_key.conversation = conversation;
1512 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1513 if (rpc_call == NULL) {
1514 /* The XID doesn't match a call from that
1515 conversation, so it's probably not an RPC reply. */
1521 /* The putative message type field contains neither
1522 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1527 if (check_col(pinfo->fd, COL_PROTOCOL))
1528 col_set_str(pinfo->fd, COL_PROTOCOL, "RPC");
1529 if (check_col(pinfo->fd, COL_INFO))
1530 col_clear(pinfo->fd, COL_INFO);
1533 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1534 tvb_length(tvb), FALSE);
1536 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1540 if (use_rm && rpc_tree) {
1541 proto_tree_add_boolean(rpc_tree,hf_rpc_lastfrag, tvb,
1542 offset-4, 4, (rpc_rm >> 31) & 0x1);
1543 proto_tree_add_uint(rpc_tree,hf_rpc_fraglen, tvb,
1544 offset-4, 4, rpc_rm & RPC_RM_FRAGLEN);
1547 xid = tvb_get_ntohl(tvb, offset + 0);
1549 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1550 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1553 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1555 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1556 offset+4, 4, msg_type);
1564 /* we know already the proto-entry, the ETT-const,
1566 proto = rpc_prog->proto;
1567 ett = rpc_prog->ett;
1568 progname = rpc_prog->progname;
1570 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1572 proto_tree_add_uint(rpc_tree,
1573 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1576 prog = tvb_get_ntohl(tvb, offset + 4);
1579 proto_tree_add_uint_format(rpc_tree,
1580 hf_rpc_program, tvb, offset+4, 4, prog,
1581 "Program: %s (%u)", progname, prog);
1584 if (check_col(pinfo->fd, COL_PROTOCOL)) {
1585 /* Set the protocol name to the underlying
1587 col_set_str(pinfo->fd, COL_PROTOCOL, progname);
1590 vers = tvb_get_ntohl(tvb, offset+8);
1592 proto_tree_add_uint(rpc_tree,
1593 hf_rpc_programversion, tvb, offset+8, 4, vers);
1596 proc = tvb_get_ntohl(tvb, offset+12);
1602 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1603 dissect_function = value->dissect_call;
1604 procname = value->name;
1607 /* happens only with strange program versions or
1608 non-existing dissectors */
1610 dissect_function = NULL;
1612 sprintf(procname_static, "proc-%u", proc);
1613 procname = procname_static;
1617 proto_tree_add_uint_format(rpc_tree,
1618 hf_rpc_procedure, tvb, offset+12, 4, proc,
1619 "Procedure: %s (%u)", procname, proc);
1622 if (check_col(pinfo->fd, COL_INFO)) {
1623 col_add_fstr(pinfo->fd, COL_INFO,"V%u %s %s XID 0x%x",
1630 /* Check for RPCSEC_GSS */
1631 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1632 switch (tvb_get_ntohl(tvb, offset+16)) {
1636 * It's GSS-API authentication...
1638 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1640 * ...and we have the procedure
1641 * and service information for it.
1643 flavor = FLAVOR_GSSAPI;
1644 gss_proc = tvb_get_ntohl(tvb, offset+28);
1645 gss_svc = tvb_get_ntohl(tvb, offset+36);
1648 * ...but the procedure and service
1649 * information isn't available.
1651 flavor = FLAVOR_GSSAPI_NO_INFO;
1657 * It's not GSS-API authentication.
1659 flavor = FLAVOR_NOT_GSSAPI;
1664 /* Keep track of the address and port whence the call came,
1665 and the port to which the call is being sent, so that
1666 we can match up calls with replies.
1668 If the transport is connection-oriented (we check, for
1669 now, only for "pinfo->ptype" of PT_TCP), we take
1670 into account the address from which the call was sent
1671 and the address to which the call was sent, because
1672 the addresses of the two endpoints should be the same
1673 for all calls and replies.
1675 If the transport is connectionless, we don't worry
1676 about the address to which the call was sent and from
1677 which the reply was sent, because there's no
1678 guarantee that the reply will come from the address
1679 to which the call was sent. */
1680 if (pinfo->ptype == PT_TCP) {
1681 conversation = find_conversation(&pinfo->src,
1682 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1683 pinfo->destport, 0);
1686 * XXX - can we just use NO_ADDR_B? Unfortunately,
1687 * you currently still have to pass a non-null
1688 * pointer for the second address argument even
1691 conversation = find_conversation(&pinfo->src,
1692 &null_address, pinfo->ptype, pinfo->srcport,
1693 pinfo->destport, 0);
1695 if (conversation == NULL) {
1696 /* It's not part of any conversation - create a new
1698 if (pinfo->ptype == PT_TCP) {
1699 conversation = conversation_new(&pinfo->src,
1700 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1701 pinfo->destport, 0);
1703 conversation = conversation_new(&pinfo->src,
1704 &null_address, pinfo->ptype, pinfo->srcport,
1705 pinfo->destport, 0);
1709 /* Make the dissector for this conversation the non-heuristic
1711 conversation_set_dissector(conversation,
1712 (pinfo->ptype == PT_TCP) ? dissect_rpc_tcp : dissect_rpc);
1714 /* prepare the key data */
1715 rpc_call_key.xid = xid;
1716 rpc_call_key.conversation = conversation;
1718 /* look up the request */
1719 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1720 if (rpc_call != NULL) {
1721 /* We've seen a request with this XID, with the same
1722 source and destination, before - but was it
1724 if (pinfo->fd->num != rpc_call->req_num) {
1725 /* No, so it's a duplicate request.
1727 if (check_col(pinfo->fd, COL_INFO)) {
1728 col_append_fstr(pinfo->fd, COL_INFO,
1729 " dup XID 0x%x", xid);
1731 proto_tree_add_uint_hidden(rpc_tree,
1732 hf_rpc_dup, tvb, 0,0, xid);
1733 proto_tree_add_uint_hidden(rpc_tree,
1734 hf_rpc_call_dup, tvb, 0,0, xid);
1740 /* Prepare the value data.
1741 "req_num" and "rep_num" are frame numbers;
1742 frame numbers are 1-origin, so we use 0
1743 to mean "we don't yet know in which frame
1744 the reply for this call appears". */
1745 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1746 *new_rpc_call_key = rpc_call_key;
1747 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1748 rpc_call->req_num = pinfo->fd->num;
1749 rpc_call->rep_num = 0;
1750 rpc_call->prog = prog;
1751 rpc_call->vers = vers;
1752 rpc_call->proc = proc;
1753 rpc_call->flavor = flavor;
1754 rpc_call->gss_proc = gss_proc;
1755 rpc_call->gss_svc = gss_svc;
1756 rpc_call->proc_info = value;
1758 g_hash_table_insert(rpc_calls, new_rpc_call_key,
1764 offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset);
1765 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1767 /* go to the next dissector */
1769 break; /* end of RPC call */
1772 /* we know already the type from the calling routine,
1773 and we already have "rpc_call" set above. */
1774 prog = rpc_call->prog;
1775 vers = rpc_call->vers;
1776 proc = rpc_call->proc;
1777 flavor = rpc_call->flavor;
1778 gss_proc = rpc_call->gss_proc;
1779 gss_svc = rpc_call->gss_svc;
1781 /* Indicate the frame to which this is a reply. */
1782 proto_tree_add_text(rpc_tree, tvb, 0, 0,
1783 "This is a reply to a request in frame %u",
1786 if (rpc_call->proc_info != NULL) {
1787 dissect_function = rpc_call->proc_info->dissect_reply;
1788 if (rpc_call->proc_info->name != NULL) {
1789 procname = rpc_call->proc_info->name;
1792 sprintf(procname_static, "proc-%u", proc);
1793 procname = procname_static;
1798 dissect_function = NULL;
1800 sprintf(procname_static, "proc-%u", proc);
1801 procname = procname_static;
1804 rpc_prog_key.prog = prog;
1805 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1808 progname = "Unknown";
1811 proto = rpc_prog->proto;
1812 ett = rpc_prog->ett;
1813 progname = rpc_prog->progname;
1815 if (check_col(pinfo->fd, COL_PROTOCOL)) {
1816 /* Set the protocol name to the underlying
1818 col_set_str(pinfo->fd, COL_PROTOCOL, progname);
1822 if (check_col(pinfo->fd, COL_INFO)) {
1823 col_add_fstr(pinfo->fd, COL_INFO,"V%u %s %s XID 0x%x",
1831 proto_tree_add_uint_format(rpc_tree,
1832 hf_rpc_program, tvb, 0, 0, prog,
1833 "Program: %s (%u)", progname, prog);
1834 proto_tree_add_uint(rpc_tree,
1835 hf_rpc_programversion, tvb, 0, 0, vers);
1836 proto_tree_add_uint_format(rpc_tree,
1837 hf_rpc_procedure, tvb, 0, 0, proc,
1838 "Procedure: %s (%u)", procname, proc);
1841 if (rpc_call->rep_num == 0) {
1842 /* We have not yet seen a reply to that call, so
1843 this must be the first reply; remember its
1845 rpc_call->rep_num = pinfo->fd->num;
1847 /* We have seen a reply to this call - but was it
1849 if (rpc_call->rep_num != pinfo->fd->num) {
1850 /* No, so it's a duplicate reply.
1852 if (check_col(pinfo->fd, COL_INFO)) {
1853 col_append_fstr(pinfo->fd, COL_INFO,
1854 " dup XID 0x%x", xid);
1856 proto_tree_add_uint_hidden(rpc_tree,
1857 hf_rpc_dup, tvb, 0,0, xid);
1858 proto_tree_add_uint_hidden(rpc_tree,
1859 hf_rpc_reply_dup, tvb, 0,0, xid);
1865 reply_state = tvb_get_ntohl(tvb,offset+0);
1867 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
1868 offset+0, 4, reply_state);
1872 if (reply_state == MSG_ACCEPTED) {
1873 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1874 accept_state = tvb_get_ntohl(tvb,offset+0);
1876 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
1877 offset+0, 4, accept_state);
1880 switch (accept_state) {
1883 /* go to the next dissector */
1887 vers_low = tvb_get_ntohl(tvb,offset+0);
1888 vers_high = tvb_get_ntohl(tvb,offset+4);
1890 proto_tree_add_uint(rpc_tree,
1891 hf_rpc_programversion_min,
1892 tvb, offset+0, 4, vers_low);
1893 proto_tree_add_uint(rpc_tree,
1894 hf_rpc_programversion_max,
1895 tvb, offset+4, 4, vers_high);
1904 } else if (reply_state == MSG_DENIED) {
1905 reject_state = tvb_get_ntohl(tvb,offset+0);
1907 proto_tree_add_uint(rpc_tree,
1908 hf_rpc_state_reject, tvb, offset+0, 4,
1913 if (reject_state==RPC_MISMATCH) {
1914 vers_low = tvb_get_ntohl(tvb,offset+0);
1915 vers_high = tvb_get_ntohl(tvb,offset+4);
1917 proto_tree_add_uint(rpc_tree,
1919 tvb, offset+0, 4, vers_low);
1920 proto_tree_add_uint(rpc_tree,
1922 tvb, offset+4, 4, vers_high);
1925 } else if (reject_state==AUTH_ERROR) {
1926 auth_state = tvb_get_ntohl(tvb,offset+0);
1928 proto_tree_add_uint(rpc_tree,
1929 hf_rpc_state_auth, tvb, offset+0, 4,
1935 break; /* end of RPC reply */
1939 * The switch statement at the top returned if
1940 * this was neither an RPC call nor a reply.
1942 g_assert_not_reached();
1945 /* now we know, that RPC was shorter */
1947 proto_item_set_len(rpc_item, offset - offset_old);
1950 /* create here the program specific sub-tree */
1952 pitem = proto_tree_add_item(tree, proto, tvb,
1953 offset, tvb_length(tvb) - offset, FALSE);
1955 ptree = proto_item_add_subtree(pitem, ett);
1959 proto_tree_add_uint(ptree,
1960 hf_rpc_programversion, tvb, 0, 0, vers);
1961 proto_tree_add_uint_format(ptree,
1962 hf_rpc_procedure, tvb, 0, 0, proc,
1963 "Procedure: %s (%u)", procname, proc);
1967 if (!proto_is_protocol_enabled(proto))
1968 dissect_function = NULL;
1971 * Handle RPCSEC_GSS specially.
1975 case FLAVOR_UNKNOWN:
1977 * We don't know the authentication flavor, so we can't
1978 * dissect the payload.
1980 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
1981 "Unknown authentication flavor - cannot dissect");
1984 case FLAVOR_NOT_GSSAPI:
1986 * It's not GSS-API authentication. Just dissect the
1989 offset = call_dissect_function(tvb, pinfo, ptree, offset,
1990 dissect_function, progname);
1993 case FLAVOR_GSSAPI_NO_INFO:
1995 * It's GSS-API authentication, but we don't have the
1996 * procedure and service information, so we can't dissect
1999 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2000 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2005 * It's GSS-API authentication, and we have the procedure
2006 * and service information; process the GSS-API stuff,
2007 * and process the payload if there is any.
2011 case RPCSEC_GSS_INIT:
2012 case RPCSEC_GSS_CONTINUE_INIT:
2013 if (msg_type == RPC_CALL) {
2014 offset = dissect_rpc_authgss_initarg(tvb,
2015 pinfo, ptree, offset);
2018 offset = dissect_rpc_authgss_initres(tvb,
2019 pinfo, ptree, offset);
2023 case RPCSEC_GSS_DATA:
2024 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2025 offset = call_dissect_function(tvb,
2026 pinfo, ptree, offset,
2030 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2031 offset = dissect_rpc_authgss_integ_data(tvb,
2032 pinfo, ptree, offset,
2036 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2037 offset = dissect_rpc_authgss_priv_data(tvb,
2038 pinfo, ptree, offset);
2047 /* dissect any remaining bytes (incomplete dissection) as pure data in
2049 dissect_data(tvb, offset, pinfo, ptree);
2055 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2057 return dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0);
2061 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2063 if (!dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0))
2064 dissect_rpc_continuation(tvb, pinfo, tree);
2070 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
2072 * IS_RPC, if we dissected at least one message in its entirety
2075 * IS_NOT_RPC, if we found no RPC message.
2083 static rpc_tcp_return_t
2084 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2089 gboolean saw_rpc = FALSE;
2091 gint tvb_len, tvb_reported_len;
2094 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2096 * XXX - we need to handle records that don't have the "last
2097 * fragment" bit set, and reassemble fragments.
2100 /* the first 4 bytes are special in "record marking mode" */
2101 if (!tvb_bytes_exist(tvb, offset, 4)) {
2103 * XXX - we should somehow arrange to handle
2104 * a record mark split across TCP segments.
2106 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2108 rpc_rm = tvb_get_ntohl(tvb, offset);
2110 len = rpc_rm&RPC_RM_FRAGLEN;
2113 * XXX - reject fragments bigger than 2 megabytes.
2114 * This is arbitrary, but should at least prevent
2115 * some crashes from either packets with really
2116 * large RPC-over-TCP fragments or from stuff that's
2119 if (len > 2*1024*1024)
2120 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2121 if (rpc_desegment) {
2122 seglen = tvb_length_remaining(tvb, offset + 4);
2124 if (len > seglen && pinfo->can_desegment) {
2126 * This frame doesn't have all of the
2127 * data for this message, but we can do
2130 * If this is a heuristic dissector, just
2131 * return IS_NOT_RPC - we don't want to try
2132 * to get more data, as that's too likely
2133 * to cause us to misidentify this as
2136 * If this isn't a heuristic dissector,
2137 * we've already identified this conversation
2138 * as containing RPC data, as we saw RPC
2139 * data in previous frames. Try to get
2145 pinfo->desegment_offset = offset;
2146 pinfo->desegment_len = len - seglen;
2147 return NEED_MORE_DATA;
2151 len += 4; /* include record mark */
2152 tvb_len = tvb_length_remaining(tvb, offset);
2153 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2156 if (tvb_reported_len > len)
2157 tvb_reported_len = len;
2158 msg_tvb = tvb_new_subset(tvb, offset, tvb_len,
2160 if (!dissect_rpc_message(msg_tvb, 4, pinfo, tree,
2166 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2170 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2172 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
2181 /* "Can't happen" */
2182 g_assert_not_reached();
2188 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2190 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
2191 dissect_rpc_continuation(tvb, pinfo, tree);
2194 /* Discard any state we've saved. */
2196 rpc_init_protocol(void)
2198 if (rpc_calls != NULL)
2199 g_hash_table_destroy(rpc_calls);
2200 if (rpc_indir_calls != NULL)
2201 g_hash_table_destroy(rpc_indir_calls);
2202 if (rpc_call_info_key_chunk != NULL)
2203 g_mem_chunk_destroy(rpc_call_info_key_chunk);
2204 if (rpc_call_info_value_chunk != NULL)
2205 g_mem_chunk_destroy(rpc_call_info_value_chunk);
2207 rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2208 rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2209 rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
2210 sizeof(rpc_call_info_key),
2211 200 * sizeof(rpc_call_info_key),
2213 rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
2214 sizeof(rpc_call_info_value),
2215 200 * sizeof(rpc_call_info_value),
2219 /* will be called once from register.c at startup time */
2221 proto_register_rpc(void)
2223 static hf_register_info hf[] = {
2224 { &hf_rpc_lastfrag, {
2225 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, BASE_NONE,
2226 &yesno, 0, "Last Fragment", HFILL }},
2227 { &hf_rpc_fraglen, {
2228 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
2229 NULL, 0, "Fragment Length", HFILL }},
2231 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
2232 NULL, 0, "XID", HFILL }},
2233 { &hf_rpc_msgtype, {
2234 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
2235 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
2236 { &hf_rpc_state_reply, {
2237 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
2238 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
2239 { &hf_rpc_state_accept, {
2240 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
2241 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
2242 { &hf_rpc_state_reject, {
2243 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
2244 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
2245 { &hf_rpc_state_auth, {
2246 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
2247 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
2248 { &hf_rpc_version, {
2249 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
2250 NULL, 0, "RPC Version", HFILL }},
2251 { &hf_rpc_version_min, {
2252 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
2253 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2254 { &hf_rpc_version_max, {
2255 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
2256 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
2257 { &hf_rpc_program, {
2258 "Program", "rpc.program", FT_UINT32, BASE_DEC,
2259 NULL, 0, "Program", HFILL }},
2260 { &hf_rpc_programversion, {
2261 "Program Version", "rpc.programversion", FT_UINT32,
2262 BASE_DEC, NULL, 0, "Program Version", HFILL }},
2263 { &hf_rpc_programversion_min, {
2264 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
2265 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2266 { &hf_rpc_programversion_max, {
2267 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
2268 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
2269 { &hf_rpc_procedure, {
2270 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
2271 NULL, 0, "Procedure", HFILL }},
2272 { &hf_rpc_auth_flavor, {
2273 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
2274 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
2275 { &hf_rpc_auth_length, {
2276 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
2277 NULL, 0, "Length", HFILL }},
2278 { &hf_rpc_auth_stamp, {
2279 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
2280 NULL, 0, "Stamp", HFILL }},
2281 { &hf_rpc_auth_uid, {
2282 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
2283 NULL, 0, "UID", HFILL }},
2284 { &hf_rpc_auth_gid, {
2285 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
2286 NULL, 0, "GID", HFILL }},
2287 { &hf_rpc_authgss_v, {
2288 "GSS Version", "rpc.authgss.version", FT_UINT32,
2289 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
2290 { &hf_rpc_authgss_proc, {
2291 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
2292 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
2293 { &hf_rpc_authgss_seq, {
2294 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
2295 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
2296 { &hf_rpc_authgss_svc, {
2297 "GSS Service", "rpc.authgss.service", FT_UINT32,
2298 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
2299 { &hf_rpc_authgss_ctx, {
2300 "GSS Context", "rpc.authgss.context", FT_BYTES,
2301 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
2302 { &hf_rpc_authgss_major, {
2303 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
2304 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
2305 { &hf_rpc_authgss_minor, {
2306 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
2307 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
2308 { &hf_rpc_authgss_window, {
2309 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
2310 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
2311 { &hf_rpc_authgss_token, {
2312 "GSS Token", "rpc.authgss.token", FT_BYTES,
2313 BASE_HEX, NULL, 0, "GSS Token", HFILL }},
2314 { &hf_rpc_authgss_data_length, {
2315 "Length", "rpc.authgss.data.length", FT_UINT32,
2316 BASE_DEC, NULL, 0, "Length", HFILL }},
2317 { &hf_rpc_authgss_data, {
2318 "GSS Data", "rpc.authgss.data", FT_BYTES,
2319 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
2320 { &hf_rpc_authgss_checksum, {
2321 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
2322 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
2323 { &hf_rpc_authdes_namekind, {
2324 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
2325 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
2326 { &hf_rpc_authdes_netname, {
2327 "Netname", "rpc.authdes.netname", FT_STRING,
2328 BASE_DEC, NULL, 0, "Netname", HFILL }},
2329 { &hf_rpc_authdes_convkey, {
2330 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
2331 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
2332 { &hf_rpc_authdes_window, {
2333 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
2334 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
2335 { &hf_rpc_authdes_nickname, {
2336 "Nickname", "rpc.authdes.nickname", FT_UINT32,
2337 BASE_HEX, NULL, 0, "Nickname", HFILL }},
2338 { &hf_rpc_authdes_timestamp, {
2339 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
2340 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
2341 { &hf_rpc_authdes_windowverf, {
2342 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
2343 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
2344 { &hf_rpc_authdes_timeverf, {
2345 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
2346 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
2347 { &hf_rpc_auth_machinename, {
2348 "Machine Name", "rpc.auth.machinename", FT_STRING,
2349 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
2351 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
2352 NULL, 0, "Duplicate Transaction", HFILL }},
2353 { &hf_rpc_call_dup, {
2354 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
2355 NULL, 0, "Duplicate Call", HFILL }},
2356 { &hf_rpc_reply_dup, {
2357 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
2358 NULL, 0, "Duplicate Reply", HFILL }},
2359 { &hf_rpc_value_follows, {
2360 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
2361 &yesno, 0, "Value Follows", HFILL }},
2362 { &hf_rpc_array_len, {
2363 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
2364 NULL, 0, "Length of RPC array", HFILL }},
2366 static gint *ett[] = {
2375 module_t *rpc_module;
2377 proto_rpc = proto_register_protocol("Remote Procedure Call",
2379 proto_register_field_array(proto_rpc, hf, array_length(hf));
2380 proto_register_subtree_array(ett, array_length(ett));
2381 register_init_routine(&rpc_init_protocol);
2382 rpc_module = prefs_register_protocol(proto_rpc, NULL);
2383 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
2384 "Desegment all RPC over TCP commands",
2385 "Whether the RPC dissector should desegment all RPC over TCP commands",
2389 * Init the hash tables. Dissectors for RPC protocols must
2390 * have a "handoff registration" routine that registers the
2391 * protocol with RPC; they must not do it in their protocol
2392 * registration routine, as their protocol registration
2393 * routine might be called before this routine is called and
2394 * thus might be called before the hash tables are initialized,
2395 * but it's guaranteed that all protocol registration routines
2396 * will be called before any handoff registration routines
2399 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
2400 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
2404 proto_reg_handoff_rpc(void)
2406 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
2407 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);