summaryrefslogtreecommitdiff
path: root/epan
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2015-06-20 12:22:22 -0400
committerAnders Broman <a.broman58@gmail.com>2015-06-22 15:13:39 +0000
commit8f390d497577937dee7311f345b77c840ba42e15 (patch)
treed59679646ab38e4c22d7773cd00003719be028e7 /epan
parent8b230eabddf11becf4ae895fba17f43a3415716e (diff)
downloadwireshark-8f390d497577937dee7311f345b77c840ba42e15.tar.gz
Refactor RTD stats.
Very similar to the refactoring of SRT stats, it provides more commonality of the stats for all GUI interfaces. Currently implemented for TShark and GTK. Affected dissectors: MEGACO, MGCP, Radius Change-Id: Icb73a7e603dc3502b39bf696227fcaae37d4ed21 Reviewed-on: https://code.wireshark.org/review/8998 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/Makefile.common2
-rw-r--r--epan/dissectors/packet-megaco.c212
-rw-r--r--epan/dissectors/packet-mgcp.c99
-rw-r--r--epan/dissectors/packet-radius.c147
-rw-r--r--epan/rtd_table.c205
-rw-r--r--epan/rtd_table.h183
7 files changed, 849 insertions, 0 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 87b2d298f9..fec0cf3a2d 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1629,6 +1629,7 @@ set(LIBWIRESHARK_FILES
reassemble.c
reedsolomon.c
req_resp_hdrs.c
+ rtd_table.c
show_exception.c
sminmpec.c
srt_table.c
diff --git a/epan/Makefile.common b/epan/Makefile.common
index ec2ee1926e..a8c3bb5ad1 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -79,6 +79,7 @@ LIBWIRESHARK_SRC = \
reassemble.c \
reedsolomon.c \
req_resp_hdrs.c \
+ rtd_table.c \
show_exception.c \
sminmpec.c \
srt_table.c \
@@ -232,6 +233,7 @@ LIBWIRESHARK_INCLUDES = \
reassemble.h \
reedsolomon.h \
req_resp_hdrs.h \
+ rtd_table.h \
rtp_pt.h \
sctpppids.h \
show_exception.h \
diff --git a/epan/dissectors/packet-megaco.c b/epan/dissectors/packet-megaco.c
index ac6e23ae1d..e822245059 100644
--- a/epan/dissectors/packet-megaco.c
+++ b/epan/dissectors/packet-megaco.c
@@ -46,6 +46,8 @@
#include <epan/exceptions.h>
#include <epan/gcp.h>
#include <epan/tap.h>
+#include <epan/rtd_table.h>
+#include <epan/prefs-int.h>
#include "packet-tpkt.h"
#include "packet-h245.h"
#include "packet-ip.h"
@@ -201,6 +203,215 @@ static const value_string megaco_context_vals[] = {
static gint megaco_tvb_skip_wsp(tvbuff_t *tvb, gint offset);
static gint megaco_tvb_skip_wsp_return(tvbuff_t *tvb, gint offset);
+#define NUM_TIMESTATS 12
+
+static const value_string megaco_message_type[] = {
+ { 0, "ADD "},
+ { 1, "MOVE"},
+ { 2, "MDFY"},
+ { 3, "SUBT"},
+ { 4, "AUCP"},
+ { 5, "AUVL"},
+ { 6, "NTFY"},
+ { 7, "SVCC"},
+ { 8, "TOPO"},
+ { 9, "NONE"},
+ { 10, "ALL "},
+ { 0, NULL}
+};
+
+#define GCP_CMD_REPLY_CASE \
+ case GCP_CMD_ADD_REPLY: \
+ case GCP_CMD_MOVE_REPLY: \
+ case GCP_CMD_MOD_REPLY: \
+ case GCP_CMD_SUB_REPLY: \
+ case GCP_CMD_AUDITCAP_REPLY: \
+ case GCP_CMD_AUDITVAL_REPLY: \
+ case GCP_CMD_NOTIFY_REPLY: \
+ case GCP_CMD_SVCCHG_REPLY: \
+ case GCP_CMD_TOPOLOGY_REPLY: \
+ case GCP_CMD_REPLY:
+
+#define GCP_CMD_REQ_CASE \
+ case GCP_CMD_ADD_REQ: \
+ case GCP_CMD_MOVE_REQ: \
+ case GCP_CMD_MOD_REQ: \
+ case GCP_CMD_SUB_REQ: \
+ case GCP_CMD_AUDITCAP_REQ: \
+ case GCP_CMD_AUDITVAL_REQ: \
+ case GCP_CMD_NOTIFY_REQ: \
+ case GCP_CMD_SVCCHG_REQ: \
+ case GCP_CMD_TOPOLOGY_REQ: \
+ case GCP_CMD_CTX_ATTR_AUDIT_REQ: \
+ case GCP_CMD_OTHER_REQ:
+
+static gboolean
+megacostat_is_duplicate_reply(const gcp_cmd_t* cmd)
+{
+ switch (cmd->type) {
+
+ GCP_CMD_REPLY_CASE
+ {
+ gcp_cmd_msg_t *cmd_msg;
+ /* cycle through commands to find same command in the transaction */
+ for (cmd_msg = cmd->trx->cmds;
+ (cmd_msg != NULL) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
+ cmd_msg = cmd_msg->next) {
+ if (cmd_msg->cmd->type == cmd->type)
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+}
+
+static gboolean
+megacostat_had_request(const gcp_cmd_t* cmd)
+{
+ switch (cmd->type) {
+
+ GCP_CMD_REPLY_CASE
+ {
+ gcp_cmd_msg_t *cmd_msg;
+ /* cycle through commands to find a request in the transaction */
+ for (cmd_msg = cmd->trx->cmds;
+ (cmd_msg != NULL) && (cmd_msg->cmd->msg->framenum != cmd->msg->framenum);
+ cmd_msg = cmd_msg->next) {
+
+ switch (cmd_msg->cmd->type) {
+
+ GCP_CMD_REQ_CASE
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ }
+
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+}
+
+static void
+megacostat_filtercheck(const char *opt_arg _U_, const char **filter _U_, char** err)
+{
+ pref_t *megaco_ctx_track, *h248_ctx_track;
+
+ megaco_ctx_track = prefs_find_preference(prefs_find_module("megaco"), "ctx_info");
+ h248_ctx_track = prefs_find_preference(prefs_find_module("h248"), "ctx_info");
+
+ if (!megaco_ctx_track || !h248_ctx_track) {
+ /* No such preferences */
+ return;
+ }
+
+ if (!*megaco_ctx_track->varp.boolp || !*h248_ctx_track->varp.boolp) {
+ *err = g_strdup_printf("Track Context option at Protocols -> MEGACO and Protocols -> H248 preferences\n"
+ "has to be set to true to enable measurement of service response times.\n");
+ }
+}
+
+static int
+megacostat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi)
+{
+ rtd_data_t* rtd_data = (rtd_data_t*)pms;
+ rtd_stat_table* ms = &rtd_data->stat_table;
+ const gcp_cmd_t *mi=(const gcp_cmd_t*)pmi;
+ nstime_t delta;
+ int ret = 0;
+
+ switch (mi->type) {
+
+ GCP_CMD_REQ_CASE
+ if(!mi->trx->initial) {
+ /* Track Context is probably disabled, we cannot
+ * measure service response time */
+ return 0;
+ }
+
+ else if(mi->trx->initial->framenum != mi->msg->framenum){
+ /* Duplicate is ignored */
+ ms->time_stats[0].req_dup_num++;
+ }
+ else {
+ ms->time_stats[0].open_req_num++;
+ }
+ break;
+
+ GCP_CMD_REPLY_CASE
+ if(megacostat_is_duplicate_reply(mi)){
+ /* Duplicate is ignored */
+ ms->time_stats[0].rsp_dup_num++;
+ }
+ else if (!megacostat_had_request(mi)) {
+ /* no request was seen */
+ ms->time_stats[0].disc_rsp_num++;
+ }
+ else {
+ ms->time_stats[0].open_req_num--;
+ /* calculate time delta between request and response */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &mi->trx->initial->time);
+
+ switch(mi->type) {
+
+ case GCP_CMD_ADD_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[0]),&delta, pinfo);
+ break;
+ case GCP_CMD_MOVE_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[1]),&delta, pinfo);
+ break;
+ case GCP_CMD_MOD_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[2]),&delta, pinfo);
+ break;
+ case GCP_CMD_SUB_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[3]),&delta, pinfo);
+ break;
+ case GCP_CMD_AUDITCAP_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[4]),&delta, pinfo);
+ break;
+ case GCP_CMD_AUDITVAL_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[5]),&delta, pinfo);
+ break;
+ case GCP_CMD_NOTIFY_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[6]),&delta, pinfo);
+ break;
+ case GCP_CMD_SVCCHG_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[7]),&delta, pinfo);
+ break;
+ case GCP_CMD_TOPOLOGY_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[8]),&delta, pinfo);
+ break;
+ case GCP_CMD_REPLY:
+ time_stat_update(&(ms->time_stats[0].rtd[9]),&delta, pinfo);
+ break;
+ default:
+ time_stat_update(&(ms->time_stats[0].rtd[11]),&delta, pinfo);
+ }
+
+ time_stat_update(&(ms->time_stats[0].rtd[10]),&delta, pinfo);
+ ret = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
/*
* The various functions that either dissect some
* subpart of MEGACO. These aren't really proto dissectors but they
@@ -3575,6 +3786,7 @@ proto_register_megaco(void)
ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n");
ws_mempbrk_compile(&pbrk_braces, "{}");
+ register_rtd_table(proto_megaco, NULL, 1, NUM_TIMESTATS, megaco_message_type, megacostat_packet, megacostat_filtercheck);
}
/* Register all the bits needed with the filtering engine */
diff --git a/epan/dissectors/packet-mgcp.c b/epan/dissectors/packet-mgcp.c
index aabe2a3915..21b5fdfdbb 100644
--- a/epan/dissectors/packet-mgcp.c
+++ b/epan/dissectors/packet-mgcp.c
@@ -42,6 +42,7 @@
#include <epan/prefs.h>
#include <epan/conversation.h>
#include <epan/tap.h>
+#include <epan/rtd_table.h>
#include "packet-mgcp.h"
@@ -279,6 +280,102 @@ static void dissect_mgcp_localconnectionoptions(proto_tree *parent_tree, tvbuff_
static void mgcp_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
+#define NUM_TIMESTATS 11
+
+static const value_string mgcp_mesage_type[] = {
+ { 0, "Overall"},
+ { 1, "EPCF "},
+ { 2, "CRCX "},
+ { 3, "MDCX "},
+ { 4, "DLCX "},
+ { 5, "RQNT "},
+ { 6, "NTFY "},
+ { 7, "AUEP "},
+ { 8, "AUCX "},
+ { 9, "RSIP "},
+ { 0, NULL}
+};
+
+static int
+mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pmi)
+{
+ rtd_data_t* rtd_data = (rtd_data_t*)pms;
+ rtd_stat_table* ms = &rtd_data->stat_table;
+ const mgcp_info_t *mi = (const mgcp_info_t *)pmi;
+ nstime_t delta;
+ int ret = 0;
+
+ switch (mi->mgcp_type) {
+
+ case MGCP_REQUEST:
+ if (mi->is_duplicate) {
+ /* Duplicate is ignored */
+ ms->time_stats[0].req_dup_num++;
+ }
+ else {
+ ms->time_stats[0].open_req_num++;
+ }
+ break;
+
+ case MGCP_RESPONSE:
+ if (mi->is_duplicate) {
+ /* Duplicate is ignored */
+ ms->time_stats[0].rsp_dup_num++;
+ }
+ else if (!mi->request_available) {
+ /* no request was seen */
+ ms->time_stats[0].disc_rsp_num++;
+ }
+ else {
+ ms->time_stats[0].open_req_num--;
+ /* calculate time delta between request and response */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &mi->req_time);
+
+ time_stat_update(&(ms->time_stats[0].rtd[0]), &delta, pinfo);
+
+ if (g_ascii_strncasecmp(mi->code, "EPCF", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[1]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "CRCX", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[2]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "MDCX", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[3]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "DLCX", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[4]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "RQNT", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[5]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "NTFY", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[6]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "AUEP", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[7]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "AUCX", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[8]), &delta, pinfo);
+ }
+ else if (g_ascii_strncasecmp(mi->code, "RSIP", 4) == 0 ) {
+ time_stat_update(&(ms->time_stats[0].rtd[9]), &delta, pinfo);
+ }
+ else {
+ time_stat_update(&(ms->time_stats[0].rtd[10]), &delta, pinfo);
+ }
+
+ ret = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
/*
* Some functions which should be moved to a library
* as I think that people may find them of general usefulness.
@@ -2258,6 +2355,8 @@ void proto_register_mgcp(void)
&global_mgcp_message_count);
mgcp_tap = register_tap("mgcp");
+
+ register_rtd_table(proto_mgcp, NULL, 1, NUM_TIMESTATS, mgcp_mesage_type, mgcpstat_packet, NULL);
}
/* The registration hand-off routine */
diff --git a/epan/dissectors/packet-radius.c b/epan/dissectors/packet-radius.c
index 2f02fa4a09..dc5176ee46 100644
--- a/epan/dissectors/packet-radius.c
+++ b/epan/dissectors/packet-radius.c
@@ -63,6 +63,7 @@
#include <epan/sminmpec.h>
#include <epan/conversation.h>
#include <epan/tap.h>
+#include <epan/rtd_table.h>
#include <epan/addr_resolv.h>
#include <wsutil/filesystem.h>
#include <wsutil/report_err.h>
@@ -212,6 +213,150 @@ static const value_string radius_pkt_type_codes[] =
};
static value_string_ext radius_pkt_type_codes_ext = VALUE_STRING_EXT_INIT(radius_pkt_type_codes);
+typedef enum _radius_category {
+ RADIUS_CAT_OVERALL = 0,
+ RADIUS_CAT_ACCESS,
+ RADIUS_CAT_ACCOUNTING,
+ RADIUS_CAT_PASSWORD,
+ RADIUS_CAT_RESOURCE_FREE,
+ RADIUS_CAT_RESOURCE_QUERY,
+ RADIUS_CAT_NAS_REBOOT,
+ RADIUS_CAT_EVENT,
+ RADIUS_CAT_DISCONNECT,
+ RADIUS_CAT_COA,
+ RADIUS_CAT_OTHERS,
+ RADIUS_CAT_NUM_TIMESTATS
+} radius_category;
+
+static const value_string radius_message_code[] = {
+ { RADIUS_CAT_OVERALL, "Overall"},
+ { RADIUS_CAT_ACCESS, "Access"},
+ { RADIUS_CAT_ACCOUNTING, "Accounting"},
+ { RADIUS_CAT_PASSWORD, "Password"},
+ { RADIUS_CAT_RESOURCE_FREE, "Resource Free"},
+ { RADIUS_CAT_RESOURCE_QUERY, "Resource Query"},
+ { RADIUS_CAT_NAS_REBOOT, "NAS Reboot"},
+ { RADIUS_CAT_EVENT, "Event"},
+ { RADIUS_CAT_DISCONNECT, "Disconnect"},
+ { RADIUS_CAT_COA, "CoA"},
+ { RADIUS_CAT_OTHERS, "Other"},
+ { 0, NULL}
+};
+
+static int
+radiusstat_packet(void *prs, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pri)
+{
+ rtd_data_t* rtd_data = (rtd_data_t*)prs;
+ rtd_stat_table* rs = &rtd_data->stat_table;
+ const radius_info_t *ri=(radius_info_t *)pri;
+ nstime_t delta;
+ radius_category radius_cat = RADIUS_CAT_OTHERS;
+ int ret = 0;
+
+ switch (ri->code) {
+ case RADIUS_PKT_TYPE_ACCESS_REQUEST:
+ case RADIUS_PKT_TYPE_ACCESS_ACCEPT:
+ case RADIUS_PKT_TYPE_ACCESS_REJECT:
+ radius_cat = RADIUS_CAT_ACCESS;
+ break;
+ case RADIUS_PKT_TYPE_ACCOUNTING_REQUEST:
+ case RADIUS_PKT_TYPE_ACCOUNTING_RESPONSE:
+ radius_cat = RADIUS_CAT_ACCOUNTING;
+ break;
+ case RADIUS_PKT_TYPE_PASSWORD_REQUEST:
+ case RADIUS_PKT_TYPE_PASSWORD_ACK:
+ case RADIUS_PKT_TYPE_PASSWORD_REJECT:
+ radius_cat = RADIUS_CAT_PASSWORD;
+ break;
+ case RADIUS_PKT_TYPE_RESOURCE_FREE_REQUEST:
+ case RADIUS_PKT_TYPE_RESOURCE_FREE_RESPONSE:
+ radius_cat = RADIUS_CAT_RESOURCE_FREE;
+ break;
+ case RADIUS_PKT_TYPE_RESOURCE_QUERY_REQUEST:
+ case RADIUS_PKT_TYPE_RESOURCE_QUERY_RESPONSE:
+ radius_cat = RADIUS_CAT_RESOURCE_QUERY;
+ break;
+ case RADIUS_PKT_TYPE_NAS_REBOOT_REQUEST:
+ case RADIUS_PKT_TYPE_NAS_REBOOT_RESPONSE:
+ radius_cat = RADIUS_CAT_NAS_REBOOT;
+ break;
+ case RADIUS_PKT_TYPE_EVENT_REQUEST:
+ case RADIUS_PKT_TYPE_EVENT_RESPONSE:
+ radius_cat = RADIUS_CAT_EVENT;
+ break;
+ case RADIUS_PKT_TYPE_DISCONNECT_REQUEST:
+ case RADIUS_PKT_TYPE_DISCONNECT_ACK:
+ case RADIUS_PKT_TYPE_DISCONNECT_NAK:
+ radius_cat = RADIUS_CAT_DISCONNECT;
+ break;
+ case RADIUS_PKT_TYPE_COA_REQUEST:
+ case RADIUS_PKT_TYPE_COA_ACK:
+ case RADIUS_PKT_TYPE_COA_NAK:
+ radius_cat = RADIUS_CAT_COA;
+ break;
+ }
+
+ switch (ri->code) {
+
+ case RADIUS_PKT_TYPE_ACCESS_REQUEST:
+ case RADIUS_PKT_TYPE_ACCOUNTING_REQUEST:
+ case RADIUS_PKT_TYPE_PASSWORD_REQUEST:
+ case RADIUS_PKT_TYPE_EVENT_REQUEST:
+ case RADIUS_PKT_TYPE_DISCONNECT_REQUEST:
+ case RADIUS_PKT_TYPE_COA_REQUEST:
+ if(ri->is_duplicate){
+ /* Duplicate is ignored */
+ rs->time_stats[RADIUS_CAT_OVERALL].req_dup_num++;
+ rs->time_stats[radius_cat].req_dup_num++;
+ }
+ else {
+ rs->time_stats[RADIUS_CAT_OVERALL].open_req_num++;
+ rs->time_stats[radius_cat].open_req_num++;
+ }
+ break;
+
+ case RADIUS_PKT_TYPE_ACCESS_ACCEPT:
+ case RADIUS_PKT_TYPE_ACCESS_REJECT:
+ case RADIUS_PKT_TYPE_ACCOUNTING_RESPONSE:
+ case RADIUS_PKT_TYPE_PASSWORD_ACK:
+ case RADIUS_PKT_TYPE_PASSWORD_REJECT:
+ case RADIUS_PKT_TYPE_EVENT_RESPONSE:
+ case RADIUS_PKT_TYPE_DISCONNECT_ACK:
+ case RADIUS_PKT_TYPE_DISCONNECT_NAK:
+ case RADIUS_PKT_TYPE_COA_ACK:
+ case RADIUS_PKT_TYPE_COA_NAK:
+ if(ri->is_duplicate){
+ /* Duplicate is ignored */
+ rs->time_stats[RADIUS_CAT_OVERALL].rsp_dup_num++;
+ rs->time_stats[radius_cat].rsp_dup_num++;
+ }
+ else if (!ri->request_available) {
+ /* no request was seen */
+ rs->time_stats[RADIUS_CAT_OVERALL].disc_rsp_num++;
+ rs->time_stats[radius_cat].disc_rsp_num++;
+ }
+ else {
+ rs->time_stats[RADIUS_CAT_OVERALL].open_req_num--;
+ rs->time_stats[radius_cat].open_req_num--;
+ /* calculate time delta between request and response */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &ri->req_time);
+
+ time_stat_update(&(rs->time_stats[RADIUS_CAT_OVERALL].rtd[0]),&delta, pinfo);
+ time_stat_update(&(rs->time_stats[radius_cat].rtd[0]),&delta, pinfo);
+
+ ret = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+
/*
* Init Hash table stuff for conversation
*/
@@ -2130,6 +2275,8 @@ proto_register_radius(void)
dict->vendors_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
dict->vendors_by_name = g_hash_table_new(g_str_hash,g_str_equal);
dict->tlvs_by_name = g_hash_table_new(g_str_hash,g_str_equal);
+
+ register_rtd_table(proto_radius, NULL, RADIUS_CAT_NUM_TIMESTATS, 1, radius_message_code, radiusstat_packet, NULL);
}
void
diff --git a/epan/rtd_table.c b/epan/rtd_table.c
new file mode 100644
index 0000000000..a74a32adb2
--- /dev/null
+++ b/epan/rtd_table.c
@@ -0,0 +1,205 @@
+/* rtd_table.c
+ * Helper routines common to all RTD taps.
+ * Based on srt_table.c
+ *
+ * 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 "rtd_table.h"
+
+struct register_rtd {
+ int proto_id; /* protocol id (0-indexed) */
+ const char* tap_listen_str; /* string used in register_tap_listener (NULL to use protocol name) */
+ tap_packet_cb rtd_func; /* function to be called for new incoming packets for RTD */
+ guint num_tables;
+ guint num_timestats;
+ const value_string* vs_type;
+ rtd_filter_check_cb filter_check;
+};
+
+int get_rtd_proto_id(register_rtd_t* rtd)
+{
+ if (!rtd) {
+ return -1;
+ }
+ return rtd->proto_id;
+}
+
+const char* get_rtd_tap_listener_name(register_rtd_t* rtd)
+{
+ return rtd->tap_listen_str;
+}
+
+tap_packet_cb get_rtd_packet_func(register_rtd_t* rtd)
+{
+ return rtd->rtd_func;
+}
+
+const value_string* get_rtd_value_string(register_rtd_t* rtd)
+{
+ return rtd->vs_type;
+}
+
+static GSList *registered_rtd_tables = NULL;
+
+static gint
+insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
+{
+ const register_rtd_t *a = (register_rtd_t *)aparam;
+ const register_rtd_t *b = (register_rtd_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_rtd_table(const int proto_id, const char* tap_listener, guint num_tables, guint num_timestats, const value_string* vs_type,
+ tap_packet_cb rtd_packet_func, rtd_filter_check_cb filter_check_cb)
+{
+ register_rtd_t *table;
+ DISSECTOR_ASSERT(rtd_packet_func);
+
+ table = g_new(register_rtd_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->rtd_func = rtd_packet_func;
+ table->num_tables = num_tables;
+ table->num_timestats = num_timestats;
+ table->vs_type = vs_type;
+ table->filter_check = filter_check_cb;
+
+ registered_rtd_tables = g_slist_insert_sorted(registered_rtd_tables, table, insert_sorted_by_table_name);
+}
+
+void free_rtd_table(register_rtd_t* rtd _U_, rtd_stat_table* table, rtd_gui_free_cb gui_callback, void *callback_data)
+{
+ guint i;
+
+ for (i = 0; i < table->num_rtds; i++)
+ {
+ g_free(table->time_stats[i].rtd);
+ }
+ g_free(table->time_stats);
+
+ /* Give GUI the first crack at it before we clean up */
+ if (gui_callback)
+ gui_callback(table, callback_data);
+}
+
+void reset_rtd_table(rtd_stat_table* table, rtd_gui_reset_cb gui_callback, void *callback_data)
+{
+ guint i = 0;
+
+ for (i = 0; i < table->num_rtds; i++)
+ memset(table->time_stats[i].rtd, 0, sizeof(timestat_t)*table->time_stats[i].num_timestat);
+
+ /* Give GUI the first crack at it before we clean up */
+ if (gui_callback)
+ gui_callback(table, callback_data);
+
+}
+
+register_rtd_t* get_rtd_table_by_name(const char* name)
+{
+ guint i, size = g_slist_length(registered_rtd_tables);
+ register_rtd_t* rtd;
+ GSList *slist;
+
+ for (i = 0; i < size; i++) {
+ slist = g_slist_nth(registered_rtd_tables, i);
+ rtd = (register_rtd_t*)slist->data;
+
+ if (strcmp(name, proto_get_protocol_filter_name(rtd->proto_id)) == 0)
+ return rtd;
+ }
+
+ return NULL;
+}
+
+gchar* rtd_table_get_tap_string(register_rtd_t* rtd)
+{
+ GString *cmd_str = g_string_new(proto_get_protocol_filter_name(rtd->proto_id));
+ g_string_append(cmd_str, ",rtd");
+ return g_string_free(cmd_str, FALSE);
+}
+
+void rtd_table_get_filter(register_rtd_t* rtd, const char *opt_arg, const char **filter, char** err)
+{
+ gchar* cmd_str = rtd_table_get_tap_string(rtd);
+ guint len = strlen(cmd_str);
+ *filter=NULL;
+ *err=NULL;
+
+ if (!strncmp(opt_arg, cmd_str, len))
+ {
+ if (opt_arg[len] == ',')
+ {
+ *filter = opt_arg + len+1;
+ }
+ }
+
+ if (rtd->filter_check)
+ rtd->filter_check(opt_arg, filter, err);
+
+ g_free(cmd_str);
+}
+
+void rtd_table_dissector_init(register_rtd_t* rtd, rtd_stat_table* table, rtd_gui_init_cb gui_callback, void *callback_data)
+{
+ guint i;
+
+ table->num_rtds = rtd->num_tables;
+ table->time_stats = g_new0(rtd_timestat, rtd->num_tables);
+
+ for (i = 0; i < table->num_rtds; i++)
+ {
+ table->time_stats[i].num_timestat = rtd->num_timestats;
+ table->time_stats[i].rtd = g_new0(timestat_t, rtd->num_timestats);
+ }
+
+ if (gui_callback)
+ gui_callback(table, callback_data);
+}
+
+void rtd_table_iterate_tables(GFunc func, gpointer user_data)
+{
+ g_slist_foreach(registered_rtd_tables, func, user_data);
+}
+
+/*
+ * 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/rtd_table.h b/epan/rtd_table.h
new file mode 100644
index 0000000000..168c8beb4e
--- /dev/null
+++ b/epan/rtd_table.h
@@ -0,0 +1,183 @@
+/* rtd_table.h
+ * GUI independent helper routines common to all Response Time Delay (RTD) taps.
+ * Based on srt_table.h
+ *
+ * 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 __RTD_TABLE_H__
+#define __RTD_TABLE_H__
+
+#include "tap.h"
+#include "timestats.h"
+#include "value_string.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _rtd_timestat {
+ guint num_timestat; /**< number of elements on rtd array */
+ timestat_t* rtd;
+ guint32 open_req_num;
+ guint32 disc_rsp_num;
+ guint32 req_dup_num;
+ guint32 rsp_dup_num;
+} rtd_timestat;
+
+/** Statistics table */
+typedef struct _rtd_stat_table {
+ char *filter;
+ guint num_rtds; /**< number of elements on time_stats array */
+ rtd_timestat* time_stats;
+} rtd_stat_table;
+
+/** tap data
+ */
+typedef struct _rtd_data_t {
+ rtd_stat_table stat_table; /**< RTD table data */
+ void *user_data; /**< "GUI" specifics (if necessary) */
+} rtd_data_t;
+
+/** Structure for information about a registered service response table */
+struct register_rtd;
+typedef struct register_rtd register_rtd_t;
+
+typedef void (*rtd_gui_init_cb)(rtd_stat_table* rtd, void* gui_data);
+typedef void (*rtd_gui_reset_cb)(rtd_stat_table* rtd, void* gui_data);
+typedef void (*rtd_gui_free_cb)(rtd_stat_table* rtd, void* gui_data);
+typedef void (*rtd_init_cb)(struct register_rtd* rtd, rtd_gui_init_cb gui_callback, void* gui_data);
+typedef void (*rtd_filter_check_cb)(const char *opt_arg, const char **filter, char** err);
+
+/** Register the response time delay table.
+ *
+ * @param proto_id is the protocol with conversation
+ * @param tap_listener string for register_tap_listener (NULL to just use protocol name)
+ * @param num_timestats number of timestamps in the table
+ * @param vs_type value_string for the stat types
+ * @param rtd_packet_func the tap processing function
+ * @param filter_check_cb callback for verification of filter or other dissector checks
+ */
+WS_DLL_PUBLIC void register_rtd_table(const int proto_id, const char* tap_listener, guint num_tables, guint num_timestats, const value_string* vs_type,
+ tap_packet_cb rtd_packet_func, rtd_filter_check_cb filter_check_cb);
+
+/** Get protocol ID from RTD
+ *
+ * @param rtd Registered RTD
+ * @return protocol id of RTD
+ */
+WS_DLL_PUBLIC int get_rtd_proto_id(register_rtd_t* rtd);
+
+/** Get string for register_tap_listener call. Typically just dissector name
+ *
+ * @param rtd Registered RTD
+ * @return string for register_tap_listener call
+ */
+WS_DLL_PUBLIC const char* get_rtd_tap_listener_name(register_rtd_t* rtd);
+
+/** Get tap function handler from RTD
+ *
+ * @param rtd Registered RTD
+ * @return tap function handler of RTD
+ */
+WS_DLL_PUBLIC tap_packet_cb get_rtd_packet_func(register_rtd_t* rtd);
+
+/** Get value_string used for RTD
+ *
+ * @param rtd Registered RTD
+ * @return value_string of RTD
+ */
+WS_DLL_PUBLIC const value_string* get_rtd_value_string(register_rtd_t* rtd);
+
+/** Get RTD table by its dissector name
+ *
+ * @param name dissector name to fetch.
+ * @return RTD table pointer or NULL.
+ */
+WS_DLL_PUBLIC register_rtd_t* get_rtd_table_by_name(const char* name);
+
+/** Free the RTD table data.
+ *
+ * @param srt Registered RTD
+ * @param srt_array RTD table array
+ * @param gui_callback optional callback from GUI
+ * @param callback_data callback data needed for GUI
+ */
+WS_DLL_PUBLIC void free_rtd_table(register_rtd_t* rtd, rtd_stat_table* table, rtd_gui_free_cb gui_callback, void *callback_data);
+
+/** Reset table data in the RTD.
+ *
+ * @param table RTD table
+ * @param gui_callback optional callback from GUI
+ * @param callback_data callback data needed for GUI
+ */
+WS_DLL_PUBLIC void reset_rtd_table(rtd_stat_table* table, rtd_gui_reset_cb gui_callback, void *callback_data);
+
+/** Interator to walk RTD 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 rtd_table_iterate_tables(GFunc func, gpointer user_data);
+
+/** Return filter used for register_tap_listener
+ *
+ * @param srt Registered RTD
+ * @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 handled. Caller must free memory
+ */
+WS_DLL_PUBLIC void rtd_table_get_filter(register_rtd_t* rtd, const char *opt_arg, const char **filter, char** err);
+
+/** "Common" initialization function for all GUIs
+ *
+ * @param srt Registered RTD
+ * @param table RTD table
+ * @param gui_callback optional GUI callback function
+ * @param callback_data optional GUI callback data
+ */
+WS_DLL_PUBLIC void rtd_table_dissector_init(register_rtd_t* rtd, rtd_stat_table* table, rtd_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 RTD
+ * @return RTD tap string
+ */
+WS_DLL_PUBLIC gchar* rtd_table_get_tap_string(register_rtd_t* rtd);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __RTD_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:
+ */