diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/Makefile.common | 2 | ||||
-rw-r--r-- | epan/conversation_table.c | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-afp.c | 42 | ||||
-rw-r--r-- | epan/dissectors/packet-camel.c | 60 | ||||
-rw-r--r-- | epan/dissectors/packet-dcerpc.c | 160 | ||||
-rw-r--r-- | epan/dissectors/packet-dcerpc.h | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-diameter.c | 64 | ||||
-rw-r--r-- | epan/dissectors/packet-fc.c | 43 | ||||
-rw-r--r-- | epan/dissectors/packet-gtp.c | 58 | ||||
-rw-r--r-- | epan/dissectors/packet-ldap.c | 67 | ||||
-rw-r--r-- | epan/dissectors/packet-ncp.c | 250 | ||||
-rw-r--r-- | epan/dissectors/packet-rpc.c | 128 | ||||
-rw-r--r-- | epan/dissectors/packet-rpc.h | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-scsi.c | 108 | ||||
-rw-r--r-- | epan/dissectors/packet-smb.c | 72 | ||||
-rw-r--r-- | epan/dissectors/packet-smb2.c | 49 | ||||
-rw-r--r-- | epan/srt_table.c | 322 | ||||
-rw-r--r-- | epan/srt_table.h | 240 |
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, >p->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: + */ |