2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.131 2003/05/23 17:46:05 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);
672 offset += string_length_copy;
676 if (fill_truncated) {
677 proto_tree_add_text(string_tree, tvb,
678 offset,fill_length_copy,
679 "fill bytes: opaque data<TRUNCATED>");
682 proto_tree_add_text(string_tree, tvb,
683 offset,fill_length_copy,
684 "fill bytes: opaque data");
687 offset += fill_length_copy;
691 proto_item_set_end(string_item, tvb, offset);
693 if (string_buffer != NULL)
694 g_free(string_buffer);
695 if (string_buffer_print != NULL) {
696 if (string_buffer_ret != NULL)
697 *string_buffer_ret = string_buffer_print;
699 g_free(string_buffer_print);
703 * If the data was truncated, throw the appropriate exception,
704 * so that dissection stops and the frame is properly marked.
713 dissect_rpc_string(tvbuff_t *tvb, proto_tree *tree,
714 int hfindex, int offset, char **string_buffer_ret)
716 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
717 hfindex, FALSE, 0, TRUE, string_buffer_ret, NULL);
723 dissect_rpc_data(tvbuff_t *tvb, proto_tree *tree,
724 int hfindex, int offset)
726 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
727 hfindex, FALSE, 0, FALSE, NULL, NULL);
733 dissect_rpc_bytes(tvbuff_t *tvb, proto_tree *tree,
734 int hfindex, int offset, guint32 length,
735 gboolean string_data, char **string_buffer_ret)
737 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
738 hfindex, TRUE, length, string_data, string_buffer_ret, NULL);
744 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
745 int offset, dissect_function_t *rpc_list_dissector)
747 guint32 value_follows;
750 value_follows = tvb_get_ntohl(tvb, offset+0);
751 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
752 offset+0, 4, value_follows);
754 if (value_follows == 1) {
755 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
766 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
767 int offset, dissect_function_t *rpc_array_dissector,
770 proto_item* lock_item;
771 proto_tree* lock_tree;
774 num = tvb_get_ntohl(tvb, offset);
777 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
784 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset, -1, FALSE);
786 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
788 offset = dissect_rpc_uint32(tvb, lock_tree,
789 hf_rpc_array_len, offset);
792 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
795 proto_item_set_end(lock_item, tvb, offset);
800 dissect_rpc_authunix_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
809 proto_tree *gtree = NULL;
811 stamp = tvb_get_ntohl(tvb,offset+0);
813 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
817 offset = dissect_rpc_string(tvb, tree,
818 hf_rpc_auth_machinename, offset, NULL);
820 uid = tvb_get_ntohl(tvb,offset+0);
822 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
826 gid = tvb_get_ntohl(tvb,offset+0);
828 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
832 gids_count = tvb_get_ntohl(tvb,offset+0);
834 gitem = proto_tree_add_text(tree, tvb,
835 offset, 4+gids_count*4, "Auxiliary GIDs");
836 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
840 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
841 gids_entry = tvb_get_ntohl(tvb,offset+0);
843 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
844 offset, 4, gids_entry);
847 /* how can I NOW change the gitem to print a list with
848 the first 16 gids? */
854 dissect_rpc_authgss_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
861 agc_v = tvb_get_ntohl(tvb, offset+0);
863 proto_tree_add_uint(tree, hf_rpc_authgss_v,
864 tvb, offset+0, 4, agc_v);
867 agc_proc = tvb_get_ntohl(tvb, offset+0);
869 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
870 tvb, offset+0, 4, agc_proc);
873 agc_seq = tvb_get_ntohl(tvb, offset+0);
875 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
876 tvb, offset+0, 4, agc_seq);
879 agc_svc = tvb_get_ntohl(tvb, offset+0);
881 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
882 tvb, offset+0, 4, agc_svc);
885 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
892 dissect_rpc_authdes_desblock(tvbuff_t *tvb, proto_tree *tree,
893 int hfindex, int offset)
898 value_high = tvb_get_ntohl(tvb, offset + 0);
899 value_low = tvb_get_ntohl(tvb, offset + 4);
902 proto_tree_add_text(tree, tvb, offset, 8,
903 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
911 dissect_rpc_authdes_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
917 adc_namekind = tvb_get_ntohl(tvb, offset+0);
919 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
920 tvb, offset+0, 4, adc_namekind);
925 case AUTHDES_NAMEKIND_FULLNAME:
926 offset = dissect_rpc_string(tvb, tree,
927 hf_rpc_authdes_netname, offset, NULL);
928 offset = dissect_rpc_authdes_desblock(tvb, tree,
929 hf_rpc_authdes_convkey, offset);
930 window = tvb_get_ntohl(tvb, offset+0);
931 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
936 case AUTHDES_NAMEKIND_NICKNAME:
937 nickname = tvb_get_ntohl(tvb, offset+0);
938 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
948 dissect_rpc_authgssapi_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
953 agc_v = tvb_get_ntohl(tvb, offset+0);
955 proto_tree_add_uint(tree, hf_rpc_authgssapi_v,
956 tvb, offset+0, 4, agc_v);
959 agc_msg = tvb_get_ntohl(tvb, offset+0);
961 proto_tree_add_boolean(tree, hf_rpc_authgssapi_msg,
962 tvb, offset+0, 4, agc_msg);
965 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgssapi_handle,
972 dissect_rpc_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
980 flavor = tvb_get_ntohl(tvb,offset+0);
981 length = tvb_get_ntohl(tvb,offset+4);
982 length = rpc_roundup(length);
985 citem = proto_tree_add_text(tree, tvb, offset,
986 8+length, "Credentials");
987 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
988 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
989 offset+0, 4, flavor);
990 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
991 offset+4, 4, length);
995 dissect_rpc_authunix_cred(tvb, ctree, offset+8);
1003 dissect_rpc_authdes_cred(tvb, ctree, offset+8);
1007 dissect_rpc_authgss_cred(tvb, ctree, offset+8);
1011 dissect_rpc_authgssapi_cred(tvb, ctree, offset+8);
1016 proto_tree_add_text(ctree, tvb, offset+8,
1017 length,"opaque data");
1021 offset += 8 + length;
1027 * XDR opaque object, the contents of which are interpreted as a GSS-API
1031 dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
1034 guint32 opaque_length, rounded_length;
1035 gint len_consumed, length, reported_length;
1039 proto_tree *gtree = NULL;
1041 opaque_length = tvb_get_ntohl(tvb, offset+0);
1042 rounded_length = rpc_roundup(opaque_length);
1044 gitem = proto_tree_add_text(tree, tvb, offset,
1045 4+rounded_length, "GSS Token");
1046 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_token);
1047 proto_tree_add_uint(gtree, hf_rpc_authgss_token_length,
1048 tvb, offset+0, 4, opaque_length);
1051 length = tvb_length_remaining(tvb, offset);
1052 reported_length = tvb_reported_length_remaining(tvb, offset);
1053 g_assert(length >= 0);
1054 g_assert(reported_length >= 0);
1055 if (length > reported_length)
1056 length = reported_length;
1057 if ((guint32)length > opaque_length)
1058 length = opaque_length;
1059 if ((guint32)reported_length > opaque_length)
1060 reported_length = opaque_length;
1061 new_tvb = tvb_new_subset(tvb, offset, length, reported_length);
1062 len_consumed = call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1063 offset += len_consumed;
1064 offset = rpc_roundup(offset);
1068 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
1069 * verifier we're decoding (CALL or REPLY).
1072 dissect_rpc_verf(tvbuff_t* tvb, proto_tree* tree, int offset, int msg_type,
1081 flavor = tvb_get_ntohl(tvb,offset+0);
1082 length = tvb_get_ntohl(tvb,offset+4);
1083 length = rpc_roundup(length);
1086 vitem = proto_tree_add_text(tree, tvb, offset,
1087 8+length, "Verifier");
1088 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
1089 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
1090 offset+0, 4, flavor);
1094 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1095 offset+4, 4, length);
1096 dissect_rpc_authunix_cred(tvb, vtree, offset+8);
1099 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1100 offset+4, 4, length);
1102 if (msg_type == RPC_CALL)
1106 dissect_rpc_authdes_desblock(tvb, vtree,
1107 hf_rpc_authdes_timestamp, offset+8);
1108 window = tvb_get_ntohl(tvb, offset+16);
1109 proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
1110 offset+16, 4, window);
1114 /* must be an RPC_REPLY */
1117 dissect_rpc_authdes_desblock(tvb, vtree,
1118 hf_rpc_authdes_timeverf, offset+8);
1119 nickname = tvb_get_ntohl(tvb, offset+16);
1120 proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
1121 offset+16, 4, nickname);
1125 dissect_rpc_authgss_token(tvb, vtree, offset+4, pinfo);
1128 proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
1129 offset+4, 4, length);
1131 proto_tree_add_text(vtree, tvb, offset+8,
1132 length, "opaque data");
1136 offset += 8 + length;
1142 dissect_rpc_authgss_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
1145 return dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
1149 dissect_rpc_authgss_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
1152 int major, minor, window;
1154 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
1157 major = tvb_get_ntohl(tvb,offset+0);
1159 proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
1160 offset+0, 4, major);
1163 minor = tvb_get_ntohl(tvb,offset+0);
1165 proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
1166 offset+0, 4, minor);
1169 window = tvb_get_ntohl(tvb,offset+0);
1171 proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
1172 offset+0, 4, window);
1175 offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
1181 dissect_rpc_authgssapi_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
1186 proto_tree *mtree = NULL;
1189 mitem = proto_tree_add_text(tree, tvb, offset, -1,
1191 mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
1193 version = tvb_get_ntohl(tvb, offset+0);
1195 proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
1196 offset+0, 4, version);
1200 offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
1206 dissect_rpc_authgssapi_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
1212 proto_tree *mtree = NULL;
1215 mitem = proto_tree_add_text(tree, tvb, offset, -1,
1217 mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
1220 version = tvb_get_ntohl(tvb,offset+0);
1222 proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
1223 offset+0, 4, version);
1227 offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_handle,
1230 major = tvb_get_ntohl(tvb,offset+0);
1232 proto_tree_add_uint(mtree, hf_rpc_authgss_major, tvb,
1233 offset+0, 4, major);
1237 minor = tvb_get_ntohl(tvb,offset+0);
1239 proto_tree_add_uint(mtree, hf_rpc_authgss_minor, tvb,
1240 offset+0, 4, minor);
1244 offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
1246 offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_isn, offset);
1252 dissect_auth_gssapi_data(tvbuff_t *tvb, proto_tree *tree, int offset)
1254 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
1260 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1261 int offset, dissect_function_t* dissect_function, const char *progname)
1263 const char *saved_proto;
1265 if (dissect_function != NULL) {
1266 /* set the current protocol name */
1267 saved_proto = pinfo->current_proto;
1268 if (progname != NULL)
1269 pinfo->current_proto = progname;
1271 /* call the dissector for the next level */
1272 offset = dissect_function(tvb, offset, pinfo, tree);
1274 /* restore the protocol name */
1275 pinfo->current_proto = saved_proto;
1283 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1284 proto_tree *tree, int offset,
1285 dissect_function_t* dissect_function,
1286 const char *progname)
1288 guint32 length, rounded_length, seq;
1291 proto_tree *gtree = NULL;
1293 length = tvb_get_ntohl(tvb, offset+0);
1294 rounded_length = rpc_roundup(length);
1295 seq = tvb_get_ntohl(tvb, offset+4);
1298 gitem = proto_tree_add_text(tree, tvb, offset,
1299 4+rounded_length, "GSS Data");
1300 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1301 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1302 tvb, offset+0, 4, length);
1303 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1304 tvb, offset+4, 4, seq);
1308 if (dissect_function != NULL) {
1310 call_dissect_function(tvb, pinfo, gtree, offset,
1311 dissect_function, progname);
1313 offset += rounded_length - 4;
1314 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_checksum,
1321 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, proto_tree *tree, int offset)
1323 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
1329 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1332 * Record this call in a hash table, similar to the hash table for
1333 * direct calls, so we can find it when dissecting an indirect call reply.
1336 dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1337 int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
1339 conversation_t* conversation;
1340 static address null_address = { AT_NONE, 0, NULL };
1341 rpc_proc_info_key key;
1342 rpc_proc_info_value *value;
1343 rpc_call_info_value *rpc_call;
1344 rpc_call_info_key rpc_call_key;
1345 rpc_call_info_key *new_rpc_call_key;
1346 dissect_function_t *dissect_function = NULL;
1351 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1352 dissect_function = value->dissect_call;
1354 /* Keep track of the address and port whence the call came,
1355 and the port to which the call is being sent, so that
1356 we can match up calls with replies.
1358 If the transport is connection-oriented (we check, for
1359 now, only for "pinfo->ptype" of PT_TCP), we take
1360 into account the address from which the call was sent
1361 and the address to which the call was sent, because
1362 the addresses of the two endpoints should be the same
1363 for all calls and replies.
1365 If the transport is connectionless, we don't worry
1366 about the address to which the call was sent and from
1367 which the reply was sent, because there's no
1368 guarantee that the reply will come from the address
1369 to which the call was sent. */
1370 if (pinfo->ptype == PT_TCP) {
1371 conversation = find_conversation(&pinfo->src,
1372 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1373 pinfo->destport, 0);
1376 * XXX - can we just use NO_ADDR_B? Unfortunately,
1377 * you currently still have to pass a non-null
1378 * pointer for the second address argument even
1381 conversation = find_conversation(&pinfo->src,
1382 &null_address, pinfo->ptype, pinfo->srcport,
1383 pinfo->destport, 0);
1385 if (conversation == NULL) {
1386 /* It's not part of any conversation - create a new
1389 XXX - this should never happen, as we should've
1390 created a conversation for it in the RPC
1392 if (pinfo->ptype == PT_TCP) {
1393 conversation = conversation_new(&pinfo->src,
1394 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1395 pinfo->destport, 0);
1397 conversation = conversation_new(&pinfo->src,
1398 &null_address, pinfo->ptype, pinfo->srcport,
1399 pinfo->destport, 0);
1403 /* Make the dissector for this conversation the non-heuristic
1405 conversation_set_dissector(conversation,
1406 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1408 /* Prepare the key data.
1410 Dissectors for RPC procedure calls and replies shouldn't
1411 create new tvbuffs, and we don't create one ourselves,
1412 so we should have been handed the tvbuff for this RPC call;
1413 as such, the XID is at offset 0 in this tvbuff. */
1414 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1415 rpc_call_key.conversation = conversation;
1417 /* look up the request */
1418 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1419 if (rpc_call == NULL) {
1420 /* We didn't find it; create a new entry.
1421 Prepare the value data.
1422 Not all of it is needed for handling indirect
1423 calls, so we set a bunch of items to 0. */
1424 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
1425 *new_rpc_call_key = rpc_call_key;
1426 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
1427 rpc_call->req_num = 0;
1428 rpc_call->rep_num = 0;
1429 rpc_call->prog = prog;
1430 rpc_call->vers = vers;
1431 rpc_call->proc = proc;
1432 rpc_call->private_data = NULL;
1435 * XXX - what about RPCSEC_GSS?
1436 * Do we have to worry about it?
1438 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1439 rpc_call->gss_proc = 0;
1440 rpc_call->gss_svc = 0;
1441 rpc_call->proc_info = value;
1443 g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
1448 /* We don't know the procedure.
1449 Happens only with strange program versions or
1450 non-existing dissectors.
1451 Just show the arguments as opaque data. */
1452 offset = dissect_rpc_data(tvb, tree, args_id,
1459 proto_tree_add_text(tree, tvb, offset, 4,
1460 "Argument length: %u",
1461 tvb_get_ntohl(tvb, offset));
1465 /* Dissect the arguments */
1466 offset = call_dissect_function(tvb, pinfo, tree, offset,
1467 dissect_function, NULL);
1472 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1476 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1477 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1479 conversation_t* conversation;
1480 static address null_address = { AT_NONE, 0, NULL };
1481 rpc_call_info_key rpc_call_key;
1482 rpc_call_info_value *rpc_call;
1483 char *procname = NULL;
1484 char procname_static[20];
1485 dissect_function_t *dissect_function = NULL;
1487 /* Look for the matching call in the hash table of indirect
1488 calls. A reply must match a call that we've seen, and the
1489 reply must be sent to the same port and address that the
1490 call came from, and must come from the port to which the
1493 If the transport is connection-oriented (we check, for
1494 now, only for "pinfo->ptype" of PT_TCP), we take
1495 into account the address from which the call was sent
1496 and the address to which the call was sent, because
1497 the addresses of the two endpoints should be the same
1498 for all calls and replies.
1500 If the transport is connectionless, we don't worry
1501 about the address to which the call was sent and from
1502 which the reply was sent, because there's no
1503 guarantee that the reply will come from the address
1504 to which the call was sent. */
1505 if (pinfo->ptype == PT_TCP) {
1506 conversation = find_conversation(&pinfo->src, &pinfo->dst,
1507 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1510 * XXX - can we just use NO_ADDR_B? Unfortunately,
1511 * you currently still have to pass a non-null
1512 * pointer for the second address argument even
1515 conversation = find_conversation(&null_address, &pinfo->dst,
1516 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1518 if (conversation == NULL) {
1519 /* We haven't seen an RPC call for that conversation,
1520 so we can't check for a reply to that call.
1521 Just show the reply stuff as opaque data. */
1522 offset = dissect_rpc_data(tvb, tree, result_id,
1527 /* The XIDs of the call and reply must match. */
1528 rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
1529 rpc_call_key.conversation = conversation;
1530 rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
1531 if (rpc_call == NULL) {
1532 /* The XID doesn't match a call from that
1533 conversation, so it's probably not an RPC reply.
1534 Just show the reply stuff as opaque data. */
1535 offset = dissect_rpc_data(tvb, tree, result_id,
1540 if (rpc_call->proc_info != NULL) {
1541 dissect_function = rpc_call->proc_info->dissect_reply;
1542 if (rpc_call->proc_info->name != NULL) {
1543 procname = rpc_call->proc_info->name;
1546 sprintf(procname_static, "proc-%u", rpc_call->proc);
1547 procname = procname_static;
1552 dissect_function = NULL;
1554 sprintf(procname_static, "proc-%u", rpc_call->proc);
1555 procname = procname_static;
1560 /* Put the program, version, and procedure into the tree. */
1561 proto_tree_add_uint_format(tree, prog_id, tvb,
1562 0, 0, rpc_call->prog, "Program: %s (%u)",
1563 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1564 proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1565 proto_tree_add_uint_format(tree, proc_id, tvb,
1566 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1567 procname, rpc_call->proc);
1570 if (dissect_function == NULL) {
1571 /* We don't know how to dissect the reply procedure.
1572 Just show the reply stuff as opaque data. */
1573 offset = dissect_rpc_data(tvb, tree, result_id,
1579 /* Put the length of the reply value into the tree. */
1580 proto_tree_add_text(tree, tvb, offset, 4,
1581 "Argument length: %u",
1582 tvb_get_ntohl(tvb, offset));
1586 /* Dissect the return value */
1587 offset = call_dissect_function(tvb, pinfo, tree, offset,
1588 dissect_function, NULL);
1593 * Just mark this as a continuation of an earlier packet.
1596 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1598 proto_item *rpc_item;
1599 proto_tree *rpc_tree;
1601 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1602 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1603 if (check_col(pinfo->cinfo, COL_INFO))
1604 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1607 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1609 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1610 proto_tree_add_text(rpc_tree, tvb, 0, -1, "Continuation data");
1615 dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1616 tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
1617 guint32 rpc_rm, gboolean first_pdu)
1620 rpc_call_info_key rpc_call_key;
1621 rpc_call_info_value *rpc_call = NULL;
1622 rpc_prog_info_value *rpc_prog = NULL;
1623 rpc_prog_info_key rpc_prog_key;
1626 unsigned int rpcvers;
1627 unsigned int prog = 0;
1628 unsigned int vers = 0;
1629 unsigned int proc = 0;
1630 flavor_t flavor = FLAVOR_UNKNOWN;
1631 unsigned int gss_proc = 0;
1632 unsigned int gss_svc = 0;
1637 unsigned int reply_state;
1638 unsigned int accept_state;
1639 unsigned int reject_state;
1641 char *msg_type_name = NULL;
1642 char *progname = NULL;
1643 char *procname = NULL;
1644 static char procname_static[20];
1646 unsigned int vers_low;
1647 unsigned int vers_high;
1649 unsigned int auth_state;
1651 proto_item *rpc_item = NULL;
1652 proto_tree *rpc_tree = NULL;
1654 proto_item *pitem = NULL;
1655 proto_tree *ptree = NULL;
1656 int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
1658 rpc_call_info_key *new_rpc_call_key;
1659 rpc_proc_info_key key;
1660 rpc_proc_info_value *value = NULL;
1661 conversation_t* conversation;
1662 static address null_address = { AT_NONE, 0, NULL };
1665 dissect_function_t *dissect_function = NULL;
1666 gboolean dissect_rpc = TRUE;
1669 * Check to see whether this looks like an RPC call or reply.
1671 if (!tvb_bytes_exist(tvb, offset, 8)) {
1672 /* Captured data in packet isn't enough to let us tell. */
1676 /* both directions need at least this */
1677 msg_type = tvb_get_ntohl(tvb, offset + 4);
1682 /* check for RPC call */
1683 if (!tvb_bytes_exist(tvb, offset, 16)) {
1684 /* Captured data in packet isn't enough to let us
1689 /* XID can be anything, we don't check it.
1690 We already have the message type.
1691 Check whether an RPC version number of 2 is in the
1692 location where it would be, and that an RPC program
1693 number we know about is in the location where it would be. */
1694 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1695 if (tvb_get_ntohl(tvb, offset + 8) != 2 ||
1696 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1698 /* They're not, so it's probably not an RPC call. */
1704 /* Check for RPC reply. A reply must match a call that
1705 we've seen, and the reply must be sent to the same
1706 port and address that the call came from, and must
1707 come from the port to which the call was sent.
1709 If the transport is connection-oriented (we check, for
1710 now, only for "pinfo->ptype" of PT_TCP), we take
1711 into account the address from which the call was sent
1712 and the address to which the call was sent, because
1713 the addresses of the two endpoints should be the same
1714 for all calls and replies.
1716 If the transport is connectionless, we don't worry
1717 about the address to which the call was sent and from
1718 which the reply was sent, because there's no
1719 guarantee that the reply will come from the address
1720 to which the call was sent. */
1721 if (pinfo->ptype == PT_TCP) {
1722 conversation = find_conversation(&pinfo->src,
1723 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1724 pinfo->destport, 0);
1727 * XXX - can we just use NO_ADDR_B? Unfortunately,
1728 * you currently still have to pass a non-null
1729 * pointer for the second address argument even
1732 conversation = find_conversation(&null_address,
1733 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1734 pinfo->destport, 0);
1736 if (conversation == NULL) {
1737 /* We haven't seen an RPC call for that conversation,
1738 so we can't check for a reply to that call. */
1742 /* The XIDs of the call and reply must match. */
1743 rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
1744 rpc_call_key.conversation = conversation;
1745 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1746 if (rpc_call == NULL) {
1747 /* The XID doesn't match a call from that
1748 conversation, so it's probably not an RPC reply. */
1751 /* pass rpc_info to subdissectors */
1752 rpc_call->request=FALSE;
1753 pinfo->private_data=rpc_call;
1757 /* The putative message type field contains neither
1758 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1765 * This is RPC-over-TCP; check if this is the last
1768 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
1770 * This isn't the last fragment.
1771 * If we're doing reassembly, just return
1772 * TRUE to indicate that this looks like
1773 * the beginning of an RPC message,
1774 * and let them do fragment reassembly.
1781 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1782 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1785 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1787 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1790 show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm,
1795 xid = tvb_get_ntohl(tvb, offset + 0);
1797 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1798 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1801 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1803 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1804 offset+4, 4, msg_type);
1812 /* we know already the proto-entry, the ETT-const,
1814 proto = rpc_prog->proto;
1815 ett = rpc_prog->ett;
1816 progname = rpc_prog->progname;
1818 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1820 proto_tree_add_uint(rpc_tree,
1821 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1824 prog = tvb_get_ntohl(tvb, offset + 4);
1827 proto_tree_add_uint_format(rpc_tree,
1828 hf_rpc_program, tvb, offset+4, 4, prog,
1829 "Program: %s (%u)", progname, prog);
1832 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1833 /* Set the protocol name to the underlying
1835 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1838 vers = tvb_get_ntohl(tvb, offset+8);
1840 proto_tree_add_uint(rpc_tree,
1841 hf_rpc_programversion, tvb, offset+8, 4, vers);
1844 proc = tvb_get_ntohl(tvb, offset+12);
1850 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1851 dissect_function = value->dissect_call;
1852 procname = value->name;
1855 /* happens only with strange program versions or
1856 non-existing dissectors */
1858 dissect_function = NULL;
1860 sprintf(procname_static, "proc-%u", proc);
1861 procname = procname_static;
1864 /* Check for RPCSEC_GSS and AUTH_GSSAPI */
1865 if (tvb_bytes_exist(tvb, offset+16, 4)) {
1866 switch (tvb_get_ntohl(tvb, offset+16)) {
1870 * It's GSS-API authentication...
1872 if (tvb_bytes_exist(tvb, offset+28, 8)) {
1874 * ...and we have the procedure
1875 * and service information for it.
1877 flavor = FLAVOR_GSSAPI;
1878 gss_proc = tvb_get_ntohl(tvb, offset+28);
1879 gss_svc = tvb_get_ntohl(tvb, offset+36);
1882 * ...but the procedure and service
1883 * information isn't available.
1885 flavor = FLAVOR_GSSAPI_NO_INFO;
1891 * AUTH_GSSAPI flavor. If auth_msg is TRUE,
1892 * then this is an AUTH_GSSAPI message and
1893 * not an application level message.
1895 if (tvb_bytes_exist(tvb, offset+28, 4)) {
1896 if (tvb_get_ntohl(tvb, offset+28)) {
1897 flavor = FLAVOR_AUTHGSSAPI_MSG;
1900 match_strval(gss_proc,
1901 rpc_authgssapi_proc);
1903 flavor = FLAVOR_AUTHGSSAPI;
1910 * It's not GSS-API authentication.
1912 flavor = FLAVOR_NOT_GSSAPI;
1918 proto_tree_add_uint_format(rpc_tree,
1919 hf_rpc_procedure, tvb, offset+12, 4, proc,
1920 "Procedure: %s (%u)", procname, proc);
1923 if (check_col(pinfo->cinfo, COL_INFO)) {
1925 col_clear(pinfo->cinfo, COL_INFO);
1927 col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
1928 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
1935 /* Keep track of the address and port whence the call came,
1936 and the port to which the call is being sent, so that
1937 we can match up calls with replies.
1939 If the transport is connection-oriented (we check, for
1940 now, only for "pinfo->ptype" of PT_TCP), we take
1941 into account the address from which the call was sent
1942 and the address to which the call was sent, because
1943 the addresses of the two endpoints should be the same
1944 for all calls and replies.
1946 If the transport is connectionless, we don't worry
1947 about the address to which the call was sent and from
1948 which the reply was sent, because there's no
1949 guarantee that the reply will come from the address
1950 to which the call was sent. */
1951 if (pinfo->ptype == PT_TCP) {
1952 conversation = find_conversation(&pinfo->src,
1953 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1954 pinfo->destport, 0);
1957 * XXX - can we just use NO_ADDR_B? Unfortunately,
1958 * you currently still have to pass a non-null
1959 * pointer for the second address argument even
1962 conversation = find_conversation(&pinfo->src,
1963 &null_address, pinfo->ptype, pinfo->srcport,
1964 pinfo->destport, 0);
1966 if (conversation == NULL) {
1967 /* It's not part of any conversation - create a new
1969 if (pinfo->ptype == PT_TCP) {
1970 conversation = conversation_new(&pinfo->src,
1971 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1972 pinfo->destport, 0);
1974 conversation = conversation_new(&pinfo->src,
1975 &null_address, pinfo->ptype, pinfo->srcport,
1976 pinfo->destport, 0);
1980 /* Make the dissector for this conversation the non-heuristic
1982 conversation_set_dissector(conversation,
1983 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1985 /* prepare the key data */
1986 rpc_call_key.xid = xid;
1987 rpc_call_key.conversation = conversation;
1989 /* look up the request */
1990 rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
1991 if (rpc_call != NULL) {
1992 /* We've seen a request with this XID, with the same
1993 source and destination, before - but was it
1995 if (pinfo->fd->num != rpc_call->req_num) {
1996 /* No, so it's a duplicate request.
1998 if (check_col(pinfo->cinfo, COL_INFO)) {
1999 col_append_fstr(pinfo->cinfo, COL_INFO,
2000 " dup XID 0x%x", xid);
2002 proto_tree_add_uint_hidden(rpc_tree,
2003 hf_rpc_dup, tvb, 0,0, xid);
2004 proto_tree_add_uint_hidden(rpc_tree,
2005 hf_rpc_call_dup, tvb, 0,0, xid);
2011 /* Prepare the value data.
2012 "req_num" and "rep_num" are frame numbers;
2013 frame numbers are 1-origin, so we use 0
2014 to mean "we don't yet know in which frame
2015 the reply for this call appears". */
2016 new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
2017 *new_rpc_call_key = rpc_call_key;
2018 rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
2019 rpc_call->req_num = pinfo->fd->num;
2020 rpc_call->rep_num = 0;
2021 rpc_call->prog = prog;
2022 rpc_call->vers = vers;
2023 rpc_call->proc = proc;
2024 rpc_call->private_data = NULL;
2025 rpc_call->xid = xid;
2026 rpc_call->flavor = flavor;
2027 rpc_call->gss_proc = gss_proc;
2028 rpc_call->gss_svc = gss_svc;
2029 rpc_call->proc_info = value;
2030 rpc_call->req_time.secs=pinfo->fd->abs_secs;
2031 rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
2034 g_hash_table_insert(rpc_calls, new_rpc_call_key,
2038 if(rpc_call && rpc_call->rep_num){
2039 proto_tree_add_uint_format(rpc_tree, hf_rpc_repframe,
2040 tvb, 0, 0, rpc_call->rep_num,
2041 "The reply to this request is in frame %u",
2047 offset = dissect_rpc_cred(tvb, rpc_tree, offset);
2048 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2050 /* pass rpc_info to subdissectors */
2051 rpc_call->request=TRUE;
2052 pinfo->private_data=rpc_call;
2054 /* go to the next dissector */
2056 break; /* end of RPC call */
2059 /* we know already the type from the calling routine,
2060 and we already have "rpc_call" set above. */
2061 prog = rpc_call->prog;
2062 vers = rpc_call->vers;
2063 proc = rpc_call->proc;
2064 flavor = rpc_call->flavor;
2065 gss_proc = rpc_call->gss_proc;
2066 gss_svc = rpc_call->gss_svc;
2068 if (rpc_call->proc_info != NULL) {
2069 dissect_function = rpc_call->proc_info->dissect_reply;
2070 if (rpc_call->proc_info->name != NULL) {
2071 procname = rpc_call->proc_info->name;
2074 sprintf(procname_static, "proc-%u", proc);
2075 procname = procname_static;
2080 dissect_function = NULL;
2082 sprintf(procname_static, "proc-%u", proc);
2083 procname = procname_static;
2087 * If this is an AUTH_GSSAPI message, then the RPC procedure
2088 * is not an application procedure, but rather an auth level
2089 * procedure, so it would be misleading to print the RPC
2090 * procname. Replace the RPC procname with the corresponding
2091 * AUTH_GSSAPI procname.
2093 if (flavor == FLAVOR_AUTHGSSAPI_MSG) {
2094 procname = match_strval(gss_proc, rpc_authgssapi_proc);
2097 rpc_prog_key.prog = prog;
2098 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
2101 progname = "Unknown";
2104 proto = rpc_prog->proto;
2105 ett = rpc_prog->ett;
2106 progname = rpc_prog->progname;
2108 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2109 /* Set the protocol name to the underlying
2111 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
2115 if (check_col(pinfo->cinfo, COL_INFO)) {
2117 col_clear(pinfo->cinfo, COL_INFO);
2119 col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
2120 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s XID 0x%x",
2128 proto_tree_add_uint_format(rpc_tree,
2129 hf_rpc_program, tvb, 0, 0, prog,
2130 "Program: %s (%u)", progname, prog);
2131 proto_tree_add_uint(rpc_tree,
2132 hf_rpc_programversion, tvb, 0, 0, vers);
2133 proto_tree_add_uint_format(rpc_tree,
2134 hf_rpc_procedure, tvb, 0, 0, proc,
2135 "Procedure: %s (%u)", procname, proc);
2138 reply_state = tvb_get_ntohl(tvb,offset+0);
2140 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
2141 offset+0, 4, reply_state);
2145 /* Indicate the frame to which this is a reply. */
2146 if(rpc_call && rpc_call->req_num){
2147 proto_tree_add_uint_format(rpc_tree, hf_rpc_reqframe,
2148 tvb, 0, 0, rpc_call->req_num,
2149 "This is a reply to a request in frame %u",
2151 ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
2152 ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
2154 ns.nsecs+=1000000000;
2157 proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
2162 if (rpc_call->rep_num == 0) {
2163 /* We have not yet seen a reply to that call, so
2164 this must be the first reply; remember its
2166 rpc_call->rep_num = pinfo->fd->num;
2168 /* We have seen a reply to this call - but was it
2170 if (rpc_call->rep_num != pinfo->fd->num) {
2171 /* No, so it's a duplicate reply.
2173 if (check_col(pinfo->cinfo, COL_INFO)) {
2174 col_append_fstr(pinfo->cinfo, COL_INFO,
2175 " dup XID 0x%x", xid);
2177 proto_tree_add_uint_hidden(rpc_tree,
2178 hf_rpc_dup, tvb, 0,0, xid);
2179 proto_tree_add_uint_hidden(rpc_tree,
2180 hf_rpc_reply_dup, tvb, 0,0, xid);
2186 switch (reply_state) {
2189 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2190 accept_state = tvb_get_ntohl(tvb,offset+0);
2192 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
2193 offset+0, 4, accept_state);
2196 switch (accept_state) {
2199 /* go to the next dissector */
2203 vers_low = tvb_get_ntohl(tvb,offset+0);
2204 vers_high = tvb_get_ntohl(tvb,offset+4);
2206 proto_tree_add_uint(rpc_tree,
2207 hf_rpc_programversion_min,
2208 tvb, offset+0, 4, vers_low);
2209 proto_tree_add_uint(rpc_tree,
2210 hf_rpc_programversion_max,
2211 tvb, offset+4, 4, vers_high);
2216 * There's no protocol reply, so don't
2217 * try to dissect it.
2219 dissect_rpc = FALSE;
2224 * There's no protocol reply, so don't
2225 * try to dissect it.
2227 dissect_rpc = FALSE;
2233 reject_state = tvb_get_ntohl(tvb,offset+0);
2235 proto_tree_add_uint(rpc_tree,
2236 hf_rpc_state_reject, tvb, offset+0, 4,
2241 if (reject_state==RPC_MISMATCH) {
2242 vers_low = tvb_get_ntohl(tvb,offset+0);
2243 vers_high = tvb_get_ntohl(tvb,offset+4);
2245 proto_tree_add_uint(rpc_tree,
2247 tvb, offset+0, 4, vers_low);
2248 proto_tree_add_uint(rpc_tree,
2250 tvb, offset+4, 4, vers_high);
2253 } else if (reject_state==AUTH_ERROR) {
2254 auth_state = tvb_get_ntohl(tvb,offset+0);
2256 proto_tree_add_uint(rpc_tree,
2257 hf_rpc_state_auth, tvb, offset+0, 4,
2264 * There's no protocol reply, so don't
2265 * try to dissect it.
2267 dissect_rpc = FALSE;
2272 * This isn't a valid reply state, so we have
2273 * no clue what's going on; don't try to dissect
2274 * the protocol reply.
2276 dissect_rpc = FALSE;
2279 break; /* end of RPC reply */
2283 * The switch statement at the top returned if
2284 * this was neither an RPC call nor a reply.
2286 g_assert_not_reached();
2289 /* now we know, that RPC was shorter */
2291 proto_item_set_end(rpc_item, tvb, offset);
2296 * There's no RPC call or reply here; just dissect
2297 * whatever's left as data.
2299 call_dissector(data_handle,
2300 tvb_new_subset(tvb, offset, -1, -1), pinfo, rpc_tree);
2304 /* create here the program specific sub-tree */
2305 if (tree && (flavor != FLAVOR_AUTHGSSAPI_MSG)) {
2306 pitem = proto_tree_add_item(tree, proto, tvb, offset, -1,
2309 ptree = proto_item_add_subtree(pitem, ett);
2313 proto_tree_add_uint(ptree,
2314 hf_rpc_programversion, tvb, 0, 0, vers);
2315 if (rpc_prog->procedure_hfs->len > vers)
2316 procedure_hf = g_array_index(rpc_prog->procedure_hfs, int, vers);
2319 * No such element in the GArray.
2323 if (procedure_hf != 0 && procedure_hf != -1) {
2324 proto_tree_add_uint(ptree,
2325 procedure_hf, tvb, 0, 0, proc);
2327 proto_tree_add_uint_format(ptree,
2328 hf_rpc_procedure, tvb, 0, 0, proc,
2329 "Procedure: %s (%u)", procname, proc);
2334 /* we must queue this packet to the tap system before we actually
2335 call the subdissectors since short packets (i.e. nfs read reply)
2336 will cause an exception and execution would never reach the call
2337 to tap_queue_packet() in that case
2339 tap_queue_packet(rpc_tap, pinfo, rpc_call);
2342 if (!proto_is_protocol_enabled(proto))
2343 dissect_function = NULL;
2346 * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
2350 case FLAVOR_UNKNOWN:
2352 * We don't know the authentication flavor, so we can't
2353 * dissect the payload.
2355 proto_tree_add_text(ptree, tvb, offset, -1,
2356 "Unknown authentication flavor - cannot dissect");
2359 case FLAVOR_NOT_GSSAPI:
2361 * It's not GSS-API authentication. Just dissect the
2364 offset = call_dissect_function(tvb, pinfo, ptree, offset,
2365 dissect_function, progname);
2368 case FLAVOR_GSSAPI_NO_INFO:
2370 * It's GSS-API authentication, but we don't have the
2371 * procedure and service information, so we can't dissect
2374 proto_tree_add_text(ptree, tvb, offset, -1,
2375 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2380 * It's GSS-API authentication, and we have the procedure
2381 * and service information; process the GSS-API stuff,
2382 * and process the payload if there is any.
2386 case RPCSEC_GSS_INIT:
2387 case RPCSEC_GSS_CONTINUE_INIT:
2388 if (msg_type == RPC_CALL) {
2389 offset = dissect_rpc_authgss_initarg(tvb,
2390 ptree, offset, pinfo);
2393 offset = dissect_rpc_authgss_initres(tvb,
2394 ptree, offset, pinfo);
2398 case RPCSEC_GSS_DATA:
2399 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2400 offset = call_dissect_function(tvb,
2401 pinfo, ptree, offset,
2405 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2406 offset = dissect_rpc_authgss_integ_data(tvb,
2407 pinfo, ptree, offset,
2411 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2412 offset = dissect_rpc_authgss_priv_data(tvb,
2422 case FLAVOR_AUTHGSSAPI_MSG:
2424 * This is an AUTH_GSSAPI message. It contains data
2425 * only for the authentication procedure and not for the
2426 * application level RPC procedure. Reset the column
2427 * protocol and info fields to indicate that this is
2428 * an RPC auth level message, then process the args.
2430 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2431 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
2433 if (check_col(pinfo->cinfo, COL_INFO)) {
2434 col_clear(pinfo->cinfo, COL_INFO);
2435 col_append_fstr(pinfo->cinfo, COL_INFO,
2437 match_strval(gss_proc, rpc_authgssapi_proc),
2438 msg_type_name, xid);
2443 case AUTH_GSSAPI_INIT:
2444 case AUTH_GSSAPI_CONTINUE_INIT:
2445 case AUTH_GSSAPI_MSG:
2446 if (msg_type == RPC_CALL) {
2447 offset = dissect_rpc_authgssapi_initarg(tvb,
2448 rpc_tree, offset, pinfo);
2450 offset = dissect_rpc_authgssapi_initres(tvb,
2451 rpc_tree, offset, pinfo);
2455 case AUTH_GSSAPI_DESTROY:
2456 offset = dissect_rpc_data(tvb, rpc_tree,
2457 hf_rpc_authgss_data, offset);
2460 case AUTH_GSSAPI_EXIT:
2464 /* Adjust the length to account for the auth message. */
2466 proto_item_set_end(rpc_item, tvb, offset);
2470 case FLAVOR_AUTHGSSAPI:
2472 * An RPC with AUTH_GSSAPI authentication. The data
2473 * portion is always private, so don't call the dissector.
2475 offset = dissect_auth_gssapi_data(tvb, ptree, offset);
2479 if (tvb_length_remaining(tvb, offset) > 0) {
2481 * dissect any remaining bytes (incomplete dissection) as pure
2485 call_dissector(data_handle,
2486 tvb_new_subset(tvb, offset, -1, -1), pinfo, ptree);
2489 /* XXX this should really loop over all fhandles registred for the frame */
2490 if(nfs_fhandle_reqrep_matching){
2491 nfs_fhandle_data_t *fhd;
2494 if(rpc_call && rpc_call->rep_num){
2495 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
2496 nfs_fhandle_frame_table,
2497 (gconstpointer)rpc_call->rep_num);
2499 dissect_fhandle_hidden(pinfo,
2505 if(rpc_call && rpc_call->req_num){
2506 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
2507 nfs_fhandle_frame_table,
2508 (gconstpointer)rpc_call->req_num);
2510 dissect_fhandle_hidden(pinfo,
2522 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2524 return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2529 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2531 if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2533 if (tvb_length(tvb) != 0)
2534 dissect_rpc_continuation(tvb, pinfo, tree);
2539 /* Defragmentation of RPC-over-TCP records */
2540 /* table to hold defragmented RPC records */
2541 static GHashTable *rpc_fragment_table = NULL;
2543 static GHashTable *rpc_reassembly_table = NULL;
2544 static GMemChunk *rpc_fragment_key_chunk = NULL;
2545 static int rpc_fragment_init_count = 200;
2547 typedef struct _rpc_fragment_key {
2556 rpc_fragment_hash(gconstpointer k)
2558 const rpc_fragment_key *key = (const rpc_fragment_key *)k;
2560 return key->conv_id + key->seq;
2564 rpc_fragment_equal(gconstpointer k1, gconstpointer k2)
2566 const rpc_fragment_key *key1 = (const rpc_fragment_key *)k1;
2567 const rpc_fragment_key *key2 = (const rpc_fragment_key *)k2;
2569 return key1->conv_id == key2->conv_id &&
2570 key1->seq == key2->seq;
2574 show_rpc_fragheader(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2576 proto_item *hdr_item;
2577 proto_tree *hdr_tree;
2581 fraglen = rpc_rm & RPC_RM_FRAGLEN;
2583 hdr_item = proto_tree_add_text(tree, tvb, 0, 4,
2584 "Fragment header: %s%u %s",
2585 (rpc_rm & RPC_RM_LASTFRAG) ? "Last fragment, " : "",
2586 fraglen, plurality(fraglen, "byte", "bytes"));
2587 hdr_tree = proto_item_add_subtree(hdr_item, ett_rpc_fraghdr);
2589 proto_tree_add_boolean(hdr_tree, hf_rpc_lastfrag, tvb, 0, 4,
2591 proto_tree_add_uint(hdr_tree, hf_rpc_fraglen, tvb, 0, 4,
2597 show_rpc_fragment(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2601 * Show the fragment header and the data for the fragment.
2603 show_rpc_fragheader(tvb, tree, rpc_rm);
2604 proto_tree_add_text(tree, tvb, 4, -1, "Fragment Data");
2609 make_frag_tree(tvbuff_t *tvb, proto_tree *tree, int proto, gint ett,
2612 proto_item *frag_item;
2613 proto_tree *frag_tree;
2616 return; /* nothing to do */
2618 frag_item = proto_tree_add_protocol_format(tree, proto, tvb, 0, -1,
2619 "%s Fragment", proto_get_protocol_name(proto));
2620 frag_tree = proto_item_add_subtree(frag_item, ett);
2621 show_rpc_fragment(tvb, frag_tree, rpc_rm);
2625 show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
2626 guint32 rpc_rm, fragment_data *ipfd_head, packet_info *pinfo)
2629 return; /* don't do any work */
2631 if (tvb != frag_tvb) {
2633 * This message was not all in one fragment,
2634 * so show the fragment header *and* the data
2635 * for the fragment (which is the last fragment),
2636 * and a tree with information about all fragments.
2638 show_rpc_fragment(frag_tvb, tree, rpc_rm);
2641 * Show a tree with information about all fragments.
2643 show_fragment_tree(ipfd_head, &rpc_frag_items, tree, pinfo, tvb);
2646 * This message was all in one fragment, so just show
2647 * the fragment header.
2649 show_rpc_fragheader(tvb, tree, rpc_rm);
2654 call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
2655 proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector,
2656 fragment_data *ipfd_head, guint32 rpc_rm, gboolean first_pdu)
2658 const char *saved_proto;
2659 volatile gboolean rpc_succeeded;
2662 * Catch the ReportedBoundsError exception; if
2663 * this particular message happens to get a
2664 * ReportedBoundsError exception, that doesn't
2665 * mean that we should stop dissecting RPC
2666 * messages within this frame or chunk of
2669 * If it gets a BoundsError, we can stop, as there's
2670 * nothing more to see, so we just re-throw it.
2672 saved_proto = pinfo->current_proto;
2673 rpc_succeeded = FALSE;
2675 rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
2676 frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu);
2678 CATCH(BoundsError) {
2681 CATCH(ReportedBoundsError) {
2682 show_reported_bounds_error(tvb, pinfo, tree);
2683 pinfo->current_proto = saved_proto;
2686 * We treat this as a "successful" dissection of
2687 * an RPC packet, as "dissect_rpc_message()"
2688 * *did* decide it was an RPC packet, throwing
2689 * an exception while dissecting it as such.
2691 rpc_succeeded = TRUE;
2694 return rpc_succeeded;
2698 dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
2699 proto_tree *tree, rec_dissector_t dissector, gboolean is_heur,
2700 int proto, int ett, gboolean defragment, gboolean first_pdu)
2702 struct tcpinfo *tcpinfo = pinfo->private_data;
2703 guint32 seq = tcpinfo->seq + offset;
2705 volatile gint32 len;
2707 gint tvb_len, tvb_reported_len;
2709 gboolean rpc_succeeded;
2710 gboolean save_fragmented;
2711 rpc_fragment_key old_rfk, *rfk, *new_rfk;
2712 conversation_t *conversation;
2713 fragment_data *ipfd_head;
2717 * Get the record mark.
2719 if (!tvb_bytes_exist(tvb, offset, 4)) {
2721 * XXX - we should somehow arrange to handle
2722 * a record mark split across TCP segments.
2724 return 0; /* not enough to tell if it's valid */
2726 rpc_rm = tvb_get_ntohl(tvb, offset);
2728 len = rpc_rm & RPC_RM_FRAGLEN;
2731 * Do TCP desegmentation, if enabled.
2733 * XXX - reject fragments bigger than 2 megabytes.
2734 * This is arbitrary, but should at least prevent
2735 * some crashes from either packets with really
2736 * large RPC-over-TCP fragments or from stuff that's
2737 * not really valid for this protocol.
2739 if (len > 2*1024*1024)
2740 return 0; /* pretend it's not valid */
2741 if (rpc_desegment) {
2742 seglen = tvb_length_remaining(tvb, offset + 4);
2744 if (len > seglen && pinfo->can_desegment) {
2746 * This frame doesn't have all of the
2747 * data for this message, but we can do
2750 * If this is a heuristic dissector, just
2751 * return 0 - we don't want to try to get
2752 * more data, as that's too likely to cause
2753 * us to misidentify this as valid.
2755 * If this isn't a heuristic dissector,
2756 * we've already identified this conversation
2757 * as containing data for this protocol, as we
2758 * saw valid data in previous frames. Try to
2762 return 0; /* not valid */
2764 pinfo->desegment_offset = offset;
2765 pinfo->desegment_len = len - seglen;
2766 return -pinfo->desegment_len;
2770 len += 4; /* include record mark */
2771 tvb_len = tvb_length_remaining(tvb, offset);
2772 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2775 if (tvb_reported_len > len)
2776 tvb_reported_len = len;
2777 frag_tvb = tvb_new_subset(tvb, offset, tvb_len,
2781 * If we're not defragmenting, just hand this to the
2786 * This is the first fragment we've seen, and it's also
2787 * the last fragment; that means the record wasn't
2788 * fragmented. Hand the dissector the tvbuff for the
2789 * fragment as the tvbuff for the record.
2795 * Mark this as fragmented, so if somebody throws an
2796 * exception, we don't report it as a malformed frame.
2798 save_fragmented = pinfo->fragmented;
2799 pinfo->fragmented = TRUE;
2800 rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo,
2801 tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu);
2802 pinfo->fragmented = save_fragmented;
2804 return 0; /* not RPC */
2809 * First, we check to see if this fragment is part of a record
2810 * that we're in the process of defragmenting.
2812 * The key is the conversation ID for the conversation to which
2813 * the packet belongs and the current sequence number.
2814 * We must first find the conversation and, if we don't find
2815 * one, create it. We know this is running over TCP, so the
2816 * conversation should not wildcard either address or port.
2818 conversation = find_conversation(&pinfo->src, &pinfo->dst,
2819 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2820 if (conversation == NULL) {
2822 * It's not part of any conversation - create a new one.
2824 conversation = conversation_new(&pinfo->src, &pinfo->dst,
2825 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2827 old_rfk.conv_id = conversation->index;
2829 rfk = g_hash_table_lookup(rpc_reassembly_table, &old_rfk);
2833 * This fragment was not found in our table, so it doesn't
2834 * contain a continuation of a higher-level PDU.
2835 * Is it the last fragment?
2837 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
2839 * This isn't the last fragment, so we don't
2840 * have the complete record.
2842 * It's the first fragment we've seen, so if
2843 * it's truly the first fragment of the record,
2844 * and it has enough data, the dissector can at
2845 * least check whether it looks like a valid
2846 * message, as it contains the start of the
2849 * The dissector should not dissect anything
2850 * if the "last fragment" flag isn't set in
2851 * the record marker, so it shouldn't throw
2854 if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb,
2855 NULL, TRUE, rpc_rm, first_pdu))
2856 return 0; /* not valid */
2859 * OK, now start defragmentation with that
2860 * fragment. Add this fragment, and set up
2861 * next packet/sequence number as well.
2863 * We must remember this fragment.
2866 rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2867 rfk->conv_id = conversation->index;
2870 rfk->start_seq = seq;
2871 g_hash_table_insert(rpc_reassembly_table, rfk, rfk);
2874 * Start defragmentation.
2876 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4,
2877 pinfo, rfk->start_seq, rpc_fragment_table,
2878 rfk->offset, len - 4, TRUE);
2881 * Make sure that defragmentation isn't complete;
2882 * it shouldn't be, as this is the first fragment
2883 * we've seen, and the "last fragment" bit wasn't
2886 g_assert(ipfd_head == NULL);
2888 new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2889 new_rfk->conv_id = rfk->conv_id;
2890 new_rfk->seq = seq + len;
2891 new_rfk->offset = rfk->offset + len - 4;
2892 new_rfk->start_seq = rfk->start_seq;
2893 g_hash_table_insert(rpc_reassembly_table, new_rfk,
2897 * This is part of a fragmented record,
2898 * but it's not the first part.
2899 * Show it as a record marker plus data, under
2900 * a top-level tree for this protocol.
2902 make_frag_tree(frag_tvb, tree, proto, ett,rpc_rm);
2905 * No more processing need be done, as we don't
2906 * have a complete record.
2912 * This is the first fragment we've seen, and it's also
2913 * the last fragment; that means the record wasn't
2914 * fragmented. Hand the dissector the tvbuff for the
2915 * fragment as the tvbuff for the record.
2921 * OK, this fragment was found, which means it continues
2922 * a record. This means we must defragment it.
2923 * Add it to the defragmentation lists.
2925 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4, pinfo,
2926 rfk->start_seq, rpc_fragment_table,
2927 rfk->offset, len - 4, !(rpc_rm & RPC_RM_LASTFRAG));
2929 if (ipfd_head == NULL) {
2931 * fragment_add_multiple_ok() returned NULL.
2932 * This means that defragmentation is not
2935 * We must add an entry to the hash table with
2936 * the sequence number following this fragment
2937 * as the starting sequence number, so that when
2938 * we see that fragment we'll find that entry.
2940 * XXX - as TCP stream data is not currently
2941 * guaranteed to be provided in order to dissectors,
2942 * RPC fragments aren't guaranteed to be provided
2945 new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
2946 new_rfk->conv_id = rfk->conv_id;
2947 new_rfk->seq = seq + len;
2948 new_rfk->offset = rfk->offset + len - 4;
2949 new_rfk->start_seq = rfk->start_seq;
2950 g_hash_table_insert(rpc_reassembly_table, new_rfk,
2954 * This is part of a fragmented record,
2955 * but it's not the first part.
2956 * Show it as a record marker plus data, under
2957 * a top-level tree for this protocol,
2958 * but don't hand it to the dissector
2960 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
2963 * No more processing need be done, as we don't
2964 * have a complete record.
2970 * It's completely defragmented.
2972 * We only call subdissector for the last fragment.
2973 * XXX - this assumes in-order delivery of RPC
2974 * fragments, which requires in-order delivery of TCP
2977 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
2979 * Well, it's defragmented, but this isn't
2980 * the last fragment; this probably means
2981 * this isn't the first pass, so we don't
2982 * need to start defragmentation.
2984 * This is part of a fragmented record,
2985 * but it's not the first part.
2986 * Show it as a record marker plus data, under
2987 * a top-level tree for this protocol,
2988 * but don't show it to the dissector.
2990 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
2993 * No more processing need be done, as we
2994 * only disssect the data with the last
3001 * OK, this is the last segment.
3002 * Create a tvbuff for the defragmented
3007 * Create a new TVB structure for
3008 * defragmented data.
3010 rec_tvb = tvb_new_real_data(ipfd_head->data,
3011 ipfd_head->datalen, ipfd_head->datalen);
3014 * Add this tvb as a child to the original
3017 tvb_set_child_real_data_tvbuff(tvb, rec_tvb);
3020 * Add defragmented data to the data source list.
3022 add_new_data_source(pinfo, rec_tvb, "Defragmented");
3026 * We have something to hand to the RPC message
3029 if (!call_message_dissector(tvb, rec_tvb, pinfo, tree,
3030 frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu))
3031 return 0; /* not RPC */
3038 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
3040 * IS_RPC, if we dissected at least one message in its entirety
3043 * IS_NOT_RPC, if we found no RPC message.
3051 static rpc_tcp_return_t
3052 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3056 gboolean saw_rpc = FALSE;
3057 gboolean first_pdu = TRUE;
3060 while (tvb_reported_length_remaining(tvb, offset) != 0) {
3062 * Process this fragment.
3064 len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
3065 dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
3066 rpc_defragment, first_pdu);
3070 * We need more data from the TCP stream for
3073 return NEED_MORE_DATA;
3077 * It's not RPC. Stop processing.
3083 If the length indicates that the PDU continues beyond
3084 the end of this tvb, then tell TCP about it so that it
3085 knows where the next PDU starts.
3086 This is to help TCP detect when PDUs are not aligned to
3087 segment boundaries and allow it to find RPC headers
3088 that starts in the middle of a TCP segment.
3090 if(!pinfo->fd->flags.visited){
3091 if(len>tvb_reported_length_remaining(tvb, offset)){
3092 pinfo->want_pdu_tracking=2;
3093 pinfo->bytes_until_next_pdu=len-tvb_reported_length_remaining(tvb, offset);
3099 return saw_rpc ? IS_RPC : IS_NOT_RPC;
3103 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3105 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
3114 /* "Can't happen" */
3115 g_assert_not_reached();
3121 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3123 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
3124 dissect_rpc_continuation(tvb, pinfo, tree);
3127 /* Discard any state we've saved. */
3129 rpc_init_protocol(void)
3131 if (rpc_calls != NULL) {
3132 g_hash_table_destroy(rpc_calls);
3135 if (rpc_indir_calls != NULL) {
3136 g_hash_table_destroy(rpc_indir_calls);
3137 rpc_indir_calls = NULL;
3139 if (rpc_call_info_key_chunk != NULL) {
3140 g_mem_chunk_destroy(rpc_call_info_key_chunk);
3141 rpc_call_info_key_chunk = NULL;
3143 if (rpc_call_info_value_chunk != NULL) {
3144 g_mem_chunk_destroy(rpc_call_info_value_chunk);
3145 rpc_call_info_value_chunk = NULL;
3147 if (rpc_fragment_key_chunk != NULL) {
3148 g_mem_chunk_destroy(rpc_fragment_key_chunk);
3149 rpc_fragment_key_chunk = NULL;
3151 if (rpc_reassembly_table != NULL) {
3152 g_hash_table_destroy(rpc_reassembly_table);
3153 rpc_reassembly_table = NULL;
3156 rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
3157 rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
3158 rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
3159 sizeof(rpc_call_info_key),
3160 200 * sizeof(rpc_call_info_key),
3162 rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
3163 sizeof(rpc_call_info_value),
3164 200 * sizeof(rpc_call_info_value),
3166 rpc_fragment_key_chunk = g_mem_chunk_new("rpc_fragment_key_chunk",
3167 sizeof(rpc_fragment_key),
3168 rpc_fragment_init_count*sizeof(rpc_fragment_key),
3170 rpc_reassembly_table = g_hash_table_new(rpc_fragment_hash,
3171 rpc_fragment_equal);
3173 fragment_table_init(&rpc_fragment_table);
3176 /* will be called once from register.c at startup time */
3178 proto_register_rpc(void)
3180 static hf_register_info hf[] = {
3181 { &hf_rpc_reqframe, {
3182 "Request Frame", "rpc.reqframe", FT_FRAMENUM, BASE_NONE,
3183 NULL, 0, "Request Frame", HFILL }},
3184 { &hf_rpc_repframe, {
3185 "Reply Frame", "rpc.repframe", FT_FRAMENUM, BASE_NONE,
3186 NULL, 0, "Reply Frame", HFILL }},
3187 { &hf_rpc_lastfrag, {
3188 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, 32,
3189 &yesno, RPC_RM_LASTFRAG, "Last Fragment", HFILL }},
3190 { &hf_rpc_fraglen, {
3191 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
3192 NULL, RPC_RM_FRAGLEN, "Fragment Length", HFILL }},
3194 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
3195 NULL, 0, "XID", HFILL }},
3196 { &hf_rpc_msgtype, {
3197 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
3198 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
3199 { &hf_rpc_state_reply, {
3200 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
3201 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
3202 { &hf_rpc_state_accept, {
3203 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
3204 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
3205 { &hf_rpc_state_reject, {
3206 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
3207 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
3208 { &hf_rpc_state_auth, {
3209 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
3210 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
3211 { &hf_rpc_version, {
3212 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
3213 NULL, 0, "RPC Version", HFILL }},
3214 { &hf_rpc_version_min, {
3215 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
3216 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3217 { &hf_rpc_version_max, {
3218 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
3219 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
3220 { &hf_rpc_program, {
3221 "Program", "rpc.program", FT_UINT32, BASE_DEC,
3222 NULL, 0, "Program", HFILL }},
3223 { &hf_rpc_programversion, {
3224 "Program Version", "rpc.programversion", FT_UINT32,
3225 BASE_DEC, NULL, 0, "Program Version", HFILL }},
3226 { &hf_rpc_programversion_min, {
3227 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
3228 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3229 { &hf_rpc_programversion_max, {
3230 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
3231 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
3232 { &hf_rpc_procedure, {
3233 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
3234 NULL, 0, "Procedure", HFILL }},
3235 { &hf_rpc_auth_flavor, {
3236 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
3237 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
3238 { &hf_rpc_auth_length, {
3239 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
3240 NULL, 0, "Length", HFILL }},
3241 { &hf_rpc_auth_stamp, {
3242 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
3243 NULL, 0, "Stamp", HFILL }},
3244 { &hf_rpc_auth_uid, {
3245 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
3246 NULL, 0, "UID", HFILL }},
3247 { &hf_rpc_auth_gid, {
3248 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
3249 NULL, 0, "GID", HFILL }},
3250 { &hf_rpc_authgss_v, {
3251 "GSS Version", "rpc.authgss.version", FT_UINT32,
3252 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
3253 { &hf_rpc_authgss_proc, {
3254 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
3255 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
3256 { &hf_rpc_authgss_seq, {
3257 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
3258 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
3259 { &hf_rpc_authgss_svc, {
3260 "GSS Service", "rpc.authgss.service", FT_UINT32,
3261 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
3262 { &hf_rpc_authgss_ctx, {
3263 "GSS Context", "rpc.authgss.context", FT_BYTES,
3264 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
3265 { &hf_rpc_authgss_major, {
3266 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
3267 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
3268 { &hf_rpc_authgss_minor, {
3269 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
3270 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
3271 { &hf_rpc_authgss_window, {
3272 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
3273 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
3274 { &hf_rpc_authgss_token_length, {
3275 "GSS Token Length", "rpc.authgss.token_length", FT_UINT32,
3276 BASE_DEC, NULL, 0, "GSS Token Length", HFILL }},
3277 { &hf_rpc_authgss_data_length, {
3278 "Length", "rpc.authgss.data.length", FT_UINT32,
3279 BASE_DEC, NULL, 0, "Length", HFILL }},
3280 { &hf_rpc_authgss_data, {
3281 "GSS Data", "rpc.authgss.data", FT_BYTES,
3282 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
3283 { &hf_rpc_authgss_checksum, {
3284 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
3285 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
3286 { &hf_rpc_authgssapi_v, {
3287 "AUTH_GSSAPI Version", "rpc.authgssapi.version",
3288 FT_UINT32, BASE_DEC, NULL, 0, "AUTH_GSSAPI Version",
3290 { &hf_rpc_authgssapi_msg, {
3291 "AUTH_GSSAPI Message", "rpc.authgssapi.message",
3292 FT_BOOLEAN, BASE_NONE, &yesno, 0, "AUTH_GSSAPI Message",
3294 { &hf_rpc_authgssapi_msgv, {
3295 "Msg Version", "rpc.authgssapi.msgversion",
3296 FT_UINT32, BASE_DEC, NULL, 0, "Msg Version",
3298 { &hf_rpc_authgssapi_handle, {
3299 "Client Handle", "rpc.authgssapi.handle",
3300 FT_BYTES, BASE_HEX, NULL, 0, "Client Handle", HFILL }},
3301 { &hf_rpc_authgssapi_isn, {
3302 "Signed ISN", "rpc.authgssapi.isn",
3303 FT_BYTES, BASE_HEX, NULL, 0, "Signed ISN", HFILL }},
3304 { &hf_rpc_authdes_namekind, {
3305 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
3306 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
3307 { &hf_rpc_authdes_netname, {
3308 "Netname", "rpc.authdes.netname", FT_STRING,
3309 BASE_DEC, NULL, 0, "Netname", HFILL }},
3310 { &hf_rpc_authdes_convkey, {
3311 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
3312 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
3313 { &hf_rpc_authdes_window, {
3314 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
3315 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
3316 { &hf_rpc_authdes_nickname, {
3317 "Nickname", "rpc.authdes.nickname", FT_UINT32,
3318 BASE_HEX, NULL, 0, "Nickname", HFILL }},
3319 { &hf_rpc_authdes_timestamp, {
3320 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
3321 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
3322 { &hf_rpc_authdes_windowverf, {
3323 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
3324 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
3325 { &hf_rpc_authdes_timeverf, {
3326 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
3327 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
3328 { &hf_rpc_auth_machinename, {
3329 "Machine Name", "rpc.auth.machinename", FT_STRING,
3330 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
3332 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
3333 NULL, 0, "Duplicate Transaction", HFILL }},
3334 { &hf_rpc_call_dup, {
3335 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
3336 NULL, 0, "Duplicate Call", HFILL }},
3337 { &hf_rpc_reply_dup, {
3338 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
3339 NULL, 0, "Duplicate Reply", HFILL }},
3340 { &hf_rpc_value_follows, {
3341 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
3342 &yesno, 0, "Value Follows", HFILL }},
3343 { &hf_rpc_array_len, {
3344 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
3345 NULL, 0, "Length of RPC array", HFILL }},
3348 "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
3349 NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
3351 { &hf_rpc_fragment_overlap,
3352 { "Fragment overlap", "rpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3353 "Fragment overlaps with other fragments", HFILL }},
3355 { &hf_rpc_fragment_overlap_conflict,
3356 { "Conflicting data in fragment overlap", "rpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3357 "Overlapping fragments contained conflicting data", HFILL }},
3359 { &hf_rpc_fragment_multiple_tails,
3360 { "Multiple tail fragments found", "rpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3361 "Several tails were found when defragmenting the packet", HFILL }},
3363 { &hf_rpc_fragment_too_long_fragment,
3364 { "Fragment too long", "rpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3365 "Fragment contained data past end of packet", HFILL }},
3367 { &hf_rpc_fragment_error,
3368 { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3369 "Defragmentation error due to illegal fragments", HFILL }},
3372 { "RPC Fragment", "rpc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3373 "RPC Fragment", HFILL }},
3375 { &hf_rpc_fragments,
3376 { "RPC Fragments", "rpc.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
3377 "RPC Fragments", HFILL }},
3379 static gint *ett[] = {
3391 &ett_rpc_authgssapi_msg,
3393 module_t *rpc_module;
3395 proto_rpc = proto_register_protocol("Remote Procedure Call",
3397 proto_register_field_array(proto_rpc, hf, array_length(hf));
3398 proto_register_subtree_array(ett, array_length(ett));
3399 register_init_routine(&rpc_init_protocol);
3401 rpc_module = prefs_register_protocol(proto_rpc, NULL);
3402 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
3403 "Desegment all RPC-over-TCP messages",
3404 "Whether the RPC dissector should desegment all RPC-over-TCP messages",
3406 prefs_register_bool_preference(rpc_module, "defragment_rpc_over_tcp",
3407 "Defragment all RPC-over-TCP messages",
3408 "Whether the RPC dissector should defragment multi-fragment RPC-over-TCP messages",
3411 register_dissector("rpc", dissect_rpc, proto_rpc);
3412 rpc_handle = find_dissector("rpc");
3413 register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
3414 rpc_tcp_handle = find_dissector("rpc-tcp");
3415 rpc_tap = register_tap("rpc");
3418 * Init the hash tables. Dissectors for RPC protocols must
3419 * have a "handoff registration" routine that registers the
3420 * protocol with RPC; they must not do it in their protocol
3421 * registration routine, as their protocol registration
3422 * routine might be called before this routine is called and
3423 * thus might be called before the hash tables are initialized,
3424 * but it's guaranteed that all protocol registration routines
3425 * will be called before any handoff registration routines
3428 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
3429 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
3433 proto_reg_handoff_rpc(void)
3435 dissector_handle_t rpc_tcp_handle;
3436 dissector_handle_t rpc_udp_handle;
3438 /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
3439 we register onc-rpc on this port so that we can choose RPC in
3440 the list offered by DecodeAs, and so that traffic to or from
3441 port 111 from or to a higher-numbered port is dissected as RPC
3442 even if there's a dissector registered on the other port (it's
3443 probably RPC traffic from some randomly-chosen port that happens
3444 to match some port for which we have a dissector)
3446 rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
3447 dissector_add("tcp.port", 111, rpc_tcp_handle);
3448 rpc_udp_handle = create_dissector_handle(dissect_rpc, proto_rpc);
3449 dissector_add("udp.port", 111, rpc_udp_handle);
3451 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
3452 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
3453 gssapi_handle = find_dissector("gssapi");
3454 data_handle = find_dissector("data");