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.c128
1 files changed, 127 insertions, 1 deletions
diff --git a/epan/dissectors/packet-rpc.c b/epan/dissectors/packet-rpc.c
index e8004870e4..5df6cb0d8a 100644
--- a/epan/dissectors/packet-rpc.c
+++ b/epan/dissectors/packet-rpc.c
@@ -25,7 +25,7 @@
#include "config.h"
-
+#include <stdio.h>
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/exceptions.h>
@@ -33,6 +33,7 @@
#include <epan/prefs.h>
#include <epan/reassemble.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/strutil.h>
#include <epan/show_exception.h>
@@ -312,6 +313,129 @@ static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
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);
+
+static guint32 rpc_program = 0;
+static guint32 rpc_version = 0;
+static gint32 rpc_min_proc = -1;
+static gint32 rpc_max_proc = -1;
+
+static void *
+rpcstat_find_procs(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
+{
+ rpc_proc_info_key *k = (rpc_proc_info_key *)key;
+
+ if (k->prog != rpc_program) {
+ return NULL;
+ }
+ if (k->vers != rpc_version) {
+ return NULL;
+ }
+ if (rpc_min_proc == -1) {
+ rpc_min_proc = k->proc;
+ rpc_max_proc = k->proc;
+ }
+ if ((gint32)k->proc < rpc_min_proc) {
+ rpc_min_proc = k->proc;
+ }
+ if ((gint32)k->proc > rpc_max_proc) {
+ rpc_max_proc = k->proc;
+ }
+
+ return NULL;
+}
+
+static void
+rpcstat_init(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ rpcstat_tap_data_t* tap_data = (rpcstat_tap_data_t*)get_srt_table_param_data(srt);
+ srt_stat_table *rpc_srt_table;
+ int i, hf_index;
+ header_field_info *hfi;
+ static char table_name[100];
+
+ DISSECTOR_ASSERT(tap_data);
+
+ 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);
+ rpc_srt_table = init_srt_table(table_name, NULL, srt_array, tap_data->num_procedures, NULL, hfi->abbrev, gui_callback, gui_data, tap_data);
+ for (i = 0; i < rpc_srt_table->num_procs; i++)
+ {
+ init_srt_table_row(rpc_srt_table, i, rpc_proc_name(tap_data->program, tap_data->version, i));
+ }
+}
+
+static int
+rpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *rpc_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const rpc_call_info_value *ri = (const rpc_call_info_value *)prv;
+ rpcstat_tap_data_t* tap_data;
+
+ rpc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ tap_data = (rpcstat_tap_data_t*)rpc_srt_table->table_specific_data;
+
+ if ((int)ri->proc >= rpc_srt_table->num_procs) {
+ /* don't handle this since its outside of known table */
+ return 0;
+ }
+ /* we are only interested in reply packets */
+ if (ri->request) {
+ return 0;
+ }
+ /* we are only interested in certain program/versions */
+ if ( (ri->prog != tap_data->program) || (ri->vers != tap_data->version) ) {
+ return 0;
+ }
+
+ add_srt_table_data(rpc_srt_table, ri->proc, &ri->req_time, pinfo);
+ return 1;
+
+}
+
+static guint
+rpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
+{
+ guint pos = 0;
+ int program, version;
+ rpcstat_tap_data_t* tap_data;
+
+ if (sscanf(opt_arg, ",%d,%d,%n", &program, &version, &pos) == 2)
+ {
+ tap_data = g_new0(rpcstat_tap_data_t, 1);
+
+ tap_data->prog = rpc_prog_name(program);
+ tap_data->program = program;
+ tap_data->version = version;
+
+ set_srt_table_param_data(srt, tap_data);
+
+ rpc_program = tap_data->program;
+ rpc_version = tap_data->version;
+ rpc_min_proc = -1;
+ rpc_max_proc = -1;
+ g_hash_table_foreach(rpc_procs, (GHFunc)rpcstat_find_procs, NULL);
+
+ 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);
+ }
+ }
+ else
+ {
+ *err = g_strdup_printf("<program>,<version>[,<filter>]");
+ }
+
+ return pos;
+}
+
+
+
+
+
/***********************************/
/* Hash array with procedure names */
/***********************************/
@@ -4030,6 +4154,8 @@ proto_register_rpc(void)
new_register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
rpc_tap = register_tap("rpc");
+ register_srt_table(proto_rpc, NULL, 1, rpcstat_packet, rpcstat_init, rpcstat_param);
+
/*
* Init the hash tables. Dissectors for RPC protocols must
* have a "handoff registration" routine that registers the