aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-rpc.c')
-rw-r--r--epan/dissectors/packet-rpc.c398
1 files changed, 222 insertions, 176 deletions
diff --git a/epan/dissectors/packet-rpc.c b/epan/dissectors/packet-rpc.c
index 0c8d118e28..d12b9e9d2f 100644
--- a/epan/dissectors/packet-rpc.c
+++ b/epan/dissectors/packet-rpc.c
@@ -13,7 +13,7 @@
#include "config.h"
-#include <stdio.h>
+#include <stdio.h> /* fprintf() */
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/exceptions.h>
@@ -29,8 +29,8 @@
#include "packet-rpc.h"
#include "packet-tcp.h"
+#include "packet-tls.h"
#include "packet-nfs.h"
-#include "packet-dcerpc.h"
#include "packet-gssapi.h"
/*
@@ -52,13 +52,17 @@
* RFC 5531, "Appendix C: Current Number Assignments" defines AUTH_RSA.
* AUTH_RSA is not implemented for any known RPC-protocols. The Gluster
* protocols (ab)use AUTH_RSA for their own AUTH-flavor. AUTH_RSA is
- * therefore dissected as the inofficial AUTH_GLUSTER.
+ * therefore dissected as the unofficial AUTH_GLUSTER.
*/
void proto_register_rpc(void);
void proto_reg_handoff_rpc(void);
#define RPC_TCP_PORT 111
+#define RPC_UDP 0
+#define RPC_TCP 1
+#define RPC_TLS 2
+
/* desegmentation of RPC over TCP */
static gboolean rpc_desegment = TRUE;
@@ -75,7 +79,7 @@ static gboolean rpc_dissect_unknown_programs = FALSE;
*/
static gboolean rpc_find_fragment_start = FALSE;
-static int rpc_tap = -1;
+static int rpc_tap;
static dissector_handle_t spnego_krb5_wrap_handle = NULL;
@@ -98,6 +102,7 @@ const value_string rpc_auth_flavor[] = {
{ AUTH_DES, "AUTH_DES" },
{ AUTH_RSA, "AUTH_RSA/Gluster" },
{ RPCSEC_GSS, "RPCSEC_GSS" },
+ { AUTH_TLS, "AUTH_TLS" },
{ AUTH_GSSAPI, "AUTH_GSSAPI" },
{ RPCSEC_GSS_KRB5, "RPCSEC_GSS_KRB5" },
{ RPCSEC_GSS_KRB5I, "RPCSEC_GSS_KRB5I" },
@@ -109,6 +114,7 @@ const value_string rpc_auth_flavor[] = {
{ RPCSEC_GSS_SPKM3I, "RPCSEC_GSS_SPKM3I" },
{ RPCSEC_GSS_SPKM3P, "RPCSEC_GSS_SPKM3P" },
{ AUTH_GLUSTERFS, "AUTH_GLUSTERFS" },
+ { AUTH_GLUSTERFS_V3, "AUTH_GLUSTERFS_V3" },
{ 0, NULL }
};
@@ -170,113 +176,114 @@ static const value_string rpc_authdes_namekind[] = {
};
/* the protocol number */
-static int proto_rpc = -1;
-static int hf_rpc_reqframe = -1;
-static int hf_rpc_repframe = -1;
-static int hf_rpc_lastfrag = -1;
-static int hf_rpc_fraglen = -1;
-static int hf_rpc_xid = -1;
-static int hf_rpc_msgtype = -1;
-static int hf_rpc_version = -1;
-static int hf_rpc_version_min = -1;
-static int hf_rpc_version_max = -1;
-static int hf_rpc_program = -1;
-static int hf_rpc_programversion = -1;
-static int hf_rpc_programversion_min = -1;
-static int hf_rpc_programversion_max = -1;
-static int hf_rpc_procedure = -1;
-static int hf_rpc_auth_flavor = -1;
-static int hf_rpc_auth_length = -1;
-static int hf_rpc_auth_machinename = -1;
-static int hf_rpc_auth_stamp = -1;
-static int hf_rpc_auth_lk_owner = -1;
-static int hf_rpc_auth_pid = -1;
-static int hf_rpc_auth_uid = -1;
-static int hf_rpc_auth_gid = -1;
-static int hf_rpc_auth_flags = -1;
-static int hf_rpc_auth_ctime = -1;
-static int hf_rpc_authgss_v = -1;
-static int hf_rpc_authgss_proc = -1;
-static int hf_rpc_authgss_seq = -1;
-static int hf_rpc_authgss_svc = -1;
-static int hf_rpc_authgss_ctx = -1;
-static int hf_rpc_authgss_ctx_create_frame = -1;
-static int hf_rpc_authgss_ctx_destroy_frame = -1;
-static int hf_rpc_authgss_ctx_len = -1;
-static int hf_rpc_authgss_major = -1;
-static int hf_rpc_authgss_minor = -1;
-static int hf_rpc_authgss_window = -1;
-static int hf_rpc_authgss_token_length = -1;
-static int hf_rpc_authgss_data_length = -1;
-static int hf_rpc_authgss_data = -1;
-static int hf_rpc_authgss_token = -1;
-static int hf_rpc_authgss_checksum = -1;
-static int hf_rpc_authgssapi_v = -1;
-static int hf_rpc_authgssapi_msg = -1;
-static int hf_rpc_authgssapi_msgv = -1;
-static int hf_rpc_authgssapi_handle = -1;
-static int hf_rpc_authgssapi_isn = -1;
-static int hf_rpc_authdes_namekind = -1;
-static int hf_rpc_authdes_netname = -1;
-static int hf_rpc_authdes_convkey = -1;
-static int hf_rpc_authdes_window = -1;
-static int hf_rpc_authdes_nickname = -1;
-static int hf_rpc_authdes_timestamp = -1;
-static int hf_rpc_authdes_windowverf = -1;
-static int hf_rpc_authdes_timeverf = -1;
-static int hf_rpc_state_accept = -1;
-static int hf_rpc_state_reply = -1;
-static int hf_rpc_state_reject = -1;
-static int hf_rpc_state_auth = -1;
-static int hf_rpc_dup = -1;
-static int hf_rpc_call_dup = -1;
-static int hf_rpc_reply_dup = -1;
-static int hf_rpc_value_follows = -1;
-static int hf_rpc_array_len = -1;
-static int hf_rpc_time = -1;
-static int hf_rpc_fragments = -1;
-static int hf_rpc_fragment = -1;
-static int hf_rpc_fragment_overlap = -1;
-static int hf_rpc_fragment_overlap_conflict = -1;
-static int hf_rpc_fragment_multiple_tails = -1;
-static int hf_rpc_fragment_too_long_fragment = -1;
-static int hf_rpc_fragment_error = -1;
-static int hf_rpc_fragment_count = -1;
-static int hf_rpc_reassembled_length = -1;
-static int hf_rpc_unknown_body = -1;
+static int proto_rpc;
+static int hf_rpc_reqframe;
+static int hf_rpc_repframe;
+static int hf_rpc_lastfrag;
+static int hf_rpc_fraglen;
+static int hf_rpc_xid;
+static int hf_rpc_msgtype;
+static int hf_rpc_version;
+static int hf_rpc_version_min;
+static int hf_rpc_version_max;
+static int hf_rpc_program;
+static int hf_rpc_programversion;
+static int hf_rpc_programversion_min;
+static int hf_rpc_programversion_max;
+static int hf_rpc_procedure;
+static int hf_rpc_auth_flavor;
+static int hf_rpc_auth_length;
+static int hf_rpc_auth_machinename;
+static int hf_rpc_auth_stamp;
+static int hf_rpc_auth_lk_owner;
+static int hf_rpc_auth_pid;
+static int hf_rpc_auth_uid;
+static int hf_rpc_auth_gid;
+static int hf_rpc_auth_flags;
+static int hf_rpc_auth_ctime;
+static int hf_rpc_authgss_v;
+static int hf_rpc_authgss_proc;
+static int hf_rpc_authgss_seq;
+static int hf_rpc_authgss_svc;
+static int hf_rpc_authgss_ctx;
+static int hf_rpc_authgss_ctx_create_frame;
+static int hf_rpc_authgss_ctx_destroy_frame;
+static int hf_rpc_authgss_ctx_len;
+static int hf_rpc_authgss_major;
+static int hf_rpc_authgss_minor;
+static int hf_rpc_authgss_window;
+static int hf_rpc_authgss_token_length;
+static int hf_rpc_authgss_data_length;
+static int hf_rpc_authgss_data;
+static int hf_rpc_authgss_token;
+static int hf_rpc_authgss_checksum;
+static int hf_rpc_authgssapi_v;
+static int hf_rpc_authgssapi_msg;
+static int hf_rpc_authgssapi_msgv;
+static int hf_rpc_authgssapi_handle;
+static int hf_rpc_authgssapi_isn;
+static int hf_rpc_authdes_namekind;
+static int hf_rpc_authdes_netname;
+static int hf_rpc_authdes_convkey;
+static int hf_rpc_authdes_window;
+static int hf_rpc_authdes_nickname;
+static int hf_rpc_authdes_timestamp;
+static int hf_rpc_authdes_windowverf;
+static int hf_rpc_authdes_timeverf;
+static int hf_rpc_state_accept;
+static int hf_rpc_state_reply;
+static int hf_rpc_state_reject;
+static int hf_rpc_state_auth;
+static int hf_rpc_dup;
+static int hf_rpc_call_dup;
+static int hf_rpc_reply_dup;
+static int hf_rpc_value_follows;
+static int hf_rpc_array_len;
+static int hf_rpc_time;
+static int hf_rpc_fragments;
+static int hf_rpc_fragment;
+static int hf_rpc_fragment_overlap;
+static int hf_rpc_fragment_overlap_conflict;
+static int hf_rpc_fragment_multiple_tails;
+static int hf_rpc_fragment_too_long_fragment;
+static int hf_rpc_fragment_error;
+static int hf_rpc_fragment_count;
+static int hf_rpc_reassembled_length;
+static int hf_rpc_unknown_body;
/* Generated from convert_proto_tree_add_text.pl */
-static int hf_rpc_opaque_data = -1;
-static int hf_rpc_no_values = -1;
-static int hf_rpc_continuation_data = -1;
-static int hf_rpc_fill_bytes = -1;
-static int hf_rpc_argument_length = -1;
-static int hf_rpc_fragment_data = -1;
-static int hf_rpc_opaque_length = -1;
-
-static gint ett_rpc = -1;
-static gint ett_rpc_unknown_program = -1;
-static gint ett_rpc_fragments = -1;
-static gint ett_rpc_fragment = -1;
-static gint ett_rpc_fraghdr = -1;
-static gint ett_rpc_string = -1;
-static gint ett_rpc_cred = -1;
-static gint ett_rpc_verf = -1;
-static gint ett_rpc_gids = -1;
-static gint ett_rpc_gss_token = -1;
-static gint ett_rpc_gss_data = -1;
-static gint ett_rpc_array = -1;
-static gint ett_rpc_authgssapi_msg = -1;
-static gint ett_gss_context = -1;
-static gint ett_gss_wrap = -1;
-
-static expert_field ei_rpc_cannot_dissect = EI_INIT;
-static expert_field ei_rpc_segment_needed = EI_INIT;
+static int hf_rpc_opaque_data;
+static int hf_rpc_no_values;
+static int hf_rpc_continuation_data;
+static int hf_rpc_fill_bytes;
+static int hf_rpc_argument_length;
+static int hf_rpc_fragment_data;
+static int hf_rpc_opaque_length;
+
+static gint ett_rpc;
+static gint ett_rpc_unknown_program;
+static gint ett_rpc_fragments;
+static gint ett_rpc_fragment;
+static gint ett_rpc_fraghdr;
+static gint ett_rpc_string;
+static gint ett_rpc_cred;
+static gint ett_rpc_verf;
+static gint ett_rpc_gids;
+static gint ett_rpc_gss_token;
+static gint ett_rpc_gss_data;
+static gint ett_rpc_array;
+static gint ett_rpc_authgssapi_msg;
+static gint ett_gss_context;
+static gint ett_gss_wrap;
+
+static expert_field ei_rpc_cannot_dissect;
+static expert_field ei_rpc_segment_needed;
static dissector_handle_t rpc_tcp_handle;
static dissector_handle_t rpc_handle;
static dissector_handle_t gssapi_handle;
static dissector_handle_t data_handle;
+static dissector_handle_t rpc_tls_handle;
static dissector_table_t subdissector_call_table;
static dissector_table_t subdissector_reply_table;
@@ -306,7 +313,7 @@ static const fragment_items rpc_frag_items = {
GHashTable *rpc_progs = NULL;
typedef gboolean (*rec_dissector_t)(tvbuff_t *, packet_info *, proto_tree *,
- tvbuff_t *, fragment_head *, gboolean, guint32, gboolean, gboolean);
+ tvbuff_t *, fragment_head *, int, guint32, gboolean, gboolean);
static void show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
guint32 rpc_rm, fragment_head *ipfd_head, packet_info *pinfo);
@@ -356,7 +363,7 @@ rpcstat_init(struct register_srt* srt, GArray* srt_array)
hf_index=rpc_prog_hf(tap_data->program, tap_data->version);
hfi=proto_registrar_get_nth(hf_index);
- g_snprintf(table_name, sizeof(table_name), "%s Version %u", tap_data->prog, tap_data->version);
+ snprintf(table_name, sizeof(table_name), "%s Version %u", tap_data->prog, tap_data->version);
rpc_srt_table = init_srt_table(table_name, NULL, srt_array, tap_data->num_procedures, NULL, hfi->abbrev, tap_data);
for (i = 0; i < rpc_srt_table->num_procs; i++)
{
@@ -367,7 +374,7 @@ rpcstat_init(struct register_srt* srt, GArray* srt_array)
}
static tap_packet_status
-rpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+rpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv, tap_flags_t flags _U_)
{
srt_stat_table *rpc_srt_table;
srt_data_t *data = (srt_data_t *)pss;
@@ -422,7 +429,7 @@ rpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
tap_data->num_procedures = rpc_max_proc+1;
if (rpc_min_proc == -1) {
- *err = g_strdup_printf("Program:%u version:%u isn't supported", rpc_program, rpc_version);
+ *err = ws_strdup_printf("Program:%u version:%u isn't supported", rpc_program, rpc_version);
}
}
else
@@ -477,6 +484,7 @@ rpc_proc_name_internal(wmem_allocator_t *allocator, guint32 prog, guint32 vers,
key.proc = proc;
/* Look at both tables for possible procedure names */
+ /* XXX - dissector name, or protocol name? */
if ((dissect_function = dissector_get_custom_table_handle(subdissector_call_table, &key)) != NULL)
procname = wmem_strdup(allocator, dissector_handle_get_dissector_name(dissect_function));
else if ((dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key)) != NULL)
@@ -713,7 +721,8 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
/* int string_item_offset; */
char *string_buffer = NULL;
- const char *string_buffer_print = NULL;
+ uint8_t *bytes_buffer;
+ const char *formatted_text = NULL;
if (fixed_length) {
string_length = length;
@@ -779,9 +788,9 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
if (string_data) {
string_buffer = tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset, string_length_copy, ENC_ASCII);
} else {
- string_buffer = (char *)tvb_memcpy(tvb, wmem_alloc(wmem_packet_scope(), string_length_copy+1), data_offset, string_length_copy);
+ bytes_buffer = tvb_memcpy(tvb, wmem_alloc(wmem_packet_scope(), string_length_copy), data_offset, string_length_copy);
}
- string_buffer[string_length_copy] = '\0';
+
/* calculate a nice printable string */
if (string_length) {
if (string_length != string_length_copy) {
@@ -790,25 +799,25 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
formatted = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer));
/* copy over the data and append <TRUNCATED> */
- string_buffer_print=wmem_strdup_printf(wmem_packet_scope(), "%s%s", formatted, RPC_STRING_TRUNCATED);
+ formatted_text=wmem_strdup_printf(wmem_packet_scope(), "%s%s", formatted, RPC_STRING_TRUNCATED);
} else {
- string_buffer_print=RPC_STRING_DATA RPC_STRING_TRUNCATED;
+ formatted_text=RPC_STRING_DATA RPC_STRING_TRUNCATED;
}
} else {
if (string_data) {
- string_buffer_print = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer));
+ formatted_text = format_text(wmem_packet_scope(), string_buffer, strlen(string_buffer));
} else {
- string_buffer_print=RPC_STRING_DATA;
+ formatted_text=RPC_STRING_DATA;
}
}
} else {
- string_buffer_print=RPC_STRING_EMPTY;
+ formatted_text=RPC_STRING_EMPTY;
}
/* string_item_offset = offset; */
string_tree = proto_tree_add_subtree_format(tree, tvb,offset, -1,
ett_rpc_string, &string_item, "%s: %s", proto_registrar_get_name(hfindex),
- string_buffer_print);
+ formatted_text);
if (!fixed_length) {
proto_tree_add_uint(string_tree, hf_rpc_opaque_length, tvb,offset, 4, string_length);
@@ -820,12 +829,12 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
proto_tree_add_string_format(string_tree,
hfindex, tvb, offset, string_length_copy,
string_buffer,
- "contents: %s", string_buffer_print);
+ "contents: %s", formatted_text);
} else {
proto_tree_add_bytes_format(string_tree,
hfindex, tvb, offset, string_length_copy,
- string_buffer,
- "contents: %s", string_buffer_print);
+ bytes_buffer,
+ "contents: %s", formatted_text);
}
}
@@ -846,7 +855,7 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
proto_item_set_end(string_item, tvb, offset);
if (string_buffer_ret != NULL)
- *string_buffer_ret = string_buffer_print;
+ *string_buffer_ret = formatted_text;
/*
* If the data was truncated, throw the appropriate exception,
@@ -1227,11 +1236,11 @@ dissect_rpc_authglusterfs_v3_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
offset = dissect_rpc_uint32(tvb, tree, hf_rpc_auth_gid, offset);
offset = dissect_rpc_uint32(tvb, tree, hf_rpc_auth_flags, offset);
timestamp.secs = tvb_get_ntohl(tvb, offset);
- timestamp.nsecs = tvb_get_ntohl(tvb, offset + 4);
+ timestamp.nsecs = (int)tvb_get_ntohi64(tvb, offset + 4);
if (tree)
proto_tree_add_time(tree, hf_rpc_auth_ctime, tvb,
- offset, 8, &timestamp);
- offset += 8;
+ offset, 12, &timestamp);
+ offset += 12;
offset = dissect_rpc_authunix_groups(tvb, tree, offset);
@@ -1687,18 +1696,18 @@ get_conversation_for_call(packet_info *pinfo)
* if you use NO_ADDR_B.
*/
conversation = find_conversation(pinfo->num,
- &pinfo->src, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype),
+ &pinfo->src, &null_address, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, 0, NO_ADDR_B|NO_PORT_B);
}
if (conversation == NULL) {
if (pinfo->ptype == PT_TCP || pinfo->ptype == PT_IBQP || pinfo->ptype == PT_IWARP_MPA) {
conversation = conversation_new(pinfo->num,
- &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
+ &pinfo->src, &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->srcport, pinfo->destport, 0);
} else {
conversation = conversation_new(pinfo->num,
- &pinfo->src, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype),
+ &pinfo->src, &null_address, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->destport, 0, NO_ADDR2|NO_PORT2);
}
}
@@ -1739,7 +1748,7 @@ find_conversation_for_reply(packet_info *pinfo)
* if you use NO_ADDR_B.
*/
conversation = find_conversation(pinfo->num,
- &pinfo->dst, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype),
+ &pinfo->dst, &null_address, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->srcport, 0, NO_ADDR_B|NO_PORT_B);
}
return conversation;
@@ -1754,22 +1763,22 @@ new_conversation_for_reply(packet_info *pinfo)
{
case PT_TCP:
conversation = conversation_new(pinfo->num,
- &pinfo->src, &pinfo->dst, ENDPOINT_TCP,
+ &pinfo->src, &pinfo->dst, CONVERSATION_TCP,
pinfo->srcport, pinfo->destport, 0);
break;
case PT_IBQP:
conversation = conversation_new(pinfo->num,
- &pinfo->src, &pinfo->dst, ENDPOINT_IBQP,
+ &pinfo->src, &pinfo->dst, CONVERSATION_IBQP,
pinfo->srcport, pinfo->destport, 0);
break;
case PT_IWARP_MPA:
conversation = conversation_new(pinfo->num,
- &pinfo->src, &pinfo->dst, ENDPOINT_IWARP_MPA,
+ &pinfo->src, &pinfo->dst, CONVERSATION_IWARP_MPA,
pinfo->srcport, pinfo->destport, 0);
break;
default:
conversation = conversation_new(pinfo->num,
- &pinfo->dst, &null_address, conversation_pt_to_endpoint_type(pinfo->ptype),
+ &pinfo->dst, &null_address, conversation_pt_to_conversation_type(pinfo->ptype),
pinfo->srcport, 0, NO_ADDR2|NO_PORT2);
break;
}
@@ -1937,6 +1946,7 @@ dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key);
if (dissect_function != NULL) {
+ /* XXX - dissector name, or protocol name? */
procname = dissector_handle_get_dissector_name(dissect_function);
}
else {
@@ -2203,7 +2213,7 @@ looks_like_rpc_reply(tvbuff_t *tvb, packet_info *pinfo, int offset)
static gboolean
dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- tvbuff_t *frag_tvb, fragment_head *ipfd_head, gboolean is_tcp,
+ tvbuff_t *frag_tvb, fragment_head *ipfd_head, int tp_type,
guint32 rpc_rm, gboolean first_pdu, gboolean can_defragment)
{
guint32 msg_type;
@@ -2216,6 +2226,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
unsigned int prog = 0;
unsigned int vers = 0;
unsigned int proc = 0;
+ unsigned int cred_flavor = 0;
flavor_t flavor = FLAVOR_UNKNOWN;
unsigned int gss_proc = 0;
unsigned int gss_svc = 0;
@@ -2242,7 +2253,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_item *pitem = NULL;
proto_tree *ptree = NULL;
- int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
+ int offset = (tp_type != RPC_UDP && tvb == frag_tvb) ? 4 : 0;
rpc_proc_info_key key;
conversation_t* conversation;
@@ -2290,7 +2301,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
return FALSE;
}
- if (is_tcp) {
+ if (tp_type != RPC_UDP) {
/*
* This is RPC-over-TCP; check if this is the last
* fragment.
@@ -2314,7 +2325,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
ENC_NA);
rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
- if (is_tcp) {
+ if (tp_type != RPC_UDP) {
show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm,
ipfd_head, pinfo);
}
@@ -2371,6 +2382,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
key.proc = proc;
if ((dissect_function = dissector_get_custom_table_handle(subdissector_call_table, &key)) != NULL) {
+ /* XXX - dissector name, or protocol name? */
procname = dissector_handle_get_dissector_name(dissect_function);
}
else {
@@ -2383,7 +2395,8 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* Check for RPCSEC_GSS and AUTH_GSSAPI */
if (tvb_bytes_exist(tvb, offset+16, 4)) {
- switch (tvb_get_ntohl(tvb, offset+16)) {
+ cred_flavor = tvb_get_ntohl(tvb, offset+16);
+ switch (cred_flavor) {
case RPCSEC_GSS:
/*
@@ -2472,8 +2485,10 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* Make the dissector for this conversation the non-heuristic
RPC dissector. */
- conversation_set_dissector(conversation,
- (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
+ if (tp_type != RPC_TLS && cred_flavor != AUTH_TLS) {
+ conversation_set_dissector(conversation,
+ (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
+ }
/* look up the request */
rpc_call = (rpc_call_info_value *)wmem_tree_lookup32(rpc_conv_info->xids, xid);
@@ -2531,16 +2546,11 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
offset += 16;
offset = dissect_rpc_cred(tvb, rpc_tree, offset, pinfo, rpc_conv_info);
+ offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
+
/* pass rpc_info to subdissectors */
rpc_call->request=TRUE;
- if (gss_proc == RPCSEC_GSS_DESTROY) {
- /* there is no verifier for GSS destroy packets */
- break;
- }
-
- offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
-
/* go to the next dissector */
break; /* end of RPC call */
@@ -2557,6 +2567,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
dissect_function = dissector_get_custom_table_handle(subdissector_reply_table, &key);
if (dissect_function != NULL) {
+ /* XXX - dissector name, or protocol name? */
procname = dissector_handle_get_dissector_name(dissect_function);
}
else {
@@ -3014,7 +3025,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb_new_subset_remaining(tvb, offset), pinfo, ptree);
}
- /* XXX this should really loop over all fhandles registred for the frame */
+ /* XXX this should really loop over all fhandles registered for the frame */
if(nfs_fhandle_reqrep_matching){
switch (msg_type) {
case RPC_CALL:
@@ -3038,14 +3049,14 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
static gboolean
dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
- return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
+ return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, RPC_UDP, 0,
TRUE, FALSE);
}
static int
dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
- if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
+ if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, RPC_UDP, 0,
TRUE, FALSE)) {
if (tvb_reported_length(tvb) != 0)
dissect_rpc_continuation(tvb, pinfo, tree);
@@ -3177,8 +3188,8 @@ show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
static gboolean
call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector,
- fragment_head *ipfd_head, guint32 rpc_rm, gboolean first_pdu,
- gboolean can_defragment)
+ fragment_head *ipfd_head, int tp_type, guint32 rpc_rm,
+ gboolean first_pdu, gboolean can_defragment)
{
const char *saved_proto;
volatile gboolean rpc_succeeded;
@@ -3187,7 +3198,7 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
rpc_succeeded = FALSE;
TRY {
rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
- frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu,
+ frag_tvb, ipfd_head, tp_type, rpc_rm, first_pdu,
can_defragment);
}
CATCH_NONFATAL_ERRORS {
@@ -3216,13 +3227,14 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
}
static int
-dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, rec_dissector_t dissector, gboolean is_heur,
- int proto, int ett, gboolean first_pdu, struct tcpinfo *tcpinfo)
+dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ rec_dissector_t dissector, gboolean is_heur, int proto, int ett,
+ gboolean first_pdu, struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo)
{
guint32 seq;
guint32 rpc_rm;
guint32 len;
+ int tp_type;
gint tvb_len, tvb_reported_len;
tvbuff_t *frag_tvb;
conversation_t *conversation = NULL;
@@ -3233,11 +3245,12 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
fragment_head *ipfd_head;
tvbuff_t *rec_tvb;
- if (pinfo == NULL || tcpinfo == NULL) {
+ if (pinfo == NULL || (tcpinfo == NULL && tlsinfo == NULL)) {
return 0;
}
- seq = tcpinfo->seq + offset;
+ seq = (tcpinfo != NULL ? tcpinfo->seq : tlsinfo->seq) + offset;
+ tp_type = (tcpinfo != NULL ? RPC_TCP : RPC_TLS);
/*
* Get the record mark.
@@ -3322,8 +3335,9 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
dissector for it the non-heuristic RPC
dissector for RPC-over-TCP. */
conversation = find_or_create_conversation(pinfo);
- conversation_set_dissector(conversation,
- rpc_tcp_handle);
+ if (tcpinfo != NULL) {
+ conversation_set_dissector(conversation, rpc_tcp_handle);
+ }
}
/* OK, we think it is RPC. Can we desegment? */
@@ -3376,8 +3390,8 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
save_fragmented = pinfo->fragmented;
pinfo->fragmented = TRUE;
rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo,
- tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu,
- can_defragment);
+ tree, frag_tvb, dissector, ipfd_head, tp_type, rpc_rm,
+ first_pdu, can_defragment);
pinfo->fragmented = save_fragmented;
if (!rpc_succeeded)
return 0; /* not RPC */
@@ -3424,7 +3438,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
* an exception.
*/
if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb,
- NULL, TRUE, rpc_rm, first_pdu, can_defragment))
+ NULL, tp_type, rpc_rm, first_pdu, can_defragment))
return 0; /* not valid */
/*
@@ -3609,8 +3623,8 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
* dissector.
*/
if (!call_message_dissector(tvb, rec_tvb, pinfo, tree,
- frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu,
- can_defragment))
+ frag_tvb, dissector, ipfd_head, tp_type, rpc_rm,
+ first_pdu, can_defragment))
return 0; /* not RPC */
return len;
} /* end of dissect_rpc_fragment() */
@@ -3766,8 +3780,8 @@ find_rpc_over_tcp_reply_start(tvbuff_t *tvb, int offset)
static int
find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, rec_dissector_t dissector,
- gboolean is_heur,
- int proto, int ett, struct tcpinfo* tcpinfo)
+ gboolean is_heur, int proto, int ett,
+ struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo)
{
int offReply;
@@ -3782,7 +3796,7 @@ find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
len = dissect_rpc_fragment(tvb, offReply,
pinfo, tree,
dissector, is_heur, proto, ett,
- TRUE /* force first-pdu state */, tcpinfo);
+ TRUE /* force first-pdu state */, tcpinfo, tlsinfo);
/* misses are reported as-is */
if (len == 0)
@@ -3813,7 +3827,7 @@ find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
*/
static gboolean
dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- gboolean is_heur, struct tcpinfo* tcpinfo)
+ gboolean is_heur, struct tcpinfo *tcpinfo, struct tlsinfo *tlsinfo)
{
int offset = 0;
gboolean saw_rpc = FALSE;
@@ -3826,7 +3840,7 @@ dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
*/
len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
- first_pdu, tcpinfo);
+ first_pdu, tcpinfo, tlsinfo);
if ((len == 0) && first_pdu && rpc_find_fragment_start) {
/*
@@ -3835,7 +3849,7 @@ dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
*/
len = find_and_dissect_rpc_fragment(tvb, offset, pinfo, tree,
dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
- tcpinfo);
+ tcpinfo, tlsinfo);
}
first_pdu = FALSE;
@@ -3893,7 +3907,7 @@ dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
{
struct tcpinfo* tcpinfo = (struct tcpinfo *)data;
- return dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, tcpinfo);
+ return dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, tcpinfo, NULL);
}
static int
@@ -3901,12 +3915,42 @@ dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
struct tcpinfo* tcpinfo = (struct tcpinfo *)data;
- if (!dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, tcpinfo))
+ if (!dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, tcpinfo, NULL))
dissect_rpc_continuation(tvb, pinfo, tree);
return tvb_reported_length(tvb);
}
+static gboolean
+dissect_rpc_tls_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ struct tlsinfo *tlsinfo = (struct tlsinfo *)data;
+
+ if (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE, NULL, tlsinfo)) {
+ if (tlsinfo != NULL) {
+ *(tlsinfo->app_handle) = rpc_tls_handle;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int
+dissect_rpc_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
+{
+ struct tlsinfo* tlsinfo = (struct tlsinfo *)data;
+
+ col_set_writable(pinfo->cinfo, COL_PROTOCOL, TRUE);
+ if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE, NULL, tlsinfo)) {
+ col_set_writable(pinfo->cinfo, COL_PROTOCOL, FALSE);
+ col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
+ } else {
+ dissect_rpc_continuation(tvb, pinfo, tree);
+ }
+
+ return tvb_reported_length(tvb);
+}
+
/* Tap statistics */
typedef enum
{
@@ -3948,7 +3992,7 @@ static void rpc_prog_stat_init(stat_tap_table_ui* new_stat)
}
static tap_packet_status
-rpc_prog_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rciv_ptr)
+rpc_prog_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rciv_ptr, tap_flags_t flags _U_)
{
stat_data_t* stat_data = (stat_data_t*)tapdata;
const rpc_call_info_value *ri = (const rpc_call_info_value *)rciv_ptr;
@@ -4342,7 +4386,7 @@ proto_register_rpc(void)
};
static stat_tap_table_ui rpc_prog_stat_table = {
- REGISTER_STAT_GROUP_UNSORTED,
+ REGISTER_PACKET_STAT_GROUP_UNSORTED,
"ONC-RPC Programs",
"rpc",
"rpc,programs",
@@ -4359,8 +4403,8 @@ proto_register_rpc(void)
proto_rpc = proto_register_protocol("Remote Procedure Call", "RPC", "rpc");
- subdissector_call_table = register_custom_dissector_table("rpc.call", "RPC Call Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal);
- subdissector_reply_table = register_custom_dissector_table("rpc.reply", "RPC Reply Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal);
+ subdissector_call_table = register_custom_dissector_table("rpc.call", "RPC Call Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal, g_free);
+ subdissector_reply_table = register_custom_dissector_table("rpc.reply", "RPC Reply Functions", proto_rpc, rpc_proc_hash, rpc_proc_equal, g_free);
/* this is a dummy dissector for all those unknown rpc programs */
proto_register_field_array(proto_rpc, hf, array_length(hf));
@@ -4401,6 +4445,7 @@ proto_register_rpc(void)
rpc_handle = register_dissector("rpc", dissect_rpc, proto_rpc);
rpc_tcp_handle = register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
+ rpc_tls_handle = register_dissector("rpc-with-tls", dissect_rpc_tls, proto_rpc);
rpc_tap = register_tap("rpc");
register_srt_table(proto_rpc, NULL, 1, rpcstat_packet, rpcstat_init, rpcstat_param);
@@ -4441,6 +4486,7 @@ proto_reg_handoff_rpc(void)
heur_dissector_add("tcp", dissect_rpc_tcp_heur, "RPC over TCP", "rpc_tcp", proto_rpc, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_rpc_heur, "RPC over UDP", "rpc_udp", proto_rpc, HEURISTIC_ENABLE);
+ heur_dissector_add("tls", dissect_rpc_tls_heur, "RPC with TLS", "rpc_tls", proto_rpc, HEURISTIC_ENABLE);
gssapi_handle = find_dissector_add_dependency("gssapi", proto_rpc);
spnego_krb5_wrap_handle = find_dissector_add_dependency("spnego-krb5-wrap", proto_rpc);
data_handle = find_dissector("data");