2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.79 2002/01/07 00:59: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"
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;
387 FLAVOR_UNKNOWN, /* authentication flavor unknown */
388 FLAVOR_NOT_GSSAPI, /* flavor isn't GSSAPI */
389 FLAVOR_GSSAPI_NO_INFO, /* flavor is GSSAPI, procedure & service unknown */
390 FLAVOR_GSSAPI /* flavor is GSSAPI, procedure & service known */
393 typedef struct _rpc_call_info_value {
394 guint32 req_num; /* frame number of first request seen */
395 guint32 rep_num; /* frame number of first reply seen */
402 rpc_proc_info_value* proc_info;
404 } rpc_call_info_value;
406 static GMemChunk *rpc_call_info_value_chunk;
408 static GHashTable *rpc_calls;
410 static GHashTable *rpc_indir_calls;
414 rpc_call_equal(gconstpointer k1, gconstpointer k2)
416 rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
417 rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
419 return (key1->xid == key2->xid &&
420 key1->conversation == key2->conversation);
424 /* calculate a hash key */
426 rpc_call_hash(gconstpointer k)
428 rpc_call_info_key* key = (rpc_call_info_key*) k;
430 return key->xid + (guint32)(key->conversation);
435 rpc_roundup(unsigned int a)
437 unsigned int mod = a % 4;
438 return a + ((mod)? 4-mod : 0);
443 dissect_rpc_bool(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
444 int hfindex, int offset)
447 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
453 dissect_rpc_uint32(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
454 int hfindex, int offset)
457 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
463 dissect_rpc_uint64(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
464 int hfindex, int offset)
466 header_field_info *hfinfo;
468 hfinfo = proto_registrar_get_nth(hfindex);
469 g_assert(hfinfo->type == FT_UINT64);
471 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
478 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
479 proto_tree *tree, int hfindex, gboolean string_data,
480 char **string_buffer_ret)
482 proto_item *string_item = NULL;
483 proto_tree *string_tree = NULL;
484 int old_offset = offset;
486 int length_truncated = 0;
488 int string_truncated = 0;
489 guint32 string_length = 0;
490 guint32 string_length_full;
491 guint32 string_length_packet;
492 guint32 string_length_copy = 0;
494 int fill_truncated = 0;
495 guint32 fill_length = 0;
496 guint32 fill_length_packet = 0;
497 guint32 fill_length_copy = 0;
499 char *string_buffer = NULL;
500 char *string_buffer_print = NULL;
502 string_length = tvb_get_ntohl(tvb,offset+0);
503 string_length_full = rpc_roundup(string_length);
504 /* XXX - just let the tvbuff stuff throw an exception? */
505 string_length_packet = tvb_length_remaining(tvb, offset + 4);
506 if (string_length_packet < string_length) {
507 /* truncated string */
508 string_truncated = 1;
509 string_length_copy = string_length_packet;
512 fill_length_packet = 0;
513 fill_length_copy = 0;
516 /* full string data */
517 string_truncated = 0;
518 string_length_copy = string_length;
519 fill_length = string_length_full - string_length;
520 /* XXX - just let the tvbuff stuff throw an exception? */
521 fill_length_packet = tvb_length_remaining(tvb,
522 offset + 4 + string_length);
523 if (fill_length_packet < fill_length) {
524 /* truncated fill bytes */
525 fill_length_copy = fill_length_packet;
529 /* full fill bytes */
530 fill_length_copy = fill_length;
534 string_buffer = (char*)g_malloc(string_length_copy +
535 (string_data ? 1 : 0));
536 tvb_memcpy(tvb,string_buffer,offset+4,string_length_copy);
538 string_buffer[string_length_copy] = '\0';
540 /* calculate a nice printable string */
542 if (string_length != string_length_copy) {
544 /* alloc maximum data area */
545 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
546 /* copy over the data */
547 memcpy(string_buffer_print,string_buffer,string_length_copy);
548 /* append a 0 byte for sure printing */
549 string_buffer_print[string_length_copy] = '\0';
550 /* append <TRUNCATED> */
551 /* This way, we get the TRUNCATED even
552 in the case of totally wrong packets,
553 where \0 are inside the string.
554 TRUNCATED will appear at the
555 first \0 or at the end (where we
556 put the securing \0).
558 strcat(string_buffer_print,"<TRUNCATED>");
561 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
566 string_buffer_print = g_strdup(string_buffer);
569 string_buffer_print = g_strdup("<DATA>");
574 string_buffer_print = g_strdup("<EMPTY>");
578 string_item = proto_tree_add_text(tree, tvb,offset+0, tvb_length_remaining(tvb, offset),
579 "%s: %s", proto_registrar_get_name(hfindex), string_buffer_print);
581 proto_tree_add_string_hidden(tree, hfindex, tvb, offset+4,
582 string_length_copy, string_buffer);
585 string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
588 if (length_truncated) {
590 proto_tree_add_text(string_tree, tvb,
591 offset, tvb_length_remaining(tvb, offset),
592 "length: <TRUNCATED>");
593 offset = tvb_length(tvb);
596 proto_tree_add_text(string_tree, tvb,offset+0,4,
597 "length: %u", string_length);
602 proto_tree_add_string_format(string_tree,
603 hfindex, tvb, offset, string_length_copy,
605 "contents: %s", string_buffer_print);
607 proto_tree_add_bytes_format(string_tree,
608 hfindex, tvb, offset, string_length_copy,
610 "contents: %s", string_buffer_print);
613 offset += string_length_copy;
616 if (fill_truncated) {
617 proto_tree_add_text(string_tree, tvb,
618 offset,fill_length_copy,
619 "fill bytes: opaque data<TRUNCATED>");
622 proto_tree_add_text(string_tree, tvb,
623 offset,fill_length_copy,
624 "fill bytes: opaque data");
627 offset += fill_length_copy;
632 proto_item_set_len(string_item, offset - old_offset);
635 if (string_buffer != NULL) g_free (string_buffer );
636 if (string_buffer_print != NULL) {
637 if (string_buffer_ret != NULL)
638 *string_buffer_ret = string_buffer_print;
640 g_free (string_buffer_print);
647 dissect_rpc_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
648 int hfindex, int offset, char **string_buffer_ret)
650 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree,
651 hfindex, TRUE, string_buffer_ret);
657 dissect_rpc_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
658 int hfindex, int offset)
660 offset = dissect_rpc_opaque_data(tvb, offset, pinfo, tree, hfindex,
668 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
669 int offset, dissect_function_t *rpc_list_dissector)
671 guint32 value_follows;
674 value_follows = tvb_get_ntohl(tvb, offset+0);
675 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
676 offset+0, 4, value_follows);
678 if (value_follows == 1) {
679 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
690 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
691 int offset, dissect_function_t *rpc_array_dissector,
694 proto_item* lock_item;
695 proto_tree* lock_tree;
697 int old_offset = offset;
699 num = tvb_get_ntohl(tvb, offset);
702 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
709 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset,
712 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
714 offset = dissect_rpc_uint32(tvb, pinfo, lock_tree,
715 hf_rpc_array_len, offset);
718 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
721 proto_item_set_len(lock_item, offset-old_offset);
726 dissect_rpc_authunix_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
735 proto_tree *gtree = NULL;
737 stamp = tvb_get_ntohl(tvb,offset+0);
739 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
743 offset = dissect_rpc_string(tvb, pinfo, tree,
744 hf_rpc_auth_machinename, offset, NULL);
746 uid = tvb_get_ntohl(tvb,offset+0);
748 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
752 gid = tvb_get_ntohl(tvb,offset+0);
754 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
758 gids_count = tvb_get_ntohl(tvb,offset+0);
760 gitem = proto_tree_add_text(tree, tvb,
761 offset, 4+gids_count*4, "Auxiliary GIDs");
762 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
766 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
767 gids_entry = tvb_get_ntohl(tvb,offset+0);
769 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
770 offset, 4, gids_entry);
773 /* how can I NOW change the gitem to print a list with
774 the first 16 gids? */
780 dissect_rpc_authgss_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
787 agc_v = tvb_get_ntohl(tvb, offset+0);
789 proto_tree_add_uint(tree, hf_rpc_authgss_v,
790 tvb, offset+0, 4, agc_v);
793 agc_proc = tvb_get_ntohl(tvb, offset+0);
795 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
796 tvb, offset+0, 4, agc_proc);
799 agc_seq = tvb_get_ntohl(tvb, offset+0);
801 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
802 tvb, offset+0, 4, agc_seq);
805 agc_svc = tvb_get_ntohl(tvb, offset+0);
807 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
808 tvb, offset+0, 4, agc_svc);
811 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
818 dissect_rpc_authdes_desblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
819 int hfindex, int offset)
824 value_high = tvb_get_ntohl(tvb, offset + 0);
825 value_low = tvb_get_ntohl(tvb, offset + 4);
828 proto_tree_add_text(tree, tvb, offset, 8,
829 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
837 dissect_rpc_authdes_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
843 adc_namekind = tvb_get_ntohl(tvb, offset+0);
845 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
846 tvb, offset+0, 4, adc_namekind);
851 case AUTHDES_NAMEKIND_FULLNAME:
852 offset = dissect_rpc_string(tvb, pinfo, tree,
853 hf_rpc_authdes_netname, offset, NULL);
854 offset = dissect_rpc_authdes_desblock(tvb, pinfo, tree,
855 hf_rpc_authdes_convkey, offset);
856 window = tvb_get_ntohl(tvb, offset+0);
857 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
862 case AUTHDES_NAMEKIND_NICKNAME:
863 nickname = tvb_get_ntohl(tvb, offset+0);
864 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
874 dissect_rpc_cred(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
882 flavor = tvb_get_ntohl(tvb,offset+0);
883 length = tvb_get_ntohl(tvb,offset+4);
884 length = rpc_roundup(length);
887 citem = proto_tree_add_text(tree, tvb, offset,
888 8+length, "Credentials");
889 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
890 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
891 offset+0, 4, flavor);
892 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
893 offset+4, 4, length);
897 dissect_rpc_authunix_cred(tvb, pinfo, ctree, offset+8);
905 dissect_rpc_authdes_cred(tvb, pinfo, ctree, offset+8);
909 dissect_rpc_authgss_cred(tvb, pinfo, ctree, offset+8);
913 proto_tree_add_text(ctree, tvb, offset+8,
914 length,"opaque data");
918 offset += 8 + length;
923 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
924 * verifier we're decoding (CALL or REPLY).
927 dissect_rpc_verf(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset, int msg_type)
935 flavor = tvb_get_ntohl(tvb,offset+0);
936 length = tvb_get_ntohl(tvb,offset+4);
937 length = rpc_roundup(length);
940 vitem = proto_tree_add_text(tree, tvb, offset,
941 8+length, "Verifier");
942 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
943 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
944 offset+0, 4, flavor);
948 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
949 offset+4, 4, length);
950 dissect_rpc_authunix_cred(tvb, pinfo, vtree, offset+8);
953 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
954 offset+4, 4, length);
956 if (msg_type == RPC_CALL)
960 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
961 hf_rpc_authdes_timestamp, offset+8);
962 window = tvb_get_ntohl(tvb, offset+16);
963 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
964 offset+16, 4, window);
968 /* must be an RPC_REPLY */
971 dissect_rpc_authdes_desblock(tvb, pinfo, vtree,
972 hf_rpc_authdes_timeverf, offset+8);
973 nickname = tvb_get_ntohl(tvb, offset+16);
974 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
975 offset+16, 4, nickname);
979 dissect_rpc_data(tvb, pinfo, vtree,
980 hf_rpc_authgss_checksum, offset+4);
983 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
984 offset+4, 4, length);
986 proto_tree_add_text(vtree, tvb, offset+8,
987 length, "opaque data");
991 offset += 8 + length;
997 dissect_rpc_authgss_initarg(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
999 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1005 dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int offset)
1007 int major, minor, window;
1009 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_ctx,
1012 major = tvb_get_ntohl(tvb,offset+0);
1014 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1015 offset+0, 4, major);
1018 minor = tvb_get_ntohl(tvb,offset+0);
1020 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1021 offset+0, 4, minor);
1024 window = tvb_get_ntohl(tvb,offset+0);
1026 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1027 offset+0, 4, window);
1030 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_token,
1038 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1039 int offset, dissect_function_t* dissect_function, const char *progname)
1041 const char *saved_proto;
1043 if (dissect_function != NULL) {
1044 /* set the current protocol name */
1045 saved_proto = pinfo->current_proto;
1046 if (progname != NULL)
1047 pinfo->current_proto = progname;
1049 /* call the dissector for the next level */
1050 offset = dissect_function(tvb, offset, pinfo, tree);
1052 /* restore the protocol name */
1053 pinfo->current_proto = saved_proto;
1061 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1062 proto_tree *tree, int offset,
1063 dissect_function_t* dissect_function,
1064 const char *progname)
1066 guint32 length, seq;
1069 proto_tree *gtree = NULL;
1071 length = tvb_get_ntohl(tvb, offset+0);
1072 length = rpc_roundup(length);
1073 seq = tvb_get_ntohl(tvb, offset+4);
1076 gitem = proto_tree_add_text(tree, tvb, offset,
1077 4+length, "GSS Data");
1078 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1079 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1080 tvb, offset+0, 4, length);
1081 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1082 tvb, offset+4, 4, seq);
1086 if (dissect_function != NULL) {
1088 call_dissect_function(tvb, pinfo, gtree, offset,
1089 dissect_function, progname);
1091 offset += length - 4;
1092 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_checksum,
1099 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1101 offset = dissect_rpc_data(tvb, pinfo, tree, hf_rpc_authgss_data,
1107 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1110 * Record this call in a hash table, similar to the hash table for
1111 * direct calls, so we can find it when dissecting an indirect call reply.
1114 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1115 int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1117 conversation_t* conversation;
1118 static address null_address = { AT_NONE, 0, NULL };
1119 rpc_proc_info_key key;
1120 rpc_proc_info_value *value;
1121 rpc_call_info_value *rpc_call;
1122 rpc_call_info_key rpc_call_key;
1123 rpc_call_info_key *new_rpc_call_key;
1124 dissect_function_t *dissect_function = NULL;
1129 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1130 dissect_function = value->dissect_call;
1132 /* Keep track of the address and port whence the call came,
1133 and the port to which the call is being sent, so that
1134 we can match up calls with replies.
1136 If the transport is connection-oriented (we check, for
1137 now, only for "pinfo->ptype" of PT_TCP), we take
1138 into account the address from which the call was sent
1139 and the address to which the call was sent, because
1140 the addresses of the two endpoints should be the same
1141 for all calls and replies.
1143 If the transport is connectionless, we don't worry
1144 about the address to which the call was sent and from
1145 which the reply was sent, because there's no
1146 guarantee that the reply will come from the address
1147 to which the call was sent. */
1148 if (pinfo->ptype == PT_TCP) {
1149 conversation = find_conversation(&pinfo->src,
1150 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1151 pinfo->destport, 0);
1154 * XXX - can we just use NO_ADDR_B? Unfortunately,
1155 * you currently still have to pass a non-null
1156 * pointer for the second address argument even
1159 conversation = find_conversation(&pinfo->src,
1160 &null_address, pinfo->ptype, pinfo->srcport,
1161 pinfo->destport, 0);
1163 if (conversation == NULL) {
1164 /* It's not part of any conversation - create a new
1167 XXX - this should never happen, as we should've
1168 created a conversation for it in the RPC
1170 if (pinfo->ptype == PT_TCP) {
1171 conversation = conversation_new(&pinfo->src,
1172 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1173 pinfo->destport, 0);
1175 conversation = conversation_new(&pinfo->src,
1176 &null_address, pinfo->ptype, pinfo->srcport,
1177 pinfo->destport, 0);
1181 /* Make the dissector for this conversation the non-heuristic
1183 conversation_set_dissector(conversation,
1184 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1186 /* Prepare the key data.
1188 Dissectors for RPC procedure calls and replies shouldn't
1189 create new tvbuffs, and we don't create one ourselves,
1190 so we should have been handed the tvbuff for this RPC call;
1191 as such, the XID is at offset 0 in this tvbuff. */
1192 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1193 rpc_call_key.conversation = conversation;
1195 /* look up the request */
1196 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1197 if (rpc_call == NULL) {
1198 /* We didn't find it; create a new entry.
1199 Prepare the value data.
1200 Not all of it is needed for handling indirect
1201 calls, so we set a bunch of items to 0. */
1202 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1203 *new_rpc_call_key = rpc_call_key;
1204 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1205 rpc_call->req_num = 0;
1206 rpc_call->rep_num = 0;
1207 rpc_call->prog = prog;
1208 rpc_call->vers = vers;
1209 rpc_call->proc = proc;
1212 * XXX - what about RPCSEC_GSS?
1213 * Do we have to worry about it?
1215 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1216 rpc_call->gss_proc = 0;
1217 rpc_call->gss_svc = 0;
1218 rpc_call->proc_info = value;
1220 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1225 /* We don't know the procedure.
1226 Happens only with strange program versions or
1227 non-existing dissectors.
1228 Just show the arguments as opaque data. */
1229 offset = dissect_rpc_data(tvb, pinfo, tree, args_id,
1236 proto_tree_add_text(tree, tvb, offset, 4,
1237 "Argument length: %u",
1238 tvb_get_ntohl(tvb, offset));
1242 /* Dissect the arguments */
1243 offset = call_dissect_function(tvb, pinfo, tree, offset,
1244 dissect_function, NULL);
1249 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1253 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1254 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1256 conversation_t* conversation;
1257 static address null_address = { AT_NONE, 0, NULL };
1258 rpc_call_info_key rpc_call_key;
1259 rpc_call_info_value *rpc_call;
1260 char *procname = NULL;
1261 char procname_static[20];
1262 dissect_function_t *dissect_function = NULL;
1264 /* Look for the matching call in the hash table of indirect
1265 calls. A reply must match a call that we've seen, and the
1266 reply must be sent to the same port and address that the
1267 call came from, and must come from the port to which the
1270 If the transport is connection-oriented (we check, for
1271 now, only for "pinfo->ptype" of PT_TCP), we take
1272 into account the address from which the call was sent
1273 and the address to which the call was sent, because
1274 the addresses of the two endpoints should be the same
1275 for all calls and replies.
1277 If the transport is connectionless, we don't worry
1278 about the address to which the call was sent and from
1279 which the reply was sent, because there's no
1280 guarantee that the reply will come from the address
1281 to which the call was sent. */
1282 if (pinfo->ptype == PT_TCP) {
1283 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1284 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1287 * XXX - can we just use NO_ADDR_B? Unfortunately,
1288 * you currently still have to pass a non-null
1289 * pointer for the second address argument even
1292 conversation = find_conversation(&null_address, &pinfo->dst,
1293 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1295 if (conversation == NULL) {
1296 /* We haven't seen an RPC call for that conversation,
1297 so we can't check for a reply to that call.
1298 Just show the reply stuff as opaque data. */
1299 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1304 /* The XIDs of the call and reply must match. */
1305 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1306 rpc_call_key.conversation = conversation;
1307 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1308 if (rpc_call == NULL) {
1309 /* The XID doesn't match a call from that
1310 conversation, so it's probably not an RPC reply.
1311 Just show the reply stuff as opaque data. */
1312 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1317 if (rpc_call->proc_info != NULL) {
1318 dissect_function = rpc_call->proc_info->dissect_reply;
1319 if (rpc_call->proc_info->name != NULL) {
1320 procname = rpc_call->proc_info->name;
1323 sprintf(procname_static, "proc-%u", rpc_call->proc);
1324 procname = procname_static;
1329 dissect_function = NULL;
1331 sprintf(procname_static, "proc-%u", rpc_call->proc);
1332 procname = procname_static;
1337 /* Put the program, version, and procedure into the tree. */
1338 proto_tree_add_uint_format(tree, prog_id, tvb,
1339 0, 0, rpc_call->prog, "Program: %s (%u)",
1340 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1341 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1342 proto_tree_add_uint_format(tree, proc_id, tvb,
1343 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1344 procname, rpc_call->proc);
1347 if (dissect_function == NULL) {
1348 /* We don't know how to dissect the reply procedure.
1349 Just show the reply stuff as opaque data. */
1350 offset = dissect_rpc_data(tvb, pinfo, tree, result_id,
1356 /* Put the length of the reply value into the tree. */
1357 proto_tree_add_text(tree, tvb, offset, 4,
1358 "Argument length: %u",
1359 tvb_get_ntohl(tvb, offset));
1363 /* Dissect the return value */
1364 offset = call_dissect_function(tvb, pinfo, tree, offset,
1365 dissect_function, NULL);
1370 * Just mark this as a continuation of an earlier packet.
1373 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1375 proto_item *rpc_item;
1376 proto_tree *rpc_tree;
1378 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1379 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1380 if (check_col(pinfo->cinfo, COL_INFO))
1381 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1384 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1385 tvb_length(tvb), FALSE);
1386 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1387 proto_tree_add_text(rpc_tree, tvb, 0, tvb_length(tvb),
1388 "Continuation data");
1393 dissect_rpc_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
1394 proto_tree *tree, gboolean use_rm, guint32 rpc_rm)
1397 rpc_call_info_key rpc_call_key;
1398 rpc_call_info_value *rpc_call = NULL;
1399 rpc_prog_info_value *rpc_prog = NULL;
1400 rpc_prog_info_key rpc_prog_key;
1403 unsigned int rpcvers;
1404 unsigned int prog = 0;
1405 unsigned int vers = 0;
1406 unsigned int proc = 0;
1407 flavor_t flavor = FLAVOR_UNKNOWN;
1408 unsigned int gss_proc = 0;
1409 unsigned int gss_svc = 0;
1413 unsigned int reply_state;
1414 unsigned int accept_state;
1415 unsigned int reject_state;
1417 char *msg_type_name = NULL;
1418 char *progname = NULL;
1419 char *procname = NULL;
1420 static char procname_static[20];
1422 unsigned int vers_low;
1423 unsigned int vers_high;
1425 unsigned int auth_state;
1427 proto_item *rpc_item=NULL;
1428 proto_tree *rpc_tree = NULL;
1430 proto_item *pitem=NULL;
1431 proto_tree *ptree = NULL;
1432 int offset_old = offset;
1434 rpc_call_info_key *new_rpc_call_key;
1435 rpc_proc_info_key key;
1436 rpc_proc_info_value *value = NULL;
1437 conversation_t* conversation;
1438 static address null_address = { AT_NONE, 0, NULL };
1441 dissect_function_t *dissect_function = NULL;
1444 * Check to see whether this looks like an RPC call or reply.
1446 if (!tvb_bytes_exist(tvb, offset, 8)) {
1447 /* Captured data in packet isn't enough to let us tell. */
1451 /* both directions need at least this */
1452 msg_type = tvb_get_ntohl(tvb, offset + 4);
1457 /* check for RPC call */
1458 if (!tvb_bytes_exist(tvb, offset, 16)) {
1459 /* Captured data in packet isn't enough to let us
1464 /* XID can be anything, we don't check it.
1465 We already have the message type.
1466 Check whether an RPC version number of 2 is in the
1467 location where it would be, and that an RPC program
1468 number we know about is in the location where it would be. */
1469 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1470 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1471 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1473 /* They're not, so it's probably not an RPC call. */
1479 /* Check for RPC reply. A reply must match a call that
1480 we've seen, and the reply must be sent to the same
1481 port and address that the call came from, and must
1482 come from the port to which the call was sent.
1484 If the transport is connection-oriented (we check, for
1485 now, only for "pinfo->ptype" of PT_TCP), we take
1486 into account the address from which the call was sent
1487 and the address to which the call was sent, because
1488 the addresses of the two endpoints should be the same
1489 for all calls and replies.
1491 If the transport is connectionless, we don't worry
1492 about the address to which the call was sent and from
1493 which the reply was sent, because there's no
1494 guarantee that the reply will come from the address
1495 to which the call was sent. */
1496 if (pinfo->ptype == PT_TCP) {
1497 conversation = find_conversation(&pinfo->src,
1498 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1499 pinfo->destport, 0);
1502 * XXX - can we just use NO_ADDR_B? Unfortunately,
1503 * you currently still have to pass a non-null
1504 * pointer for the second address argument even
1507 conversation = find_conversation(&null_address,
1508 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1509 pinfo->destport, 0);
1511 if (conversation == NULL) {
1512 /* We haven't seen an RPC call for that conversation,
1513 so we can't check for a reply to that call. */
1517 /* The XIDs of the call and reply must match. */
1518 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1519 rpc_call_key.conversation = conversation;
1520 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1521 if (rpc_call == NULL) {
1522 /* The XID doesn't match a call from that
1523 conversation, so it's probably not an RPC reply. */
1529 /* The putative message type field contains neither
1530 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1535 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1536 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1537 if (check_col(pinfo->cinfo, COL_INFO))
1538 col_clear(pinfo->cinfo, COL_INFO);
1541 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0,
1542 tvb_length(tvb), FALSE);
1544 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1548 if (use_rm && rpc_tree) {
1549 proto_tree_add_boolean(rpc_tree,hf_rpc_lastfrag, tvb,
1550 offset-4, 4, (rpc_rm >> 31) & 0x1);
1551 proto_tree_add_uint(rpc_tree,hf_rpc_fraglen, tvb,
1552 offset-4, 4, rpc_rm & RPC_RM_FRAGLEN);
1555 xid = tvb_get_ntohl(tvb, offset + 0);
1557 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1558 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1561 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1563 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1564 offset+4, 4, msg_type);
1572 /* we know already the proto-entry, the ETT-const,
1574 proto = rpc_prog->proto;
1575 ett = rpc_prog->ett;
1576 progname = rpc_prog->progname;
1578 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1580 proto_tree_add_uint(rpc_tree,
1581 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1584 prog = tvb_get_ntohl(tvb, offset + 4);
1587 proto_tree_add_uint_format(rpc_tree,
1588 hf_rpc_program, tvb, offset+4, 4, prog,
1589 "Program: %s (%u)", progname, prog);
1592 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1593 /* Set the protocol name to the underlying
1595 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1598 vers = tvb_get_ntohl(tvb, offset+8);
1600 proto_tree_add_uint(rpc_tree,
1601 hf_rpc_programversion, tvb, offset+8, 4, vers);
1604 proc = tvb_get_ntohl(tvb, offset+12);
1610 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1611 dissect_function = value->dissect_call;
1612 procname = value->name;
1615 /* happens only with strange program versions or
1616 non-existing dissectors */
1618 dissect_function = NULL;
1620 sprintf(procname_static, "proc-%u", proc);
1621 procname = procname_static;
1625 proto_tree_add_uint_format(rpc_tree,
1626 hf_rpc_procedure, tvb, offset+12, 4, proc,
1627 "Procedure: %s (%u)", procname, proc);
1630 if (check_col(pinfo->cinfo, COL_INFO)) {
1631 col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1638 /* Check for RPCSEC_GSS */
1639 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1640 switch (tvb_get_ntohl(tvb, offset+16)) {
1644 * It's GSS-API authentication...
1646 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1648 * ...and we have the procedure
1649 * and service information for it.
1651 flavor = FLAVOR_GSSAPI;
1652 gss_proc = tvb_get_ntohl(tvb, offset+28);
1653 gss_svc = tvb_get_ntohl(tvb, offset+36);
1656 * ...but the procedure and service
1657 * information isn't available.
1659 flavor = FLAVOR_GSSAPI_NO_INFO;
1665 * It's not GSS-API authentication.
1667 flavor = FLAVOR_NOT_GSSAPI;
1672 /* Keep track of the address and port whence the call came,
1673 and the port to which the call is being sent, so that
1674 we can match up calls with replies.
1676 If the transport is connection-oriented (we check, for
1677 now, only for "pinfo->ptype" of PT_TCP), we take
1678 into account the address from which the call was sent
1679 and the address to which the call was sent, because
1680 the addresses of the two endpoints should be the same
1681 for all calls and replies.
1683 If the transport is connectionless, we don't worry
1684 about the address to which the call was sent and from
1685 which the reply was sent, because there's no
1686 guarantee that the reply will come from the address
1687 to which the call was sent. */
1688 if (pinfo->ptype == PT_TCP) {
1689 conversation = find_conversation(&pinfo->src,
1690 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1691 pinfo->destport, 0);
1694 * XXX - can we just use NO_ADDR_B? Unfortunately,
1695 * you currently still have to pass a non-null
1696 * pointer for the second address argument even
1699 conversation = find_conversation(&pinfo->src,
1700 &null_address, pinfo->ptype, pinfo->srcport,
1701 pinfo->destport, 0);
1703 if (conversation == NULL) {
1704 /* It's not part of any conversation - create a new
1706 if (pinfo->ptype == PT_TCP) {
1707 conversation = conversation_new(&pinfo->src,
1708 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1709 pinfo->destport, 0);
1711 conversation = conversation_new(&pinfo->src,
1712 &null_address, pinfo->ptype, pinfo->srcport,
1713 pinfo->destport, 0);
1717 /* Make the dissector for this conversation the non-heuristic
1719 conversation_set_dissector(conversation,
1720 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1722 /* prepare the key data */
1723 rpc_call_key.xid = xid;
1724 rpc_call_key.conversation = conversation;
1726 /* look up the request */
1727 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1728 if (rpc_call != NULL) {
1729 /* We've seen a request with this XID, with the same
1730 source and destination, before - but was it
1732 if (pinfo->fd->num != rpc_call->req_num) {
1733 /* No, so it's a duplicate request.
1735 if (check_col(pinfo->cinfo, COL_INFO)) {
1736 col_append_fstr(pinfo->cinfo, COL_INFO,
1737 " dup XID 0x%x", xid);
1739 proto_tree_add_uint_hidden(rpc_tree,
1740 hf_rpc_dup, tvb, 0,0, xid);
1741 proto_tree_add_uint_hidden(rpc_tree,
1742 hf_rpc_call_dup, tvb, 0,0, xid);
1748 /* Prepare the value data.
1749 "req_num" and "rep_num" are frame numbers;
1750 frame numbers are 1-origin, so we use 0
1751 to mean "we don't yet know in which frame
1752 the reply for this call appears". */
1753 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1754 *new_rpc_call_key = rpc_call_key;
1755 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1756 rpc_call->req_num = pinfo->fd->num;
1757 rpc_call->rep_num = 0;
1758 rpc_call->prog = prog;
1759 rpc_call->vers = vers;
1760 rpc_call->proc = proc;
1761 rpc_call->flavor = flavor;
1762 rpc_call->gss_proc = gss_proc;
1763 rpc_call->gss_svc = gss_svc;
1764 rpc_call->proc_info = value;
1765 rpc_call->req_time.secs=pinfo->fd->abs_secs;
1766 rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
1769 g_hash_table_insert(rpc_calls, new_rpc_call_key,
1775 offset = dissect_rpc_cred(tvb, pinfo, rpc_tree, offset);
1776 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1778 /* go to the next dissector */
1780 break; /* end of RPC call */
1783 /* we know already the type from the calling routine,
1784 and we already have "rpc_call" set above. */
1785 prog = rpc_call->prog;
1786 vers = rpc_call->vers;
1787 proc = rpc_call->proc;
1788 flavor = rpc_call->flavor;
1789 gss_proc = rpc_call->gss_proc;
1790 gss_svc = rpc_call->gss_svc;
1792 /* Indicate the frame to which this is a reply. */
1793 proto_tree_add_text(rpc_tree, tvb, 0, 0,
1794 "This is a reply to a request in frame %u",
1796 ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
1797 ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
1799 ns.nsecs+=1000000000;
1802 proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
1807 if (rpc_call->proc_info != NULL) {
1808 dissect_function = rpc_call->proc_info->dissect_reply;
1809 if (rpc_call->proc_info->name != NULL) {
1810 procname = rpc_call->proc_info->name;
1813 sprintf(procname_static, "proc-%u", proc);
1814 procname = procname_static;
1819 dissect_function = NULL;
1821 sprintf(procname_static, "proc-%u", proc);
1822 procname = procname_static;
1825 rpc_prog_key.prog = prog;
1826 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1829 progname = "Unknown";
1832 proto = rpc_prog->proto;
1833 ett = rpc_prog->ett;
1834 progname = rpc_prog->progname;
1836 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1837 /* Set the protocol name to the underlying
1839 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1843 if (check_col(pinfo->cinfo, COL_INFO)) {
1844 col_add_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1852 proto_tree_add_uint_format(rpc_tree,
1853 hf_rpc_program, tvb, 0, 0, prog,
1854 "Program: %s (%u)", progname, prog);
1855 proto_tree_add_uint(rpc_tree,
1856 hf_rpc_programversion, tvb, 0, 0, vers);
1857 proto_tree_add_uint_format(rpc_tree,
1858 hf_rpc_procedure, tvb, 0, 0, proc,
1859 "Procedure: %s (%u)", procname, proc);
1862 if (rpc_call->rep_num == 0) {
1863 /* We have not yet seen a reply to that call, so
1864 this must be the first reply; remember its
1866 rpc_call->rep_num = pinfo->fd->num;
1868 /* We have seen a reply to this call - but was it
1870 if (rpc_call->rep_num != pinfo->fd->num) {
1871 /* No, so it's a duplicate reply.
1873 if (check_col(pinfo->cinfo, COL_INFO)) {
1874 col_append_fstr(pinfo->cinfo, COL_INFO,
1875 " dup XID 0x%x", xid);
1877 proto_tree_add_uint_hidden(rpc_tree,
1878 hf_rpc_dup, tvb, 0,0, xid);
1879 proto_tree_add_uint_hidden(rpc_tree,
1880 hf_rpc_reply_dup, tvb, 0,0, xid);
1886 reply_state = tvb_get_ntohl(tvb,offset+0);
1888 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
1889 offset+0, 4, reply_state);
1893 if (reply_state == MSG_ACCEPTED) {
1894 offset = dissect_rpc_verf(tvb, pinfo, rpc_tree, offset, msg_type);
1895 accept_state = tvb_get_ntohl(tvb,offset+0);
1897 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
1898 offset+0, 4, accept_state);
1901 switch (accept_state) {
1904 /* go to the next dissector */
1908 vers_low = tvb_get_ntohl(tvb,offset+0);
1909 vers_high = tvb_get_ntohl(tvb,offset+4);
1911 proto_tree_add_uint(rpc_tree,
1912 hf_rpc_programversion_min,
1913 tvb, offset+0, 4, vers_low);
1914 proto_tree_add_uint(rpc_tree,
1915 hf_rpc_programversion_max,
1916 tvb, offset+4, 4, vers_high);
1925 } else if (reply_state == MSG_DENIED) {
1926 reject_state = tvb_get_ntohl(tvb,offset+0);
1928 proto_tree_add_uint(rpc_tree,
1929 hf_rpc_state_reject, tvb, offset+0, 4,
1934 if (reject_state==RPC_MISMATCH) {
1935 vers_low = tvb_get_ntohl(tvb,offset+0);
1936 vers_high = tvb_get_ntohl(tvb,offset+4);
1938 proto_tree_add_uint(rpc_tree,
1940 tvb, offset+0, 4, vers_low);
1941 proto_tree_add_uint(rpc_tree,
1943 tvb, offset+4, 4, vers_high);
1946 } else if (reject_state==AUTH_ERROR) {
1947 auth_state = tvb_get_ntohl(tvb,offset+0);
1949 proto_tree_add_uint(rpc_tree,
1950 hf_rpc_state_auth, tvb, offset+0, 4,
1956 break; /* end of RPC reply */
1960 * The switch statement at the top returned if
1961 * this was neither an RPC call nor a reply.
1963 g_assert_not_reached();
1966 /* now we know, that RPC was shorter */
1968 proto_item_set_len(rpc_item, offset - offset_old);
1971 /* create here the program specific sub-tree */
1973 pitem = proto_tree_add_item(tree, proto, tvb,
1974 offset, tvb_length(tvb) - offset, FALSE);
1976 ptree = proto_item_add_subtree(pitem, ett);
1980 proto_tree_add_uint(ptree,
1981 hf_rpc_programversion, tvb, 0, 0, vers);
1982 proto_tree_add_uint_format(ptree,
1983 hf_rpc_procedure, tvb, 0, 0, proc,
1984 "Procedure: %s (%u)", procname, proc);
1988 if (!proto_is_protocol_enabled(proto))
1989 dissect_function = NULL;
1992 * Handle RPCSEC_GSS specially.
1996 case FLAVOR_UNKNOWN:
1998 * We don't know the authentication flavor, so we can't
1999 * dissect the payload.
2001 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2002 "Unknown authentication flavor - cannot dissect");
2005 case FLAVOR_NOT_GSSAPI:
2007 * It's not GSS-API authentication. Just dissect the
2010 offset = call_dissect_function(tvb, pinfo, ptree, offset,
2011 dissect_function, progname);
2014 case FLAVOR_GSSAPI_NO_INFO:
2016 * It's GSS-API authentication, but we don't have the
2017 * procedure and service information, so we can't dissect
2020 proto_tree_add_text(ptree, tvb, offset, tvb_length_remaining(tvb, offset),
2021 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2026 * It's GSS-API authentication, and we have the procedure
2027 * and service information; process the GSS-API stuff,
2028 * and process the payload if there is any.
2032 case RPCSEC_GSS_INIT:
2033 case RPCSEC_GSS_CONTINUE_INIT:
2034 if (msg_type == RPC_CALL) {
2035 offset = dissect_rpc_authgss_initarg(tvb,
2036 pinfo, ptree, offset);
2039 offset = dissect_rpc_authgss_initres(tvb,
2040 pinfo, ptree, offset);
2044 case RPCSEC_GSS_DATA:
2045 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2046 offset = call_dissect_function(tvb,
2047 pinfo, ptree, offset,
2051 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2052 offset = dissect_rpc_authgss_integ_data(tvb,
2053 pinfo, ptree, offset,
2057 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2058 offset = dissect_rpc_authgss_priv_data(tvb,
2059 pinfo, ptree, offset);
2068 /* dissect any remaining bytes (incomplete dissection) as pure data in
2070 call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,tvb_reported_length_remaining(tvb,offset)), pinfo, ptree);
2076 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2078 return dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0);
2082 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2084 if (!dissect_rpc_message(tvb, 0, pinfo, tree, FALSE, 0))
2085 dissect_rpc_continuation(tvb, pinfo, tree);
2091 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
2093 * IS_RPC, if we dissected at least one message in its entirety
2096 * IS_NOT_RPC, if we found no RPC message.
2104 static rpc_tcp_return_t
2105 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2108 volatile int offset = 0;
2110 volatile gboolean saw_rpc = FALSE;
2111 volatile gint32 len;
2113 gint tvb_len, tvb_reported_len;
2115 const char *saved_proto;
2117 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2119 * XXX - we need to handle records that don't have the "last
2120 * fragment" bit set, and reassemble fragments.
2123 /* the first 4 bytes are special in "record marking mode" */
2124 if (!tvb_bytes_exist(tvb, offset, 4)) {
2126 * XXX - we should somehow arrange to handle
2127 * a record mark split across TCP segments.
2129 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2131 rpc_rm = tvb_get_ntohl(tvb, offset);
2133 len = rpc_rm&RPC_RM_FRAGLEN;
2136 * XXX - reject fragments bigger than 2 megabytes.
2137 * This is arbitrary, but should at least prevent
2138 * some crashes from either packets with really
2139 * large RPC-over-TCP fragments or from stuff that's
2142 if (len > 2*1024*1024)
2143 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2144 if (rpc_desegment) {
2145 seglen = tvb_length_remaining(tvb, offset + 4);
2147 if (len > seglen && pinfo->can_desegment) {
2149 * This frame doesn't have all of the
2150 * data for this message, but we can do
2153 * If this is a heuristic dissector, just
2154 * return IS_NOT_RPC - we don't want to try
2155 * to get more data, as that's too likely
2156 * to cause us to misidentify this as
2159 * If this isn't a heuristic dissector,
2160 * we've already identified this conversation
2161 * as containing RPC data, as we saw RPC
2162 * data in previous frames. Try to get
2168 pinfo->desegment_offset = offset;
2169 pinfo->desegment_len = len - seglen;
2170 return NEED_MORE_DATA;
2174 len += 4; /* include record mark */
2175 tvb_len = tvb_length_remaining(tvb, offset);
2176 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2179 if (tvb_reported_len > len)
2180 tvb_reported_len = len;
2181 msg_tvb = tvb_new_subset(tvb, offset, tvb_len,
2185 * Catch the ReportedBoundsError exception; if this
2186 * particular message happens to get a ReportedBoundsError
2187 * exception, that doesn't mean that we should stop
2188 * dissecting RPC messages within this frame or chunk
2189 * of reassembled data.
2191 * If it gets a BoundsError, we can stop, as there's
2192 * nothing more to see, so we just re-throw it.
2194 saved_proto = pinfo->current_proto;
2196 if (!dissect_rpc_message(msg_tvb, 4, pinfo, tree,
2200 CATCH(BoundsError) {
2203 CATCH(ReportedBoundsError) {
2204 if (check_col(pinfo->cinfo, COL_INFO)) {
2205 col_append_str(pinfo->cinfo, COL_INFO,
2206 "[Malformed Packet]");
2208 proto_tree_add_protocol_format(tree, proto_malformed,
2209 tvb, 0, 0, "[Malformed Packet: %s]",
2210 pinfo->current_proto );
2211 pinfo->current_proto = saved_proto;
2217 return saw_rpc ? IS_RPC : IS_NOT_RPC;
2221 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2223 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
2232 /* "Can't happen" */
2233 g_assert_not_reached();
2239 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2241 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
2242 dissect_rpc_continuation(tvb, pinfo, tree);
2245 /* Discard any state we've saved. */
2247 rpc_init_protocol(void)
2249 if (rpc_calls != NULL)
2250 g_hash_table_destroy(rpc_calls);
2251 if (rpc_indir_calls != NULL)
2252 g_hash_table_destroy(rpc_indir_calls);
2253 if (rpc_call_info_key_chunk != NULL)
2254 g_mem_chunk_destroy(rpc_call_info_key_chunk);
2255 if (rpc_call_info_value_chunk != NULL)
2256 g_mem_chunk_destroy(rpc_call_info_value_chunk);
2258 rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2259 rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
2260 rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
2261 sizeof(rpc_call_info_key),
2262 200 * sizeof(rpc_call_info_key),
2264 rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
2265 sizeof(rpc_call_info_value),
2266 200 * sizeof(rpc_call_info_value),
2270 /* will be called once from register.c at startup time */
2272 proto_register_rpc(void)
2274 static hf_register_info hf[] = {
2275 { &hf_rpc_lastfrag, {
2276 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, BASE_NONE,
2277 &yesno, 0, "Last Fragment", HFILL }},
2278 { &hf_rpc_fraglen, {
2279 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
2280 NULL, 0, "Fragment Length", HFILL }},
2282 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
2283 NULL, 0, "XID", HFILL }},
2284 { &hf_rpc_msgtype, {
2285 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
2286 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
2287 { &hf_rpc_state_reply, {
2288 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
2289 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
2290 { &hf_rpc_state_accept, {
2291 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
2292 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
2293 { &hf_rpc_state_reject, {
2294 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
2295 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
2296 { &hf_rpc_state_auth, {
2297 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
2298 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
2299 { &hf_rpc_version, {
2300 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
2301 NULL, 0, "RPC Version", HFILL }},
2302 { &hf_rpc_version_min, {
2303 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
2304 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2305 { &hf_rpc_version_max, {
2306 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
2307 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
2308 { &hf_rpc_program, {
2309 "Program", "rpc.program", FT_UINT32, BASE_DEC,
2310 NULL, 0, "Program", HFILL }},
2311 { &hf_rpc_programversion, {
2312 "Program Version", "rpc.programversion", FT_UINT32,
2313 BASE_DEC, NULL, 0, "Program Version", HFILL }},
2314 { &hf_rpc_programversion_min, {
2315 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
2316 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
2317 { &hf_rpc_programversion_max, {
2318 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
2319 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
2320 { &hf_rpc_procedure, {
2321 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
2322 NULL, 0, "Procedure", HFILL }},
2323 { &hf_rpc_auth_flavor, {
2324 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
2325 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
2326 { &hf_rpc_auth_length, {
2327 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
2328 NULL, 0, "Length", HFILL }},
2329 { &hf_rpc_auth_stamp, {
2330 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
2331 NULL, 0, "Stamp", HFILL }},
2332 { &hf_rpc_auth_uid, {
2333 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
2334 NULL, 0, "UID", HFILL }},
2335 { &hf_rpc_auth_gid, {
2336 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
2337 NULL, 0, "GID", HFILL }},
2338 { &hf_rpc_authgss_v, {
2339 "GSS Version", "rpc.authgss.version", FT_UINT32,
2340 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
2341 { &hf_rpc_authgss_proc, {
2342 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
2343 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
2344 { &hf_rpc_authgss_seq, {
2345 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
2346 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
2347 { &hf_rpc_authgss_svc, {
2348 "GSS Service", "rpc.authgss.service", FT_UINT32,
2349 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
2350 { &hf_rpc_authgss_ctx, {
2351 "GSS Context", "rpc.authgss.context", FT_BYTES,
2352 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
2353 { &hf_rpc_authgss_major, {
2354 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
2355 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
2356 { &hf_rpc_authgss_minor, {
2357 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
2358 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
2359 { &hf_rpc_authgss_window, {
2360 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
2361 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
2362 { &hf_rpc_authgss_token, {
2363 "GSS Token", "rpc.authgss.token", FT_BYTES,
2364 BASE_HEX, NULL, 0, "GSS Token", HFILL }},
2365 { &hf_rpc_authgss_data_length, {
2366 "Length", "rpc.authgss.data.length", FT_UINT32,
2367 BASE_DEC, NULL, 0, "Length", HFILL }},
2368 { &hf_rpc_authgss_data, {
2369 "GSS Data", "rpc.authgss.data", FT_BYTES,
2370 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
2371 { &hf_rpc_authgss_checksum, {
2372 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
2373 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
2374 { &hf_rpc_authdes_namekind, {
2375 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
2376 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
2377 { &hf_rpc_authdes_netname, {
2378 "Netname", "rpc.authdes.netname", FT_STRING,
2379 BASE_DEC, NULL, 0, "Netname", HFILL }},
2380 { &hf_rpc_authdes_convkey, {
2381 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
2382 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
2383 { &hf_rpc_authdes_window, {
2384 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
2385 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
2386 { &hf_rpc_authdes_nickname, {
2387 "Nickname", "rpc.authdes.nickname", FT_UINT32,
2388 BASE_HEX, NULL, 0, "Nickname", HFILL }},
2389 { &hf_rpc_authdes_timestamp, {
2390 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
2391 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
2392 { &hf_rpc_authdes_windowverf, {
2393 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
2394 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
2395 { &hf_rpc_authdes_timeverf, {
2396 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
2397 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
2398 { &hf_rpc_auth_machinename, {
2399 "Machine Name", "rpc.auth.machinename", FT_STRING,
2400 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
2402 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
2403 NULL, 0, "Duplicate Transaction", HFILL }},
2404 { &hf_rpc_call_dup, {
2405 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
2406 NULL, 0, "Duplicate Call", HFILL }},
2407 { &hf_rpc_reply_dup, {
2408 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
2409 NULL, 0, "Duplicate Reply", HFILL }},
2410 { &hf_rpc_value_follows, {
2411 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
2412 &yesno, 0, "Value Follows", HFILL }},
2413 { &hf_rpc_array_len, {
2414 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
2415 NULL, 0, "Length of RPC array", HFILL }},
2418 "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
2419 NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
2422 static gint *ett[] = {
2431 module_t *rpc_module;
2433 proto_rpc = proto_register_protocol("Remote Procedure Call",
2435 proto_register_field_array(proto_rpc, hf, array_length(hf));
2436 proto_register_subtree_array(ett, array_length(ett));
2437 register_init_routine(&rpc_init_protocol);
2438 rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
2439 rpc_handle = create_dissector_handle(dissect_rpc, proto_rpc);
2440 rpc_module = prefs_register_protocol(proto_rpc, NULL);
2441 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
2442 "Desegment all RPC over TCP commands",
2443 "Whether the RPC dissector should desegment all RPC over TCP commands",
2447 * Init the hash tables. Dissectors for RPC protocols must
2448 * have a "handoff registration" routine that registers the
2449 * protocol with RPC; they must not do it in their protocol
2450 * registration routine, as their protocol registration
2451 * routine might be called before this routine is called and
2452 * thus might be called before the hash tables are initialized,
2453 * but it's guaranteed that all protocol registration routines
2454 * will be called before any handoff registration routines
2457 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
2458 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
2462 proto_reg_handoff_rpc(void)
2464 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
2465 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
2466 data_handle = find_dissector("data");