2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
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 <epan/emem.h>
39 #include "packet-rpc.h"
40 #include "packet-frame.h"
41 #include "packet-tcp.h"
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
44 #include <epan/dissectors/rpc_defrag.h>
45 #include "packet-nfs.h"
47 #include <epan/strutil.h>
48 #include <epan/garrayfix.h>
53 * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
56 * RFC 1832, "XDR: External Data Representation Standard";
58 * RFC 2203, "RPCSEC_GSS Protocol Specification".
62 * RFC 2695, "Authentication Mechanisms for ONC RPC"
64 * although we don't currently dissect AUTH_DES or AUTH_KERB.
67 /* desegmentation of RPC over TCP */
68 static gboolean rpc_desegment = TRUE;
70 /* defragmentation of fragmented RPC over TCP records */
71 static gboolean rpc_defragment = TRUE;
73 /* try to dissect RPC packets for programs that are not known
74 * (proprietary ones) by wireshark.
76 static gboolean rpc_dissect_unknown_programs = FALSE;
78 /* try to find RPC fragment start if normal decode fails
79 * (good when starting decode of mid-stream capture)
81 static gboolean rpc_find_fragment_start = FALSE;
83 static struct true_false_string yesno = { "Yes", "No" };
85 static int rpc_tap = -1;
87 static const value_string rpc_msg_type[] = {
89 { RPC_REPLY, "Reply" },
93 static const value_string rpc_reply_state[] = {
94 { MSG_ACCEPTED, "accepted" },
95 { MSG_DENIED, "denied" },
99 const value_string rpc_auth_flavor[] = {
100 { AUTH_NULL, "AUTH_NULL" },
101 { AUTH_UNIX, "AUTH_UNIX" },
102 { AUTH_SHORT, "AUTH_SHORT" },
103 { AUTH_DES, "AUTH_DES" },
104 { RPCSEC_GSS, "RPCSEC_GSS" },
105 { AUTH_GSSAPI, "AUTH_GSSAPI" },
106 { RPCSEC_GSS_KRB5, "RPCSEC_GSS_KRB5" },
107 { RPCSEC_GSS_KRB5I, "RPCSEC_GSS_KRB5I" },
108 { RPCSEC_GSS_KRB5P, "RPCSEC_GSS_KRB5P" },
109 { RPCSEC_GSS_LIPKEY, "RPCSEC_GSS_LIPKEY" },
110 { RPCSEC_GSS_LIPKEY_I, "RPCSEC_GSS_LIPKEY_I" },
111 { RPCSEC_GSS_LIPKEY_P, "RPCSEC_GSS_LIPKEY_P" },
112 { RPCSEC_GSS_SPKM3, "RPCSEC_GSS_SPKM3" },
113 { RPCSEC_GSS_SPKM3I, "RPCSEC_GSS_SPKM3I" },
114 { RPCSEC_GSS_SPKM3P, "RPCSEC_GSS_SPKM3P" },
118 static const value_string rpc_authgss_proc[] = {
119 { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
120 { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
121 { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
122 { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
126 static const value_string rpc_authgssapi_proc[] = {
127 { AUTH_GSSAPI_EXIT, "AUTH_GSSAPI_EXIT" },
128 { AUTH_GSSAPI_INIT, "AUTH_GSSAPI_INIT" },
129 { AUTH_GSSAPI_CONTINUE_INIT, "AUTH_GSSAPI_CONTINUE_INIT" },
130 { AUTH_GSSAPI_MSG, "AUTH_GSSAPI_MSG" },
131 { AUTH_GSSAPI_DESTROY, "AUTH_GSSAPI_DESTROY" },
135 const value_string rpc_authgss_svc[] = {
136 { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
137 { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
138 { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
142 static const value_string rpc_accept_state[] = {
143 { SUCCESS, "RPC executed successfully" },
144 { PROG_UNAVAIL, "remote hasn't exported program" },
145 { PROG_MISMATCH, "remote can't support version #" },
146 { PROC_UNAVAIL, "program can't support procedure" },
147 { GARBAGE_ARGS, "procedure can't decode params" },
148 { SYSTEM_ERROR, "system errors like memory allocation failure" },
152 static const value_string rpc_reject_state[] = {
153 { RPC_MISMATCH, "RPC_MISMATCH" },
154 { AUTH_ERROR, "AUTH_ERROR" },
158 static const value_string rpc_auth_state[] = {
159 { AUTH_BADCRED, "bad credential (seal broken)" },
160 { AUTH_REJECTEDCRED, "client must begin new session" },
161 { AUTH_BADVERF, "bad verifier (seal broken)" },
162 { AUTH_REJECTEDVERF, "verifier expired or replayed" },
163 { AUTH_TOOWEAK, "rejected for security reasons" },
164 { RPCSEC_GSSCREDPROB, "GSS credential problem" },
165 { RPCSEC_GSSCTXPROB, "GSS context problem" },
169 static const value_string rpc_authdes_namekind[] = {
170 { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
171 { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
175 /* the protocol number */
176 static int proto_rpc = -1;
177 static int hf_rpc_reqframe = -1;
178 static int hf_rpc_repframe = -1;
179 static int hf_rpc_lastfrag = -1;
180 static int hf_rpc_fraglen = -1;
181 static int hf_rpc_xid = -1;
182 static int hf_rpc_msgtype = -1;
183 static int hf_rpc_version = -1;
184 static int hf_rpc_version_min = -1;
185 static int hf_rpc_version_max = -1;
186 static int hf_rpc_program = -1;
187 static int hf_rpc_programversion = -1;
188 static int hf_rpc_programversion_min = -1;
189 static int hf_rpc_programversion_max = -1;
190 static int hf_rpc_procedure = -1;
191 static int hf_rpc_auth_flavor = -1;
192 static int hf_rpc_auth_length = -1;
193 static int hf_rpc_auth_machinename = -1;
194 static int hf_rpc_auth_stamp = -1;
195 static int hf_rpc_auth_uid = -1;
196 static int hf_rpc_auth_gid = -1;
197 static int hf_rpc_authgss_v = -1;
198 static int hf_rpc_authgss_proc = -1;
199 static int hf_rpc_authgss_seq = -1;
200 static int hf_rpc_authgss_svc = -1;
201 static int hf_rpc_authgss_ctx = -1;
202 static int hf_rpc_authgss_major = -1;
203 static int hf_rpc_authgss_minor = -1;
204 static int hf_rpc_authgss_window = -1;
205 static int hf_rpc_authgss_token_length = -1;
206 static int hf_rpc_authgss_data_length = -1;
207 static int hf_rpc_authgss_data = -1;
208 static int hf_rpc_authgss_token = -1;
209 static int hf_rpc_authgss_checksum = -1;
210 static int hf_rpc_authgssapi_v = -1;
211 static int hf_rpc_authgssapi_msg = -1;
212 static int hf_rpc_authgssapi_msgv = -1;
213 static int hf_rpc_authgssapi_handle = -1;
214 static int hf_rpc_authgssapi_isn = -1;
215 static int hf_rpc_authdes_namekind = -1;
216 static int hf_rpc_authdes_netname = -1;
217 static int hf_rpc_authdes_convkey = -1;
218 static int hf_rpc_authdes_window = -1;
219 static int hf_rpc_authdes_nickname = -1;
220 static int hf_rpc_authdes_timestamp = -1;
221 static int hf_rpc_authdes_windowverf = -1;
222 static int hf_rpc_authdes_timeverf = -1;
223 static int hf_rpc_state_accept = -1;
224 static int hf_rpc_state_reply = -1;
225 static int hf_rpc_state_reject = -1;
226 static int hf_rpc_state_auth = -1;
227 static int hf_rpc_dup = -1;
228 static int hf_rpc_call_dup = -1;
229 static int hf_rpc_reply_dup = -1;
230 static int hf_rpc_value_follows = -1;
231 static int hf_rpc_array_len = -1;
232 static int hf_rpc_time = -1;
233 static int hf_rpc_fragments = -1;
234 static int hf_rpc_fragment = -1;
235 static int hf_rpc_fragment_overlap = -1;
236 static int hf_rpc_fragment_overlap_conflict = -1;
237 static int hf_rpc_fragment_multiple_tails = -1;
238 static int hf_rpc_fragment_too_long_fragment = -1;
239 static int hf_rpc_fragment_error = -1;
241 static gint ett_rpc = -1;
242 static gint ett_rpc_unknown_program = -1;
243 static gint ett_rpc_fragments = -1;
244 static gint ett_rpc_fragment = -1;
245 static gint ett_rpc_fraghdr = -1;
246 static gint ett_rpc_string = -1;
247 static gint ett_rpc_cred = -1;
248 static gint ett_rpc_verf = -1;
249 static gint ett_rpc_gids = -1;
250 static gint ett_rpc_gss_token = -1;
251 static gint ett_rpc_gss_data = -1;
252 static gint ett_rpc_array = -1;
253 static gint ett_rpc_authgssapi_msg = -1;
255 static dissector_handle_t rpc_tcp_handle;
256 static dissector_handle_t rpc_handle;
257 static dissector_handle_t gssapi_handle;
258 static dissector_handle_t data_handle;
260 static guint max_rpc_tcp_pdu_size = 4 * 1024 * 1024;
262 static const fragment_items rpc_frag_items = {
267 &hf_rpc_fragment_overlap,
268 &hf_rpc_fragment_overlap_conflict,
269 &hf_rpc_fragment_multiple_tails,
270 &hf_rpc_fragment_too_long_fragment,
271 &hf_rpc_fragment_error,
276 /* Hash table with info on RPC program numbers */
277 GHashTable *rpc_progs = NULL;
279 /* Hash table with info on RPC procedure numbers */
280 GHashTable *rpc_procs = NULL;
282 static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
283 static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
285 /***********************************/
286 /* Hash array with procedure names */
287 /***********************************/
291 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
293 const rpc_proc_info_key* key1 = (const rpc_proc_info_key*) k1;
294 const rpc_proc_info_key* key2 = (const rpc_proc_info_key*) k2;
296 return ((key1->prog == key2->prog &&
297 key1->vers == key2->vers &&
298 key1->proc == key2->proc) ?
302 /* calculate a hash key */
304 rpc_proc_hash(gconstpointer k)
306 const rpc_proc_info_key* key = (const rpc_proc_info_key*) k;
308 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
312 /* insert some entries */
314 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table,
317 rpc_prog_info_key rpc_prog_key;
318 rpc_prog_info_value *rpc_prog;
322 * Add the operation number hfinfo value for this version of the
325 rpc_prog_key.prog = prog;
326 rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key);
327 DISSECTOR_ASSERT(rpc_prog != NULL);
328 rpc_prog->procedure_hfs = g_array_set_size(rpc_prog->procedure_hfs,
330 g_array_insert_val(rpc_prog->procedure_hfs, vers, procedure_hf);
332 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
333 rpc_proc_info_key *key;
334 rpc_proc_info_value *value;
336 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
339 key->proc = proc->value;
341 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
342 value->name = proc->strptr;
343 value->dissect_call = proc->dissect_call;
344 value->dissect_reply = proc->dissect_reply;
346 g_hash_table_insert(rpc_procs,key,value);
351 /* return the name associated with a previously registered procedure. */
353 rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
355 rpc_proc_info_key key;
356 rpc_proc_info_value *value;
359 procname=ep_alloc(20);
364 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
365 procname = (char *)value->name;
367 /* happens only with strange program versions or
368 non-existing dissectors */
369 g_snprintf(procname, 20, "proc-%u", key.proc);
374 /*----------------------------------------*/
375 /* end of Hash array with procedure names */
376 /*----------------------------------------*/
379 /*********************************/
380 /* Hash array with program names */
381 /*********************************/
385 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
387 const rpc_prog_info_key* key1 = (const rpc_prog_info_key*) k1;
388 const rpc_prog_info_key* key2 = (const rpc_prog_info_key*) k2;
390 return ((key1->prog == key2->prog) ?
395 /* calculate a hash key */
397 rpc_prog_hash(gconstpointer k)
399 const rpc_prog_info_key* key = (const rpc_prog_info_key*) k;
406 rpc_init_prog(int proto, guint32 prog, int ett)
408 rpc_prog_info_key *key;
409 rpc_prog_info_value *value;
411 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
414 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
415 value->proto = find_protocol_by_id(proto);
416 value->proto_id = proto;
418 value->progname = proto_get_protocol_short_name(value->proto);
419 value->procedure_hfs = g_array_new(FALSE, TRUE, sizeof (int));
421 g_hash_table_insert(rpc_progs,key,value);
426 /* return the hf_field associated with a previously registered program.
428 int rpc_prog_hf(guint32 prog, guint32 vers)
430 rpc_prog_info_key rpc_prog_key;
431 rpc_prog_info_value *rpc_prog;
433 rpc_prog_key.prog = prog;
434 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key))) {
435 return g_array_index(rpc_prog->procedure_hfs, int, vers);
440 /* return the name associated with a previously registered program. This
441 should probably eventually be expanded to use the rpc YP/NIS map
442 so that it can give names for programs not handled by wireshark */
443 const char *rpc_prog_name(guint32 prog)
445 const char *progname = NULL;
446 rpc_prog_info_key rpc_prog_key;
447 rpc_prog_info_value *rpc_prog;
449 rpc_prog_key.prog = prog;
450 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
451 progname = "Unknown";
454 progname = rpc_prog->progname;
460 /*--------------------------------------*/
461 /* end of Hash array with program names */
462 /*--------------------------------------*/
464 /* One of these structures are created for each conversation that contains
465 * RPC and contains the state we need to maintain for the conversation.
467 typedef struct _rpc_conv_info_t {
473 rpc_roundup(unsigned int a)
475 unsigned int mod = a % 4;
477 ret = a + ((mod)? 4-mod : 0);
478 /* Check for overflow */
480 THROW(ReportedBoundsError);
486 dissect_rpc_bool(tvbuff_t *tvb, proto_tree *tree,
487 int hfindex, int offset)
490 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
496 dissect_rpc_uint32(tvbuff_t *tvb, proto_tree *tree,
497 int hfindex, int offset)
500 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
506 dissect_rpc_uint64(tvbuff_t *tvb, proto_tree *tree,
507 int hfindex, int offset)
509 header_field_info *hfinfo;
511 hfinfo = proto_registrar_get_nth(hfindex);
512 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
514 proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
520 * We want to make this function available outside this file and
521 * allow callers to pass a dissection function for the opaque data
524 dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
528 gboolean fixed_length, guint32 length,
529 gboolean string_data, char **string_buffer_ret,
530 dissect_function_t *dissect_it)
533 proto_item *string_item = NULL;
534 proto_tree *string_tree = NULL;
536 guint32 string_length;
537 guint32 string_length_full;
538 guint32 string_length_packet;
539 guint32 string_length_captured;
540 guint32 string_length_copy;
544 guint32 fill_length_packet;
545 guint32 fill_length_captured;
546 guint32 fill_length_copy;
550 char *string_buffer = NULL;
551 char *string_buffer_print = NULL;
554 string_length = length;
555 data_offset = offset;
558 string_length = tvb_get_ntohl(tvb,offset+0);
559 data_offset = offset + 4;
561 string_length_captured = tvb_length_remaining(tvb, data_offset);
562 string_length_packet = tvb_reported_length_remaining(tvb, data_offset);
563 string_length_full = rpc_roundup(string_length);
564 if (string_length_captured < string_length) {
565 /* truncated string */
566 string_length_copy = string_length_captured;
569 fill_length_copy = 0;
570 if (string_length_packet < string_length)
571 exception = ReportedBoundsError;
573 exception = BoundsError;
576 /* full string data */
577 string_length_copy = string_length;
578 fill_length = string_length_full - string_length;
579 fill_length_captured = tvb_length_remaining(tvb,
580 data_offset + string_length);
581 fill_length_packet = tvb_reported_length_remaining(tvb,
582 data_offset + string_length);
583 if (fill_length_captured < fill_length) {
584 /* truncated fill bytes */
585 fill_length_copy = fill_length_packet;
587 if (fill_length_packet < fill_length)
588 exception = ReportedBoundsError;
590 exception = BoundsError;
593 /* full fill bytes */
594 fill_length_copy = fill_length;
600 * If we were passed a dissection routine, make a TVB of the data
601 * and call the dissection routine
605 tvbuff_t *opaque_tvb;
607 opaque_tvb = tvb_new_subset(tvb, data_offset, string_length_copy,
610 return (*dissect_it)(opaque_tvb, offset, pinfo, tree);
616 tmpstr = tvb_get_ephemeral_string(tvb, data_offset, string_length_copy);
617 string_buffer = memcpy(ep_alloc(string_length_copy+1), tmpstr, string_length_copy);
619 string_buffer = tvb_memcpy(tvb, ep_alloc(string_length_copy+1), data_offset, string_length_copy);
621 string_buffer[string_length_copy] = '\0';
622 /* calculate a nice printable string */
624 if (string_length != string_length_copy) {
628 formatted = format_text(string_buffer, strlen(string_buffer));
629 /* alloc maximum data area */
630 #define STRING_BUFFER_PRINT_MAX_LEN ((guint) strlen(formatted)+12+1)
631 string_buffer_print = (char*)ep_alloc(STRING_BUFFER_PRINT_MAX_LEN);
632 /* copy over the data and append <TRUNCATED> */
633 g_snprintf(string_buffer_print, STRING_BUFFER_PRINT_MAX_LEN, "%s<TRUNCATED>", formatted);
635 string_buffer_print="<DATA><TRUNCATED>";
639 string_buffer_print =
640 ep_strdup(format_text(string_buffer, strlen(string_buffer)));
642 string_buffer_print="<DATA>";
646 string_buffer_print="<EMPTY>";
650 string_item = proto_tree_add_text(tree, tvb,offset+0, -1,
651 "%s: %s", proto_registrar_get_name(hfindex),
652 string_buffer_print);
653 string_tree = proto_item_add_subtree(string_item,
658 proto_tree_add_text(string_tree, tvb,offset+0,4,
659 "length: %u", string_length);
665 proto_tree_add_string_format(string_tree,
666 hfindex, tvb, offset, string_length_copy,
668 "contents: %s", string_buffer_print);
670 proto_tree_add_bytes_format(string_tree,
671 hfindex, tvb, offset, string_length_copy,
673 "contents: %s", string_buffer_print);
677 offset += string_length_copy;
681 if (fill_truncated) {
682 proto_tree_add_text(string_tree, tvb,
683 offset,fill_length_copy,
684 "fill bytes: opaque data<TRUNCATED>");
687 proto_tree_add_text(string_tree, tvb,
688 offset,fill_length_copy,
689 "fill bytes: opaque data");
692 offset += fill_length_copy;
696 proto_item_set_end(string_item, tvb, offset);
698 if (string_buffer_ret != NULL)
699 *string_buffer_ret = string_buffer_print;
702 * If the data was truncated, throw the appropriate exception,
703 * so that dissection stops and the frame is properly marked.
712 dissect_rpc_string(tvbuff_t *tvb, proto_tree *tree,
713 int hfindex, int offset, char **string_buffer_ret)
715 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
716 hfindex, FALSE, 0, TRUE, string_buffer_ret, NULL);
722 dissect_rpc_data(tvbuff_t *tvb, proto_tree *tree,
723 int hfindex, int offset)
725 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
726 hfindex, FALSE, 0, FALSE, NULL, NULL);
732 dissect_rpc_bytes(tvbuff_t *tvb, proto_tree *tree,
733 int hfindex, int offset, guint32 length,
734 gboolean string_data, char **string_buffer_ret)
736 offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
737 hfindex, TRUE, length, string_data, string_buffer_ret, NULL);
743 dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
744 int offset, dissect_function_t *rpc_list_dissector)
746 guint32 value_follows;
749 value_follows = tvb_get_ntohl(tvb, offset+0);
750 proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
751 offset+0, 4, value_follows);
753 if (value_follows == 1) {
754 offset = rpc_list_dissector(tvb, offset, pinfo, tree);
765 dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
766 int offset, dissect_function_t *rpc_array_dissector,
769 proto_item* lock_item;
770 proto_tree* lock_tree;
773 num = tvb_get_ntohl(tvb, offset);
776 proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
783 lock_item = proto_tree_add_item(tree, hfindex, tvb, offset, -1, FALSE);
785 lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
787 offset = dissect_rpc_uint32(tvb, lock_tree,
788 hf_rpc_array_len, offset);
791 offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
794 proto_item_set_end(lock_item, tvb, offset);
799 dissect_rpc_authunix_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
808 proto_tree *gtree = NULL;
810 stamp = tvb_get_ntohl(tvb,offset+0);
812 proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
816 offset = dissect_rpc_string(tvb, tree,
817 hf_rpc_auth_machinename, offset, NULL);
819 uid = tvb_get_ntohl(tvb,offset+0);
821 proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
825 gid = tvb_get_ntohl(tvb,offset+0);
827 proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
831 gids_count = tvb_get_ntohl(tvb,offset+0);
833 gitem = proto_tree_add_text(tree, tvb,
834 offset, 4+gids_count*4, "Auxiliary GIDs");
835 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
839 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
840 gids_entry = tvb_get_ntohl(tvb,offset+0);
842 proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
843 offset, 4, gids_entry);
846 /* how can I NOW change the gitem to print a list with
847 the first 16 gids? */
853 dissect_rpc_authgss_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
860 agc_v = tvb_get_ntohl(tvb, offset+0);
862 proto_tree_add_uint(tree, hf_rpc_authgss_v,
863 tvb, offset+0, 4, agc_v);
866 agc_proc = tvb_get_ntohl(tvb, offset+0);
868 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
869 tvb, offset+0, 4, agc_proc);
872 agc_seq = tvb_get_ntohl(tvb, offset+0);
874 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
875 tvb, offset+0, 4, agc_seq);
878 agc_svc = tvb_get_ntohl(tvb, offset+0);
880 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
881 tvb, offset+0, 4, agc_svc);
884 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
891 dissect_rpc_authdes_desblock(tvbuff_t *tvb, proto_tree *tree,
892 int hfindex, int offset)
897 value_high = tvb_get_ntohl(tvb, offset + 0);
898 value_low = tvb_get_ntohl(tvb, offset + 4);
901 proto_tree_add_text(tree, tvb, offset, 8,
902 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
910 dissect_rpc_authdes_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
916 adc_namekind = tvb_get_ntohl(tvb, offset+0);
918 proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
919 tvb, offset+0, 4, adc_namekind);
924 case AUTHDES_NAMEKIND_FULLNAME:
925 offset = dissect_rpc_string(tvb, tree,
926 hf_rpc_authdes_netname, offset, NULL);
927 offset = dissect_rpc_authdes_desblock(tvb, tree,
928 hf_rpc_authdes_convkey, offset);
929 window = tvb_get_ntohl(tvb, offset+0);
930 proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
935 case AUTHDES_NAMEKIND_NICKNAME:
936 nickname = tvb_get_ntohl(tvb, offset+0);
937 proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
947 dissect_rpc_authgssapi_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
952 agc_v = tvb_get_ntohl(tvb, offset+0);
954 proto_tree_add_uint(tree, hf_rpc_authgssapi_v,
955 tvb, offset+0, 4, agc_v);
958 agc_msg = tvb_get_ntohl(tvb, offset+0);
960 proto_tree_add_boolean(tree, hf_rpc_authgssapi_msg,
961 tvb, offset+0, 4, agc_msg);
964 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgssapi_handle,
971 dissect_rpc_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
979 flavor = tvb_get_ntohl(tvb,offset+0);
980 length = tvb_get_ntohl(tvb,offset+4);
981 length = rpc_roundup(length);
984 citem = proto_tree_add_text(tree, tvb, offset,
985 8+length, "Credentials");
986 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
987 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
988 offset+0, 4, flavor);
989 proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
990 offset+4, 4, length);
994 dissect_rpc_authunix_cred(tvb, ctree, offset+8);
1002 dissect_rpc_authdes_cred(tvb, ctree, offset+8);
1006 dissect_rpc_authgss_cred(tvb, ctree, offset+8);
1010 dissect_rpc_authgssapi_cred(tvb, ctree, offset+8);
1015 proto_tree_add_text(ctree, tvb, offset+8,
1016 length,"opaque data");
1020 offset += 8 + length;
1026 * XDR opaque object, the contents of which are interpreted as a GSS-API
1030 dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
1031 packet_info *pinfo, int hfindex)
1033 guint32 opaque_length, rounded_length;
1034 gint len_consumed, length, reported_length;
1038 proto_tree *gtree = NULL;
1040 opaque_length = tvb_get_ntohl(tvb, offset+0);
1041 rounded_length = rpc_roundup(opaque_length);
1043 gitem = proto_tree_add_item(tree, hfindex, tvb, offset, 4+rounded_length, FALSE);
1044 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_token);
1045 proto_tree_add_uint(gtree, hf_rpc_authgss_token_length,
1046 tvb, offset+0, 4, opaque_length);
1049 if (opaque_length != 0) {
1050 length = tvb_length_remaining(tvb, offset);
1051 reported_length = tvb_reported_length_remaining(tvb, offset);
1052 DISSECTOR_ASSERT(length >= 0);
1053 DISSECTOR_ASSERT(reported_length >= 0);
1054 if (length > reported_length)
1055 length = reported_length;
1056 if ((guint32)length > opaque_length)
1057 length = opaque_length;
1058 if ((guint32)reported_length > opaque_length)
1059 reported_length = opaque_length;
1060 new_tvb = tvb_new_subset(tvb, offset, length, reported_length);
1061 len_consumed = call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
1062 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, hf_rpc_authgss_token);
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, hf_rpc_authgss_token);
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, hf_rpc_authgss_token);
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, hf_rpc_authgss_token);
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, hf_rpc_authgss_token);
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 tvb_ensure_length_remaining(tvb, offset);
1266 if (dissect_function != NULL) {
1267 /* set the current protocol name */
1268 saved_proto = pinfo->current_proto;
1269 if (progname != NULL)
1270 pinfo->current_proto = progname;
1272 /* call the dissector for the next level */
1273 offset = dissect_function(tvb, offset, pinfo, tree);
1275 /* restore the protocol name */
1276 pinfo->current_proto = saved_proto;
1284 dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
1285 proto_tree *tree, int offset,
1286 dissect_function_t* dissect_function,
1287 const char *progname)
1289 guint32 length, rounded_length, seq;
1292 proto_tree *gtree = NULL;
1294 length = tvb_get_ntohl(tvb, offset+0);
1295 rounded_length = rpc_roundup(length);
1296 seq = tvb_get_ntohl(tvb, offset+4);
1299 gitem = proto_tree_add_text(tree, tvb, offset,
1300 4+rounded_length, "GSS Data");
1301 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
1302 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
1303 tvb, offset+0, 4, length);
1304 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
1305 tvb, offset+4, 4, seq);
1309 if (dissect_function != NULL) {
1311 call_dissect_function(tvb, pinfo, gtree, offset,
1312 dissect_function, progname);
1314 offset += rounded_length - 4;
1315 offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo, hf_rpc_authgss_checksum);
1322 dissect_rpc_authgss_priv_data(tvbuff_t *tvb, proto_tree *tree, int offset)
1324 offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
1330 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1331 * dissector for the CALLIT procedure.
1333 * Record these in the same table as the direct calls
1334 * so we can find it when dissecting an indirect call reply.
1335 * (There should not be collissions between xid between direct and
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 dissect_function_t *dissect_function = NULL;
1348 rpc_conv_info_t *rpc_conv_info=NULL;
1354 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1355 dissect_function = value->dissect_call;
1357 /* Keep track of the address whence the call came, and the
1358 port to which the call is being sent, so that we can
1359 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 also take
1363 into account the port from which the call was sent
1364 and the address to which the call was sent, because
1365 the addresses and ports of the two endpoints should be
1366 the same for all calls and replies. (XXX - what if
1367 the connection is broken and re-established?)
1369 If the transport is connectionless, we don't worry
1370 about the address to which the call was sent and from
1371 which the reply was sent, because there's no
1372 guarantee that the reply will come from the address
1373 to which the call was sent. We also don't worry about
1374 the port *from* which the call was sent and *to* which
1375 the reply was sent, because some clients (*cough* OS X
1376 NFS client *cough) might send retransmissions from a
1377 different port from the original request. */
1378 if (pinfo->ptype == PT_TCP) {
1379 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
1380 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1381 pinfo->destport, 0);
1384 * XXX - you currently still have to pass a non-null
1385 * pointer for the second address argument even
1386 * if you use NO_ADDR_B.
1388 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
1389 &null_address, pinfo->ptype, pinfo->destport,
1390 0, NO_ADDR_B|NO_PORT_B);
1392 if (conversation == NULL) {
1393 /* It's not part of any conversation - create a new
1396 XXX - this should never happen, as we should've
1397 created a conversation for it in the RPC
1399 if (pinfo->ptype == PT_TCP) {
1400 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
1401 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1402 pinfo->destport, 0);
1404 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
1405 &null_address, pinfo->ptype, pinfo->destport,
1406 0, NO_ADDR2|NO_PORT2);
1410 * Do we already have a state structure for this conv
1412 rpc_conv_info = conversation_get_proto_data(conversation, proto_rpc);
1413 if (!rpc_conv_info) {
1414 /* No. Attach that information to the conversation, and add
1415 * it to the list of information structures.
1417 rpc_conv_info = se_alloc(sizeof(rpc_conv_info_t));
1418 rpc_conv_info->xids=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rpc_xids");
1420 conversation_add_proto_data(conversation, proto_rpc, rpc_conv_info);
1423 /* Make the dissector for this conversation the non-heuristic
1425 conversation_set_dissector(conversation,
1426 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
1428 /* Dissectors for RPC procedure calls and replies shouldn't
1429 create new tvbuffs, and we don't create one ourselves,
1430 so we should have been handed the tvbuff for this RPC call;
1431 as such, the XID is at offset 0 in this tvbuff. */
1432 /* look up the request */
1433 xid = tvb_get_ntohl(tvb, offset + 0);
1434 rpc_call = se_tree_lookup32(rpc_conv_info->xids, xid);
1435 if (rpc_call == NULL) {
1436 /* We didn't find it; create a new entry.
1437 Prepare the value data.
1438 Not all of it is needed for handling indirect
1439 calls, so we set a bunch of items to 0. */
1440 rpc_call = se_alloc(sizeof(rpc_call_info_value));
1441 rpc_call->req_num = 0;
1442 rpc_call->rep_num = 0;
1443 rpc_call->prog = prog;
1444 rpc_call->vers = vers;
1445 rpc_call->proc = proc;
1446 rpc_call->private_data = NULL;
1449 * XXX - what about RPCSEC_GSS?
1450 * Do we have to worry about it?
1452 rpc_call->flavor = FLAVOR_NOT_GSSAPI;
1453 rpc_call->gss_proc = 0;
1454 rpc_call->gss_svc = 0;
1455 rpc_call->proc_info = value;
1457 se_tree_insert32(rpc_conv_info->xids, xid, (void *)rpc_call);
1461 /* We don't know the procedure.
1462 Happens only with strange program versions or
1463 non-existing dissectors.
1464 Just show the arguments as opaque data. */
1465 offset = dissect_rpc_data(tvb, tree, args_id,
1472 proto_tree_add_text(tree, tvb, offset, 4,
1473 "Argument length: %u",
1474 tvb_get_ntohl(tvb, offset));
1478 /* Dissect the arguments */
1479 offset = call_dissect_function(tvb, pinfo, tree, offset,
1480 dissect_function, NULL);
1485 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1489 dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1490 int offset, int result_id, int prog_id, int vers_id, int proc_id)
1492 conversation_t* conversation;
1493 static address null_address = { AT_NONE, 0, NULL };
1494 rpc_call_info_value *rpc_call;
1495 char *procname=NULL;
1496 dissect_function_t *dissect_function = NULL;
1497 rpc_conv_info_t *rpc_conv_info=NULL;
1500 /* Look for the matching call in the xid table.
1501 A reply must match a call that we've seen, and the
1502 reply must be sent to the same address that the call came
1503 from, and must come from the port to which the call was sent.
1505 If the transport is connection-oriented (we check, for
1506 now, only for "pinfo->ptype" of PT_TCP), we take
1507 into account the port from which the call was sent
1508 and the address to which the call was sent, because
1509 the addresses and ports of the two endpoints should be
1510 the same for all calls and replies.
1512 If the transport is connectionless, we don't worry
1513 about the address to which the call was sent and from
1514 which the reply was sent, because there's no
1515 guarantee that the reply will come from the address
1516 to which the call was sent. We also don't worry about
1517 the port *from* which the call was sent and *to* which
1518 the reply was sent, because some clients (*cough* OS X
1519 NFS client *cough) might send retransmissions from a
1520 different port from the original request. */
1521 if (pinfo->ptype == PT_TCP) {
1522 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1523 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1526 * XXX - you currently still have to pass a non-null
1527 * pointer for the second address argument even
1528 * if you use NO_ADDR_B.
1530 conversation = find_conversation(pinfo->fd->num, &pinfo->dst, &null_address,
1531 pinfo->ptype, pinfo->srcport, 0, NO_ADDR_B|NO_PORT_B);
1533 if (conversation == NULL) {
1534 /* We haven't seen an RPC call for that conversation,
1535 so we can't check for a reply to that call.
1536 Just show the reply stuff as opaque data. */
1537 offset = dissect_rpc_data(tvb, tree, result_id,
1542 * Do we already have a state structure for this conv
1544 rpc_conv_info = conversation_get_proto_data(conversation, proto_rpc);
1545 if (!rpc_conv_info) {
1546 /* No. Attach that information to the conversation, and add
1547 * it to the list of information structures.
1549 rpc_conv_info = se_alloc(sizeof(rpc_conv_info_t));
1550 rpc_conv_info->xids=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rpc_xids");
1551 conversation_add_proto_data(conversation, proto_rpc, rpc_conv_info);
1554 /* The XIDs of the call and reply must match. */
1555 xid = tvb_get_ntohl(tvb, 0);
1556 rpc_call = se_tree_lookup32(rpc_conv_info->xids, xid);
1557 if (rpc_call == NULL) {
1558 /* The XID doesn't match a call from that
1559 conversation, so it's probably not an RPC reply.
1560 Just show the reply stuff as opaque data. */
1561 offset = dissect_rpc_data(tvb, tree, result_id,
1566 if (rpc_call->proc_info != NULL) {
1567 dissect_function = rpc_call->proc_info->dissect_reply;
1568 if (rpc_call->proc_info->name != NULL) {
1569 procname = (char *)rpc_call->proc_info->name;
1572 procname=ep_alloc(20);
1573 g_snprintf(procname, 20, "proc-%u", rpc_call->proc);
1578 dissect_function = NULL;
1580 procname=ep_alloc(20);
1581 g_snprintf(procname, 20, "proc-%u", rpc_call->proc);
1586 proto_item *tmp_item;
1588 /* Put the program, version, and procedure into the tree. */
1589 tmp_item=proto_tree_add_uint_format(tree, prog_id, tvb,
1590 0, 0, rpc_call->prog, "Program: %s (%u)",
1591 rpc_prog_name(rpc_call->prog), rpc_call->prog);
1592 PROTO_ITEM_SET_GENERATED(tmp_item);
1594 tmp_item=proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
1595 PROTO_ITEM_SET_GENERATED(tmp_item);
1597 tmp_item=proto_tree_add_uint_format(tree, proc_id, tvb,
1598 0, 0, rpc_call->proc, "Procedure: %s (%u)",
1599 procname, rpc_call->proc);
1600 PROTO_ITEM_SET_GENERATED(tmp_item);
1603 if (dissect_function == NULL) {
1604 /* We don't know how to dissect the reply procedure.
1605 Just show the reply stuff as opaque data. */
1606 offset = dissect_rpc_data(tvb, tree, result_id,
1612 /* Put the length of the reply value into the tree. */
1613 proto_tree_add_text(tree, tvb, offset, 4,
1614 "Argument length: %u",
1615 tvb_get_ntohl(tvb, offset));
1619 /* Dissect the return value */
1620 offset = call_dissect_function(tvb, pinfo, tree, offset,
1621 dissect_function, NULL);
1626 * Just mark this as a continuation of an earlier packet.
1629 dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1631 proto_item *rpc_item;
1632 proto_tree *rpc_tree;
1634 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1635 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1636 if (check_col(pinfo->cinfo, COL_INFO))
1637 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1640 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1642 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1643 proto_tree_add_text(rpc_tree, tvb, 0, -1, "Continuation data");
1649 * Produce a dummy RPC program entry for the given RPC program key
1650 * and version values.
1653 static void make_fake_rpc_prog_if_needed (rpc_prog_info_key *prpc_prog_key,
1657 rpc_prog_info_value *rpc_prog = NULL;
1660 /* sanity check: no one uses versions > 10 */
1665 if( (rpc_prog = g_hash_table_lookup(rpc_progs, prpc_prog_key)) == NULL) {
1666 /* ok this is not a known rpc program so we
1667 * will have to fake it.
1669 int proto_rpc_unknown_program;
1670 char *NAME, *Name, *name;
1671 static const vsff unknown_proc[] = {
1672 { 0,"NULL",NULL,NULL },
1673 { 0,NULL,NULL,NULL }
1679 g_snprintf(NAME, 36, "Unknown RPC Program:%d",prpc_prog_key->prog);
1680 g_snprintf(Name, 32, "RPC:%d",prpc_prog_key->prog);
1681 g_snprintf(name, 32, "rpc%d",prpc_prog_key->prog);
1682 proto_rpc_unknown_program = proto_register_protocol(NAME, Name, name);
1684 rpc_init_prog(proto_rpc_unknown_program, prpc_prog_key->prog, ett_rpc_unknown_program);
1685 rpc_init_proc_table(prpc_prog_key->prog, prog_ver, unknown_proc, hf_rpc_procedure);
1692 dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1693 tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
1694 guint32 rpc_rm, gboolean first_pdu)
1697 rpc_call_info_value *rpc_call = NULL;
1698 rpc_prog_info_value *rpc_prog = NULL;
1699 rpc_prog_info_key rpc_prog_key;
1702 unsigned int rpcvers;
1703 unsigned int prog = 0;
1704 unsigned int vers = 0;
1705 unsigned int proc = 0;
1706 flavor_t flavor = FLAVOR_UNKNOWN;
1707 unsigned int gss_proc = 0;
1708 unsigned int gss_svc = 0;
1709 protocol_t *proto = NULL;
1714 unsigned int reply_state;
1715 unsigned int accept_state;
1716 unsigned int reject_state;
1718 const char *msg_type_name = NULL;
1719 const char *progname = NULL;
1720 char *procname = NULL;
1722 unsigned int vers_low;
1723 unsigned int vers_high;
1725 unsigned int auth_state;
1727 proto_item *rpc_item = NULL;
1728 proto_tree *rpc_tree = NULL;
1730 proto_item *pitem = NULL;
1731 proto_tree *ptree = NULL;
1732 int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
1734 rpc_proc_info_key key;
1735 rpc_proc_info_value *value = NULL;
1736 conversation_t* conversation;
1737 static address null_address = { AT_NONE, 0, NULL };
1740 dissect_function_t *dissect_function = NULL;
1741 gboolean dissect_rpc = TRUE;
1743 rpc_conv_info_t *rpc_conv_info=NULL;
1747 * Check to see whether this looks like an RPC call or reply.
1749 if (!tvb_bytes_exist(tvb, offset, 8)) {
1750 /* Captured data in packet isn't enough to let us tell. */
1754 /* both directions need at least this */
1755 msg_type = tvb_get_ntohl(tvb, offset + 4);
1760 /* check for RPC call */
1761 if (!tvb_bytes_exist(tvb, offset, 16)) {
1762 /* Captured data in packet isn't enough to let us
1767 /* XID can be anything, so dont check it.
1768 We already have the message type.
1769 Check whether an RPC version number of 2 is in the
1770 location where it would be, and that an RPC program
1771 number we know about is in the location where it would be.
1773 XXX - Sun's snoop appears to recognize as RPC even calls
1774 to stuff it doesn't dissect; does it just look for a 2
1775 at that location, which seems far to weak a heuristic
1776 (too many false positives), or does it have some additional
1779 We could conceivably check for any of the program numbers
1782 ftp://ftp.tau.ac.il/pub/users/eilon/rpc/rpc
1784 and report it as RPC (but not dissect the payload if
1785 we don't have a subdissector) if it matches. */
1786 rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
1788 /* we only dissect version 2 */
1789 if (tvb_get_ntohl(tvb, offset + 8) != 2 ){
1792 /* let the user be able to weaken the heuristics if he need
1793 * to look at proprietary protocols not known
1796 if(rpc_dissect_unknown_programs){
1799 /* if the user has specified that he wants to try to
1800 * dissect even completely unknown RPC program numbers
1801 * then let him do that.
1802 * In this case we only check that the program number
1803 * is neither 0 nor -1 which is better than nothing.
1805 if(rpc_prog_key.prog==0 || rpc_prog_key.prog==0xffffffff){
1808 version=tvb_get_ntohl(tvb, offset+16);
1809 make_fake_rpc_prog_if_needed (&rpc_prog_key, version);
1811 if( (rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key)) == NULL) {
1812 /* They're not, so it's probably not an RPC call. */
1818 /* Check for RPC reply. A reply must match a call that
1819 we've seen, and the reply must be sent to the same
1820 address that the call came from, and must come from
1821 the port to which the call was sent.
1823 If the transport is connection-oriented (we check, for
1824 now, only for "pinfo->ptype" of PT_TCP), we take
1825 into account the port from which the call was sent
1826 and the address to which the call was sent, because
1827 the addresses and ports of the two endpoints should be
1828 the same for all calls and replies.
1830 If the transport is connectionless, we don't worry
1831 about the address to which the call was sent and from
1832 which the reply was sent, because there's no
1833 guarantee that the reply will come from the address
1834 to which the call was sent. We also don't worry about
1835 the port *from* which the call was sent and *to* which
1836 the reply was sent, because some clients (*cough* OS X
1837 NFS client *cough) might send retransmissions from a
1838 different port from the original request. */
1839 if (pinfo->ptype == PT_TCP) {
1840 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
1841 &pinfo->dst, pinfo->ptype, pinfo->srcport,
1842 pinfo->destport, 0);
1845 * XXX - you currently still have to pass a non-null
1846 * pointer for the second address argument even
1847 * if you use NO_ADDR_B.
1849 conversation = find_conversation(pinfo->fd->num, &pinfo->dst,
1850 &null_address, pinfo->ptype, pinfo->srcport,
1851 0, NO_ADDR_B|NO_PORT_B);
1853 if (conversation == NULL) {
1854 /* We haven't seen an RPC call for that conversation,
1855 so we can't check for a reply to that call. */
1859 * Do we already have a state structure for this conv
1861 rpc_conv_info = conversation_get_proto_data(conversation, proto_rpc);
1862 if (!rpc_conv_info) {
1863 /* No. Attach that information to the conversation, and add
1864 * it to the list of information structures.
1866 rpc_conv_info = se_alloc(sizeof(rpc_conv_info_t));
1867 rpc_conv_info->xids=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rpc_xids");
1869 conversation_add_proto_data(conversation, proto_rpc, rpc_conv_info);
1872 /* The XIDs of the call and reply must match. */
1873 xid = tvb_get_ntohl(tvb, offset + 0);
1874 rpc_call = se_tree_lookup32(rpc_conv_info->xids, xid);
1875 if (rpc_call == NULL) {
1876 /* The XID doesn't match a call from that
1877 conversation, so it's probably not an RPC reply. */
1879 /* unless we're permitted to scan for embedded records
1880 * and this is a connection-oriented transport, give up */
1881 if ((! rpc_find_fragment_start) || (pinfo->ptype != PT_TCP)) {
1885 /* in parse-partials, so define a dummy conversation for this reply */
1886 rpc_call = se_alloc(sizeof(rpc_call_info_value));
1887 rpc_call->req_num = 0;
1888 rpc_call->rep_num = pinfo->fd->num;
1892 rpc_call->private_data = NULL;
1893 rpc_call->xid = xid;
1894 rpc_call->flavor = FLAVOR_NOT_GSSAPI; /* total punt */
1895 rpc_call->gss_proc = 0;
1896 rpc_call->gss_svc = 0;
1897 rpc_call->proc_info = value;
1898 rpc_call->req_time = pinfo->fd->abs_ts;
1901 se_tree_insert32(rpc_conv_info->xids, xid, (void *)rpc_call);
1903 /* and fake up a matching program */
1904 rpc_prog_key.prog = rpc_call->prog;
1907 /* pass rpc_info to subdissectors */
1908 rpc_call->request=FALSE;
1909 pinfo->private_data=rpc_call;
1913 /* The putative message type field contains neither
1914 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1921 * This is RPC-over-TCP; check if this is the last
1924 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
1926 * This isn't the last fragment.
1927 * If we're doing reassembly, just return
1928 * TRUE to indicate that this looks like
1929 * the beginning of an RPC message,
1930 * and let them do fragment reassembly.
1937 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1938 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
1941 rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
1943 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1946 show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm,
1951 xid = tvb_get_ntohl(tvb, offset + 0);
1953 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
1954 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1957 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1959 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
1960 offset+4, 4, msg_type);
1961 proto_item_append_text(rpc_item, ", Type:%s XID:0x%08x", msg_type_name, xid);
1969 /* we know already the proto-entry, the ETT-const,
1971 proto = rpc_prog->proto;
1972 proto_id = rpc_prog->proto_id;
1973 ett = rpc_prog->ett;
1974 progname = rpc_prog->progname;
1976 rpcvers = tvb_get_ntohl(tvb, offset + 0);
1978 proto_tree_add_uint(rpc_tree,
1979 hf_rpc_version, tvb, offset+0, 4, rpcvers);
1982 prog = tvb_get_ntohl(tvb, offset + 4);
1985 proto_tree_add_uint_format(rpc_tree,
1986 hf_rpc_program, tvb, offset+4, 4, prog,
1987 "Program: %s (%u)", progname, prog);
1990 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1991 /* Set the protocol name to the underlying
1993 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
1996 vers = tvb_get_ntohl(tvb, offset+8);
1998 proto_tree_add_uint(rpc_tree,
1999 hf_rpc_programversion, tvb, offset+8, 4, vers);
2002 proc = tvb_get_ntohl(tvb, offset+12);
2008 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
2009 dissect_function = value->dissect_call;
2010 procname = (char *)value->name;
2013 /* happens only with strange program versions or
2014 non-existing dissectors */
2016 dissect_function = NULL;
2018 procname=ep_alloc(20);
2019 g_snprintf(procname, 20, "proc-%u", proc);
2022 /* Check for RPCSEC_GSS and AUTH_GSSAPI */
2023 if (tvb_bytes_exist(tvb, offset+16, 4)) {
2024 switch (tvb_get_ntohl(tvb, offset+16)) {
2028 * It's GSS-API authentication...
2030 if (tvb_bytes_exist(tvb, offset+28, 8)) {
2032 * ...and we have the procedure
2033 * and service information for it.
2035 flavor = FLAVOR_GSSAPI;
2036 gss_proc = tvb_get_ntohl(tvb, offset+28);
2037 gss_svc = tvb_get_ntohl(tvb, offset+36);
2040 * ...but the procedure and service
2041 * information isn't available.
2043 flavor = FLAVOR_GSSAPI_NO_INFO;
2049 * AUTH_GSSAPI flavor. If auth_msg is TRUE,
2050 * then this is an AUTH_GSSAPI message and
2051 * not an application level message.
2053 if (tvb_bytes_exist(tvb, offset+28, 4)) {
2054 if (tvb_get_ntohl(tvb, offset+28)) {
2055 flavor = FLAVOR_AUTHGSSAPI_MSG;
2058 val_to_str(gss_proc,
2059 rpc_authgssapi_proc, "Unknown (%d)");
2061 flavor = FLAVOR_AUTHGSSAPI;
2068 * It's not GSS-API authentication.
2070 flavor = FLAVOR_NOT_GSSAPI;
2076 proto_tree_add_uint_format(rpc_tree,
2077 hf_rpc_procedure, tvb, offset+12, 4, proc,
2078 "Procedure: %s (%u)", procname, proc);
2081 if (check_col(pinfo->cinfo, COL_INFO)) {
2083 col_clear(pinfo->cinfo, COL_INFO);
2085 col_append_str(pinfo->cinfo, COL_INFO, " ; ");
2086 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
2092 /* Keep track of the address whence the call came, and the
2093 port to which the call is being sent, so that we can
2094 match up calls with replies.
2096 If the transport is connection-oriented (we check, for
2097 now, only for "pinfo->ptype" of PT_TCP), we also take
2098 into account the port from which the call was sent
2099 and the address to which the call was sent, because
2100 the addresses and ports of the two endpoints should be
2101 the same for all calls and replies. (XXX - what if
2102 the connection is broken and re-established?)
2104 If the transport is connectionless, we don't worry
2105 about the address to which the call was sent and from
2106 which the reply was sent, because there's no
2107 guarantee that the reply will come from the address
2108 to which the call was sent. We also don't worry about
2109 the port *from* which the call was sent and *to* which
2110 the reply was sent, because some clients (*cough* OS X
2111 NFS client *cough) might send retransmissions from a
2112 different port from the original request. */
2113 if (pinfo->ptype == PT_TCP) {
2114 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
2115 &pinfo->dst, pinfo->ptype, pinfo->srcport,
2116 pinfo->destport, 0);
2119 * XXX - you currently still have to pass a non-null
2120 * pointer for the second address argument even
2121 * if you use NO_ADDR_B.
2123 conversation = find_conversation(pinfo->fd->num, &pinfo->src,
2124 &null_address, pinfo->ptype, pinfo->destport,
2125 0, NO_ADDR_B|NO_PORT_B);
2127 if (conversation == NULL) {
2128 /* It's not part of any conversation - create a new
2130 if (pinfo->ptype == PT_TCP) {
2131 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
2132 &pinfo->dst, pinfo->ptype, pinfo->srcport,
2133 pinfo->destport, 0);
2135 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
2136 &null_address, pinfo->ptype, pinfo->destport,
2137 0, NO_ADDR2|NO_PORT2);
2141 * Do we already have a state structure for this conv
2143 rpc_conv_info = conversation_get_proto_data(conversation, proto_rpc);
2144 if (!rpc_conv_info) {
2145 /* No. Attach that information to the conversation, and add
2146 * it to the list of information structures.
2148 rpc_conv_info = se_alloc(sizeof(rpc_conv_info_t));
2149 rpc_conv_info->xids=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "rpc_xids");
2151 conversation_add_proto_data(conversation, proto_rpc, rpc_conv_info);
2155 /* Make the dissector for this conversation the non-heuristic
2157 conversation_set_dissector(conversation,
2158 (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
2160 /* look up the request */
2161 rpc_call = se_tree_lookup32(rpc_conv_info->xids, xid);
2163 /* We've seen a request with this XID, with the same
2164 source and destination, before - but was it
2166 if (pinfo->fd->num != rpc_call->req_num) {
2167 /* No, so it's a duplicate request.
2169 if (check_col(pinfo->cinfo, COL_INFO)) {
2170 col_prepend_fstr(pinfo->cinfo, COL_INFO,
2171 "[RPC retransmission of #%d]", rpc_call->req_num);
2173 proto_tree_add_item(rpc_tree,
2174 hf_rpc_dup, tvb, 0,0, TRUE);
2175 proto_tree_add_uint(rpc_tree,
2176 hf_rpc_call_dup, tvb, 0,0, rpc_call->req_num);
2178 if(rpc_call->rep_num){
2179 if (check_col(pinfo->cinfo, COL_INFO)) {
2180 col_append_fstr(pinfo->cinfo, COL_INFO," (Reply In %d)", rpc_call->rep_num);
2184 /* Prepare the value data.
2185 "req_num" and "rep_num" are frame numbers;
2186 frame numbers are 1-origin, so we use 0
2187 to mean "we don't yet know in which frame
2188 the reply for this call appears". */
2189 rpc_call = se_alloc(sizeof(rpc_call_info_value));
2190 rpc_call->req_num = pinfo->fd->num;
2191 rpc_call->rep_num = 0;
2192 rpc_call->prog = prog;
2193 rpc_call->vers = vers;
2194 rpc_call->proc = proc;
2195 rpc_call->private_data = NULL;
2196 rpc_call->xid = xid;
2197 rpc_call->flavor = flavor;
2198 rpc_call->gss_proc = gss_proc;
2199 rpc_call->gss_svc = gss_svc;
2200 rpc_call->proc_info = value;
2201 rpc_call->req_time = pinfo->fd->abs_ts;
2204 se_tree_insert32(rpc_conv_info->xids, xid, (void *)rpc_call);
2207 if(rpc_call && rpc_call->rep_num){
2208 proto_item *tmp_item;
2210 tmp_item=proto_tree_add_uint_format(rpc_tree, hf_rpc_reqframe,
2211 tvb, 0, 0, rpc_call->rep_num,
2212 "The reply to this request is in frame %u",
2214 PROTO_ITEM_SET_GENERATED(tmp_item);
2219 offset = dissect_rpc_cred(tvb, rpc_tree, offset);
2220 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2222 /* pass rpc_info to subdissectors */
2223 rpc_call->request=TRUE;
2224 pinfo->private_data=rpc_call;
2226 /* go to the next dissector */
2228 break; /* end of RPC call */
2231 /* we know already the type from the calling routine,
2232 and we already have "rpc_call" set above. */
2233 prog = rpc_call->prog;
2234 vers = rpc_call->vers;
2235 proc = rpc_call->proc;
2236 flavor = rpc_call->flavor;
2237 gss_proc = rpc_call->gss_proc;
2238 gss_svc = rpc_call->gss_svc;
2240 if (rpc_call->proc_info != NULL) {
2241 dissect_function = rpc_call->proc_info->dissect_reply;
2242 if (rpc_call->proc_info->name != NULL) {
2243 procname = (char *)rpc_call->proc_info->name;
2246 procname=ep_alloc(20);
2247 g_snprintf(procname, 20, "proc-%u", proc);
2252 dissect_function = NULL;
2254 procname=ep_alloc(20);
2255 g_snprintf(procname, 20, "proc-%u", proc);
2259 * If this is an AUTH_GSSAPI message, then the RPC procedure
2260 * is not an application procedure, but rather an auth level
2261 * procedure, so it would be misleading to print the RPC
2262 * procname. Replace the RPC procname with the corresponding
2263 * AUTH_GSSAPI procname.
2265 if (flavor == FLAVOR_AUTHGSSAPI_MSG) {
2266 procname = (char *)match_strval(gss_proc, rpc_authgssapi_proc);
2269 rpc_prog_key.prog = prog;
2270 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
2274 progname = "Unknown";
2277 proto = rpc_prog->proto;
2278 proto_id = rpc_prog->proto_id;
2279 ett = rpc_prog->ett;
2280 progname = rpc_prog->progname;
2282 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2283 /* Set the protocol name to the underlying
2285 col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
2289 if (check_col(pinfo->cinfo, COL_INFO)) {
2291 col_clear(pinfo->cinfo, COL_INFO);
2293 col_append_str(pinfo->cinfo, COL_INFO, " ; ");
2294 col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
2301 proto_item *tmp_item;
2302 tmp_item=proto_tree_add_uint_format(rpc_tree,
2303 hf_rpc_program, tvb, 0, 0, prog,
2304 "Program: %s (%u)", progname, prog);
2305 PROTO_ITEM_SET_GENERATED(tmp_item);
2306 tmp_item=proto_tree_add_uint(rpc_tree,
2307 hf_rpc_programversion, tvb, 0, 0, vers);
2308 PROTO_ITEM_SET_GENERATED(tmp_item);
2309 tmp_item=proto_tree_add_uint_format(rpc_tree,
2310 hf_rpc_procedure, tvb, 0, 0, proc,
2311 "Procedure: %s (%u)", procname, proc);
2312 PROTO_ITEM_SET_GENERATED(tmp_item);
2315 reply_state = tvb_get_ntohl(tvb,offset+0);
2317 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
2318 offset+0, 4, reply_state);
2322 /* Indicate the frame to which this is a reply. */
2323 if(rpc_call && rpc_call->req_num){
2324 proto_item *tmp_item;
2326 tmp_item=proto_tree_add_uint_format(rpc_tree, hf_rpc_repframe,
2327 tvb, 0, 0, rpc_call->req_num,
2328 "This is a reply to a request in frame %u",
2330 PROTO_ITEM_SET_GENERATED(tmp_item);
2332 nstime_delta(&ns, &pinfo->fd->abs_ts, &rpc_call->req_time);
2333 tmp_item=proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
2335 PROTO_ITEM_SET_GENERATED(tmp_item);
2337 if (check_col(pinfo->cinfo, COL_INFO)) {
2338 col_append_fstr(pinfo->cinfo, COL_INFO," (Call In %d)", rpc_call->req_num);
2343 if ((!rpc_call) || (rpc_call->rep_num == 0)) {
2344 /* We have not yet seen a reply to that call, so
2345 this must be the first reply; remember its
2347 rpc_call->rep_num = pinfo->fd->num;
2349 /* We have seen a reply to this call - but was it
2351 if (rpc_call->rep_num != pinfo->fd->num) {
2352 proto_item *tmp_item;
2354 /* No, so it's a duplicate reply.
2356 if (check_col(pinfo->cinfo, COL_INFO)) {
2357 col_prepend_fstr(pinfo->cinfo, COL_INFO,
2358 "[RPC duplicate of #%d]", rpc_call->rep_num);
2360 tmp_item=proto_tree_add_item(rpc_tree,
2361 hf_rpc_dup, tvb, 0,0, TRUE);
2362 PROTO_ITEM_SET_GENERATED(tmp_item);
2364 tmp_item=proto_tree_add_uint(rpc_tree,
2365 hf_rpc_reply_dup, tvb, 0,0, rpc_call->rep_num);
2366 PROTO_ITEM_SET_GENERATED(tmp_item);
2370 switch (reply_state) {
2373 offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
2374 accept_state = tvb_get_ntohl(tvb,offset+0);
2376 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
2377 offset+0, 4, accept_state);
2380 switch (accept_state) {
2383 /* go to the next dissector */
2387 vers_low = tvb_get_ntohl(tvb,offset+0);
2388 vers_high = tvb_get_ntohl(tvb,offset+4);
2390 proto_tree_add_uint(rpc_tree,
2391 hf_rpc_programversion_min,
2392 tvb, offset+0, 4, vers_low);
2393 proto_tree_add_uint(rpc_tree,
2394 hf_rpc_programversion_max,
2395 tvb, offset+4, 4, vers_high);
2400 * There's no protocol reply, so don't
2401 * try to dissect it.
2403 dissect_rpc = FALSE;
2408 * There's no protocol reply, so don't
2409 * try to dissect it.
2411 dissect_rpc = FALSE;
2417 reject_state = tvb_get_ntohl(tvb,offset+0);
2419 proto_tree_add_uint(rpc_tree,
2420 hf_rpc_state_reject, tvb, offset+0, 4,
2425 if (reject_state==RPC_MISMATCH) {
2426 vers_low = tvb_get_ntohl(tvb,offset+0);
2427 vers_high = tvb_get_ntohl(tvb,offset+4);
2429 proto_tree_add_uint(rpc_tree,
2431 tvb, offset+0, 4, vers_low);
2432 proto_tree_add_uint(rpc_tree,
2434 tvb, offset+4, 4, vers_high);
2437 } else if (reject_state==AUTH_ERROR) {
2438 auth_state = tvb_get_ntohl(tvb,offset+0);
2440 proto_tree_add_uint(rpc_tree,
2441 hf_rpc_state_auth, tvb, offset+0, 4,
2448 * There's no protocol reply, so don't
2449 * try to dissect it.
2451 dissect_rpc = FALSE;
2456 * This isn't a valid reply state, so we have
2457 * no clue what's going on; don't try to dissect
2458 * the protocol reply.
2460 dissect_rpc = FALSE;
2463 break; /* end of RPC reply */
2467 * The switch statement at the top returned if
2468 * this was neither an RPC call nor a reply.
2470 DISSECTOR_ASSERT_NOT_REACHED();
2473 /* now we know, that RPC was shorter */
2476 THROW(ReportedBoundsError);
2477 tvb_ensure_bytes_exist(tvb, offset, 0);
2478 proto_item_set_end(rpc_item, tvb, offset);
2483 * There's no RPC call or reply here; just dissect
2484 * whatever's left as data.
2486 call_dissector(data_handle,
2487 tvb_new_subset(tvb, offset, -1, -1), pinfo, rpc_tree);
2491 /* we must queue this packet to the tap system before we actually
2492 call the subdissectors since short packets (i.e. nfs read reply)
2493 will cause an exception and execution would never reach the call
2494 to tap_queue_packet() in that case
2496 tap_queue_packet(rpc_tap, pinfo, rpc_call);
2498 /* create here the program specific sub-tree */
2499 if (tree && (flavor != FLAVOR_AUTHGSSAPI_MSG)) {
2500 pitem = proto_tree_add_item(tree, proto_id, tvb, offset, -1,
2503 ptree = proto_item_add_subtree(pitem, ett);
2507 proto_item *tmp_item;
2509 tmp_item=proto_tree_add_uint(ptree,
2510 hf_rpc_programversion, tvb, 0, 0, vers);
2511 PROTO_ITEM_SET_GENERATED(tmp_item);
2512 if (rpc_prog && (rpc_prog->procedure_hfs->len > vers) )
2513 procedure_hf = g_array_index(rpc_prog->procedure_hfs, int, vers);
2516 * No such element in the GArray.
2520 if (procedure_hf != 0 && procedure_hf != -1) {
2521 tmp_item=proto_tree_add_uint(ptree,
2522 procedure_hf, tvb, 0, 0, proc);
2523 PROTO_ITEM_SET_GENERATED(tmp_item);
2525 tmp_item=proto_tree_add_uint_format(ptree,
2526 hf_rpc_procedure, tvb, 0, 0, proc,
2527 "Procedure: %s (%u)", procname, proc);
2528 PROTO_ITEM_SET_GENERATED(tmp_item);
2533 /* proto==0 if this is an unknown program */
2534 if( (proto==0) || !proto_is_protocol_enabled(proto)){
2535 dissect_function = NULL;
2539 * Don't call any subdissector if we have no more date to dissect.
2541 if (tvb_length_remaining(tvb, offset) == 0) {
2546 * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
2550 case FLAVOR_UNKNOWN:
2552 * We don't know the authentication flavor, so we can't
2553 * dissect the payload.
2555 proto_tree_add_text(ptree, tvb, offset, -1,
2556 "Unknown authentication flavor - cannot dissect");
2559 case FLAVOR_NOT_GSSAPI:
2561 * It's not GSS-API authentication. Just dissect the
2564 offset = call_dissect_function(tvb, pinfo, ptree, offset,
2565 dissect_function, progname);
2568 case FLAVOR_GSSAPI_NO_INFO:
2570 * It's GSS-API authentication, but we don't have the
2571 * procedure and service information, so we can't dissect
2574 proto_tree_add_text(ptree, tvb, offset, -1,
2575 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2580 * It's GSS-API authentication, and we have the procedure
2581 * and service information; process the GSS-API stuff,
2582 * and process the payload if there is any.
2586 case RPCSEC_GSS_INIT:
2587 case RPCSEC_GSS_CONTINUE_INIT:
2588 if (msg_type == RPC_CALL) {
2589 offset = dissect_rpc_authgss_initarg(tvb,
2590 ptree, offset, pinfo);
2593 offset = dissect_rpc_authgss_initres(tvb,
2594 ptree, offset, pinfo);
2598 case RPCSEC_GSS_DATA:
2599 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
2600 offset = call_dissect_function(tvb,
2601 pinfo, ptree, offset,
2605 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
2606 offset = dissect_rpc_authgss_integ_data(tvb,
2607 pinfo, ptree, offset,
2611 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
2612 offset = dissect_rpc_authgss_priv_data(tvb,
2622 case FLAVOR_AUTHGSSAPI_MSG:
2624 * This is an AUTH_GSSAPI message. It contains data
2625 * only for the authentication procedure and not for the
2626 * application level RPC procedure. Reset the column
2627 * protocol and info fields to indicate that this is
2628 * an RPC auth level message, then process the args.
2630 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2631 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
2633 if (check_col(pinfo->cinfo, COL_INFO)) {
2634 col_clear(pinfo->cinfo, COL_INFO);
2635 col_append_fstr(pinfo->cinfo, COL_INFO,
2637 val_to_str(gss_proc, rpc_authgssapi_proc, "Unknown (%d)"),
2638 msg_type_name, xid);
2643 case AUTH_GSSAPI_INIT:
2644 case AUTH_GSSAPI_CONTINUE_INIT:
2645 case AUTH_GSSAPI_MSG:
2646 if (msg_type == RPC_CALL) {
2647 offset = dissect_rpc_authgssapi_initarg(tvb,
2648 rpc_tree, offset, pinfo);
2650 offset = dissect_rpc_authgssapi_initres(tvb,
2651 rpc_tree, offset, pinfo);
2655 case AUTH_GSSAPI_DESTROY:
2656 offset = dissect_rpc_data(tvb, rpc_tree,
2657 hf_rpc_authgss_data, offset);
2660 case AUTH_GSSAPI_EXIT:
2664 /* Adjust the length to account for the auth message. */
2666 proto_item_set_end(rpc_item, tvb, offset);
2670 case FLAVOR_AUTHGSSAPI:
2672 * An RPC with AUTH_GSSAPI authentication. The data
2673 * portion is always private, so don't call the dissector.
2675 offset = dissect_auth_gssapi_data(tvb, ptree, offset);
2679 if (tvb_length_remaining(tvb, offset) > 0) {
2681 * dissect any remaining bytes (incomplete dissection) as pure
2685 call_dissector(data_handle,
2686 tvb_new_subset(tvb, offset, -1, -1), pinfo, ptree);
2689 /* XXX this should really loop over all fhandles registred for the frame */
2690 if(nfs_fhandle_reqrep_matching){
2693 if(rpc_call && rpc_call->rep_num){
2694 dissect_fhandle_hidden(pinfo,
2695 ptree, rpc_call->rep_num);
2699 if(rpc_call && rpc_call->req_num){
2700 dissect_fhandle_hidden(pinfo,
2701 ptree, rpc_call->req_num);
2711 dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2713 return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2718 dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2720 if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
2722 if (tvb_length(tvb) != 0)
2723 dissect_rpc_continuation(tvb, pinfo, tree);
2728 /* Defragmentation of RPC-over-TCP records */
2729 /* table to hold defragmented RPC records */
2730 static GHashTable *rpc_fragment_table = NULL;
2732 static GHashTable *rpc_reassembly_table = NULL;
2734 typedef struct _rpc_fragment_key {
2744 rpc_fragment_hash(gconstpointer k)
2746 const rpc_fragment_key *key = (const rpc_fragment_key *)k;
2748 return key->conv_id + key->seq;
2752 rpc_fragment_equal(gconstpointer k1, gconstpointer k2)
2754 const rpc_fragment_key *key1 = (const rpc_fragment_key *)k1;
2755 const rpc_fragment_key *key2 = (const rpc_fragment_key *)k2;
2757 return key1->conv_id == key2->conv_id &&
2758 key1->seq == key2->seq && key1->port == key2->port;
2762 show_rpc_fragheader(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2764 proto_item *hdr_item;
2765 proto_tree *hdr_tree;
2769 fraglen = rpc_rm & RPC_RM_FRAGLEN;
2771 hdr_item = proto_tree_add_text(tree, tvb, 0, 4,
2772 "Fragment header: %s%u %s",
2773 (rpc_rm & RPC_RM_LASTFRAG) ? "Last fragment, " : "",
2774 fraglen, plurality(fraglen, "byte", "bytes"));
2775 hdr_tree = proto_item_add_subtree(hdr_item, ett_rpc_fraghdr);
2777 proto_tree_add_boolean(hdr_tree, hf_rpc_lastfrag, tvb, 0, 4,
2779 proto_tree_add_uint(hdr_tree, hf_rpc_fraglen, tvb, 0, 4,
2785 show_rpc_fragment(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
2789 * Show the fragment header and the data for the fragment.
2791 show_rpc_fragheader(tvb, tree, rpc_rm);
2792 proto_tree_add_text(tree, tvb, 4, -1, "Fragment Data");
2797 make_frag_tree(tvbuff_t *tvb, proto_tree *tree, int proto, gint ett,
2800 proto_item *frag_item;
2801 proto_tree *frag_tree;
2804 return; /* nothing to do */
2806 frag_item = proto_tree_add_protocol_format(tree, proto, tvb, 0, -1,
2807 "%s Fragment", proto_get_protocol_name(proto));
2808 frag_tree = proto_item_add_subtree(frag_item, ett);
2809 show_rpc_fragment(tvb, frag_tree, rpc_rm);
2813 show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
2814 guint32 rpc_rm, fragment_data *ipfd_head, packet_info *pinfo)
2816 proto_item *frag_tree_item;
2819 return; /* don't do any work */
2821 if (tvb != frag_tvb) {
2823 * This message was not all in one fragment,
2824 * so show the fragment header *and* the data
2825 * for the fragment (which is the last fragment),
2826 * and a tree with information about all fragments.
2828 show_rpc_fragment(frag_tvb, tree, rpc_rm);
2831 * Show a tree with information about all fragments.
2833 show_fragment_tree(ipfd_head, &rpc_frag_items, tree, pinfo, tvb, &frag_tree_item);
2836 * This message was all in one fragment, so just show
2837 * the fragment header.
2839 show_rpc_fragheader(tvb, tree, rpc_rm);
2844 call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
2845 proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector,
2846 fragment_data *ipfd_head, guint32 rpc_rm, gboolean first_pdu)
2848 const char *saved_proto;
2849 volatile gboolean rpc_succeeded;
2852 * Catch the ReportedBoundsError exception; if
2853 * this particular message happens to get a
2854 * ReportedBoundsError exception, that doesn't
2855 * mean that we should stop dissecting RPC
2856 * messages within this frame or chunk of
2859 * If it gets a BoundsError, we can stop, as there's
2860 * nothing more to see, so we just re-throw it.
2862 saved_proto = pinfo->current_proto;
2863 rpc_succeeded = FALSE;
2865 rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
2866 frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu);
2868 CATCH(BoundsError) {
2871 CATCH(ReportedBoundsError) {
2872 show_reported_bounds_error(tvb, pinfo, tree);
2873 pinfo->current_proto = saved_proto;
2876 * We treat this as a "successful" dissection of
2877 * an RPC packet, as "dissect_rpc_message()"
2878 * *did* decide it was an RPC packet, throwing
2879 * an exception while dissecting it as such.
2881 rpc_succeeded = TRUE;
2884 return rpc_succeeded;
2888 dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
2889 proto_tree *tree, rec_dissector_t dissector, gboolean is_heur,
2890 int proto, int ett, gboolean defragment, gboolean first_pdu)
2892 struct tcpinfo *tcpinfo;
2895 volatile guint32 len;
2897 gint tvb_len, tvb_reported_len;
2899 gboolean rpc_succeeded;
2900 gboolean save_fragmented;
2901 rpc_fragment_key old_rfk, *rfk, *new_rfk;
2902 conversation_t *conversation;
2903 fragment_data *ipfd_head;
2906 if (pinfo == NULL || pinfo->private_data == NULL) {
2909 tcpinfo = pinfo->private_data;
2911 if (tcpinfo == NULL) {
2914 seq = tcpinfo->seq + offset;
2917 * Get the record mark.
2919 if (!tvb_bytes_exist(tvb, offset, 4)) {
2921 * XXX - we should somehow arrange to handle
2922 * a record mark split across TCP segments.
2924 return 0; /* not enough to tell if it's valid */
2926 rpc_rm = tvb_get_ntohl(tvb, offset);
2928 len = rpc_rm & RPC_RM_FRAGLEN;
2931 * Do TCP desegmentation, if enabled.
2933 * reject fragments bigger than this preference setting.
2934 * This is arbitrary, but should at least prevent
2935 * some crashes from either packets with really
2936 * large RPC-over-TCP fragments or from stuff that's
2937 * not really valid for this protocol.
2939 if (len > max_rpc_tcp_pdu_size)
2940 return 0; /* pretend it's not valid */
2941 if (rpc_desegment) {
2942 seglen = tvb_length_remaining(tvb, offset + 4);
2944 if ((gint)len > seglen && pinfo->can_desegment) {
2946 * This frame doesn't have all of the
2947 * data for this message, but we can do
2950 * If this is a heuristic dissector, just
2951 * return 0 - we don't want to try to get
2952 * more data, as that's too likely to cause
2953 * us to misidentify this as valid.
2955 * XXX - this means that we won't
2956 * recognize the first fragment of a
2957 * multi-fragment RPC operation unless
2958 * we've already identified this
2959 * conversation as being an RPC
2960 * conversation (and thus aren't running
2961 * heuristically) - that would be a problem
2962 * if, for example, the first segment were
2963 * the beginning of a large NFS WRITE.
2965 * If this isn't a heuristic dissector,
2966 * we've already identified this conversation
2967 * as containing data for this protocol, as we
2968 * saw valid data in previous frames. Try to
2972 return 0; /* not valid */
2974 pinfo->desegment_offset = offset;
2975 pinfo->desegment_len = len - seglen;
2976 return -((gint32) pinfo->desegment_len);
2980 len += 4; /* include record mark */
2981 tvb_len = tvb_length_remaining(tvb, offset);
2982 tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
2983 if (tvb_len > (gint)len)
2985 if (tvb_reported_len > (gint)len)
2986 tvb_reported_len = len;
2987 frag_tvb = tvb_new_subset(tvb, offset, tvb_len,
2991 * If we're not defragmenting, just hand this to the
2996 * This is the first fragment we've seen, and it's also
2997 * the last fragment; that means the record wasn't
2998 * fragmented. Hand the dissector the tvbuff for the
2999 * fragment as the tvbuff for the record.
3005 * Mark this as fragmented, so if somebody throws an
3006 * exception, we don't report it as a malformed frame.
3008 save_fragmented = pinfo->fragmented;
3009 pinfo->fragmented = TRUE;
3010 rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo,
3011 tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu);
3012 pinfo->fragmented = save_fragmented;
3014 return 0; /* not RPC */
3019 * First, we check to see if this fragment is part of a record
3020 * that we're in the process of defragmenting.
3022 * The key is the conversation ID for the conversation to which
3023 * the packet belongs and the current sequence number.
3024 * We must first find the conversation and, if we don't find
3025 * one, create it. We know this is running over TCP, so the
3026 * conversation should not wildcard either address or port.
3028 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
3029 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3030 if (conversation == NULL) {
3032 * It's not part of any conversation - create a new one.
3034 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
3035 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3037 old_rfk.conv_id = conversation->index;
3039 old_rfk.port = pinfo->srcport;
3040 rfk = g_hash_table_lookup(rpc_reassembly_table, &old_rfk);
3044 * This fragment was not found in our table, so it doesn't
3045 * contain a continuation of a higher-level PDU.
3046 * Is it the last fragment?
3048 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
3050 * This isn't the last fragment, so we don't
3051 * have the complete record.
3053 * It's the first fragment we've seen, so if
3054 * it's truly the first fragment of the record,
3055 * and it has enough data, the dissector can at
3056 * least check whether it looks like a valid
3057 * message, as it contains the start of the
3060 * The dissector should not dissect anything
3061 * if the "last fragment" flag isn't set in
3062 * the record marker, so it shouldn't throw
3065 if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb,
3066 NULL, TRUE, rpc_rm, first_pdu))
3067 return 0; /* not valid */
3070 * OK, now start defragmentation with that
3071 * fragment. Add this fragment, and set up
3072 * next packet/sequence number as well.
3074 * We must remember this fragment.
3077 rfk = se_alloc(sizeof(rpc_fragment_key));
3078 rfk->conv_id = conversation->index;
3080 rfk->port = pinfo->srcport;
3082 rfk->start_seq = seq;
3083 g_hash_table_insert(rpc_reassembly_table, rfk, rfk);
3086 * Start defragmentation.
3088 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4,
3089 pinfo, rfk->start_seq, rpc_fragment_table,
3090 rfk->offset, len - 4, TRUE);
3093 * Make sure that defragmentation isn't complete;
3094 * it shouldn't be, as this is the first fragment
3095 * we've seen, and the "last fragment" bit wasn't
3098 if (ipfd_head == NULL) {
3099 new_rfk = se_alloc(sizeof(rpc_fragment_key));
3100 new_rfk->conv_id = rfk->conv_id;
3101 new_rfk->seq = seq + len;
3102 new_rfk->port = pinfo->srcport;
3103 new_rfk->offset = rfk->offset + len - 4;
3104 new_rfk->start_seq = rfk->start_seq;
3105 g_hash_table_insert(rpc_reassembly_table, new_rfk,
3109 * This is part of a fragmented record,
3110 * but it's not the first part.
3111 * Show it as a record marker plus data, under
3112 * a top-level tree for this protocol.
3114 make_frag_tree(frag_tvb, tree, proto, ett,rpc_rm);
3117 * No more processing need be done, as we don't
3118 * have a complete record.
3122 /* oddly, we have a first fragment, not marked as last,
3123 * but which the defragmenter thinks is complete.
3124 * So rather than creating a fragment reassembly tree,
3125 * we simply throw away the partial fragment structure
3126 * and fall though to our "sole fragment" processing below.
3132 * This is the first fragment we've seen, and it's also
3133 * the last fragment; that means the record wasn't
3134 * fragmented. Hand the dissector the tvbuff for the
3135 * fragment as the tvbuff for the record.
3141 * OK, this fragment was found, which means it continues
3142 * a record. This means we must defragment it.
3143 * Add it to the defragmentation lists.
3145 ipfd_head = fragment_add_multiple_ok(tvb, offset + 4, pinfo,
3146 rfk->start_seq, rpc_fragment_table,
3147 rfk->offset, len - 4, !(rpc_rm & RPC_RM_LASTFRAG));
3149 if (ipfd_head == NULL) {
3151 * fragment_add_multiple_ok() returned NULL.
3152 * This means that defragmentation is not
3155 * We must add an entry to the hash table with
3156 * the sequence number following this fragment
3157 * as the starting sequence number, so that when
3158 * we see that fragment we'll find that entry.
3160 * XXX - as TCP stream data is not currently
3161 * guaranteed to be provided in order to dissectors,
3162 * RPC fragments aren't guaranteed to be provided
3165 new_rfk = se_alloc(sizeof(rpc_fragment_key));
3166 new_rfk->conv_id = rfk->conv_id;
3167 new_rfk->seq = seq + len;
3168 new_rfk->port = pinfo->srcport;
3169 new_rfk->offset = rfk->offset + len - 4;
3170 new_rfk->start_seq = rfk->start_seq;
3171 g_hash_table_insert(rpc_reassembly_table, new_rfk,
3175 * This is part of a fragmented record,
3176 * but it's not the first part.
3177 * Show it as a record marker plus data, under
3178 * a top-level tree for this protocol,
3179 * but don't hand it to the dissector
3181 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
3184 * No more processing need be done, as we don't
3185 * have a complete record.
3191 * It's completely defragmented.
3193 * We only call subdissector for the last fragment.
3194 * XXX - this assumes in-order delivery of RPC
3195 * fragments, which requires in-order delivery of TCP
3198 if (!(rpc_rm & RPC_RM_LASTFRAG)) {
3200 * Well, it's defragmented, but this isn't
3201 * the last fragment; this probably means
3202 * this isn't the first pass, so we don't
3203 * need to start defragmentation.
3205 * This is part of a fragmented record,
3206 * but it's not the first part.
3207 * Show it as a record marker plus data, under
3208 * a top-level tree for this protocol,
3209 * but don't show it to the dissector.
3211 make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
3214 * No more processing need be done, as we
3215 * only disssect the data with the last
3222 * OK, this is the last segment.
3223 * Create a tvbuff for the defragmented
3228 * Create a new TVB structure for
3229 * defragmented data.
3231 rec_tvb = tvb_new_real_data(ipfd_head->data,
3232 ipfd_head->datalen, ipfd_head->datalen);
3235 * Add this tvb as a child to the original
3238 tvb_set_child_real_data_tvbuff(tvb, rec_tvb);
3241 * Add defragmented data to the data source list.
3243 add_new_data_source(pinfo, rec_tvb, "Defragmented");
3247 * We have something to hand to the RPC message
3250 if (!call_message_dissector(tvb, rec_tvb, pinfo, tree,
3251 frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu))
3252 return 0; /* not RPC */
3254 } /* end of dissect_rpc_fragment() */
3257 * Scans tvb, starting at given offset, to see if we can find
3258 * what looks like a valid RPC-over-TCP reply header.
3260 * @param tvb Buffer to inspect for RPC reply header.
3261 * @param offset Offset to begin search of tvb at.
3263 * @return -1 if no reply header found, else offset to start of header
3264 * (i.e., to the RPC record mark field).
3268 find_rpc_over_tcp_reply_start(tvbuff_t *tvb, int offset)
3272 * Looking for partial header sequence. From beginning of
3273 * stream-style header, including "record mark", full ONC-RPC
3275 * BE int32 record mark (rfc 1831 sec. 10)
3276 * ? int32 XID (rfc 1831 sec. 8)
3277 * BE int32 msg_type (ibid sec. 8, call = 0, reply = 1)
3279 * -------------------------------------------------------------
3280 * Then reply-specific fields are
3281 * BE int32 reply_stat (ibid, accept = 0, deny = 1)
3283 * Then, assuming accepted,
3285 * BE int32 auth_flavor (ibid, none = 0)
3286 * BE int32 ? auth_len (ibid, none = 0)
3288 * BE int32 accept_stat (ibid, success = 0, errs are 1..5 in rpc v2)
3290 * -------------------------------------------------------------
3291 * Or, call-specific fields are
3292 * BE int32 rpc_vers (rfc 1831 sec 8, always == 2)
3293 * BE int32 prog (NFS == 000186A3)
3294 * BE int32 prog_ver (NFS v2/3 == 2 or 3)
3295 * BE int32 proc_id (NFS, <= 256 ???)
3300 /* Initially, we search only for something matching the template
3301 * of a successful reply with no auth verifier.
3302 * Our first qualification test is search for a string of zero bytes,
3303 * corresponding the four guint32 values
3309 * If this string of zeros matches, then we go back and check the
3310 * preceding msg_type and record_mark fields.
3313 const gint cbZeroTail = 4 * 4; /* four guint32s of zeros */
3314 const gint ibPatternStart = 3 * 4; /* offset of zero fill from reply start */
3315 const guint8 * pbWholeBuf; /* all of tvb, from offset onwards */
3316 const int NoMatch = -1;
3318 gint ibSearchStart; /* offset of search start, in case of false hits. */
3320 const guint8 * pbBuf;
3322 gint cbInBuf; /* bytes in tvb, from offset onwards */
3330 cbInBuf = tvb_reported_length_remaining(tvb, offset);
3332 /* start search at first possible location */
3333 ibSearchStart = ibPatternStart;
3335 if (cbInBuf < (cbZeroTail + ibSearchStart)) {
3336 /* nothing to search, so claim no RPC */
3340 pbWholeBuf = tvb_get_ptr(tvb, offset, cbInBuf);
3341 if (pbWholeBuf == NULL) {
3342 /* probably never take this, as get_ptr seems to assert */
3346 while ((cbInBuf - ibSearchStart) > cbZeroTail) {
3347 /* First test for long tail of zeros, starting at the back.
3348 * A failure lets us skip the maximum possible buffer amount.
3350 pbBuf = pbWholeBuf + ibSearchStart + cbZeroTail - 1;
3351 for (i = cbZeroTail; i > 0; i --)
3355 /* match failure. Since we need N contiguous zeros,
3356 * we can increment next match start so zero testing
3357 * begins right after this failure spot.
3367 if (pbBuf == NULL) {
3371 /* got a match in zero-fill region, verify reply ID and
3372 * record mark fields */
3373 ulMsgType = pntohl (pbWholeBuf + ibSearchStart - 4);
3374 ulRecMark = pntohl (pbWholeBuf + ibSearchStart - ibPatternStart);
3376 if ((ulMsgType == RPC_REPLY) &&
3377 ((ulRecMark & ~0x80000000) <= (unsigned) max_rpc_tcp_pdu_size)) {
3378 /* looks ok, try dissect */
3379 return (offset + ibSearchStart - ibPatternStart);
3382 /* no match yet, nor egregious miss either. Inch along to next try */
3388 } /* end of find_rpc_over_tcp_reply_start() */
3391 * Scans tvb for what looks like a valid RPC call / reply header.
3392 * If found, calls standard dissect_rpc_fragment() logic to digest
3393 * the (hopefully valid) fragment.
3395 * With any luck, one invocation of this will be sufficient to get
3396 * us back in alignment with the stream, and no further calls to
3397 * this routine will be needed for a given conversation. As if. :-)
3400 * Same as dissect_rpc_fragment(). Will return zero (no frame)
3401 * if no valid RPC header is found.
3405 find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
3406 proto_tree *tree, rec_dissector_t dissector,
3408 int proto, int ett, gboolean defragment)
3415 offReply = find_rpc_over_tcp_reply_start(tvb, offset);
3417 /* could search for request, but not needed (or testable) thus far */
3418 return (0); /* claim no RPC */
3421 len = dissect_rpc_fragment(tvb, offReply,
3423 dissector, is_heur, proto, ett,
3425 TRUE /* force first-pdu state */);
3427 /* misses are reported as-is */
3433 /* returning a non-zero length, correct it to reflect the extra offset
3434 * we found necessary
3437 len += offReply - offset;
3440 /* negative length seems to only be used as a flag,
3441 * don't mess it up until found necessary
3443 /* len -= offReply - offset; */
3448 } /* end of find_and_dissect_rpc_fragment */
3454 * NEED_MORE_DATA, if we don't have enough data to dissect anything;
3456 * IS_RPC, if we dissected at least one message in its entirety
3459 * IS_NOT_RPC, if we found no RPC message.
3467 static rpc_tcp_return_t
3468 dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3472 gboolean saw_rpc = FALSE;
3473 gboolean first_pdu = TRUE;
3476 while (tvb_reported_length_remaining(tvb, offset) != 0) {
3478 * Process this fragment.
3480 len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
3481 dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
3482 rpc_defragment, first_pdu);
3484 if ((len == 0) && first_pdu && rpc_find_fragment_start) {
3486 * Try discarding some leading bytes from tvb, on assumption
3487 * that we are looking at the middle of a stream-based transfer
3489 len = find_and_dissect_rpc_fragment(tvb, offset, pinfo, tree,
3490 dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
3497 * We need more data from the TCP stream for
3500 return NEED_MORE_DATA;
3504 * It's not RPC. Stop processing.
3510 If the length indicates that the PDU continues beyond
3511 the end of this tvb, then tell TCP about it so that it
3512 knows where the next PDU starts.
3513 This is to help TCP detect when PDUs are not aligned to
3514 segment boundaries and allow it to find RPC headers
3515 that starts in the middle of a TCP segment.
3517 if(!pinfo->fd->flags.visited){
3518 if(len>tvb_reported_length_remaining(tvb, offset)){
3519 pinfo->want_pdu_tracking=2;
3520 pinfo->bytes_until_next_pdu=len-tvb_reported_length_remaining(tvb, offset);
3526 return saw_rpc ? IS_RPC : IS_NOT_RPC;
3530 dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3532 switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
3541 /* "Can't happen" */
3542 DISSECTOR_ASSERT_NOT_REACHED();
3548 dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3550 if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
3551 dissect_rpc_continuation(tvb, pinfo, tree);
3554 /* Discard any state we've saved. */
3556 rpc_init_protocol(void)
3558 if (rpc_reassembly_table != NULL) {
3559 g_hash_table_destroy(rpc_reassembly_table);
3560 rpc_reassembly_table = NULL;
3563 rpc_reassembly_table = g_hash_table_new(rpc_fragment_hash,
3564 rpc_fragment_equal);
3566 fragment_table_init(&rpc_fragment_table);
3569 /* will be called once from register.c at startup time */
3571 proto_register_rpc(void)
3573 static hf_register_info hf[] = {
3574 { &hf_rpc_reqframe, {
3575 "Request Frame", "rpc.reqframe", FT_FRAMENUM, BASE_NONE,
3576 NULL, 0, "Request Frame", HFILL }},
3577 { &hf_rpc_repframe, {
3578 "Reply Frame", "rpc.repframe", FT_FRAMENUM, BASE_NONE,
3579 NULL, 0, "Reply Frame", HFILL }},
3580 { &hf_rpc_lastfrag, {
3581 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, 32,
3582 &yesno, RPC_RM_LASTFRAG, "Last Fragment", HFILL }},
3583 { &hf_rpc_fraglen, {
3584 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
3585 NULL, RPC_RM_FRAGLEN, "Fragment Length", HFILL }},
3587 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
3588 NULL, 0, "XID", HFILL }},
3589 { &hf_rpc_msgtype, {
3590 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
3591 VALS(rpc_msg_type), 0, "Message Type", HFILL }},
3592 { &hf_rpc_state_reply, {
3593 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
3594 VALS(rpc_reply_state), 0, "Reply State", HFILL }},
3595 { &hf_rpc_state_accept, {
3596 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
3597 VALS(rpc_accept_state), 0, "Accept State", HFILL }},
3598 { &hf_rpc_state_reject, {
3599 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
3600 VALS(rpc_reject_state), 0, "Reject State", HFILL }},
3601 { &hf_rpc_state_auth, {
3602 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
3603 VALS(rpc_auth_state), 0, "Auth State", HFILL }},
3604 { &hf_rpc_version, {
3605 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
3606 NULL, 0, "RPC Version", HFILL }},
3607 { &hf_rpc_version_min, {
3608 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
3609 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3610 { &hf_rpc_version_max, {
3611 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
3612 BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
3613 { &hf_rpc_program, {
3614 "Program", "rpc.program", FT_UINT32, BASE_DEC,
3615 NULL, 0, "Program", HFILL }},
3616 { &hf_rpc_programversion, {
3617 "Program Version", "rpc.programversion", FT_UINT32,
3618 BASE_DEC, NULL, 0, "Program Version", HFILL }},
3619 { &hf_rpc_programversion_min, {
3620 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
3621 BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
3622 { &hf_rpc_programversion_max, {
3623 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
3624 BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
3625 { &hf_rpc_procedure, {
3626 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
3627 NULL, 0, "Procedure", HFILL }},
3628 { &hf_rpc_auth_flavor, {
3629 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
3630 VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
3631 { &hf_rpc_auth_length, {
3632 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
3633 NULL, 0, "Length", HFILL }},
3634 { &hf_rpc_auth_stamp, {
3635 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
3636 NULL, 0, "Stamp", HFILL }},
3637 { &hf_rpc_auth_uid, {
3638 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
3639 NULL, 0, "UID", HFILL }},
3640 { &hf_rpc_auth_gid, {
3641 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
3642 NULL, 0, "GID", HFILL }},
3643 { &hf_rpc_authgss_v, {
3644 "GSS Version", "rpc.authgss.version", FT_UINT32,
3645 BASE_DEC, NULL, 0, "GSS Version", HFILL }},
3646 { &hf_rpc_authgss_proc, {
3647 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
3648 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
3649 { &hf_rpc_authgss_seq, {
3650 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
3651 BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
3652 { &hf_rpc_authgss_svc, {
3653 "GSS Service", "rpc.authgss.service", FT_UINT32,
3654 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
3655 { &hf_rpc_authgss_ctx, {
3656 "GSS Context", "rpc.authgss.context", FT_BYTES,
3657 BASE_HEX, NULL, 0, "GSS Context", HFILL }},
3658 { &hf_rpc_authgss_major, {
3659 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
3660 BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
3661 { &hf_rpc_authgss_minor, {
3662 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
3663 BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
3664 { &hf_rpc_authgss_window, {
3665 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
3666 BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
3667 { &hf_rpc_authgss_token_length, {
3668 "GSS Token Length", "rpc.authgss.token_length", FT_UINT32,
3669 BASE_DEC, NULL, 0, "GSS Token Length", HFILL }},
3670 { &hf_rpc_authgss_data_length, {
3671 "Length", "rpc.authgss.data.length", FT_UINT32,
3672 BASE_DEC, NULL, 0, "Length", HFILL }},
3673 { &hf_rpc_authgss_data, {
3674 "GSS Data", "rpc.authgss.data", FT_BYTES,
3675 BASE_HEX, NULL, 0, "GSS Data", HFILL }},
3676 { &hf_rpc_authgss_checksum, {
3677 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
3678 BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
3679 { &hf_rpc_authgss_token, {
3680 "GSS Token", "rpc.authgss.token", FT_BYTES,
3681 BASE_HEX, NULL, 0, "GSS Token", HFILL }},
3682 { &hf_rpc_authgssapi_v, {
3683 "AUTH_GSSAPI Version", "rpc.authgssapi.version",
3684 FT_UINT32, BASE_DEC, NULL, 0, "AUTH_GSSAPI Version",
3686 { &hf_rpc_authgssapi_msg, {
3687 "AUTH_GSSAPI Message", "rpc.authgssapi.message",
3688 FT_BOOLEAN, BASE_NONE, &yesno, 0, "AUTH_GSSAPI Message",
3690 { &hf_rpc_authgssapi_msgv, {
3691 "Msg Version", "rpc.authgssapi.msgversion",
3692 FT_UINT32, BASE_DEC, NULL, 0, "Msg Version",
3694 { &hf_rpc_authgssapi_handle, {
3695 "Client Handle", "rpc.authgssapi.handle",
3696 FT_BYTES, BASE_HEX, NULL, 0, "Client Handle", HFILL }},
3697 { &hf_rpc_authgssapi_isn, {
3698 "Signed ISN", "rpc.authgssapi.isn",
3699 FT_BYTES, BASE_HEX, NULL, 0, "Signed ISN", HFILL }},
3700 { &hf_rpc_authdes_namekind, {
3701 "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
3702 VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
3703 { &hf_rpc_authdes_netname, {
3704 "Netname", "rpc.authdes.netname", FT_STRING,
3705 BASE_DEC, NULL, 0, "Netname", HFILL }},
3706 { &hf_rpc_authdes_convkey, {
3707 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
3708 BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
3709 { &hf_rpc_authdes_window, {
3710 "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
3711 BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
3712 { &hf_rpc_authdes_nickname, {
3713 "Nickname", "rpc.authdes.nickname", FT_UINT32,
3714 BASE_HEX, NULL, 0, "Nickname", HFILL }},
3715 { &hf_rpc_authdes_timestamp, {
3716 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
3717 BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
3718 { &hf_rpc_authdes_windowverf, {
3719 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
3720 BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
3721 { &hf_rpc_authdes_timeverf, {
3722 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
3723 BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
3724 { &hf_rpc_auth_machinename, {
3725 "Machine Name", "rpc.auth.machinename", FT_STRING,
3726 BASE_DEC, NULL, 0, "Machine Name", HFILL }},
3728 "Duplicate Call/Reply", "rpc.dup", FT_NONE, BASE_NONE,
3729 NULL, 0, "Duplicate Call/Reply", HFILL }},
3730 { &hf_rpc_call_dup, {
3731 "Duplicate to the call in", "rpc.call.dup", FT_FRAMENUM, BASE_DEC,
3732 NULL, 0, "This is a duplicate to the call in frame", HFILL }},
3733 { &hf_rpc_reply_dup, {
3734 "Duplicate to the reply in", "rpc.reply.dup", FT_FRAMENUM, BASE_DEC,
3735 NULL, 0, "This is a duplicate to the reply in frame", HFILL }},
3736 { &hf_rpc_value_follows, {
3737 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
3738 &yesno, 0, "Value Follows", HFILL }},
3739 { &hf_rpc_array_len, {
3740 "num", "rpc.array.len", FT_UINT32, BASE_DEC,
3741 NULL, 0, "Length of RPC array", HFILL }},
3744 "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
3745 NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
3747 { &hf_rpc_fragment_overlap,
3748 { "Fragment overlap", "rpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3749 "Fragment overlaps with other fragments", HFILL }},
3751 { &hf_rpc_fragment_overlap_conflict,
3752 { "Conflicting data in fragment overlap", "rpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3753 "Overlapping fragments contained conflicting data", HFILL }},
3755 { &hf_rpc_fragment_multiple_tails,
3756 { "Multiple tail fragments found", "rpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3757 "Several tails were found when defragmenting the packet", HFILL }},
3759 { &hf_rpc_fragment_too_long_fragment,
3760 { "Fragment too long", "rpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3761 "Fragment contained data past end of packet", HFILL }},
3763 { &hf_rpc_fragment_error,
3764 { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3765 "Defragmentation error due to illegal fragments", HFILL }},
3768 { "RPC Fragment", "rpc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3769 "RPC Fragment", HFILL }},
3771 { &hf_rpc_fragments,
3772 { "RPC Fragments", "rpc.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
3773 "RPC Fragments", HFILL }},
3775 static gint *ett[] = {
3787 &ett_rpc_authgssapi_msg,
3788 &ett_rpc_unknown_program,
3790 module_t *rpc_module;
3792 proto_rpc = proto_register_protocol("Remote Procedure Call",
3794 /* this is a dummy dissector for all those unknown rpc programs */
3795 proto_register_field_array(proto_rpc, hf, array_length(hf));
3796 proto_register_subtree_array(ett, array_length(ett));
3797 register_init_routine(&rpc_init_protocol);
3799 rpc_module = prefs_register_protocol(proto_rpc, NULL);
3800 prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
3801 "Reassemble RPC over TCP messages\nspanning multiple TCP segments",
3802 "Whether the RPC dissector should reassemble messages spanning multiple TCP segments."
3803 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3805 prefs_register_bool_preference(rpc_module, "defragment_rpc_over_tcp",
3806 "Reassemble fragmented RPC-over-TCP messages",
3807 "Whether the RPC dissector should defragment RPC-over-TCP messages.",
3810 prefs_register_uint_preference(rpc_module, "max_tcp_pdu_size", "Maximum size of a RPC-over-TCP PDU",
3811 "Set the maximum size of RPCoverTCP PDUs. "
3812 " If the size field of the record marker is larger "
3813 "than this value it will not be considered a valid RPC PDU.",
3814 10, &max_rpc_tcp_pdu_size);
3816 prefs_register_bool_preference(rpc_module, "dissect_unknown_programs",
3817 "Dissect unknown RPC program numbers",
3818 "Whether the RPC dissector should attempt to dissect RPC PDUs containing programs that are not known to Wireshark. This will make the heuristics significantly weaker and elevate the risk for falsely identifying and misdissecting packets significantly.",
3819 &rpc_dissect_unknown_programs);
3821 prefs_register_bool_preference(rpc_module, "find_fragment_start",
3822 "Attempt to locate start-of-fragment in partial RPC-over-TCP captures",
3823 "Whether the RPC dissector should attempt to locate RPC PDU boundaries when initial fragment alignment is not known. This may cause false positives, or slow operation.",
3824 &rpc_find_fragment_start);
3826 register_dissector("rpc", dissect_rpc, proto_rpc);
3827 register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
3828 rpc_tap = register_tap("rpc");
3831 * Init the hash tables. Dissectors for RPC protocols must
3832 * have a "handoff registration" routine that registers the
3833 * protocol with RPC; they must not do it in their protocol
3834 * registration routine, as their protocol registration
3835 * routine might be called before this routine is called and
3836 * thus might be called before the hash tables are initialized,
3837 * but it's guaranteed that all protocol registration routines
3838 * will be called before any handoff registration routines
3841 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
3842 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
3846 proto_reg_handoff_rpc(void)
3848 /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
3849 we register onc-rpc on this port so that we can choose RPC in
3850 the list offered by DecodeAs, and so that traffic to or from
3851 port 111 from or to a higher-numbered port is dissected as RPC
3852 even if there's a dissector registered on the other port (it's
3853 probably RPC traffic from some randomly-chosen port that happens
3854 to match some port for which we have a dissector)
3856 rpc_tcp_handle = find_dissector("rpc-tcp");
3857 dissector_add("tcp.port", 111, rpc_tcp_handle);
3858 rpc_handle = find_dissector("rpc");
3859 dissector_add("udp.port", 111, rpc_handle);
3861 heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
3862 heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
3863 gssapi_handle = find_dissector("gssapi");
3864 data_handle = find_dissector("data");
3873 * indent-tabs-mode: t
3876 * ex: set shiftwidth=8 tabstop=8 noexpandtab
3877 * :indentSize=8:tabSize=8:noTabs=false: