2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.81 2002/01/12 10:24:47 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"
43 #include "packet-frame.h"
49 * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
52 * RFC 1832, "XDR: External Data Representation Standard";
54 * RFC 2203, "RPCSEC_GSS Protocol Specification".
58 * RFC 2695, "Authentication Mechanisms for ONC RPC"
60 * although we don't currently dissect AUTH_DES or AUTH_KERB.
63 #define RPC_RM_FRAGLEN 0x7fffffffL
65 /* desegmentation of RPC over TCP */
66 static gboolean rpc_desegment = TRUE;
68 static struct true_false_string yesno = { "Yes", "No" };
71 static const value_string rpc_msg_type[] = {
73 { RPC_REPLY, "Reply" },
77 static const value_string rpc_reply_state[] = {
78 { MSG_ACCEPTED, "accepted" },
79 { MSG_DENIED, "denied" },
83 const value_string rpc_auth_flavor[] = {
84 { AUTH_NULL, "AUTH_NULL" },
85 { AUTH_UNIX, "AUTH_UNIX" },
86 { AUTH_SHORT, "AUTH_SHORT" },
87 { AUTH_DES, "AUTH_DES" },
88 { RPCSEC_GSS, "RPCSEC_GSS" },
92 static const value_string rpc_authgss_proc[] = {
93 { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
94 { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
95 { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
96 { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
100 value_string rpc_authgss_svc[] = {
101 { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
102 { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
103 { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
107 static const value_string rpc_accept_state[] = {
108 { SUCCESS, "RPC executed successfully" },
109 { PROG_UNAVAIL, "remote hasn't exported program" },
110 { PROG_MISMATCH, "remote can't support version #" },
111 { PROC_UNAVAIL, "program can't support procedure" },
112 { GARBAGE_ARGS, "procedure can't decode params" },
116 static const value_string rpc_reject_state[] = {
117 { RPC_MISMATCH, "RPC_MISMATCH" },
118 { AUTH_ERROR, "AUTH_ERROR" },
122 static const value_string rpc_auth_state[] = {
123 { AUTH_BADCRED, "bad credential (seal broken)" },
124 { AUTH_REJECTEDCRED, "client must begin new session" },
125 { AUTH_BADVERF, "bad verifier (seal broken)" },
126 { AUTH_REJECTEDVERF, "verifier expired or replayed" },
127 { AUTH_TOOWEAK, "rejected for security reasons" },
128 { RPCSEC_GSSCREDPROB, "GSS credential problem" },
129 { RPCSEC_GSSCTXPROB, "GSS context problem" },
133 static const value_string rpc_authdes_namekind[] = {
134 { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
135 { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
139 /* the protocol number */
140 static int proto_rpc = -1;
141 static int hf_rpc_lastfrag = -1;
142 static int hf_rpc_fraglen = -1;
143 static int hf_rpc_xid = -1;
144 static int hf_rpc_msgtype = -1;
145 static int hf_rpc_version = -1;
146 static int hf_rpc_version_min = -1;
147 static int hf_rpc_version_max = -1;
148 static int hf_rpc_program = -1;
149 static int hf_rpc_programversion = -1;
150 static int hf_rpc_programversion_min = -1;
151 static int hf_rpc_programversion_max = -1;
152 static int hf_rpc_procedure = -1;
153 static int hf_rpc_auth_flavor = -1;
154 static int hf_rpc_auth_length = -1;
155 static int hf_rpc_auth_machinename = -1;
156 static int hf_rpc_auth_stamp = -1;
157 static int hf_rpc_auth_uid = -1;
158 static int hf_rpc_auth_gid = -1;
159 static int hf_rpc_authgss_v = -1;
160 static int hf_rpc_authgss_proc = -1;
161 static int hf_rpc_authgss_seq = -1;
162 static int hf_rpc_authgss_svc = -1;
163 static int hf_rpc_authgss_ctx = -1;
164 static int hf_rpc_authgss_major = -1;
165 static int hf_rpc_authgss_minor = -1;
166 static int hf_rpc_authgss_window = -1;
167 static int hf_rpc_authgss_token = -1;
168 static int hf_rpc_authgss_data_length = -1;
169 static int hf_rpc_authgss_data = -1;
170 static int hf_rpc_authgss_checksum = -1;
171 static int hf_rpc_authdes_namekind = -1;
172 static int hf_rpc_authdes_netname = -1;
173 static int hf_rpc_authdes_convkey = -1;
174 static int hf_rpc_authdes_window = -1;
175 static int hf_rpc_authdes_nickname = -1;
176 static int hf_rpc_authdes_timestamp = -1;
177 static int hf_rpc_authdes_windowverf = -1;
178 static int hf_rpc_authdes_timeverf = -1;
179 static int hf_rpc_state_accept = -1;
180 static int hf_rpc_state_reply = -1;
181 static int hf_rpc_state_reject = -1;
182 static int hf_rpc_state_auth = -1;
183 static int hf_rpc_dup = -1;
184 static int hf_rpc_call_dup = -1;
185 static int hf_rpc_reply_dup = -1;
186 static int hf_rpc_value_follows = -1;
187 static int hf_rpc_array_len = -1;
188 static int hf_rpc_time = -1;
190 static gint ett_rpc = -1;
191 static gint ett_rpc_string = -1;
192 static gint ett_rpc_cred = -1;
193 static gint ett_rpc_verf = -1;
194 static gint ett_rpc_gids = -1;
195 static gint ett_rpc_gss_data = -1;
196 static gint ett_rpc_array = -1;
198 static dissector_handle_t rpc_tcp_handle;
199 static dissector_handle_t rpc_handle;
200 static dissector_handle_t data_handle;
202 /* Hash table with info on RPC program numbers */
203 static GHashTable *rpc_progs;
205 /* Hash table with info on RPC procedure numbers */
206 static GHashTable *rpc_procs;
208 typedef struct _rpc_proc_info_key {
214 typedef struct _rpc_proc_info_value {
216 dissect_function_t *dissect_call;
217 dissect_function_t *dissect_reply;
218 } rpc_proc_info_value;
220 typedef struct _rpc_prog_info_key {
224 typedef struct _rpc_prog_info_value {
228 } rpc_prog_info_value;
230 static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
231 static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
233 /***********************************/
234 /* Hash array with procedure names */
235 /***********************************/
239 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
241 rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
242 rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
244 return ((key1->prog == key2->prog &&
245 key1->vers == key2->vers &&
246 key1->proc == key2->proc) ?
250 /* calculate a hash key */
252 rpc_proc_hash(gconstpointer k)
254 rpc_proc_info_key* key = (rpc_proc_info_key*) k;
256 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
260 /* insert some entries */
262 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
266 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
267 rpc_proc_info_key *key;
268 rpc_proc_info_value *value;
270 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
273 key->proc = proc->value;
275 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
276 value->name = proc->strptr;
277 value->dissect_call = proc->dissect_call;
278 value->dissect_reply = proc->dissect_reply;
280 g_hash_table_insert(rpc_procs,key,value);
284 /* return the name associated with a previously registered procedure. */
285 char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
287 rpc_proc_info_key key;
288 rpc_proc_info_value *value;
290 static char procname_static[20];
296 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
297 procname = value->name;
299 /* happens only with strange program versions or
300 non-existing dissectors */
301 sprintf(procname_static, "proc-%u", key.proc);
302 procname = procname_static;
307 /*----------------------------------------*/
308 /* end of Hash array with procedure names */
309 /*----------------------------------------*/
312 /*********************************/
313 /* Hash array with program names */
314 /*********************************/
318 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
320 rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
321 rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
323 return ((key1->prog == key2->prog) ?
328 /* calculate a hash key */
330 rpc_prog_hash(gconstpointer k)
332 rpc_prog_info_key* key = (rpc_prog_info_key*) k;
339 rpc_init_prog(int proto, guint32 prog, int ett)
341 rpc_prog_info_key *key;
342 rpc_prog_info_value *value;
344 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
347 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
348 value->proto = proto;
350 value->progname = proto_get_protocol_short_name(proto);
352 g_hash_table_insert(rpc_progs,key,value);
355 /* return the name associated with a previously registered program. This
356 should probably eventually be expanded to use the rpc YP/NIS map
357 so that it can give names for programs not handled by ethereal */
358 char *rpc_prog_name(guint32 prog)
360 char *progname = NULL;
361 rpc_prog_info_key rpc_prog_key;
362 rpc_prog_info_value *rpc_prog;
364 rpc_prog_key.prog = prog;
365 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
366 progname = "Unknown";
369 progname = rpc_prog->progname;
375 /*--------------------------------------*/
376 /* end of Hash array with program names */
377 /*--------------------------------------*/
379 typedef struct _rpc_call_info_key {
381 conversation_t *conversation;
384 static GMemChunk *rpc_call_info_key_chunk;
386 static GMemChunk *rpc_call_info_value_chunk;
388 static GHashTable *rpc_calls;
390 static GHashTable *rpc_indir_calls;
394 rpc_call_equal(gconstpointer k1, gconstpointer k2)
396 rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
397 rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
399 return (key1->xid == key2->xid &&
400 key1->conversation == key2->conversation);
404 /* calculate a hash key */
406 rpc_call_hash(gconstpointer k)
408 rpc_call_info_key* key = (rpc_call_info_key*) k;
410 return key->xid + (guint32)(key->conversation);
415 rpc_roundup(unsigned int a)
417 unsigned int mod = a % 4;
418 return a + ((mod)? 4-mod : 0);
423 dissect_rpc_bool(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
424 int hfindex, int offset)
427 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
433 dissect_rpc_uint32(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
434 int hfindex, int offset)
437 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
443 dissect_rpc_uint64(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
444 int hfindex, int offset)
446 header_field_info *hfinfo;
448 hfinfo = proto_registrar_get_nth(hfindex);
449 g_assert(hfinfo->type == FT_UINT64);
451 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
458 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
459 proto_tree *tree, int hfindex, gboolean string_data,
460 char **string_buffer_ret)
462 proto_item *string_item = NULL;
463 proto_tree *string_tree = NULL;
464 int old_offset = offset;
466 int length_truncated = 0;
468 int string_truncated = 0;
469 guint32 string_length = 0;
470 guint32 string_length_full;
471 guint32 string_length_packet;
472 guint32 string_length_copy = 0;
474 int fill_truncated = 0;
475 guint32 fill_length = 0;
476 guint32 fill_length_packet = 0;
477 guint32 fill_length_copy = 0;
479 char *string_buffer = NULL;
480 char *string_buffer_print = NULL;
482 string_length = tvb_get_ntohl(tvb,offset+0);
483 string_length_full = rpc_roundup(string_length);
484 /* XXX - just let the tvbuff stuff throw an exception? */
485 string_length_packet = tvb_length_remaining(tvb, offset + 4);
486 if (string_length_packet < string_length) {
487 /* truncated string */
488 string_truncated = 1;
489 string_length_copy = string_length_packet;
492 fill_length_packet = 0;
493 fill_length_copy = 0;
496 /* full string data */
497 string_truncated = 0;
498 string_length_copy = string_length;
499 fill_length = string_length_full - string_length;
500 /* XXX - just let the tvbuff stuff throw an exception? */
501 fill_length_packet = tvb_length_remaining(tvb,
502 offset + 4 + string_length);
503 if (fill_length_packet < fill_length) {
504 /* truncated fill bytes */
505 fill_length_copy = fill_length_packet;
509 /* full fill bytes */
510 fill_length_copy = fill_length;
514 string_buffer = (char*)g_malloc(string_length_copy +
515 (string_data ? 1 : 0));
516 tvb_memcpy(tvb,string_buffer,offset+4,string_length_copy);
518 string_buffer[string_length_copy] = '\0';
520 /* calculate a nice printable string */
522 if (string_length != string_length_copy) {
524 /* alloc maximum data area */
525 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
526 /* copy over the data */
527 memcpy(string_buffer_print,string_buffer,string_length_copy);
528 /* append a 0 byte for sure printing */
529 string_buffer_print[string_length_copy] = '\0';
530 /* append <TRUNCATED> */
531 /* This way, we get the TRUNCATED even
532 in the case of totally wrong packets,
533 where \0 are inside the string.
534 TRUNCATED will appear at the
535 first \0 or at the end (where we
536 put the securing \0).
538 strcat(string_buffer_print,"<TRUNCATED>");
541 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
546 string_buffer_print = g_strdup(string_buffer);
549 string_buffer_print = g_strdup("<DATA>");
554 string_buffer_print = g_strdup("<EMPTY>");
558 string_item = proto_tree_add_text(tree, tvb,offset+0, tvb_length_remaining(tvb, offset),
559 "%s: %s", proto_registrar_get_name(hfindex), string_buffer_print);
561 proto_tree_add_string_hidden(tree, hfindex, tvb, offset+4,
562 string_length_copy, string_buffer);
565 string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
568 if (length_truncated) {
570 proto_tree_add_text(string_tree, tvb,
571 offset, tvb_length_remaining(tvb, offset),
572 "length: <TRUNCATED>");
573 offset = tvb_length(tvb);
576 proto_tree_add_text(string_tree, tvb,offset+0,4,
577 "length: %u", string_length);
582 proto_tree_add_string_format(string_tree,
583 hfindex, tvb, offset, string_length_copy,
585 "contents: %s", string_buffer_print);
587 proto_tree_add_bytes_format(string_tree,
588 hfindex, tvb, offset, string_length_copy,
590 "contents: %s", string_buffer_print);
593 offset += string_length_copy;
596 if (fill_truncated) {
597 proto_tree_add_text(string_tree, tvb,
598 offset,fill_length_copy,
599 "fill bytes: opaque data<TRUNCATED>");
602 proto_tree_add_text(string_tree, tvb,
603 offset,fill_length_copy,
604 "fill bytes: opaque data");
607 offset += fill_length_copy;
612 proto_item_set_len(string_item, offset - old_offset);
615 if (string_buffer != NULL) g_free (string_buffer );
616 if (string_buffer_print != NULL) {
617 if (string_buffer_ret != NULL)
618 *string_buffer_ret = string_buffer_print;
620 g_free (string_buffer_print);
627 dissect_rpc_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
628 int hfindex, int offset, char **string_buffer_ret)
630 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree,
631 hfindex, TRUE, string_buffer_ret);
637 dissect_rpc_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
638 int hfindex, int offset)
640 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree, hfindex,
648 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
649 int offset, dissect_function_t *rpc_list_dissector)
651 guint32 value_follows;
654 value_follows = tvb_get_ntohl(tvb, offset+0);
655 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
656 offset+0, 4, value_follows);
658 if (value_follows == 1) {
659 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
670 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
671 int offset, dissect_function_t *rpc_array_dissector,
674 proto_item* lock_item;
675 proto_tree* lock_tree;
677 int old_offset = offset;
679 num = tvb_get_ntohl(tvb, offset);
682 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
689 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset,
692 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
694 offset = dissect_rpc_uint32(tvb, pinfo, lock_tree,
695 hf_rpc_array_len, offset);
698 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
701 proto_item_set_len(lock_item, offset-old_offset);
706 dissect_rpc_authunix_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
715 proto_tree *gtree = NULL;
717 stamp = tvb_get_ntohl(tvb,offset+0);
719 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
723 offset = dissect_rpc_string(tvb, pinfo, tree,
724 hf_rpc_auth_machinename, offset, NULL);
726 uid = tvb_get_ntohl(tvb,offset+0);
728 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
732 gid = tvb_get_ntohl(tvb,offset+0);
734 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
738 gids_count = tvb_get_ntohl(tvb,offset+0);
740 gitem = proto_tree_add_text(tree, tvb,
741 offset, 4+gids_count*4, "Auxiliary GIDs");
742 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
746 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
747 gids_entry = tvb_get_ntohl(tvb,offset+0);
749 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
750 offset, 4, gids_entry);
753 /* how can I NOW change the gitem to print a list with
754 the first 16 gids? */
760 dissect_rpc_authgss_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
767 agc_v = tvb_get_ntohl(tvb, offset+0);
769 proto_tree_add_uint(tree, hf_rpc_authgss_v,
770 tvb, offset+0, 4, agc_v);
773 agc_proc = tvb_get_ntohl(tvb, offset+0);
775 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
776 tvb, offset+0, 4, agc_proc);
779 agc_seq = tvb_get_ntohl(tvb, offset+0);
781 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
782 tvb, offset+0, 4, agc_seq);
785 agc_svc = tvb_get_ntohl(tvb, offset+0);
787 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
788 tvb, offset+0, 4, agc_svc);
791 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
798 dissect_rpc_authdes_desblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
799 int hfindex, int offset)
804 value_high = tvb_get_ntohl(tvb, offset + 0);
805 value_low = tvb_get_ntohl(tvb, offset + 4);
808 proto_tree_add_text(tree, tvb, offset, 8,
809 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
817 dissect_rpc_authdes_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
823 adc_namekind = tvb_get_ntohl(tvb, offset+0);
825 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
826 tvb, offset+0, 4, adc_namekind);
831 case AUTHDES_NAMEKIND_FULLNAME:
832 offset = dissect_rpc_string(tvb, pinfo, tree,
833 hf_rpc_authdes_netname, offset, NULL);
834 offset = dissect_rpc_authdes_desblock(tvb, pinfo, tree,
835 hf_rpc_authdes_convkey, offset);
836 window = tvb_get_ntohl(tvb, offset+0);
837 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
842 case AUTHDES_NAMEKIND_NICKNAME:
843 nickname = tvb_get_ntohl(tvb, offset+0);
844 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
854 dissect_rpc_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
862 flavor = tvb_get_ntohl(tvb,offset+0);
863 length = tvb_get_ntohl(tvb,offset+4);
864 length = rpc_roundup(length);
867 citem = proto_tree_add_text(tree, tvb, offset,
868 8+length, "Credentials");
869 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
870 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
871 offset+0, 4, flavor);
872 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
873 offset+4, 4, length);
877 dissect_rpc_authunix_cred(tvb, pinfo, ctree, offset+8);
885 dissect_rpc_authdes_cred(tvb, pinfo, ctree, offset+8);
889 dissect_rpc_authgss_cred(tvb, pinfo, ctree, offset+8);
893 proto_tree_add_text(ctree, tvb, offset+8,
894 length,"opaque data");
898 offset += 8 + length;
903 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
904 * verifier we're decoding (CALL or REPLY).
907 dissect_rpc_verf(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset, int msg_type)
915 flavor = tvb_get_ntohl(tvb,offset+0);
916 length = tvb_get_ntohl(tvb,offset+4);
917 length = rpc_roundup(length);
920 vitem = proto_tree_add_text(tree, tvb, offset,
921 8+length, "Verifier");
922 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
923 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
924 offset+0, 4, flavor);
928 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
929 offset+4, 4, length);
930 dissect_rpc_authunix_cred(tvb, pinfo, vtree, offset+8);
933 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
934 offset+4, 4, length);
936 if (msg_type == RPC_CALL)
940 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
941 hf_rpc_authdes_timestamp, offset+8);
942 window = tvb_get_ntohl(tvb, offset+16);
943 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
944 offset+16, 4, window);
948 /* must be an RPC_REPLY */
951 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
952 hf_rpc_authdes_timeverf, offset+8);
953 nickname = tvb_get_ntohl(tvb, offset+16);
954 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
955 offset+16, 4, nickname);
959 dissect_rpc_data(tvb, pinfo, vtree,
960 hf_rpc_authgss_checksum, offset+4);
963 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
964 offset+4, 4, length);
966 proto_tree_add_text(vtree, tvb, offset+8,
967 length, "opaque data");
971 offset += 8 + length;
977 dissect_rpc_authgss_initarg(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
979 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
985 dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
987 int major, minor, window;
989 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
992 major = tvb_get_ntohl(tvb,offset+0);
994 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
998 minor = tvb_get_ntohl(tvb,offset+0);
1000 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1001 offset+0, 4, minor);
1004 window = tvb_get_ntohl(tvb,offset+0);
1006 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1007 offset+0, 4, window);
1010 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1018 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1019 int offset, dissect_function_t* dissect_function, const char *progname)
1021 const char *saved_proto;
1023 if (dissect_function != NULL) {
1024 /* set the current protocol name */
1025 saved_proto = pinfo->current_proto;
1026 if (progname != NULL)
1027 pinfo->current_proto = progname;
1029 /* call the dissector for the next level */
1030 offset = dissect_function(tvb, offset, pinfo, tree);
1032 /* restore the protocol name */
1033 pinfo->current_proto = saved_proto;
1041 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1042 proto_tree *tree, int offset,
1043 dissect_function_t* dissect_function,
1044 const char *progname)
1046 guint32 length, seq;
1049 proto_tree *gtree = NULL;
1051 length = tvb_get_ntohl(tvb, offset+0);
1052 length = rpc_roundup(length);
1053 seq = tvb_get_ntohl(tvb, offset+4);
1056 gitem = proto_tree_add_text(tree, tvb, offset,
1057 4+length, "GSS Data");
1058 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1059 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1060 tvb, offset+0, 4, length);
1061 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1062 tvb, offset+4, 4, seq);
1066 if (dissect_function != NULL) {
1068 call_dissect_function(tvb, pinfo, gtree, offset,
1069 dissect_function, progname);
1071 offset += length - 4;
1072 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_checksum,
1079 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1081 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_data,
1087 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1090 * Record this call in a hash table, similar to the hash table for
1091 * direct calls, so we can find it when dissecting an indirect call reply.
1094 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1095 int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1097 conversation_t* conversation;
1098 static address null_address = { AT_NONE, 0, NULL };
1099 rpc_proc_info_key key;
1100 rpc_proc_info_value *value;
1101 rpc_call_info_value *rpc_call;
1102 rpc_call_info_key rpc_call_key;
1103 rpc_call_info_key *new_rpc_call_key;
1104 dissect_function_t *dissect_function = NULL;
1109 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1110 dissect_function = value->dissect_call;
1112 /* Keep track of the address and port whence the call came,
1113 and the port to which the call is being sent, so that
1114 we can match up calls with replies.
1116 If the transport is connection-oriented (we check, for
1117 now, only for "pinfo->ptype" of PT_TCP), we take
1118 into account the address from which the call was sent
1119 and the address to which the call was sent, because
1120 the addresses of the two endpoints should be the same
1121 for all calls and replies.
1123 If the transport is connectionless, we don't worry
1124 about the address to which the call was sent and from
1125 which the reply was sent, because there's no
1126 guarantee that the reply will come from the address
1127 to which the call was sent. */
1128 if (pinfo->ptype == PT_TCP) {
1129 conversation = find_conversation(&pinfo->src,
1130 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1131 pinfo->destport, 0);
1134 * XXX - can we just use NO_ADDR_B? Unfortunately,
1135 * you currently still have to pass a non-null
1136 * pointer for the second address argument even
1139 conversation = find_conversation(&pinfo->src,
1140 &null_address, pinfo->ptype, pinfo->srcport,
1141 pinfo->destport, 0);
1143 if (conversation == NULL) {
1144 /* It's not part of any conversation - create a new
1147 XXX - this should never happen, as we should've
1148 created a conversation for it in the RPC
1150 if (pinfo->ptype == PT_TCP) {
1151 conversation = conversation_new(&pinfo->src,
1152 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1153 pinfo->destport, 0);
1155 conversation = conversation_new(&pinfo->src,
1156 &null_address, pinfo->ptype, pinfo->srcport,
1157 pinfo->destport, 0);
1161 /* Make the dissector for this conversation the non-heuristic
1163 conversation_set_dissector(conversation,
1164 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1166 /* Prepare the key data.
1168 Dissectors for RPC procedure calls and replies shouldn't
1169 create new tvbuffs, and we don't create one ourselves,
1170 so we should have been handed the tvbuff for this RPC call;
1171 as such, the XID is at offset 0 in this tvbuff. */
1172 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1173 rpc_call_key.conversation = conversation;
1175 /* look up the request */
1176 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1177 if (rpc_call == NULL) {
1178 /* We didn't find it; create a new entry.
1179 Prepare the value data.
1180 Not all of it is needed for handling indirect
1181 calls, so we set a bunch of items to 0. */
1182 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1183 *new_rpc_call_key = rpc_call_key;
1184 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1185 rpc_call->req_num = 0;
1186 rpc_call->rep_num = 0;
1187 rpc_call->prog = prog;
1188 rpc_call->vers = vers;
1189 rpc_call->proc = proc;
1192 * XXX - what about RPCSEC_GSS?
1193 * Do we have to worry about it?
1195 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1196 rpc_call->gss_proc = 0;
1197 rpc_call->gss_svc = 0;
1198 rpc_call->proc_info = value;
1200 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1205 /* We don't know the procedure.
1206 Happens only with strange program versions or
1207 non-existing dissectors.
1208 Just show the arguments as opaque data. */
1209 offset = dissect_rpc_data(tvb, pinfo, tree, args_id,
1216 proto_tree_add_text(tree, tvb, offset, 4,
1217 "Argument length: %u",
1218 tvb_get_ntohl(tvb, offset));
1222 /* Dissect the arguments */
1223 offset = call_dissect_function(tvb, pinfo, tree, offset,
1224 dissect_function, NULL);
1229 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1233 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1234 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1236 conversation_t* conversation;
1237 static address null_address = { AT_NONE, 0, NULL };
1238 rpc_call_info_key rpc_call_key;
1239 rpc_call_info_value *rpc_call;
1240 char *procname = NULL;
1241 char procname_static[20];
1242 dissect_function_t *dissect_function = NULL;
1244 /* Look for the matching call in the hash table of indirect
1245 calls. A reply must match a call that we've seen, and the
1246 reply must be sent to the same port and address that the
1247 call came from, and must come from the port to which the
1250 If the transport is connection-oriented (we check, for
1251 now, only for "pinfo->ptype" of PT_TCP), we take
1252 into account the address from which the call was sent
1253 and the address to which the call was sent, because
1254 the addresses of the two endpoints should be the same
1255 for all calls and replies.
1257 If the transport is connectionless, we don't worry
1258 about the address to which the call was sent and from
1259 which the reply was sent, because there's no
1260 guarantee that the reply will come from the address
1261 to which the call was sent. */
1262 if (pinfo->ptype == PT_TCP) {
1263 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1264 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1267 * XXX - can we just use NO_ADDR_B? Unfortunately,
1268 * you currently still have to pass a non-null
1269 * pointer for the second address argument even
1272 conversation = find_conversation(&null_address, &pinfo->dst,
1273 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1275 if (conversation == NULL) {
1276 /* We haven't seen an RPC call for that conversation,
1277 so we can't check for a reply to that call.
1278 Just show the reply stuff as opaque data. */
1279 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1284 /* The XIDs of the call and reply must match. */
1285 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1286 rpc_call_key.conversation = conversation;
1287 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1288 if (rpc_call == NULL) {
1289 /* The XID doesn't match a call from that
1290 conversation, so it's probably not an RPC reply.
1291 Just show the reply stuff as opaque data. */
1292 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1297 if (rpc_call->proc_info != NULL) {
1298 dissect_function = rpc_call->proc_info->dissect_reply;
1299 if (rpc_call->proc_info->name != NULL) {
1300 procname = rpc_call->proc_info->name;
1303 sprintf(procname_static, "proc-%u", rpc_call->proc);
1304 procname = procname_static;
1309 dissect_function = NULL;
1311 sprintf(procname_static, "proc-%u", rpc_call->proc);
1312 procname = procname_static;
1317 /* Put the program, version, and procedure into the tree. */
1318 proto_tree_add_uint_format(tree, prog_id, tvb,
1319 0, 0, rpc_call->prog, "Program: %s (%u)",
1320 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1321 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1322 proto_tree_add_uint_format(tree, proc_id, tvb,
1323 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1324 procname, rpc_call->proc);
1327 if (dissect_function == NULL) {
1328 /* We don't know how to dissect the reply procedure.
1329 Just show the reply stuff as opaque data. */
1330 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1336 /* Put the length of the reply value into the tree. */
1337 proto_tree_add_text(tree, tvb, offset, 4,
1338 "Argument length: %u",
1339 tvb_get_ntohl(tvb, offset));
1343 /* Dissect the return value */
1344 offset = call_dissect_function(tvb, pinfo, tree, offset,
1345 dissect_function, NULL);
1350 * Just mark this as a continuation of an earlier packet.
1353 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1355 proto_item *rpc_item;
1356 proto_tree *rpc_tree;
1358 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1359 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1360 if (check_col(pinfo->cinfo, COL_INFO))
1361 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1364 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1365 tvb_length(tvb), FALSE);
1366 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1367 proto_tree_add_text(rpc_tree, tvb, 0, tvb_length(tvb),
1368 "Continuation data");
1373 dissect_rpc_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1374 proto_tree *tree, gboolean use_rm, guint32 rpc_rm)
1377 rpc_call_info_key rpc_call_key;
1378 rpc_call_info_value *rpc_call = NULL;
1379 rpc_prog_info_value *rpc_prog = NULL;
1380 rpc_prog_info_key rpc_prog_key;
1383 unsigned int rpcvers;
1384 unsigned int prog = 0;
1385 unsigned int vers = 0;
1386 unsigned int proc = 0;
1387 flavor_t flavor = FLAVOR_UNKNOWN;
1388 unsigned int gss_proc = 0;
1389 unsigned int gss_svc = 0;
1393 unsigned int reply_state;
1394 unsigned int accept_state;
1395 unsigned int reject_state;
1397 char *msg_type_name = NULL;
1398 char *progname = NULL;
1399 char *procname = NULL;
1400 static char procname_static[20];
1402 unsigned int vers_low;
1403 unsigned int vers_high;
1405 unsigned int auth_state;
1407 proto_item *rpc_item=NULL;
1408 proto_tree *rpc_tree = NULL;
1410 proto_item *pitem=NULL;
1411 proto_tree *ptree = NULL;
1412 int offset_old = offset;
1414 rpc_call_info_key *new_rpc_call_key;
1415 rpc_proc_info_key key;
1416 rpc_proc_info_value *value = NULL;
1417 conversation_t* conversation;
1418 static address null_address = { AT_NONE, 0, NULL };
1421 dissect_function_t *dissect_function = NULL;
1424 * Check to see whether this looks like an RPC call or reply.
1426 if (!tvb_bytes_exist(tvb, offset, 8)) {
1427 /* Captured data in packet isn't enough to let us tell. */
1431 /* both directions need at least this */
1432 msg_type = tvb_get_ntohl(tvb, offset + 4);
1437 /* check for RPC call */
1438 if (!tvb_bytes_exist(tvb, offset, 16)) {
1439 /* Captured data in packet isn't enough to let us
1444 /* XID can be anything, we don't check it.
1445 We already have the message type.
1446 Check whether an RPC version number of 2 is in the
1447 location where it would be, and that an RPC program
1448 number we know about is in the location where it would be. */
1449 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1450 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1451 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1453 /* They're not, so it's probably not an RPC call. */
1459 /* Check for RPC reply. A reply must match a call that
1460 we've seen, and the reply must be sent to the same
1461 port and address that the call came from, and must
1462 come from the port to which the call was sent.
1464 If the transport is connection-oriented (we check, for
1465 now, only for "pinfo->ptype" of PT_TCP), we take
1466 into account the address from which the call was sent
1467 and the address to which the call was sent, because
1468 the addresses of the two endpoints should be the same
1469 for all calls and replies.
1471 If the transport is connectionless, we don't worry
1472 about the address to which the call was sent and from
1473 which the reply was sent, because there's no
1474 guarantee that the reply will come from the address
1475 to which the call was sent. */
1476 if (pinfo->ptype == PT_TCP) {
1477 conversation = find_conversation(&pinfo->src,
1478 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1479 pinfo->destport, 0);
1482 * XXX - can we just use NO_ADDR_B? Unfortunately,
1483 * you currently still have to pass a non-null
1484 * pointer for the second address argument even
1487 conversation = find_conversation(&null_address,
1488 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1489 pinfo->destport, 0);
1491 if (conversation == NULL) {
1492 /* We haven't seen an RPC call for that conversation,
1493 so we can't check for a reply to that call. */
1497 /* The XIDs of the call and reply must match. */
1498 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1499 rpc_call_key.conversation = conversation;
1500 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1501 if (rpc_call == NULL) {
1502 /* The XID doesn't match a call from that
1503 conversation, so it's probably not an RPC reply. */
1506 /* pass rpc_info to subdissectors */
1507 rpc_call->request=FALSE;
1508 pinfo->private_data=rpc_call;
1512 /* The putative message type field contains neither
1513 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1518 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1519 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1520 if (check_col(pinfo->cinfo, COL_INFO))
1521 col_clear(pinfo->cinfo, COL_INFO);
1524 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1525 tvb_length(tvb), FALSE);
1527 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1531 if (use_rm && rpc_tree) {
1532 proto_tree_add_boolean(rpc_tree,hf_rpc_lastfrag, tvb,
1533 offset-4, 4, (rpc_rm >> 31) & 0x1);
1534 proto_tree_add_uint(rpc_tree,hf_rpc_fraglen, tvb,
1535 offset-4, 4, rpc_rm & RPC_RM_FRAGLEN);
1538 xid = tvb_get_ntohl(tvb, offset + 0);
1540 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1541 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1544 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1546 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1547 offset+4, 4, msg_type);
1555 /* we know already the proto-entry, the ETT-const,
1557 proto = rpc_prog->proto;
1558 ett = rpc_prog->ett;
1559 progname = rpc_prog->progname;
1561 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1563 proto_tree_add_uint(rpc_tree,
1564 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1567 prog = tvb_get_ntohl(tvb, offset + 4);
1570 proto_tree_add_uint_format(rpc_tree,
1571 hf_rpc_program, tvb, offset+4, 4, prog,
1572 "Program: %s (%u)", progname, prog);
1575 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1576 /* Set the protocol name to the underlying
1578 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1581 vers = tvb_get_ntohl(tvb, offset+8);
1583 proto_tree_add_uint(rpc_tree,
1584 hf_rpc_programversion, tvb, offset+8, 4, vers);
1587 proc = tvb_get_ntohl(tvb, offset+12);
1593 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1594 dissect_function = value->dissect_call;
1595 procname = value->name;
1598 /* happens only with strange program versions or
1599 non-existing dissectors */
1601 dissect_function = NULL;
1603 sprintf(procname_static, "proc-%u", proc);
1604 procname = procname_static;
1608 proto_tree_add_uint_format(rpc_tree,
1609 hf_rpc_procedure, tvb, offset+12, 4, proc,
1610 "Procedure: %s (%u)", procname, proc);
1613 if (check_col(pinfo->cinfo, COL_INFO)) {
1614 col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1621 /* Check for RPCSEC_GSS */
1622 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1623 switch (tvb_get_ntohl(tvb, offset+16)) {
1627 * It's GSS-API authentication...
1629 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1631 * ...and we have the procedure
1632 * and service information for it.
1634 flavor = FLAVOR_GSSAPI;
1635 gss_proc = tvb_get_ntohl(tvb, offset+28);
1636 gss_svc = tvb_get_ntohl(tvb, offset+36);
1639 * ...but the procedure and service
1640 * information isn't available.
1642 flavor = FLAVOR_GSSAPI_NO_INFO;
1648 * It's not GSS-API authentication.
1650 flavor = FLAVOR_NOT_GSSAPI;
1655 /* Keep track of the address and port whence the call came,
1656 and the port to which the call is being sent, so that
1657 we can match up calls with replies.
1659 If the transport is connection-oriented (we check, for
1660 now, only for "pinfo->ptype" of PT_TCP), we take
1661 into account the address from which the call was sent
1662 and the address to which the call was sent, because
1663 the addresses of the two endpoints should be the same
1664 for all calls and replies.
1666 If the transport is connectionless, we don't worry
1667 about the address to which the call was sent and from
1668 which the reply was sent, because there's no
1669 guarantee that the reply will come from the address
1670 to which the call was sent. */
1671 if (pinfo->ptype == PT_TCP) {
1672 conversation = find_conversation(&pinfo->src,
1673 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1674 pinfo->destport, 0);
1677 * XXX - can we just use NO_ADDR_B? Unfortunately,
1678 * you currently still have to pass a non-null
1679 * pointer for the second address argument even
1682 conversation = find_conversation(&pinfo->src,
1683 &null_address, pinfo->ptype, pinfo->srcport,
1684 pinfo->destport, 0);
1686 if (conversation == NULL) {
1687 /* It's not part of any conversation - create a new
1689 if (pinfo->ptype == PT_TCP) {
1690 conversation = conversation_new(&pinfo->src,
1691 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1692 pinfo->destport, 0);
1694 conversation = conversation_new(&pinfo->src,
1695 &null_address, pinfo->ptype, pinfo->srcport,
1696 pinfo->destport, 0);
1700 /* Make the dissector for this conversation the non-heuristic
1702 conversation_set_dissector(conversation,
1703 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1705 /* prepare the key data */
1706 rpc_call_key.xid = xid;
1707 rpc_call_key.conversation = conversation;
1709 /* look up the request */
1710 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1711 if (rpc_call != NULL) {
1712 /* We've seen a request with this XID, with the same
1713 source and destination, before - but was it
1715 if (pinfo->fd->num != rpc_call->req_num) {
1716 /* No, so it's a duplicate request.
1718 if (check_col(pinfo->cinfo, COL_INFO)) {
1719 col_append_fstr(pinfo->cinfo, COL_INFO,
1720 " dup XID 0x%x", xid);
1722 proto_tree_add_uint_hidden(rpc_tree,
1723 hf_rpc_dup, tvb, 0,0, xid);
1724 proto_tree_add_uint_hidden(rpc_tree,
1725 hf_rpc_call_dup, tvb, 0,0, xid);
1731 /* Prepare the value data.
1732 "req_num" and "rep_num" are frame numbers;
1733 frame numbers are 1-origin, so we use 0
1734 to mean "we don't yet know in which frame
1735 the reply for this call appears". */
1736 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1737 *new_rpc_call_key = rpc_call_key;
1738 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1739 rpc_call->req_num = pinfo->fd->num;
1740 rpc_call->rep_num = 0;
1741 rpc_call->prog = prog;
1742 rpc_call->vers = vers;
1743 rpc_call->proc = proc;
1744 rpc_call->xid = xid;
1745 rpc_call->flavor = flavor;
1746 rpc_call->gss_proc = gss_proc;
1747 rpc_call->gss_svc = gss_svc;
1748 rpc_call->proc_info = value;
1749 rpc_call->req_time.secs=pinfo->fd->abs_secs;
1750 rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
1753 g_hash_table_insert(rpc_calls, new_rpc_call_key,
1759 offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset);
1760 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1762 /* pass rpc_info to subdissectors */
1763 rpc_call->request=TRUE;
1764 pinfo->private_data=rpc_call;
1766 /* go to the next dissector */
1768 break; /* end of RPC call */
1771 /* we know already the type from the calling routine,
1772 and we already have "rpc_call" set above. */
1773 prog = rpc_call->prog;
1774 vers = rpc_call->vers;
1775 proc = rpc_call->proc;
1776 flavor = rpc_call->flavor;
1777 gss_proc = rpc_call->gss_proc;
1778 gss_svc = rpc_call->gss_svc;
1780 /* Indicate the frame to which this is a reply. */
1781 proto_tree_add_text(rpc_tree, tvb, 0, 0,
1782 "This is a reply to a request in frame %u",
1784 ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
1785 ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
1787 ns.nsecs+=1000000000;
1790 proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
1795 if (rpc_call->proc_info != NULL) {
1796 dissect_function = rpc_call->proc_info->dissect_reply;
1797 if (rpc_call->proc_info->name != NULL) {
1798 procname = rpc_call->proc_info->name;
1801 sprintf(procname_static, "proc-%u", proc);
1802 procname = procname_static;
1807 dissect_function = NULL;
1809 sprintf(procname_static, "proc-%u", proc);
1810 procname = procname_static;
1813 rpc_prog_key.prog = prog;
1814 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1817 progname = "Unknown";
1820 proto = rpc_prog->proto;
1821 ett = rpc_prog->ett;
1822 progname = rpc_prog->progname;
1824 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1825 /* Set the protocol name to the underlying
1827 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1831 if (check_col(pinfo->cinfo, COL_INFO)) {
1832 col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1840 proto_tree_add_uint_format(rpc_tree,
1841 hf_rpc_program, tvb, 0, 0, prog,
1842 "Program: %s (%u)", progname, prog);
1843 proto_tree_add_uint(rpc_tree,
1844 hf_rpc_programversion, tvb, 0, 0, vers);
1845 proto_tree_add_uint_format(rpc_tree,
1846 hf_rpc_procedure, tvb, 0, 0, proc,
1847 "Procedure: %s (%u)", procname, proc);
1850 if (rpc_call->rep_num == 0) {
1851 /* We have not yet seen a reply to that call, so
1852 this must be the first reply; remember its
1854 rpc_call->rep_num = pinfo->fd->num;
1856 /* We have seen a reply to this call - but was it
1858 if (rpc_call->rep_num != pinfo->fd->num) {
1859 /* No, so it's a duplicate reply.
1861 if (check_col(pinfo->cinfo, COL_INFO)) {
1862 col_append_fstr(pinfo->cinfo, COL_INFO,
1863 " dup XID 0x%x", xid);
1865 proto_tree_add_uint_hidden(rpc_tree,
1866 hf_rpc_dup, tvb, 0,0, xid);
1867 proto_tree_add_uint_hidden(rpc_tree,
1868 hf_rpc_reply_dup, tvb, 0,0, xid);
1874 reply_state = tvb_get_ntohl(tvb,offset+0);
1876 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
1877 offset+0, 4, reply_state);
1881 if (reply_state == MSG_ACCEPTED) {
1882 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1883 accept_state = tvb_get_ntohl(tvb,offset+0);
1885 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
1886 offset+0, 4, accept_state);
1889 switch (accept_state) {
1892 /* go to the next dissector */
1896 vers_low = tvb_get_ntohl(tvb,offset+0);
1897 vers_high = tvb_get_ntohl(tvb,offset+4);
1899 proto_tree_add_uint(rpc_tree,
1900 hf_rpc_programversion_min,
1901 tvb, offset+0, 4, vers_low);
1902 proto_tree_add_uint(rpc_tree,
1903 hf_rpc_programversion_max,
1904 tvb, offset+4, 4, vers_high);
1913 } else if (reply_state == MSG_DENIED) {
1914 reject_state = tvb_get_ntohl(tvb,offset+0);
1916 proto_tree_add_uint(rpc_tree,
1917 hf_rpc_state_reject, tvb, offset+0, 4,
1922 if (reject_state==RPC_MISMATCH) {
1923 vers_low = tvb_get_ntohl(tvb,offset+0);
1924 vers_high = tvb_get_ntohl(tvb,offset+4);
1926 proto_tree_add_uint(rpc_tree,
1928 tvb, offset+0, 4, vers_low);
1929 proto_tree_add_uint(rpc_tree,
1931 tvb, offset+4, 4, vers_high);
1934 } else if (reject_state==AUTH_ERROR) {
1935 auth_state = tvb_get_ntohl(tvb,offset+0);
1937 proto_tree_add_uint(rpc_tree,
1938 hf_rpc_state_auth, tvb, offset+0, 4,
1944 break; /* end of RPC reply */
1948 * The switch statement at the top returned if
1949 * this was neither an RPC call nor a reply.
1951 g_assert_not_reached();
1954 /* now we know, that RPC was shorter */
1956 proto_item_set_len(rpc_item, offset - offset_old);
1959 /* create here the program specific sub-tree */
1961 pitem = proto_tree_add_item(tree, proto, tvb,
1962 offset, tvb_length(tvb) - offset, FALSE);
1964 ptree = proto_item_add_subtree(pitem, ett);
1968 proto_tree_add_uint(ptree,
1969 hf_rpc_programversion, tvb, 0, 0, vers);
1970 proto_tree_add_uint_format(ptree,
1971 hf_rpc_procedure, tvb, 0, 0, proc,
1972 "Procedure: %s (%u)", procname, proc);
1976 if (!proto_is_protocol_enabled(proto))
1977 dissect_function = NULL;
1980 * Handle RPCSEC_GSS specially.
1984 case FLAVOR_UNKNOWN:
1986 * We don't know the authentication flavor, so we can't
1987 * dissect the payload.
1989 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
1990 "Unknown authentication flavor - cannot dissect");
1993 case FLAVOR_NOT_GSSAPI:
1995 * It's not GSS-API authentication. Just dissect the
1998 offset = call_dissect_function(tvb, pinfo, ptree, offset,
1999 dissect_function, progname);
2002 case FLAVOR_GSSAPI_NO_INFO:
2004 * It's GSS-API authentication, but we don't have the
2005 * procedure and service information, so we can't dissect
2008 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2009 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2014 * It's GSS-API authentication, and we have the procedure
2015 * and service information; process the GSS-API stuff,
2016 * and process the payload if there is any.
2020 case RPCSEC_GSS_INIT:
2021 case RPCSEC_GSS_CONTINUE_INIT:
2022 if (msg_type == RPC_CALL) {
2023 offset = dissect_rpc_authgss_initarg(tvb,
2024 pinfo, ptree, offset);
2027 offset = dissect_rpc_authgss_initres(tvb,
2028 pinfo, ptree, offset);
2032 case RPCSEC_GSS_DATA:
2033 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2034 offset = call_dissect_function(tvb,
2035 pinfo, ptree, offset,
2039 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2040 offset = dissect_rpc_authgss_integ_data(tvb,
2041 pinfo, ptree, offset,
2045 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2046 offset = dissect_rpc_authgss_priv_data(tvb,
2047 pinfo, ptree, offset);
2056 /* dissect any remaining bytes (incomplete dissection) as pure data in
2058 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, ptree);
2064 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2066 return dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0);
2070 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2072 if (!dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0))
2073 dissect_rpc_continuation(tvb, pinfo, tree);
2079 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
2081 * IS_RPC, if we dissected at least one message in its entirety
2084 * IS_NOT_RPC, if we found no RPC message.
2092 static rpc_tcp_return_t
2093 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2096 volatile int offset = 0;
2098 volatile gboolean saw_rpc = FALSE;
2099 volatile gint32 len;
2101 gint tvb_len, tvb_reported_len;
2103 const char *saved_proto;
2104 volatile gboolean rpc_succeeded;
2106 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2108 * XXX - we need to handle records that don't have the "last
2109 * fragment" bit set, and reassemble fragments.
2112 /* the first 4 bytes are special in "record marking mode" */
2113 if (!tvb_bytes_exist(tvb, offset, 4)) {
2115 * XXX - we should somehow arrange to handle
2116 * a record mark split across TCP segments.
2118 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2120 rpc_rm = tvb_get_ntohl(tvb, offset);
2122 len = rpc_rm&RPC_RM_FRAGLEN;
2125 * XXX - reject fragments bigger than 2 megabytes.
2126 * This is arbitrary, but should at least prevent
2127 * some crashes from either packets with really
2128 * large RPC-over-TCP fragments or from stuff that's
2131 if (len > 2*1024*1024)
2132 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2133 if (rpc_desegment) {
2134 seglen = tvb_length_remaining(tvb, offset + 4);
2136 if (len > seglen && pinfo->can_desegment) {
2138 * This frame doesn't have all of the
2139 * data for this message, but we can do
2142 * If this is a heuristic dissector, just
2143 * return IS_NOT_RPC - we don't want to try
2144 * to get more data, as that's too likely
2145 * to cause us to misidentify this as
2148 * If this isn't a heuristic dissector,
2149 * we've already identified this conversation
2150 * as containing RPC data, as we saw RPC
2151 * data in previous frames. Try to get
2157 pinfo->desegment_offset = offset;
2158 pinfo->desegment_len = len - seglen;
2159 return NEED_MORE_DATA;
2163 len += 4; /* include record mark */
2164 tvb_len = tvb_length_remaining(tvb, offset);
2165 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2168 if (tvb_reported_len > len)
2169 tvb_reported_len = len;
2170 msg_tvb = tvb_new_subset(tvb, offset, tvb_len,
2174 * Catch the ReportedBoundsError exception; if this
2175 * particular message happens to get a ReportedBoundsError
2176 * exception, that doesn't mean that we should stop
2177 * dissecting RPC messages within this frame or chunk
2178 * of reassembled data.
2180 * If it gets a BoundsError, we can stop, as there's
2181 * nothing more to see, so we just re-throw it.
2183 saved_proto = pinfo->current_proto;
2184 rpc_succeeded = FALSE;
2186 rpc_succeeded = dissect_rpc_message(msg_tvb, 4,
2187 pinfo, tree, TRUE, rpc_rm);
2189 CATCH(BoundsError) {
2192 CATCH(ReportedBoundsError) {
2193 if (check_col(pinfo->cinfo, COL_INFO)) {
2194 col_append_str(pinfo->cinfo, COL_INFO,
2195 "[Malformed Packet]");
2197 proto_tree_add_protocol_format(tree, proto_malformed,
2198 tvb, 0, 0, "[Malformed Packet: %s]",
2199 pinfo->current_proto );
2200 pinfo->current_proto = saved_proto;
2203 * We treat this as a "successful" dissection of
2204 * an RPC packet, as "dissect_rpc_message()"
2205 * *did* decide it was an RPC packet, throwing
2206 * an exception while dissecting it as such.
2208 rpc_succeeded = TRUE;
2216 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2220 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2222 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
2231 /* "Can't happen" */
2232 g_assert_not_reached();
2238 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2240 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
2241 dissect_rpc_continuation(tvb, pinfo, tree);
2244 /* Discard any state we've saved. */
2246 rpc_init_protocol(void)
2248 if (rpc_calls != NULL)
2249 g_hash_table_destroy(rpc_calls);
2250 if (rpc_indir_calls != NULL)
2251 g_hash_table_destroy(rpc_indir_calls);
2252 if (rpc_call_info_key_chunk != NULL)
2253 g_mem_chunk_destroy(rpc_call_info_key_chunk);
2254 if (rpc_call_info_value_chunk != NULL)
2255 g_mem_chunk_destroy(rpc_call_info_value_chunk);
2257 rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2258 rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2259 rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
2260 sizeof(rpc_call_info_key),
2261 200 * sizeof(rpc_call_info_key),
2263 rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
2264 sizeof(rpc_call_info_value),
2265 200 * sizeof(rpc_call_info_value),
2269 /* will be called once from register.c at startup time */
2271 proto_register_rpc(void)
2273 static hf_register_info hf[] = {
2274 { &hf_rpc_lastfrag, {
2275 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, BASE_NONE,
2276 &yesno, 0, "Last Fragment", HFILL }},
2277 { &hf_rpc_fraglen, {
2278 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
2279 NULL, 0, "Fragment Length", HFILL }},
2281 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
2282 NULL, 0, "XID", HFILL }},
2283 { &hf_rpc_msgtype, {
2284 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
2285 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
2286 { &hf_rpc_state_reply, {
2287 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
2288 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
2289 { &hf_rpc_state_accept, {
2290 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
2291 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
2292 { &hf_rpc_state_reject, {
2293 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
2294 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
2295 { &hf_rpc_state_auth, {
2296 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
2297 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
2298 { &hf_rpc_version, {
2299 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
2300 NULL, 0, "RPC Version", HFILL }},
2301 { &hf_rpc_version_min, {
2302 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
2303 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2304 { &hf_rpc_version_max, {
2305 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
2306 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
2307 { &hf_rpc_program, {
2308 "Program", "rpc.program", FT_UINT32, BASE_DEC,
2309 NULL, 0, "Program", HFILL }},
2310 { &hf_rpc_programversion, {
2311 "Program Version", "rpc.programversion", FT_UINT32,
2312 BASE_DEC, NULL, 0, "Program Version", HFILL }},
2313 { &hf_rpc_programversion_min, {
2314 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
2315 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2316 { &hf_rpc_programversion_max, {
2317 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
2318 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
2319 { &hf_rpc_procedure, {
2320 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
2321 NULL, 0, "Procedure", HFILL }},
2322 { &hf_rpc_auth_flavor, {
2323 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
2324 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
2325 { &hf_rpc_auth_length, {
2326 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
2327 NULL, 0, "Length", HFILL }},
2328 { &hf_rpc_auth_stamp, {
2329 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
2330 NULL, 0, "Stamp", HFILL }},
2331 { &hf_rpc_auth_uid, {
2332 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
2333 NULL, 0, "UID", HFILL }},
2334 { &hf_rpc_auth_gid, {
2335 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
2336 NULL, 0, "GID", HFILL }},
2337 { &hf_rpc_authgss_v, {
2338 "GSS Version", "rpc.authgss.version", FT_UINT32,
2339 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
2340 { &hf_rpc_authgss_proc, {
2341 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
2342 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
2343 { &hf_rpc_authgss_seq, {
2344 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
2345 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
2346 { &hf_rpc_authgss_svc, {
2347 "GSS Service", "rpc.authgss.service", FT_UINT32,
2348 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
2349 { &hf_rpc_authgss_ctx, {
2350 "GSS Context", "rpc.authgss.context", FT_BYTES,
2351 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
2352 { &hf_rpc_authgss_major, {
2353 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
2354 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
2355 { &hf_rpc_authgss_minor, {
2356 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
2357 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
2358 { &hf_rpc_authgss_window, {
2359 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
2360 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
2361 { &hf_rpc_authgss_token, {
2362 "GSS Token", "rpc.authgss.token", FT_BYTES,
2363 BASE_HEX, NULL, 0, "GSS Token", HFILL }},
2364 { &hf_rpc_authgss_data_length, {
2365 "Length", "rpc.authgss.data.length", FT_UINT32,
2366 BASE_DEC, NULL, 0, "Length", HFILL }},
2367 { &hf_rpc_authgss_data, {
2368 "GSS Data", "rpc.authgss.data", FT_BYTES,
2369 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
2370 { &hf_rpc_authgss_checksum, {
2371 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
2372 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
2373 { &hf_rpc_authdes_namekind, {
2374 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
2375 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
2376 { &hf_rpc_authdes_netname, {
2377 "Netname", "rpc.authdes.netname", FT_STRING,
2378 BASE_DEC, NULL, 0, "Netname", HFILL }},
2379 { &hf_rpc_authdes_convkey, {
2380 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
2381 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
2382 { &hf_rpc_authdes_window, {
2383 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
2384 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
2385 { &hf_rpc_authdes_nickname, {
2386 "Nickname", "rpc.authdes.nickname", FT_UINT32,
2387 BASE_HEX, NULL, 0, "Nickname", HFILL }},
2388 { &hf_rpc_authdes_timestamp, {
2389 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
2390 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
2391 { &hf_rpc_authdes_windowverf, {
2392 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
2393 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
2394 { &hf_rpc_authdes_timeverf, {
2395 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
2396 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
2397 { &hf_rpc_auth_machinename, {
2398 "Machine Name", "rpc.auth.machinename", FT_STRING,
2399 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
2401 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
2402 NULL, 0, "Duplicate Transaction", HFILL }},
2403 { &hf_rpc_call_dup, {
2404 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
2405 NULL, 0, "Duplicate Call", HFILL }},
2406 { &hf_rpc_reply_dup, {
2407 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
2408 NULL, 0, "Duplicate Reply", HFILL }},
2409 { &hf_rpc_value_follows, {
2410 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
2411 &yesno, 0, "Value Follows", HFILL }},
2412 { &hf_rpc_array_len, {
2413 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
2414 NULL, 0, "Length of RPC array", HFILL }},
2417 "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
2418 NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
2421 static gint *ett[] = {
2430 module_t *rpc_module;
2432 proto_rpc = proto_register_protocol("Remote Procedure Call",
2434 proto_register_field_array(proto_rpc, hf, array_length(hf));
2435 proto_register_subtree_array(ett, array_length(ett));
2436 register_init_routine(&rpc_init_protocol);
2437 rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
2438 rpc_handle = create_dissector_handle(dissect_rpc, proto_rpc);
2439 rpc_module = prefs_register_protocol(proto_rpc, NULL);
2440 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
2441 "Desegment all RPC over TCP commands",
2442 "Whether the RPC dissector should desegment all RPC over TCP commands",
2446 * Init the hash tables. Dissectors for RPC protocols must
2447 * have a "handoff registration" routine that registers the
2448 * protocol with RPC; they must not do it in their protocol
2449 * registration routine, as their protocol registration
2450 * routine might be called before this routine is called and
2451 * thus might be called before the hash tables are initialized,
2452 * but it's guaranteed that all protocol registration routines
2453 * will be called before any handoff registration routines
2456 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
2457 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
2461 proto_reg_handoff_rpc(void)
2463 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
2464 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
2465 data_handle = find_dissector("data");