aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2015-06-16 17:07:04 -0400
committerMichael Mann <mmann78@netscape.net>2015-06-21 03:35:13 +0000
commit6de6f7f0f8f8b79c4fc7473c7e54dad433c7b61b (patch)
tree20b4b81b49467f5685f51c6b75e240c41ca6cb32 /epan
parent2895d58dc38321a72c82e1bf77d165ef4acbc73a (diff)
Further refactor SRT stats.
Create "common" SRT tap data collection intended for all GUIs. Refactor/merge functionality of existing dissectors that have SRT support (AFP, DCERPC, Diameter, FC, GTP, LDAP, NCP, RPC, SCIS, SMB, and SMB2) for both TShark and GTK. SMB and DCERPC "tap packet filtering" were different between TShark and GTK, so I went with GTK filter logic. CAMEL "tap packet filtering" was different between TShark and GTK, so GTK filtering logic was pushed to the dissector and the TShark tap was left alone. Change-Id: I7d6eaad0673fe628ef337f9165d7ed94f4a5e1cc Reviewed-on: https://code.wireshark.org/review/8894 Petri-Dish: Michael Mann <mmann78@netscape.net> Reviewed-by: Gerald Combs <gerald@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
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:
+ */