summaryrefslogtreecommitdiff
path: root/epan/dissectors/packet-megaco.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-megaco.c')
-rw-r--r--epan/dissectors/packet-megaco.c212
1 files changed, 212 insertions, 0 deletions
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 */