2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.129 2003/05/22 21:37:54 sharpe 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.
36 #include <epan/packet.h>
37 #include <epan/conversation.h>
38 #include "packet-rpc.h"
39 #include "packet-frame.h"
40 #include "packet-tcp.h"
42 #include "reassemble.h"
43 #include "rpc_defrag.h"
44 #include "packet-nfs.h"
50 * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
53 * RFC 1832, "XDR: External Data Representation Standard";
55 * RFC 2203, "RPCSEC_GSS Protocol Specification".
59 * RFC 2695, "Authentication Mechanisms for ONC RPC"
61 * although we don't currently dissect AUTH_DES or AUTH_KERB.
64 /* desegmentation of RPC over TCP */
65 static gboolean rpc_desegment = TRUE;
67 /* defragmentation of fragmented RPC over TCP records */
68 static gboolean rpc_defragment = FALSE;
70 static struct true_false_string yesno = { "Yes", "No" };
72 static int rpc_tap = -1;
74 static const value_string rpc_msg_type[] = {
76 { RPC_REPLY, "Reply" },
80 static const value_string rpc_reply_state[] = {
81 { MSG_ACCEPTED, "accepted" },
82 { MSG_DENIED, "denied" },
86 const value_string rpc_auth_flavor[] = {
87 { AUTH_NULL, "AUTH_NULL" },
88 { AUTH_UNIX, "AUTH_UNIX" },
89 { AUTH_SHORT, "AUTH_SHORT" },
90 { AUTH_DES, "AUTH_DES" },
91 { RPCSEC_GSS, "RPCSEC_GSS" },
92 { AUTH_GSSAPI, "AUTH_GSSAPI" },
96 static const value_string rpc_authgss_proc[] = {
97 { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
98 { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
99 { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
100 { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
104 static const value_string rpc_authgssapi_proc[] = {
105 { AUTH_GSSAPI_EXIT, "AUTH_GSSAPI_EXIT" },
106 { AUTH_GSSAPI_INIT, "AUTH_GSSAPI_INIT" },
107 { AUTH_GSSAPI_CONTINUE_INIT, "AUTH_GSSAPI_CONTINUE_INIT" },
108 { AUTH_GSSAPI_MSG, "AUTH_GSSAPI_MSG" },
109 { AUTH_GSSAPI_DESTROY, "AUTH_GSSAPI_DESTROY" },
113 value_string rpc_authgss_svc[] = {
114 { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
115 { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
116 { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
120 static const value_string rpc_accept_state[] = {
121 { SUCCESS, "RPC executed successfully" },
122 { PROG_UNAVAIL, "remote hasn't exported program" },
123 { PROG_MISMATCH, "remote can't support version #" },
124 { PROC_UNAVAIL, "program can't support procedure" },
125 { GARBAGE_ARGS, "procedure can't decode params" },
129 static const value_string rpc_reject_state[] = {
130 { RPC_MISMATCH, "RPC_MISMATCH" },
131 { AUTH_ERROR, "AUTH_ERROR" },
135 static const value_string rpc_auth_state[] = {
136 { AUTH_BADCRED, "bad credential (seal broken)" },
137 { AUTH_REJECTEDCRED, "client must begin new session" },
138 { AUTH_BADVERF, "bad verifier (seal broken)" },
139 { AUTH_REJECTEDVERF, "verifier expired or replayed" },
140 { AUTH_TOOWEAK, "rejected for security reasons" },
141 { RPCSEC_GSSCREDPROB, "GSS credential problem" },
142 { RPCSEC_GSSCTXPROB, "GSS context problem" },
146 static const value_string rpc_authdes_namekind[] = {
147 { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
148 { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
152 /* the protocol number */
153 static int proto_rpc = -1;
154 static int hf_rpc_reqframe = -1;
155 static int hf_rpc_repframe = -1;
156 static int hf_rpc_lastfrag = -1;
157 static int hf_rpc_fraglen = -1;
158 static int hf_rpc_xid = -1;
159 static int hf_rpc_msgtype = -1;
160 static int hf_rpc_version = -1;
161 static int hf_rpc_version_min = -1;
162 static int hf_rpc_version_max = -1;
163 static int hf_rpc_program = -1;
164 static int hf_rpc_programversion = -1;
165 static int hf_rpc_programversion_min = -1;
166 static int hf_rpc_programversion_max = -1;
167 static int hf_rpc_procedure = -1;
168 static int hf_rpc_auth_flavor = -1;
169 static int hf_rpc_auth_length = -1;
170 static int hf_rpc_auth_machinename = -1;
171 static int hf_rpc_auth_stamp = -1;
172 static int hf_rpc_auth_uid = -1;
173 static int hf_rpc_auth_gid = -1;
174 static int hf_rpc_authgss_v = -1;
175 static int hf_rpc_authgss_proc = -1;
176 static int hf_rpc_authgss_seq = -1;
177 static int hf_rpc_authgss_svc = -1;
178 static int hf_rpc_authgss_ctx = -1;
179 static int hf_rpc_authgss_major = -1;
180 static int hf_rpc_authgss_minor = -1;
181 static int hf_rpc_authgss_window = -1;
182 static int hf_rpc_authgss_token_length = -1;
183 static int hf_rpc_authgss_data_length = -1;
184 static int hf_rpc_authgss_data = -1;
185 static int hf_rpc_authgss_checksum = -1;
186 static int hf_rpc_authgssapi_v = -1;
187 static int hf_rpc_authgssapi_msg = -1;
188 static int hf_rpc_authgssapi_msgv = -1;
189 static int hf_rpc_authgssapi_handle = -1;
190 static int hf_rpc_authgssapi_isn = -1;
191 static int hf_rpc_authdes_namekind = -1;
192 static int hf_rpc_authdes_netname = -1;
193 static int hf_rpc_authdes_convkey = -1;
194 static int hf_rpc_authdes_window = -1;
195 static int hf_rpc_authdes_nickname = -1;
196 static int hf_rpc_authdes_timestamp = -1;
197 static int hf_rpc_authdes_windowverf = -1;
198 static int hf_rpc_authdes_timeverf = -1;
199 static int hf_rpc_state_accept = -1;
200 static int hf_rpc_state_reply = -1;
201 static int hf_rpc_state_reject = -1;
202 static int hf_rpc_state_auth = -1;
203 static int hf_rpc_dup = -1;
204 static int hf_rpc_call_dup = -1;
205 static int hf_rpc_reply_dup = -1;
206 static int hf_rpc_value_follows = -1;
207 static int hf_rpc_array_len = -1;
208 static int hf_rpc_time = -1;
209 static int hf_rpc_fragments = -1;
210 static int hf_rpc_fragment = -1;
211 static int hf_rpc_fragment_overlap = -1;
212 static int hf_rpc_fragment_overlap_conflict = -1;
213 static int hf_rpc_fragment_multiple_tails = -1;
214 static int hf_rpc_fragment_too_long_fragment = -1;
215 static int hf_rpc_fragment_error = -1;
217 static gint ett_rpc = -1;
218 static gint ett_rpc_fragments = -1;
219 static gint ett_rpc_fragment = -1;
220 static gint ett_rpc_fraghdr = -1;
221 static gint ett_rpc_string = -1;
222 static gint ett_rpc_cred = -1;
223 static gint ett_rpc_verf = -1;
224 static gint ett_rpc_gids = -1;
225 static gint ett_rpc_gss_token = -1;
226 static gint ett_rpc_gss_data = -1;
227 static gint ett_rpc_array = -1;
228 static gint ett_rpc_authgssapi_msg = -1;
230 static dissector_handle_t rpc_tcp_handle;
231 static dissector_handle_t rpc_handle;
232 static dissector_handle_t gssapi_handle;
233 static dissector_handle_t data_handle;
235 static const fragment_items rpc_frag_items = {
240 &hf_rpc_fragment_overlap,
241 &hf_rpc_fragment_overlap_conflict,
242 &hf_rpc_fragment_multiple_tails,
243 &hf_rpc_fragment_too_long_fragment,
244 &hf_rpc_fragment_error,
249 /* Hash table with info on RPC program numbers */
250 GHashTable *rpc_progs;
252 /* Hash table with info on RPC procedure numbers */
253 GHashTable *rpc_procs;
255 static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
256 static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
258 /***********************************/
259 /* Hash array with procedure names */
260 /***********************************/
264 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
266 const rpc_proc_info_key* key1 = (const rpc_proc_info_key*) k1;
267 const rpc_proc_info_key* key2 = (const rpc_proc_info_key*) k2;
269 return ((key1->prog == key2->prog &&
270 key1->vers == key2->vers &&
271 key1->proc == key2->proc) ?
275 /* calculate a hash key */
277 rpc_proc_hash(gconstpointer k)
279 const rpc_proc_info_key* key = (const rpc_proc_info_key*) k;
281 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
285 /* insert some entries */
287 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table,
290 rpc_prog_info_key rpc_prog_key;
291 rpc_prog_info_value *rpc_prog;
295 * Add the operation number hfinfo value for this version of the
298 rpc_prog_key.prog = prog;
299 rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key);
300 g_assert(rpc_prog != NULL);
301 rpc_prog->procedure_hfs = g_array_set_size(rpc_prog->procedure_hfs,
303 g_array_insert_val(rpc_prog->procedure_hfs, vers, procedure_hf);
305 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
306 rpc_proc_info_key *key;
307 rpc_proc_info_value *value;
309 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
312 key->proc = proc->value;
314 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
315 value->name = proc->strptr;
316 value->dissect_call = proc->dissect_call;
317 value->dissect_reply = proc->dissect_reply;
319 g_hash_table_insert(rpc_procs,key,value);
323 /* return the name associated with a previously registered procedure. */
324 char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
326 rpc_proc_info_key key;
327 rpc_proc_info_value *value;
329 static char procname_static[20];
335 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
336 procname = value->name;
338 /* happens only with strange program versions or
339 non-existing dissectors */
340 sprintf(procname_static, "proc-%u", key.proc);
341 procname = procname_static;
346 /*----------------------------------------*/
347 /* end of Hash array with procedure names */
348 /*----------------------------------------*/
351 /*********************************/
352 /* Hash array with program names */
353 /*********************************/
357 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
359 const rpc_prog_info_key* key1 = (const rpc_prog_info_key*) k1;
360 const rpc_prog_info_key* key2 = (const rpc_prog_info_key*) k2;
362 return ((key1->prog == key2->prog) ?
367 /* calculate a hash key */
369 rpc_prog_hash(gconstpointer k)
371 const rpc_prog_info_key* key = (const rpc_prog_info_key*) k;
378 rpc_init_prog(int proto, guint32 prog, int ett)
380 rpc_prog_info_key *key;
381 rpc_prog_info_value *value;
383 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
386 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
387 value->proto = proto;
389 value->progname = proto_get_protocol_short_name(proto);
390 value->procedure_hfs = g_array_new(FALSE, TRUE, sizeof (int));
392 g_hash_table_insert(rpc_progs,key,value);
395 /* return the name associated with a previously registered program. This
396 should probably eventually be expanded to use the rpc YP/NIS map
397 so that it can give names for programs not handled by ethereal */
398 char *rpc_prog_name(guint32 prog)
400 char *progname = NULL;
401 rpc_prog_info_key rpc_prog_key;
402 rpc_prog_info_value *rpc_prog;
404 rpc_prog_key.prog = prog;
405 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
406 progname = "Unknown";
409 progname = rpc_prog->progname;
415 /*--------------------------------------*/
416 /* end of Hash array with program names */
417 /*--------------------------------------*/
419 typedef struct _rpc_call_info_key {
421 conversation_t *conversation;
424 static GMemChunk *rpc_call_info_key_chunk;
426 static GMemChunk *rpc_call_info_value_chunk;
428 static GHashTable *rpc_calls;
430 static GHashTable *rpc_indir_calls;
434 rpc_call_equal(gconstpointer k1, gconstpointer k2)
436 const rpc_call_info_key* key1 = (const rpc_call_info_key*) k1;
437 const rpc_call_info_key* key2 = (const rpc_call_info_key*) k2;
439 return (key1->xid == key2->xid &&
440 key1->conversation == key2->conversation);
444 /* calculate a hash key */
446 rpc_call_hash(gconstpointer k)
448 const rpc_call_info_key* key = (const rpc_call_info_key*) k;
450 return key->xid + GPOINTER_TO_UINT(key->conversation);
455 rpc_roundup(unsigned int a)
457 unsigned int mod = a % 4;
458 return a + ((mod)? 4-mod : 0);
463 dissect_rpc_bool(tvbuff_t *tvb, proto_tree *tree,
464 int hfindex, int offset)
467 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
473 dissect_rpc_uint32(tvbuff_t *tvb, proto_tree *tree,
474 int hfindex, int offset)
477 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
483 dissect_rpc_uint64(tvbuff_t *tvb, proto_tree *tree,
484 int hfindex, int offset)
486 header_field_info *hfinfo;
488 hfinfo = proto_registrar_get_nth(hfindex);
489 g_assert(hfinfo->type == FT_UINT64);
491 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
497 * We want to make this function available outside this file and
498 * allow callers to pass a dissection function for the opaque data
501 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
505 gboolean fixed_length, guint32 length,
506 gboolean string_data, char **string_buffer_ret,
507 dissect_function_t *dissect_it)
509 proto_item *string_item = NULL;
510 proto_tree *string_tree = NULL;
512 guint32 string_length;
513 guint32 string_length_full;
514 guint32 string_length_packet;
515 guint32 string_length_captured;
516 guint32 string_length_copy;
520 guint32 fill_length_packet;
521 guint32 fill_length_captured;
522 guint32 fill_length_copy;
526 char *string_buffer = NULL;
527 char *string_buffer_print = NULL;
530 string_length = length;
531 string_length_captured = tvb_length_remaining(tvb, offset);
532 string_length_packet = tvb_reported_length_remaining(tvb, offset);
535 string_length = tvb_get_ntohl(tvb,offset+0);
536 string_length_captured = tvb_length_remaining(tvb, offset + 4);
537 string_length_packet = tvb_reported_length_remaining(tvb, offset + 4);
539 string_length_full = rpc_roundup(string_length);
540 if (string_length_captured < string_length) {
541 /* truncated string */
542 string_length_copy = string_length_captured;
545 fill_length_copy = 0;
546 if (string_length_packet < string_length)
547 exception = ReportedBoundsError;
549 exception = BoundsError;
552 /* full string data */
553 string_length_copy = string_length;
554 fill_length = string_length_full - string_length;
556 fill_length_captured = tvb_length_remaining(tvb,
557 offset + string_length);
558 fill_length_packet = tvb_reported_length_remaining(tvb,
559 offset + string_length);
562 fill_length_captured = tvb_length_remaining(tvb,
563 offset + 4 + string_length);
564 fill_length_packet = tvb_reported_length_remaining(tvb,
565 offset + 4 + string_length);
567 if (fill_length_captured < fill_length) {
568 /* truncated fill bytes */
569 fill_length_copy = fill_length_packet;
571 if (fill_length_packet < fill_length)
572 exception = ReportedBoundsError;
574 exception = BoundsError;
577 /* full fill bytes */
578 fill_length_copy = fill_length;
584 * If we were passed a dissection routine, make a TVB of the data
585 * and call the dissection routine
589 tvbuff_t *opaque_tvb;
591 opaque_tvb = tvb_new_subset(tvb, offset,
592 (fixed_length?offset:(offset + 4)), string_length_copy);
594 return (*dissect_it)(opaque_tvb, offset, pinfo, tree);
598 string_buffer = (char*)g_malloc(string_length_copy +
599 (string_data ? 1 : 0));
601 tvb_memcpy(tvb,string_buffer, offset, string_length_copy);
603 tvb_memcpy(tvb,string_buffer,offset+4,string_length_copy);
605 string_buffer[string_length_copy] = '\0';
607 /* calculate a nice printable string */
609 if (string_length != string_length_copy) {
611 /* alloc maximum data area */
612 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
613 /* copy over the data */
614 memcpy(string_buffer_print,string_buffer,string_length_copy);
615 /* append a 0 byte for sure printing */
616 string_buffer_print[string_length_copy] = '\0';
617 /* append <TRUNCATED> */
618 /* This way, we get the TRUNCATED even
619 in the case of totally wrong packets,
620 where \0 are inside the string.
621 TRUNCATED will appear at the
622 first \0 or at the end (where we
623 put the securing \0).
625 strcat(string_buffer_print,"<TRUNCATED>");
628 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
633 string_buffer_print = g_strdup(string_buffer);
636 string_buffer_print = g_strdup("<DATA>");
641 string_buffer_print = g_strdup("<EMPTY>");
645 string_item = proto_tree_add_text(tree, tvb,offset+0, -1,
646 "%s: %s", proto_registrar_get_name(hfindex),
647 string_buffer_print);
648 string_tree = proto_item_add_subtree(string_item,
653 proto_tree_add_text(string_tree, tvb,offset+0,4,
654 "length: %u", string_length);
660 proto_tree_add_string_format(string_tree,
661 hfindex, tvb, offset, string_length_copy,
663 "contents: %s", string_buffer_print);
665 proto_tree_add_bytes_format(string_tree,
666 hfindex, tvb, offset, string_length_copy,
668 "contents: %s", string_buffer_print);
671 proto_tree_add_text(string_tree, tvb, offset, -1,
672 " Offsetb %d:", offset);
673 offset += string_length_copy;
674 proto_tree_add_text(string_tree, tvb, offset, -1,
675 " Offseta %d:", offset);
678 if (fill_truncated) {
679 proto_tree_add_text(string_tree, tvb,
680 offset,fill_length_copy,
681 "fill bytes: opaque data<TRUNCATED>");
684 proto_tree_add_text(string_tree, tvb,
685 offset,fill_length_copy,
686 "fill bytes: opaque data");
689 offset += fill_length_copy;
693 proto_item_set_end(string_item, tvb, offset);
695 if (string_buffer != NULL)
696 g_free(string_buffer);
697 if (string_buffer_print != NULL) {
698 if (string_buffer_ret != NULL)
699 *string_buffer_ret = string_buffer_print;
701 g_free(string_buffer_print);
705 * If the data was truncated, throw the appropriate exception,
706 * so that dissection stops and the frame is properly marked.
715 dissect_rpc_string(tvbuff_t *tvb, proto_tree *tree,
716 int hfindex, int offset, char **string_buffer_ret)
718 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
719 hfindex, FALSE, 0, TRUE, string_buffer_ret, NULL);
725 dissect_rpc_data(tvbuff_t *tvb, proto_tree *tree,
726 int hfindex, int offset)
728 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
729 hfindex, FALSE, 0, FALSE, NULL, NULL);
735 dissect_rpc_bytes(tvbuff_t *tvb, proto_tree *tree,
736 int hfindex, int offset, guint32 length,
737 gboolean string_data, char **string_buffer_ret)
739 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
740 hfindex, TRUE, length, string_data, string_buffer_ret, NULL);
746 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
747 int offset, dissect_function_t *rpc_list_dissector)
749 guint32 value_follows;
752 value_follows = tvb_get_ntohl(tvb, offset+0);
753 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
754 offset+0, 4, value_follows);
756 if (value_follows == 1) {
757 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
768 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
769 int offset, dissect_function_t *rpc_array_dissector,
772 proto_item* lock_item;
773 proto_tree* lock_tree;
776 num = tvb_get_ntohl(tvb, offset);
779 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
786 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset, -1, FALSE);
788 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
790 offset = dissect_rpc_uint32(tvb, lock_tree,
791 hf_rpc_array_len, offset);
794 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
797 proto_item_set_end(lock_item, tvb, offset);
802 dissect_rpc_authunix_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
811 proto_tree *gtree = NULL;
813 stamp = tvb_get_ntohl(tvb,offset+0);
815 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
819 offset = dissect_rpc_string(tvb, tree,
820 hf_rpc_auth_machinename, offset, NULL);
822 uid = tvb_get_ntohl(tvb,offset+0);
824 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
828 gid = tvb_get_ntohl(tvb,offset+0);
830 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
834 gids_count = tvb_get_ntohl(tvb,offset+0);
836 gitem = proto_tree_add_text(tree, tvb,
837 offset, 4+gids_count*4, "Auxiliary GIDs");
838 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
842 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
843 gids_entry = tvb_get_ntohl(tvb,offset+0);
845 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
846 offset, 4, gids_entry);
849 /* how can I NOW change the gitem to print a list with
850 the first 16 gids? */
856 dissect_rpc_authgss_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
863 agc_v = tvb_get_ntohl(tvb, offset+0);
865 proto_tree_add_uint(tree, hf_rpc_authgss_v,
866 tvb, offset+0, 4, agc_v);
869 agc_proc = tvb_get_ntohl(tvb, offset+0);
871 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
872 tvb, offset+0, 4, agc_proc);
875 agc_seq = tvb_get_ntohl(tvb, offset+0);
877 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
878 tvb, offset+0, 4, agc_seq);
881 agc_svc = tvb_get_ntohl(tvb, offset+0);
883 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
884 tvb, offset+0, 4, agc_svc);
887 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
894 dissect_rpc_authdes_desblock(tvbuff_t *tvb, proto_tree *tree,
895 int hfindex, int offset)
900 value_high = tvb_get_ntohl(tvb, offset + 0);
901 value_low = tvb_get_ntohl(tvb, offset + 4);
904 proto_tree_add_text(tree, tvb, offset, 8,
905 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
913 dissect_rpc_authdes_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
919 adc_namekind = tvb_get_ntohl(tvb, offset+0);
921 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
922 tvb, offset+0, 4, adc_namekind);
927 case AUTHDES_NAMEKIND_FULLNAME:
928 offset = dissect_rpc_string(tvb, tree,
929 hf_rpc_authdes_netname, offset, NULL);
930 offset = dissect_rpc_authdes_desblock(tvb, tree,
931 hf_rpc_authdes_convkey, offset);
932 window = tvb_get_ntohl(tvb, offset+0);
933 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
938 case AUTHDES_NAMEKIND_NICKNAME:
939 nickname = tvb_get_ntohl(tvb, offset+0);
940 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
950 dissect_rpc_authgssapi_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
955 agc_v = tvb_get_ntohl(tvb, offset+0);
957 proto_tree_add_uint(tree, hf_rpc_authgssapi_v,
958 tvb, offset+0, 4, agc_v);
961 agc_msg = tvb_get_ntohl(tvb, offset+0);
963 proto_tree_add_boolean(tree, hf_rpc_authgssapi_msg,
964 tvb, offset+0, 4, agc_msg);
967 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgssapi_handle,
974 dissect_rpc_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
982 flavor = tvb_get_ntohl(tvb,offset+0);
983 length = tvb_get_ntohl(tvb,offset+4);
984 length = rpc_roundup(length);
987 citem = proto_tree_add_text(tree, tvb, offset,
988 8+length, "Credentials");
989 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
990 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
991 offset+0, 4, flavor);
992 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
993 offset+4, 4, length);
997 dissect_rpc_authunix_cred(tvb, ctree, offset+8);
1005 dissect_rpc_authdes_cred(tvb, ctree, offset+8);
1009 dissect_rpc_authgss_cred(tvb, ctree, offset+8);
1013 dissect_rpc_authgssapi_cred(tvb, ctree, offset+8);
1018 proto_tree_add_text(ctree, tvb, offset+8,
1019 length,"opaque data");
1023 offset += 8 + length;
1029 * XDR opaque object, the contents of which are interpreted as a GSS-API
1033 dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
1036 guint32 opaque_length, rounded_length;
1037 gint len_consumed, length, reported_length;
1041 proto_tree *gtree = NULL;
1043 opaque_length = tvb_get_ntohl(tvb, offset+0);
1044 rounded_length = rpc_roundup(opaque_length);
1046 gitem = proto_tree_add_text(tree, tvb, offset,
1047 4+rounded_length, "GSS Token");
1048 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_token);
1049 proto_tree_add_uint(gtree, hf_rpc_authgss_token_length,
1050 tvb, offset+0, 4, opaque_length);
1053 length = tvb_length_remaining(tvb, offset);
1054 reported_length = tvb_reported_length_remaining(tvb, offset);
1055 g_assert(length >= 0);
1056 g_assert(reported_length >= 0);
1057 if (length > reported_length)
1058 length = reported_length;
1059 if ((guint32)length > opaque_length)
1060 length = opaque_length;
1061 if ((guint32)reported_length > opaque_length)
1062 reported_length = opaque_length;
1063 new_tvb = tvb_new_subset(tvb, offset, length, reported_length);
1064 len_consumed = call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1065 offset += len_consumed;
1066 offset = rpc_roundup(offset);
1071 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
1072 * verifier we're decoding (CALL or REPLY).
1075 dissect_rpc_verf(tvbuff_t* tvb, proto_tree* tree, int offset, int msg_type,
1084 flavor = tvb_get_ntohl(tvb,offset+0);
1085 length = tvb_get_ntohl(tvb,offset+4);
1086 length = rpc_roundup(length);
1089 vitem = proto_tree_add_text(tree, tvb, offset,
1090 8+length, "Verifier");
1091 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
1092 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
1093 offset+0, 4, flavor);
1097 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1098 offset+4, 4, length);
1099 dissect_rpc_authunix_cred(tvb, vtree, offset+8);
1102 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1103 offset+4, 4, length);
1105 if (msg_type == RPC_CALL)
1109 dissect_rpc_authdes_desblock(tvb, vtree,
1110 hf_rpc_authdes_timestamp, offset+8);
1111 window = tvb_get_ntohl(tvb, offset+16);
1112 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
1113 offset+16, 4, window);
1117 /* must be an RPC_REPLY */
1120 dissect_rpc_authdes_desblock(tvb, vtree,
1121 hf_rpc_authdes_timeverf, offset+8);
1122 nickname = tvb_get_ntohl(tvb, offset+16);
1123 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
1124 offset+16, 4, nickname);
1128 dissect_rpc_authgss_token(tvb, vtree, offset+4, pinfo);
1131 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1132 offset+4, 4, length);
1134 proto_tree_add_text(vtree, tvb, offset+8,
1135 length, "opaque data");
1139 offset += 8 + length;
1145 dissect_rpc_authgss_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
1148 return dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
1152 dissect_rpc_authgss_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
1155 int major, minor, window;
1157 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
1160 major = tvb_get_ntohl(tvb,offset+0);
1162 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1163 offset+0, 4, major);
1166 minor = tvb_get_ntohl(tvb,offset+0);
1168 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1169 offset+0, 4, minor);
1172 window = tvb_get_ntohl(tvb,offset+0);
1174 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1175 offset+0, 4, window);
1178 offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
1184 dissect_rpc_authgssapi_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
1189 proto_tree *mtree = NULL;
1192 mitem = proto_tree_add_text(tree, tvb, offset, -1,
1194 mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
1196 version = tvb_get_ntohl(tvb, offset+0);
1198 proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
1199 offset+0, 4, version);
1203 offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
1209 dissect_rpc_authgssapi_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
1215 proto_tree *mtree = NULL;
1218 mitem = proto_tree_add_text(tree, tvb, offset, -1,
1220 mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
1223 version = tvb_get_ntohl(tvb,offset+0);
1225 proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
1226 offset+0, 4, version);
1230 offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_handle,
1233 major = tvb_get_ntohl(tvb,offset+0);
1235 proto_tree_add_uint(mtree, hf_rpc_authgss_major, tvb,
1236 offset+0, 4, major);
1240 minor = tvb_get_ntohl(tvb,offset+0);
1242 proto_tree_add_uint(mtree, hf_rpc_authgss_minor, tvb,
1243 offset+0, 4, minor);
1247 offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
1249 offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_isn, offset);
1255 dissect_auth_gssapi_data(tvbuff_t *tvb, proto_tree *tree, int offset)
1257 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
1263 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1264 int offset, dissect_function_t* dissect_function, const char *progname)
1266 const char *saved_proto;
1268 if (dissect_function != NULL) {
1269 /* set the current protocol name */
1270 saved_proto = pinfo->current_proto;
1271 if (progname != NULL)
1272 pinfo->current_proto = progname;
1274 /* call the dissector for the next level */
1275 offset = dissect_function(tvb, offset, pinfo, tree);
1277 /* restore the protocol name */
1278 pinfo->current_proto = saved_proto;
1286 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1287 proto_tree *tree, int offset,
1288 dissect_function_t* dissect_function,
1289 const char *progname)
1291 guint32 length, rounded_length, seq;
1294 proto_tree *gtree = NULL;
1296 length = tvb_get_ntohl(tvb, offset+0);
1297 rounded_length = rpc_roundup(length);
1298 seq = tvb_get_ntohl(tvb, offset+4);
1301 gitem = proto_tree_add_text(tree, tvb, offset,
1302 4+rounded_length, "GSS Data");
1303 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1304 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1305 tvb, offset+0, 4, length);
1306 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1307 tvb, offset+4, 4, seq);
1311 if (dissect_function != NULL) {
1313 call_dissect_function(tvb, pinfo, gtree, offset,
1314 dissect_function, progname);
1316 offset += rounded_length - 4;
1317 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_checksum,
1324 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, proto_tree *tree, int offset)
1326 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
1332 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1335 * Record this call in a hash table, similar to the hash table for
1336 * direct calls, so we can find it when dissecting an indirect call reply.
1339 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1340 int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1342 conversation_t* conversation;
1343 static address null_address = { AT_NONE, 0, NULL };
1344 rpc_proc_info_key key;
1345 rpc_proc_info_value *value;
1346 rpc_call_info_value *rpc_call;
1347 rpc_call_info_key rpc_call_key;
1348 rpc_call_info_key *new_rpc_call_key;
1349 dissect_function_t *dissect_function = NULL;
1354 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1355 dissect_function = value->dissect_call;
1357 /* Keep track of the address and port whence the call came,
1358 and the port to which the call is being sent, so that
1359 we can match up calls with replies.
1361 If the transport is connection-oriented (we check, for
1362 now, only for "pinfo->ptype" of PT_TCP), we take
1363 into account the address from which the call was sent
1364 and the address to which the call was sent, because
1365 the addresses of the two endpoints should be the same
1366 for all calls and replies.
1368 If the transport is connectionless, we don't worry
1369 about the address to which the call was sent and from
1370 which the reply was sent, because there's no
1371 guarantee that the reply will come from the address
1372 to which the call was sent. */
1373 if (pinfo->ptype == PT_TCP) {
1374 conversation = find_conversation(&pinfo->src,
1375 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1376 pinfo->destport, 0);
1379 * XXX - can we just use NO_ADDR_B? Unfortunately,
1380 * you currently still have to pass a non-null
1381 * pointer for the second address argument even
1384 conversation = find_conversation(&pinfo->src,
1385 &null_address, pinfo->ptype, pinfo->srcport,
1386 pinfo->destport, 0);
1388 if (conversation == NULL) {
1389 /* It's not part of any conversation - create a new
1392 XXX - this should never happen, as we should've
1393 created a conversation for it in the RPC
1395 if (pinfo->ptype == PT_TCP) {
1396 conversation = conversation_new(&pinfo->src,
1397 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1398 pinfo->destport, 0);
1400 conversation = conversation_new(&pinfo->src,
1401 &null_address, pinfo->ptype, pinfo->srcport,
1402 pinfo->destport, 0);
1406 /* Make the dissector for this conversation the non-heuristic
1408 conversation_set_dissector(conversation,
1409 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1411 /* Prepare the key data.
1413 Dissectors for RPC procedure calls and replies shouldn't
1414 create new tvbuffs, and we don't create one ourselves,
1415 so we should have been handed the tvbuff for this RPC call;
1416 as such, the XID is at offset 0 in this tvbuff. */
1417 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1418 rpc_call_key.conversation = conversation;
1420 /* look up the request */
1421 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1422 if (rpc_call == NULL) {
1423 /* We didn't find it; create a new entry.
1424 Prepare the value data.
1425 Not all of it is needed for handling indirect
1426 calls, so we set a bunch of items to 0. */
1427 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1428 *new_rpc_call_key = rpc_call_key;
1429 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1430 rpc_call->req_num = 0;
1431 rpc_call->rep_num = 0;
1432 rpc_call->prog = prog;
1433 rpc_call->vers = vers;
1434 rpc_call->proc = proc;
1435 rpc_call->private_data = NULL;
1438 * XXX - what about RPCSEC_GSS?
1439 * Do we have to worry about it?
1441 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1442 rpc_call->gss_proc = 0;
1443 rpc_call->gss_svc = 0;
1444 rpc_call->proc_info = value;
1446 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1451 /* We don't know the procedure.
1452 Happens only with strange program versions or
1453 non-existing dissectors.
1454 Just show the arguments as opaque data. */
1455 offset = dissect_rpc_data(tvb, tree, args_id,
1462 proto_tree_add_text(tree, tvb, offset, 4,
1463 "Argument length: %u",
1464 tvb_get_ntohl(tvb, offset));
1468 /* Dissect the arguments */
1469 offset = call_dissect_function(tvb, pinfo, tree, offset,
1470 dissect_function, NULL);
1475 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1479 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1480 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1482 conversation_t* conversation;
1483 static address null_address = { AT_NONE, 0, NULL };
1484 rpc_call_info_key rpc_call_key;
1485 rpc_call_info_value *rpc_call;
1486 char *procname = NULL;
1487 char procname_static[20];
1488 dissect_function_t *dissect_function = NULL;
1490 /* Look for the matching call in the hash table of indirect
1491 calls. A reply must match a call that we've seen, and the
1492 reply must be sent to the same port and address that the
1493 call came from, and must come from the port to which the
1496 If the transport is connection-oriented (we check, for
1497 now, only for "pinfo->ptype" of PT_TCP), we take
1498 into account the address from which the call was sent
1499 and the address to which the call was sent, because
1500 the addresses of the two endpoints should be the same
1501 for all calls and replies.
1503 If the transport is connectionless, we don't worry
1504 about the address to which the call was sent and from
1505 which the reply was sent, because there's no
1506 guarantee that the reply will come from the address
1507 to which the call was sent. */
1508 if (pinfo->ptype == PT_TCP) {
1509 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1510 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1513 * XXX - can we just use NO_ADDR_B? Unfortunately,
1514 * you currently still have to pass a non-null
1515 * pointer for the second address argument even
1518 conversation = find_conversation(&null_address, &pinfo->dst,
1519 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1521 if (conversation == NULL) {
1522 /* We haven't seen an RPC call for that conversation,
1523 so we can't check for a reply to that call.
1524 Just show the reply stuff as opaque data. */
1525 offset = dissect_rpc_data(tvb, tree, result_id,
1530 /* The XIDs of the call and reply must match. */
1531 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1532 rpc_call_key.conversation = conversation;
1533 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1534 if (rpc_call == NULL) {
1535 /* The XID doesn't match a call from that
1536 conversation, so it's probably not an RPC reply.
1537 Just show the reply stuff as opaque data. */
1538 offset = dissect_rpc_data(tvb, tree, result_id,
1543 if (rpc_call->proc_info != NULL) {
1544 dissect_function = rpc_call->proc_info->dissect_reply;
1545 if (rpc_call->proc_info->name != NULL) {
1546 procname = rpc_call->proc_info->name;
1549 sprintf(procname_static, "proc-%u", rpc_call->proc);
1550 procname = procname_static;
1555 dissect_function = NULL;
1557 sprintf(procname_static, "proc-%u", rpc_call->proc);
1558 procname = procname_static;
1563 /* Put the program, version, and procedure into the tree. */
1564 proto_tree_add_uint_format(tree, prog_id, tvb,
1565 0, 0, rpc_call->prog, "Program: %s (%u)",
1566 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1567 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1568 proto_tree_add_uint_format(tree, proc_id, tvb,
1569 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1570 procname, rpc_call->proc);
1573 if (dissect_function == NULL) {
1574 /* We don't know how to dissect the reply procedure.
1575 Just show the reply stuff as opaque data. */
1576 offset = dissect_rpc_data(tvb, tree, result_id,
1582 /* Put the length of the reply value into the tree. */
1583 proto_tree_add_text(tree, tvb, offset, 4,
1584 "Argument length: %u",
1585 tvb_get_ntohl(tvb, offset));
1589 /* Dissect the return value */
1590 offset = call_dissect_function(tvb, pinfo, tree, offset,
1591 dissect_function, NULL);
1596 * Just mark this as a continuation of an earlier packet.
1599 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1601 proto_item *rpc_item;
1602 proto_tree *rpc_tree;
1604 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1605 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1606 if (check_col(pinfo->cinfo, COL_INFO))
1607 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1610 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1612 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1613 proto_tree_add_text(rpc_tree, tvb, 0, -1, "Continuation data");
1618 dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1619 tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
1620 guint32 rpc_rm, gboolean first_pdu)
1623 rpc_call_info_key rpc_call_key;
1624 rpc_call_info_value *rpc_call = NULL;
1625 rpc_prog_info_value *rpc_prog = NULL;
1626 rpc_prog_info_key rpc_prog_key;
1629 unsigned int rpcvers;
1630 unsigned int prog = 0;
1631 unsigned int vers = 0;
1632 unsigned int proc = 0;
1633 flavor_t flavor = FLAVOR_UNKNOWN;
1634 unsigned int gss_proc = 0;
1635 unsigned int gss_svc = 0;
1640 unsigned int reply_state;
1641 unsigned int accept_state;
1642 unsigned int reject_state;
1644 char *msg_type_name = NULL;
1645 char *progname = NULL;
1646 char *procname = NULL;
1647 static char procname_static[20];
1649 unsigned int vers_low;
1650 unsigned int vers_high;
1652 unsigned int auth_state;
1654 proto_item *rpc_item = NULL;
1655 proto_tree *rpc_tree = NULL;
1657 proto_item *pitem = NULL;
1658 proto_tree *ptree = NULL;
1659 int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
1661 rpc_call_info_key *new_rpc_call_key;
1662 rpc_proc_info_key key;
1663 rpc_proc_info_value *value = NULL;
1664 conversation_t* conversation;
1665 static address null_address = { AT_NONE, 0, NULL };
1668 dissect_function_t *dissect_function = NULL;
1669 gboolean dissect_rpc = TRUE;
1672 * Check to see whether this looks like an RPC call or reply.
1674 if (!tvb_bytes_exist(tvb, offset, 8)) {
1675 /* Captured data in packet isn't enough to let us tell. */
1679 /* both directions need at least this */
1680 msg_type = tvb_get_ntohl(tvb, offset + 4);
1685 /* check for RPC call */
1686 if (!tvb_bytes_exist(tvb, offset, 16)) {
1687 /* Captured data in packet isn't enough to let us
1692 /* XID can be anything, we don't check it.
1693 We already have the message type.
1694 Check whether an RPC version number of 2 is in the
1695 location where it would be, and that an RPC program
1696 number we know about is in the location where it would be. */
1697 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1698 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1699 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1701 /* They're not, so it's probably not an RPC call. */
1707 /* Check for RPC reply. A reply must match a call that
1708 we've seen, and the reply must be sent to the same
1709 port and address that the call came from, and must
1710 come from the port to which the call was sent.
1712 If the transport is connection-oriented (we check, for
1713 now, only for "pinfo->ptype" of PT_TCP), we take
1714 into account the address from which the call was sent
1715 and the address to which the call was sent, because
1716 the addresses of the two endpoints should be the same
1717 for all calls and replies.
1719 If the transport is connectionless, we don't worry
1720 about the address to which the call was sent and from
1721 which the reply was sent, because there's no
1722 guarantee that the reply will come from the address
1723 to which the call was sent. */
1724 if (pinfo->ptype == PT_TCP) {
1725 conversation = find_conversation(&pinfo->src,
1726 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1727 pinfo->destport, 0);
1730 * XXX - can we just use NO_ADDR_B? Unfortunately,
1731 * you currently still have to pass a non-null
1732 * pointer for the second address argument even
1735 conversation = find_conversation(&null_address,
1736 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1737 pinfo->destport, 0);
1739 if (conversation == NULL) {
1740 /* We haven't seen an RPC call for that conversation,
1741 so we can't check for a reply to that call. */
1745 /* The XIDs of the call and reply must match. */
1746 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1747 rpc_call_key.conversation = conversation;
1748 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1749 if (rpc_call == NULL) {
1750 /* The XID doesn't match a call from that
1751 conversation, so it's probably not an RPC reply. */
1754 /* pass rpc_info to subdissectors */
1755 rpc_call->request=FALSE;
1756 pinfo->private_data=rpc_call;
1760 /* The putative message type field contains neither
1761 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1768 * This is RPC-over-TCP; check if this is the last
1771 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
1773 * This isn't the last fragment.
1774 * If we're doing reassembly, just return
1775 * TRUE to indicate that this looks like
1776 * the beginning of an RPC message,
1777 * and let them do fragment reassembly.
1784 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1785 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1788 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1790 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1793 show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm,
1798 xid = tvb_get_ntohl(tvb, offset + 0);
1800 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1801 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1804 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1806 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1807 offset+4, 4, msg_type);
1815 /* we know already the proto-entry, the ETT-const,
1817 proto = rpc_prog->proto;
1818 ett = rpc_prog->ett;
1819 progname = rpc_prog->progname;
1821 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1823 proto_tree_add_uint(rpc_tree,
1824 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1827 prog = tvb_get_ntohl(tvb, offset + 4);
1830 proto_tree_add_uint_format(rpc_tree,
1831 hf_rpc_program, tvb, offset+4, 4, prog,
1832 "Program: %s (%u)", progname, prog);
1835 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1836 /* Set the protocol name to the underlying
1838 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1841 vers = tvb_get_ntohl(tvb, offset+8);
1843 proto_tree_add_uint(rpc_tree,
1844 hf_rpc_programversion, tvb, offset+8, 4, vers);
1847 proc = tvb_get_ntohl(tvb, offset+12);
1853 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1854 dissect_function = value->dissect_call;
1855 procname = value->name;
1858 /* happens only with strange program versions or
1859 non-existing dissectors */
1861 dissect_function = NULL;
1863 sprintf(procname_static, "proc-%u", proc);
1864 procname = procname_static;
1867 /* Check for RPCSEC_GSS and AUTH_GSSAPI */
1868 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1869 switch (tvb_get_ntohl(tvb, offset+16)) {
1873 * It's GSS-API authentication...
1875 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1877 * ...and we have the procedure
1878 * and service information for it.
1880 flavor = FLAVOR_GSSAPI;
1881 gss_proc = tvb_get_ntohl(tvb, offset+28);
1882 gss_svc = tvb_get_ntohl(tvb, offset+36);
1885 * ...but the procedure and service
1886 * information isn't available.
1888 flavor = FLAVOR_GSSAPI_NO_INFO;
1894 * AUTH_GSSAPI flavor. If auth_msg is TRUE,
1895 * then this is an AUTH_GSSAPI message and
1896 * not an application level message.
1898 if (tvb_bytes_exist(tvb, offset+28, 4)) {
1899 if (tvb_get_ntohl(tvb, offset+28)) {
1900 flavor = FLAVOR_AUTHGSSAPI_MSG;
1903 match_strval(gss_proc,
1904 rpc_authgssapi_proc);
1906 flavor = FLAVOR_AUTHGSSAPI;
1913 * It's not GSS-API authentication.
1915 flavor = FLAVOR_NOT_GSSAPI;
1921 proto_tree_add_uint_format(rpc_tree,
1922 hf_rpc_procedure, tvb, offset+12, 4, proc,
1923 "Procedure: %s (%u)", procname, proc);
1926 if (check_col(pinfo->cinfo, COL_INFO)) {
1928 col_clear(pinfo->cinfo, COL_INFO);
1930 col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
1931 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1938 /* Keep track of the address and port whence the call came,
1939 and the port to which the call is being sent, so that
1940 we can match up calls with replies.
1942 If the transport is connection-oriented (we check, for
1943 now, only for "pinfo->ptype" of PT_TCP), we take
1944 into account the address from which the call was sent
1945 and the address to which the call was sent, because
1946 the addresses of the two endpoints should be the same
1947 for all calls and replies.
1949 If the transport is connectionless, we don't worry
1950 about the address to which the call was sent and from
1951 which the reply was sent, because there's no
1952 guarantee that the reply will come from the address
1953 to which the call was sent. */
1954 if (pinfo->ptype == PT_TCP) {
1955 conversation = find_conversation(&pinfo->src,
1956 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1957 pinfo->destport, 0);
1960 * XXX - can we just use NO_ADDR_B? Unfortunately,
1961 * you currently still have to pass a non-null
1962 * pointer for the second address argument even
1965 conversation = find_conversation(&pinfo->src,
1966 &null_address, pinfo->ptype, pinfo->srcport,
1967 pinfo->destport, 0);
1969 if (conversation == NULL) {
1970 /* It's not part of any conversation - create a new
1972 if (pinfo->ptype == PT_TCP) {
1973 conversation = conversation_new(&pinfo->src,
1974 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1975 pinfo->destport, 0);
1977 conversation = conversation_new(&pinfo->src,
1978 &null_address, pinfo->ptype, pinfo->srcport,
1979 pinfo->destport, 0);
1983 /* Make the dissector for this conversation the non-heuristic
1985 conversation_set_dissector(conversation,
1986 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1988 /* prepare the key data */
1989 rpc_call_key.xid = xid;
1990 rpc_call_key.conversation = conversation;
1992 /* look up the request */
1993 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1994 if (rpc_call != NULL) {
1995 /* We've seen a request with this XID, with the same
1996 source and destination, before - but was it
1998 if (pinfo->fd->num != rpc_call->req_num) {
1999 /* No, so it's a duplicate request.
2001 if (check_col(pinfo->cinfo, COL_INFO)) {
2002 col_append_fstr(pinfo->cinfo, COL_INFO,
2003 " dup XID 0x%x", xid);
2005 proto_tree_add_uint_hidden(rpc_tree,
2006 hf_rpc_dup, tvb, 0,0, xid);
2007 proto_tree_add_uint_hidden(rpc_tree,
2008 hf_rpc_call_dup, tvb, 0,0, xid);
2014 /* Prepare the value data.
2015 "req_num" and "rep_num" are frame numbers;
2016 frame numbers are 1-origin, so we use 0
2017 to mean "we don't yet know in which frame
2018 the reply for this call appears". */
2019 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
2020 *new_rpc_call_key = rpc_call_key;
2021 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
2022 rpc_call->req_num = pinfo->fd->num;
2023 rpc_call->rep_num = 0;
2024 rpc_call->prog = prog;
2025 rpc_call->vers = vers;
2026 rpc_call->proc = proc;
2027 rpc_call->private_data = NULL;
2028 rpc_call->xid = xid;
2029 rpc_call->flavor = flavor;
2030 rpc_call->gss_proc = gss_proc;
2031 rpc_call->gss_svc = gss_svc;
2032 rpc_call->proc_info = value;
2033 rpc_call->req_time.secs=pinfo->fd->abs_secs;
2034 rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
2037 g_hash_table_insert(rpc_calls, new_rpc_call_key,
2041 if(rpc_call && rpc_call->rep_num){
2042 proto_tree_add_uint_format(rpc_tree, hf_rpc_repframe,
2043 tvb, 0, 0, rpc_call->rep_num,
2044 "The reply to this request is in frame %u",
2050 offset = dissect_rpc_cred(tvb, rpc_tree, offset);
2051 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2053 /* pass rpc_info to subdissectors */
2054 rpc_call->request=TRUE;
2055 pinfo->private_data=rpc_call;
2057 /* go to the next dissector */
2059 break; /* end of RPC call */
2062 /* we know already the type from the calling routine,
2063 and we already have "rpc_call" set above. */
2064 prog = rpc_call->prog;
2065 vers = rpc_call->vers;
2066 proc = rpc_call->proc;
2067 flavor = rpc_call->flavor;
2068 gss_proc = rpc_call->gss_proc;
2069 gss_svc = rpc_call->gss_svc;
2071 if (rpc_call->proc_info != NULL) {
2072 dissect_function = rpc_call->proc_info->dissect_reply;
2073 if (rpc_call->proc_info->name != NULL) {
2074 procname = rpc_call->proc_info->name;
2077 sprintf(procname_static, "proc-%u", proc);
2078 procname = procname_static;
2083 dissect_function = NULL;
2085 sprintf(procname_static, "proc-%u", proc);
2086 procname = procname_static;
2090 * If this is an AUTH_GSSAPI message, then the RPC procedure
2091 * is not an application procedure, but rather an auth level
2092 * procedure, so it would be misleading to print the RPC
2093 * procname. Replace the RPC procname with the corresponding
2094 * AUTH_GSSAPI procname.
2096 if (flavor == FLAVOR_AUTHGSSAPI_MSG) {
2097 procname = match_strval(gss_proc, rpc_authgssapi_proc);
2100 rpc_prog_key.prog = prog;
2101 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
2104 progname = "Unknown";
2107 proto = rpc_prog->proto;
2108 ett = rpc_prog->ett;
2109 progname = rpc_prog->progname;
2111 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2112 /* Set the protocol name to the underlying
2114 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
2118 if (check_col(pinfo->cinfo, COL_INFO)) {
2120 col_clear(pinfo->cinfo, COL_INFO);
2122 col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
2123 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
2131 proto_tree_add_uint_format(rpc_tree,
2132 hf_rpc_program, tvb, 0, 0, prog,
2133 "Program: %s (%u)", progname, prog);
2134 proto_tree_add_uint(rpc_tree,
2135 hf_rpc_programversion, tvb, 0, 0, vers);
2136 proto_tree_add_uint_format(rpc_tree,
2137 hf_rpc_procedure, tvb, 0, 0, proc,
2138 "Procedure: %s (%u)", procname, proc);
2141 reply_state = tvb_get_ntohl(tvb,offset+0);
2143 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
2144 offset+0, 4, reply_state);
2148 /* Indicate the frame to which this is a reply. */
2149 if(rpc_call && rpc_call->req_num){
2150 proto_tree_add_uint_format(rpc_tree, hf_rpc_reqframe,
2151 tvb, 0, 0, rpc_call->req_num,
2152 "This is a reply to a request in frame %u",
2154 ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
2155 ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
2157 ns.nsecs+=1000000000;
2160 proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
2165 if (rpc_call->rep_num == 0) {
2166 /* We have not yet seen a reply to that call, so
2167 this must be the first reply; remember its
2169 rpc_call->rep_num = pinfo->fd->num;
2171 /* We have seen a reply to this call - but was it
2173 if (rpc_call->rep_num != pinfo->fd->num) {
2174 /* No, so it's a duplicate reply.
2176 if (check_col(pinfo->cinfo, COL_INFO)) {
2177 col_append_fstr(pinfo->cinfo, COL_INFO,
2178 " dup XID 0x%x", xid);
2180 proto_tree_add_uint_hidden(rpc_tree,
2181 hf_rpc_dup, tvb, 0,0, xid);
2182 proto_tree_add_uint_hidden(rpc_tree,
2183 hf_rpc_reply_dup, tvb, 0,0, xid);
2189 switch (reply_state) {
2192 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2193 accept_state = tvb_get_ntohl(tvb,offset+0);
2195 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
2196 offset+0, 4, accept_state);
2199 switch (accept_state) {
2202 /* go to the next dissector */
2206 vers_low = tvb_get_ntohl(tvb,offset+0);
2207 vers_high = tvb_get_ntohl(tvb,offset+4);
2209 proto_tree_add_uint(rpc_tree,
2210 hf_rpc_programversion_min,
2211 tvb, offset+0, 4, vers_low);
2212 proto_tree_add_uint(rpc_tree,
2213 hf_rpc_programversion_max,
2214 tvb, offset+4, 4, vers_high);
2219 * There's no protocol reply, so don't
2220 * try to dissect it.
2222 dissect_rpc = FALSE;
2227 * There's no protocol reply, so don't
2228 * try to dissect it.
2230 dissect_rpc = FALSE;
2236 reject_state = tvb_get_ntohl(tvb,offset+0);
2238 proto_tree_add_uint(rpc_tree,
2239 hf_rpc_state_reject, tvb, offset+0, 4,
2244 if (reject_state==RPC_MISMATCH) {
2245 vers_low = tvb_get_ntohl(tvb,offset+0);
2246 vers_high = tvb_get_ntohl(tvb,offset+4);
2248 proto_tree_add_uint(rpc_tree,
2250 tvb, offset+0, 4, vers_low);
2251 proto_tree_add_uint(rpc_tree,
2253 tvb, offset+4, 4, vers_high);
2256 } else if (reject_state==AUTH_ERROR) {
2257 auth_state = tvb_get_ntohl(tvb,offset+0);
2259 proto_tree_add_uint(rpc_tree,
2260 hf_rpc_state_auth, tvb, offset+0, 4,
2267 * There's no protocol reply, so don't
2268 * try to dissect it.
2270 dissect_rpc = FALSE;
2275 * This isn't a valid reply state, so we have
2276 * no clue what's going on; don't try to dissect
2277 * the protocol reply.
2279 dissect_rpc = FALSE;
2282 break; /* end of RPC reply */
2286 * The switch statement at the top returned if
2287 * this was neither an RPC call nor a reply.
2289 g_assert_not_reached();
2292 /* now we know, that RPC was shorter */
2294 proto_item_set_end(rpc_item, tvb, offset);
2299 * There's no RPC call or reply here; just dissect
2300 * whatever's left as data.
2302 call_dissector(data_handle,
2303 tvb_new_subset(tvb, offset, -1, -1), pinfo, rpc_tree);
2307 /* create here the program specific sub-tree */
2308 if (tree && (flavor != FLAVOR_AUTHGSSAPI_MSG)) {
2309 pitem = proto_tree_add_item(tree, proto, tvb, offset, -1,
2312 ptree = proto_item_add_subtree(pitem, ett);
2316 proto_tree_add_uint(ptree,
2317 hf_rpc_programversion, tvb, 0, 0, vers);
2318 if (rpc_prog->procedure_hfs->len > vers)
2319 procedure_hf = g_array_index(rpc_prog->procedure_hfs, int, vers);
2322 * No such element in the GArray.
2326 if (procedure_hf != 0 && procedure_hf != -1) {
2327 proto_tree_add_uint(ptree,
2328 procedure_hf, tvb, 0, 0, proc);
2330 proto_tree_add_uint_format(ptree,
2331 hf_rpc_procedure, tvb, 0, 0, proc,
2332 "Procedure: %s (%u)", procname, proc);
2337 /* we must queue this packet to the tap system before we actually
2338 call the subdissectors since short packets (i.e. nfs read reply)
2339 will cause an exception and execution would never reach the call
2340 to tap_queue_packet() in that case
2342 tap_queue_packet(rpc_tap, pinfo, rpc_call);
2345 if (!proto_is_protocol_enabled(proto))
2346 dissect_function = NULL;
2349 * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
2353 case FLAVOR_UNKNOWN:
2355 * We don't know the authentication flavor, so we can't
2356 * dissect the payload.
2358 proto_tree_add_text(ptree, tvb, offset, -1,
2359 "Unknown authentication flavor - cannot dissect");
2362 case FLAVOR_NOT_GSSAPI:
2364 * It's not GSS-API authentication. Just dissect the
2367 offset = call_dissect_function(tvb, pinfo, ptree, offset,
2368 dissect_function, progname);
2371 case FLAVOR_GSSAPI_NO_INFO:
2373 * It's GSS-API authentication, but we don't have the
2374 * procedure and service information, so we can't dissect
2377 proto_tree_add_text(ptree, tvb, offset, -1,
2378 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2383 * It's GSS-API authentication, and we have the procedure
2384 * and service information; process the GSS-API stuff,
2385 * and process the payload if there is any.
2389 case RPCSEC_GSS_INIT:
2390 case RPCSEC_GSS_CONTINUE_INIT:
2391 if (msg_type == RPC_CALL) {
2392 offset = dissect_rpc_authgss_initarg(tvb,
2393 ptree, offset, pinfo);
2396 offset = dissect_rpc_authgss_initres(tvb,
2397 ptree, offset, pinfo);
2401 case RPCSEC_GSS_DATA:
2402 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2403 offset = call_dissect_function(tvb,
2404 pinfo, ptree, offset,
2408 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2409 offset = dissect_rpc_authgss_integ_data(tvb,
2410 pinfo, ptree, offset,
2414 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2415 offset = dissect_rpc_authgss_priv_data(tvb,
2425 case FLAVOR_AUTHGSSAPI_MSG:
2427 * This is an AUTH_GSSAPI message. It contains data
2428 * only for the authentication procedure and not for the
2429 * application level RPC procedure. Reset the column
2430 * protocol and info fields to indicate that this is
2431 * an RPC auth level message, then process the args.
2433 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2434 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
2436 if (check_col(pinfo->cinfo, COL_INFO)) {
2437 col_clear(pinfo->cinfo, COL_INFO);
2438 col_append_fstr(pinfo->cinfo, COL_INFO,
2440 match_strval(gss_proc, rpc_authgssapi_proc),
2441 msg_type_name, xid);
2446 case AUTH_GSSAPI_INIT:
2447 case AUTH_GSSAPI_CONTINUE_INIT:
2448 case AUTH_GSSAPI_MSG:
2449 if (msg_type == RPC_CALL) {
2450 offset = dissect_rpc_authgssapi_initarg(tvb,
2451 rpc_tree, offset, pinfo);
2453 offset = dissect_rpc_authgssapi_initres(tvb,
2454 rpc_tree, offset, pinfo);
2458 case AUTH_GSSAPI_DESTROY:
2459 offset = dissect_rpc_data(tvb, rpc_tree,
2460 hf_rpc_authgss_data, offset);
2463 case AUTH_GSSAPI_EXIT:
2467 /* Adjust the length to account for the auth message. */
2469 proto_item_set_end(rpc_item, tvb, offset);
2473 case FLAVOR_AUTHGSSAPI:
2475 * An RPC with AUTH_GSSAPI authentication. The data
2476 * portion is always private, so don't call the dissector.
2478 offset = dissect_auth_gssapi_data(tvb, ptree, offset);
2482 /* dissect any remaining bytes (incomplete dissection) as pure data in
2484 call_dissector(data_handle,
2485 tvb_new_subset(tvb, offset, -1, -1), pinfo, ptree);
2488 /* XXX this should really loop over all fhandles registred for the frame */
2489 if(nfs_fhandle_reqrep_matching){
2490 nfs_fhandle_data_t *fhd;
2493 if(rpc_call && rpc_call->rep_num){
2494 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
2495 nfs_fhandle_frame_table,
2496 (gconstpointer)rpc_call->rep_num);
2498 dissect_fhandle_hidden(pinfo,
2504 if(rpc_call && rpc_call->req_num){
2505 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
2506 nfs_fhandle_frame_table,
2507 (gconstpointer)rpc_call->req_num);
2509 dissect_fhandle_hidden(pinfo,
2521 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2523 return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2528 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2530 if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2532 if (tvb_length(tvb) != 0)
2533 dissect_rpc_continuation(tvb, pinfo, tree);
2538 /* Defragmentation of RPC-over-TCP records */
2539 /* table to hold defragmented RPC records */
2540 static GHashTable *rpc_fragment_table = NULL;
2542 static GHashTable *rpc_reassembly_table = NULL;
2543 static GMemChunk *rpc_fragment_key_chunk = NULL;
2544 static int rpc_fragment_init_count = 200;
2546 typedef struct _rpc_fragment_key {
2555 rpc_fragment_hash(gconstpointer k)
2557 const rpc_fragment_key *key = (const rpc_fragment_key *)k;
2559 return key->conv_id + key->seq;
2563 rpc_fragment_equal(gconstpointer k1, gconstpointer k2)
2565 const rpc_fragment_key *key1 = (const rpc_fragment_key *)k1;
2566 const rpc_fragment_key *key2 = (const rpc_fragment_key *)k2;
2568 return key1->conv_id == key2->conv_id &&
2569 key1->seq == key2->seq;
2573 show_rpc_fragheader(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2575 proto_item *hdr_item;
2576 proto_tree *hdr_tree;
2580 fraglen = rpc_rm & RPC_RM_FRAGLEN;
2582 hdr_item = proto_tree_add_text(tree, tvb, 0, 4,
2583 "Fragment header: %s%u %s",
2584 (rpc_rm & RPC_RM_LASTFRAG) ? "Last fragment, " : "",
2585 fraglen, plurality(fraglen, "byte", "bytes"));
2586 hdr_tree = proto_item_add_subtree(hdr_item, ett_rpc_fraghdr);
2588 proto_tree_add_boolean(hdr_tree, hf_rpc_lastfrag, tvb, 0, 4,
2590 proto_tree_add_uint(hdr_tree, hf_rpc_fraglen, tvb, 0, 4,
2596 show_rpc_fragment(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2600 * Show the fragment header and the data for the fragment.
2602 show_rpc_fragheader(tvb, tree, rpc_rm);
2603 proto_tree_add_text(tree, tvb, 4, -1, "Fragment Data");
2608 make_frag_tree(tvbuff_t *tvb, proto_tree *tree, int proto, gint ett,
2611 proto_item *frag_item;
2612 proto_tree *frag_tree;
2615 return; /* nothing to do */
2617 frag_item = proto_tree_add_protocol_format(tree, proto, tvb, 0, -1,
2618 "%s Fragment", proto_get_protocol_name(proto));
2619 frag_tree = proto_item_add_subtree(frag_item, ett);
2620 show_rpc_fragment(tvb, frag_tree, rpc_rm);
2624 show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
2625 guint32 rpc_rm, fragment_data *ipfd_head, packet_info *pinfo)
2628 return; /* don't do any work */
2630 if (tvb != frag_tvb) {
2632 * This message was not all in one fragment,
2633 * so show the fragment header *and* the data
2634 * for the fragment (which is the last fragment),
2635 * and a tree with information about all fragments.
2637 show_rpc_fragment(frag_tvb, tree, rpc_rm);
2640 * Show a tree with information about all fragments.
2642 show_fragment_tree(ipfd_head, &rpc_frag_items, tree, pinfo, tvb);
2645 * This message was all in one fragment, so just show
2646 * the fragment header.
2648 show_rpc_fragheader(tvb, tree, rpc_rm);
2653 call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
2654 proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector,
2655 fragment_data *ipfd_head, guint32 rpc_rm, gboolean first_pdu)
2657 const char *saved_proto;
2658 volatile gboolean rpc_succeeded;
2661 * Catch the ReportedBoundsError exception; if
2662 * this particular message happens to get a
2663 * ReportedBoundsError exception, that doesn't
2664 * mean that we should stop dissecting RPC
2665 * messages within this frame or chunk of
2668 * If it gets a BoundsError, we can stop, as there's
2669 * nothing more to see, so we just re-throw it.
2671 saved_proto = pinfo->current_proto;
2672 rpc_succeeded = FALSE;
2674 rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
2675 frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu);
2677 CATCH(BoundsError) {
2680 CATCH(ReportedBoundsError) {
2681 show_reported_bounds_error(tvb, pinfo, tree);
2682 pinfo->current_proto = saved_proto;
2685 * We treat this as a "successful" dissection of
2686 * an RPC packet, as "dissect_rpc_message()"
2687 * *did* decide it was an RPC packet, throwing
2688 * an exception while dissecting it as such.
2690 rpc_succeeded = TRUE;
2693 return rpc_succeeded;
2697 dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
2698 proto_tree *tree, rec_dissector_t dissector, gboolean is_heur,
2699 int proto, int ett, gboolean defragment, gboolean first_pdu)
2701 struct tcpinfo *tcpinfo = pinfo->private_data;
2702 guint32 seq = tcpinfo->seq + offset;
2704 volatile gint32 len;
2706 gint tvb_len, tvb_reported_len;
2708 gboolean rpc_succeeded;
2709 gboolean save_fragmented;
2710 rpc_fragment_key old_rfk, *rfk, *new_rfk;
2711 conversation_t *conversation;
2712 fragment_data *ipfd_head;
2716 * Get the record mark.
2718 if (!tvb_bytes_exist(tvb, offset, 4)) {
2720 * XXX - we should somehow arrange to handle
2721 * a record mark split across TCP segments.
2723 return 0; /* not enough to tell if it's valid */
2725 rpc_rm = tvb_get_ntohl(tvb, offset);
2727 len = rpc_rm & RPC_RM_FRAGLEN;
2730 * Do TCP desegmentation, if enabled.
2732 * XXX - reject fragments bigger than 2 megabytes.
2733 * This is arbitrary, but should at least prevent
2734 * some crashes from either packets with really
2735 * large RPC-over-TCP fragments or from stuff that's
2736 * not really valid for this protocol.
2738 if (len > 2*1024*1024)
2739 return 0; /* pretend it's not valid */
2740 if (rpc_desegment) {
2741 seglen = tvb_length_remaining(tvb, offset + 4);
2743 if (len > seglen && pinfo->can_desegment) {
2745 * This frame doesn't have all of the
2746 * data for this message, but we can do
2749 * If this is a heuristic dissector, just
2750 * return 0 - we don't want to try to get
2751 * more data, as that's too likely to cause
2752 * us to misidentify this as valid.
2754 * If this isn't a heuristic dissector,
2755 * we've already identified this conversation
2756 * as containing data for this protocol, as we
2757 * saw valid data in previous frames. Try to
2761 return 0; /* not valid */
2763 pinfo->desegment_offset = offset;
2764 pinfo->desegment_len = len - seglen;
2765 return -pinfo->desegment_len;
2769 len += 4; /* include record mark */
2770 tvb_len = tvb_length_remaining(tvb, offset);
2771 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2774 if (tvb_reported_len > len)
2775 tvb_reported_len = len;
2776 frag_tvb = tvb_new_subset(tvb, offset, tvb_len,
2780 * If we're not defragmenting, just hand this to the
2785 * This is the first fragment we've seen, and it's also
2786 * the last fragment; that means the record wasn't
2787 * fragmented. Hand the dissector the tvbuff for the
2788 * fragment as the tvbuff for the record.
2794 * Mark this as fragmented, so if somebody throws an
2795 * exception, we don't report it as a malformed frame.
2797 save_fragmented = pinfo->fragmented;
2798 pinfo->fragmented = TRUE;
2799 rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo,
2800 tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu);
2801 pinfo->fragmented = save_fragmented;
2803 return 0; /* not RPC */
2808 * First, we check to see if this fragment is part of a record
2809 * that we're in the process of defragmenting.
2811 * The key is the conversation ID for the conversation to which
2812 * the packet belongs and the current sequence number.
2813 * We must first find the conversation and, if we don't find
2814 * one, create it. We know this is running over TCP, so the
2815 * conversation should not wildcard either address or port.
2817 conversation = find_conversation(&pinfo->src, &pinfo->dst,
2818 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2819 if (conversation == NULL) {
2821 * It's not part of any conversation - create a new one.
2823 conversation = conversation_new(&pinfo->src, &pinfo->dst,
2824 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2826 old_rfk.conv_id = conversation->index;
2828 rfk = g_hash_table_lookup(rpc_reassembly_table, &old_rfk);
2832 * This fragment was not found in our table, so it doesn't
2833 * contain a continuation of a higher-level PDU.
2834 * Is it the last fragment?
2836 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
2838 * This isn't the last fragment, so we don't
2839 * have the complete record.
2841 * It's the first fragment we've seen, so if
2842 * it's truly the first fragment of the record,
2843 * and it has enough data, the dissector can at
2844 * least check whether it looks like a valid
2845 * message, as it contains the start of the
2848 * The dissector should not dissect anything
2849 * if the "last fragment" flag isn't set in
2850 * the record marker, so it shouldn't throw
2853 if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb,
2854 NULL, TRUE, rpc_rm, first_pdu))
2855 return 0; /* not valid */
2858 * OK, now start defragmentation with that
2859 * fragment. Add this fragment, and set up
2860 * next packet/sequence number as well.
2862 * We must remember this fragment.
2865 rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2866 rfk->conv_id = conversation->index;
2869 rfk->start_seq = seq;
2870 g_hash_table_insert(rpc_reassembly_table, rfk, rfk);
2873 * Start defragmentation.
2875 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4,
2876 pinfo, rfk->start_seq, rpc_fragment_table,
2877 rfk->offset, len - 4, TRUE);
2880 * Make sure that defragmentation isn't complete;
2881 * it shouldn't be, as this is the first fragment
2882 * we've seen, and the "last fragment" bit wasn't
2885 g_assert(ipfd_head == NULL);
2887 new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2888 new_rfk->conv_id = rfk->conv_id;
2889 new_rfk->seq = seq + len;
2890 new_rfk->offset = rfk->offset + len - 4;
2891 new_rfk->start_seq = rfk->start_seq;
2892 g_hash_table_insert(rpc_reassembly_table, new_rfk,
2896 * This is part of a fragmented record,
2897 * but it's not the first part.
2898 * Show it as a record marker plus data, under
2899 * a top-level tree for this protocol.
2901 make_frag_tree(frag_tvb, tree, proto, ett,rpc_rm);
2904 * No more processing need be done, as we don't
2905 * have a complete record.
2911 * This is the first fragment we've seen, and it's also
2912 * the last fragment; that means the record wasn't
2913 * fragmented. Hand the dissector the tvbuff for the
2914 * fragment as the tvbuff for the record.
2920 * OK, this fragment was found, which means it continues
2921 * a record. This means we must defragment it.
2922 * Add it to the defragmentation lists.
2924 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4, pinfo,
2925 rfk->start_seq, rpc_fragment_table,
2926 rfk->offset, len - 4, !(rpc_rm & RPC_RM_LASTFRAG));
2928 if (ipfd_head == NULL) {
2930 * fragment_add_multiple_ok() returned NULL.
2931 * This means that defragmentation is not
2934 * We must add an entry to the hash table with
2935 * the sequence number following this fragment
2936 * as the starting sequence number, so that when
2937 * we see that fragment we'll find that entry.
2939 * XXX - as TCP stream data is not currently
2940 * guaranteed to be provided in order to dissectors,
2941 * RPC fragments aren't guaranteed to be provided
2944 new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2945 new_rfk->conv_id = rfk->conv_id;
2946 new_rfk->seq = seq + len;
2947 new_rfk->offset = rfk->offset + len - 4;
2948 new_rfk->start_seq = rfk->start_seq;
2949 g_hash_table_insert(rpc_reassembly_table, new_rfk,
2953 * This is part of a fragmented record,
2954 * but it's not the first part.
2955 * Show it as a record marker plus data, under
2956 * a top-level tree for this protocol,
2957 * but don't hand it to the dissector
2959 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
2962 * No more processing need be done, as we don't
2963 * have a complete record.
2969 * It's completely defragmented.
2971 * We only call subdissector for the last fragment.
2972 * XXX - this assumes in-order delivery of RPC
2973 * fragments, which requires in-order delivery of TCP
2976 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
2978 * Well, it's defragmented, but this isn't
2979 * the last fragment; this probably means
2980 * this isn't the first pass, so we don't
2981 * need to start defragmentation.
2983 * This is part of a fragmented record,
2984 * but it's not the first part.
2985 * Show it as a record marker plus data, under
2986 * a top-level tree for this protocol,
2987 * but don't show it to the dissector.
2989 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
2992 * No more processing need be done, as we
2993 * only disssect the data with the last
3000 * OK, this is the last segment.
3001 * Create a tvbuff for the defragmented
3006 * Create a new TVB structure for
3007 * defragmented data.
3009 rec_tvb = tvb_new_real_data(ipfd_head->data,
3010 ipfd_head->datalen, ipfd_head->datalen);
3013 * Add this tvb as a child to the original
3016 tvb_set_child_real_data_tvbuff(tvb, rec_tvb);
3019 * Add defragmented data to the data source list.
3021 add_new_data_source(pinfo, rec_tvb, "Defragmented");
3025 * We have something to hand to the RPC message
3028 if (!call_message_dissector(tvb, rec_tvb, pinfo, tree,
3029 frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu))
3030 return 0; /* not RPC */
3037 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
3039 * IS_RPC, if we dissected at least one message in its entirety
3042 * IS_NOT_RPC, if we found no RPC message.
3050 static rpc_tcp_return_t
3051 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3055 gboolean saw_rpc = FALSE;
3056 gboolean first_pdu = TRUE;
3059 while (tvb_reported_length_remaining(tvb, offset) != 0) {
3061 * Process this fragment.
3063 len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
3064 dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
3065 rpc_defragment, first_pdu);
3069 * We need more data from the TCP stream for
3072 return NEED_MORE_DATA;
3076 * It's not RPC. Stop processing.
3082 If the length indicates that the PDU continues beyond
3083 the end of this tvb, then tell TCP about it so that it
3084 knows where the next PDU starts.
3085 This is to help TCP detect when PDUs are not aligned to
3086 segment boundaries and allow it to find RPC headers
3087 that starts in the middle of a TCP segment.
3089 if(!pinfo->fd->flags.visited){
3090 if(len>tvb_reported_length_remaining(tvb, offset)){
3091 pinfo->want_pdu_tracking=2;
3092 pinfo->bytes_until_next_pdu=len-tvb_reported_length_remaining(tvb, offset);
3098 return saw_rpc ? IS_RPC : IS_NOT_RPC;
3102 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3104 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
3113 /* "Can't happen" */
3114 g_assert_not_reached();
3120 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3122 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
3123 dissect_rpc_continuation(tvb, pinfo, tree);
3126 /* Discard any state we've saved. */
3128 rpc_init_protocol(void)
3130 if (rpc_calls != NULL) {
3131 g_hash_table_destroy(rpc_calls);
3134 if (rpc_indir_calls != NULL) {
3135 g_hash_table_destroy(rpc_indir_calls);
3136 rpc_indir_calls = NULL;
3138 if (rpc_call_info_key_chunk != NULL) {
3139 g_mem_chunk_destroy(rpc_call_info_key_chunk);
3140 rpc_call_info_key_chunk = NULL;
3142 if (rpc_call_info_value_chunk != NULL) {
3143 g_mem_chunk_destroy(rpc_call_info_value_chunk);
3144 rpc_call_info_value_chunk = NULL;
3146 if (rpc_fragment_key_chunk != NULL) {
3147 g_mem_chunk_destroy(rpc_fragment_key_chunk);
3148 rpc_fragment_key_chunk = NULL;
3150 if (rpc_reassembly_table != NULL) {
3151 g_hash_table_destroy(rpc_reassembly_table);
3152 rpc_reassembly_table = NULL;
3155 rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
3156 rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
3157 rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
3158 sizeof(rpc_call_info_key),
3159 200 * sizeof(rpc_call_info_key),
3161 rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
3162 sizeof(rpc_call_info_value),
3163 200 * sizeof(rpc_call_info_value),
3165 rpc_fragment_key_chunk = g_mem_chunk_new("rpc_fragment_key_chunk",
3166 sizeof(rpc_fragment_key),
3167 rpc_fragment_init_count*sizeof(rpc_fragment_key),
3169 rpc_reassembly_table = g_hash_table_new(rpc_fragment_hash,
3170 rpc_fragment_equal);
3172 fragment_table_init(&rpc_fragment_table);
3175 /* will be called once from register.c at startup time */
3177 proto_register_rpc(void)
3179 static hf_register_info hf[] = {
3180 { &hf_rpc_reqframe, {
3181 "Request Frame", "rpc.reqframe", FT_FRAMENUM, BASE_NONE,
3182 NULL, 0, "Request Frame", HFILL }},
3183 { &hf_rpc_repframe, {
3184 "Reply Frame", "rpc.repframe", FT_FRAMENUM, BASE_NONE,
3185 NULL, 0, "Reply Frame", HFILL }},
3186 { &hf_rpc_lastfrag, {
3187 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, 32,
3188 &yesno, RPC_RM_LASTFRAG, "Last Fragment", HFILL }},
3189 { &hf_rpc_fraglen, {
3190 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
3191 NULL, RPC_RM_FRAGLEN, "Fragment Length", HFILL }},
3193 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
3194 NULL, 0, "XID", HFILL }},
3195 { &hf_rpc_msgtype, {
3196 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
3197 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
3198 { &hf_rpc_state_reply, {
3199 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
3200 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
3201 { &hf_rpc_state_accept, {
3202 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
3203 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
3204 { &hf_rpc_state_reject, {
3205 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
3206 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
3207 { &hf_rpc_state_auth, {
3208 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
3209 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
3210 { &hf_rpc_version, {
3211 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
3212 NULL, 0, "RPC Version", HFILL }},
3213 { &hf_rpc_version_min, {
3214 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
3215 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3216 { &hf_rpc_version_max, {
3217 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
3218 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
3219 { &hf_rpc_program, {
3220 "Program", "rpc.program", FT_UINT32, BASE_DEC,
3221 NULL, 0, "Program", HFILL }},
3222 { &hf_rpc_programversion, {
3223 "Program Version", "rpc.programversion", FT_UINT32,
3224 BASE_DEC, NULL, 0, "Program Version", HFILL }},
3225 { &hf_rpc_programversion_min, {
3226 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
3227 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3228 { &hf_rpc_programversion_max, {
3229 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
3230 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
3231 { &hf_rpc_procedure, {
3232 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
3233 NULL, 0, "Procedure", HFILL }},
3234 { &hf_rpc_auth_flavor, {
3235 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
3236 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
3237 { &hf_rpc_auth_length, {
3238 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
3239 NULL, 0, "Length", HFILL }},
3240 { &hf_rpc_auth_stamp, {
3241 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
3242 NULL, 0, "Stamp", HFILL }},
3243 { &hf_rpc_auth_uid, {
3244 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
3245 NULL, 0, "UID", HFILL }},
3246 { &hf_rpc_auth_gid, {
3247 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
3248 NULL, 0, "GID", HFILL }},
3249 { &hf_rpc_authgss_v, {
3250 "GSS Version", "rpc.authgss.version", FT_UINT32,
3251 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
3252 { &hf_rpc_authgss_proc, {
3253 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
3254 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
3255 { &hf_rpc_authgss_seq, {
3256 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
3257 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
3258 { &hf_rpc_authgss_svc, {
3259 "GSS Service", "rpc.authgss.service", FT_UINT32,
3260 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
3261 { &hf_rpc_authgss_ctx, {
3262 "GSS Context", "rpc.authgss.context", FT_BYTES,
3263 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
3264 { &hf_rpc_authgss_major, {
3265 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
3266 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
3267 { &hf_rpc_authgss_minor, {
3268 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
3269 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
3270 { &hf_rpc_authgss_window, {
3271 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
3272 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
3273 { &hf_rpc_authgss_token_length, {
3274 "GSS Token Length", "rpc.authgss.token_length", FT_UINT32,
3275 BASE_DEC, NULL, 0, "GSS Token Length", HFILL }},
3276 { &hf_rpc_authgss_data_length, {
3277 "Length", "rpc.authgss.data.length", FT_UINT32,
3278 BASE_DEC, NULL, 0, "Length", HFILL }},
3279 { &hf_rpc_authgss_data, {
3280 "GSS Data", "rpc.authgss.data", FT_BYTES,
3281 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
3282 { &hf_rpc_authgss_checksum, {
3283 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
3284 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
3285 { &hf_rpc_authgssapi_v, {
3286 "AUTH_GSSAPI Version", "rpc.authgssapi.version",
3287 FT_UINT32, BASE_DEC, NULL, 0, "AUTH_GSSAPI Version",
3289 { &hf_rpc_authgssapi_msg, {
3290 "AUTH_GSSAPI Message", "rpc.authgssapi.message",
3291 FT_BOOLEAN, BASE_NONE, &yesno, 0, "AUTH_GSSAPI Message",
3293 { &hf_rpc_authgssapi_msgv, {
3294 "Msg Version", "rpc.authgssapi.msgversion",
3295 FT_UINT32, BASE_DEC, NULL, 0, "Msg Version",
3297 { &hf_rpc_authgssapi_handle, {
3298 "Client Handle", "rpc.authgssapi.handle",
3299 FT_BYTES, BASE_HEX, NULL, 0, "Client Handle", HFILL }},
3300 { &hf_rpc_authgssapi_isn, {
3301 "Signed ISN", "rpc.authgssapi.isn",
3302 FT_BYTES, BASE_HEX, NULL, 0, "Signed ISN", HFILL }},
3303 { &hf_rpc_authdes_namekind, {
3304 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
3305 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
3306 { &hf_rpc_authdes_netname, {
3307 "Netname", "rpc.authdes.netname", FT_STRING,
3308 BASE_DEC, NULL, 0, "Netname", HFILL }},
3309 { &hf_rpc_authdes_convkey, {
3310 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
3311 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
3312 { &hf_rpc_authdes_window, {
3313 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
3314 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
3315 { &hf_rpc_authdes_nickname, {
3316 "Nickname", "rpc.authdes.nickname", FT_UINT32,
3317 BASE_HEX, NULL, 0, "Nickname", HFILL }},
3318 { &hf_rpc_authdes_timestamp, {
3319 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
3320 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
3321 { &hf_rpc_authdes_windowverf, {
3322 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
3323 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
3324 { &hf_rpc_authdes_timeverf, {
3325 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
3326 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
3327 { &hf_rpc_auth_machinename, {
3328 "Machine Name", "rpc.auth.machinename", FT_STRING,
3329 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
3331 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
3332 NULL, 0, "Duplicate Transaction", HFILL }},
3333 { &hf_rpc_call_dup, {
3334 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
3335 NULL, 0, "Duplicate Call", HFILL }},
3336 { &hf_rpc_reply_dup, {
3337 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
3338 NULL, 0, "Duplicate Reply", HFILL }},
3339 { &hf_rpc_value_follows, {
3340 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
3341 &yesno, 0, "Value Follows", HFILL }},
3342 { &hf_rpc_array_len, {
3343 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
3344 NULL, 0, "Length of RPC array", HFILL }},
3347 "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
3348 NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
3350 { &hf_rpc_fragment_overlap,
3351 { "Fragment overlap", "rpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3352 "Fragment overlaps with other fragments", HFILL }},
3354 { &hf_rpc_fragment_overlap_conflict,
3355 { "Conflicting data in fragment overlap", "rpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3356 "Overlapping fragments contained conflicting data", HFILL }},
3358 { &hf_rpc_fragment_multiple_tails,
3359 { "Multiple tail fragments found", "rpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3360 "Several tails were found when defragmenting the packet", HFILL }},
3362 { &hf_rpc_fragment_too_long_fragment,
3363 { "Fragment too long", "rpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3364 "Fragment contained data past end of packet", HFILL }},
3366 { &hf_rpc_fragment_error,
3367 { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3368 "Defragmentation error due to illegal fragments", HFILL }},
3371 { "RPC Fragment", "rpc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3372 "RPC Fragment", HFILL }},
3374 { &hf_rpc_fragments,
3375 { "RPC Fragments", "rpc.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
3376 "RPC Fragments", HFILL }},
3378 static gint *ett[] = {
3390 &ett_rpc_authgssapi_msg,
3392 module_t *rpc_module;
3394 proto_rpc = proto_register_protocol("Remote Procedure Call",
3396 proto_register_field_array(proto_rpc, hf, array_length(hf));
3397 proto_register_subtree_array(ett, array_length(ett));
3398 register_init_routine(&rpc_init_protocol);
3400 rpc_module = prefs_register_protocol(proto_rpc, NULL);
3401 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
3402 "Desegment all RPC-over-TCP messages",
3403 "Whether the RPC dissector should desegment all RPC-over-TCP messages",
3405 prefs_register_bool_preference(rpc_module, "defragment_rpc_over_tcp",
3406 "Defragment all RPC-over-TCP messages",
3407 "Whether the RPC dissector should defragment multi-fragment RPC-over-TCP messages",
3410 register_dissector("rpc", dissect_rpc, proto_rpc);
3411 rpc_handle = find_dissector("rpc");
3412 register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
3413 rpc_tcp_handle = find_dissector("rpc-tcp");
3414 rpc_tap = register_tap("rpc");
3417 * Init the hash tables. Dissectors for RPC protocols must
3418 * have a "handoff registration" routine that registers the
3419 * protocol with RPC; they must not do it in their protocol
3420 * registration routine, as their protocol registration
3421 * routine might be called before this routine is called and
3422 * thus might be called before the hash tables are initialized,
3423 * but it's guaranteed that all protocol registration routines
3424 * will be called before any handoff registration routines
3427 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
3428 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
3432 proto_reg_handoff_rpc(void)
3434 dissector_handle_t rpc_tcp_handle;
3435 dissector_handle_t rpc_udp_handle;
3437 /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
3438 we register onc-rpc on this port so that we can choose RPC in
3439 the list offered by DecodeAs, and so that traffic to or from
3440 port 111 from or to a higher-numbered port is dissected as RPC
3441 even if there's a dissector registered on the other port (it's
3442 probably RPC traffic from some randomly-chosen port that happens
3443 to match some port for which we have a dissector)
3445 rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
3446 dissector_add("tcp.port", 111, rpc_tcp_handle);
3447 rpc_udp_handle = create_dissector_handle(dissect_rpc, proto_rpc);
3448 dissector_add("udp.port", 111, rpc_udp_handle);
3450 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
3451 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
3452 gssapi_handle = find_dissector("gssapi");
3453 data_handle = find_dissector("data");