aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
Diffstat (limited to 'epan')
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/Makefile.common2
-rw-r--r--epan/conversation_table.c3
-rw-r--r--epan/dissectors/packet-afp.c42
-rw-r--r--epan/dissectors/packet-camel.c60
-rw-r--r--epan/dissectors/packet-dcerpc.c160
-rw-r--r--epan/dissectors/packet-dcerpc.h8
-rw-r--r--epan/dissectors/packet-diameter.c64
-rw-r--r--epan/dissectors/packet-fc.c43
-rw-r--r--epan/dissectors/packet-gtp.c58
-rw-r--r--epan/dissectors/packet-ldap.c67
-rw-r--r--epan/dissectors/packet-ncp.c250
-rw-r--r--epan/dissectors/packet-rpc.c128
-rw-r--r--epan/dissectors/packet-rpc.h8
-rw-r--r--epan/dissectors/packet-scsi.c108
-rw-r--r--epan/dissectors/packet-smb.c72
-rw-r--r--epan/dissectors/packet-smb2.c49
-rw-r--r--epan/srt_table.c322
-rw-r--r--epan/srt_table.h240
19 files changed, 1665 insertions, 20 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index c972107b08..87b2d298f9 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1631,6 +1631,7 @@ set(LIBWIRESHARK_FILES
req_resp_hdrs.c
show_exception.c
sminmpec.c
+ srt_table.c
stat_tap_ui.c
stats_tree.c
strutil.c
diff --git a/epan/Makefile.common b/epan/Makefile.common
index 52b772ebd1..ec2ee1926e 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -81,6 +81,7 @@ LIBWIRESHARK_SRC = \
req_resp_hdrs.c \
show_exception.c \
sminmpec.c \
+ srt_table.c \
stat_tap_ui.c \
stats_tree.c \
strutil.c \
@@ -236,6 +237,7 @@ LIBWIRESHARK_INCLUDES = \
show_exception.h \
slow_protocol_subtypes.h \
sminmpec.h \
+ srt_table.h \
stat_tap_ui.h \
stat_groups.h \
stats_tree.h \
diff --git a/epan/conversation_table.c b/epan/conversation_table.c
index b02d6e558b..f1f397780d 100644
--- a/epan/conversation_table.c
+++ b/epan/conversation_table.c
@@ -32,8 +32,6 @@
#include "stat_tap_ui.h"
-GList *cmd_string_list_ = NULL;
-
struct register_ct {
gboolean hide_ports; /* hide TCP / UDP port columns */
int proto_id; /* protocol id (0-indexed) */
@@ -164,7 +162,6 @@ set_conv_gui_data(gpointer data, gpointer user_data)
table->conv_gui_init = (conv_gui_init_cb)user_data;
g_string_append(conv_cmd_str, proto_get_protocol_filter_name(table->proto_id));
- cmd_string_list_ = g_list_append(cmd_string_list_, conv_cmd_str->str);
ui_info.group = REGISTER_STAT_GROUP_CONVERSATION_LIST;
ui_info.title = NULL; /* construct this from the protocol info? */
ui_info.cli_string = g_string_free(conv_cmd_str, FALSE);
diff --git a/epan/dissectors/packet-afp.c b/epan/dissectors/packet-afp.c
index 2f89b82f20..e317af7b10 100644
--- a/epan/dissectors/packet-afp.c
+++ b/epan/dissectors/packet-afp.c
@@ -32,6 +32,7 @@
#include <epan/to_str.h>
#include <epan/conversation.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/expert.h>
#include "packet-afp.h"
@@ -1094,6 +1095,45 @@ static const value_string afp_server_addr_type_vals[] = {
{0, NULL } };
value_string_ext afp_server_addr_type_vals_ext = VALUE_STRING_EXT_INIT(afp_server_addr_type_vals);
+#define AFP_NUM_PROCEDURES 256
+
+static void
+afpstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *afp_srt_table;
+ guint32 i;
+
+ afp_srt_table = init_srt_table("AFP Commands", NULL, srt_array, AFP_NUM_PROCEDURES, NULL, "afp.command", gui_callback, gui_data, NULL);
+ for (i = 0; i < AFP_NUM_PROCEDURES; i++)
+ {
+ gchar* tmp_str = val_to_str_ext_wmem(NULL, i, &CommandCode_vals_ext, "Unknown(%u)");
+ init_srt_table_row(afp_srt_table, i, tmp_str);
+ wmem_free(NULL, tmp_str);
+ }
+}
+
+static int
+afpstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *afp_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const afp_request_val *request_val = (const afp_request_val *)prv;
+
+ /* if we haven't seen the request, just ignore it */
+ if (!request_val) {
+ return 0;
+ }
+
+ afp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+
+ add_srt_table_data(afp_srt_table, request_val->command, &request_val->req_time, pinfo);
+
+ return 1;
+}
+
+
+
#define hash_init_count 20
/* Forward declarations */
@@ -7232,6 +7272,8 @@ proto_register_afp(void)
new_register_dissector("afp_spotlight", dissect_spotlight, proto_afp);
afp_tap = register_tap("afp");
+
+ register_srt_table(proto_afp, NULL, 1, afpstat_packet, afpstat_init, NULL);
}
void
diff --git a/epan/dissectors/packet-camel.c b/epan/dissectors/packet-camel.c
index 74f917ddf8..80fbdcbde6 100644
--- a/epan/dissectors/packet-camel.c
+++ b/epan/dissectors/packet-camel.c
@@ -47,6 +47,7 @@
#include <epan/prefs.h>
#include <epan/oids.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/asn1.h>
#include <epan/expert.h>
@@ -605,7 +606,7 @@ static int hf_camel_present = -1; /* INTEGER */
static int hf_camel_InvokeId_present = -1; /* InvokeId_present */
/*--- End of included file: packet-camel-hf.c ---*/
-#line 112 "../../asn1/camel/packet-camel-template.c"
+#line 113 "../../asn1/camel/packet-camel-template.c"
static struct camelsrt_info_t * gp_camelsrt_info;
@@ -835,7 +836,7 @@ static gint ett_camel_T_problem = -1;
static gint ett_camel_InvokeId = -1;
/*--- End of included file: packet-camel-ett.c ---*/
-#line 143 "../../asn1/camel/packet-camel-template.c"
+#line 144 "../../asn1/camel/packet-camel-template.c"
static expert_field ei_camel_unknown_invokeData = EI_INIT;
static expert_field ei_camel_unknown_returnResultData = EI_INIT;
@@ -1180,7 +1181,7 @@ static const value_string camel_ectTreatmentIndicator_values[] = {
#define noInvokeId NULL
/*--- End of included file: packet-camel-val.h ---*/
-#line 303 "../../asn1/camel/packet-camel-template.c"
+#line 304 "../../asn1/camel/packet-camel-template.c"
/*--- Included file: packet-camel-table.c ---*/
@@ -1270,7 +1271,7 @@ static const value_string camel_err_code_string_vals[] = {
/*--- End of included file: packet-camel-table.c ---*/
-#line 305 "../../asn1/camel/packet-camel-template.c"
+#line 306 "../../asn1/camel/packet-camel-template.c"
/*
* DEBUG fonctions
@@ -1294,6 +1295,45 @@ static void dbg(guint level, char *fmt, ...) {
}
#endif
+static void
+camelstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *camel_srt_table;
+ gchar* tmp_str;
+ guint32 i;
+
+ camel_srt_table = init_srt_table("CAMEL Commands", NULL, srt_array, NB_CAMELSRT_CATEGORY, NULL, NULL, gui_callback, gui_data, NULL);
+ for (i = 0; i < NB_CAMELSRT_CATEGORY; i++)
+ {
+ tmp_str = val_to_str_wmem(NULL,i,camelSRTtype_naming,"Unknown (%d)");
+ init_srt_table_row(camel_srt_table, i, tmp_str);
+ wmem_free(NULL, tmp_str);
+ }
+}
+
+static int
+camelstat_packet(void *pcamel, packet_info *pinfo, epan_dissect_t *edt _U_, const void *psi)
+{
+ guint idx = 0;
+ srt_stat_table *camel_srt_table;
+ const struct camelsrt_info_t * pi=(const struct camelsrt_info_t *)psi;
+ srt_data_t *data = (srt_data_t *)pcamel;
+ int i;
+
+ for (i=1; i<NB_CAMELSRT_CATEGORY; i++) {
+ if ( pi->bool_msginfo[i] &&
+ pi->msginfo[i].is_delta_time
+ && pi->msginfo[i].request_available
+ && !pi->msginfo[i].is_duplicate )
+ {
+ camel_srt_table = g_array_index(data->srt_array, srt_stat_table*, idx);
+ add_srt_table_data(camel_srt_table, i, &pi->msginfo[i].req_time, pinfo);
+ }
+ } /* category */
+ return 1;
+}
+
+
static char camel_number_to_char(int number)
{
if (number < 10)
@@ -7071,7 +7111,7 @@ static int dissect_CAP_U_ABORT_REASON_PDU(tvbuff_t *tvb _U_, packet_info *pinfo
/*--- End of included file: packet-camel-fn.c ---*/
-#line 374 "../../asn1/camel/packet-camel-template.c"
+#line 414 "../../asn1/camel/packet-camel-template.c"
/*--- Included file: packet-camel-table2.c ---*/
@@ -7278,7 +7318,7 @@ static int dissect_returnErrorData(proto_tree *tree, tvbuff_t *tvb, int offset,a
/*--- End of included file: packet-camel-table2.c ---*/
-#line 376 "../../asn1/camel/packet-camel-template.c"
+#line 416 "../../asn1/camel/packet-camel-template.c"
/*
* Functions needed for Hash-Table
@@ -8130,7 +8170,7 @@ void proto_reg_handoff_camel(void) {
/*--- End of included file: packet-camel-dis-tab.c ---*/
-#line 1220 "../../asn1/camel/packet-camel-template.c"
+#line 1260 "../../asn1/camel/packet-camel-template.c"
} else {
range_foreach(ssn_range, range_delete_callback);
g_free(ssn_range);
@@ -10244,7 +10284,7 @@ void proto_register_camel(void) {
"InvokeId_present", HFILL }},
/*--- End of included file: packet-camel-hfarr.c ---*/
-#line 1393 "../../asn1/camel/packet-camel-template.c"
+#line 1433 "../../asn1/camel/packet-camel-template.c"
};
/* List of subtrees */
@@ -10460,7 +10500,7 @@ void proto_register_camel(void) {
&ett_camel_InvokeId,
/*--- End of included file: packet-camel-ettarr.c ---*/
-#line 1410 "../../asn1/camel/packet-camel-template.c"
+#line 1450 "../../asn1/camel/packet-camel-template.c"
};
static ei_register_info ei[] = {
@@ -10525,5 +10565,7 @@ void proto_register_camel(void) {
/* Routine for statistic */
register_init_routine(&camelsrt_init_routine);
camel_tap=register_tap(PSNAME);
+
+ register_srt_table(proto_camel, "CAMEL", 1, camelstat_packet, camelstat_init, NULL);
}
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c
index 72acdedb37..8c64e46984 100644
--- a/epan/dissectors/packet-dcerpc.c
+++ b/epan/dissectors/packet-dcerpc.c
@@ -29,12 +29,13 @@
#include "config.h"
-
+#include <stdio.h>
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/prefs.h>
#include <epan/reassemble.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/expert.h>
#include <epan/addr_resolv.h>
#include <epan/show_exception.h>
@@ -1479,6 +1480,161 @@ dcerpc_matched_hash(gconstpointer k)
return key->frame;
}
+static gboolean
+uuid_equal(e_guid_t *uuid1, e_guid_t *uuid2)
+{
+ if( (uuid1->data1 != uuid2->data1)
+ ||(uuid1->data2 != uuid2->data2)
+ ||(uuid1->data3 != uuid2->data3)
+ ||(uuid1->data4[0] != uuid2->data4[0])
+ ||(uuid1->data4[1] != uuid2->data4[1])
+ ||(uuid1->data4[2] != uuid2->data4[2])
+ ||(uuid1->data4[3] != uuid2->data4[3])
+ ||(uuid1->data4[4] != uuid2->data4[4])
+ ||(uuid1->data4[5] != uuid2->data4[5])
+ ||(uuid1->data4[6] != uuid2->data4[6])
+ ||(uuid1->data4[7] != uuid2->data4[7]) ){
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+dcerpcstat_init(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ dcerpcstat_tap_data_t* tap_data = (dcerpcstat_tap_data_t*)get_srt_table_param_data(srt);
+ srt_stat_table *dcerpc_srt_table;
+ int i, hf_opnum;
+ dcerpc_sub_dissector *procs;
+
+ DISSECTOR_ASSERT(tap_data);
+
+ hf_opnum = dcerpc_get_proto_hf_opnum(&tap_data->uuid, tap_data->ver);
+ procs = dcerpc_get_proto_sub_dissector(&tap_data->uuid, tap_data->ver);
+
+ if(hf_opnum != -1){
+ dcerpc_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, tap_data->num_procedures, NULL, proto_registrar_get_nth(hf_opnum)->abbrev, gui_callback, gui_data, tap_data);
+ } else {
+ dcerpc_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, tap_data->num_procedures, NULL, NULL, gui_callback, gui_data, tap_data);
+ }
+
+ for(i=0;i<tap_data->num_procedures;i++){
+ int j;
+ const char *proc_name;
+
+ proc_name = "unknown";
+ for(j=0;procs[j].name;j++)
+ {
+ if (procs[j].num == i)
+ {
+ proc_name = procs[j].name;
+ }
+ }
+
+ init_srt_table_row(dcerpc_srt_table, i, proc_name);
+ }
+}
+
+static int
+dcerpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *dcerpc_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const dcerpc_info *ri = (dcerpc_info *)prv;
+ dcerpcstat_tap_data_t* tap_data;
+
+ dcerpc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ tap_data = (dcerpcstat_tap_data_t*)dcerpc_srt_table->table_specific_data;
+
+ if(!ri->call_data){
+ return 0;
+ }
+ if(!ri->call_data->req_frame){
+ /* we have not seen the request so we don't know the delta*/
+ return 0;
+ }
+ if(ri->call_data->opnum >= tap_data->num_procedures){
+ /* don't handle this since it's outside of known table */
+ return 0;
+ }
+
+ /* we are only interested in reply packets */
+ if(ri->ptype != PDU_RESP){
+ return 0;
+ }
+
+ /* we are only interested in certain program/versions */
+ if( (!uuid_equal( (&ri->call_data->uuid), (&tap_data->uuid)))
+ ||(ri->call_data->ver != tap_data->ver)){
+ return 0;
+ }
+
+ add_srt_table_data(dcerpc_srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
+
+ return 1;
+}
+
+static guint
+dcerpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
+{
+ guint pos = 0;
+ guint32 i, max_procs;
+ dcerpcstat_tap_data_t* tap_data;
+ guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
+ int major, minor;
+ guint16 ver;
+ dcerpc_sub_dissector *procs;
+
+ if (sscanf(opt_arg, ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d,%n",
+ &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos) == 13)
+ {
+ if ((major < 0) || (major > 65535)) {
+ *err = g_strdup_printf("dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535", major);
+ return pos;
+ }
+ if ((minor < 0) || (minor > 65535)) {
+ *err = g_strdup_printf("dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535", minor);
+ return pos;
+ }
+ ver = major;
+
+ tap_data = g_new0(dcerpcstat_tap_data_t, 1);
+
+ tap_data->uuid.data1 = d1;
+ tap_data->uuid.data2 = d2;
+ tap_data->uuid.data3 = d3;
+ tap_data->uuid.data4[0] = d40;
+ tap_data->uuid.data4[1] = d41;
+ tap_data->uuid.data4[2] = d42;
+ tap_data->uuid.data4[3] = d43;
+ tap_data->uuid.data4[4] = d44;
+ tap_data->uuid.data4[5] = d45;
+ tap_data->uuid.data4[6] = d46;
+ tap_data->uuid.data4[7] = d47;
+
+ procs = dcerpc_get_proto_sub_dissector(&tap_data->uuid, ver);
+ tap_data->prog = dcerpc_get_proto_name(&tap_data->uuid, ver);
+ tap_data->ver = ver;
+
+ for(i=0,max_procs=0;procs[i].name;i++)
+ {
+ if(procs[i].num>max_procs)
+ {
+ max_procs = procs[i].num;
+ }
+ }
+ tap_data->num_procedures = max_procs+1;
+
+ set_srt_table_param_data(srt, tap_data);
+ }
+ else
+ {
+ *err = g_strdup_printf("<uuid>,<major version>.<minor version>[,<filter>]");
+ }
+
+ return pos;
+}
/*
@@ -6384,6 +6540,8 @@ proto_register_dcerpc(void)
dcerpc_tap = register_tap("dcerpc");
register_decode_as(&dcerpc_da);
+
+ register_srt_table(proto_dcerpc, NULL, 1, dcerpcstat_packet, dcerpcstat_init, dcerpcstat_param);
}
void
diff --git a/epan/dissectors/packet-dcerpc.h b/epan/dissectors/packet-dcerpc.h
index 2db4d8e5ab..c9222bfb9c 100644
--- a/epan/dissectors/packet-dcerpc.h
+++ b/epan/dissectors/packet-dcerpc.h
@@ -108,6 +108,14 @@ typedef struct _dcerpc_auth_info {
tvbuff_t *auth_data;
} dcerpc_auth_info;
+typedef struct dcerpcstat_tap_data
+{
+ const char *prog;
+ e_guid_t uuid;
+ guint16 ver;
+ int num_procedures;
+} dcerpcstat_tap_data_t;
+
/* Private data passed to subdissectors from the main DCERPC dissector.
* One unique instance of this structure is created for each
* DCERPC request/response transaction when we see the initial request
diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c
index 8f2045170c..b4e3e4a4ae 100644
--- a/epan/dissectors/packet-diameter.c
+++ b/epan/dissectors/packet-diameter.c
@@ -48,6 +48,7 @@
#include <epan/sminmpec.h>
#include <epan/expert.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/exported_pdu.h>
#include <epan/diam_dict.h>
#include <epan/sctpppids.h>
@@ -365,6 +366,67 @@ compare_avps(const void *a, const void *b)
return 0;
}
+static GHashTable* diameterstat_cmd_str_hash = NULL;
+#define DIAMETER_NUM_PROCEDURES 1
+
+static void
+diameterstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *diameter_srt_table;
+ int* idx;
+
+ /* XXX - This is a hack/workaround support so reseting/freeing parameters at the dissector
+ level doesn't need to be supported. */
+ if (diameterstat_cmd_str_hash != NULL)
+ {
+ g_hash_table_destroy(diameterstat_cmd_str_hash);
+ }
+
+ idx = (int *)g_malloc(sizeof(int));
+ *idx = 0;
+ diameterstat_cmd_str_hash = g_hash_table_new(g_str_hash,g_str_equal);
+ g_hash_table_insert(diameterstat_cmd_str_hash, (gchar *)"Unknown", idx);
+
+ /** @todo the filter to use in stead of NULL is "diameter.cmd.code"
+ * to enable the filter popup in the service response time dalouge
+ * Note to make it work the command code must be stored rather than the
+ * index.
+ */
+ diameter_srt_table = init_srt_table("Diameter Requests", NULL, srt_array, DIAMETER_NUM_PROCEDURES, NULL, NULL, gui_callback, gui_data, NULL);
+ init_srt_table_row(diameter_srt_table, 0, "Unknown");
+}
+
+static int
+diameterstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *diameter_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const diameter_req_ans_pair_t *diameter=(const diameter_req_ans_pair_t *)prv;
+ int* idx = NULL;
+
+ /* Process only answers where corresponding request is found.
+ * Unpaired daimeter messages are currently not supported by statistics.
+ * Return 0, since redraw is not needed. */
+ if(!diameter || diameter->processing_request || !diameter->req_frame)
+ return 0;
+
+ diameter_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+
+ idx = (int*) g_hash_table_lookup(diameterstat_cmd_str_hash, diameter->cmd_str);
+ if (idx == NULL) {
+ idx = (int *)g_malloc(sizeof(int));
+ *idx = (int) g_hash_table_size(diameterstat_cmd_str_hash);
+ g_hash_table_insert(diameterstat_cmd_str_hash, (gchar*) diameter->cmd_str, idx);
+ init_srt_table_row(diameter_srt_table, *idx, (const char*) diameter->cmd_str);
+ }
+
+ add_srt_table_data(diameter_srt_table, *idx, &diameter->req_time, pinfo);
+
+ return 1;
+}
+
+
/* Special decoding of some AVPs */
static int
@@ -2200,6 +2262,8 @@ real_proto_register_diameter(void)
/* Register tap */
diameter_tap = register_tap("diameter");
+
+ register_srt_table(proto_diameter, NULL, 1, diameterstat_packet, diameterstat_init, NULL);
}
void
diff --git a/epan/dissectors/packet-fc.c b/epan/dissectors/packet-fc.c
index 900a19ac47..a4c3ef2307 100644
--- a/epan/dissectors/packet-fc.c
+++ b/epan/dissectors/packet-fc.c
@@ -33,6 +33,7 @@
#include <epan/reassemble.h>
#include <epan/conversation_table.h>
#include <epan/etypes.h>
+#include <epan/srt_table.h>
#include "packet-fc.h"
#include "packet-fclctl.h"
#include "packet-fcbls.h"
@@ -253,6 +254,47 @@ fc_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const
return 1;
}
+#define FC_NUM_PROCEDURES 256
+
+static void
+fcstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *fc_srt_table;
+ guint32 i;
+
+ fc_srt_table = init_srt_table("Fibre Channel Types", NULL, srt_array, FC_NUM_PROCEDURES, NULL, NULL, gui_callback, gui_data, NULL);
+ for (i = 0; i < FC_NUM_PROCEDURES; i++)
+ {
+ gchar* tmp_str = val_to_str_wmem(NULL, i, fc_fc4_val, "Unknown(0x%02x)");
+ init_srt_table_row(fc_srt_table, i, tmp_str);
+ wmem_free(NULL, tmp_str);
+ }
+}
+
+static int
+fcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *fc_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const fc_hdr *fc=(const fc_hdr *)prv;
+
+ /* we are only interested in reply packets */
+ if(!(fc->fctl&FC_FCTL_EXCHANGE_RESPONDER)){
+ return 0;
+ }
+ /* if we havnt seen the request, just ignore it */
+ if ( (!fc->fc_ex) || (fc->fc_ex->first_exchange_frame==0) ){
+ return 0;
+ }
+
+ fc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(fc_srt_table, fc->type, &fc->fc_ex->fc_time, pinfo);
+
+ return 1;
+}
+
+
const value_string fc_fc4_val[] = {
{FC_TYPE_BLS, "Basic Link Svc"},
{FC_TYPE_ELS, "Ext Link Svc"},
@@ -1544,6 +1586,7 @@ proto_register_fc(void)
fcsof_handle = register_dissector("fcsof", dissect_fcsof, proto_fcsof);
register_conversation_table(proto_fc, TRUE, fc_conversation_packet, fc_hostlist_packet);
+ register_srt_table(proto_fc, NULL, 1, fcstat_packet, fcstat_init, NULL);
}
diff --git a/epan/dissectors/packet-gtp.c b/epan/dissectors/packet-gtp.c
index 5270cf93bf..37de190955 100644
--- a/epan/dissectors/packet-gtp.c
+++ b/epan/dissectors/packet-gtp.c
@@ -59,6 +59,7 @@
#include <epan/sminmpec.h>
#include <epan/asn1.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/to_str.h>
#include "packet-ppp.h"
#include "packet-radius.h"
@@ -1767,6 +1768,61 @@ static const value_string tft_code_type[] = {
{0, NULL}
};
+static void
+gtpstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *gtp_srt_table;
+
+ gtp_srt_table = init_srt_table("GTP Requests", NULL, srt_array, 4, NULL, NULL, gui_callback, gui_data, NULL);
+ init_srt_table_row(gtp_srt_table, 0, "Echo");
+ init_srt_table_row(gtp_srt_table, 1, "Create PDP context");
+ init_srt_table_row(gtp_srt_table, 2, "Update PDP context");
+ init_srt_table_row(gtp_srt_table, 3, "Delete PDP context");
+}
+
+static int
+gtpstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *gtp_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const gtp_msg_hash_t *gtp=(const gtp_msg_hash_t *)prv;
+ int idx=0;
+
+ /* we are only interested in reply packets */
+ if(gtp->is_request){
+ return 0;
+ }
+ /* if we have not seen the request, just ignore it */
+ if(!gtp->req_frame){
+ return 0;
+ }
+
+ /* Only use the commands we know how to handle, this is not a comprehensive list */
+ /* Redoing the message indexing is bit reduntant, */
+ /* but using message type as such would yield a long gtp_srt_table. */
+ /* Only a fraction of the messages are matchable req/resp pairs, */
+ /* it just doesn't feel feasible. */
+
+ switch(gtp->msgtype){
+ case GTP_MSG_ECHO_REQ: idx=0;
+ break;
+ case GTP_MSG_CREATE_PDP_REQ: idx=1;
+ break;
+ case GTP_MSG_UPDATE_PDP_REQ: idx=2;
+ break;
+ case GTP_MSG_DELETE_PDP_REQ: idx=3;
+ break;
+ default:
+ return 0;
+ }
+
+ gtp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(gtp_srt_table, idx, &gtp->req_time, pinfo);
+
+ return 1;
+}
+
static dissector_handle_t ip_handle;
static dissector_handle_t ipv6_handle;
@@ -9734,6 +9790,8 @@ proto_register_gtp(void)
register_init_routine(gtp_reinit);
gtp_tap = register_tap("gtp");
gtpv1_tap = register_tap("gtpv1");
+
+ register_srt_table(proto_gtp, NULL, 1, gtpstat_packet, gtpstat_init, NULL);
}
/* TS 132 295 V9.0.0 (2010-02)
* 5.1.3 Port usage
diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c
index 1533178f25..7366cb31d3 100644
--- a/epan/dissectors/packet-ldap.c
+++ b/epan/dissectors/packet-ldap.c
@@ -95,6 +95,7 @@
#include <epan/conversation.h>
#include <epan/prefs.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/oids.h>
#include <epan/strutil.h>
#include <epan/show_exception.h>
@@ -342,7 +343,7 @@ static int hf_ldap_graceAuthNsRemaining = -1; /* INTEGER_0_maxInt */
static int hf_ldap_error = -1; /* T_error */
/*--- End of included file: packet-ldap-hf.c ---*/
-#line 192 "../../asn1/ldap/packet-ldap-template.c"
+#line 193 "../../asn1/ldap/packet-ldap-template.c"
/* Initialize the subtree pointers */
static gint ett_ldap = -1;
@@ -414,7 +415,7 @@ static gint ett_ldap_PasswordPolicyResponseValue = -1;
static gint ett_ldap_T_warning = -1;
/*--- End of included file: packet-ldap-ett.c ---*/
-#line 204 "../../asn1/ldap/packet-ldap-template.c"
+#line 205 "../../asn1/ldap/packet-ldap-template.c"
static expert_field ei_ldap_exceeded_filter_length = EI_INIT;
static expert_field ei_ldap_too_many_filter_elements = EI_INIT;
@@ -513,6 +514,59 @@ static const value_string netlogon_opcode_vals[] = {
{ 0, NULL }
};
+#define LDAP_NUM_PROCEDURES 24
+
+static void
+ldapstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *ldap_srt_table;
+ guint32 i;
+
+ ldap_srt_table = init_srt_table("LDAP Commands", NULL, srt_array, LDAP_NUM_PROCEDURES, NULL, "ldap.protocolOp", gui_callback, gui_data, NULL);
+ for (i = 0; i < LDAP_NUM_PROCEDURES; i++)
+ {
+ init_srt_table_row(ldap_srt_table, i, val_to_str_const(i, ldap_procedure_names, "<unknown>"));
+ }
+}
+
+static int
+ldapstat_packet(void *pldap, packet_info *pinfo, epan_dissect_t *edt _U_, const void *psi)
+{
+ guint i = 0;
+ srt_stat_table *ldap_srt_table;
+ const ldap_call_response_t *ldap=(const ldap_call_response_t *)psi;
+ srt_data_t *data = (srt_data_t *)pldap;
+
+ /* we are only interested in reply packets */
+ if(ldap->is_request){
+ return 0;
+ }
+ /* if we havnt seen the request, just ignore it */
+ if(!ldap->req_frame){
+ return 0;
+ }
+
+ /* only use the commands we know how to handle */
+ switch(ldap->protocolOpTag){
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_SEARCH:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_DELETE:
+ case LDAP_REQ_MODRDN:
+ case LDAP_REQ_COMPARE:
+ case LDAP_REQ_EXTENDED:
+ break;
+ default:
+ return 0;
+ }
+
+ ldap_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+
+ add_srt_table_data(ldap_srt_table, ldap->protocolOpTag, &ldap->req_time, pinfo);
+ return 1;
+}
+
/*
* Data structure attached to a conversation, giving authentication
* information from a bind request.
@@ -3781,7 +3835,7 @@ static int dissect_PasswordPolicyResponseValue_PDU(tvbuff_t *tvb _U_, packet_inf
/*--- End of included file: packet-ldap-fn.c ---*/
-#line 866 "../../asn1/ldap/packet-ldap-template.c"
+#line 920 "../../asn1/ldap/packet-ldap-template.c"
static int dissect_LDAPMessage_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ldap_conv_info_t *ldap_info) {
int offset = 0;
@@ -5647,7 +5701,7 @@ void proto_register_ldap(void) {
NULL, HFILL }},
/*--- End of included file: packet-ldap-hfarr.c ---*/
-#line 2163 "../../asn1/ldap/packet-ldap-template.c"
+#line 2217 "../../asn1/ldap/packet-ldap-template.c"
};
/* List of subtrees */
@@ -5721,7 +5775,7 @@ void proto_register_ldap(void) {
&ett_ldap_T_warning,
/*--- End of included file: packet-ldap-ettarr.c ---*/
-#line 2177 "../../asn1/ldap/packet-ldap-template.c"
+#line 2231 "../../asn1/ldap/packet-ldap-template.c"
};
/* UAT for header fields */
static uat_field_t custom_attribute_types_uat_fields[] = {
@@ -5796,6 +5850,7 @@ void proto_register_ldap(void) {
ldap_name_dissector_table = register_dissector_table("ldap.name", "LDAP Attribute Type Dissectors", FT_STRING, BASE_NONE);
+ register_srt_table(proto_ldap, NULL, 1, ldapstat_packet, ldapstat_init, NULL);
}
@@ -5887,7 +5942,7 @@ proto_reg_handoff_ldap(void)
/*--- End of included file: packet-ldap-dis-tab.c ---*/
-#line 2326 "../../asn1/ldap/packet-ldap-template.c"
+#line 2381 "../../asn1/ldap/packet-ldap-template.c"
}
diff --git a/epan/dissectors/packet-ncp.c b/epan/dissectors/packet-ncp.c
index 85ebe0b3a8..3caabaedea 100644
--- a/epan/dissectors/packet-ncp.c
+++ b/epan/dissectors/packet-ncp.c
@@ -45,6 +45,7 @@
#include <epan/packet.h>
#include <epan/prefs.h>
+#include <epan/srt_table.h>
#include "packet-ipx.h"
#include "packet-tcp.h"
#include "packet-ncp-int.h"
@@ -190,6 +191,253 @@ static const value_string ncp_oplock_vals[] = {
{ 0, NULL }
};
+enum ncp_table_values
+{
+ NCP_NCP_SRT_TABLE_INDEX = 0,
+ NCP_NDS_SRT_TABLE_INDEX,
+ NCP_FUNC_SRT_TABLE_INDEX,
+ NCP_SSS_SRT_TABLE_INDEX,
+ NCP_NMAS_SRT_TABLE_INDEX,
+ NCP_SUB17_SRT_TABLE_INDEX,
+ NCP_SUB21_SRT_TABLE_INDEX,
+ NCP_SUB22_SRT_TABLE_INDEX,
+ NCP_SUB23_SRT_TABLE_INDEX,
+ NCP_SUB32_SRT_TABLE_INDEX,
+ NCP_SUB34_SRT_TABLE_INDEX,
+ NCP_SUB35_SRT_TABLE_INDEX,
+ NCP_SUB36_SRT_TABLE_INDEX,
+ NCP_SUB86_SRT_TABLE_INDEX,
+ NCP_SUB87_SRT_TABLE_INDEX,
+ NCP_SUB89_SRT_TABLE_INDEX,
+ NCP_SUB90_SRT_TABLE_INDEX,
+ NCP_SUB92_SRT_TABLE_INDEX,
+ NCP_SUB94_SRT_TABLE_INDEX,
+ NCP_SUB104_SRT_TABLE_INDEX,
+ NCP_SUB111_SRT_TABLE_INDEX,
+ NCP_SUB114_SRT_TABLE_INDEX,
+ NCP_SUB123_SRT_TABLE_INDEX,
+ NCP_SUB131_SRT_TABLE_INDEX,
+
+};
+
+#define NCP_NUM_PROCEDURES 0
+
+static void
+ncpstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ /* Initialize all of the SRT tables with 0 rows. That way we can "filter" the drawing
+ function to only output tables with rows > 0 */
+
+ init_srt_table("NCP", "Groups", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.group", gui_callback, gui_data, NULL);
+
+ /* NDS Verbs */
+ init_srt_table("NDS Verbs", "NDS", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.ndsverb", gui_callback, gui_data, NULL);
+
+ /* NCP Functions */
+ init_srt_table("NCP Functions without Subfunctions", "Functions", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func", gui_callback, gui_data, NULL);
+
+ /* Secret Store Verbs */
+ init_srt_table("Secret Store Verbs", "SSS", srt_array, NCP_NUM_PROCEDURES, NULL, "sss.subverb", gui_callback, gui_data, NULL);
+
+ /* NMAS Verbs */
+ init_srt_table("NMAS Verbs", "NMAS", srt_array, NCP_NUM_PROCEDURES, NULL, "nmas.subverb", gui_callback, gui_data, NULL);
+
+ /* NCP Subfunctions */
+ init_srt_table("Subfunctions for NCP 17", "17", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==17 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 21", "21", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==21 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 22", "22", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==22 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 23", "23", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==23 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 32", "32", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==32 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 34", "34", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==34 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 35", "35", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==35 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 36", "36", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==36 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 86", "86", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==86 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 87", "87", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==87 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 89 (Extended NCP's with UTF8 Support)", "89", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==89 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 90", "90", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==90 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 92 (Secret Store Services)", "92", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==92 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 94 (Novell Modular Authentication Services)", "94", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==94 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 104", "104", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==104 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 111", "111", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==111 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 114", "114", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==114 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 123", "123", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==123 && ncp.subfunc", gui_callback, gui_data, NULL);
+ init_srt_table("Subfunctions for NCP 131", "131", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==131 && ncp.subfunc", gui_callback, gui_data, NULL);
+}
+
+static int
+ncpstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *ncp_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const ncp_req_hash_value *request_val=(const ncp_req_hash_value *)prv;
+ gchar* tmp_str;
+
+ /* if we haven't seen the request, just ignore it */
+ if(!request_val || request_val->ncp_rec==0){
+ return 0;
+ }
+
+ /* By Group */
+ tmp_str = val_to_str_wmem(NULL, request_val->ncp_rec->group, ncp_group_vals, "Unknown(%u)");
+ i = NCP_NCP_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, request_val->ncp_rec->group, tmp_str);
+ wmem_free(NULL, tmp_str);
+ add_srt_table_data(ncp_srt_table, request_val->ncp_rec->group, &request_val->req_frame_time, pinfo);
+ /* By NCP number without subfunction*/
+ if (request_val->ncp_rec->subfunc==0) {
+ i = NCP_FUNC_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, request_val->ncp_rec->func, request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, request_val->ncp_rec->func, &request_val->req_frame_time, pinfo);
+ }
+ /* By Subfunction number */
+ if(request_val->ncp_rec->subfunc!=0){
+ if (request_val->ncp_rec->func==17) {
+ i = NCP_SUB17_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==21) {
+ i = NCP_SUB21_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==22) {
+ i = NCP_SUB22_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==23) {
+ i = NCP_SUB23_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==32) {
+ i = NCP_SUB32_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==34) {
+ i = NCP_SUB34_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==35) {
+ i = NCP_SUB35_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==36) {
+ i = NCP_SUB36_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==86) {
+ i = NCP_SUB86_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==87) {
+ i = NCP_SUB87_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==89) {
+ i = NCP_SUB89_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==90) {
+ i = NCP_SUB90_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==92) {
+ i = NCP_SUB92_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==94) {
+ i = NCP_SUB94_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==104) {
+ i = NCP_SUB104_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==111) {
+ i = NCP_SUB111_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==114) {
+ i = NCP_SUB114_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==123) {
+ i = NCP_SUB123_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ if (request_val->ncp_rec->func==131) {
+ i = NCP_SUB131_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
+ add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
+ }
+ }
+ /* By NDS verb */
+ if (request_val->ncp_rec->func==0x68) {
+ tmp_str = val_to_str_wmem(NULL, request_val->nds_request_verb, ncp_nds_verb_vals, "Unknown(%u)");
+ i = NCP_NDS_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->nds_request_verb), tmp_str);
+ add_srt_table_data(ncp_srt_table, (request_val->nds_request_verb), &request_val->req_frame_time, pinfo);
+ wmem_free(NULL, tmp_str);
+ }
+ if (request_val->ncp_rec->func==0x5c) {
+ tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, sss_verb_enum, "Unknown(%u)");
+ i = NCP_SSS_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
+ add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
+ wmem_free(NULL, tmp_str);
+ }
+ if (request_val->ncp_rec->func==0x5e) {
+ tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, nmas_subverb_enum, "Unknown(%u)");
+ i = NCP_NMAS_SRT_TABLE_INDEX;
+ ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
+ add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
+ wmem_free(NULL, tmp_str);
+ }
+ return 1;
+}
+
+
/* Conversation Struct so we can detect NCP server sessions */
typedef struct {
@@ -1091,6 +1339,7 @@ proto_register_ncp(void)
expert_module_t* expert_ncp;
proto_ncp = proto_register_protocol("NetWare Core Protocol", "NCP", "ncp");
+
proto_register_field_array(proto_ncp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_ncp = expert_register_protocol(proto_ncp);
@@ -1137,6 +1386,7 @@ proto_register_ncp(void)
register_postseq_cleanup_routine(&mncp_postseq_cleanup);
register_conversation_table(proto_ncp, FALSE, ncp_conversation_packet, ncp_hostlist_packet);
+ register_srt_table(proto_ncp, "ncp_srt", 24, ncpstat_packet, ncpstat_init, NULL);
}
void
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
diff --git a/epan/dissectors/packet-rpc.h b/epan/dissectors/packet-rpc.h
index ffe41686cb..187445fe32 100644
--- a/epan/dissectors/packet-rpc.h
+++ b/epan/dissectors/packet-rpc.h
@@ -222,5 +222,13 @@ typedef struct _rpc_proc_info_value {
*/
WS_DLL_PUBLIC GHashTable *rpc_procs;
+typedef struct rpcstat_tap_data
+{
+ const char *prog;
+ guint32 program;
+ guint32 version;
+ int num_procedures;
+} rpcstat_tap_data_t;
+
#endif /* packet-rpc.h */
diff --git a/epan/dissectors/packet-scsi.c b/epan/dissectors/packet-scsi.c
index de1ce6f09e..137d39644f 100644
--- a/epan/dissectors/packet-scsi.c
+++ b/epan/dissectors/packet-scsi.c
@@ -79,11 +79,13 @@
*/
#include "config.h"
+#include <stdio.h>
#include <epan/packet.h>
#include <epan/to_str.h>
#include <epan/prefs.h>
#include <epan/conversation.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/reassemble.h>
#include <epan/expert.h>
#include "packet-scsi.h"
@@ -936,6 +938,110 @@ static const value_string scsi_log_pc_val[] = {
{0, NULL},
};
+#define SCSI_NUM_PROCEDURES 256
+typedef struct scsistat_tap_data
+{
+ guint8 cmdset;
+ const char *prog;
+ value_string_ext *cdbnames_ext;
+ const char *hf_name;
+} scsistat_tap_data_t;
+
+static void
+scsistat_init(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ scsistat_tap_data_t* tap_data = (scsistat_tap_data_t*)get_srt_table_param_data(srt);
+ srt_stat_table *scsi_srt_table;
+ guint32 i;
+
+ DISSECTOR_ASSERT(tap_data);
+
+ scsi_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, SCSI_NUM_PROCEDURES, NULL, tap_data->hf_name, gui_callback, gui_data, tap_data);
+ for (i = 0; i < SCSI_NUM_PROCEDURES; i++)
+ {
+ init_srt_table_row(scsi_srt_table, i, val_to_str_ext_const(i, tap_data->cdbnames_ext, "Unknown-0x%02x"));
+ }
+}
+
+static int
+scsistat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *scsi_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const scsi_task_data_t *ri = (const scsi_task_data_t *)prv;
+ scsistat_tap_data_t* tap_data;
+
+ scsi_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ tap_data = (scsistat_tap_data_t*)scsi_srt_table->table_specific_data;
+
+ /* we are only interested in response packets */
+ if (ri->type != SCSI_PDU_TYPE_RSP) {
+ return 0;
+ }
+ /* we are only interested in a specific commandset */
+ if ( (!ri->itl) || ((ri->itl->cmdset&SCSI_CMDSET_MASK) != tap_data->cmdset) ) {
+ return 0;
+ }
+ /* check that the opcode looks sane */
+ if ( (!ri->itlq) || (ri->itlq->scsi_opcode > 255) ) {
+ return 0;
+ }
+
+ add_srt_table_data(scsi_srt_table, ri->itlq->scsi_opcode, &ri->itlq->fc_time, pinfo);
+ return 1;
+}
+
+static guint
+scsistat_param(register_srt_t* srt, const char* opt_arg, char** err)
+{
+ guint pos = 0;
+ int program;
+ scsistat_tap_data_t* tap_data;
+
+ if (sscanf(opt_arg, ",%d,%n", &program, &pos) == 1)
+ {
+ tap_data = g_new0(scsistat_tap_data_t, 1);
+ tap_data->cmdset = (guint8)program;
+
+ switch(program){
+ case SCSI_DEV_SBC:
+ tap_data->prog = "SBC (disk)";
+ tap_data->cdbnames_ext = &scsi_sbc_vals_ext;
+ tap_data->hf_name = "scsi_sbc.opcode";
+ break;
+ case SCSI_DEV_SSC:
+ tap_data->prog = "SSC (tape)";
+ tap_data->cdbnames_ext = &scsi_ssc_vals_ext;
+ tap_data->hf_name = "scsi_ssc.opcode";
+ break;
+ case SCSI_DEV_CDROM:
+ tap_data->prog = "MMC (cd/dvd)";
+ tap_data->cdbnames_ext = &scsi_mmc_vals_ext;
+ tap_data->hf_name = "scsi_mmc.opcode";
+ break;
+ case SCSI_DEV_SMC:
+ tap_data->prog = "SMC (tape robot)";
+ tap_data->cdbnames_ext = &scsi_smc_vals_ext;
+ tap_data->hf_name = "scsi_smc.opcode";
+ break;
+ case SCSI_DEV_OSD:
+ tap_data->prog = "OSD (object based)";
+ tap_data->cdbnames_ext = &scsi_osd_vals_ext;
+ tap_data->hf_name = "scsi_osd.opcode";
+ break;
+ }
+
+ set_srt_table_param_data(srt, tap_data);
+ }
+ else
+ {
+ *err = g_strdup_printf("<cmdset>[,<filter>]");
+ }
+
+ return pos;
+}
+
/* TapeAlert page : read warning flag */
static void
log_parameter_2e_0001(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
@@ -7567,6 +7673,8 @@ proto_register_scsi(void)
"Whether fragmented SCSI DATA IN/OUT transfers should be reassembled",
&scsi_defragment);
register_init_routine(scsi_defragment_init);
+
+ register_srt_table(proto_scsi, NULL, 1, scsistat_packet, scsistat_init, scsistat_param);
}
void
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c
index 614cf0900b..1f1286a1a4 100644
--- a/epan/dissectors/packet-smb.c
+++ b/epan/dissectors/packet-smb.c
@@ -32,6 +32,7 @@
#include <epan/prefs.h>
#include <epan/reassemble.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/expert.h>
#include <epan/to_str.h>
@@ -883,6 +884,75 @@ static proto_tree *top_tree_global = NULL; /* ugly */
static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *smb_tree, guint8 cmd, gboolean first_pdu, smb_info_t *si);
+#define SMB_NUM_PROCEDURES 256
+#define SMB_SRT_TABLE_INDEX 0
+#define TRANS2_SRT_TABLE_INDEX 1
+#define NT_SRT_TABLE_INDEX 2
+
+static void
+smbstat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *smb_srt_table;
+ srt_stat_table *trans2_srt_table;
+ srt_stat_table *nt_srt_table;
+ guint32 i;
+
+ smb_srt_table = init_srt_table("SMB Commands", NULL, srt_array, SMB_NUM_PROCEDURES, "Commands", "smb.cmd", gui_callback, gui_data, NULL);
+ trans2_srt_table = init_srt_table("Transaction2 Sub-Commands", NULL, srt_array, SMB_NUM_PROCEDURES, "Transaction2 Commands", "smb.trans2.cmd", gui_callback, gui_data, NULL);
+ nt_srt_table = init_srt_table("NT Transaction Sub-Commands", NULL, srt_array, SMB_NUM_PROCEDURES, "NT Transaction Sub-Commands", "smb.nt.function", gui_callback, gui_data, NULL);
+ for (i = 0; i < SMB_NUM_PROCEDURES; i++)
+ {
+ init_srt_table_row(smb_srt_table, i, val_to_str_ext_const(i, &smb_cmd_vals_ext, "<unknown>"));
+ init_srt_table_row(trans2_srt_table, i, val_to_str_ext_const(i, &trans2_cmd_vals_ext, "<unknown>"));
+ init_srt_table_row(nt_srt_table, i, val_to_str_ext_const(i, &nt_cmd_vals_ext, "<unknown>"));
+ }
+}
+
+static int
+smbstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *smb_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const smb_info_t *si = (const smb_info_t *)prv;
+
+ /* we are only interested in reply packets */
+ if (si->request) {
+ return 0;
+ }
+ /* if we havnt seen the request, just ignore it */
+ if (!si->sip) {
+ return 0;
+ }
+
+ if (si->cmd == 0xA0 && si->sip->extra_info_type == SMB_EI_NTI) {
+ smb_nt_transact_info_t *sti = (smb_nt_transact_info_t *)si->sip->extra_info;
+
+ /*nt transaction*/
+ if (sti) {
+ i = NT_SRT_TABLE_INDEX;
+ smb_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(smb_srt_table, sti->subcmd, &si->sip->req_time, pinfo);
+ }
+ } else if (si->cmd == 0x32 && si->sip->extra_info_type == SMB_EI_T2I) {
+ smb_transact2_info_t *st2i = (smb_transact2_info_t *)si->sip->extra_info;
+
+ /*transaction2*/
+ if (st2i) {
+ i = TRANS2_SRT_TABLE_INDEX;
+ smb_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(smb_srt_table, st2i->subcmd, &si->sip->req_time, pinfo);
+ }
+ } else {
+ i = SMB_SRT_TABLE_INDEX;
+ smb_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(smb_srt_table, si->cmd, &si->sip->req_time, pinfo);
+ }
+
+ return 1;
+
+}
+
/*
* Macros for use in the main dissector routines for an SMB.
*/
@@ -20463,6 +20533,8 @@ proto_register_smb(void)
smb_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
register_dissector("smb", dissect_smb, proto_smb);
+
+ register_srt_table(proto_smb, NULL, 3, smbstat_packet, smbstat_init, NULL);
}
void
diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c
index 0d8c749b08..c5afb95ce0 100644
--- a/epan/dissectors/packet-smb2.c
+++ b/epan/dissectors/packet-smb2.c
@@ -35,6 +35,7 @@
#include <epan/prefs.h>
#include <epan/expert.h>
#include <epan/tap.h>
+#include <epan/srt_table.h>
#include <epan/aftypes.h>
#include <epan/to_str.h>
#include <epan/asn1.h>
@@ -578,6 +579,53 @@ static const value_string smb2_negotiate_context_types[] = {
{ 0, NULL }
};
+#define SMB2_NUM_PROCEDURES 256
+
+static void
+smb2stat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *smb2_srt_table;
+ guint32 i;
+
+ smb2_srt_table = init_srt_table("SMB2", NULL, srt_array, SMB2_NUM_PROCEDURES, "Commands", "smb2.cmd", gui_callback, gui_data, NULL);
+ for (i = 0; i < SMB2_NUM_PROCEDURES; i++)
+ {
+ init_srt_table_row(smb2_srt_table, i, val_to_str_ext_const(i, &smb2_cmd_vals_ext, "<unknown>"));
+ }
+}
+
+static int
+smb2stat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *smb2_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const smb2_info_t *si=(const smb2_info_t *)prv;
+
+ /* we are only interested in response packets */
+ if(!(si->flags&SMB2_FLAGS_RESPONSE)){
+ return 0;
+ }
+ /* if we haven't seen the request, just ignore it */
+ if(!si->saved){
+ return 0;
+ }
+
+ /* SMB2 SRT can be very inaccurate in the presence of retransmissions. Retransmitted responses
+ * not only add additional (bogus) transactions but also the latency associated with them.
+ * This can greatly inflate the maximum and average SRT stats especially in the case of
+ * retransmissions triggered by the expiry of the rexmit timer (RTOs). Only calculating SRT
+ * for the last received response accomplishes this goal without requiring the TCP pref
+ * "Do not call subdissectors for error packets" to be set. */
+ if ((si->saved->frame_req == 0) || (si->saved->frame_res != pinfo->fd->num))
+ return 0;
+
+ smb2_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(smb2_srt_table, si->opcode, &si->saved->req_time, pinfo);
+ return 1;
+}
+
+
static const gint8 zeros[NTLMSSP_KEY_LEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
/* ExportObject preferences variable */
@@ -8724,6 +8772,7 @@ proto_register_smb2(void)
smb2_tap = register_tap("smb2");
smb2_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
+ register_srt_table(proto_smb2, NULL, 1, smb2stat_packet, smb2stat_init, NULL);
}
void
diff --git a/epan/srt_table.c b/epan/srt_table.c
new file mode 100644
index 0000000000..2fe4bafb35
--- /dev/null
+++ b/epan/srt_table.c
@@ -0,0 +1,322 @@
+/* srt_table.c
+ * Helper routines common to all SRT taps.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "packet_info.h"
+#include "proto.h"
+#include "srt_table.h"
+
+struct register_srt {
+ int proto_id; /* protocol id (0-indexed) */
+ const char* tap_listen_str; /* string used in register_tap_listener (NULL to use protocol name) */
+ int max_tables; /* Maximum number of tables expected (used by GUI to determine how to display tables) */
+ tap_packet_cb srt_func; /* function to be called for new incoming packets for SRT */
+ srt_init_cb srt_init; /* function to create dissector SRT tables */
+ srt_param_handler_cb param_cb; /* function to parse parameters of optional arguments of tap string */
+ void* param_data; /* Storage for tap parameter data */
+};
+
+int get_srt_proto_id(register_srt_t* srt)
+{
+ if (!srt) {
+ return -1;
+ }
+ return srt->proto_id;
+}
+
+const char* get_srt_tap_listener_name(register_srt_t* srt)
+{
+ return srt->tap_listen_str;
+}
+
+int get_srt_max_tables(register_srt_t* srt)
+{
+ return srt->max_tables;
+}
+
+tap_packet_cb get_srt_packet_func(register_srt_t* srt)
+{
+ return srt->srt_func;
+}
+
+void set_srt_table_param_data(register_srt_t* srt, void* data)
+{
+ srt->param_data = data;
+}
+
+void* get_srt_table_param_data(register_srt_t* srt)
+{
+ return srt->param_data;
+}
+
+void
+free_srt_table_data(srt_stat_table *rst)
+{
+ int i;
+
+ for(i=0;i<rst->num_procs;i++){
+ g_free(rst->procedures[i].procedure);
+ rst->procedures[i].procedure=NULL;
+ }
+ g_free(rst->filter_string);
+ rst->filter_string=NULL;
+ g_free(rst->procedures);
+ rst->procedures=NULL;
+ rst->num_procs=0;
+}
+
+void free_srt_table(register_srt_t *srt, GArray* srt_array, srt_gui_free_cb gui_callback, void *callback_data)
+{
+ guint i = 0;
+ srt_stat_table *srt_table;
+
+ for (i = 0; i < srt_array->len; i++)
+ {
+ srt_table = g_array_index(srt_array, srt_stat_table*, i);
+
+ /* Give GUI the first crack at it before we clean up */
+ if (gui_callback)
+ gui_callback(srt_table, callback_data);
+
+ free_srt_table_data(srt_table);
+ }
+
+ /* Clear the tables */
+ g_array_set_size(srt_array, 0);
+
+ /* Clear out any possible parameter data */
+ g_free(srt->param_data);
+ srt->param_data = NULL;
+}
+
+static void reset_srt_table_data(srt_stat_table *rst)
+{
+ int i;
+
+ for(i=0;i<rst->num_procs;i++){
+ time_stat_init(&rst->procedures[i].stats);
+ }
+}
+
+void reset_srt_table(GArray* srt_array, srt_gui_reset_cb gui_callback, void *callback_data)
+{
+ guint i = 0;
+ srt_stat_table *srt_table;
+
+ for (i = 0; i < srt_array->len; i++)
+ {
+ srt_table = g_array_index(srt_array, srt_stat_table*, i);
+
+ /* Give GUI the first crack at it before we clean up */
+ if (gui_callback)
+ gui_callback(srt_table, callback_data);
+
+ reset_srt_table_data(srt_table);
+ }
+}
+
+static GSList *registered_srt_tables = NULL;
+
+register_srt_t* get_srt_table_by_name(const char* name)
+{
+ guint i, size = g_slist_length(registered_srt_tables);
+ register_srt_t* srt;
+ GSList *slist;
+
+ for (i = 0; i < size; i++) {
+ slist = g_slist_nth(registered_srt_tables, i);
+ srt = (register_srt_t*)slist->data;
+
+ if (strcmp(name, proto_get_protocol_filter_name(srt->proto_id)) == 0)
+ return srt;
+ }
+
+ return NULL;
+}
+
+gchar* srt_table_get_tap_string(register_srt_t* srt)
+{
+ GString *cmd_str = g_string_new(proto_get_protocol_filter_name(srt->proto_id));
+ g_string_append(cmd_str, ",srt");
+ return g_string_free(cmd_str, FALSE);
+}
+
+void srt_table_get_filter(register_srt_t* srt, const char *opt_arg, const char **filter, char** err)
+{
+ gchar* cmd_str = srt_table_get_tap_string(srt);
+ guint len = strlen(cmd_str);
+ guint pos = len;
+ *filter=NULL;
+ *err = NULL;
+
+ if(!strncmp(opt_arg, cmd_str, len))
+ {
+ if (srt->param_cb != NULL)
+ {
+ pos = srt->param_cb(srt, opt_arg + len, err);
+ if (*err != NULL)
+ return;
+
+ if (pos > 0)
+ pos += len;
+ }
+ else
+ {
+ pos++; /* Adjust for comma */
+ }
+
+ if (opt_arg[pos] == ',')
+ {
+ *filter = opt_arg + pos;
+ }
+ }
+
+ g_free(cmd_str);
+}
+
+void srt_table_dissector_init(register_srt_t* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void *callback_data)
+{
+ srt->srt_init(srt, srt_array, gui_callback, callback_data);
+}
+
+static gint
+insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
+{
+ const register_srt_t *a = (register_srt_t *)aparam;
+ const register_srt_t *b = (register_srt_t *)bparam;
+
+ return g_ascii_strcasecmp(proto_get_protocol_short_name(find_protocol_by_id(a->proto_id)), proto_get_protocol_short_name(find_protocol_by_id(b->proto_id)));
+}
+
+void
+register_srt_table(const int proto_id, const char* tap_listener, int max_tables, tap_packet_cb srt_packet_func, srt_init_cb init_cb, srt_param_handler_cb param_cb)
+{
+ register_srt_t *table;
+ DISSECTOR_ASSERT(init_cb);
+ DISSECTOR_ASSERT(srt_packet_func);
+
+ table = g_new(register_srt_t,1);
+
+ table->proto_id = proto_id;
+ if (tap_listener != NULL)
+ table->tap_listen_str = tap_listener;
+ else
+ table->tap_listen_str = proto_get_protocol_filter_name(proto_id);
+ table->max_tables = max_tables;
+ table->srt_func = srt_packet_func;
+ table->srt_init = init_cb;
+ table->param_cb = param_cb;
+ table->param_data = NULL;
+
+ registered_srt_tables = g_slist_insert_sorted(registered_srt_tables, table, insert_sorted_by_table_name);
+}
+
+void srt_table_iterate_tables(GFunc func, gpointer user_data)
+{
+ g_slist_foreach(registered_srt_tables, func, user_data);
+}
+
+srt_stat_table*
+init_srt_table(const char *name, const char *short_name, GArray *srt_array, int num_procs, const char* proc_column_name,
+ const char *filter_string, srt_gui_init_cb gui_callback, void* gui_data, void* table_specific_data)
+{
+ int i;
+ srt_stat_table *table = g_new(srt_stat_table, 1);
+
+ if(filter_string){
+ table->filter_string=g_strdup(filter_string);
+ } else {
+ table->filter_string=NULL;
+ }
+
+ table->name = name;
+ table->short_name = short_name;
+ table->proc_column_name = proc_column_name;
+ table->num_procs=num_procs;
+ table->procedures=(srt_procedure_t *)g_malloc(sizeof(srt_procedure_t)*num_procs);
+ for(i=0;i<num_procs;i++){
+ time_stat_init(&table->procedures[i].stats);
+ table->procedures[i].index = 0;
+ table->procedures[i].procedure = NULL;
+ }
+
+ g_array_insert_val(srt_array, srt_array->len, table);
+
+ table->table_specific_data = table_specific_data;
+
+ if (gui_callback)
+ gui_callback(table, gui_data);
+
+ return table;
+}
+
+void
+init_srt_table_row(srt_stat_table *rst, int indx, const char *procedure)
+{
+ /* we have discovered a new procedure. Extend the table accordingly */
+ if(indx>=rst->num_procs){
+ int old_num_procs=rst->num_procs;
+ int i;
+
+ rst->num_procs=indx+1;
+ rst->procedures=(srt_procedure_t *)g_realloc(rst->procedures, sizeof(srt_procedure_t)*(rst->num_procs));
+ for(i=old_num_procs;i<rst->num_procs;i++){
+ time_stat_init(&rst->procedures[i].stats);
+ rst->procedures[i].index = i;
+ rst->procedures[i].procedure=NULL;
+ }
+ }
+ rst->procedures[indx].index = indx;
+ rst->procedures[indx].procedure=g_strdup(procedure);
+}
+
+void
+add_srt_table_data(srt_stat_table *rst, int indx, const nstime_t *req_time, packet_info *pinfo)
+{
+ srt_procedure_t *rp;
+ nstime_t t, delta;
+
+ g_assert(indx >= 0 && indx < rst->num_procs);
+ rp=&rst->procedures[indx];
+
+ /* calculate time delta between request and reply */
+ t=pinfo->fd->abs_ts;
+ nstime_delta(&delta, &t, req_time);
+
+ time_stat_update(&rp->stats, &delta, pinfo);
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/epan/srt_table.h b/epan/srt_table.h
new file mode 100644
index 0000000000..f2f9278f51
--- /dev/null
+++ b/epan/srt_table.h
@@ -0,0 +1,240 @@
+/* srt_table.h
+ * GUI independent helper routines common to all service response time (SRT) taps.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SRT_TABLE_H__
+#define __SRT_TABLE_H__
+
+#include "tap.h"
+#include "timestats.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Procedure data */
+typedef struct _srt_procedure_t {
+ int index;
+ timestat_t stats; /**< stats */
+ char *procedure; /**< column entries */
+} srt_procedure_t;
+
+/** Statistics table */
+typedef struct _srt_stat_table {
+ const char *name; /**< table name */
+ const char *short_name; /**< tab name */
+ char *filter_string; /**< append procedure number (%d) to this string
+ to create a display filter */
+ int num_procs; /**< number of elements on procedures array */
+ const char *proc_column_name; /**< procedure column name (if different from default) */
+ srt_procedure_t *procedures;/**< the procedures array */
+ void* table_specific_data; /** any dissector/table specific data needed for packet filtering */
+} srt_stat_table;
+
+
+struct register_srt;
+struct _srt_data_t;
+typedef void (*srt_gui_init_cb)(srt_stat_table* rst, void* gui_data);
+typedef void (*srt_gui_reset_cb)(srt_stat_table* rst, void* gui_data);
+typedef void (*srt_gui_free_cb)(srt_stat_table* rst, void* gui_data);
+typedef void (*srt_proc_table_cb)(srt_stat_table* rst, int indx, struct _srt_data_t* gui_data);
+typedef void (*srt_init_cb)(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data);
+typedef guint (*srt_param_handler_cb)(struct register_srt* srt, const char* opt_arg, char** err);
+
+/** tap data
+ */
+typedef struct _srt_data_t {
+ GArray *srt_array; /**< array of srt_stat_table */
+ void *user_data; /**< "GUI" specifics (if necessary) */
+} srt_data_t;
+
+/** Structure for information about a registered service response table */
+typedef struct register_srt register_srt_t;
+
+/** Register the service response time table for the srt windows.
+ *
+ * @param proto_id is the protocol with conversation
+ * @param tap_listener string for register_tap_listener (NULL to just use protocol name)
+ * @param srt_packet_func the tap processing function
+ * @param init_cb initialize dissector SRT function
+ * @param param_cb handles dissection of parameters to optional arguments of tap string
+ */
+WS_DLL_PUBLIC void register_srt_table(const int proto_id, const char* tap_listener, int max_tables,
+ tap_packet_cb srt_packet_func, srt_init_cb init_cb, srt_param_handler_cb param_cb);
+
+/** Get protocol ID from SRT
+ *
+ * @param srt Registered SRT
+ * @return protocol id of SRT
+ */
+WS_DLL_PUBLIC int get_srt_proto_id(register_srt_t* srt);
+
+/** Get string for register_tap_listener call. Typically just dissector name
+ *
+ * @param srt Registered SRT
+ * @return string for register_tap_listener call
+ */
+WS_DLL_PUBLIC const char* get_srt_tap_listener_name(register_srt_t* srt);
+
+/** Get maximum number of tables from SRT
+ *
+ * @param srt Registered SRT
+ * @return maximum number of tables of SRT
+ */
+WS_DLL_PUBLIC int get_srt_max_tables(register_srt_t* srt);
+
+/** Get tap function handler from SRT
+ *
+ * @param srt Registered SRT
+ * @return tap function handler of SRT
+ */
+WS_DLL_PUBLIC tap_packet_cb get_srt_packet_func(register_srt_t* srt);
+
+/** Set parameter data from SRT parsed from tap string. Data will be
+ * freed on tap reset
+ *
+ * @param srt Registered SRT
+ * @param data Parameter data
+ */
+WS_DLL_PUBLIC void set_srt_table_param_data(register_srt_t* srt, void* data);
+
+/** Get parameter data from SRT
+ *
+ * @param srt Registered SRT
+ * @return Parameter data
+ */
+WS_DLL_PUBLIC void* get_srt_table_param_data(register_srt_t* srt);
+
+/** Get SRT table by its dissector name
+ *
+ * @param name dissector name to fetch.
+ * @return SRT table pointer or NULL.
+ */
+WS_DLL_PUBLIC register_srt_t* get_srt_table_by_name(const char* name);
+
+/** Free the srt table data.
+ *
+ * @param rst the srt table
+ */
+WS_DLL_PUBLIC void free_srt_table_data(srt_stat_table *rst);
+
+/** Free the srt table data.
+ *
+ * @param srt Registered SRT
+ * @param srt_array SRT table array
+ * @param gui_callback optional callback from GUI
+ * @param callback_data callback data needed for GUI
+ */
+WS_DLL_PUBLIC void free_srt_table(register_srt_t *srt, GArray* srt_array, srt_gui_free_cb gui_callback, void *callback_data);
+
+/** Reset ALL tables in the srt.
+ *
+ * @param srt_array SRT table array
+ * @param gui_callback optional callback from GUI
+ * @param callback_data callback data needed for GUI
+ */
+WS_DLL_PUBLIC void reset_srt_table(GArray* srt_array, srt_gui_reset_cb gui_callback, void *callback_data);
+
+/** Interator to walk srt tables and execute func
+ * Used for initialization
+ *
+ * @param func action to be performed on all converation tables
+ * @param user_data any data needed to help perform function
+ */
+WS_DLL_PUBLIC void srt_table_iterate_tables(GFunc func, gpointer user_data);
+
+/** Return filter used for register_tap_listener
+ *
+ * @param srt Registered SRT
+ * @param opt_arg passed in opt_arg from GUI
+ * @param filter returned filter string to be used for registering tap
+ * @param err returned error if opt_arg string can't be successfully parsed. Caller must free memory
+ */
+WS_DLL_PUBLIC void srt_table_get_filter(register_srt_t* srt, const char *opt_arg, const char **filter, char** err);
+
+/** "Common" initialization function for all GUIs
+ *
+ * @param srt Registered SRT
+ * @param srt_array SRT table array
+ * @param opt_arg passed in opt_arg from GUI
+ * @param filter returned filter string to be used for registering tap
+ */
+WS_DLL_PUBLIC void srt_table_dissector_init(register_srt_t* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void *callback_data);
+
+/** Helper function to get tap string name
+ * Caller is responsible for freeing returned string
+ *
+ * @param srt Registered SRT
+ * @return SRT tap string
+ */
+WS_DLL_PUBLIC gchar* srt_table_get_tap_string(register_srt_t* srt);
+
+/** Init an srt table data structure.
+ *
+ * @param name the table name
+ * @param short_name the name used in a tab display
+ * @param srt_array the srt table array to add to
+ * @param num_procs number of procedures
+ * @param proc_column_name procedure column name (if different from "Procedure")
+ * @param filter_string table filter string or NULL
+ * @param gui_callback optional GUI callback
+ * @param gui_data GUI content data
+ * @return newly created srt_stat_table
+ */
+WS_DLL_PUBLIC srt_stat_table* init_srt_table(const char *name, const char *short_name, GArray *srt_array, int num_procs, const char* proc_column_name,
+ const char *filter_string, srt_gui_init_cb gui_callback, void* gui_data, void* table_specific_data);
+
+/** Init an srt table row data structure.
+ *
+ * @param rst the srt table
+ * @param index number of procedure
+ * @param procedure the procedures name
+ */
+WS_DLL_PUBLIC void init_srt_table_row(srt_stat_table *rst, int index, const char *procedure);
+
+/** Add srt response to table row data.
+ *
+ * @param rst the srt table
+ * @param index number of procedure
+ * @param req_time the time of the corresponding request
+ * @param pinfo current packet info
+ */
+WS_DLL_PUBLIC void add_srt_table_data(srt_stat_table *rst, int index, const nstime_t *req_time, packet_info *pinfo);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SRT_TABLE_H__ */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */