2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.76 2001/11/27 07:13:26 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 static dissector_handle_t rpc_tcp_handle;
197 static dissector_handle_t rpc_handle;
198 static dissector_handle_t data_handle;
200 /* Hash table with info on RPC program numbers */
201 static GHashTable *rpc_progs;
203 /* Hash table with info on RPC procedure numbers */
204 static GHashTable *rpc_procs;
206 typedef struct _rpc_proc_info_key {
212 typedef struct _rpc_proc_info_value {
214 dissect_function_t *dissect_call;
215 dissect_function_t *dissect_reply;
216 } rpc_proc_info_value;
218 typedef struct _rpc_prog_info_key {
222 typedef struct _rpc_prog_info_value {
226 } rpc_prog_info_value;
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);
231 /***********************************/
232 /* Hash array with procedure names */
233 /***********************************/
237 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
239 rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
240 rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
242 return ((key1->prog == key2->prog &&
243 key1->vers == key2->vers &&
244 key1->proc == key2->proc) ?
248 /* calculate a hash key */
250 rpc_proc_hash(gconstpointer k)
252 rpc_proc_info_key* key = (rpc_proc_info_key*) k;
254 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
258 /* insert some entries */
260 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
264 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
265 rpc_proc_info_key *key;
266 rpc_proc_info_value *value;
268 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
271 key->proc = proc->value;
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;
278 g_hash_table_insert(rpc_procs,key,value);
282 /* return the name associated with a previously registered procedure. */
283 char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
285 rpc_proc_info_key key;
286 rpc_proc_info_value *value;
288 static char procname_static[20];
294 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
295 procname = value->name;
297 /* happens only with strange program versions or
298 non-existing dissectors */
299 sprintf(procname_static, "proc-%u", key.proc);
300 procname = procname_static;
305 /*----------------------------------------*/
306 /* end of Hash array with procedure names */
307 /*----------------------------------------*/
310 /*********************************/
311 /* Hash array with program names */
312 /*********************************/
316 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
318 rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
319 rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
321 return ((key1->prog == key2->prog) ?
326 /* calculate a hash key */
328 rpc_prog_hash(gconstpointer k)
330 rpc_prog_info_key* key = (rpc_prog_info_key*) k;
337 rpc_init_prog(int proto, guint32 prog, int ett)
339 rpc_prog_info_key *key;
340 rpc_prog_info_value *value;
342 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
345 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
346 value->proto = proto;
348 value->progname = proto_get_protocol_short_name(proto);
350 g_hash_table_insert(rpc_progs,key,value);
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)
358 char *progname = NULL;
359 rpc_prog_info_key rpc_prog_key;
360 rpc_prog_info_value *rpc_prog;
362 rpc_prog_key.prog = prog;
363 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
364 progname = "Unknown";
367 progname = rpc_prog->progname;
373 /*--------------------------------------*/
374 /* end of Hash array with program names */
375 /*--------------------------------------*/
377 typedef struct _rpc_call_info_key {
379 conversation_t *conversation;
382 static GMemChunk *rpc_call_info_key_chunk;
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 */
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 */
400 rpc_proc_info_value* proc_info;
401 } rpc_call_info_value;
403 static GMemChunk *rpc_call_info_value_chunk;
405 static GHashTable *rpc_calls;
407 static GHashTable *rpc_indir_calls;
411 rpc_call_equal(gconstpointer k1, gconstpointer k2)
413 rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
414 rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
416 return (key1->xid == key2->xid &&
417 key1->conversation == key2->conversation);
421 /* calculate a hash key */
423 rpc_call_hash(gconstpointer k)
425 rpc_call_info_key* key = (rpc_call_info_key*) k;
427 return key->xid + (guint32)(key->conversation);
432 rpc_roundup(unsigned int a)
434 unsigned int mod = a % 4;
435 return a + ((mod)? 4-mod : 0);
440 dissect_rpc_bool(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
441 int hfindex, int offset)
444 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
450 dissect_rpc_uint32(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
451 int hfindex, int offset)
454 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
460 dissect_rpc_uint64(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
461 int hfindex, int offset)
463 header_field_info *hfinfo;
465 hfinfo = proto_registrar_get_nth(hfindex);
466 g_assert(hfinfo->type == FT_UINT64);
468 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
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)
479 proto_item *string_item = NULL;
480 proto_tree *string_tree = NULL;
481 int old_offset = offset;
483 int length_truncated = 0;
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;
491 int fill_truncated = 0;
492 guint32 fill_length = 0;
493 guint32 fill_length_packet = 0;
494 guint32 fill_length_copy = 0;
496 char *string_buffer = NULL;
497 char *string_buffer_print = NULL;
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;
509 fill_length_packet = 0;
510 fill_length_copy = 0;
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;
526 /* full fill bytes */
527 fill_length_copy = fill_length;
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);
535 string_buffer[string_length_copy] = '\0';
537 /* calculate a nice printable string */
539 if (string_length != string_length_copy) {
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).
555 strcat(string_buffer_print,"<TRUNCATED>");
558 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
563 string_buffer_print = g_strdup(string_buffer);
566 string_buffer_print = g_strdup("<DATA>");
571 string_buffer_print = g_strdup("<EMPTY>");
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);
578 proto_tree_add_string_hidden(tree, hfindex, tvb, offset+4,
579 string_length_copy, string_buffer);
582 string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
585 if (length_truncated) {
587 proto_tree_add_text(string_tree, tvb,
588 offset, tvb_length_remaining(tvb, offset),
589 "length: <TRUNCATED>");
590 offset = tvb_length(tvb);
593 proto_tree_add_text(string_tree, tvb,offset+0,4,
594 "length: %u", string_length);
599 proto_tree_add_string_format(string_tree,
600 hfindex, tvb, offset, string_length_copy,
602 "contents: %s", string_buffer_print);
604 proto_tree_add_bytes_format(string_tree,
605 hfindex, tvb, offset, string_length_copy,
607 "contents: %s", string_buffer_print);
610 offset += string_length_copy;
613 if (fill_truncated) {
614 proto_tree_add_text(string_tree, tvb,
615 offset,fill_length_copy,
616 "fill bytes: opaque data<TRUNCATED>");
619 proto_tree_add_text(string_tree, tvb,
620 offset,fill_length_copy,
621 "fill bytes: opaque data");
624 offset += fill_length_copy;
629 proto_item_set_len(string_item, offset - old_offset);
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;
637 g_free (string_buffer_print);
644 dissect_rpc_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
645 int hfindex, int offset, char **string_buffer_ret)
647 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree,
648 hfindex, TRUE, string_buffer_ret);
654 dissect_rpc_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
655 int hfindex, int offset)
657 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree, hfindex,
665 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
666 int offset, dissect_function_t *rpc_list_dissector)
668 guint32 value_follows;
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);
675 if (value_follows == 1) {
676 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
687 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
688 int offset, dissect_function_t *rpc_array_dissector,
691 proto_item* lock_item;
692 proto_tree* lock_tree;
694 int old_offset = offset;
696 num = tvb_get_ntohl(tvb, offset);
699 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
706 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset,
709 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
711 offset = dissect_rpc_uint32(tvb, pinfo, lock_tree,
712 hf_rpc_array_len, offset);
715 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
718 proto_item_set_len(lock_item, offset-old_offset);
723 dissect_rpc_authunix_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
732 proto_tree *gtree = NULL;
734 stamp = tvb_get_ntohl(tvb,offset+0);
736 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
740 offset = dissect_rpc_string(tvb, pinfo, tree,
741 hf_rpc_auth_machinename, offset, NULL);
743 uid = tvb_get_ntohl(tvb,offset+0);
745 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
749 gid = tvb_get_ntohl(tvb,offset+0);
751 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
755 gids_count = tvb_get_ntohl(tvb,offset+0);
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);
763 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
764 gids_entry = tvb_get_ntohl(tvb,offset+0);
766 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
767 offset, 4, gids_entry);
770 /* how can I NOW change the gitem to print a list with
771 the first 16 gids? */
777 dissect_rpc_authgss_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
784 agc_v = tvb_get_ntohl(tvb, offset+0);
786 proto_tree_add_uint(tree, hf_rpc_authgss_v,
787 tvb, offset+0, 4, agc_v);
790 agc_proc = tvb_get_ntohl(tvb, offset+0);
792 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
793 tvb, offset+0, 4, agc_proc);
796 agc_seq = tvb_get_ntohl(tvb, offset+0);
798 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
799 tvb, offset+0, 4, agc_seq);
802 agc_svc = tvb_get_ntohl(tvb, offset+0);
804 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
805 tvb, offset+0, 4, agc_svc);
808 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
815 dissect_rpc_authdes_desblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
816 int hfindex, int offset)
821 value_high = tvb_get_ntohl(tvb, offset + 0);
822 value_low = tvb_get_ntohl(tvb, offset + 4);
825 proto_tree_add_text(tree, tvb, offset, 8,
826 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
834 dissect_rpc_authdes_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
840 adc_namekind = tvb_get_ntohl(tvb, offset+0);
842 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
843 tvb, offset+0, 4, adc_namekind);
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,
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,
871 dissect_rpc_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
879 flavor = tvb_get_ntohl(tvb,offset+0);
880 length = tvb_get_ntohl(tvb,offset+4);
881 length = rpc_roundup(length);
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);
894 dissect_rpc_authunix_cred(tvb, pinfo, ctree, offset+8);
902 dissect_rpc_authdes_cred(tvb, pinfo, ctree, offset+8);
906 dissect_rpc_authgss_cred(tvb, pinfo, ctree, offset+8);
910 proto_tree_add_text(ctree, tvb, offset+8,
911 length,"opaque data");
915 offset += 8 + length;
920 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
921 * verifier we're decoding (CALL or REPLY).
924 dissect_rpc_verf(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset, int msg_type)
932 flavor = tvb_get_ntohl(tvb,offset+0);
933 length = tvb_get_ntohl(tvb,offset+4);
934 length = rpc_roundup(length);
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);
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);
950 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
951 offset+4, 4, length);
953 if (msg_type == RPC_CALL)
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);
965 /* must be an RPC_REPLY */
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);
976 dissect_rpc_data(tvb, pinfo, vtree,
977 hf_rpc_authgss_checksum, offset+4);
980 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
981 offset+4, 4, length);
983 proto_tree_add_text(vtree, tvb, offset+8,
984 length, "opaque data");
988 offset += 8 + length;
994 dissect_rpc_authgss_initarg(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
996 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1002 dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
1004 int major, minor, window;
1006 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
1009 major = tvb_get_ntohl(tvb,offset+0);
1011 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1012 offset+0, 4, major);
1015 minor = tvb_get_ntohl(tvb,offset+0);
1017 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1018 offset+0, 4, minor);
1021 window = tvb_get_ntohl(tvb,offset+0);
1023 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1024 offset+0, 4, window);
1027 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1035 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1036 int offset, dissect_function_t* dissect_function, const char *progname)
1038 const char *saved_proto;
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;
1046 /* call the dissector for the next level */
1047 offset = dissect_function(tvb, offset, pinfo, tree);
1049 /* restore the protocol name */
1050 pinfo->current_proto = saved_proto;
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)
1063 guint32 length, seq;
1066 proto_tree *gtree = NULL;
1068 length = tvb_get_ntohl(tvb, offset+0);
1069 length = rpc_roundup(length);
1070 seq = tvb_get_ntohl(tvb, offset+4);
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);
1083 if (dissect_function != NULL) {
1085 call_dissect_function(tvb, pinfo, gtree, offset,
1086 dissect_function, progname);
1088 offset += length - 4;
1089 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_checksum,
1096 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1098 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_data,
1104 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
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.
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)
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;
1126 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1127 dissect_function = value->dissect_call;
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.
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.
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);
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
1156 conversation = find_conversation(&pinfo->src,
1157 &null_address, pinfo->ptype, pinfo->srcport,
1158 pinfo->destport, 0);
1160 if (conversation == NULL) {
1161 /* It's not part of any conversation - create a new
1164 XXX - this should never happen, as we should've
1165 created a conversation for it in the RPC
1167 if (pinfo->ptype == PT_TCP) {
1168 conversation = conversation_new(&pinfo->src,
1169 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1170 pinfo->destport, 0);
1172 conversation = conversation_new(&pinfo->src,
1173 &null_address, pinfo->ptype, pinfo->srcport,
1174 pinfo->destport, 0);
1178 /* Make the dissector for this conversation the non-heuristic
1180 conversation_set_dissector(conversation,
1181 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1183 /* Prepare the key data.
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;
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;
1209 * XXX - what about RPCSEC_GSS?
1210 * Do we have to worry about it?
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;
1217 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
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,
1233 proto_tree_add_text(tree, tvb, offset, 4,
1234 "Argument length: %u",
1235 tvb_get_ntohl(tvb, offset));
1239 /* Dissect the arguments */
1240 offset = call_dissect_function(tvb, pinfo, tree, offset,
1241 dissect_function, NULL);
1246 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
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)
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;
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
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.
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);
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
1289 conversation = find_conversation(&null_address, &pinfo->dst,
1290 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
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,
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,
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;
1320 sprintf(procname_static, "proc-%u", rpc_call->proc);
1321 procname = procname_static;
1326 dissect_function = NULL;
1328 sprintf(procname_static, "proc-%u", rpc_call->proc);
1329 procname = procname_static;
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);
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,
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));
1360 /* Dissect the return value */
1361 offset = call_dissect_function(tvb, pinfo, tree, offset,
1362 dissect_function, NULL);
1367 * Just mark this as a continuation of an earlier packet.
1370 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1372 proto_item *rpc_item;
1373 proto_tree *rpc_tree;
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");
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");
1390 dissect_rpc_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1391 proto_tree *tree, gboolean use_rm, guint32 rpc_rm)
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;
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;
1410 unsigned int reply_state;
1411 unsigned int accept_state;
1412 unsigned int reject_state;
1414 char *msg_type_name = NULL;
1415 char *progname = NULL;
1416 char *procname = NULL;
1417 static char procname_static[20];
1419 unsigned int vers_low;
1420 unsigned int vers_high;
1422 unsigned int auth_state;
1424 proto_item *rpc_item=NULL;
1425 proto_tree *rpc_tree = NULL;
1427 proto_item *pitem=NULL;
1428 proto_tree *ptree = NULL;
1429 int offset_old = offset;
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 };
1437 dissect_function_t *dissect_function = NULL;
1440 * Check to see whether this looks like an RPC call or reply.
1442 if (!tvb_bytes_exist(tvb, offset, 8)) {
1443 /* Captured data in packet isn't enough to let us tell. */
1447 /* both directions need at least this */
1448 msg_type = tvb_get_ntohl(tvb, offset + 4);
1453 /* check for RPC call */
1454 if (!tvb_bytes_exist(tvb, offset, 16)) {
1455 /* Captured data in packet isn't enough to let us
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))
1469 /* They're not, so it's probably not an RPC call. */
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.
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.
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);
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
1503 conversation = find_conversation(&null_address,
1504 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1505 pinfo->destport, 0);
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. */
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. */
1525 /* The putative message type field contains neither
1526 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
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);
1537 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1538 tvb_length(tvb), FALSE);
1540 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
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);
1551 xid = tvb_get_ntohl(tvb, offset + 0);
1553 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1554 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1557 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1559 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1560 offset+4, 4, msg_type);
1568 /* we know already the proto-entry, the ETT-const,
1570 proto = rpc_prog->proto;
1571 ett = rpc_prog->ett;
1572 progname = rpc_prog->progname;
1574 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1576 proto_tree_add_uint(rpc_tree,
1577 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1580 prog = tvb_get_ntohl(tvb, offset + 4);
1583 proto_tree_add_uint_format(rpc_tree,
1584 hf_rpc_program, tvb, offset+4, 4, prog,
1585 "Program: %s (%u)", progname, prog);
1588 if (check_col(pinfo->fd, COL_PROTOCOL)) {
1589 /* Set the protocol name to the underlying
1591 col_set_str(pinfo->fd, COL_PROTOCOL, progname);
1594 vers = tvb_get_ntohl(tvb, offset+8);
1596 proto_tree_add_uint(rpc_tree,
1597 hf_rpc_programversion, tvb, offset+8, 4, vers);
1600 proc = tvb_get_ntohl(tvb, offset+12);
1606 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1607 dissect_function = value->dissect_call;
1608 procname = value->name;
1611 /* happens only with strange program versions or
1612 non-existing dissectors */
1614 dissect_function = NULL;
1616 sprintf(procname_static, "proc-%u", proc);
1617 procname = procname_static;
1621 proto_tree_add_uint_format(rpc_tree,
1622 hf_rpc_procedure, tvb, offset+12, 4, proc,
1623 "Procedure: %s (%u)", procname, proc);
1626 if (check_col(pinfo->fd, COL_INFO)) {
1627 col_add_fstr(pinfo->fd, COL_INFO,"V%u %s %s XID 0x%x",
1634 /* Check for RPCSEC_GSS */
1635 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1636 switch (tvb_get_ntohl(tvb, offset+16)) {
1640 * It's GSS-API authentication...
1642 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1644 * ...and we have the procedure
1645 * and service information for it.
1647 flavor = FLAVOR_GSSAPI;
1648 gss_proc = tvb_get_ntohl(tvb, offset+28);
1649 gss_svc = tvb_get_ntohl(tvb, offset+36);
1652 * ...but the procedure and service
1653 * information isn't available.
1655 flavor = FLAVOR_GSSAPI_NO_INFO;
1661 * It's not GSS-API authentication.
1663 flavor = FLAVOR_NOT_GSSAPI;
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.
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.
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);
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
1695 conversation = find_conversation(&pinfo->src,
1696 &null_address, pinfo->ptype, pinfo->srcport,
1697 pinfo->destport, 0);
1699 if (conversation == NULL) {
1700 /* It's not part of any conversation - create a new
1702 if (pinfo->ptype == PT_TCP) {
1703 conversation = conversation_new(&pinfo->src,
1704 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1705 pinfo->destport, 0);
1707 conversation = conversation_new(&pinfo->src,
1708 &null_address, pinfo->ptype, pinfo->srcport,
1709 pinfo->destport, 0);
1713 /* Make the dissector for this conversation the non-heuristic
1715 conversation_set_dissector(conversation,
1716 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1718 /* prepare the key data */
1719 rpc_call_key.xid = xid;
1720 rpc_call_key.conversation = conversation;
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
1728 if (pinfo->fd->num != rpc_call->req_num) {
1729 /* No, so it's a duplicate request.
1731 if (check_col(pinfo->fd, COL_INFO)) {
1732 col_append_fstr(pinfo->fd, COL_INFO,
1733 " dup XID 0x%x", xid);
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);
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;
1762 g_hash_table_insert(rpc_calls, new_rpc_call_key,
1768 offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset);
1769 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1771 /* go to the next dissector */
1773 break; /* end of RPC call */
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;
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",
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;
1796 sprintf(procname_static, "proc-%u", proc);
1797 procname = procname_static;
1802 dissect_function = NULL;
1804 sprintf(procname_static, "proc-%u", proc);
1805 procname = procname_static;
1808 rpc_prog_key.prog = prog;
1809 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1812 progname = "Unknown";
1815 proto = rpc_prog->proto;
1816 ett = rpc_prog->ett;
1817 progname = rpc_prog->progname;
1819 if (check_col(pinfo->fd, COL_PROTOCOL)) {
1820 /* Set the protocol name to the underlying
1822 col_set_str(pinfo->fd, COL_PROTOCOL, progname);
1826 if (check_col(pinfo->fd, COL_INFO)) {
1827 col_add_fstr(pinfo->fd, COL_INFO,"V%u %s %s XID 0x%x",
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);
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
1849 rpc_call->rep_num = pinfo->fd->num;
1851 /* We have seen a reply to this call - but was it
1853 if (rpc_call->rep_num != pinfo->fd->num) {
1854 /* No, so it's a duplicate reply.
1856 if (check_col(pinfo->fd, COL_INFO)) {
1857 col_append_fstr(pinfo->fd, COL_INFO,
1858 " dup XID 0x%x", xid);
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);
1869 reply_state = tvb_get_ntohl(tvb,offset+0);
1871 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
1872 offset+0, 4, reply_state);
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);
1880 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
1881 offset+0, 4, accept_state);
1884 switch (accept_state) {
1887 /* go to the next dissector */
1891 vers_low = tvb_get_ntohl(tvb,offset+0);
1892 vers_high = tvb_get_ntohl(tvb,offset+4);
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);
1908 } else if (reply_state == MSG_DENIED) {
1909 reject_state = tvb_get_ntohl(tvb,offset+0);
1911 proto_tree_add_uint(rpc_tree,
1912 hf_rpc_state_reject, tvb, offset+0, 4,
1917 if (reject_state==RPC_MISMATCH) {
1918 vers_low = tvb_get_ntohl(tvb,offset+0);
1919 vers_high = tvb_get_ntohl(tvb,offset+4);
1921 proto_tree_add_uint(rpc_tree,
1923 tvb, offset+0, 4, vers_low);
1924 proto_tree_add_uint(rpc_tree,
1926 tvb, offset+4, 4, vers_high);
1929 } else if (reject_state==AUTH_ERROR) {
1930 auth_state = tvb_get_ntohl(tvb,offset+0);
1932 proto_tree_add_uint(rpc_tree,
1933 hf_rpc_state_auth, tvb, offset+0, 4,
1939 break; /* end of RPC reply */
1943 * The switch statement at the top returned if
1944 * this was neither an RPC call nor a reply.
1946 g_assert_not_reached();
1949 /* now we know, that RPC was shorter */
1951 proto_item_set_len(rpc_item, offset - offset_old);
1954 /* create here the program specific sub-tree */
1956 pitem = proto_tree_add_item(tree, proto, tvb,
1957 offset, tvb_length(tvb) - offset, FALSE);
1959 ptree = proto_item_add_subtree(pitem, ett);
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);
1971 if (!proto_is_protocol_enabled(proto))
1972 dissect_function = NULL;
1975 * Handle RPCSEC_GSS specially.
1979 case FLAVOR_UNKNOWN:
1981 * We don't know the authentication flavor, so we can't
1982 * dissect the payload.
1984 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
1985 "Unknown authentication flavor - cannot dissect");
1988 case FLAVOR_NOT_GSSAPI:
1990 * It's not GSS-API authentication. Just dissect the
1993 offset = call_dissect_function(tvb, pinfo, ptree, offset,
1994 dissect_function, progname);
1997 case FLAVOR_GSSAPI_NO_INFO:
1999 * It's GSS-API authentication, but we don't have the
2000 * procedure and service information, so we can't dissect
2003 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2004 "GSS-API authentication, but procedure and service unknown - cannot dissect");
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.
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);
2022 offset = dissect_rpc_authgss_initres(tvb,
2023 pinfo, ptree, offset);
2027 case RPCSEC_GSS_DATA:
2028 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2029 offset = call_dissect_function(tvb,
2030 pinfo, ptree, offset,
2034 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2035 offset = dissect_rpc_authgss_integ_data(tvb,
2036 pinfo, ptree, offset,
2040 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2041 offset = dissect_rpc_authgss_priv_data(tvb,
2042 pinfo, ptree, offset);
2051 /* dissect any remaining bytes (incomplete dissection) as pure data in
2053 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, ptree);
2059 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2061 return dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0);
2065 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2067 if (!dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0))
2068 dissect_rpc_continuation(tvb, pinfo, tree);
2074 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
2076 * IS_RPC, if we dissected at least one message in its entirety
2079 * IS_NOT_RPC, if we found no RPC message.
2087 static rpc_tcp_return_t
2088 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2093 gboolean saw_rpc = FALSE;
2095 gint tvb_len, tvb_reported_len;
2098 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2100 * XXX - we need to handle records that don't have the "last
2101 * fragment" bit set, and reassemble fragments.
2104 /* the first 4 bytes are special in "record marking mode" */
2105 if (!tvb_bytes_exist(tvb, offset, 4)) {
2107 * XXX - we should somehow arrange to handle
2108 * a record mark split across TCP segments.
2110 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2112 rpc_rm = tvb_get_ntohl(tvb, offset);
2114 len = rpc_rm&RPC_RM_FRAGLEN;
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
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);
2128 if (len > seglen && pinfo->can_desegment) {
2130 * This frame doesn't have all of the
2131 * data for this message, but we can do
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
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
2149 pinfo->desegment_offset = offset;
2150 pinfo->desegment_len = len - seglen;
2151 return NEED_MORE_DATA;
2155 len += 4; /* include record mark */
2156 tvb_len = tvb_length_remaining(tvb, offset);
2157 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2160 if (tvb_reported_len > len)
2161 tvb_reported_len = len;
2162 msg_tvb = tvb_new_subset(tvb, offset, tvb_len,
2164 if (!dissect_rpc_message(msg_tvb, 4, pinfo, tree,
2170 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2174 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2176 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
2185 /* "Can't happen" */
2186 g_assert_not_reached();
2192 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2194 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
2195 dissect_rpc_continuation(tvb, pinfo, tree);
2198 /* Discard any state we've saved. */
2200 rpc_init_protocol(void)
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);
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),
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),
2223 /* will be called once from register.c at startup time */
2225 proto_register_rpc(void)
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 }},
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 }},
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 }},
2370 static gint *ett[] = {
2379 module_t *rpc_module;
2381 proto_rpc = proto_register_protocol("Remote Procedure Call",
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",
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
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);
2410 proto_reg_handoff_rpc(void)
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");