2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Copied from packet-smb.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <stdio.h> /* fprintf() */
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/exceptions.h>
20 #include <wsutil/pint.h>
21 #include <wsutil/str_util.h>
22 #include <epan/prefs.h>
23 #include <epan/reassemble.h>
25 #include <epan/stat_tap_ui.h>
26 #include <epan/srt_table.h>
27 #include <epan/show_exception.h>
29 #include <wsutil/array.h>
31 #include "packet-rpc.h"
32 #include "packet-tcp.h"
33 #include "packet-tls.h"
34 #include "packet-nfs.h"
35 #include "packet-gssapi.h"
40 * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
43 * RFC 1832, "XDR: External Data Representation Standard";
45 * RFC 2203, "RPCSEC_GSS Protocol Specification".
49 * RFC 2695, "Authentication Mechanisms for ONC RPC"
51 * although we don't currently dissect AUTH_DES or AUTH_KERB.
53 * RFC 5531, "Appendix C: Current Number Assignments" defines AUTH_RSA.
54 * AUTH_RSA is not implemented for any known RPC-protocols. The Gluster
55 * protocols (ab)use AUTH_RSA for their own AUTH-flavor. AUTH_RSA is
56 * therefore dissected as the unofficial AUTH_GLUSTER.
58 void proto_register_rpc(void);
59 void proto_reg_handoff_rpc(void);
61 #define RPC_TCP_PORT 111
67 /* desegmentation of RPC over TCP */
68 static bool rpc_desegment
= true;
70 /* defragmentation of fragmented RPC over TCP records */
71 static bool rpc_defragment
= true;
73 /* try to dissect RPC packets for programs that are not known
74 * (proprietary ones) by wireshark.
76 static bool rpc_dissect_unknown_programs
;
78 /* try to find RPC fragment start if normal decode fails
79 * (good when starting decode of mid-stream capture)
81 static bool rpc_find_fragment_start
;
85 static dissector_handle_t spnego_krb5_wrap_handle
;
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 { AUTH_RSA
, "AUTH_RSA/Gluster" },
105 { RPCSEC_GSS
, "RPCSEC_GSS" },
106 { AUTH_TLS
, "AUTH_TLS" },
107 { AUTH_GSSAPI
, "AUTH_GSSAPI" },
108 { RPCSEC_GSS_KRB5
, "RPCSEC_GSS_KRB5" },
109 { RPCSEC_GSS_KRB5I
, "RPCSEC_GSS_KRB5I" },
110 { RPCSEC_GSS_KRB5P
, "RPCSEC_GSS_KRB5P" },
111 { RPCSEC_GSS_LIPKEY
, "RPCSEC_GSS_LIPKEY" },
112 { RPCSEC_GSS_LIPKEY_I
, "RPCSEC_GSS_LIPKEY_I" },
113 { RPCSEC_GSS_LIPKEY_P
, "RPCSEC_GSS_LIPKEY_P" },
114 { RPCSEC_GSS_SPKM3
, "RPCSEC_GSS_SPKM3" },
115 { RPCSEC_GSS_SPKM3I
, "RPCSEC_GSS_SPKM3I" },
116 { RPCSEC_GSS_SPKM3P
, "RPCSEC_GSS_SPKM3P" },
117 { AUTH_GLUSTERFS
, "AUTH_GLUSTERFS" },
118 { AUTH_GLUSTERFS_V3
, "AUTH_GLUSTERFS_V3" },
122 static const value_string rpc_authgss_proc
[] = {
123 { RPCSEC_GSS_DATA
, "RPCSEC_GSS_DATA" },
124 { RPCSEC_GSS_INIT
, "RPCSEC_GSS_INIT" },
125 { RPCSEC_GSS_CONTINUE_INIT
, "RPCSEC_GSS_CONTINUE_INIT" },
126 { RPCSEC_GSS_DESTROY
, "RPCSEC_GSS_DESTROY" },
130 static const value_string rpc_authgssapi_proc
[] = {
131 { AUTH_GSSAPI_EXIT
, "AUTH_GSSAPI_EXIT" },
132 { AUTH_GSSAPI_INIT
, "AUTH_GSSAPI_INIT" },
133 { AUTH_GSSAPI_CONTINUE_INIT
, "AUTH_GSSAPI_CONTINUE_INIT" },
134 { AUTH_GSSAPI_MSG
, "AUTH_GSSAPI_MSG" },
135 { AUTH_GSSAPI_DESTROY
, "AUTH_GSSAPI_DESTROY" },
139 const value_string rpc_authgss_svc
[] = {
140 { RPCSEC_GSS_SVC_NONE
, "rpcsec_gss_svc_none" },
141 { RPCSEC_GSS_SVC_INTEGRITY
, "rpcsec_gss_svc_integrity" },
142 { RPCSEC_GSS_SVC_PRIVACY
, "rpcsec_gss_svc_privacy" },
146 static const value_string rpc_accept_state
[] = {
147 { SUCCESS
, "RPC executed successfully" },
148 { PROG_UNAVAIL
, "remote hasn't exported program" },
149 { PROG_MISMATCH
, "remote can't support version #" },
150 { PROC_UNAVAIL
, "program can't support procedure" },
151 { GARBAGE_ARGS
, "procedure can't decode params" },
152 { SYSTEM_ERROR
, "system errors like memory allocation failure" },
156 static const value_string rpc_reject_state
[] = {
157 { RPC_MISMATCH
, "RPC_MISMATCH" },
158 { AUTH_ERROR
, "AUTH_ERROR" },
162 static const value_string rpc_auth_state
[] = {
163 { AUTH_BADCRED
, "bad credential (seal broken)" },
164 { AUTH_REJECTEDCRED
, "client must begin new session" },
165 { AUTH_BADVERF
, "bad verifier (seal broken)" },
166 { AUTH_REJECTEDVERF
, "verifier expired or replayed" },
167 { AUTH_TOOWEAK
, "rejected for security reasons" },
168 { RPCSEC_GSSCREDPROB
, "GSS credential problem" },
169 { RPCSEC_GSSCTXPROB
, "GSS context problem" },
173 static const value_string rpc_authdes_namekind
[] = {
174 { AUTHDES_NAMEKIND_FULLNAME
, "ADN_FULLNAME" },
175 { AUTHDES_NAMEKIND_NICKNAME
, "ADN_NICKNAME" },
179 /* the protocol number */
180 static int proto_rpc
;
181 static int proto_rpc_unknown
;
182 static int hf_rpc_reqframe
;
183 static int hf_rpc_repframe
;
184 static int hf_rpc_lastfrag
;
185 static int hf_rpc_fraglen
;
186 static int hf_rpc_xid
;
187 static int hf_rpc_msgtype
;
188 static int hf_rpc_version
;
189 static int hf_rpc_version_min
;
190 static int hf_rpc_version_max
;
191 static int hf_rpc_program
;
192 static int hf_rpc_programversion
;
193 static int hf_rpc_programversion_min
;
194 static int hf_rpc_programversion_max
;
195 static int hf_rpc_procedure
;
196 static int hf_rpc_auth_flavor
;
197 static int hf_rpc_auth_length
;
198 static int hf_rpc_auth_machinename
;
199 static int hf_rpc_auth_stamp
;
200 static int hf_rpc_auth_lk_owner
;
201 static int hf_rpc_auth_pid
;
202 static int hf_rpc_auth_uid
;
203 static int hf_rpc_auth_gid
;
204 static int hf_rpc_auth_flags
;
205 static int hf_rpc_auth_ctime
;
206 static int hf_rpc_authgss_v
;
207 static int hf_rpc_authgss_proc
;
208 static int hf_rpc_authgss_seq
;
209 static int hf_rpc_authgss_svc
;
210 static int hf_rpc_authgss_ctx
;
211 static int hf_rpc_authgss_ctx_create_frame
;
212 static int hf_rpc_authgss_ctx_destroy_frame
;
213 static int hf_rpc_authgss_ctx_len
;
214 static int hf_rpc_authgss_major
;
215 static int hf_rpc_authgss_minor
;
216 static int hf_rpc_authgss_window
;
217 static int hf_rpc_authgss_token_length
;
218 static int hf_rpc_authgss_data_length
;
219 static int hf_rpc_authgss_data
;
220 static int hf_rpc_authgss_token
;
221 static int hf_rpc_authgss_checksum
;
222 static int hf_rpc_authgssapi_v
;
223 static int hf_rpc_authgssapi_msg
;
224 static int hf_rpc_authgssapi_msgv
;
225 static int hf_rpc_authgssapi_handle
;
226 static int hf_rpc_authgssapi_isn
;
227 static int hf_rpc_authdes_namekind
;
228 static int hf_rpc_authdes_netname
;
229 static int hf_rpc_authdes_convkey
;
230 static int hf_rpc_authdes_window
;
231 static int hf_rpc_authdes_nickname
;
232 static int hf_rpc_authdes_timestamp
;
233 static int hf_rpc_authdes_windowverf
;
234 static int hf_rpc_authdes_timeverf
;
235 static int hf_rpc_state_accept
;
236 static int hf_rpc_state_reply
;
237 static int hf_rpc_state_reject
;
238 static int hf_rpc_state_auth
;
239 static int hf_rpc_dup
;
240 static int hf_rpc_call_dup
;
241 static int hf_rpc_reply_dup
;
242 static int hf_rpc_value_follows
;
243 static int hf_rpc_array_len
;
244 static int hf_rpc_time
;
245 static int hf_rpc_fragments
;
246 static int hf_rpc_fragment
;
247 static int hf_rpc_fragment_overlap
;
248 static int hf_rpc_fragment_overlap_conflict
;
249 static int hf_rpc_fragment_multiple_tails
;
250 static int hf_rpc_fragment_too_long_fragment
;
251 static int hf_rpc_fragment_error
;
252 static int hf_rpc_fragment_count
;
253 static int hf_rpc_reassembled_length
;
254 static int hf_rpc_unknown_body
;
256 /* Generated from convert_proto_tree_add_text.pl */
257 static int hf_rpc_opaque_data
;
258 static int hf_rpc_no_values
;
259 static int hf_rpc_continuation_data
;
260 static int hf_rpc_fill_bytes
;
261 static int hf_rpc_argument_length
;
262 static int hf_rpc_fragment_data
;
263 static int hf_rpc_opaque_length
;
266 static int ett_rpc_unknown_program
;
267 static int ett_rpc_fragments
;
268 static int ett_rpc_fragment
;
269 static int ett_rpc_fraghdr
;
270 static int ett_rpc_string
;
271 static int ett_rpc_cred
;
272 static int ett_rpc_verf
;
273 static int ett_rpc_gids
;
274 static int ett_rpc_gss_token
;
275 static int ett_rpc_gss_data
;
276 static int ett_rpc_array
;
277 static int ett_rpc_authgssapi_msg
;
278 static int ett_gss_context
;
279 static int ett_gss_wrap
;
281 static expert_field ei_rpc_cannot_dissect
;
282 static expert_field ei_rpc_segment_needed
;
284 static dissector_handle_t rpc_tcp_handle
;
285 static dissector_handle_t rpc_handle
;
286 static dissector_handle_t gssapi_handle
;
287 static dissector_handle_t data_handle
;
288 static dissector_handle_t rpc_tls_handle
;
290 static dissector_table_t subdissector_call_table
;
291 static dissector_table_t subdissector_reply_table
;
294 static unsigned max_rpc_tcp_pdu_size
= 4 * 1024 * 1024;
296 static const fragment_items rpc_frag_items
= {
301 &hf_rpc_fragment_overlap
,
302 &hf_rpc_fragment_overlap_conflict
,
303 &hf_rpc_fragment_multiple_tails
,
304 &hf_rpc_fragment_too_long_fragment
,
305 &hf_rpc_fragment_error
,
306 &hf_rpc_fragment_count
,
308 &hf_rpc_reassembled_length
,
309 /* Reassembled data field */
314 /* Hash table with info on RPC program numbers */
315 GHashTable
*rpc_progs
;
317 typedef bool (*rec_dissector_t
)(tvbuff_t
*, packet_info
*, proto_tree
*,
318 tvbuff_t
*, fragment_head
*, int, uint32_t, bool, bool);
320 static void show_rpc_fraginfo(tvbuff_t
*tvb
, tvbuff_t
*frag_tvb
, proto_tree
*tree
,
321 uint32_t rpc_rm
, fragment_head
*ipfd_head
, packet_info
*pinfo
);
324 static uint32_t rpc_program
;
325 static uint32_t rpc_version
;
326 static int32_t rpc_min_proc
= -1;
327 static int32_t rpc_max_proc
= -1;
330 rpcstat_find_procs(const char *table_name _U_
, ftenum_t selector_type _U_
, void *key
, void *value _U_
, void *user_data _U_
)
332 rpc_proc_info_key
*k
= (rpc_proc_info_key
*)key
;
334 if (k
->prog
!= rpc_program
) {
337 if (k
->vers
!= rpc_version
) {
340 if (rpc_min_proc
== -1) {
341 rpc_min_proc
= k
->proc
;
342 rpc_max_proc
= k
->proc
;
344 if ((int32_t)k
->proc
< rpc_min_proc
) {
345 rpc_min_proc
= k
->proc
;
347 if ((int32_t)k
->proc
> rpc_max_proc
) {
348 rpc_max_proc
= k
->proc
;
353 rpcstat_init(struct register_srt
* srt
, GArray
* srt_array
)
355 rpcstat_tap_data_t
* tap_data
= (rpcstat_tap_data_t
*)get_srt_table_param_data(srt
);
356 srt_stat_table
*rpc_srt_table
;
358 header_field_info
*hfi
;
359 static char table_name
[100];
361 DISSECTOR_ASSERT(tap_data
);
363 hf_index
=rpc_prog_hf(tap_data
->program
, tap_data
->version
);
364 hfi
=proto_registrar_get_nth(hf_index
);
366 snprintf(table_name
, sizeof(table_name
), "%s Version %u", tap_data
->prog
, tap_data
->version
);
367 rpc_srt_table
= init_srt_table(table_name
, NULL
, srt_array
, tap_data
->num_procedures
, NULL
, hfi
->abbrev
, tap_data
);
368 for (i
= 0; i
< rpc_srt_table
->num_procs
; i
++)
370 const char *proc_name
= rpc_proc_name(NULL
, tap_data
->program
, tap_data
->version
, i
);
371 init_srt_table_row(rpc_srt_table
, i
, proc_name
);
372 wmem_free(NULL
, (void *)proc_name
);
376 static tap_packet_status
377 rpcstat_packet(void *pss
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *prv
, tap_flags_t flags _U_
)
379 srt_stat_table
*rpc_srt_table
;
380 srt_data_t
*data
= (srt_data_t
*)pss
;
381 const rpc_call_info_value
*ri
= (const rpc_call_info_value
*)prv
;
382 rpcstat_tap_data_t
* tap_data
;
384 rpc_srt_table
= g_array_index(data
->srt_array
, srt_stat_table
*, 0);
385 tap_data
= (rpcstat_tap_data_t
*)rpc_srt_table
->table_specific_data
;
387 if ((int)ri
->proc
>= rpc_srt_table
->num_procs
) {
388 /* don't handle this since its outside of known table */
389 return TAP_PACKET_DONT_REDRAW
;
391 /* we are only interested in reply packets */
393 return TAP_PACKET_DONT_REDRAW
;
395 /* we are only interested in certain program/versions */
396 if ( (ri
->prog
!= tap_data
->program
) || (ri
->vers
!= tap_data
->version
) ) {
397 return TAP_PACKET_DONT_REDRAW
;
400 add_srt_table_data(rpc_srt_table
, ri
->proc
, &ri
->req_time
, pinfo
);
401 return TAP_PACKET_REDRAW
;
406 rpcstat_param(register_srt_t
* srt
, const char* opt_arg
, char** err
)
409 int program
, version
;
410 rpcstat_tap_data_t
* tap_data
;
412 if (sscanf(opt_arg
, ",%d,%d%n", &program
, &version
, &pos
) == 2)
414 tap_data
= g_new0(rpcstat_tap_data_t
, 1);
416 tap_data
->prog
= rpc_prog_name(program
);
417 tap_data
->program
= program
;
418 tap_data
->version
= version
;
420 set_srt_table_param_data(srt
, tap_data
);
422 rpc_program
= tap_data
->program
;
423 rpc_version
= tap_data
->version
;
426 /* Need to run over both dissector tables */
427 dissector_table_foreach ("rpc.call", rpcstat_find_procs
, NULL
);
428 dissector_table_foreach ("rpc.reply", rpcstat_find_procs
, NULL
);
430 tap_data
->num_procedures
= rpc_max_proc
+1;
431 if (rpc_min_proc
== -1) {
432 *err
= ws_strdup_printf("Program:%u version:%u isn't supported", rpc_program
, rpc_version
);
437 *err
= g_strdup("<program>,<version>[,<filter>]");
447 /***********************************/
448 /* Hash array with procedure names */
449 /***********************************/
453 rpc_proc_equal(const void *k1
, const void *k2
)
455 const rpc_proc_info_key
* key1
= (const rpc_proc_info_key
*) k1
;
456 const rpc_proc_info_key
* key2
= (const rpc_proc_info_key
*) k2
;
458 return ((key1
->prog
== key2
->prog
&&
459 key1
->vers
== key2
->vers
&&
460 key1
->proc
== key2
->proc
) ?
464 /* calculate a hash key */
466 rpc_proc_hash(const void *k
)
468 const rpc_proc_info_key
* key
= (const rpc_proc_info_key
*) k
;
470 return (key
->prog
^ (key
->vers
<<16) ^ (key
->proc
<<24));
474 /* return the name associated with a previously registered procedure. */
476 rpc_proc_name(wmem_allocator_t
*allocator
, uint32_t prog
, uint32_t vers
, uint32_t proc
)
478 rpc_proc_info_key key
;
479 dissector_handle_t dissect_function
;
486 /* Look at both tables for possible procedure names */
487 if ((dissect_function
= dissector_get_custom_table_handle(subdissector_call_table
, &key
)) != NULL
)
488 procname
= wmem_strdup(allocator
, dissector_handle_get_description(dissect_function
));
489 else if ((dissect_function
= dissector_get_custom_table_handle(subdissector_reply_table
, &key
)) != NULL
)
490 procname
= wmem_strdup(allocator
, dissector_handle_get_description(dissect_function
));
492 /* happens only with strange program versions or
493 non-existing dissectors */
494 procname
= wmem_strdup_printf(allocator
, "proc-%u", key
.proc
);
499 /*----------------------------------------*/
500 /* end of Hash array with procedure names */
501 /*----------------------------------------*/
504 /*********************************/
505 /* Hash array with program names */
506 /*********************************/
509 rpc_prog_free_val(void *v
)
511 rpc_prog_info_value
*value
= (rpc_prog_info_value
*)v
;
513 g_array_free(value
->procedure_hfs
, true);
518 rpc_init_prog(int proto
, uint32_t prog
, int ett
, size_t nvers
,
519 const rpc_prog_vers_info
*versions
)
521 rpc_prog_info_value
*value
;
525 value
= g_new(rpc_prog_info_value
, 1);
526 value
->proto
= find_protocol_by_id(proto
);
527 value
->proto_id
= proto
;
529 value
->progname
= proto_get_protocol_short_name(value
->proto
);
530 value
->procedure_hfs
= g_array_new(false, true, sizeof (int));
532 g_hash_table_insert(rpc_progs
,GUINT_TO_POINTER(prog
),value
);
535 * Now register each of the versions of the program.
537 for (versidx
= 0; versidx
< nvers
; versidx
++) {
539 * Add the operation number hfinfo value for this version.
541 value
->procedure_hfs
= g_array_set_size(value
->procedure_hfs
,
542 versions
[versidx
].vers
);
543 g_array_insert_val(value
->procedure_hfs
,
544 versions
[versidx
].vers
, *versions
[versidx
].procedure_hf
);
546 for (proc
= versions
[versidx
].proc_table
; proc
->strptr
!= NULL
;
548 rpc_proc_info_key key
;
551 key
.vers
= versions
[versidx
].vers
;
552 key
.proc
= proc
->value
;
554 if (proc
->dissect_call
== NULL
) {
555 fprintf(stderr
, "OOPS: No call handler for %s version %u procedure %s\n",
556 proto_get_protocol_long_name(value
->proto
),
557 versions
[versidx
].vers
,
560 /* Abort out if desired - but don't throw an exception here! */
561 if (wireshark_abort_on_dissector_bug
)
562 REPORT_DISSECTOR_BUG("RPC: No call handler!");
566 dissector_add_custom_table_handle("rpc.call", g_memdup2(&key
, sizeof(rpc_proc_info_key
)),
567 create_dissector_handle_with_name_and_description(proc
->dissect_call
, value
->proto_id
, NULL
, proc
->strptr
));
569 if (proc
->dissect_reply
== NULL
) {
570 fprintf(stderr
, "OOPS: No reply handler for %s version %u procedure %s\n",
571 proto_get_protocol_long_name(value
->proto
),
572 versions
[versidx
].vers
,
575 /* Abort out if desired - but don't throw an exception here! */
576 if (wireshark_abort_on_dissector_bug
)
577 REPORT_DISSECTOR_BUG("RPC: No reply handler!");
581 dissector_add_custom_table_handle("rpc.reply", g_memdup2(&key
, sizeof(rpc_proc_info_key
)),
582 create_dissector_handle_with_name_and_description(proc
->dissect_reply
, value
->proto_id
, NULL
, proc
->strptr
));
589 /* return the hf_field associated with a previously registered program.
592 rpc_prog_hf(uint32_t prog
, uint32_t vers
)
594 rpc_prog_info_value
*rpc_prog
;
596 if ((rpc_prog
= (rpc_prog_info_value
*)g_hash_table_lookup(rpc_progs
,GUINT_TO_POINTER(prog
)))) {
597 return g_array_index(rpc_prog
->procedure_hfs
, int, vers
);
602 /* return the name associated with a previously registered program. This
603 should probably eventually be expanded to use the rpc YP/NIS map
604 so that it can give names for programs not handled by wireshark */
606 rpc_prog_name(uint32_t prog
)
608 const char *progname
= NULL
;
609 rpc_prog_info_value
*rpc_prog
;
611 if ((rpc_prog
= (rpc_prog_info_value
*)g_hash_table_lookup(rpc_progs
,GUINT_TO_POINTER(prog
))) == NULL
) {
612 progname
= "Unknown";
615 progname
= rpc_prog
->progname
;
621 /*--------------------------------------*/
622 /* end of Hash array with program names */
623 /*--------------------------------------*/
625 /* One of these structures are created for each conversation that contains
626 * RPC and contains the state we need to maintain for the conversation.
628 typedef struct _rpc_conv_info_t
{
633 /* we can not hang this off the conversation structure above since the context
634 will be reused across all tcp connections between the client and the server.
635 a global tree for all contexts should still be unlikely to have collissions
638 wmem_tree_t
*authgss_contexts
;
641 rpc_roundup(unsigned int a
)
643 unsigned int mod
= a
% 4;
645 ret
= a
+ ((mod
)? 4-mod
: 0);
646 /* Check for overflow */
648 THROW(ReportedBoundsError
);
654 dissect_rpc_bool(tvbuff_t
*tvb
, proto_tree
*tree
,
655 int hfindex
, int offset
)
657 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
663 dissect_rpc_uint32(tvbuff_t
*tvb
, proto_tree
*tree
,
664 int hfindex
, int offset
)
666 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
672 dissect_rpc_uint64(tvbuff_t
*tvb
, proto_tree
*tree
,
673 int hfindex
, int offset
)
675 header_field_info
*hfinfo
;
677 hfinfo
= proto_registrar_get_nth(hfindex
);
678 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_UINT64
);
679 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
685 * We want to make this function available outside this file and
686 * allow callers to pass a dissection function for the opaque data
689 dissect_rpc_opaque_data(tvbuff_t
*tvb
, int offset
,
693 bool fixed_length
, uint32_t length
,
694 bool string_data
, const char **string_buffer_ret
,
695 dissect_function_t
*dissect_it
)
698 proto_item
*string_item
= NULL
;
699 proto_tree
*string_tree
= NULL
;
701 uint32_t string_length
;
702 uint32_t string_length_full
;
703 uint32_t string_length_packet
;
704 uint32_t string_length_captured
;
705 uint32_t string_length_copy
;
708 uint32_t fill_length
;
709 uint32_t fill_length_packet
;
710 uint32_t fill_length_captured
;
711 uint32_t fill_length_copy
;
714 /* int string_item_offset; */
716 char *string_buffer
= NULL
;
717 uint8_t *bytes_buffer
;
718 const char *formatted_text
= NULL
;
721 string_length
= length
;
722 data_offset
= offset
;
725 string_length
= tvb_get_ntohl(tvb
,offset
);
726 data_offset
= offset
+ 4;
728 string_length_captured
= tvb_captured_length_remaining(tvb
, data_offset
);
729 string_length_packet
= tvb_reported_length_remaining(tvb
, data_offset
);
730 string_length_full
= rpc_roundup(string_length
);
731 if (string_length_captured
< string_length
) {
732 /* truncated string */
733 string_length_copy
= string_length_captured
;
736 fill_length_copy
= 0;
737 if (string_length_packet
< string_length
)
738 exception
= ReportedBoundsError
;
740 exception
= BoundsError
;
743 /* full string data */
744 string_length_copy
= string_length
;
745 fill_length
= string_length_full
- string_length
;
746 fill_length_captured
= tvb_captured_length_remaining(tvb
,
747 data_offset
+ string_length
);
748 fill_length_packet
= tvb_reported_length_remaining(tvb
,
749 data_offset
+ string_length
);
750 if (fill_length_captured
< fill_length
) {
751 /* truncated fill bytes */
752 fill_length_copy
= fill_length_packet
;
754 if (fill_length_packet
< fill_length
)
755 exception
= ReportedBoundsError
;
757 exception
= BoundsError
;
760 /* full fill bytes */
761 fill_length_copy
= fill_length
;
767 * If we were passed a dissection routine, make a TVB of the data
768 * and call the dissection routine
772 tvbuff_t
*opaque_tvb
;
774 opaque_tvb
= tvb_new_subset_length_caplen(tvb
, data_offset
, string_length_copy
,
777 return (*dissect_it
)(opaque_tvb
, offset
, pinfo
, tree
, NULL
);
782 string_buffer
= tvb_get_string_enc(wmem_packet_scope(), tvb
, data_offset
, string_length_copy
, ENC_ASCII
);
784 bytes_buffer
= tvb_memcpy(tvb
, wmem_alloc(wmem_packet_scope(), string_length_copy
), data_offset
, string_length_copy
);
787 /* calculate a nice printable string */
789 if (string_length
!= string_length_copy
) {
793 formatted
= format_text(wmem_packet_scope(), string_buffer
, strlen(string_buffer
));
794 /* copy over the data and append <TRUNCATED> */
795 formatted_text
=wmem_strdup_printf(wmem_packet_scope(), "%s%s", formatted
, RPC_STRING_TRUNCATED
);
797 formatted_text
=RPC_STRING_DATA RPC_STRING_TRUNCATED
;
801 formatted_text
= format_text(wmem_packet_scope(), string_buffer
, strlen(string_buffer
));
803 formatted_text
=RPC_STRING_DATA
;
807 formatted_text
=RPC_STRING_EMPTY
;
810 /* string_item_offset = offset; */
811 string_tree
= proto_tree_add_subtree_format(tree
, tvb
,offset
, -1,
812 ett_rpc_string
, &string_item
, "%s: %s", proto_registrar_get_name(hfindex
),
816 proto_tree_add_uint(string_tree
, hf_rpc_opaque_length
, tvb
,offset
, 4, string_length
);
822 proto_tree_add_string_format(string_tree
,
823 hfindex
, tvb
, offset
, string_length_copy
,
825 "contents: %s", formatted_text
);
827 proto_tree_add_bytes_format(string_tree
,
828 hfindex
, tvb
, offset
, string_length_copy
,
830 "contents: %s", formatted_text
);
834 offset
+= string_length_copy
;
837 if (fill_truncated
) {
838 proto_tree_add_bytes_format_value(string_tree
, hf_rpc_fill_bytes
, tvb
,
839 offset
, fill_length_copy
, NULL
, "opaque data<TRUNCATED>");
842 proto_tree_add_bytes_format_value(string_tree
, hf_rpc_fill_bytes
, tvb
,
843 offset
, fill_length_copy
, NULL
, "opaque data");
845 offset
+= fill_length_copy
;
848 proto_item_set_end(string_item
, tvb
, offset
);
850 if (string_buffer_ret
!= NULL
)
851 *string_buffer_ret
= formatted_text
;
854 * If the data was truncated, throw the appropriate exception,
855 * so that dissection stops and the frame is properly marked.
864 dissect_rpc_string(tvbuff_t
*tvb
, proto_tree
*tree
,
865 int hfindex
, int offset
, const char **string_buffer_ret
)
867 offset
= dissect_rpc_opaque_data(tvb
, offset
, tree
, NULL
,
868 hfindex
, false, 0, true, string_buffer_ret
, NULL
);
874 dissect_rpc_data(tvbuff_t
*tvb
, proto_tree
*tree
,
875 int hfindex
, int offset
)
877 offset
= dissect_rpc_opaque_data(tvb
, offset
, tree
, NULL
,
878 hfindex
, false, 0, false, NULL
, NULL
);
884 dissect_rpc_bytes(tvbuff_t
*tvb
, proto_tree
*tree
,
885 int hfindex
, int offset
, uint32_t length
,
886 bool string_data
, const char **string_buffer_ret
)
888 offset
= dissect_rpc_opaque_data(tvb
, offset
, tree
, NULL
,
889 hfindex
, true, length
, string_data
, string_buffer_ret
, NULL
);
895 dissect_rpc_list(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
896 int offset
, dissect_function_t
*rpc_list_dissector
, void *data
)
898 uint32_t value_follows
;
901 value_follows
= tvb_get_ntohl(tvb
, offset
);
902 proto_tree_add_boolean(tree
,hf_rpc_value_follows
, tvb
,
903 offset
, 4, value_follows
);
905 if (value_follows
== 1) {
906 offset
= rpc_list_dissector(tvb
, offset
, pinfo
, tree
,
918 dissect_rpc_array(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
919 int offset
, dissect_function_t
*rpc_array_dissector
,
922 proto_item
* lock_item
;
923 proto_tree
* lock_tree
;
926 num
= tvb_get_ntohl(tvb
, offset
);
928 lock_item
= proto_tree_add_item(tree
, hfindex
, tvb
, offset
, -1, ENC_NA
);
930 lock_tree
= proto_item_add_subtree(lock_item
, ett_rpc_array
);
933 proto_tree_add_item(lock_tree
, hf_rpc_no_values
, tvb
, offset
, 4, ENC_NA
);
936 proto_item_set_end(lock_item
, tvb
, offset
);
941 offset
= dissect_rpc_uint32(tvb
, lock_tree
,
942 hf_rpc_array_len
, offset
);
945 offset
= rpc_array_dissector(tvb
, offset
, pinfo
, lock_tree
, NULL
);
948 proto_item_set_end(lock_item
, tvb
, offset
);
953 dissect_rpc_authunix_groups(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
958 proto_item
*gitem
= NULL
;
959 proto_tree
*gtree
= NULL
;
961 gids_count
= tvb_get_ntohl(tvb
,offset
);
962 gtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
,
963 4+gids_count
*4, ett_rpc_gids
, &gitem
, "Auxiliary GIDs (%u)", gids_count
);
966 /* first, open with [ */
967 if (tree
&& gids_count
> 0)
968 proto_item_append_text(gitem
, " [");
970 for (gids_i
= 0 ; gids_i
< gids_count
; gids_i
++) {
971 gids_entry
= tvb_get_ntohl(tvb
,offset
);
973 proto_tree_add_uint(gtree
, hf_rpc_auth_gid
, tvb
,
974 offset
, 4, gids_entry
);
977 /* add at most 16 GIDs to the text */
978 if (tree
&& gids_i
< 16) {
980 proto_item_append_text(gitem
, ", ");
982 proto_item_append_text(gitem
, "%u", gids_entry
);
983 } else if (tree
&& gids_i
== 16) {
984 proto_item_append_text(gitem
, "...");
989 /* finally, close with ] */
990 if (tree
&& gids_count
> 0)
991 proto_item_append_text(gitem
, "]");
997 dissect_rpc_authunix_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1003 stamp
= tvb_get_ntohl(tvb
,offset
);
1004 proto_tree_add_uint(tree
, hf_rpc_auth_stamp
, tvb
,
1008 offset
= dissect_rpc_string(tvb
, tree
,
1009 hf_rpc_auth_machinename
, offset
, NULL
);
1011 uid
= tvb_get_ntohl(tvb
,offset
);
1012 proto_tree_add_uint(tree
, hf_rpc_auth_uid
, tvb
,
1016 gid
= tvb_get_ntohl(tvb
,offset
);
1017 proto_tree_add_uint(tree
, hf_rpc_auth_gid
, tvb
,
1021 offset
= dissect_rpc_authunix_groups(tvb
, tree
, offset
);
1026 typedef struct _gssauth_context_info_t
{
1027 uint32_t create_frame
;
1028 uint32_t destroy_frame
;
1029 } gssauth_context_info_t
;
1033 dissect_rpc_authgss_context(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
,
1034 packet_info
*pinfo
, rpc_conv_info_t
*rpc_conv_info _U_
,
1035 bool is_create
, bool is_destroy
)
1037 proto_item
*context_item
;
1038 proto_tree
*context_tree
;
1039 int old_offset
= offset
;
1041 uint32_t context_length
;
1042 gssauth_context_info_t
*context_info
;
1043 wmem_tree_key_t tkey
[2];
1044 uint32_t key
[4] = {0,0,0,0};
1046 context_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1,
1047 ett_gss_context
, &context_item
, "GSS Context");
1049 context_length
= tvb_get_ntohl(tvb
, offset
);
1050 proto_tree_add_item(context_tree
, hf_rpc_authgss_ctx_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1053 context_offset
= offset
;
1054 proto_tree_add_item(context_tree
, hf_rpc_authgss_ctx
, tvb
, offset
, context_length
, ENC_NA
);
1055 offset
+= context_length
;
1057 offset
= (offset
+ 3) & 0xffffffc;
1059 if (context_length
> 16) {
1060 /* we only track contexts up to 16 bytes in size */
1064 tvb_memcpy(tvb
, key
, context_offset
, context_length
);
1066 tkey
[0].key
= &key
[0];
1070 context_info
= (gssauth_context_info_t
*)wmem_tree_lookup32_array(authgss_contexts
, &tkey
[0]);
1071 if(context_info
== NULL
) {
1072 tvb_memcpy(tvb
, key
, context_offset
, context_length
);
1074 tkey
[0].key
= &key
[0];
1078 context_info
= wmem_new(wmem_file_scope(), gssauth_context_info_t
);
1079 context_info
->create_frame
= 0;
1080 context_info
->destroy_frame
= 0;
1081 wmem_tree_insert32_array(authgss_contexts
, &tkey
[0], context_info
);
1084 context_info
->create_frame
= pinfo
->num
;
1087 context_info
->destroy_frame
= pinfo
->num
;
1090 if (context_info
->create_frame
) {
1092 it
= proto_tree_add_uint(context_tree
, hf_rpc_authgss_ctx_create_frame
, tvb
, 0, 0, context_info
->create_frame
);
1093 proto_item_set_generated(it
);
1096 if (context_info
->destroy_frame
) {
1098 it
= proto_tree_add_uint(context_tree
, hf_rpc_authgss_ctx_destroy_frame
, tvb
, 0, 0, context_info
->destroy_frame
);
1099 proto_item_set_generated(it
);
1102 proto_item_set_len(context_item
, offset
- old_offset
);
1108 dissect_rpc_authgss_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1109 packet_info
*pinfo
, rpc_conv_info_t
*rpc_conv_info
)
1116 agc_v
= tvb_get_ntohl(tvb
, offset
);
1117 proto_tree_add_uint(tree
, hf_rpc_authgss_v
,
1118 tvb
, offset
, 4, agc_v
);
1121 agc_proc
= tvb_get_ntohl(tvb
, offset
);
1122 proto_tree_add_uint(tree
, hf_rpc_authgss_proc
,
1123 tvb
, offset
, 4, agc_proc
);
1126 agc_seq
= tvb_get_ntohl(tvb
, offset
);
1127 proto_tree_add_uint(tree
, hf_rpc_authgss_seq
,
1128 tvb
, offset
, 4, agc_seq
);
1131 agc_svc
= tvb_get_ntohl(tvb
, offset
);
1132 proto_tree_add_uint(tree
, hf_rpc_authgss_svc
,
1133 tvb
, offset
, 4, agc_svc
);
1136 offset
= dissect_rpc_authgss_context(tree
, tvb
, offset
, pinfo
, rpc_conv_info
, false, agc_proc
== RPCSEC_GSS_DESTROY
? true : false);
1142 dissect_rpc_authdes_desblock(tvbuff_t
*tvb
, proto_tree
*tree
,
1143 int hfindex
, int offset
)
1145 proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
1151 dissect_rpc_authdes_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1153 unsigned adc_namekind
;
1154 unsigned window
= 0;
1155 unsigned nickname
= 0;
1157 adc_namekind
= tvb_get_ntohl(tvb
, offset
);
1158 proto_tree_add_uint(tree
, hf_rpc_authdes_namekind
,
1159 tvb
, offset
, 4, adc_namekind
);
1162 switch(adc_namekind
)
1164 case AUTHDES_NAMEKIND_FULLNAME
:
1165 offset
= dissect_rpc_string(tvb
, tree
,
1166 hf_rpc_authdes_netname
, offset
, NULL
);
1167 offset
= dissect_rpc_authdes_desblock(tvb
, tree
,
1168 hf_rpc_authdes_convkey
, offset
);
1169 window
= tvb_get_ntohl(tvb
, offset
);
1170 proto_tree_add_uint(tree
, hf_rpc_authdes_window
, tvb
, offset
, 4,
1175 case AUTHDES_NAMEKIND_NICKNAME
:
1176 nickname
= tvb_get_ntohl(tvb
, offset
);
1177 proto_tree_add_uint(tree
, hf_rpc_authdes_nickname
, tvb
, offset
, 4,
1187 dissect_rpc_authgluster_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1189 proto_tree_add_item(tree
, hf_rpc_auth_lk_owner
, tvb
, offset
,
1193 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_pid
, offset
);
1194 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_uid
, offset
);
1195 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_gid
, offset
);
1196 offset
= dissect_rpc_authunix_groups(tvb
, tree
, offset
);
1202 dissect_rpc_authglusterfs_v2_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1206 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_pid
, offset
);
1207 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_uid
, offset
);
1208 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_gid
, offset
);
1209 offset
= dissect_rpc_authunix_groups(tvb
, tree
, offset
);
1211 len
= tvb_get_ntohl(tvb
, offset
);
1214 proto_tree_add_item(tree
, hf_rpc_auth_lk_owner
, tvb
, offset
,
1222 dissect_rpc_authglusterfs_v3_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1227 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_pid
, offset
);
1228 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_uid
, offset
);
1229 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_gid
, offset
);
1230 offset
= dissect_rpc_uint32(tvb
, tree
, hf_rpc_auth_flags
, offset
);
1231 timestamp
.secs
= tvb_get_ntohl(tvb
, offset
);
1232 timestamp
.nsecs
= (int)tvb_get_ntohi64(tvb
, offset
+ 4);
1234 proto_tree_add_time(tree
, hf_rpc_auth_ctime
, tvb
,
1235 offset
, 12, ×tamp
);
1238 offset
= dissect_rpc_authunix_groups(tvb
, tree
, offset
);
1240 len
= tvb_get_ntohl(tvb
, offset
);
1243 proto_tree_add_item(tree
, hf_rpc_auth_lk_owner
, tvb
, offset
,
1251 dissect_rpc_authgssapi_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
)
1253 proto_tree_add_item(tree
, hf_rpc_authgssapi_v
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1256 proto_tree_add_item(tree
, hf_rpc_authgssapi_msg
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1259 offset
= dissect_rpc_data(tvb
, tree
, hf_rpc_authgssapi_handle
,
1266 dissect_rpc_cred(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1267 packet_info
*pinfo
, rpc_conv_info_t
*rpc_conv_info
)
1274 flavor
= tvb_get_ntohl(tvb
,offset
);
1275 length
= tvb_get_ntohl(tvb
,offset
+4);
1276 length
= rpc_roundup(length
);
1279 ctree
= proto_tree_add_subtree(tree
, tvb
, offset
,
1280 8+length
, ett_rpc_cred
, NULL
, "Credentials");
1281 proto_tree_add_uint(ctree
, hf_rpc_auth_flavor
, tvb
,
1283 proto_tree_add_uint(ctree
, hf_rpc_auth_length
, tvb
,
1284 offset
+4, 4, length
);
1288 dissect_rpc_authunix_cred(tvb
, ctree
, offset
+8);
1296 dissect_rpc_authdes_cred(tvb
, ctree
, offset
+8);
1300 /* AUTH_RSA is (ab)used by Gluster */
1301 dissect_rpc_authgluster_cred(tvb
, ctree
, offset
+8);
1305 dissect_rpc_authgss_cred(tvb
, ctree
, offset
+8, pinfo
, rpc_conv_info
);
1308 case AUTH_GLUSTERFS
:
1309 dissect_rpc_authglusterfs_v2_cred(tvb
, ctree
, offset
+8);
1312 case AUTH_GLUSTERFS_V3
:
1313 dissect_rpc_authglusterfs_v3_cred(tvb
, ctree
, offset
+8);
1317 dissect_rpc_authgssapi_cred(tvb
, ctree
, offset
+8);
1322 proto_tree_add_item(ctree
, hf_rpc_opaque_data
, tvb
, offset
+8, length
, ENC_NA
);
1326 offset
+= 8 + length
;
1332 dissect_rpc_opaque_auth(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1335 conversation_t
*conv
= NULL
;
1336 rpc_conv_info_t
*conv_info
= NULL
;
1338 if (pinfo
->ptype
== PT_TCP
)
1339 conv
= find_conversation_pinfo(pinfo
, 0);
1342 conv_info
= (rpc_conv_info_t
*)conversation_get_proto_data(conv
,
1345 return dissect_rpc_cred(tvb
, tree
, offset
, pinfo
, conv_info
);
1349 * XDR opaque object, the contents of which are interpreted as a GSS-API
1353 dissect_rpc_authgss_token(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1354 packet_info
*pinfo
, int hfindex
)
1356 uint32_t opaque_length
, rounded_length
;
1357 int len_consumed
, length
, reported_length
;
1361 proto_tree
*gtree
= NULL
;
1363 opaque_length
= tvb_get_ntohl(tvb
, offset
);
1364 rounded_length
= rpc_roundup(opaque_length
);
1366 gitem
= proto_tree_add_item(tree
, hfindex
, tvb
, offset
, 4+rounded_length
, ENC_NA
);
1367 gtree
= proto_item_add_subtree(gitem
, ett_rpc_gss_token
);
1368 proto_tree_add_uint(gtree
, hf_rpc_authgss_token_length
,
1369 tvb
, offset
, 4, opaque_length
);
1372 if (opaque_length
!= 0) {
1373 length
= tvb_captured_length_remaining(tvb
, offset
);
1374 reported_length
= tvb_reported_length_remaining(tvb
, offset
);
1375 if (length
> reported_length
)
1376 length
= reported_length
;
1377 if ((uint32_t)length
> opaque_length
)
1378 length
= opaque_length
;
1379 if ((uint32_t)reported_length
> opaque_length
)
1380 reported_length
= opaque_length
;
1381 new_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, length
, reported_length
);
1382 len_consumed
= call_dissector(gssapi_handle
, new_tvb
, pinfo
, gtree
);
1383 offset
+= len_consumed
;
1385 offset
= rpc_roundup(offset
);
1389 /* AUTH_DES verifiers are asymmetrical, so we need to know what type of
1390 * verifier we're decoding (CALL or REPLY).
1393 dissect_rpc_verf(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
, int msg_type
,
1401 flavor
= tvb_get_ntohl(tvb
,offset
);
1402 length
= tvb_get_ntohl(tvb
,offset
+4);
1403 length
= rpc_roundup(length
);
1406 vtree
= proto_tree_add_subtree(tree
, tvb
, offset
,
1407 8+length
, ett_rpc_verf
, NULL
, "Verifier");
1408 proto_tree_add_uint(vtree
, hf_rpc_auth_flavor
, tvb
,
1413 proto_tree_add_uint(vtree
, hf_rpc_auth_length
, tvb
,
1414 offset
+4, 4, length
);
1415 dissect_rpc_authunix_cred(tvb
, vtree
, offset
+8);
1418 proto_tree_add_uint(vtree
, hf_rpc_auth_length
, tvb
,
1419 offset
+4, 4, length
);
1421 if (msg_type
== RPC_CALL
)
1425 dissect_rpc_authdes_desblock(tvb
, vtree
,
1426 hf_rpc_authdes_timestamp
, offset
+8);
1427 window
= tvb_get_ntohl(tvb
, offset
+16);
1428 proto_tree_add_uint(vtree
, hf_rpc_authdes_windowverf
, tvb
,
1429 offset
+16, 4, window
);
1433 /* must be an RPC_REPLY */
1436 dissect_rpc_authdes_desblock(tvb
, vtree
,
1437 hf_rpc_authdes_timeverf
, offset
+8);
1438 nickname
= tvb_get_ntohl(tvb
, offset
+16);
1439 proto_tree_add_uint(vtree
, hf_rpc_authdes_nickname
, tvb
,
1440 offset
+16, 4, nickname
);
1444 dissect_rpc_authgss_token(tvb
, vtree
, offset
+4, pinfo
, hf_rpc_authgss_token
);
1447 proto_tree_add_uint(vtree
, hf_rpc_auth_length
, tvb
,
1448 offset
+4, 4, length
);
1450 proto_tree_add_item(vtree
, hf_rpc_opaque_data
, tvb
, offset
+8, length
, ENC_NA
);
1454 offset
+= 8 + length
;
1460 dissect_rpc_authgss_initarg(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1463 return dissect_rpc_authgss_token(tvb
, tree
, offset
, pinfo
, hf_rpc_authgss_token
);
1467 dissect_rpc_authgss_initres(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1468 packet_info
*pinfo
, rpc_conv_info_t
*rpc_conv_info
)
1470 int major
, minor
, window
;
1472 offset
= dissect_rpc_authgss_context(tree
, tvb
, offset
, pinfo
, rpc_conv_info
, true, false);
1474 major
= tvb_get_ntohl(tvb
,offset
);
1475 proto_tree_add_uint(tree
, hf_rpc_authgss_major
, tvb
,
1479 minor
= tvb_get_ntohl(tvb
,offset
);
1480 proto_tree_add_uint(tree
, hf_rpc_authgss_minor
, tvb
,
1484 window
= tvb_get_ntohl(tvb
,offset
);
1485 proto_tree_add_uint(tree
, hf_rpc_authgss_window
, tvb
,
1489 offset
= dissect_rpc_authgss_token(tvb
, tree
, offset
, pinfo
, hf_rpc_authgss_token
);
1495 dissect_rpc_authgssapi_initarg(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1501 mtree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1,
1502 ett_rpc_authgssapi_msg
, NULL
, "AUTH_GSSAPI Msg");
1504 version
= tvb_get_ntohl(tvb
, offset
);
1506 proto_tree_add_uint(mtree
, hf_rpc_authgssapi_msgv
, tvb
, offset
, 4, version
);
1509 offset
= dissect_rpc_authgss_token(tvb
, mtree
, offset
, pinfo
, hf_rpc_authgss_token
);
1515 dissect_rpc_authgssapi_initres(tvbuff_t
* tvb
, proto_tree
* tree
, int offset
,
1519 unsigned major
, minor
;
1522 mtree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1,
1523 ett_rpc_authgssapi_msg
, NULL
, "AUTH_GSSAPI Msg");
1525 version
= tvb_get_ntohl(tvb
,offset
);
1526 proto_tree_add_uint(mtree
, hf_rpc_authgssapi_msgv
, tvb
,
1527 offset
, 4, version
);
1530 offset
= dissect_rpc_data(tvb
, mtree
, hf_rpc_authgssapi_handle
,
1533 major
= tvb_get_ntohl(tvb
,offset
);
1534 proto_tree_add_uint(mtree
, hf_rpc_authgss_major
, tvb
,
1538 minor
= tvb_get_ntohl(tvb
,offset
);
1539 proto_tree_add_uint(mtree
, hf_rpc_authgss_minor
, tvb
,
1543 offset
= dissect_rpc_authgss_token(tvb
, mtree
, offset
, pinfo
, hf_rpc_authgss_token
);
1545 offset
= dissect_rpc_data(tvb
, mtree
, hf_rpc_authgssapi_isn
, offset
);
1551 dissect_auth_gssapi_data(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
)
1553 offset
= dissect_rpc_data(tvb
, tree
, hf_rpc_authgss_data
,
1559 call_dissect_function(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1560 int offset
, dissector_handle_t dissect_function
, const char *progname
,
1561 rpc_call_info_value
*rpc_call
)
1563 const char *saved_proto
;
1566 if (dissect_function
!= NULL
) {
1567 /* set the current protocol name */
1568 saved_proto
= pinfo
->current_proto
;
1569 if (progname
!= NULL
)
1570 pinfo
->current_proto
= progname
;
1572 /* call the dissector for the next level */
1573 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1574 offset
+= call_dissector_with_data(dissect_function
, next_tvb
, pinfo
, tree
, rpc_call
);
1576 /* restore the protocol name */
1577 pinfo
->current_proto
= saved_proto
;
1585 dissect_rpc_authgss_integ_data(tvbuff_t
*tvb
, packet_info
*pinfo
,
1586 proto_tree
*tree
, int offset
,
1587 dissector_handle_t dissect_function
,
1588 const char *progname
, rpc_call_info_value
*rpc_call
)
1590 int reported_length
, captured_length
;
1591 uint32_t length
, rounded_length
, seq
;
1595 reported_length
= tvb_reported_length_remaining(tvb
, offset
);
1596 captured_length
= tvb_captured_length_remaining(tvb
, offset
);
1597 length
= tvb_get_ntohl(tvb
, offset
);
1598 rounded_length
= rpc_roundup(length
);
1599 seq
= tvb_get_ntohl(tvb
, offset
+4);
1601 if (captured_length
< reported_length
) {
1602 /* Set rounded length so it does not croak while setting up the
1603 * GSS Data subtree when the packet has been truncated so at
1604 * least the rest of the packet could be partially dissected */
1605 rounded_length
= captured_length
- 4;
1607 gtree
= proto_tree_add_subtree(tree
, tvb
, offset
,
1608 4+rounded_length
, ett_rpc_gss_data
, NULL
, "GSS Data");
1609 proto_tree_add_uint(gtree
, hf_rpc_authgss_data_length
,
1610 tvb
, offset
, 4, length
);
1611 proto_tree_add_uint(gtree
, hf_rpc_authgss_seq
,
1612 tvb
, offset
+4, 4, seq
);
1616 call_dissect_function(tvb
, pinfo
, gtree
, offset
, dissect_function
, progname
, rpc_call
);
1618 offset
+= rounded_length
- 4;
1619 offset
= dissect_rpc_authgss_token(tvb
, tree
, offset
, pinfo
, hf_rpc_authgss_checksum
);
1625 dissect_rpc_authgss_priv_data(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
,
1626 packet_info
*pinfo
, gssapi_encrypt_info_t
* gssapi_encrypt
)
1629 /* int return_offset; */
1631 length
= tvb_get_ntohl(tvb
, offset
);
1632 proto_tree_add_uint(tree
, hf_rpc_authgss_data_length
,
1633 tvb
, offset
, 4, length
);
1636 proto_tree_add_item(tree
, hf_rpc_authgss_data
, tvb
, offset
, length
,
1640 /* can't decrypt if we don't have SPNEGO */
1641 if (!spnego_krb5_wrap_handle
) {
1646 /* return_offset = */ call_dissector_with_data(spnego_krb5_wrap_handle
,
1647 tvb_new_subset_remaining(tvb
, offset
),
1648 pinfo
, tree
, gssapi_encrypt
);
1654 static address null_address
= ADDRESS_INIT_NONE
;
1657 * Attempt to find a conversation for a call and, if we don't find one,
1660 static conversation_t
*
1661 get_conversation_for_call(packet_info
*pinfo
)
1663 conversation_t
*conversation
;
1666 * If the transport is connection-oriented (TCP or Infiniband),
1667 * we use the addresses and ports of both endpoints, because
1668 * the addresses and ports of the two endpoints should be
1669 * the same for a call and its matching reply. (XXX - what
1670 * if the connection is broken and re-established between
1671 * the call and the reply? Or will the call be re-made on
1672 * the new connection?)
1674 * If the transport is connectionless, we don't worry
1675 * about the address to which the call was sent, because
1676 * there's no guarantee that the reply will come from the
1677 * address to which the call was sent. We also don't
1678 * worry about the port *from* which the call was sent,
1679 * because some clients (*cough* macOS NFS client *cough*)
1680 * might send retransmissions from a different port from
1681 * the original request.
1683 if (pinfo
->ptype
== PT_TCP
|| pinfo
->ptype
== PT_IBQP
|| pinfo
->ptype
== PT_IWARP_MPA
) {
1684 conversation
= find_conversation_pinfo(pinfo
, 0);
1687 * XXX - you currently still have to pass a non-null
1688 * pointer for the second address argument even
1689 * if you use NO_ADDR_B.
1691 conversation
= find_conversation(pinfo
->num
,
1692 &pinfo
->src
, &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
),
1693 pinfo
->destport
, 0, NO_ADDR_B
|NO_PORT_B
);
1696 if (conversation
== NULL
) {
1697 if (pinfo
->ptype
== PT_TCP
|| pinfo
->ptype
== PT_IBQP
|| pinfo
->ptype
== PT_IWARP_MPA
) {
1698 conversation
= conversation_new(pinfo
->num
,
1699 &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
),
1700 pinfo
->srcport
, pinfo
->destport
, 0);
1702 conversation
= conversation_new(pinfo
->num
,
1703 &pinfo
->src
, &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
),
1704 pinfo
->destport
, 0, NO_ADDR2
|NO_PORT2
);
1707 return conversation
;
1710 static conversation_t
*
1711 find_conversation_for_reply(packet_info
*pinfo
)
1713 conversation_t
*conversation
;
1716 * If the transport is connection-oriented (TCP or Infiniband),
1717 * we use the addresses and ports of both endpoints, because
1718 * the addresses and ports of the two endpoints should be
1719 * the same for a call and its matching reply. (XXX - what
1720 * if the connection is broken and re-established between
1721 * the call and the reply? Or will the call be re-made on
1722 * the new connection?)
1724 * If the transport is connectionless, we don't worry
1725 * about the address from which the reply was sent,
1726 * because there's no guarantee that the call was sent
1727 * to the address from which the reply came. We also
1728 * don't worry about the port *to* which the reply was
1729 * sent, because some clients (*cough* macOS NFS client
1730 * *cough*) might send call retransmissions from a
1731 * different port from the original request, so replies
1732 * to the original call and a retransmission of the call
1733 * might be sent to different ports.
1735 if (pinfo
->ptype
== PT_TCP
|| pinfo
->ptype
== PT_IBQP
|| pinfo
->ptype
== PT_IWARP_MPA
) {
1736 conversation
= find_conversation_pinfo(pinfo
, 0);
1739 * XXX - you currently still have to pass a non-null
1740 * pointer for the second address argument even
1741 * if you use NO_ADDR_B.
1743 conversation
= find_conversation(pinfo
->num
,
1744 &pinfo
->dst
, &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
),
1745 pinfo
->srcport
, 0, NO_ADDR_B
|NO_PORT_B
);
1747 return conversation
;
1750 static conversation_t
*
1751 new_conversation_for_reply(packet_info
*pinfo
)
1753 conversation_t
*conversation
;
1755 switch (pinfo
->ptype
)
1758 conversation
= conversation_new(pinfo
->num
,
1759 &pinfo
->src
, &pinfo
->dst
, CONVERSATION_TCP
,
1760 pinfo
->srcport
, pinfo
->destport
, 0);
1763 conversation
= conversation_new(pinfo
->num
,
1764 &pinfo
->src
, &pinfo
->dst
, CONVERSATION_IBQP
,
1765 pinfo
->srcport
, pinfo
->destport
, 0);
1768 conversation
= conversation_new(pinfo
->num
,
1769 &pinfo
->src
, &pinfo
->dst
, CONVERSATION_IWARP_MPA
,
1770 pinfo
->srcport
, pinfo
->destport
, 0);
1773 conversation
= conversation_new(pinfo
->num
,
1774 &pinfo
->dst
, &null_address
, conversation_pt_to_conversation_type(pinfo
->ptype
),
1775 pinfo
->srcport
, 0, NO_ADDR2
|NO_PORT2
);
1778 return conversation
;
1782 * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
1783 * dissector for the CALLIT procedure.
1785 * Record these in the same table as the direct calls
1786 * so we can find it when dissecting an indirect call reply.
1787 * (There should not be collissions between xid between direct and
1791 dissect_rpc_indir_call(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1792 int offset
, int args_id
, uint32_t prog
, uint32_t vers
, uint32_t proc
)
1794 conversation_t
* conversation
;
1795 rpc_proc_info_key key
;
1796 rpc_call_info_value
*rpc_call
;
1797 dissector_handle_t dissect_function
= NULL
;
1798 rpc_conv_info_t
*rpc_conv_info
=NULL
;
1804 if ((dissect_function
= dissector_get_custom_table_handle(subdissector_call_table
, &key
)) != NULL
) {
1806 * Establish a conversation for the call, for use when
1807 * matching calls with replies.
1809 conversation
= get_conversation_for_call(pinfo
);
1812 * Do we already have a state structure for this conv
1814 rpc_conv_info
= (rpc_conv_info_t
*)conversation_get_proto_data(conversation
, proto_rpc
);
1815 if (!rpc_conv_info
) {
1816 /* No. Attach that information to the conversation, and add
1817 * it to the list of information structures.
1819 rpc_conv_info
= wmem_new(wmem_file_scope(), rpc_conv_info_t
);
1820 rpc_conv_info
->xids
=wmem_tree_new(wmem_file_scope());
1822 conversation_add_proto_data(conversation
, proto_rpc
, rpc_conv_info
);
1825 /* Make the dissector for this conversation the non-heuristic
1827 conversation_set_dissector(conversation
,
1828 (pinfo
->ptype
== PT_TCP
) ? rpc_tcp_handle
: rpc_handle
);
1830 /* Dissectors for RPC procedure calls and replies shouldn't
1831 create new tvbuffs, and we don't create one ourselves,
1832 so we should have been handed the tvbuff for this RPC call;
1833 as such, the XID is at offset 0 in this tvbuff. */
1834 /* look up the request */
1835 xid
= tvb_get_ntohl(tvb
, offset
);
1836 rpc_call
= (rpc_call_info_value
*)wmem_tree_lookup32(rpc_conv_info
->xids
, xid
);
1837 if (rpc_call
== NULL
) {
1838 /* We didn't find it; create a new entry.
1839 Prepare the value data.
1840 Not all of it is needed for handling indirect
1841 calls, so we set a bunch of items to 0. */
1842 rpc_call
= wmem_new(wmem_file_scope(), rpc_call_info_value
);
1843 rpc_call
->req_num
= 0;
1844 rpc_call
->rep_num
= 0;
1845 rpc_call
->prog
= prog
;
1846 rpc_call
->vers
= vers
;
1847 rpc_call
->proc
= proc
;
1848 rpc_call
->private_data
= NULL
;
1851 * XXX - what about RPCSEC_GSS?
1852 * Do we have to worry about it?
1854 rpc_call
->flavor
= FLAVOR_NOT_GSSAPI
;
1855 rpc_call
->gss_proc
= 0;
1856 rpc_call
->gss_svc
= 0;
1858 wmem_tree_insert32(rpc_conv_info
->xids
, xid
, (void *)rpc_call
);
1862 /* We don't know the procedure.
1863 Happens only with strange program versions or
1864 non-existing dissectors.
1865 Just show the arguments as opaque data. */
1866 offset
= dissect_rpc_data(tvb
, tree
, args_id
,
1871 proto_tree_add_item(tree
, hf_rpc_argument_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1874 /* Dissect the arguments */
1875 offset
= call_dissect_function(tvb
, pinfo
, tree
, offset
,
1876 dissect_function
, NULL
, rpc_call
);
1881 * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
1885 dissect_rpc_indir_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
1886 int offset
, int result_id
, int prog_id
, int vers_id
, int proc_id
)
1888 conversation_t
* conversation
;
1889 rpc_call_info_value
*rpc_call
;
1890 const char *procname
=NULL
;
1891 dissector_handle_t dissect_function
= NULL
;
1892 rpc_conv_info_t
*rpc_conv_info
=NULL
;
1893 rpc_proc_info_key key
;
1897 * Look for the matching call in the xid table.
1898 * A reply must match a call that we've seen, and the
1899 * reply must be sent to the same address that the call came
1900 * from, and must come from the port to which the call was sent.
1902 conversation
= find_conversation_for_reply(pinfo
);
1903 if (conversation
== NULL
) {
1904 /* We haven't seen an RPC call for that conversation,
1905 so we can't check for a reply to that call.
1906 Just show the reply stuff as opaque data. */
1907 offset
= dissect_rpc_data(tvb
, tree
, result_id
,
1912 * Do we already have a state structure for this conv
1914 rpc_conv_info
= (rpc_conv_info_t
*)conversation_get_proto_data(conversation
, proto_rpc
);
1915 if (!rpc_conv_info
) {
1916 /* No. Attach that information to the conversation, and add
1917 * it to the list of information structures.
1919 rpc_conv_info
= wmem_new(wmem_file_scope(), rpc_conv_info_t
);
1920 rpc_conv_info
->xids
=wmem_tree_new(wmem_file_scope());
1921 conversation_add_proto_data(conversation
, proto_rpc
, rpc_conv_info
);
1924 /* The XIDs of the call and reply must match. */
1925 xid
= tvb_get_ntohl(tvb
, 0);
1926 rpc_call
= (rpc_call_info_value
*)wmem_tree_lookup32(rpc_conv_info
->xids
, xid
);
1927 if (rpc_call
== NULL
) {
1928 /* The XID doesn't match a call from that
1929 conversation, so it's probably not an RPC reply.
1930 Just show the reply stuff as opaque data. */
1931 offset
= dissect_rpc_data(tvb
, tree
, result_id
,
1936 key
.prog
= rpc_call
->prog
;
1937 key
.vers
= rpc_call
->vers
;
1938 key
.proc
= rpc_call
->proc
;
1940 dissect_function
= dissector_get_custom_table_handle(subdissector_reply_table
, &key
);
1941 if (dissect_function
!= NULL
) {
1942 procname
= dissector_handle_get_description(dissect_function
);
1945 procname
=wmem_strdup_printf(wmem_packet_scope(), "proc-%u", rpc_call
->proc
);
1950 proto_item
*tmp_item
;
1952 /* Put the program, version, and procedure into the tree. */
1953 tmp_item
=proto_tree_add_uint_format(tree
, prog_id
, tvb
,
1954 0, 0, rpc_call
->prog
, "Program: %s (%u)",
1955 rpc_prog_name(rpc_call
->prog
), rpc_call
->prog
);
1956 proto_item_set_generated(tmp_item
);
1958 tmp_item
=proto_tree_add_uint(tree
, vers_id
, tvb
, 0, 0, rpc_call
->vers
);
1959 proto_item_set_generated(tmp_item
);
1961 tmp_item
=proto_tree_add_uint_format(tree
, proc_id
, tvb
,
1962 0, 0, rpc_call
->proc
, "Procedure: %s (%u)",
1963 procname
, rpc_call
->proc
);
1964 proto_item_set_generated(tmp_item
);
1967 if (dissect_function
== NULL
) {
1968 /* We don't know how to dissect the reply procedure.
1969 Just show the reply stuff as opaque data. */
1970 offset
= dissect_rpc_data(tvb
, tree
, result_id
,
1975 /* Put the length of the reply value into the tree. */
1976 proto_tree_add_item(tree
, hf_rpc_argument_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1979 /* Dissect the return value */
1980 offset
= call_dissect_function(tvb
, pinfo
, tree
, offset
,
1981 dissect_function
, NULL
, rpc_call
);
1986 * Just mark this as a continuation of an earlier packet.
1989 dissect_rpc_continuation(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1991 proto_item
*rpc_item
;
1992 proto_tree
*rpc_tree
;
1994 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
1995 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation");
1997 rpc_item
= proto_tree_add_item(tree
, proto_rpc
, tvb
, 0, -1, ENC_NA
);
1998 rpc_tree
= proto_item_add_subtree(rpc_item
, ett_rpc
);
1999 proto_tree_add_item(rpc_tree
, hf_rpc_continuation_data
, tvb
, 0, -1, ENC_NA
);
2004 dissect_rpc_void(tvbuff_t
*tvb _U_
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, void *data _U_
)
2010 dissect_rpc_unknown(tvbuff_t
*tvb _U_
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, void *data _U_
)
2012 unsigned captured_length
= tvb_captured_length(tvb
);
2014 proto_tree_add_item(tree
, hf_rpc_unknown_body
, tvb
, 0, captured_length
, ENC_NA
);
2015 return captured_length
;
2018 static rpc_prog_info_value
*
2019 looks_like_rpc_call(tvbuff_t
*tvb
, int offset
)
2021 uint32_t rpc_prog_key
;
2022 rpc_prog_info_value
*rpc_prog
;
2024 if (!tvb_bytes_exist(tvb
, offset
, 16)) {
2025 /* Captured data in packet isn't enough to let us
2030 /* XID can be anything, so don't check it.
2031 We already have the message type.
2032 Check whether an RPC version number of 2 is in the
2033 location where it would be, and that an RPC program
2034 number we know about is in the location where it would be.
2036 Sun's snoop just checks for a message direction of RPC_CALL
2037 and a version number of 2, which is a bit of a weak heuristic.
2039 We could conceivably check for any of the program numbers
2042 ftp://ftp.tau.ac.il/pub/users/eilon/rpc/rpc
2044 and report it as RPC (but not dissect the payload if
2045 we don't have a subdissector) if it matches. */
2046 rpc_prog_key
= tvb_get_ntohl(tvb
, offset
+ 12);
2048 /* we only dissect RPC version 2 */
2049 if (tvb_get_ntohl(tvb
, offset
+ 8) != 2)
2052 /* Do we know this program? */
2053 rpc_prog
= (rpc_prog_info_value
*)g_hash_table_lookup(rpc_progs
, GUINT_TO_POINTER(rpc_prog_key
));
2054 if (rpc_prog
== NULL
) {
2059 * If the user has specified that he wants to try to
2060 * dissect even completely unknown RPC program numbers,
2061 * then let him do that.
2063 if (!rpc_dissect_unknown_programs
) {
2064 /* They didn't, so just fail. */
2069 * The user wants us to try to dissect even
2070 * unknown program numbers.
2072 * Use some heuristics to keep from matching any
2073 * packet with a 2 in the appropriate location.
2074 * We check that the program number is neither
2075 * 0 nor -1, and that the version is <= 10, which
2076 * is better than nothing.
2078 if (rpc_prog_key
== 0 || rpc_prog_key
== 0xffffffff)
2080 version
= tvb_get_ntohl(tvb
, offset
+16);
2084 rpc_prog
= wmem_new0(wmem_packet_scope(), rpc_prog_info_value
);
2085 rpc_prog
->proto_id
= proto_rpc_unknown
;
2086 rpc_prog
->ett
= ett_rpc_unknown_program
;
2087 rpc_prog
->progname
= wmem_strdup_printf(wmem_packet_scope(), "Unknown RPC program %u", rpc_prog_key
);
2093 static rpc_call_info_value
*
2094 looks_like_rpc_reply(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
)
2097 conversation_t
*conversation
;
2098 rpc_conv_info_t
*rpc_conv_info
;
2099 rpc_call_info_value
*rpc_call
;
2101 /* A reply must match a call that we've seen, and the reply
2102 must be sent to the same address that the call came from,
2103 and must come from the port to which the call was sent.
2105 If the transport is connection-oriented (we check, for
2106 now, only for "pinfo->ptype" of PT_TCP), we take
2107 into account the port from which the call was sent
2108 and the address to which the call was sent, because
2109 the addresses and ports of the two endpoints should be
2110 the same for all calls and replies.
2112 If the transport is connectionless, we don't worry
2113 about the address from which the reply was sent,
2114 because there's no guarantee that the call was sent
2115 to the address from which the reply came. We also
2116 don't worry about the port *to* which the reply was
2117 sent, because some clients (*cough* macOS NFS client
2118 *cough*) might send retransmissions from a
2119 different port from the original request, so replies
2120 to the original call and a retransmission of the call
2121 might be sent to different ports.
2123 Sun's snoop just checks for a message direction of RPC_REPLY
2124 and a status of MSG_ACCEPTED or MSG_DENIED, which is a bit
2125 of a weak heuristic. */
2126 xid
= tvb_get_ntohl(tvb
, offset
);
2127 conversation
= find_conversation_for_reply(pinfo
);
2128 if (conversation
!= NULL
) {
2130 * We have a conversation; try to find an RPC
2131 * state structure for the conversation.
2133 rpc_conv_info
= (rpc_conv_info_t
*)conversation_get_proto_data(conversation
, proto_rpc
);
2134 if (rpc_conv_info
!= NULL
)
2135 rpc_call
= (rpc_call_info_value
*)wmem_tree_lookup32(rpc_conv_info
->xids
, xid
);
2140 * We don't have a conversation, so we obviously
2141 * don't have an RPC state structure for it.
2143 rpc_conv_info
= NULL
;
2147 if (rpc_call
== NULL
) {
2149 * We don't have a conversation, or we have one but
2150 * there's no RPC state information for it, or
2151 * we have RPC state information but the XID doesn't
2152 * match a call from the conversation, so it's
2153 * probably not an RPC reply.
2155 * Unless we're permitted to scan for embedded records
2156 * and this is a connection-oriented transport,
2159 if (((! rpc_find_fragment_start
) || (pinfo
->ptype
!= PT_TCP
)) && (pinfo
->ptype
!= PT_IBQP
) && (pinfo
->ptype
!= PT_IWARP_MPA
)) {
2164 * Do we have a conversation to which to attach
2167 if (conversation
== NULL
) {
2169 * It's not part of any conversation - create
2172 conversation
= new_conversation_for_reply(pinfo
);
2176 * Do we have RPC information for that conversation?
2178 if (rpc_conv_info
== NULL
) {
2180 * No. Create a new RPC information structure,
2181 * and attach it to the conversation.
2183 rpc_conv_info
= wmem_new(wmem_file_scope(), rpc_conv_info_t
);
2184 rpc_conv_info
->xids
=wmem_tree_new(wmem_file_scope());
2186 conversation_add_proto_data(conversation
, proto_rpc
, rpc_conv_info
);
2190 * Define a dummy call for this reply.
2192 rpc_call
= wmem_new0(wmem_file_scope(), rpc_call_info_value
);
2193 rpc_call
->rep_num
= pinfo
->num
;
2194 rpc_call
->xid
= xid
;
2195 rpc_call
->flavor
= FLAVOR_NOT_GSSAPI
; /* total punt */
2196 rpc_call
->req_time
= pinfo
->abs_ts
;
2199 wmem_tree_insert32(rpc_conv_info
->xids
, xid
, (void *)rpc_call
);
2202 /* pass rpc_info to subdissectors */
2203 rpc_call
->request
= false;
2208 dissect_rpc_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2209 tvbuff_t
*frag_tvb
, fragment_head
*ipfd_head
, int tp_type
,
2210 uint32_t rpc_rm
, bool first_pdu
, bool can_defragment
)
2213 rpc_call_info_value
*rpc_call
;
2214 rpc_prog_info_value
*rpc_prog
;
2215 uint32_t rpc_prog_key
;
2218 unsigned int rpcvers
;
2219 unsigned int prog
= 0;
2220 unsigned int vers
= 0;
2221 unsigned int proc
= 0;
2222 unsigned int cred_flavor
= 0;
2223 flavor_t flavor
= FLAVOR_UNKNOWN
;
2224 unsigned int gss_proc
= 0;
2225 unsigned int gss_svc
= 0;
2226 protocol_t
*proto
= NULL
;
2231 unsigned int reply_state
;
2232 unsigned int accept_state
;
2233 unsigned int reject_state
;
2235 const char *msg_type_name
;
2236 const char *progname
;
2237 const char *procname
;
2239 unsigned int vers_low
;
2240 unsigned int vers_high
;
2242 unsigned int auth_state
;
2244 proto_item
*rpc_item
= NULL
;
2245 proto_tree
*rpc_tree
= NULL
;
2247 proto_item
*pitem
= NULL
;
2248 proto_tree
*ptree
= NULL
;
2249 int offset
= (tp_type
!= RPC_UDP
&& tvb
== frag_tvb
) ? 4 : 0;
2251 rpc_proc_info_key key
;
2252 conversation_t
* conversation
;
2255 dissector_handle_t dissect_function
;
2256 bool dissect_rpc_flag
= true;
2258 rpc_conv_info_t
*rpc_conv_info
=NULL
;
2259 gssapi_encrypt_info_t gssapi_encrypt
;
2262 * Check to see whether this looks like an RPC call or reply.
2264 if (!tvb_bytes_exist(tvb
, offset
, 8)) {
2265 /* Captured data in packet isn't enough to let us tell. */
2269 /* both directions need at least this */
2270 msg_type
= tvb_get_ntohl(tvb
, offset
+ 4);
2275 /* Check for RPC call. */
2276 rpc_prog
= looks_like_rpc_call(tvb
, offset
);
2277 if (rpc_prog
== NULL
)
2283 /* Check for RPC reply. */
2284 rpc_call
= looks_like_rpc_reply(tvb
, pinfo
, offset
);
2285 if (rpc_call
== NULL
)
2291 /* The putative message type field contains neither
2292 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
2297 if (tp_type
!= RPC_UDP
) {
2299 * This is RPC-over-TCP; check if this is the last
2302 if (!(rpc_rm
& RPC_RM_LASTFRAG
)) {
2304 * This isn't the last fragment.
2305 * If we're doing reassembly, just return
2306 * true to indicate that this looks like
2307 * the beginning of an RPC message,
2308 * and let them do fragment reassembly.
2315 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
2317 rpc_item
= proto_tree_add_item(tree
, proto_rpc
, tvb
, 0, -1,
2319 rpc_tree
= proto_item_add_subtree(rpc_item
, ett_rpc
);
2321 if (tp_type
!= RPC_UDP
) {
2322 show_rpc_fraginfo(tvb
, frag_tvb
, rpc_tree
, rpc_rm
,
2326 xid
= tvb_get_ntohl(tvb
, offset
);
2327 proto_tree_add_item(rpc_tree
,hf_rpc_xid
, tvb
,
2328 offset
, 4, ENC_BIG_ENDIAN
);
2330 msg_type_name
= val_to_str(msg_type
,rpc_msg_type
,"%u");
2332 proto_tree_add_uint(rpc_tree
, hf_rpc_msgtype
, tvb
,
2333 offset
+4, 4, msg_type
);
2334 proto_item_append_text(rpc_item
, ", Type:%s XID:0x%08x", msg_type_name
, xid
);
2342 proto
= rpc_prog
->proto
;
2343 proto_id
= rpc_prog
->proto_id
;
2344 ett
= rpc_prog
->ett
;
2345 progname
= rpc_prog
->progname
;
2347 rpcvers
= tvb_get_ntohl(tvb
, offset
);
2349 proto_tree_add_uint(rpc_tree
,
2350 hf_rpc_version
, tvb
, offset
, 4, rpcvers
);
2353 prog
= tvb_get_ntohl(tvb
, offset
+ 4);
2356 proto_tree_add_uint_format_value(rpc_tree
,
2357 hf_rpc_program
, tvb
, offset
+4, 4, prog
,
2358 "%s (%u)", progname
, prog
);
2361 /* Set the protocol name to the underlying
2363 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, progname
);
2365 vers
= tvb_get_ntohl(tvb
, offset
+8);
2367 proto_tree_add_uint(rpc_tree
,
2368 hf_rpc_programversion
, tvb
, offset
+8, 4, vers
);
2371 proc
= tvb_get_ntohl(tvb
, offset
+12);
2377 if ((dissect_function
= dissector_get_custom_table_handle(subdissector_call_table
, &key
)) != NULL
) {
2378 procname
= dissector_handle_get_description(dissect_function
);
2381 /* happens only with unknown program or version
2384 dissect_function
= data_handle
;
2385 procname
=wmem_strdup_printf(wmem_packet_scope(), "proc-%u", proc
);
2388 /* Check for RPCSEC_GSS and AUTH_GSSAPI */
2389 if (tvb_bytes_exist(tvb
, offset
+16, 4)) {
2390 cred_flavor
= tvb_get_ntohl(tvb
, offset
+16);
2391 switch (cred_flavor
) {
2395 * It's GSS-API authentication...
2397 if (tvb_bytes_exist(tvb
, offset
+28, 8)) {
2399 * ...and we have the procedure
2400 * and service information for it.
2402 flavor
= FLAVOR_GSSAPI
;
2403 gss_proc
= tvb_get_ntohl(tvb
, offset
+28);
2404 gss_svc
= tvb_get_ntohl(tvb
, offset
+36);
2407 * ...but the procedure and service
2408 * information isn't available.
2410 flavor
= FLAVOR_GSSAPI_NO_INFO
;
2416 * AUTH_GSSAPI flavor. If auth_msg is true,
2417 * then this is an AUTH_GSSAPI message and
2418 * not an application level message.
2420 if (tvb_bytes_exist(tvb
, offset
+28, 4)) {
2421 if (tvb_get_ntohl(tvb
, offset
+28)) {
2422 flavor
= FLAVOR_AUTHGSSAPI_MSG
;
2424 procname
= val_to_str(gss_proc
,
2425 rpc_authgssapi_proc
, "Unknown (%d)");
2427 flavor
= FLAVOR_AUTHGSSAPI
;
2434 * It's not GSS-API authentication.
2436 flavor
= FLAVOR_NOT_GSSAPI
;
2441 proto_tree_add_uint_format_value(rpc_tree
,
2442 hf_rpc_procedure
, tvb
, offset
+12, 4, proc
,
2443 "%s (%u)", procname
, proc
);
2445 /* Print the program version, procedure name, and message type (call or reply). */
2447 col_clear(pinfo
->cinfo
, COL_INFO
);
2449 col_append_str(pinfo
->cinfo
, COL_INFO
, " ; ");
2450 /* Special case for NFSv4 - if the type is COMPOUND, do not print the procedure name */
2451 if (vers
==4 && prog
==NFS_PROGRAM
&& !strcmp(procname
, "COMPOUND"))
2452 col_append_fstr(pinfo
->cinfo
, COL_INFO
,"V%u %s", vers
,
2455 col_append_fstr(pinfo
->cinfo
, COL_INFO
,"V%u %s %s",
2456 vers
, procname
, msg_type_name
);
2459 * Establish a conversation for the call, for use when
2460 * matching calls with replies.
2462 conversation
= get_conversation_for_call(pinfo
);
2465 * Do we already have a state structure for this conv
2467 rpc_conv_info
= (rpc_conv_info_t
*)conversation_get_proto_data(conversation
, proto_rpc
);
2468 if (!rpc_conv_info
) {
2469 /* No. Attach that information to the conversation, and add
2470 * it to the list of information structures.
2472 rpc_conv_info
= wmem_new(wmem_file_scope(), rpc_conv_info_t
);
2473 rpc_conv_info
->xids
=wmem_tree_new(wmem_file_scope());
2474 conversation_add_proto_data(conversation
, proto_rpc
, rpc_conv_info
);
2478 /* Make the dissector for this conversation the non-heuristic
2480 if (tp_type
!= RPC_TLS
&& cred_flavor
!= AUTH_TLS
) {
2481 conversation_set_dissector(conversation
,
2482 (pinfo
->ptype
== PT_TCP
) ? rpc_tcp_handle
: rpc_handle
);
2485 /* look up the request */
2486 rpc_call
= (rpc_call_info_value
*)wmem_tree_lookup32(rpc_conv_info
->xids
, xid
);
2488 /* We've seen a request with this XID, with the same
2489 source and destination, before - but was it
2491 if (pinfo
->num
!= rpc_call
->req_num
) {
2492 /* No, so it's a duplicate request.
2494 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
,
2495 "[RPC retransmission of #%u]",
2497 proto_tree_add_item(rpc_tree
, hf_rpc_dup
, tvb
,
2499 proto_tree_add_uint(rpc_tree
, hf_rpc_call_dup
,
2500 tvb
, 0,0, rpc_call
->req_num
);
2502 if(rpc_call
->rep_num
){
2503 col_append_fstr(pinfo
->cinfo
, COL_INFO
," (Reply In %u)", rpc_call
->rep_num
);
2506 /* Prepare the value data.
2507 "req_num" and "rep_num" are frame numbers;
2508 frame numbers are 1-origin, so we use 0
2509 to mean "we don't yet know in which frame
2510 the reply for this call appears". */
2511 rpc_call
= wmem_new(wmem_file_scope(), rpc_call_info_value
);
2512 rpc_call
->req_num
= pinfo
->num
;
2513 rpc_call
->rep_num
= 0;
2514 rpc_call
->prog
= prog
;
2515 rpc_call
->vers
= vers
;
2516 rpc_call
->proc
= proc
;
2517 rpc_call
->private_data
= NULL
;
2518 rpc_call
->xid
= xid
;
2519 rpc_call
->flavor
= flavor
;
2520 rpc_call
->gss_proc
= gss_proc
;
2521 rpc_call
->gss_svc
= gss_svc
;
2522 rpc_call
->req_time
= pinfo
->abs_ts
;
2525 wmem_tree_insert32(rpc_conv_info
->xids
, xid
, (void *)rpc_call
);
2528 if(rpc_call
->rep_num
){
2529 proto_item
*tmp_item
;
2531 tmp_item
=proto_tree_add_uint_format(rpc_tree
, hf_rpc_reqframe
,
2532 tvb
, 0, 0, rpc_call
->rep_num
,
2533 "The reply to this request is in frame %u",
2535 proto_item_set_generated(tmp_item
);
2540 offset
= dissect_rpc_cred(tvb
, rpc_tree
, offset
, pinfo
, rpc_conv_info
);
2541 offset
= dissect_rpc_verf(tvb
, rpc_tree
, offset
, msg_type
, pinfo
);
2543 /* pass rpc_info to subdissectors */
2544 rpc_call
->request
=true;
2546 /* go to the next dissector */
2548 break; /* end of RPC call */
2551 /* we know already the type from the calling routine,
2552 and we already have "rpc_call" set above. */
2553 key
.prog
= prog
= rpc_call
->prog
;
2554 key
.vers
= vers
= rpc_call
->vers
;
2555 key
.proc
= proc
= rpc_call
->proc
;
2556 flavor
= rpc_call
->flavor
;
2557 gss_proc
= rpc_call
->gss_proc
;
2558 gss_svc
= rpc_call
->gss_svc
;
2560 dissect_function
= dissector_get_custom_table_handle(subdissector_reply_table
, &key
);
2561 if (dissect_function
!= NULL
) {
2562 procname
= dissector_handle_get_description(dissect_function
);
2565 /* happens only with unknown program or version
2568 dissect_function
= data_handle
;
2569 procname
=wmem_strdup_printf(wmem_packet_scope(), "proc-%u", rpc_call
->proc
);
2573 * If this is an AUTH_GSSAPI message, then the RPC procedure
2574 * is not an application procedure, but rather an auth level
2575 * procedure, so it would be misleading to print the RPC
2576 * procname. Replace the RPC procname with the corresponding
2577 * AUTH_GSSAPI procname.
2579 if (flavor
== FLAVOR_AUTHGSSAPI_MSG
) {
2580 procname
= val_to_str_const(gss_proc
, rpc_authgssapi_proc
, "(null)");
2583 rpc_prog_key
= prog
;
2584 if ((rpc_prog
= (rpc_prog_info_value
*)g_hash_table_lookup(rpc_progs
,GUINT_TO_POINTER(rpc_prog_key
))) == NULL
) {
2586 proto_id
= proto_rpc_unknown
;
2588 progname
= "Unknown";
2591 proto
= rpc_prog
->proto
;
2592 proto_id
= rpc_prog
->proto_id
;
2593 ett
= rpc_prog
->ett
;
2594 progname
= rpc_prog
->progname
;
2596 /* Set the protocol name to the underlying
2598 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, progname
);
2601 /* Print the program version, procedure name, and message type (call or reply). */
2603 col_clear(pinfo
->cinfo
, COL_INFO
);
2605 col_append_str(pinfo
->cinfo
, COL_INFO
, " ; ");
2606 /* Special case for NFSv4 - if the type is COMPOUND, do not print the procedure name */
2607 if (vers
==4 && prog
==NFS_PROGRAM
&& !strcmp(procname
, "COMPOUND"))
2608 col_append_fstr(pinfo
->cinfo
, COL_INFO
,"V%u %s",
2609 vers
, msg_type_name
);
2611 col_append_fstr(pinfo
->cinfo
, COL_INFO
,"V%u %s %s",
2612 vers
, procname
, msg_type_name
);
2615 proto_item
*tmp_item
;
2616 tmp_item
=proto_tree_add_uint_format_value(rpc_tree
,
2617 hf_rpc_program
, tvb
, 0, 0, prog
,
2618 "%s (%u)", progname
, prog
);
2619 proto_item_set_generated(tmp_item
);
2620 tmp_item
=proto_tree_add_uint(rpc_tree
,
2621 hf_rpc_programversion
, tvb
, 0, 0, vers
);
2622 proto_item_set_generated(tmp_item
);
2623 tmp_item
=proto_tree_add_uint_format_value(rpc_tree
,
2624 hf_rpc_procedure
, tvb
, 0, 0, proc
,
2625 "%s (%u)", procname
, proc
);
2626 proto_item_set_generated(tmp_item
);
2629 reply_state
= tvb_get_ntohl(tvb
,offset
);
2630 proto_tree_add_uint(rpc_tree
, hf_rpc_state_reply
, tvb
,
2631 offset
, 4, reply_state
);
2634 /* Indicate the frame to which this is a reply. */
2635 if (rpc_call
->req_num
) {
2636 proto_item
*tmp_item
;
2638 tmp_item
=proto_tree_add_uint_format(rpc_tree
, hf_rpc_repframe
,
2639 tvb
, 0, 0, rpc_call
->req_num
,
2640 "This is a reply to a request in frame %u",
2642 proto_item_set_generated(tmp_item
);
2644 nstime_delta(&ns
, &pinfo
->abs_ts
, &rpc_call
->req_time
);
2645 tmp_item
=proto_tree_add_time(rpc_tree
, hf_rpc_time
, tvb
, offset
, 0,
2647 proto_item_set_generated(tmp_item
);
2649 col_append_fstr(pinfo
->cinfo
, COL_INFO
," (Call In %u)", rpc_call
->req_num
);
2653 if (rpc_call
->rep_num
== 0) {
2654 /* We have not yet seen a reply to that call, so
2655 this must be the first reply; remember its
2657 rpc_call
->rep_num
= pinfo
->num
;
2659 /* We have seen a reply to this call - but was it
2661 if (rpc_call
->rep_num
!= pinfo
->num
) {
2662 proto_item
*tmp_item
;
2664 /* No, so it's a duplicate reply.
2666 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
,
2667 "[RPC duplicate of #%u]", rpc_call
->rep_num
);
2668 tmp_item
=proto_tree_add_item(rpc_tree
,
2669 hf_rpc_dup
, tvb
, 0,0, ENC_NA
);
2670 proto_item_set_generated(tmp_item
);
2672 tmp_item
=proto_tree_add_uint(rpc_tree
,
2673 hf_rpc_reply_dup
, tvb
, 0,0, rpc_call
->rep_num
);
2674 proto_item_set_generated(tmp_item
);
2678 switch (reply_state
) {
2681 offset
= dissect_rpc_verf(tvb
, rpc_tree
, offset
, msg_type
, pinfo
);
2682 accept_state
= tvb_get_ntohl(tvb
,offset
);
2684 proto_tree_add_uint(rpc_tree
, hf_rpc_state_accept
, tvb
,
2685 offset
, 4, accept_state
);
2688 switch (accept_state
) {
2691 /* go to the next dissector */
2695 vers_low
= tvb_get_ntohl(tvb
,offset
);
2696 vers_high
= tvb_get_ntohl(tvb
,offset
+4);
2698 proto_tree_add_uint(rpc_tree
,
2699 hf_rpc_programversion_min
,
2700 tvb
, offset
, 4, vers_low
);
2701 proto_tree_add_uint(rpc_tree
,
2702 hf_rpc_programversion_max
,
2703 tvb
, offset
+4, 4, vers_high
);
2708 * There's no protocol reply, so don't
2709 * try to dissect it.
2711 dissect_rpc_flag
= false;
2716 * There's no protocol reply, so don't
2717 * try to dissect it.
2719 dissect_rpc_flag
= false;
2725 reject_state
= tvb_get_ntohl(tvb
,offset
);
2727 proto_tree_add_uint(rpc_tree
,
2728 hf_rpc_state_reject
, tvb
, offset
, 4,
2733 if (reject_state
==RPC_MISMATCH
) {
2734 vers_low
= tvb_get_ntohl(tvb
,offset
);
2735 vers_high
= tvb_get_ntohl(tvb
,offset
+4);
2737 proto_tree_add_uint(rpc_tree
,
2739 tvb
, offset
, 4, vers_low
);
2740 proto_tree_add_uint(rpc_tree
,
2742 tvb
, offset
+4, 4, vers_high
);
2745 } else if (reject_state
==AUTH_ERROR
) {
2746 auth_state
= tvb_get_ntohl(tvb
,offset
);
2748 proto_tree_add_uint(rpc_tree
,
2749 hf_rpc_state_auth
, tvb
, offset
, 4,
2756 * There's no protocol reply, so don't
2757 * try to dissect it.
2759 dissect_rpc_flag
= false;
2764 * This isn't a valid reply state, so we have
2765 * no clue what's going on; don't try to dissect
2766 * the protocol reply.
2768 dissect_rpc_flag
= false;
2771 break; /* end of RPC reply */
2775 * The switch statement at the top returned if
2776 * this was neither an RPC call nor a reply.
2778 DISSECTOR_ASSERT_NOT_REACHED();
2781 /* now we know, that RPC was shorter */
2784 THROW(ReportedBoundsError
);
2785 tvb_ensure_bytes_exist(tvb
, offset
, 0);
2786 proto_item_set_end(rpc_item
, tvb
, offset
);
2789 if (!dissect_rpc_flag
) {
2791 * There's no RPC call or reply here; just dissect
2792 * whatever's left as data.
2794 call_dissector(data_handle
,
2795 tvb_new_subset_remaining(tvb
, offset
), pinfo
, rpc_tree
);
2799 /* we must queue this packet to the tap system before we actually
2800 call the subdissectors since short packets (i.e. nfs read reply)
2801 will cause an exception and execution would never reach the call
2802 to tap_queue_packet() in that case
2804 tap_queue_packet(rpc_tap
, pinfo
, rpc_call
);
2807 /* If this is encrypted data we have to try to decrypt the data first before we
2809 * the reason for this is because if we can decrypt the data we must create the
2810 * item/tree for the next protocol using the decrypted tvb and not the current
2813 memset(&gssapi_encrypt
, 0, sizeof(gssapi_encrypt
));
2814 gssapi_encrypt
.decrypt_gssapi_tvb
=DECRYPT_GSSAPI_NORMAL
;
2816 if (flavor
== FLAVOR_GSSAPI
&& gss_proc
== RPCSEC_GSS_DATA
&& gss_svc
== RPCSEC_GSS_SVC_PRIVACY
) {
2817 proto_tree
*gss_tree
;
2819 gss_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_gss_wrap
, NULL
, "GSS-Wrap");
2821 offset
= dissect_rpc_authgss_priv_data(tvb
, gss_tree
, offset
, pinfo
, &gssapi_encrypt
);
2822 if (gssapi_encrypt
.gssapi_decrypted_tvb
) {
2823 proto_tree_add_item(gss_tree
, hf_rpc_authgss_seq
, gssapi_encrypt
.gssapi_decrypted_tvb
, 0, 4, ENC_BIG_ENDIAN
);
2825 /* Switcheroo to the new tvb that contains the decrypted payload */
2826 tvb
= gssapi_encrypt
.gssapi_decrypted_tvb
;
2832 /* create here the program specific sub-tree */
2833 if (tree
&& (flavor
!= FLAVOR_AUTHGSSAPI_MSG
)) {
2834 proto_item
*tmp_item
;
2836 pitem
= proto_tree_add_item(tree
, proto_id
, tvb
, offset
, tvb_reported_length_remaining(tvb
, offset
), ENC_NA
);
2837 ptree
= proto_item_add_subtree(pitem
, ett
);
2839 tmp_item
=proto_tree_add_uint(ptree
,
2840 hf_rpc_programversion
, tvb
, 0, 0, vers
);
2841 proto_item_set_generated(tmp_item
);
2842 if (rpc_prog
&& rpc_prog
->procedure_hfs
&& (rpc_prog
->procedure_hfs
->len
> vers
) )
2843 procedure_hf
= g_array_index(rpc_prog
->procedure_hfs
, int, vers
);
2846 * No such element in the GArray.
2850 if (procedure_hf
!= 0 && procedure_hf
!= -1) {
2851 tmp_item
=proto_tree_add_uint(ptree
,
2852 procedure_hf
, tvb
, 0, 0, proc
);
2853 proto_item_set_generated(tmp_item
);
2855 tmp_item
=proto_tree_add_uint_format_value(ptree
,
2856 hf_rpc_procedure
, tvb
, 0, 0, proc
,
2857 "%s (%u)", procname
, proc
);
2858 proto_item_set_generated(tmp_item
);
2862 /* proto==0 if this is an unknown program */
2863 if( (proto
==0) || !proto_is_protocol_enabled(proto
)){
2864 dissect_function
= data_handle
;
2868 * Don't call any subdissector if we have no more date to dissect.
2870 if (tvb_reported_length_remaining(tvb
, offset
) == 0) {
2875 * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
2879 case FLAVOR_UNKNOWN
:
2881 * We don't know the authentication flavor, so we can't
2882 * dissect the payload.
2884 proto_tree_add_expert_format(ptree
, pinfo
, &ei_rpc_cannot_dissect
, tvb
, offset
, -1,
2885 "Unknown authentication flavor - cannot dissect");
2888 case FLAVOR_NOT_GSSAPI
:
2890 * It's not GSS-API authentication. Just dissect the
2893 offset
= call_dissect_function(tvb
, pinfo
, ptree
, offset
,
2894 dissect_function
, progname
, rpc_call
);
2897 case FLAVOR_GSSAPI_NO_INFO
:
2899 * It's GSS-API authentication, but we don't have the
2900 * procedure and service information, so we can't dissect
2903 proto_tree_add_expert_format(ptree
, pinfo
, &ei_rpc_cannot_dissect
, tvb
, offset
, -1,
2904 "GSS-API authentication, but procedure and service unknown - cannot dissect");
2909 * It's GSS-API authentication, and we have the procedure
2910 * and service information; process the GSS-API stuff,
2911 * and process the payload if there is any.
2915 case RPCSEC_GSS_INIT
:
2916 case RPCSEC_GSS_CONTINUE_INIT
:
2917 if (msg_type
== RPC_CALL
) {
2918 offset
= dissect_rpc_authgss_initarg(tvb
,
2919 ptree
, offset
, pinfo
);
2922 offset
= dissect_rpc_authgss_initres(tvb
,
2923 ptree
, offset
, pinfo
, rpc_conv_info
);
2927 case RPCSEC_GSS_DATA
:
2928 if (gss_svc
== RPCSEC_GSS_SVC_NONE
) {
2929 offset
= call_dissect_function(tvb
,
2930 pinfo
, ptree
, offset
,
2932 progname
, rpc_call
);
2934 else if (gss_svc
== RPCSEC_GSS_SVC_INTEGRITY
) {
2935 offset
= dissect_rpc_authgss_integ_data(tvb
,
2936 pinfo
, ptree
, offset
,
2938 progname
, rpc_call
);
2940 else if (gss_svc
== RPCSEC_GSS_SVC_PRIVACY
) {
2941 if (gssapi_encrypt
.gssapi_decrypted_tvb
) {
2942 call_dissect_function(
2943 gssapi_encrypt
.gssapi_decrypted_tvb
,
2946 progname
, rpc_call
);
2947 offset
= tvb_reported_length(gssapi_encrypt
.gssapi_decrypted_tvb
);
2957 case FLAVOR_AUTHGSSAPI_MSG
:
2959 * This is an AUTH_GSSAPI message. It contains data
2960 * only for the authentication procedure and not for the
2961 * application level RPC procedure. Reset the column
2962 * protocol and info fields to indicate that this is
2963 * an RPC auth level message, then process the args.
2965 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
2966 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
2968 val_to_str(gss_proc
, rpc_authgssapi_proc
, "Unknown (%d)"),
2969 msg_type_name
, xid
);
2973 case AUTH_GSSAPI_INIT
:
2974 case AUTH_GSSAPI_CONTINUE_INIT
:
2975 case AUTH_GSSAPI_MSG
:
2976 if (msg_type
== RPC_CALL
) {
2977 offset
= dissect_rpc_authgssapi_initarg(tvb
,
2978 rpc_tree
, offset
, pinfo
);
2980 offset
= dissect_rpc_authgssapi_initres(tvb
,
2981 rpc_tree
, offset
, pinfo
);
2985 case AUTH_GSSAPI_DESTROY
:
2986 offset
= dissect_rpc_data(tvb
, rpc_tree
,
2987 hf_rpc_authgss_data
, offset
);
2990 case AUTH_GSSAPI_EXIT
:
2994 /* Adjust the length to account for the auth message. */
2996 proto_item_set_end(rpc_item
, tvb
, offset
);
3000 case FLAVOR_AUTHGSSAPI
:
3002 * An RPC with AUTH_GSSAPI authentication. The data
3003 * portion is always private, so don't call the dissector.
3005 offset
= dissect_auth_gssapi_data(tvb
, ptree
, offset
);
3009 if (tvb_reported_length_remaining(tvb
, offset
) > 0) {
3011 * dissect any remaining bytes (incomplete dissection) as pure
3015 call_dissector(data_handle
,
3016 tvb_new_subset_remaining(tvb
, offset
), pinfo
, ptree
);
3019 /* XXX this should really loop over all fhandles registered for the frame */
3020 if(nfs_fhandle_reqrep_matching
){
3023 if(rpc_call
&& rpc_call
->rep_num
){
3024 dissect_fhandle_hidden(pinfo
,
3025 ptree
, rpc_call
->rep_num
);
3029 if(rpc_call
&& rpc_call
->req_num
){
3030 dissect_fhandle_hidden(pinfo
,
3031 ptree
, rpc_call
->req_num
);
3041 dissect_rpc_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3043 return (bool)dissect_rpc_message(tvb
, pinfo
, tree
, NULL
, NULL
, RPC_UDP
, 0,
3048 dissect_rpc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
3050 if (!dissect_rpc_message(tvb
, pinfo
, tree
, NULL
, NULL
, RPC_UDP
, 0,
3052 if (tvb_reported_length(tvb
) != 0)
3053 dissect_rpc_continuation(tvb
, pinfo
, tree
);
3055 return tvb_captured_length(tvb
);
3059 /* Defragmentation of RPC-over-TCP records */
3060 /* table to hold defragmented RPC records */
3061 static reassembly_table rpc_fragment_table
;
3064 * XXX - can we eliminate this by defining our own key-handling functions
3065 * for rpc_fragment_table? (Note that those functions must look at
3066 * not only the addresses of the endpoints, but the ports of the endpoints,
3067 * so that they don't try to combine fragments from different TCP
3070 static wmem_map_t
*rpc_reassembly_table
;
3072 typedef struct _rpc_fragment_key
{
3082 rpc_fragment_hash(const void *k
)
3084 const rpc_fragment_key
*key
= (const rpc_fragment_key
*)k
;
3086 return key
->conv_id
+ key
->seq
;
3090 rpc_fragment_equal(const void *k1
, const void *k2
)
3092 const rpc_fragment_key
*key1
= (const rpc_fragment_key
*)k1
;
3093 const rpc_fragment_key
*key2
= (const rpc_fragment_key
*)k2
;
3095 return key1
->conv_id
== key2
->conv_id
&&
3096 key1
->seq
== key2
->seq
&& key1
->port
== key2
->port
;
3100 show_rpc_fragheader(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t rpc_rm
)
3102 proto_tree
*hdr_tree
;
3106 fraglen
= rpc_rm
& RPC_RM_FRAGLEN
;
3108 hdr_tree
= proto_tree_add_subtree_format(tree
, tvb
, 0, 4,
3109 ett_rpc_fraghdr
, NULL
, "Fragment header: %s%u %s",
3110 (rpc_rm
& RPC_RM_LASTFRAG
) ? "Last fragment, " : "",
3111 fraglen
, plurality(fraglen
, "byte", "bytes"));
3113 proto_tree_add_boolean(hdr_tree
, hf_rpc_lastfrag
, tvb
, 0, 4,
3115 proto_tree_add_uint(hdr_tree
, hf_rpc_fraglen
, tvb
, 0, 4,
3121 show_rpc_fragment(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t rpc_rm
)
3125 * Show the fragment header and the data for the fragment.
3127 show_rpc_fragheader(tvb
, tree
, rpc_rm
);
3128 proto_tree_add_item(tree
, hf_rpc_fragment_data
, tvb
, 4, -1, ENC_NA
);
3133 make_frag_tree(tvbuff_t
*tvb
, proto_tree
*tree
, int proto
, int ett
,
3136 proto_item
*frag_item
;
3137 proto_tree
*frag_tree
;
3140 return; /* nothing to do */
3142 frag_item
= proto_tree_add_protocol_format(tree
, proto
, tvb
, 0, -1,
3143 "%s Fragment", proto_get_protocol_name(proto
));
3144 frag_tree
= proto_item_add_subtree(frag_item
, ett
);
3145 show_rpc_fragment(tvb
, frag_tree
, rpc_rm
);
3149 show_rpc_fraginfo(tvbuff_t
*tvb
, tvbuff_t
*frag_tvb
, proto_tree
*tree
,
3150 uint32_t rpc_rm
, fragment_head
*ipfd_head
, packet_info
*pinfo
)
3152 proto_item
*frag_tree_item
;
3155 return; /* don't do any work */
3157 if (tvb
!= frag_tvb
) {
3159 * This message was not all in one fragment,
3160 * so show the fragment header *and* the data
3161 * for the fragment (which is the last fragment),
3162 * and a tree with information about all fragments.
3164 show_rpc_fragment(frag_tvb
, tree
, rpc_rm
);
3167 * Show a tree with information about all fragments.
3169 show_fragment_tree(ipfd_head
, &rpc_frag_items
, tree
, pinfo
, tvb
, &frag_tree_item
);
3172 * This message was all in one fragment, so just show
3173 * the fragment header.
3175 show_rpc_fragheader(tvb
, tree
, rpc_rm
);
3180 call_message_dissector(tvbuff_t
*tvb
, tvbuff_t
*rec_tvb
, packet_info
*pinfo
,
3181 proto_tree
*tree
, tvbuff_t
*frag_tvb
, rec_dissector_t dissector
,
3182 fragment_head
*ipfd_head
, int tp_type
, uint32_t rpc_rm
,
3183 bool first_pdu
, bool can_defragment
)
3185 const char *saved_proto
;
3186 volatile bool rpc_succeeded
;
3188 saved_proto
= pinfo
->current_proto
;
3189 rpc_succeeded
= false;
3191 rpc_succeeded
= (*dissector
)(rec_tvb
, pinfo
, tree
,
3192 frag_tvb
, ipfd_head
, tp_type
, rpc_rm
, first_pdu
,
3195 CATCH_NONFATAL_ERRORS
{
3197 * Somebody threw an exception that means that there
3198 * was a problem dissecting the payload; that means
3199 * that a dissector was found, so we don't need to
3200 * dissect the payload as data or update the protocol
3203 * Just show the exception and then continue dissecting.
3205 show_exception(tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
3206 pinfo
->current_proto
= saved_proto
;
3209 * We treat this as a "successful" dissection of
3210 * an RPC packet, as "dissect_rpc_message()"
3211 * *did* decide it was an RPC packet, throwing
3212 * an exception while dissecting it as such.
3214 rpc_succeeded
= true;
3217 return rpc_succeeded
;
3221 dissect_rpc_fragment(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
,
3222 rec_dissector_t dissector
, bool is_heur
, int proto
, int ett
,
3223 bool first_pdu
, struct tcpinfo
*tcpinfo
, struct tlsinfo
*tlsinfo
)
3229 int tvb_len
, tvb_reported_len
;
3231 conversation_t
*conversation
= NULL
;
3233 bool save_fragmented
;
3234 bool can_defragment
;
3235 rpc_fragment_key old_rfk
, *rfk
, *new_rfk
;
3236 fragment_head
*ipfd_head
;
3239 if (pinfo
== NULL
|| (tcpinfo
== NULL
&& tlsinfo
== NULL
)) {
3243 seq
= (tcpinfo
!= NULL
? tcpinfo
->seq
: tlsinfo
->seq
) + offset
;
3244 tp_type
= (tcpinfo
!= NULL
? RPC_TCP
: RPC_TLS
);
3247 * Get the record mark.
3249 if (!tvb_bytes_exist(tvb
, offset
, 4)) {
3251 * XXX - we should somehow arrange to handle
3252 * a record mark split across TCP segments.
3254 return 0; /* not enough to tell if it's valid */
3256 rpc_rm
= tvb_get_ntohl(tvb
, offset
);
3258 len
= rpc_rm
& RPC_RM_FRAGLEN
;
3261 * Do TCP desegmentation, if enabled.
3263 * reject fragments bigger than this preference setting.
3264 * This is arbitrary, but should at least prevent
3265 * some crashes from either packets with really
3266 * large RPC-over-TCP fragments or from stuff that's
3267 * not really valid for this protocol.
3269 if (len
> max_rpc_tcp_pdu_size
)
3270 return 0; /* pretend it's not valid */
3272 can_defragment
= rpc_defragment
;
3273 len
+= 4; /* include record mark */
3274 tvb_reported_len
= tvb_reported_length_remaining(tvb
, offset
);
3276 if ((int)len
> tvb_reported_len
) {
3277 /* This frame doesn't have all the data for this message.
3279 * If this is a heuristic dissector, check whether it looks
3280 * like the beginning of an RPC call or reply.
3285 if (!tvb_bytes_exist(tvb
, offset
+ 4, 8)) {
3287 * Captured data in packet isn't
3288 * enough to let us tell.
3293 /* both directions need at least this */
3294 msg_type
= tvb_get_ntohl(tvb
, offset
+ 4 + 4);
3299 /* Check for RPC call. */
3300 if (looks_like_rpc_call(tvb
,
3301 offset
+ 4) == NULL
) {
3302 /* Doesn't look like a call. */
3308 /* Check for RPC reply. */
3309 if (looks_like_rpc_reply(tvb
, pinfo
,
3310 offset
+ 4) == NULL
) {
3311 /* Doesn't look like a reply. */
3317 /* The putative message type field
3318 contains neither RPC_CALL nor
3319 RPC_REPLY, so it's not an RPC
3324 /* Get this conversation, creating it if
3325 it doesn't already exist, and make the
3326 dissector for it the non-heuristic RPC
3327 dissector for RPC-over-TCP. */
3328 conversation
= find_or_create_conversation(pinfo
);
3329 if (tcpinfo
!= NULL
) {
3330 conversation_set_dissector(conversation
, rpc_tcp_handle
);
3334 /* OK, we think it is RPC. Can we desegment? */
3335 if (rpc_desegment
&& pinfo
->can_desegment
) {
3336 /* Yes, so tell the TCP dissector how much
3337 * more data we need. */
3339 pinfo
->desegment_offset
= offset
;
3340 pinfo
->desegment_len
= len
- tvb_reported_len
;
3341 return -((int32_t) pinfo
->desegment_len
);
3344 expert_add_info(pinfo
, NULL
, &ei_rpc_segment_needed
);
3345 can_defragment
= false;
3347 } else if (tvb_reported_len
> (int)len
) {
3348 tvb_reported_len
= len
;
3351 tvb_len
= tvb_captured_length_remaining(tvb
, offset
);
3352 if (tvb_len
< (int)len
) {
3353 /* We don't have all the data for this fragment. */
3354 can_defragment
= false;
3355 }if (tvb_len
> (int)len
) {
3359 frag_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, tvb_len
,
3363 * If we're not defragmenting, just hand this to the
3366 * We defragment only if we should (rpc_defragment true) *and* we
3367 * can (tvb_len <= len, so that we have all the data in the fragment).
3369 if (!can_defragment
) {
3371 * We can't defragment. Hand the dissector the tvbuff for the
3372 * fragment as the tvbuff for the record.
3378 * Mark this as fragmented, so if somebody throws an
3379 * exception, we don't report it as a malformed frame.
3381 save_fragmented
= pinfo
->fragmented
;
3382 pinfo
->fragmented
= true;
3383 rpc_succeeded
= call_message_dissector(tvb
, rec_tvb
, pinfo
,
3384 tree
, frag_tvb
, dissector
, ipfd_head
, tp_type
, rpc_rm
,
3385 first_pdu
, can_defragment
);
3386 pinfo
->fragmented
= save_fragmented
;
3388 return 0; /* not RPC */
3393 * First, we check to see if this fragment is part of a record
3394 * that we're in the process of defragmenting.
3396 * The key is the conversation ID for the conversation to which
3397 * the packet belongs and the current sequence number.
3399 * We must first find the conversation and, if we don't find
3402 conversation
= find_or_create_conversation(pinfo
);
3403 old_rfk
.conv_id
= conversation
->conv_index
;
3405 old_rfk
.port
= pinfo
->srcport
;
3406 rfk
= (rpc_fragment_key
*)wmem_map_lookup(rpc_reassembly_table
, &old_rfk
);
3410 * This fragment was not found in our table, so it doesn't
3411 * contain a continuation of a higher-level PDU.
3412 * Is it the last fragment?
3414 if (!(rpc_rm
& RPC_RM_LASTFRAG
)) {
3416 * This isn't the last fragment, so we don't
3417 * have the complete record.
3419 * It's the first fragment we've seen, so if
3420 * it's truly the first fragment of the record,
3421 * and it has enough data, the dissector can at
3422 * least check whether it looks like a valid
3423 * message, as it contains the start of the
3426 * The dissector should not dissect anything
3427 * if the "last fragment" flag isn't set in
3428 * the record marker, so it shouldn't throw
3431 if (!(*dissector
)(frag_tvb
, pinfo
, tree
, frag_tvb
,
3432 NULL
, tp_type
, rpc_rm
, first_pdu
, can_defragment
))
3433 return 0; /* not valid */
3436 * OK, now start defragmentation with that
3437 * fragment. Add this fragment, and set up
3438 * next packet/sequence number as well.
3440 * We must remember this fragment.
3443 rfk
= wmem_new(wmem_file_scope(), rpc_fragment_key
);
3444 rfk
->conv_id
= conversation
->conv_index
;
3446 rfk
->port
= pinfo
->srcport
;
3448 rfk
->start_seq
= seq
;
3449 wmem_map_insert(rpc_reassembly_table
, rfk
, rfk
);
3452 * Start defragmentation.
3454 ipfd_head
= fragment_add_multiple_ok(&rpc_fragment_table
,
3456 pinfo
, rfk
->start_seq
, NULL
,
3457 rfk
->offset
, len
- 4, true);
3460 * Make sure that defragmentation isn't complete;
3461 * it shouldn't be, as this is the first fragment
3462 * we've seen, and the "last fragment" bit wasn't
3465 if (ipfd_head
== NULL
) {
3466 new_rfk
= wmem_new(wmem_file_scope(), rpc_fragment_key
);
3467 new_rfk
->conv_id
= rfk
->conv_id
;
3468 new_rfk
->seq
= seq
+ len
;
3469 new_rfk
->port
= pinfo
->srcport
;
3470 new_rfk
->offset
= rfk
->offset
+ len
- 4;
3471 new_rfk
->start_seq
= rfk
->start_seq
;
3472 wmem_map_insert(rpc_reassembly_table
, new_rfk
,
3476 * This is part of a fragmented record,
3477 * but it's not the first part.
3478 * Show it as a record marker plus data, under
3479 * a top-level tree for this protocol.
3481 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
3482 col_set_str(pinfo
->cinfo
, COL_INFO
, "Fragment");
3483 make_frag_tree(frag_tvb
, tree
, proto
, ett
,rpc_rm
);
3486 * No more processing need be done, as we don't
3487 * have a complete record.
3491 /* oddly, we have a first fragment, not marked as last,
3492 * but which the defragmenter thinks is complete.
3493 * So rather than creating a fragment reassembly tree,
3494 * we simply throw away the partial fragment structure
3495 * and fall though to our "sole fragment" processing below.
3501 * This is the first fragment we've seen, and it's also
3502 * the last fragment; that means the record wasn't
3503 * fragmented. Hand the dissector the tvbuff for the
3504 * fragment as the tvbuff for the record.
3510 * OK, this fragment was found, which means it continues
3511 * a record. This means we must defragment it.
3512 * Add it to the defragmentation lists.
3514 ipfd_head
= fragment_add_multiple_ok(&rpc_fragment_table
,
3515 tvb
, offset
+ 4, pinfo
, rfk
->start_seq
, NULL
,
3516 rfk
->offset
, len
- 4, !(rpc_rm
& RPC_RM_LASTFRAG
));
3518 if (ipfd_head
== NULL
) {
3520 * fragment_add_multiple_ok() returned NULL.
3521 * This means that defragmentation is not
3524 * We must add an entry to the hash table with
3525 * the sequence number following this fragment
3526 * as the starting sequence number, so that when
3527 * we see that fragment we'll find that entry.
3529 * XXX - as TCP stream data is not currently
3530 * guaranteed to be provided in order to dissectors,
3531 * RPC fragments aren't guaranteed to be provided
3534 new_rfk
= wmem_new(wmem_file_scope(), rpc_fragment_key
);
3535 new_rfk
->conv_id
= rfk
->conv_id
;
3536 new_rfk
->seq
= seq
+ len
;
3537 new_rfk
->port
= pinfo
->srcport
;
3538 new_rfk
->offset
= rfk
->offset
+ len
- 4;
3539 new_rfk
->start_seq
= rfk
->start_seq
;
3540 wmem_map_insert(rpc_reassembly_table
, new_rfk
,
3544 * This is part of a fragmented record,
3545 * but it's not the first part.
3546 * Show it as a record marker plus data, under
3547 * a top-level tree for this protocol,
3548 * but don't hand it to the dissector
3550 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
3551 col_set_str(pinfo
->cinfo
, COL_INFO
, "Fragment");
3552 make_frag_tree(frag_tvb
, tree
, proto
, ett
, rpc_rm
);
3555 * No more processing need be done, as we don't
3556 * have a complete record.
3562 * It's completely defragmented.
3564 * We only call subdissector for the last fragment.
3565 * XXX - this assumes in-order delivery of RPC
3566 * fragments, which requires in-order delivery of TCP
3569 if (!(rpc_rm
& RPC_RM_LASTFRAG
)) {
3571 * Well, it's defragmented, but this isn't
3572 * the last fragment; this probably means
3573 * this isn't the first pass, so we don't
3574 * need to start defragmentation.
3576 * This is part of a fragmented record,
3577 * but it's not the first part.
3578 * Show it as a record marker plus data, under
3579 * a top-level tree for this protocol,
3580 * but don't show it to the dissector.
3582 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RPC");
3583 col_set_str(pinfo
->cinfo
, COL_INFO
, "Fragment");
3584 make_frag_tree(frag_tvb
, tree
, proto
, ett
, rpc_rm
);
3587 * No more processing need be done, as we
3588 * only disssect the data with the last
3595 * OK, this is the last segment.
3596 * Create a tvbuff for the defragmented
3601 * Create a new TVB structure for
3602 * defragmented data.
3604 rec_tvb
= tvb_new_chain(tvb
, ipfd_head
->tvb_data
);
3607 * Add defragmented data to the data source list.
3609 add_new_data_source(pinfo
, rec_tvb
, "Defragmented");
3613 * We have something to hand to the RPC message
3616 if (!call_message_dissector(tvb
, rec_tvb
, pinfo
, tree
,
3617 frag_tvb
, dissector
, ipfd_head
, tp_type
, rpc_rm
,
3618 first_pdu
, can_defragment
))
3619 return 0; /* not RPC */
3621 } /* end of dissect_rpc_fragment() */
3624 * Scans tvb, starting at given offset, to see if we can find
3625 * what looks like a valid RPC-over-TCP reply header.
3627 * @param tvb Buffer to inspect for RPC reply header.
3628 * @param offset Offset to begin search of tvb at.
3630 * @return -1 if no reply header found, else offset to start of header
3631 * (i.e., to the RPC record mark field).
3635 find_rpc_over_tcp_reply_start(tvbuff_t
*tvb
, int offset
)
3639 * Looking for partial header sequence. From beginning of
3640 * stream-style header, including "record mark", full ONC-RPC
3642 * BE int32 record mark (rfc 1831 sec. 10)
3643 * ? int32 XID (rfc 1831 sec. 8)
3644 * BE int32 msg_type (ibid sec. 8, call = 0, reply = 1)
3646 * -------------------------------------------------------------
3647 * Then reply-specific fields are
3648 * BE int32 reply_stat (ibid, accept = 0, deny = 1)
3650 * Then, assuming accepted,
3652 * BE int32 auth_flavor (ibid, none = 0)
3653 * BE int32 ? auth_len (ibid, none = 0)
3655 * BE int32 accept_stat (ibid, success = 0, errs are 1..5 in rpc v2)
3657 * -------------------------------------------------------------
3658 * Or, call-specific fields are
3659 * BE int32 rpc_vers (rfc 1831 sec 8, always == 2)
3660 * BE int32 prog (NFS == 000186A3)
3661 * BE int32 prog_ver (NFS v2/3 == 2 or 3)
3662 * BE int32 proc_id (NFS, <= 256 ???)
3667 /* Initially, we search only for something matching the template
3668 * of a successful reply with no auth verifier.
3669 * Our first qualification test is search for a string of zero bytes,
3670 * corresponding the four uint32_t values
3676 * If this string of zeros matches, then we go back and check the
3677 * preceding msg_type and record_mark fields.
3680 const int cbZeroTail
= 4 * 4; /* four uint32_t of zeros */
3681 const int ibPatternStart
= 3 * 4; /* offset of zero fill from reply start */
3682 const uint8_t * pbWholeBuf
; /* all of tvb, from offset onwards */
3683 const int NoMatch
= -1;
3685 int ibSearchStart
; /* offset of search start, in case of false hits. */
3687 const uint8_t * pbBuf
;
3689 int cbInBuf
; /* bytes in tvb, from offset onwards */
3697 cbInBuf
= tvb_reported_length_remaining(tvb
, offset
);
3699 /* start search at first possible location */
3700 ibSearchStart
= ibPatternStart
;
3702 if (cbInBuf
< (cbZeroTail
+ ibSearchStart
)) {
3703 /* nothing to search, so claim no RPC */
3707 pbWholeBuf
= tvb_get_ptr(tvb
, offset
, cbInBuf
);
3708 if (pbWholeBuf
== NULL
) {
3709 /* probably never take this, as get_ptr seems to assert */
3713 while ((cbInBuf
- ibSearchStart
) > cbZeroTail
) {
3714 /* First test for long tail of zeros, starting at the back.
3715 * A failure lets us skip the maximum possible buffer amount.
3717 pbBuf
= pbWholeBuf
+ ibSearchStart
+ cbZeroTail
- 1;
3718 for (i
= cbZeroTail
; i
> 0; i
--)
3722 /* match failure. Since we need N contiguous zeros,
3723 * we can increment next match start so zero testing
3724 * begins right after this failure spot.
3734 if (pbBuf
== NULL
) {
3738 /* got a match in zero-fill region, verify reply ID and
3739 * record mark fields */
3740 ulMsgType
= pntoh32 (pbWholeBuf
+ ibSearchStart
- 4);
3741 ulRecMark
= pntoh32 (pbWholeBuf
+ ibSearchStart
- ibPatternStart
);
3743 if ((ulMsgType
== RPC_REPLY
) &&
3744 ((ulRecMark
& ~0x80000000) <= (unsigned) max_rpc_tcp_pdu_size
)) {
3745 /* looks ok, try dissect */
3746 return (offset
+ ibSearchStart
- ibPatternStart
);
3749 /* no match yet, nor egregious miss either. Inch along to next try */
3755 } /* end of find_rpc_over_tcp_reply_start() */
3758 * Scans tvb for what looks like a valid RPC call / reply header.
3759 * If found, calls standard dissect_rpc_fragment() logic to digest
3760 * the (hopefully valid) fragment.
3762 * With any luck, one invocation of this will be sufficient to get
3763 * us back in alignment with the stream, and no further calls to
3764 * this routine will be needed for a given conversation. As if. :-)
3767 * Same as dissect_rpc_fragment(). Will return zero (no frame)
3768 * if no valid RPC header is found.
3772 find_and_dissect_rpc_fragment(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
3773 proto_tree
*tree
, rec_dissector_t dissector
,
3774 bool is_heur
, int proto
, int ett
,
3775 struct tcpinfo
*tcpinfo
, struct tlsinfo
*tlsinfo
)
3781 offReply
= find_rpc_over_tcp_reply_start(tvb
, offset
);
3783 /* could search for request, but not needed (or testable) thus far */
3784 return 0; /* claim no RPC */
3787 len
= dissect_rpc_fragment(tvb
, offReply
,
3789 dissector
, is_heur
, proto
, ett
,
3790 true /* force first-pdu state */, tcpinfo
, tlsinfo
);
3792 /* misses are reported as-is */
3798 /* returning a non-zero length, correct it to reflect the extra offset
3799 * we found necessary
3802 len
+= offReply
- offset
;
3805 /* negative length seems to only be used as a flag,
3806 * don't mess it up until found necessary
3808 /* len -= offReply - offset; */
3813 } /* end of find_and_dissect_rpc_fragment */
3817 * Returns true if it looks like ONC RPC, false otherwise.
3820 dissect_rpc_tcp_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
3821 bool is_heur
, struct tcpinfo
*tcpinfo
, struct tlsinfo
*tlsinfo
)
3824 bool saw_rpc
= false;
3825 bool first_pdu
= true;
3828 while (tvb_reported_length_remaining(tvb
, offset
) != 0) {
3830 * Process this fragment.
3832 len
= dissect_rpc_fragment(tvb
, offset
, pinfo
, tree
,
3833 dissect_rpc_message
, is_heur
, proto_rpc
, ett_rpc
,
3834 first_pdu
, tcpinfo
, tlsinfo
);
3836 if ((len
== 0) && first_pdu
&& rpc_find_fragment_start
) {
3838 * Try discarding some leading bytes from tvb, on assumption
3839 * that we are looking at the middle of a stream-based transfer
3841 len
= find_and_dissect_rpc_fragment(tvb
, offset
, pinfo
, tree
,
3842 dissect_rpc_message
, is_heur
, proto_rpc
, ett_rpc
,
3849 * dissect_rpc_fragment() thinks this is ONC RPC,
3850 * but we need more data from the TCP stream for
3857 * It's not RPC. Stop processing.
3862 /* Set fence so whatever the subdissector put in the
3863 * Info column stays there.
3865 * This is useful when some ONC RPC protocol is
3866 * carrying another protocol that can also run atop
3867 * other protocols, so that the other protocol's
3868 * dissector has to clear the Info column to add
3869 * its own material, and there are multiple PDUs
3870 * in one frame. If the fence isn't set, the Info
3871 * column will only reflect the information from
3872 * the first PDU in the frame.
3874 col_set_fence(pinfo
->cinfo
, COL_INFO
);
3877 If the length indicates that the PDU continues beyond
3878 the end of this tvb, then tell TCP about it so that it
3879 knows where the next PDU starts.
3880 This is to help TCP detect when PDUs are not aligned to
3881 segment boundaries and allow it to find RPC headers
3882 that starts in the middle of a TCP segment.
3884 if(!pinfo
->fd
->visited
){
3885 if(len
>tvb_reported_length_remaining(tvb
, offset
)){
3886 pinfo
->want_pdu_tracking
=2;
3887 pinfo
->bytes_until_next_pdu
=len
-tvb_reported_length_remaining(tvb
, offset
);
3897 dissect_rpc_tcp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
3899 struct tcpinfo
* tcpinfo
= (struct tcpinfo
*)data
;
3901 return (bool)dissect_rpc_tcp_common(tvb
, pinfo
, tree
, true, tcpinfo
, NULL
);
3905 dissect_rpc_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
3907 struct tcpinfo
* tcpinfo
= (struct tcpinfo
*)data
;
3909 if (!dissect_rpc_tcp_common(tvb
, pinfo
, tree
, false, tcpinfo
, NULL
))
3910 dissect_rpc_continuation(tvb
, pinfo
, tree
);
3912 return tvb_reported_length(tvb
);
3916 dissect_rpc_tls_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
3918 struct tlsinfo
*tlsinfo
= (struct tlsinfo
*)data
;
3920 if (dissect_rpc_tcp_common(tvb
, pinfo
, tree
, true, NULL
, tlsinfo
)) {
3921 if (tlsinfo
!= NULL
) {
3922 *(tlsinfo
->app_handle
) = rpc_tls_handle
;
3930 dissect_rpc_tls(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
3932 struct tlsinfo
* tlsinfo
= (struct tlsinfo
*)data
;
3934 col_set_writable(pinfo
->cinfo
, COL_PROTOCOL
, true);
3935 if (dissect_rpc_tcp_common(tvb
, pinfo
, tree
, false, NULL
, tlsinfo
)) {
3936 col_set_writable(pinfo
->cinfo
, COL_PROTOCOL
, false);
3937 col_set_writable(pinfo
->cinfo
, COL_INFO
, false);
3939 dissect_rpc_continuation(tvb
, pinfo
, tree
);
3942 return tvb_reported_length(tvb
);
3945 /* Tap statistics */
3948 PROGRAM_NAME_COLUMN
,
3955 } rpc_prog_stat_columns
;
3957 static stat_tap_table_item rpc_prog_stat_fields
[] = {
3958 {TABLE_ITEM_STRING
, TAP_ALIGN_LEFT
, "Program", "%-25s"},
3959 {TABLE_ITEM_UINT
, TAP_ALIGN_RIGHT
, "Program Num", "%u"},
3960 {TABLE_ITEM_UINT
, TAP_ALIGN_RIGHT
, "Version", "%u"},
3961 {TABLE_ITEM_UINT
, TAP_ALIGN_RIGHT
, "Calls", "%u"},
3962 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Min SRT (s)", "%.2f"},
3963 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Max SRT (s)", "%.2f"},
3964 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Avg SRT (s)", "%.2f"}
3967 static void rpc_prog_stat_init(stat_tap_table_ui
* new_stat
)
3969 const char *table_name
= "ONC-RPC Program Statistics";
3970 int num_fields
= array_length(rpc_prog_stat_fields
);
3971 stat_tap_table
*table
;
3973 table
= stat_tap_find_table(new_stat
, table_name
);
3975 if (new_stat
->stat_tap_reset_table_cb
) {
3976 new_stat
->stat_tap_reset_table_cb(table
);
3981 table
= stat_tap_init_table(table_name
, num_fields
, 0, NULL
);
3982 stat_tap_add_table(new_stat
, table
);
3985 static tap_packet_status
3986 rpc_prog_stat_packet(void *tapdata
, packet_info
*pinfo _U_
, epan_dissect_t
*edt _U_
, const void *rciv_ptr
, tap_flags_t flags _U_
)
3988 stat_data_t
* stat_data
= (stat_data_t
*)tapdata
;
3989 const rpc_call_info_value
*ri
= (const rpc_call_info_value
*)rciv_ptr
;
3990 int num_fields
= array_length(rpc_prog_stat_fields
);
3992 double delta_s
= 0.0;
3993 unsigned call_count
;
3996 stat_tap_table
* table
;
3997 stat_tap_table_item_type
* item_data
;
3999 table
= g_array_index(stat_data
->stat_tap_data
->tables
, stat_tap_table
*, 0);
4001 for (element
= 0; element
< table
->num_elements
; element
++)
4003 stat_tap_table_item_type
*program_data
, *version_data
;
4004 program_data
= stat_tap_get_field_data(table
, element
, PROGRAM_NUM_COLUMN
);
4005 version_data
= stat_tap_get_field_data(table
, element
, VERSION_COLUMN
);
4007 if ((ri
->prog
== program_data
->value
.uint_value
) && (ri
->vers
== version_data
->value
.uint_value
)) {
4015 stat_tap_table_item_type items
[array_length(rpc_prog_stat_fields
)];
4016 memset(items
, 0, sizeof(items
));
4018 items
[PROGRAM_NAME_COLUMN
].type
= TABLE_ITEM_STRING
;
4019 items
[PROGRAM_NAME_COLUMN
].value
.string_value
= g_strdup(rpc_prog_name(ri
->prog
));
4020 items
[PROGRAM_NUM_COLUMN
].type
= TABLE_ITEM_UINT
;
4021 items
[PROGRAM_NUM_COLUMN
].value
.uint_value
= ri
->prog
;
4022 items
[VERSION_COLUMN
].type
= TABLE_ITEM_UINT
;
4023 items
[VERSION_COLUMN
].value
.uint_value
= ri
->vers
;
4024 items
[CALLS_COLUMN
].type
= TABLE_ITEM_UINT
;
4025 items
[MIN_SRT_COLUMN
].type
= TABLE_ITEM_FLOAT
;
4026 items
[MAX_SRT_COLUMN
].type
= TABLE_ITEM_FLOAT
;
4027 items
[AVG_SRT_COLUMN
].type
= TABLE_ITEM_FLOAT
;
4029 stat_tap_init_table_row(table
, element
, num_fields
, items
);
4032 /* we are only interested in reply packets */
4034 return TAP_PACKET_DONT_REDRAW
;
4037 item_data
= stat_tap_get_field_data(table
, element
, CALLS_COLUMN
);
4038 item_data
->value
.uint_value
++;
4039 call_count
= item_data
->value
.uint_value
;
4040 stat_tap_set_field_data(table
, element
, CALLS_COLUMN
, item_data
);
4042 /* calculate time delta between request and reply */
4043 nstime_delta(&delta
, &pinfo
->abs_ts
, &ri
->req_time
);
4044 delta_s
= nstime_to_sec(&delta
);
4046 item_data
= stat_tap_get_field_data(table
, element
, MIN_SRT_COLUMN
);
4047 if (item_data
->value
.float_value
== 0.0 || delta_s
< item_data
->value
.float_value
) {
4048 item_data
->value
.float_value
= delta_s
;
4049 stat_tap_set_field_data(table
, element
, MIN_SRT_COLUMN
, item_data
);
4052 item_data
= stat_tap_get_field_data(table
, element
, MAX_SRT_COLUMN
);
4053 if (item_data
->value
.float_value
== 0.0 || delta_s
> item_data
->value
.float_value
) {
4054 item_data
->value
.float_value
= delta_s
;
4055 stat_tap_set_field_data(table
, element
, MAX_SRT_COLUMN
, item_data
);
4058 item_data
= stat_tap_get_field_data(table
, element
, AVG_SRT_COLUMN
);
4059 item_data
->user_data
.float_value
+= delta_s
;
4060 item_data
->value
.float_value
= item_data
->user_data
.float_value
/ call_count
;
4061 stat_tap_set_field_data(table
, element
, AVG_SRT_COLUMN
, item_data
);
4063 return TAP_PACKET_REDRAW
;
4067 rpc_prog_stat_reset(stat_tap_table
* table
)
4070 stat_tap_table_item_type
* item_data
;
4072 for (element
= 0; element
< table
->num_elements
; element
++)
4074 item_data
= stat_tap_get_field_data(table
, element
, CALLS_COLUMN
);
4075 item_data
->value
.uint_value
= 0;
4076 stat_tap_set_field_data(table
, element
, CALLS_COLUMN
, item_data
);
4077 item_data
= stat_tap_get_field_data(table
, element
, MIN_SRT_COLUMN
);
4078 item_data
->value
.float_value
= 0.0;
4079 stat_tap_set_field_data(table
, element
, MIN_SRT_COLUMN
, item_data
);
4080 item_data
= stat_tap_get_field_data(table
, element
, MAX_SRT_COLUMN
);
4081 item_data
->value
.float_value
= 0.0;
4082 stat_tap_set_field_data(table
, element
, MAX_SRT_COLUMN
, item_data
);
4083 item_data
= stat_tap_get_field_data(table
, element
, AVG_SRT_COLUMN
);
4084 item_data
->value
.float_value
= 0.0;
4085 stat_tap_set_field_data(table
, element
, AVG_SRT_COLUMN
, item_data
);
4090 rpc_prog_stat_free_table_item(stat_tap_table
* table _U_
, unsigned row _U_
, unsigned column
, stat_tap_table_item_type
* field_data
)
4092 if (column
!= PROGRAM_NAME_COLUMN
) return;
4093 g_free((char*)field_data
->value
.string_value
);
4099 g_hash_table_destroy(rpc_progs
);
4102 /* will be called once from register.c at startup time */
4104 proto_register_rpc(void)
4106 static hf_register_info hf
[] = {
4107 { &hf_rpc_reqframe
, {
4108 "Request Frame", "rpc.reqframe", FT_FRAMENUM
, BASE_NONE
,
4109 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0, NULL
, HFILL
}},
4110 { &hf_rpc_repframe
, {
4111 "Reply Frame", "rpc.repframe", FT_FRAMENUM
, BASE_NONE
,
4112 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0, NULL
, HFILL
}},
4113 { &hf_rpc_lastfrag
, {
4114 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN
, 32,
4115 TFS(&tfs_yes_no
), RPC_RM_LASTFRAG
, NULL
, HFILL
}},
4116 { &hf_rpc_fraglen
, {
4117 "Fragment Length", "rpc.fraglen", FT_UINT32
, BASE_DEC
,
4118 NULL
, RPC_RM_FRAGLEN
, NULL
, HFILL
}},
4120 "XID", "rpc.xid", FT_UINT32
, BASE_HEX_DEC
,
4121 NULL
, 0, "Transaction identifier", HFILL
}},
4122 { &hf_rpc_msgtype
, {
4123 "Message Type", "rpc.msgtyp", FT_UINT32
, BASE_DEC
,
4124 VALS(rpc_msg_type
), 0, NULL
, HFILL
}},
4125 { &hf_rpc_state_reply
, {
4126 "Reply State", "rpc.replystat", FT_UINT32
, BASE_DEC
,
4127 VALS(rpc_reply_state
), 0, NULL
, HFILL
}},
4128 { &hf_rpc_state_accept
, {
4129 "Accept State", "rpc.state_accept", FT_UINT32
, BASE_DEC
,
4130 VALS(rpc_accept_state
), 0, NULL
, HFILL
}},
4131 { &hf_rpc_state_reject
, {
4132 "Reject State", "rpc.state_reject", FT_UINT32
, BASE_DEC
,
4133 VALS(rpc_reject_state
), 0, NULL
, HFILL
}},
4134 { &hf_rpc_state_auth
, {
4135 "Auth State", "rpc.state_auth", FT_UINT32
, BASE_DEC
,
4136 VALS(rpc_auth_state
), 0, NULL
, HFILL
}},
4137 { &hf_rpc_version
, {
4138 "RPC Version", "rpc.version", FT_UINT32
, BASE_DEC
,
4139 NULL
, 0, NULL
, HFILL
}},
4140 { &hf_rpc_version_min
, {
4141 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32
,
4142 BASE_DEC
, NULL
, 0, "Program Version (Minimum)", HFILL
}},
4143 { &hf_rpc_version_max
, {
4144 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32
,
4145 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4146 { &hf_rpc_program
, {
4147 "Program", "rpc.program", FT_UINT32
, BASE_DEC
,
4148 NULL
, 0, NULL
, HFILL
}},
4149 { &hf_rpc_programversion
, {
4150 "Program Version", "rpc.programversion", FT_UINT32
,
4151 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4152 { &hf_rpc_programversion_min
, {
4153 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32
,
4154 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4155 { &hf_rpc_programversion_max
, {
4156 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32
,
4157 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4158 { &hf_rpc_procedure
, {
4159 "Procedure", "rpc.procedure", FT_UINT32
, BASE_DEC
,
4160 NULL
, 0, NULL
, HFILL
}},
4161 { &hf_rpc_auth_flavor
, {
4162 "Flavor", "rpc.auth.flavor", FT_UINT32
, BASE_DEC
,
4163 VALS(rpc_auth_flavor
), 0, NULL
, HFILL
}},
4164 { &hf_rpc_auth_length
, {
4165 "Length", "rpc.auth.length", FT_UINT32
, BASE_DEC
,
4166 NULL
, 0, NULL
, HFILL
}},
4167 { &hf_rpc_auth_stamp
, {
4168 "Stamp", "rpc.auth.stamp", FT_UINT32
, BASE_HEX
,
4169 NULL
, 0, NULL
, HFILL
}},
4170 { &hf_rpc_auth_lk_owner
, {
4171 "Lock Owner", "rpc.auth.lk_owner", FT_BYTES
, BASE_NONE
,
4172 NULL
, 0, NULL
, HFILL
}},
4173 { &hf_rpc_auth_pid
, {
4174 "PID", "rpc.auth.pid", FT_UINT32
, BASE_DEC
,
4175 NULL
, 0, NULL
, HFILL
}},
4176 { &hf_rpc_auth_uid
, {
4177 "UID", "rpc.auth.uid", FT_UINT32
, BASE_DEC
,
4178 NULL
, 0, NULL
, HFILL
}},
4179 { &hf_rpc_auth_gid
, {
4180 "GID", "rpc.auth.gid", FT_UINT32
, BASE_DEC
,
4181 NULL
, 0, NULL
, HFILL
}},
4182 { &hf_rpc_auth_flags
, {
4183 "FLAGS", "rpc.auth.flags", FT_UINT32
, BASE_HEX
,
4184 NULL
, 0, NULL
, HFILL
}},
4185 { &hf_rpc_auth_ctime
, {
4186 "CTIME", "rpc.auth.ctime", FT_ABSOLUTE_TIME
,
4187 ABSOLUTE_TIME_LOCAL
, NULL
, 0, NULL
, HFILL
}},
4188 { &hf_rpc_authgss_v
, {
4189 "GSS Version", "rpc.authgss.version", FT_UINT32
,
4190 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4191 { &hf_rpc_authgss_proc
, {
4192 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32
,
4193 BASE_DEC
, VALS(rpc_authgss_proc
), 0, NULL
, HFILL
}},
4194 { &hf_rpc_authgss_seq
, {
4195 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32
,
4196 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4197 { &hf_rpc_authgss_svc
, {
4198 "GSS Service", "rpc.authgss.service", FT_UINT32
,
4199 BASE_DEC
, VALS(rpc_authgss_svc
), 0, NULL
, HFILL
}},
4200 { &hf_rpc_authgss_ctx
, {
4201 "GSS Context", "rpc.authgss.context", FT_BYTES
,
4202 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4203 { &hf_rpc_authgss_ctx_create_frame
, {
4204 "Created in frame", "rpc.authgss.context.created_frame", FT_FRAMENUM
,
4205 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4206 { &hf_rpc_authgss_ctx_destroy_frame
, {
4207 "Destroyed in frame", "rpc.authgss.context.destroyed_frame", FT_FRAMENUM
,
4208 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4209 { &hf_rpc_authgss_ctx_len
, {
4210 "GSS Context Length", "rpc.authgss.context.length", FT_UINT32
,
4211 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4212 { &hf_rpc_authgss_major
, {
4213 "GSS Major Status", "rpc.authgss.major", FT_UINT32
,
4214 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4215 { &hf_rpc_authgss_minor
, {
4216 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32
,
4217 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4218 { &hf_rpc_authgss_window
, {
4219 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32
,
4220 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4221 { &hf_rpc_authgss_token_length
, {
4222 "GSS Token Length", "rpc.authgss.token_length", FT_UINT32
,
4223 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4224 { &hf_rpc_authgss_data_length
, {
4225 "Length", "rpc.authgss.data.length", FT_UINT32
,
4226 BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
4227 { &hf_rpc_authgss_data
, {
4228 "GSS Data", "rpc.authgss.data", FT_BYTES
,
4229 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4230 { &hf_rpc_authgss_checksum
, {
4231 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES
,
4232 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4233 { &hf_rpc_authgss_token
, {
4234 "GSS Token", "rpc.authgss.token", FT_BYTES
,
4235 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4236 { &hf_rpc_authgssapi_v
, {
4237 "AUTH_GSSAPI Version", "rpc.authgssapi.version",
4238 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
,
4240 { &hf_rpc_authgssapi_msg
, {
4241 "AUTH_GSSAPI Message", "rpc.authgssapi.message",
4242 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_yes_no
), 0x0, NULL
,
4244 { &hf_rpc_authgssapi_msgv
, {
4245 "Msg Version", "rpc.authgssapi.msgversion",
4246 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
,
4248 { &hf_rpc_authgssapi_handle
, {
4249 "Client Handle", "rpc.authgssapi.handle",
4250 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4251 { &hf_rpc_authgssapi_isn
, {
4252 "Signed ISN", "rpc.authgssapi.isn",
4253 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4254 { &hf_rpc_authdes_namekind
, {
4255 "Namekind", "rpc.authdes.namekind", FT_UINT32
, BASE_DEC
,
4256 VALS(rpc_authdes_namekind
), 0, NULL
, HFILL
}},
4257 { &hf_rpc_authdes_netname
, {
4258 "Netname", "rpc.authdes.netname", FT_STRING
,
4259 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4260 { &hf_rpc_authdes_convkey
, {
4261 "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT64
,
4262 BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
4263 { &hf_rpc_authdes_window
, {
4264 "Window (encrypted)", "rpc.authdes.window", FT_UINT32
,
4265 BASE_HEX
, NULL
, 0, "Windows (encrypted)", HFILL
}},
4266 { &hf_rpc_authdes_nickname
, {
4267 "Nickname", "rpc.authdes.nickname", FT_UINT32
,
4268 BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
4269 { &hf_rpc_authdes_timestamp
, {
4270 "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT64
,
4271 BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
4272 { &hf_rpc_authdes_windowverf
, {
4273 "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32
,
4274 BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
4275 { &hf_rpc_authdes_timeverf
, {
4276 "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT64
,
4277 BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
4278 { &hf_rpc_auth_machinename
, {
4279 "Machine Name", "rpc.auth.machinename", FT_STRING
,
4280 BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
4282 "Duplicate Call/Reply", "rpc.dup", FT_NONE
, BASE_NONE
,
4283 NULL
, 0, NULL
, HFILL
}},
4284 { &hf_rpc_call_dup
, {
4285 "Duplicate to the call in", "rpc.call.dup", FT_FRAMENUM
, BASE_NONE
,
4286 NULL
, 0, "This is a duplicate to the call in frame", HFILL
}},
4287 { &hf_rpc_reply_dup
, {
4288 "Duplicate to the reply in", "rpc.reply.dup", FT_FRAMENUM
, BASE_NONE
,
4289 NULL
, 0, "This is a duplicate to the reply in frame", HFILL
}},
4290 { &hf_rpc_value_follows
, {
4291 "Value Follows", "rpc.value_follows", FT_BOOLEAN
, BASE_NONE
,
4292 TFS(&tfs_yes_no
), 0x0, NULL
, HFILL
}},
4293 { &hf_rpc_array_len
, {
4294 "num", "rpc.array.len", FT_UINT32
, BASE_DEC
,
4295 NULL
, 0, "Length of RPC array", HFILL
}},
4297 /* Generated from convert_proto_tree_add_text.pl */
4298 { &hf_rpc_opaque_length
, { "length", "rpc.opaque_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4299 { &hf_rpc_fill_bytes
, { "fill bytes", "rpc.fill_bytes", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4300 { &hf_rpc_no_values
, { "no values", "rpc.array_no_values", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4301 { &hf_rpc_opaque_data
, { "opaque data", "rpc.opaque_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4302 { &hf_rpc_argument_length
, { "Argument length", "rpc.argument_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4303 { &hf_rpc_continuation_data
, { "Continuation data", "rpc.continuation_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4304 { &hf_rpc_fragment_data
, { "Fragment Data", "rpc.fragment_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4307 "Time from request", "rpc.time", FT_RELATIVE_TIME
, BASE_NONE
,
4308 NULL
, 0, "Time between Request and Reply for ONC-RPC calls", HFILL
}},
4310 { &hf_rpc_fragment_overlap
,
4311 { "Fragment overlap", "rpc.fragment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4312 "Fragment overlaps with other fragments", HFILL
}},
4314 { &hf_rpc_fragment_overlap_conflict
,
4315 { "Conflicting data in fragment overlap", "rpc.fragment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4316 "Overlapping fragments contained conflicting data", HFILL
}},
4318 { &hf_rpc_fragment_multiple_tails
,
4319 { "Multiple tail fragments found", "rpc.fragment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4320 "Several tails were found when defragmenting the packet", HFILL
}},
4322 { &hf_rpc_fragment_too_long_fragment
,
4323 { "Fragment too long", "rpc.fragment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4324 "Fragment contained data past end of packet", HFILL
}},
4326 { &hf_rpc_fragment_error
,
4327 { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
4328 "Defragmentation error due to illegal fragments", HFILL
}},
4330 { &hf_rpc_fragment_count
,
4331 { "Fragment count", "rpc.fragment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4335 { "RPC Fragment", "rpc.fragment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
4338 { &hf_rpc_fragments
,
4339 { "RPC Fragments", "rpc.fragments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
4342 { &hf_rpc_reassembled_length
,
4343 { "Reassembled RPC length", "rpc.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4344 "The total length of the reassembled payload", HFILL
}},
4346 { &hf_rpc_unknown_body
,
4347 { "Unknown RPC call/reply body", "rpc.unknown_body", FT_NONE
, BASE_NONE
, NULL
, 0x0,
4350 static int *ett
[] = {
4362 &ett_rpc_authgssapi_msg
,
4363 &ett_rpc_unknown_program
,
4367 static ei_register_info ei
[] = {
4368 { &ei_rpc_cannot_dissect
, { "rpc.cannot_dissect", PI_UNDECODED
, PI_WARN
, "Cannot dissect", EXPFILL
}},
4369 { &ei_rpc_segment_needed
, { "rpc.segment_needed", PI_REASSEMBLE
, PI_NOTE
, "Need another TCP segment but cannot desegment or not enabled (check RPC and TCP preferences)", EXPFILL
}},
4372 module_t
*rpc_module
;
4373 expert_module_t
* expert_rpc
;
4375 static tap_param rpc_prog_stat_params
[] = {
4376 { PARAM_FILTER
, "filter", "Filter", NULL
, true }
4379 static stat_tap_table_ui rpc_prog_stat_table
= {
4380 REGISTER_PACKET_STAT_GROUP_UNSORTED
,
4385 rpc_prog_stat_packet
,
4386 rpc_prog_stat_reset
,
4387 rpc_prog_stat_free_table_item
,
4389 array_length(rpc_prog_stat_fields
), rpc_prog_stat_fields
,
4390 array_length(rpc_prog_stat_params
), rpc_prog_stat_params
,
4395 proto_rpc
= proto_register_protocol("Remote Procedure Call", "RPC", "rpc");
4396 proto_rpc_unknown
= proto_register_protocol("Unknown RPC protocol", "Unknown RPC", "rpc-unknown");
4398 subdissector_call_table
= register_custom_dissector_table("rpc.call", "RPC Call Functions", proto_rpc
, rpc_proc_hash
, rpc_proc_equal
, g_free
);
4399 subdissector_reply_table
= register_custom_dissector_table("rpc.reply", "RPC Reply Functions", proto_rpc
, rpc_proc_hash
, rpc_proc_equal
, g_free
);
4401 /* this is a dummy dissector for all those unknown rpc programs */
4402 proto_register_field_array(proto_rpc
, hf
, array_length(hf
));
4403 proto_register_subtree_array(ett
, array_length(ett
));
4404 expert_rpc
= expert_register_protocol(proto_rpc
);
4405 expert_register_field_array(expert_rpc
, ei
, array_length(ei
));
4407 rpc_reassembly_table
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rpc_fragment_hash
, rpc_fragment_equal
);
4408 reassembly_table_register(&rpc_fragment_table
,
4409 &addresses_ports_reassembly_table_functions
);
4411 rpc_module
= prefs_register_protocol(proto_rpc
, NULL
);
4412 prefs_register_bool_preference(rpc_module
, "desegment_rpc_over_tcp",
4413 "Reassemble RPC over TCP messages spanning multiple TCP segments",
4414 "Whether the RPC dissector should reassemble messages spanning multiple TCP segments."
4415 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4417 prefs_register_bool_preference(rpc_module
, "defragment_rpc_over_tcp",
4418 "Reassemble fragmented RPC-over-TCP messages",
4419 "Whether the RPC dissector should defragment RPC-over-TCP messages.",
4422 prefs_register_uint_preference(rpc_module
, "max_tcp_pdu_size", "Maximum size of a RPC-over-TCP PDU",
4423 "Set the maximum size of RPCoverTCP PDUs. "
4424 " If the size field of the record marker is larger "
4425 "than this value it will not be considered a valid RPC PDU.",
4426 10, &max_rpc_tcp_pdu_size
);
4428 prefs_register_bool_preference(rpc_module
, "dissect_unknown_programs",
4429 "Dissect unknown RPC program numbers",
4430 "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.",
4431 &rpc_dissect_unknown_programs
);
4433 prefs_register_bool_preference(rpc_module
, "find_fragment_start",
4434 "Attempt to locate start-of-fragment in partial RPC-over-TCP captures",
4435 "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.",
4436 &rpc_find_fragment_start
);
4438 rpc_handle
= register_dissector("rpc", dissect_rpc
, proto_rpc
);
4439 rpc_tcp_handle
= register_dissector("rpc-tcp", dissect_rpc_tcp
, proto_rpc
);
4440 rpc_tls_handle
= register_dissector("rpc-with-tls", dissect_rpc_tls
, proto_rpc
);
4441 rpc_tap
= register_tap("rpc");
4443 register_srt_table(proto_rpc
, NULL
, 1, rpcstat_packet
, rpcstat_init
, rpcstat_param
);
4444 register_stat_tap_table_ui(&rpc_prog_stat_table
);
4447 * Init the hash tables. Dissectors for RPC protocols must
4448 * have a "handoff registration" routine that registers the
4449 * protocol with RPC; they must not do it in their protocol
4450 * registration routine, as their protocol registration
4451 * routine might be called before this routine is called and
4452 * thus might be called before the hash tables are initialized,
4453 * but it's guaranteed that all protocol registration routines
4454 * will be called before any handoff registration routines
4457 rpc_progs
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
4458 NULL
, rpc_prog_free_val
);
4460 authgss_contexts
=wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
4462 register_shutdown_routine(rpc_shutdown
);
4466 proto_reg_handoff_rpc(void)
4468 /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
4469 we register onc-rpc on this port so that we can choose RPC in
4470 the list offered by DecodeAs, and so that traffic to or from
4471 port 111 from or to a higher-numbered port is dissected as RPC
4472 even if there's a dissector registered on the other port (it's
4473 probably RPC traffic from some randomly-chosen port that happens
4474 to match some port for which we have a dissector)
4476 dissector_add_uint_with_preference("tcp.port", RPC_TCP_PORT
, rpc_tcp_handle
);
4477 dissector_add_uint_with_preference("udp.port", RPC_TCP_PORT
, rpc_handle
);
4478 dissector_add_string("tls.alpn", "sunrpc", rpc_tls_handle
);
4480 heur_dissector_add("tcp", dissect_rpc_tcp_heur
, "RPC over TCP", "rpc_tcp", proto_rpc
, HEURISTIC_ENABLE
);
4481 heur_dissector_add("udp", dissect_rpc_heur
, "RPC over UDP", "rpc_udp", proto_rpc
, HEURISTIC_ENABLE
);
4482 heur_dissector_add("tls", dissect_rpc_tls_heur
, "RPC with TLS", "rpc_tls", proto_rpc
, HEURISTIC_ENABLE
);
4483 gssapi_handle
= find_dissector_add_dependency("gssapi", proto_rpc
);
4484 spnego_krb5_wrap_handle
= find_dissector_add_dependency("spnego-krb5-wrap", proto_rpc
);
4485 data_handle
= find_dissector("data");
4494 * indent-tabs-mode: t
4497 * ex: set shiftwidth=8 tabstop=8 noexpandtab:
4498 * :indentSize=8:tabSize=8:noTabs=false: