#include "packet-ber.h"
#include "packet-tcap.h"
#include "packet-ansi_tcap.h"
-#include <epan/tcap-persistentdata.h>
#define PNAME "ANSI Transaction Capabilities Application Part"
#define PSNAME "ANSI_TCAP"
extern guint gtcap_RepetitionTimeout;
extern guint gtcap_LostTimeout;
+/* When several Tcap components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_TCAP_INSTANCE 10
+int tcapsrt_global_current=0;
+struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
+
static dissector_table_t ber_oid_dissector_table=NULL;
static const char * cur_oid;
static const char * tcapext_oid;
#include "packet-gsm_a_common.h"
#include "packet-inap.h"
#include "packet-tcap.h"
-#include <epan/camel-persistentdata.h>
-#include <epan/tcap-persistentdata.h>
#define PNAME "Camel"
#define PSNAME "CAMEL"
static guint32 opcode=0;
static guint32 errorCode=0;
static guint32 camel_ver = 0;
+
+/* When several Camel components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_CAMEL_INSTANCE 10
+static int camelsrt_global_current=0;
+static struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
/* ROSE context */
static rose_ctx_t camel_rose_ctx;
static int hf_camel_CAMEL_SCIGPRSBillingChargingCharacteristics = -1;
static int hf_camel_CAMEL_CallResult = -1;
-/* Used by camel-persistentdata.c */
-int hf_camelsrt_SessionId=-1;
-int hf_camelsrt_RequestNumber=-1;
-int hf_camelsrt_Duplicate=-1;
-int hf_camelsrt_RequestFrame=-1;
-int hf_camelsrt_ResponseFrame=-1;
-int hf_camelsrt_DeltaTime=-1;
-int hf_camelsrt_SessionTime=-1;
-int hf_camelsrt_DeltaTime31=-1;
-int hf_camelsrt_DeltaTime75=-1;
-int hf_camelsrt_DeltaTime65=-1;
-int hf_camelsrt_DeltaTime22=-1;
-int hf_camelsrt_DeltaTime35=-1;
-int hf_camelsrt_DeltaTime80=-1;
+/* Used by persistent data */
+static int hf_camelsrt_SessionId=-1;
+static int hf_camelsrt_RequestNumber=-1;
+static int hf_camelsrt_Duplicate=-1;
+static int hf_camelsrt_RequestFrame=-1;
+static int hf_camelsrt_ResponseFrame=-1;
+static int hf_camelsrt_DeltaTime=-1;
+static int hf_camelsrt_SessionTime=-1;
+static int hf_camelsrt_DeltaTime31=-1;
+static int hf_camelsrt_DeltaTime75=-1;
+static int hf_camelsrt_DeltaTime65=-1;
+static int hf_camelsrt_DeltaTime22=-1;
+static int hf_camelsrt_DeltaTime35=-1;
+static int hf_camelsrt_DeltaTime80=-1;
#include "packet-camel-hf.c"
static int dissect_camel_CAMEL_AChBillingChargingCharacteristicsV2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
static int dissect_camel_CAMEL_CallResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
-gboolean gcamel_HandleSRT=FALSE;
-extern gboolean gcamel_PersistentSRT;
-extern gboolean gcamel_DisplaySRT;
+static gboolean gcamel_HandleSRT=FALSE;
+static gboolean gcamel_PersistentSRT=FALSE;
+static gboolean gcamel_DisplaySRT=FALSE;
+static gboolean gcamel_StatSRT=FALSE;
/* Initialize the subtree pointers */
static gint ett_camel = -1;
const char *camel_obj_id = NULL;
gboolean is_ExtensionField =FALSE;
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+static guint32 camelsrt_global_SessionId=1;
+
static int camel_opcode_type;
#define CAMEL_OPCODE_INVOKE 1
#define CAMEL_OPCODE_RETURN_RESULT 2
{ 0, NULL }
};
+const value_string camelSRTtype_naming[]= {
+ { CAMELSRT_SESSION, "TCAP_Session" },
+ { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
+ { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
+ { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
+ { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
+ { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
+ { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
+ { 0,NULL}
+};
+
#if 0
static const true_false_string camel_extension_value = {
"No Extension",
#include "packet-camel-table.c"
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void dbg(guint level, char *fmt, ...) {
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
static char camel_number_to_char(int number)
{
if (number < 10)
#include "packet-camel-table2.c"
+/*
+ * Functions needed for Hash-Table
+ */
+
+/* compare 2 keys */
+static gint
+camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct camelsrt_call_info_key_t *key1 = (const struct camelsrt_call_info_key_t *) k1;
+ const struct camelsrt_call_info_key_t *key2 = (const struct camelsrt_call_info_key_t *) k2;
+
+ return (key1->SessionIdKey == key2->SessionIdKey) ;
+}
+
+/* calculate a hash key */
+static guint
+camelsrt_call_hash(gconstpointer k)
+{
+ const struct camelsrt_call_info_key_t *key = (const struct camelsrt_call_info_key_t *) k;
+ return key->SessionIdKey;
+}
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct camelsrt_call_t *
+find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_t *p_camelsrt_call = NULL;
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
+
+#ifdef DEBUG_CAMELSRT
+ if(p_camelsrt_call) {
+ dbg(10,"D%d ", p_camelsrt_call->session_id);
+ } else {
+ dbg(23,"Not in hash ");
+ }
+#endif
+
+ return p_camelsrt_call;
+}
+
+/*
+ * Initialize the data per call for the Service Response Time Statistics
+ * Data are linked to a Camel operation in a TCAP transaction
+ */
+static void
+raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
+{
+ memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct camelsrt_call_t *
+new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_info_key_t *p_new_camelsrt_call_key;
+ struct camelsrt_call_t *p_new_camelsrt_call = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as main Key
+ Once created, this entry will be updated later */
+
+ p_new_camelsrt_call_key = se_new(struct camelsrt_call_info_key_t);
+ p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+ p_new_camelsrt_call = se_new(struct camelsrt_call_t);
+ raz_camelsrt_call(p_new_camelsrt_call);
+ p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"D%d ", p_new_camelsrt_call->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
+ return p_new_camelsrt_call;
+}
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+camelsrt_init_routine(void)
+{
+
+ /* free hash-table for SRT */
+ if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Destroy hash ");
+#endif
+ g_hash_table_destroy(srt_calls);
+ }
+
+ /* create new hash-table for SRT */
+ srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Create hash ");
+#endif
+ /* Reset the session counter */
+ camelsrt_global_SessionId=1;
+
+ /* The Display of SRT is enable
+ * 1) For wireshark only if Persistent Stat is enable
+ * 2) For Tshark, if the SRT handling is enable
+ */
+ gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
+}
+
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
+ guint msg_category)
+{
+ p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
+ p_camelsrt_call->category[msg_category].rsp_num = 0;
+ p_camelsrt_call->category[msg_category].responded = FALSE;
+ p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Update the Camel session info, and close the session.
+ * Then remove the associated context, if we do not have persistentSRT enable
+ */
+static void
+camelsrt_close_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session end #%u\n", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
+ p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
+
+ if ( !gcamel_PersistentSRT ) {
+ g_hash_table_remove(srt_calls, &camelsrt_call_key);
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"remove hash ");
+#endif
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"keep hash ");
+#endif
+ }
+ } /* call reference found */
+}
+
+/*
+ * Callback function for the TCAP dissector
+ * This callback function is used to inform the camel layer, that the session
+ * has been Closed or Aborted by a TCAP message without Camel component
+ * So, we can close the context for camel session, and update the stats.
+ */
+static void
+camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
+ proto_tree *tree _U_,
+ struct tcaphash_context_t *p_tcap_context)
+{
+ struct camelsrt_info_t *p_camelsrt_info;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Camel_CallBack ");
+#endif
+ p_camelsrt_info=camelsrt_razinfo();
+
+ p_camelsrt_info->tcap_context=p_tcap_context;
+ if (p_tcap_context) {
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Close TCAP ");
+#endif
+ p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
+ }
+}
+
+/*
+ * Create the record identifiying the Camel session
+ * As the Tcap session id given by the TCAP dissector is uniq, it will be
+ * used as main key.
+ */
+static void
+camelsrt_begin_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+
+ /* prepare the key data */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+ /* look up the request */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session begin #%u\n", pinfo->fd->num);
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
+ if (p_camelsrt_call) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_CAMELSRT
+ dbg(22,"Already seen ");
+#endif
+ } else { /* p_camelsrt_call has not been found */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key);
+ p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)p_camelsrt_info->tcap_context;
+ update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Update Callback ");
+#endif
+ p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
+ }
+}
+
+/*
+ * Register the request, and try to find the response
+ *
+ */
+static void
+camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type )
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ if (gcamel_DisplaySRT)
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+
+ /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
+ * we will prepare the measurement for 3 slices with 3 categories */
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Request ACR %u ",srt_type);
+ dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
+ dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
+ dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+
+ if (p_camelsrt_call->category[srt_type].req_num == 0) {
+ /* We have not yet seen a request to that call, so this must be the first request
+ remember its frame number. */
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } else {
+ /* We have seen a request to this call - but was it *this* request? */
+ if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
+
+ if (srt_type!=CAMELSRT_VOICE_DISC) {
+ /* No, so it's a duplicate resquest. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if (gcamel_DisplaySRT){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+
+ } else {
+ /* Ignore duplicate frame */
+ if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
+ p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"DISC Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } /* greater frame */
+ } /* DISC */
+ } /* req_num already seen */
+ } /* req_num != 0 */
+
+ /* add link to response frame, if available */
+ if ( gcamel_DisplaySRT &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].rsp_num,
+ "Linked response %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ } /* frame valid */
+ } /* call reference */
+}
+
+/*
+ * Display the delta time between two messages in a field corresponding
+ * to the category (hf_camelsrt_DeltaTimexx).
+ */
+static void
+camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
+ guint category)
+{
+ proto_item *ti;
+
+ if ( gcamel_DisplaySRT ) {
+ switch(category) {
+ case CAMELSRT_VOICE_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_ACR1:
+ case CAMELSRT_VOICE_ACR2:
+ case CAMELSRT_VOICE_ACR3:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_DISC:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_REPORT:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_SMS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Check if the received message is a response to a previous request
+ * registered is the camel session context.
+ */
+static void
+camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+ /* look only for matching request, if matching conversation is available. */
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ if ( gcamel_DisplaySRT )
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Report ACR %u ",srt_type);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+ if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0)
+ && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
+ /* We have not yet seen a response to that call, so this must be the first response;
+ remember its frame number only if response comes after request */
+#ifdef DEBUG_CAMELSRT
+ dbg(14,"Set reslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
+
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ } /* req_num != 0 */
+ } else { /* rsp_num != 0 */
+ /* We have seen a response to this call - but was it *this* response? */
+ if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if ( gcamel_DisplaySRT ){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+ }
+ } /* rsp_num != 0 */
+
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
+
+ p_camelsrt_call->category[srt_type].responded = TRUE;
+ p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if ( gcamel_DisplaySRT ) {
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].req_num,
+ "Linked request %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
+
+ p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
+
+ /* display Service Response Time and make it filterable */
+ camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
+
+ } /*req_num != 0 && not duplicate */
+ } /* call reference found */
+}
+
+/*
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void
+camelsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
+#endif
+
+ switch (p_camelsrt_info->opcode) {
+
+ case 0: /*InitialDP*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 60: /*InitialDPSMS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 78: /*InitialDPGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ break;
+
+ case 23: /*RequestReportBCSMEvent*/
+ break;
+
+ case 63: /*RequestReportSMSEvent*/
+ break;
+
+ case 81: /*RequestReportGPRSEvent*/
+ break;
+
+ case 24: /*EventReportBCSMEvent*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC );
+ break;
+
+ case 64: /*EventReportSMS*/
+ /* Session has been explicity closed without TC_END */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
+ break;
+
+ case 80: /*EventReportGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 35: /*ApplyCharging*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 71: /*ApplyChargingGPRS*/
+ break;
+
+ case 36: /*ApplyChargingReport*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 72: /*ApplyChargingReportGPRS*/
+ break;
+
+ case 31: /*Continue*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 65: /*ContinueSMS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 75: /*ContinueGPRS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 22: /*ReleaseCall*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC);
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+
+ case 66: /*ReleaseSMS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
+ break;
+
+ case 79: /*ReleaseGPRS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+ } /* switch opcode */
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t *
+camelsrt_razinfo(void)
+{
+ struct camelsrt_info_t *p_camelsrt_info ;
+
+ /* Global buffer for packet extraction */
+ camelsrt_global_current++;
+ if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
+ camelsrt_global_current=0;
+ }
+
+ p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
+ memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
+
+ p_camelsrt_info->opcode=255;
+
+ return p_camelsrt_info;
+}
+
static guint8 camel_pdu_type = 0;
static guint8 camel_pdu_size = 0;
WS_DLL_PUBLIC const value_string camel_opr_code_strings[];
/* #include "packet-camel-exp.h"*/
+/** @file
+*/
+#define NB_CAMELSRT_CATEGORY 9+1 /**< Number of type of message */
+/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
+ is a category, we want to measure the delay between the two messages */
+
+#define CAMELSRT_SESSION 1
+
+#define CAMELSRT_VOICE_INITIALDP 2
+#define CAMELSRT_VOICE_ACR1 3
+#define CAMELSRT_VOICE_ACR2 4
+#define CAMELSRT_VOICE_ACR3 5
+#define CAMELSRT_VOICE_DISC 6
+
+#define CAMELSRT_GPRS_INITIALDP 7
+#define CAMELSRT_GPRS_REPORT 8
+
+#define CAMELSRT_SMS_INITIALDP 9
+
+WS_DLL_PUBLIC const value_string camelSRTtype_naming[];
+
+/** If we have a request message and its response,
+ (eg: ApplyCharging, ApplyChargingReport)
+ the frames numbers are stored in this structure */
+
+struct camelsrt_category_t {
+ guint32 req_num; /**< frame number request seen */
+ guint32 rsp_num; /**< frame number response seen */
+ nstime_t req_time; /**< arrival time of request */
+ gboolean responded; /**< true, if request has been responded */
+};
+
+/** List of stored parameters for a Camel dialogue
+ All this parameters are linked to the hash table key below (use of Tid)
+ In case of same Tid reused, the Camel parameters are chained.
+ The right dialogue will be identified with the arrival time of the InitialDP */
+
+struct camelsrt_call_t {
+ guint32 session_id; /**< Identify the session, with an internal number */
+ struct tcaphash_context_t * tcap_context;
+ struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
+};
+
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct camelsrt_call_info_key_t {
+ guint32 SessionIdKey;
+};
+
+/** Info for a couple of messages (or category)
+ The request must be available, not duplicated,
+ and once the corresponding response received,
+ we can deduce the Delta Time between Request/response */
+
+struct camelsrt_msginfo_t {
+ gboolean request_available;
+ gboolean is_duplicate;
+ gboolean is_delta_time;
+ nstime_t req_time;
+ nstime_t delta_time;
+};
+
+/** List of infos to store for the analyse */
+
+struct camelsrt_info_t {
+ guint32 tcap_session_id;
+ void * tcap_context;
+ guint8 opcode; /**< operation code of message received */
+ guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /**< category for the received message */
+ struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+/**
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void camelsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camel_info);
+
+WS_DLL_PUBLIC gboolean gcamel_StatSRT;
+
#endif /* PACKET_camel_H */
#include <string.h>
#include "packet-ber.h"
#include "packet-tcap.h"
-#include <epan/tcap-persistentdata.h>
+#include "packet-mtp3.h"
+
#define PNAME "Transaction Capabilities Application Part"
#define PSNAME "TCAP"
#include "packet-tcap-ett.c"
+/* When several Tcap components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_TCAP_INSTANCE 10
+static int tcapsrt_global_current=0;
+static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
+
#define MAX_SSN 254
static range_t *global_ssn_range;
static range_t *ssn_range;
struct tcap_private_t tcap_private;
gboolean gtcap_HandleSRT=FALSE;
-extern gboolean gtcap_PersistentSRT;
-extern gboolean gtcap_DisplaySRT;
-extern guint gtcap_RepetitionTimeout;
-extern guint gtcap_LostTimeout;
+/* These two timeout (in second) are used when some message are lost,
+ or when the same TCAP transcation identifier is reused */
+guint gtcap_RepetitionTimeout = 10;
+guint gtcap_LostTimeout = 30;
+gboolean gtcap_PersistentSRT=FALSE;
+gboolean gtcap_DisplaySRT=FALSE;
+gboolean gtcap_StatSRT=FALSE;
+
+/* Global hash tables*/
+static GHashTable *tcaphash_context = NULL;
+static GHashTable *tcaphash_begin = NULL;
+static GHashTable *tcaphash_cont = NULL;
+static GHashTable *tcaphash_end = NULL;
+static GHashTable *tcaphash_ansi = NULL;
+
+static guint32 tcapsrt_global_SessionId=1;
static dissector_handle_t tcap_handle = NULL;
static dissector_table_t ber_oid_dissector_table;
return (dissector_handle_t)g_hash_table_lookup(itu_sub_dissectors,GUINT_TO_POINTER(ssn));
}
+#include "packet-tcap-fn.c"
+/*
+ * DEBUG functions
+ */
+#undef MEM_TCAPSRT
+/* #define MEM_TCAPSRT */
-#include "packet-tcap-fn.c"
+#undef DEBUG_TCAPSRT
+/* #define DEBUG_TCAPSRT */
+
+#ifdef DEBUG_TCAPSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void
+dbg(guint level, char* fmt, ...)
+{
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
+static gint
+tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
+ const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
+
+ return (key1->session_id == key2->session_id);
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_context_calchash(gconstpointer k)
+{
+ const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
+ return key->session_id;
+}
+
+
+static gint
+tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
+ const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) )
+ )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_begin_calchash(gconstpointer k)
+{
+ const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
+ guint hashkey;
+ /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+ hashkey = key->tid;
+ return hashkey;
+}
+
+static gint
+tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
+ const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->src_tid == key2->src_tid) &&
+ (key1->dst_tid == key2->dst_tid) ) {
+ return TRUE;
+ }
+ else if ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->src_tid == key2->dst_tid) &&
+ (key1->dst_tid == key2->src_tid) ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_cont_calchash(gconstpointer k)
+{
+ const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->src_tid + key->dst_tid;
+ return hashkey;
+}
+
+
+static gint
+tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
+ const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_end_calchash(gconstpointer k)
+{
+ const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->tid;
+ return hashkey;
+}
+
+static gint
+tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
+ const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) )
+ )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_ansi_calchash(gconstpointer k)
+{
+ const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
+ guint hashkey;
+ /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+ hashkey = key->tid;
+ return hashkey;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
+ packet_info *pinfo)
+{
+ p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_tcaphash_begincall->context->last_frame = 0;
+ p_tcaphash_begincall->context->responded = FALSE;
+ p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_begincall_t *
+append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
+ struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
+ p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=prev_begincall;
+ p_new_tcaphash_begincall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_begincall->next_begincall = p_new_tcaphash_begincall;
+ if (prev_begincall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"last ");
+#endif
+ prev_begincall->context->last_frame = pinfo->fd->num-1;
+ }
+ return p_new_tcaphash_begincall;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
+ packet_info *pinfo)
+{
+ p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+ p_tcaphash_ansicall->context->last_frame = 0;
+ p_tcaphash_ansicall->context->responded = FALSE;
+ p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_ansicall_t *
+append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
+ struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+ p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+ p_new_tcaphash_ansicall->context=p_tcaphash_context;
+ p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+ p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
+ p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+ p_new_tcaphash_ansicall->next_ansicall=NULL;
+ p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
+ p_new_tcaphash_ansicall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
+ if (prev_ansicall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"last ");
+#endif
+ prev_ansicall->context->last_frame = pinfo->fd->num-1;
+ }
+ return p_new_tcaphash_ansicall;
+}
+
+
+static struct tcaphash_contcall_t *
+append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+ p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=prev_contcall;
+ p_new_tcaphash_contcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_contcall->next_contcall = p_new_tcaphash_contcall;
+ return p_new_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+ p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=prev_endcall;
+ p_new_tcaphash_endcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_endcall->next_endcall = p_new_tcaphash_endcall;
+ return p_new_tcaphash_endcall;
+}
+
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct tcaphash_begincall_t *
+find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+ packet_info *pinfo, gboolean isBegin)
+{
+ struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
+
+ if(p_tcaphash_begincall) {
+ do {
+ if ( p_tcaphash_begincall->context ) {
+ if ( ( isBegin &&
+ pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
+ ||
+ ( !isBegin &&
+ pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
+ ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
+#endif
+ return p_tcaphash_begincall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_begincall->next_begincall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Blist ");
+#endif
+ break;
+ }
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Bhash ");
+#endif
+ }
+ return NULL;
+}
+
+
+
+static struct tcaphash_contcall_t *
+find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+ p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if(p_tcaphash_contcall) {
+ do {
+ if ( p_tcaphash_contcall->context ) {
+ if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
+ (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
+#endif
+ return p_tcaphash_contcall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_contcall->next_contcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Clist ");
+#endif
+ break;
+ }
+ p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
+ } while (p_tcaphash_contcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Chash ");
+#endif
+ }
+ return NULL;
+}
+
+static struct tcaphash_endcall_t *
+find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ packet_info *pinfo, gboolean isEnd)
+{
+ struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+ p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if(p_tcaphash_endcall) {
+ do {
+ if ( p_tcaphash_endcall->context ) {
+ if ( ( isEnd &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
+ )
+ ||
+ ( !isEnd &&
+ pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
+#endif
+ return p_tcaphash_endcall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_endcall->next_endcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Elist ");
+#endif
+ break;
+ }
+ p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
+ } while (p_tcaphash_endcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Ehash ");
+#endif
+ }
+ return NULL;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_context_t *
+new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_context_key_t *p_new_tcaphash_context_key;
+ struct tcaphash_context_t *p_new_tcaphash_context = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
+#else
+ p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
+#endif
+ p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
+#else
+ p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
+#endif
+ p_new_tcaphash_context->key = p_new_tcaphash_context_key;
+ p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
+ p_new_tcaphash_context->first_frame = pinfo->fd->num;
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"S%d ", p_new_tcaphash_context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
+ return p_new_tcaphash_context;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_begincall_t *
+new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
+#else
+ p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
+#endif
+ p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
+ p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
+ p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
+ p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+ p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->father=TRUE;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
+ return p_new_tcaphash_begincall;
+}
+
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_contcall_t *
+new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
+ struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
+#else
+ p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
+#endif
+ p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
+ p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
+ p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
+ p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
+ p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+ p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+ p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->father=TRUE;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
+ return p_new_tcaphash_contcall;
+}
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_endcall_t *
+new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
+ struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
+#else
+ p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
+#endif
+ p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
+ p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
+ p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
+ p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+ p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+ p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->father=TRUE;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
+ return p_new_tcaphash_endcall;
+}
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_ansicall_t *
+new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
+ struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
+#else
+ p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
+#endif
+ p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
+ p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
+ p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
+ p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+ p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+ p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
+ p_new_tcaphash_ansicall->context=p_tcaphash_context;
+ p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+ p_new_tcaphash_ansicall->father=TRUE;
+ p_new_tcaphash_ansicall->next_ansicall=NULL;
+ p_new_tcaphash_ansicall->previous_ansicall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
+ return p_new_tcaphash_ansicall;
+}
+
+static struct tcaphash_contcall_t *
+create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
+ struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+
+ p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
+ g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if (p_tcaphash_contcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_contcall1->next_contcall) {
+ p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
+ p_tcaphash_context);
+ break;
+ }
+ p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
+ } while (p_tcaphash_contcall1 != NULL );
+ } else {
+ p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
+ p_tcaphash_context);
+ }
+ return p_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
+ struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+
+ p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
+ g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if (p_tcaphash_endcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_endcall1->next_endcall) {
+ p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
+ p_tcaphash_context);
+ break;
+ }
+ p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
+ } while (p_tcaphash_endcall1 != NULL );
+ } else {
+ p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
+ p_tcaphash_context);
+ }
+ return p_tcaphash_endcall;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+tcapsrt_init_routine(void)
+{
+
+ /* free hash-table for SRT */
+ if (tcaphash_context != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_context \n");
+#endif
+ g_hash_table_destroy(tcaphash_context);
+ }
+
+ if (tcaphash_begin != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_begin \n");
+#endif
+ g_hash_table_destroy(tcaphash_begin);
+ }
+
+ if (tcaphash_cont != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_cont \n");
+#endif
+ g_hash_table_destroy(tcaphash_cont);
+ }
+
+ if (tcaphash_end != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_end \n");
+#endif
+ g_hash_table_destroy(tcaphash_end);
+ }
+
+ if (tcaphash_ansi != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_ansi \n");
+#endif
+ g_hash_table_destroy(tcaphash_ansi);
+ }
+
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Create hash \n");
+#endif
+ /* create new hash-tables for SRT */
+ tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
+ tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
+ tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
+ tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
+ tcaphash_ansi = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
+
+ /* Reset the session counter */
+ tcapsrt_global_SessionId=1;
+
+ /* Display of SRT only if Persistent Stat */
+ gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT>cap_StatSRT;
+}
+
+/*
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_context_key_t tcaphash_context_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ proto_item *pi;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+ /* prepare the key data */
+ tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+ /* look up the request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
+ dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)
+ g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
+
+ if (p_tcaphash_begincall) {
+ /* Walk through list of transaction with identical keys */
+ do {
+ /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
+ if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Already seen ");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ break;
+ }
+ /* If the last record for Tcap transaction with identifier has not been reached */
+ if (!p_tcaphash_begincall->next_begincall) {
+ /* check if we have to create a new record or not */
+ /* if last request has been responded (response number is known)
+ and this request appears after last response (has bigger frame number)
+ and last request occurred after the timeout for repetition,
+ or
+ if last request hasn't been responded (so number unknown)
+ and this request appears after last request (has bigger frame number)
+ and this request occurred after the timeout for message lost */
+ if ( ( p_tcaphash_begincall->context->last_frame != 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
+ ) ||
+ ( p_tcaphash_begincall->context->last_frame == 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
+ )
+ )
+ {
+ /* we decide that we have a new request */
+ /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+ } else { /* timeout or message lost */
+
+ /* If the Tid is reused for a closed Transaction */
+ /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
+ /* (this is the case, for pre-arranged END, the transaction is marked as closed */
+ /* by the upper layer, thank to a callback method close) */
+ if ( p_tcaphash_begincall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+
+ } else {
+ /* the TCAP session is not closed, so, either messages have been lost */
+ /* or it's a duplicate request. Mark it as such. */
+#ifdef DEBUG_TCAPSRT
+ dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Duplicate with session %u in frame %u",
+ p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ return p_tcaphash_context;
+ } /* Previous session closed */
+ } /* test with Timeout or message Lost */
+ break;
+ } /* Next call is NULL */
+ /* Repeat the tests for the next record with the same transaction identifier */
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL );
+ /*
+ * End of analyze for the list be TC_BEGIN with same transaction ID
+ */
+ } else { /* p_tcaphash_begincall has not been found */
+ /*
+ * Create a new TCAP context
+ */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
+#endif
+
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
+ }
+
+ /* display tcap session, if available */
+ if ( gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ /* add link to response frame, if available */
+ /* p_tcaphash_begincall->context->last_frame) */
+ if( p_tcaphash_context->last_frame != 0 ){
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
+#endif
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+ p_tcaphash_context->last_frame,
+ "End of session in frame %u",
+ p_tcaphash_context->last_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ }
+ return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the source and destination
+* Identifier given in the TC_CONT
+* If nothing is found, it is probably a session in opening state, so try to find
+* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
+* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
+* and display the available info for the TCAP context
+*/
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_contcall_t *p_tcaphash_contcall;
+ struct tcaphash_cont_info_key_t tcaphash_cont_key;
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall;
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ proto_item *pi;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hcont #%u ", pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
+ tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
+#endif
+ p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
+ if(p_tcaphash_contcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CFound ");
+#endif
+ p_tcaphash_context=p_tcaphash_contcall->context;
+ } else { /* cont not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CnotFound ");
+#endif
+ /* Find the TCAP transaction according to the TC_BEGIN */
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
+ if(!p_tcaphash_begincall){
+ /* Do we have a continue from the same source? */
+ tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ }
+ if(p_tcaphash_begincall &&
+ !p_tcaphash_begincall->context->contcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BFound \n");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ p_tcaphash_context->responded=TRUE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
+ dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
+#endif
+ create_tcaphash_cont(&tcaphash_cont_key,
+ p_tcaphash_begincall->context);
+
+ tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ create_tcaphash_end(&tcaphash_end_key,
+ p_tcaphash_begincall->context);
+
+ } else { /* Begin not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BnotFound ");
+#endif
+ } /* begin found */
+ } /* cont found */
+ /* display tcap session, if available */
+ if (gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+ return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
+* If nothing is found,
+* - either it is a session in opening state,
+* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
+* so try to find a tcap session registered with a TC_BEGIN "key",
+* matching the destination Id of the TC_END
+* Then associate the TC_CONT "key" to the TCAP context
+* and display the available info for the TCAP context
+*/
+
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
+
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
+ proto_item *pi;
+ nstime_t delta;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hend #%u ", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_end_key.tid);
+#endif
+ p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
+
+ if(!p_tcaphash_endcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"EnotFound ");
+#endif
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ if(!p_tcaphash_begincall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BnotFound ");
+#endif
+ }
+ }
+ if (p_tcaphash_endcall) {
+ /* Use the TC_BEGIN Destination reference */
+ p_tcaphash_context=p_tcaphash_endcall->context;
+ } else if (p_tcaphash_begincall) {
+ /* Use the TC_BEGIN Source reference */
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ }
+
+ if (p_tcaphash_context) {
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if (gtcap_DisplaySRT && stat_tree) {
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ /* Close the context and remove it (if needed) */
+ tcapsrt_close(p_tcaphash_context,pinfo);
+
+ } else {/* context present */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Context notFound ");
+#endif
+ }
+ return p_tcaphash_context;
+}
+/*
+ * ANSI PART
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_context_key_t tcaphash_context_key;
+ struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
+ struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
+ proto_item *pi;
+ nstime_t delta;
+ gboolean isResponse=FALSE;
+ proto_tree * stat_tree=NULL;
+ proto_item * stat_item=NULL;
+
+ /* prepare the key data */
+ tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
+
+ /* look up the request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hansi #%u ", pinfo->fd->num);
+ dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
+#endif
+ p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
+ g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
+
+ if (p_tcaphash_ansicall) {
+ /* Walk through list of transaction with identical keys */
+ do {
+ /* Check if the request with this reqSeqNum has been seen */
+ if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Request already seen ");
+#endif
+ isResponse=FALSE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ break;
+ }
+
+ /* Check if the reponse with this reqSeqNum has been seen */
+ if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
+ /* We have seen this response before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Response already seen ");
+#endif
+ isResponse=TRUE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ break;
+ }
+
+ /* Check for the first Request without Response
+ received before this frame */
+ if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
+ p_tcaphash_ansicall->context->last_frame==0 ) {
+ /* Take it, and update the context */
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+ p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
+ p_tcaphash_ansicall->context->responded = TRUE;
+ p_tcaphash_ansicall->context->closed = TRUE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ isResponse=TRUE;
+
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ break;
+ } /* Lastframe=0, so take it */
+
+
+ /* If the last record for Tcap transaction with identifier has been reached */
+ if (!p_tcaphash_ansicall->next_ansicall) {
+ /* check if we have to create a new record or not */
+ /* if last request has been responded (response number in known)
+ and this request appears after last response (has bigger frame number)
+ and last request occurred after the timeout for repetition,
+ or
+ if last request hasn't been responded (so number unknown)
+ and this request appears after last request (has bigger frame number)
+ and this request occurred after the timeout for message lost */
+ if ( ( p_tcaphash_ansicall->context->last_frame != 0
+ && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+ && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
+ ) ||
+ ( p_tcaphash_ansicall->context->last_frame == 0
+ && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+ && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
+ )
+ )
+ {
+ /* we decide that we have a new request */
+ /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+ update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+ p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+ } else {
+
+ /* If the Tid is reused for a closed Transaction */
+ if ( p_tcaphash_ansicall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
+#endif
+ update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+ p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+
+ } else {
+ /* the Tid is reused for an opened Transaction */
+ /* so, this is the reply to the request of our context */
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ } /* test with Timeout */
+ } /* closed */
+ break;
+ } /* Next call is NULL */
+ p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
+ } while (p_tcaphash_ansicall != NULL );
+ /*
+ * New TCAP context
+ */
+ } else { /* p_tcaphash_ansicall has not been found */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
+ }
+
+ /* display tcap session, if available */
+ if ( gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+
+ /* add link to response frame, if available */
+ if( gtcap_DisplaySRT && stat_tree &&
+ p_tcaphash_ansicall->context->last_frame != 0){
+ if (!isResponse) { /* Request */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
+#endif
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+ p_tcaphash_ansicall->context->last_frame,
+ "End of session in frame %u",
+ p_tcaphash_ansicall->context->last_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ } else { /* Response */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if (gtcap_DisplaySRT) {
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ } /* Request or Response */
+ }
+ return p_tcaphash_context;
+}
+
+/*
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t *
+tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *tcap_context=NULL;
+
+ /* if this packet isn't loaded because of a read filter, don't output anything */
+ if(pinfo == NULL || pinfo->fd->num == 0) {
+ return NULL;
+ }
+
+ switch (p_tcapsrt_info->ope) {
+
+ case TC_BEGIN:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_BEGIN ");
+#endif
+ tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_CONT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_CONT ");
+#endif
+ tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_ABORT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_ABORT ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_END:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_END ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_ANSI_ALL:
+ case TC_ANSI_ABORT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_ANSI ");
+#endif
+ tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ default:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
+#endif
+ break;
+ } /* switch tcapop */
+#ifdef DEBUG_TCAPSRT
+ if (tcap_context)
+ dbg(1,"session %d ", tcap_context->session_id);
+#endif
+ return tcap_context;
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t *
+tcapsrt_razinfo(void)
+{
+ struct tcapsrt_info_t *p_tcapsrt_info ;
+
+ /* Global buffer for packet extraction */
+ tcapsrt_global_current++;
+ if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
+ tcapsrt_global_current=0;
+ }
+
+ p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
+ memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
+
+ return p_tcapsrt_info;
+}
+
+void
+tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"Force close ");
+#endif
+ if (p_tcaphash_context) {
+ p_tcaphash_context->responded=TRUE;
+ p_tcaphash_context->last_frame = pinfo->fd->num;
+ p_tcaphash_context->end_time = pinfo->fd->abs_ts;
+ p_tcaphash_context->closed=TRUE;
+
+ /* If the endkey is present */
+ if (p_tcaphash_context->endcall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->endcall->next_endcall) {
+ if (p_tcaphash_context->endcall->previous_endcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Ehash ");
+#endif
+ p_tcaphash_context->endcall->previous_endcall->next_endcall
+ = p_tcaphash_context->endcall->next_endcall;
+ p_tcaphash_context->endcall->next_endcall->previous_endcall
+ = p_tcaphash_context->endcall->previous_endcall;
+ g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->endcall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Ehash ");
+#endif
+ } /* no previous link, so father */
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Ehash ");
+#endif
+ g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->endcall->endkey);
+ g_free(p_tcaphash_context->endcall);
+#endif
+
+ } /* endcall without chained string */
+ } /* no endcall */
+
+
+ /* If the contkey is present */
+ if (p_tcaphash_context->contcall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->contcall->next_contcall) {
+ if (p_tcaphash_context->contcall->previous_contcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Chash ");
+#endif
+ p_tcaphash_context->contcall->previous_contcall->next_contcall
+ = p_tcaphash_context->contcall->next_contcall;
+ p_tcaphash_context->contcall->next_contcall->previous_contcall
+ = p_tcaphash_context->contcall->previous_contcall;
+ g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->contcall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Chash ");
+#endif
+ } /* no previous link, so father */
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Chash ");
+#endif
+ g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->contcall->contkey);
+ g_free(p_tcaphash_context->contcall);
+#endif
+ } /* contcall without chained string */
+ } /* no contcall */
+
+
+ /* If the beginkey is present */
+ if (p_tcaphash_context->begincall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->begincall->next_begincall) {
+ if (p_tcaphash_context->begincall->previous_begincall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Bhash ");
+#endif
+ p_tcaphash_context->begincall->previous_begincall->next_begincall
+ = p_tcaphash_context->begincall->next_begincall;
+ p_tcaphash_context->begincall->next_begincall->previous_begincall
+ = p_tcaphash_context->begincall->previous_begincall;
+ g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->begincall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Bhash ");
+#endif
+ }
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Bhash ");
+#endif
+ g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->begincall->beginkey);
+ g_free(p_tcaphash_context->begincall);
+#endif
+ } /* begincall without chained string */
+ } /* no begincall */
+
+ /* If the ansikey is present */
+ if (p_tcaphash_context->ansicall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->ansicall->next_ansicall) {
+ if (p_tcaphash_context->ansicall->previous_ansicall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Ahash ");
+#endif
+ p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
+ = p_tcaphash_context->ansicall->next_ansicall;
+ p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
+ = p_tcaphash_context->ansicall->previous_ansicall;
+ g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->ansicall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Ahash ");
+#endif
+ }
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Ahash ");
+#endif
+ g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->ansicall->ansikey);
+ g_free(p_tcaphash_context->ansicall);
+#endif
+ } /* ansicall without chained string */
+ } /* no ansicall */
+
+ if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove context ");
+#endif
+ g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->key);
+ g_free(p_tcaphash_context);
+#endif
+ }
+ } else { /* no context */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"No context to remove ");
+#endif
+ }
+}
const value_string tcap_component_type_str[] = {
{ TCAP_COMP_INVOKE, "Invoke" },
gchar *TransactionID_str;
};
+/** @file
+ * lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-calls
+ */
+
+#define LENGTH_OID 23
+struct tcaphash_context_t {
+ struct tcaphash_context_key_t * key;
+ guint32 session_id;
+ guint32 first_frame;
+ guint32 last_frame;
+ nstime_t begin_time; /**< time of arrival of TC_BEGIN */
+ nstime_t end_time; /**< time of closing message */
+ gboolean responded; /**< true, if request has been responded */
+ gboolean closed;
+ gboolean upper_dissector;
+ gboolean oid_present;
+ gchar oid[LENGTH_OID+1];
+ gboolean subdissector_present;
+ dissector_handle_t subdissector_handle;
+ void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
+ struct tcaphash_begincall_t * begincall;
+ struct tcaphash_contcall_t * contcall;
+ struct tcaphash_endcall_t * endcall;
+ struct tcaphash_ansicall_t * ansicall;
+};
+
+struct tcaphash_begincall_t {
+ struct tcaphash_begin_info_key_t * beginkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_begincall_t * next_begincall;
+ struct tcaphash_begincall_t * previous_begincall;
+};
+
+struct tcaphash_contcall_t {
+ struct tcaphash_cont_info_key_t * contkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_contcall_t * next_contcall;
+ struct tcaphash_contcall_t * previous_contcall;
+};
+
+struct tcaphash_endcall_t {
+ struct tcaphash_end_info_key_t * endkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_endcall_t * next_endcall;
+ struct tcaphash_endcall_t * previous_endcall;
+};
+
+struct tcaphash_ansicall_t {
+ struct tcaphash_ansi_info_key_t * ansikey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_ansicall_t * next_ansicall;
+ struct tcaphash_ansicall_t * previous_ansicall;
+};
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct tcaphash_context_key_t {
+ guint32 session_id;
+};
+
+struct tcaphash_begin_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_cont_info_key_t {
+ guint32 hashKey;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_end_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_ansi_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+
+/** List of infos to store for the analyse */
+struct tcapsrt_info_t {
+ guint32 tcap_session_id;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint8 ope;
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void tcapsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+ packet_info * pinfo _U_);
+
+/**
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcap_info);
+
+WS_DLL_PUBLIC gboolean gtcap_StatSRT;
+
extern gint tcap_standard;
extern const value_string tcap_component_type_str[];
app_mem_usage.c
asn1.c
atalk-utils.c
- camel-persistentdata.c
charsets.c
circuit.c
column.c
stream.c
t35.c
tap.c
- tcap-persistentdata.c
timestamp.c
timestats.c
tfs.c
app_mem_usage.c \
asn1.c \
atalk-utils.c \
- camel-persistentdata.c \
charsets.c \
circuit.c \
column.c \
stream.c \
t35.c \
tap.c \
- tcap-persistentdata.c \
timestamp.c \
timestats.c \
tfs.c \
atalk-utils.h \
ax25_pids.h \
bridged_pids.h \
- camel-persistentdata.h \
charsets.h \
chdlctypes.h \
circuit.h \
t35.h \
tap.h \
tap-voip.h \
- tcap-persistentdata.h \
timestamp.h \
timestats.h \
tfs.h \
+++ /dev/null
-/*
- * camel-persistentdata.c
- * Source for lists and hash tables used in wireshark's camel dissector
- * for calculation of delays in camel calls
- * Copyright 2006 Florent Drouin
- *
- * $Id$
- *
- * 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 <glib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <epan/emem.h>
-#include <epan/packet.h>
-#include <epan/tap.h>
-#include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
-#include <epan/dissectors/packet-tcap.h>
-#include <epan/dissectors/packet-mtp3.h>
-
-const value_string camelSRTtype_naming[]= {
- { CAMELSRT_SESSION, "TCAP_Session" },
- { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
- { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
- { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
- { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
- { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
- { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
- { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
- { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
- { 0,NULL}
-};
-
-static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
-static guint camelsrt_call_hash(gconstpointer k);
-static struct camelsrt_call_t *find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
-static struct camelsrt_call_t *new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
-
-static void update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call,
- packet_info *pinfo, guint msg_category);
-
-static void camelsrt_begin_call_matching(packet_info *pinfo,
- struct camelsrt_info_t *p_camelsrt_info);
-
-static void camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree,
- struct camelsrt_info_t *p_camelsrt_info,
- guint srt_type);
-
-static void camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree,
- struct camelsrt_info_t *p_camelsrt_info,
- guint srt_type);
-
-static void camelsrt_close_call_matching(packet_info *pinfo,
- struct camelsrt_info_t *p_camelsrt_info);
-
-static void camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb,
- nstime_t *value_ptr, guint category);
-
-static void raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call);
-
-void camelsrt_tcap_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcaphash_context_t *tcap_context);
-
-/* When several Camel components are received in a single TCAP message,
- we have to use several buffers for the stored parameters
- because else this data are erased during TAP dissector call */
-#define MAX_CAMEL_INSTANCE 10
-int camelsrt_global_current=0;
-struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
-
-/* Configuration parameters to enable or disable the Service Response Time */
-extern gboolean gcamel_HandleSRT;
-gboolean gcamel_PersistentSRT=FALSE;
-gboolean gcamel_DisplaySRT=FALSE;
-gboolean gcamel_StatSRT=FALSE;
-
-extern int camel_tap;
-
-extern int hf_camelsrt_SessionId;
-extern int hf_camelsrt_RequestNumber;
-extern int hf_camelsrt_Duplicate;
-extern int hf_camelsrt_RequestFrame;
-extern int hf_camelsrt_ResponseFrame;
-extern int hf_camelsrt_DeltaTime;
-extern int hf_camelsrt_SessionTime;
-extern int hf_camelsrt_DeltaTime31;
-extern int hf_camelsrt_DeltaTime75;
-extern int hf_camelsrt_DeltaTime65;
-extern int hf_camelsrt_DeltaTime22;
-extern int hf_camelsrt_DeltaTime35;
-extern int hf_camelsrt_DeltaTime80;
-
-/* Global hash tables*/
-static GHashTable *srt_calls = NULL;
-guint32 camelsrt_global_SessionId=1;
-
-/*
- * DEBUG fonctions
- */
-
-#undef DEBUG_CAMELSRT
-/* #define DEBUG_CAMELSRT */
-
-#ifdef DEBUG_CAMELSRT
-#include <stdio.h>
-#include <stdarg.h>
-static guint debug_level = 99;
-
-static void dbg(guint level, char *fmt, ...) {
- va_list ap;
-
- if (level > debug_level) return;
- va_start(ap,fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-#endif
-
-/*
- * Functions needed for Hash-Table
- */
-
-/* compare 2 keys */
-static gint
-camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct camelsrt_call_info_key_t *key1 = (const struct camelsrt_call_info_key_t *) k1;
- const struct camelsrt_call_info_key_t *key2 = (const struct camelsrt_call_info_key_t *) k2;
-
- return (key1->SessionIdKey == key2->SessionIdKey) ;
-}
-
-/* calculate a hash key */
-static guint
-camelsrt_call_hash(gconstpointer k)
-{
- const struct camelsrt_call_info_key_t *key = (const struct camelsrt_call_info_key_t *) k;
- return key->SessionIdKey;
-}
-
-/*
- * Find the dialog by Key and Time
- */
-static struct camelsrt_call_t *
-find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
-{
- struct camelsrt_call_t *p_camelsrt_call = NULL;
- p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
-
-#ifdef DEBUG_CAMELSRT
- if(p_camelsrt_call) {
- dbg(10,"D%d ", p_camelsrt_call->session_id);
- } else {
- dbg(23,"Not in hash ");
- }
-#endif
-
- return p_camelsrt_call;
-}
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct camelsrt_call_t *
-new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
-{
- struct camelsrt_call_info_key_t *p_new_camelsrt_call_key;
- struct camelsrt_call_t *p_new_camelsrt_call = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as main Key
- Once created, this entry will be updated later */
-
- p_new_camelsrt_call_key = se_new(struct camelsrt_call_info_key_t);
- p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
- p_new_camelsrt_call = se_new(struct camelsrt_call_t);
- raz_camelsrt_call(p_new_camelsrt_call);
- p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
-#ifdef DEBUG_CAMELSRT
- dbg(10,"D%d ", p_new_camelsrt_call->session_id);
-#endif
- /* store it */
- g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
- return p_new_camelsrt_call;
-}
-
-/*
- * Update a record with the data of the Request
- */
-static void
-update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
- guint msg_category)
-{
- p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
- p_camelsrt_call->category[msg_category].rsp_num = 0;
- p_camelsrt_call->category[msg_category].responded = FALSE;
- p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
-}
-
-
-/*
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void
-camelsrt_init_routine(void)
-{
-
- /* free hash-table for SRT */
- if (srt_calls != NULL) {
-#ifdef DEBUG_CAMELSRT
- dbg(16,"Destroy hash ");
-#endif
- g_hash_table_destroy(srt_calls);
- }
-
- /* create new hash-table for SRT */
- srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
-#ifdef DEBUG_CAMELSRT
- dbg(16,"Create hash ");
-#endif
- /* Reset the session counter */
- camelsrt_global_SessionId=1;
-
- /* The Display of SRT is enable
- * 1) For wireshark only if Persistent Stat is enable
- * 2) For Tshark, if the SRT handling is enable
- */
- gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
-}
-
-/*
- * Service Response Time analyze, called just after the camel dissector
- * According to the camel operation, we
- * - open/close a context for the camel session
- * - look for a request, or look for the corresponding response
- */
-void
-camelsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct camelsrt_info_t *p_camelsrt_info)
-{
-
-#ifdef DEBUG_CAMELSRT
- dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
-#endif
-
- switch (p_camelsrt_info->opcode) {
-
- case 0: /*InitialDP*/
- camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_INITIALDP);
- break;
- case 60: /*InitialDPSMS*/
- camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_SMS_INITIALDP);
- break;
- case 78: /*InitialDPGPRS*/
- camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_GPRS_INITIALDP);
- break;
-
- case 23: /*RequestReportBCSMEvent*/
- break;
-
- case 63: /*RequestReportSMSEvent*/
- break;
-
- case 81: /*RequestReportGPRSEvent*/
- break;
-
- case 24: /*EventReportBCSMEvent*/
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_DISC );
- break;
-
- case 64: /*EventReportSMS*/
- /* Session has been explicity closed without TC_END */
- camelsrt_close_call_matching(pinfo, p_camelsrt_info);
- tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
- break;
-
- case 80: /*EventReportGPRS*/
- camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_GPRS_REPORT);
- break;
-
- case 35: /*ApplyCharging*/
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_ACR1 );
- break;
-
- case 71: /*ApplyChargingGPRS*/
- break;
-
- case 36: /*ApplyChargingReport*/
- camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_ACR1 );
- break;
-
- case 72: /*ApplyChargingReportGPRS*/
- break;
-
- case 31: /*Continue*/
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_INITIALDP);
- break;
- case 65: /*ContinueSMS*/
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_SMS_INITIALDP);
- break;
- case 75: /*ContinueGPRS*/
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_GPRS_INITIALDP);
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_GPRS_REPORT);
- break;
-
- case 22: /*ReleaseCall*/
- camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
- CAMELSRT_VOICE_DISC);
- /* Session has been closed by Network */
- camelsrt_close_call_matching(pinfo, p_camelsrt_info);
- break;
-
- case 66: /*ReleaseSMS*/
- /* Session has been closed by Network */
- camelsrt_close_call_matching(pinfo, p_camelsrt_info);
- tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
- break;
-
- case 79: /*ReleaseGPRS*/
- /* Session has been closed by Network */
- camelsrt_close_call_matching(pinfo, p_camelsrt_info);
- break;
- } /* switch opcode */
-}
-
-/*
- * Callback function for the TCAP dissector
- * This callback function is used to inform the camel layer, that the session
- * has been Closed or Aborted by a TCAP message without Camel component
- * So, we can close the context for camel session, and update the stats.
- */
-void
-camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
- proto_tree *tree _U_,
- struct tcaphash_context_t *p_tcap_context)
-{
- struct camelsrt_info_t *p_camelsrt_info;
-
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Camel_CallBack ");
-#endif
- p_camelsrt_info=camelsrt_razinfo();
-
- p_camelsrt_info->tcap_context=p_tcap_context;
- if (p_tcap_context) {
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Close TCAP ");
-#endif
- p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
- camelsrt_close_call_matching(pinfo, p_camelsrt_info);
- tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
- }
-}
-
-
-/*
- * Create the record identifiying the Camel session
- * As the Tcap session id given by the TCAP dissector is uniq, it will be
- * used as main key.
- */
-static void
-camelsrt_begin_call_matching(packet_info *pinfo,
- struct camelsrt_info_t *p_camelsrt_info)
-{
- struct camelsrt_call_t *p_camelsrt_call;
- struct camelsrt_call_info_key_t camelsrt_call_key;
-
- p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
-
- /* prepare the key data */
- camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
-
- /* look up the request */
-#ifdef DEBUG_CAMELSRT
- dbg(10,"\n Session begin #%u\n", pinfo->fd->num);
- dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
-#endif
- p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
- if (p_camelsrt_call) {
- /* We have seen this request before -> do nothing */
-#ifdef DEBUG_CAMELSRT
- dbg(22,"Already seen ");
-#endif
- } else { /* p_camelsrt_call has not been found */
-#ifdef DEBUG_CAMELSRT
- dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
-#endif
- p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key);
- p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)p_camelsrt_info->tcap_context;
- update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
-
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Update Callback ");
-#endif
- p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
- }
-}
-
-/*
- * Register the request, and try to find the response
- *
- */
-static void
-camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree,
- struct camelsrt_info_t *p_camelsrt_info,
- guint srt_type )
-{
- struct camelsrt_call_t *p_camelsrt_call;
- struct camelsrt_call_info_key_t camelsrt_call_key;
- proto_item *ti, *hidden_item;
-
-#ifdef DEBUG_CAMELSRT
- dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
-#endif
-
- /* look only for matching request, if matching conversation is available. */
- camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
-
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
-#endif
- p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
- if(p_camelsrt_call) {
-#ifdef DEBUG_CAMELSRT
- dbg(12,"Found ");
-#endif
- if (gcamel_DisplaySRT)
- proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
-
-
- /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
- * we will prepare the measurement for 3 slices with 3 categories */
- if (srt_type==CAMELSRT_VOICE_ACR1) {
- if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
- srt_type=CAMELSRT_VOICE_ACR1;
- } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
- && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
- && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
- srt_type=CAMELSRT_VOICE_ACR2;
- } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
- && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
- && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
- srt_type=CAMELSRT_VOICE_ACR3;
- } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR1;
- } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR2;
- } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR3;
- }
-#ifdef DEBUG_CAMELSRT
- dbg(70,"Request ACR %u ",srt_type);
- dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
- dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
- dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
-#endif
- } /* not ACR */
- p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
-
-
- if (p_camelsrt_call->category[srt_type].req_num == 0) {
- /* We have not yet seen a request to that call, so this must be the first request
- remember its frame number. */
-#ifdef DEBUG_CAMELSRT
- dbg(5,"Set reqlink #%u ", pinfo->fd->num);
-#endif
- update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
- } else {
- /* We have seen a request to this call - but was it *this* request? */
- if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
-
- if (srt_type!=CAMELSRT_VOICE_DISC) {
- /* No, so it's a duplicate resquest. Mark it as such. */
-#ifdef DEBUG_CAMELSRT
- dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
-#endif
- p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
- if (gcamel_DisplaySRT){
- hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
- PROTO_ITEM_SET_HIDDEN(hidden_item);
- }
-
- } else {
- /* Ignore duplicate frame */
- if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
- p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
-#ifdef DEBUG_CAMELSRT
- dbg(5,"DISC Set reqlink #%u ", pinfo->fd->num);
-#endif
- update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
- } /* greater frame */
- } /* DISC */
- } /* req_num already seen */
- } /* req_num != 0 */
-
- /* add link to response frame, if available */
- if ( gcamel_DisplaySRT &&
- (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
- (p_camelsrt_call->category[srt_type].req_num != 0) &&
- (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
-#ifdef DEBUG_CAMELSRT
- dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
-#endif
- ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
- p_camelsrt_call->category[srt_type].rsp_num,
- "Linked response %s in frame %u",
- val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
- p_camelsrt_call->category[srt_type].rsp_num);
- PROTO_ITEM_SET_GENERATED(ti);
- } /* frame valid */
- } /* call reference */
-}
-
-
-/*
- * Check if the received message is a response to a previous request
- * registered is the camel session context.
- */
-static void
-camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree,
- struct camelsrt_info_t *p_camelsrt_info,
- guint srt_type)
-{
- struct camelsrt_call_t *p_camelsrt_call;
- struct camelsrt_call_info_key_t camelsrt_call_key;
- nstime_t delta;
- proto_item *ti, *hidden_item;
-
-#ifdef DEBUG_CAMELSRT
- dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
-#endif
- camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
- /* look only for matching request, if matching conversation is available. */
-
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
-#endif
- p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
- if(p_camelsrt_call) {
-#ifdef DEBUG_CAMELSRT
- dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
-#endif
- if ( gcamel_DisplaySRT )
- proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
-
- if (srt_type==CAMELSRT_VOICE_ACR1) {
- if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR1;
- } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR2;
- } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
- && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
- srt_type=CAMELSRT_VOICE_ACR1;
- }
-#ifdef DEBUG_CAMELSRT
- dbg(70,"Report ACR %u ",srt_type);
-#endif
- } /* not ACR */
- p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
-
- if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
- if ( (p_camelsrt_call->category[srt_type].req_num != 0)
- && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
- /* We have not yet seen a response to that call, so this must be the first response;
- remember its frame number only if response comes after request */
-#ifdef DEBUG_CAMELSRT
- dbg(14,"Set reslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
-#endif
- p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
-
- } else {
-#ifdef DEBUG_CAMELSRT
- dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
-#endif
- } /* req_num != 0 */
- } else { /* rsp_num != 0 */
- /* We have seen a response to this call - but was it *this* response? */
- if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
- /* No, so it's a duplicate response. Mark it as such. */
-#ifdef DEBUG_CAMELSRT
- dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
-#endif
- p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
- if ( gcamel_DisplaySRT ){
- hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
- PROTO_ITEM_SET_HIDDEN(hidden_item);
- }
- }
- } /* rsp_num != 0 */
-
- if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
- (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
- (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
-
- p_camelsrt_call->category[srt_type].responded = TRUE;
- p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
-#ifdef DEBUG_CAMELSRT
- dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
-#endif
- /* Indicate the frame to which this is a reply. */
- if ( gcamel_DisplaySRT ) {
- ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
- p_camelsrt_call->category[srt_type].req_num,
- "Linked request %s in frame %u",
- val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
- p_camelsrt_call->category[srt_type].req_num);
- PROTO_ITEM_SET_GENERATED(ti);
- }
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
-
- p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
- p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
- p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
-
- /* display Service Response Time and make it filterable */
- camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
-
- } /*req_num != 0 && not duplicate */
- } /* call reference found */
-}
-
-/*
- * Update the Camel session info, and close the session.
- * Then remove the associated context, if we do not have persistentSRT enable
- */
-static void
-camelsrt_close_call_matching(packet_info *pinfo,
- struct camelsrt_info_t *p_camelsrt_info)
-{
- struct camelsrt_call_t *p_camelsrt_call;
- struct camelsrt_call_info_key_t camelsrt_call_key;
- nstime_t delta;
-
- p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
-#ifdef DEBUG_CAMELSRT
- dbg(10,"\n Session end #%u\n", pinfo->fd->num);
-#endif
- /* look only for matching request, if matching conversation is available. */
- camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
-
-#ifdef DEBUG_CAMELSRT
- dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
-#endif
- p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
- if(p_camelsrt_call) {
-#ifdef DEBUG_CAMELSRT
- dbg(12,"Found ");
-#endif
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
- p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
- p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
- p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
- p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
- p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
-
- if ( !gcamel_PersistentSRT ) {
- g_hash_table_remove(srt_calls, &camelsrt_call_key);
-#ifdef DEBUG_CAMELSRT
- dbg(20,"remove hash ");
-#endif
- } else {
-#ifdef DEBUG_CAMELSRT
- dbg(20,"keep hash ");
-#endif
- }
- } /* call reference found */
-}
-
-/*
- * Display the delta time between two messages in a field corresponding
- * to the category (hf_camelsrt_DeltaTimexx).
- */
-static void
-camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
- guint category)
-{
- proto_item *ti;
-
- if ( gcamel_DisplaySRT ) {
- switch(category) {
- case CAMELSRT_VOICE_INITIALDP:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- case CAMELSRT_VOICE_ACR1:
- case CAMELSRT_VOICE_ACR2:
- case CAMELSRT_VOICE_ACR3:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- case CAMELSRT_VOICE_DISC:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- case CAMELSRT_GPRS_INITIALDP:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- case CAMELSRT_GPRS_REPORT:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- case CAMELSRT_SMS_INITIALDP:
- ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
- PROTO_ITEM_SET_GENERATED(ti);
- break;
-
- default:
- break;
- }
- }
-}
-
-/*
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct camelsrt_info_t *
-camelsrt_razinfo(void)
-{
- struct camelsrt_info_t *p_camelsrt_info ;
-
- /* Global buffer for packet extraction */
- camelsrt_global_current++;
- if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
- camelsrt_global_current=0;
- }
-
- p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
- memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
-
- p_camelsrt_info->opcode=255;
-
- return p_camelsrt_info;
-}
-
-/*
- * Initialize the data per call for the Service Response Time Statistics
- * Data are linked to a Camel operation in a TCAP transaction
- */
-static void
-raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
-{
- memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
-}
+++ /dev/null
-/*
- * camel-persistentdata.h
- * Definitions for lists and hash tables used in wireshark's camel dissector
- * for calculation of delays in camel-transactions
- * Copyright 2006 Florent Drouin
- *
- * $Id$
- *
- * 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 __CAMEL_PERSISTENTDATA_H__
-#define __CAMEL_PERSISTENTDATA_H__
-
-#include <epan/packet.h>
-#include <epan/conversation.h>
-#include <epan/dissectors/packet-camel.h>
-#include <epan/tcap-persistentdata.h>
-#include "ws_symbol_export.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/** @file
-*/
-#define NB_CAMELSRT_CATEGORY 9+1 /**< Number of type of message */
-/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
- is a category, we want to measure the delay between the two messages */
-
-#define CAMELSRT_SESSION 1
-
-#define CAMELSRT_VOICE_INITIALDP 2
-#define CAMELSRT_VOICE_ACR1 3
-#define CAMELSRT_VOICE_ACR2 4
-#define CAMELSRT_VOICE_ACR3 5
-#define CAMELSRT_VOICE_DISC 6
-
-#define CAMELSRT_GPRS_INITIALDP 7
-#define CAMELSRT_GPRS_REPORT 8
-
-#define CAMELSRT_SMS_INITIALDP 9
-
-WS_DLL_PUBLIC const value_string camelSRTtype_naming[];
-
-/** If we have a request message and its response,
- (eg: ApplyCharging, ApplyChargingReport)
- the frames numbers are stored in this structure */
-
-struct camelsrt_category_t {
- guint32 req_num; /**< frame number request seen */
- guint32 rsp_num; /**< frame number response seen */
- nstime_t req_time; /**< arrival time of request */
- gboolean responded; /**< true, if request has been responded */
-};
-
-/** List of stored parameters for a Camel dialogue
- All this parameters are linked to the hash table key below (use of Tid)
- In case of same Tid reused, the Camel parameters are chained.
- The right dialogue will be identified with the arrival time of the InitialDP */
-
-struct camelsrt_call_t {
- guint32 session_id; /**< Identify the session, with an internal number */
- struct tcaphash_context_t * tcap_context;
- struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
-};
-
-
-/** The Key for the hash table is the TCAP origine transaction identifier
- of the TC_BEGIN containing the InitialDP */
-
-struct camelsrt_call_info_key_t {
- guint32 SessionIdKey;
-};
-
-/** Info for a couple of messages (or category)
- The request must be available, not duplicated,
- and once the corresponding response received,
- we can deduce the Delta Time between Request/response */
-
-struct camelsrt_msginfo_t {
- gboolean request_available;
- gboolean is_duplicate;
- gboolean is_delta_time;
- nstime_t req_time;
- nstime_t delta_time;
-};
-
-/** List of infos to store for the analyse */
-
-struct camelsrt_info_t {
- guint32 tcap_session_id;
- void * tcap_context;
- guint8 opcode; /**< operation code of message received */
- guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /**< category for the received message */
- struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
-};
-
-/**
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void camelsrt_init_routine(void);
-
-/**
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct camelsrt_info_t * camelsrt_razinfo(void);
-
-/**
- * Service Response Time analyze, called just after the camel dissector
- * According to the camel operation, we
- * - open/close a context for the camel session
- * - look for a request, or look for the corresponding response
- */
-void camelsrt_call_matching(tvbuff_t *tvb,
- packet_info * pinfo _U_,
- proto_tree *tree,
- struct camelsrt_info_t * p_camel_info);
-
-WS_DLL_PUBLIC gboolean gcamel_StatSRT;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* camel-persistentdata.h */
#include "packet-ber.h"
#include "packet-tcap.h"
#include "packet-ansi_tcap.h"
-#include <epan/tcap-persistentdata.h>
#define PNAME "ANSI Transaction Capabilities Application Part"
#define PSNAME "ANSI_TCAP"
static int hf_ansi_tcap_paramSet = -1; /* T_paramSet */
/*--- End of included file: packet-ansi_tcap-hf.c ---*/
-#line 66 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 65 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
/* Initialize the subtree pointers */
static gint ett_tcap = -1;
static gint ett_ansi_tcap_T_paramSet = -1;
/*--- End of included file: packet-ansi_tcap-ett.c ---*/
-#line 85 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 84 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
#define MAX_SSN 254
/*--- End of included file: packet-ansi_tcap-fn.c ---*/
-#line 353 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 352 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
NULL, HFILL }},
/*--- End of included file: packet-ansi_tcap-hfarr.c ---*/
-#line 489 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 488 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
};
/* Setup protocol subtree array */
&ett_ansi_tcap_T_paramSet,
/*--- End of included file: packet-ansi_tcap-ettarr.c ---*/
-#line 500 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 499 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
};
static const enum_val_t ansi_tcap_response_matching_type_values[] = {
#include "packet-gsm_a_common.h"
#include "packet-inap.h"
#include "packet-tcap.h"
-#include <epan/camel-persistentdata.h>
-#include <epan/tcap-persistentdata.h>
#define PNAME "Camel"
#define PSNAME "CAMEL"
static guint32 opcode=0;
static guint32 errorCode=0;
static guint32 camel_ver = 0;
+
+/* When several Camel components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_CAMEL_INSTANCE 10
+static int camelsrt_global_current=0;
+static struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
/* ROSE context */
static rose_ctx_t camel_rose_ctx;
static int hf_camel_CAMEL_SCIGPRSBillingChargingCharacteristics = -1;
static int hf_camel_CAMEL_CallResult = -1;
-/* Used by camel-persistentdata.c */
-int hf_camelsrt_SessionId=-1;
-int hf_camelsrt_RequestNumber=-1;
-int hf_camelsrt_Duplicate=-1;
-int hf_camelsrt_RequestFrame=-1;
-int hf_camelsrt_ResponseFrame=-1;
-int hf_camelsrt_DeltaTime=-1;
-int hf_camelsrt_SessionTime=-1;
-int hf_camelsrt_DeltaTime31=-1;
-int hf_camelsrt_DeltaTime75=-1;
-int hf_camelsrt_DeltaTime65=-1;
-int hf_camelsrt_DeltaTime22=-1;
-int hf_camelsrt_DeltaTime35=-1;
-int hf_camelsrt_DeltaTime80=-1;
+/* Used by persistent data */
+static int hf_camelsrt_SessionId=-1;
+static int hf_camelsrt_RequestNumber=-1;
+static int hf_camelsrt_Duplicate=-1;
+static int hf_camelsrt_RequestFrame=-1;
+static int hf_camelsrt_ResponseFrame=-1;
+static int hf_camelsrt_DeltaTime=-1;
+static int hf_camelsrt_SessionTime=-1;
+static int hf_camelsrt_DeltaTime31=-1;
+static int hf_camelsrt_DeltaTime75=-1;
+static int hf_camelsrt_DeltaTime65=-1;
+static int hf_camelsrt_DeltaTime22=-1;
+static int hf_camelsrt_DeltaTime35=-1;
+static int hf_camelsrt_DeltaTime80=-1;
/*--- Included file: packet-camel-hf.c ---*/
static int hf_camel_InvokeId_present = -1; /* InvokeId_present */
/*--- End of included file: packet-camel-hf.c ---*/
-#line 110 "../../asn1/camel/packet-camel-template.c"
+#line 116 "../../asn1/camel/packet-camel-template.c"
static struct camelsrt_info_t * gp_camelsrt_info;
static int dissect_camel_CAMEL_AChBillingChargingCharacteristicsV2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
static int dissect_camel_CAMEL_CallResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
-gboolean gcamel_HandleSRT=FALSE;
-extern gboolean gcamel_PersistentSRT;
-extern gboolean gcamel_DisplaySRT;
+static gboolean gcamel_HandleSRT=FALSE;
+static gboolean gcamel_PersistentSRT=FALSE;
+static gboolean gcamel_DisplaySRT=FALSE;
+static gboolean gcamel_StatSRT=FALSE;
/* Initialize the subtree pointers */
static gint ett_camel = -1;
static gint ett_camel_InvokeId = -1;
/*--- End of included file: packet-camel-ett.c ---*/
-#line 138 "../../asn1/camel/packet-camel-template.c"
+#line 145 "../../asn1/camel/packet-camel-template.c"
static expert_field ei_camel_unknown_invokeData = EI_INIT;
static expert_field ei_camel_unknown_returnResultData = EI_INIT;
const char *camel_obj_id = NULL;
gboolean is_ExtensionField =FALSE;
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+static guint32 camelsrt_global_SessionId=1;
+
static int camel_opcode_type;
#define CAMEL_OPCODE_INVOKE 1
#define CAMEL_OPCODE_RETURN_RESULT 2
{ 0, NULL }
};
+const value_string camelSRTtype_naming[]= {
+ { CAMELSRT_SESSION, "TCAP_Session" },
+ { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
+ { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
+ { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
+ { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
+ { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
+ { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
+ { 0,NULL}
+};
+
#if 0
static const true_false_string camel_extension_value = {
"No Extension",
#define noInvokeId NULL
/*--- End of included file: packet-camel-val.h ---*/
-#line 281 "../../asn1/camel/packet-camel-template.c"
+#line 305 "../../asn1/camel/packet-camel-template.c"
/*--- Included file: packet-camel-table.c ---*/
/*--- End of included file: packet-camel-table.c ---*/
-#line 283 "../../asn1/camel/packet-camel-template.c"
+#line 307 "../../asn1/camel/packet-camel-template.c"
+
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void dbg(guint level, char *fmt, ...) {
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
static char camel_number_to_char(int number)
{
/*--- End of included file: packet-camel-fn.c ---*/
-#line 330 "../../asn1/camel/packet-camel-template.c"
+#line 376 "../../asn1/camel/packet-camel-template.c"
/*--- Included file: packet-camel-table2.c ---*/
/*--- End of included file: packet-camel-table2.c ---*/
-#line 332 "../../asn1/camel/packet-camel-template.c"
+#line 378 "../../asn1/camel/packet-camel-template.c"
+
+/*
+ * Functions needed for Hash-Table
+ */
+
+/* compare 2 keys */
+static gint
+camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct camelsrt_call_info_key_t *key1 = (const struct camelsrt_call_info_key_t *) k1;
+ const struct camelsrt_call_info_key_t *key2 = (const struct camelsrt_call_info_key_t *) k2;
+
+ return (key1->SessionIdKey == key2->SessionIdKey) ;
+}
+
+/* calculate a hash key */
+static guint
+camelsrt_call_hash(gconstpointer k)
+{
+ const struct camelsrt_call_info_key_t *key = (const struct camelsrt_call_info_key_t *) k;
+ return key->SessionIdKey;
+}
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct camelsrt_call_t *
+find_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_t *p_camelsrt_call = NULL;
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
+
+#ifdef DEBUG_CAMELSRT
+ if(p_camelsrt_call) {
+ dbg(10,"D%d ", p_camelsrt_call->session_id);
+ } else {
+ dbg(23,"Not in hash ");
+ }
+#endif
+
+ return p_camelsrt_call;
+}
+
+/*
+ * Initialize the data per call for the Service Response Time Statistics
+ * Data are linked to a Camel operation in a TCAP transaction
+ */
+static void
+raz_camelsrt_call (struct camelsrt_call_t *p_camelsrt_call)
+{
+ memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct camelsrt_call_t *
+new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key)
+{
+ struct camelsrt_call_info_key_t *p_new_camelsrt_call_key;
+ struct camelsrt_call_t *p_new_camelsrt_call = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as main Key
+ Once created, this entry will be updated later */
+
+ p_new_camelsrt_call_key = se_new(struct camelsrt_call_info_key_t);
+ p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+ p_new_camelsrt_call = se_new(struct camelsrt_call_t);
+ raz_camelsrt_call(p_new_camelsrt_call);
+ p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"D%d ", p_new_camelsrt_call->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
+ return p_new_camelsrt_call;
+}
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+camelsrt_init_routine(void)
+{
+
+ /* free hash-table for SRT */
+ if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Destroy hash ");
+#endif
+ g_hash_table_destroy(srt_calls);
+ }
+
+ /* create new hash-table for SRT */
+ srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Create hash ");
+#endif
+ /* Reset the session counter */
+ camelsrt_global_SessionId=1;
+
+ /* The Display of SRT is enable
+ * 1) For wireshark only if Persistent Stat is enable
+ * 2) For Tshark, if the SRT handling is enable
+ */
+ gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
+}
+
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call, packet_info *pinfo,
+ guint msg_category)
+{
+ p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
+ p_camelsrt_call->category[msg_category].rsp_num = 0;
+ p_camelsrt_call->category[msg_category].responded = FALSE;
+ p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Update the Camel session info, and close the session.
+ * Then remove the associated context, if we do not have persistentSRT enable
+ */
+static void
+camelsrt_close_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session end #%u\n", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
+ p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
+
+ if ( !gcamel_PersistentSRT ) {
+ g_hash_table_remove(srt_calls, &camelsrt_call_key);
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"remove hash ");
+#endif
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"keep hash ");
+#endif
+ }
+ } /* call reference found */
+}
+
+/*
+ * Callback function for the TCAP dissector
+ * This callback function is used to inform the camel layer, that the session
+ * has been Closed or Aborted by a TCAP message without Camel component
+ * So, we can close the context for camel session, and update the stats.
+ */
+static void
+camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
+ proto_tree *tree _U_,
+ struct tcaphash_context_t *p_tcap_context)
+{
+ struct camelsrt_info_t *p_camelsrt_info;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Camel_CallBack ");
+#endif
+ p_camelsrt_info=camelsrt_razinfo();
+
+ p_camelsrt_info->tcap_context=p_tcap_context;
+ if (p_tcap_context) {
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Close TCAP ");
+#endif
+ p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
+ }
+}
+
+/*
+ * Create the record identifiying the Camel session
+ * As the Tcap session id given by the TCAP dissector is uniq, it will be
+ * used as main key.
+ */
+static void
+camelsrt_begin_call_matching(packet_info *pinfo,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+
+ /* prepare the key data */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+ /* look up the request */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session begin #%u\n", pinfo->fd->num);
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
+ if (p_camelsrt_call) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_CAMELSRT
+ dbg(22,"Already seen ");
+#endif
+ } else { /* p_camelsrt_call has not been found */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key);
+ p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)p_camelsrt_info->tcap_context;
+ update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Update Callback ");
+#endif
+ p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
+ }
+}
+
+/*
+ * Register the request, and try to find the response
+ *
+ */
+static void
+camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type )
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ if (gcamel_DisplaySRT)
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+
+ /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
+ * we will prepare the measurement for 3 slices with 3 categories */
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Request ACR %u ",srt_type);
+ dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
+ dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
+ dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+
+ if (p_camelsrt_call->category[srt_type].req_num == 0) {
+ /* We have not yet seen a request to that call, so this must be the first request
+ remember its frame number. */
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } else {
+ /* We have seen a request to this call - but was it *this* request? */
+ if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
+
+ if (srt_type!=CAMELSRT_VOICE_DISC) {
+ /* No, so it's a duplicate resquest. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if (gcamel_DisplaySRT){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+
+ } else {
+ /* Ignore duplicate frame */
+ if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
+ p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"DISC Set reqlink #%u ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } /* greater frame */
+ } /* DISC */
+ } /* req_num already seen */
+ } /* req_num != 0 */
+
+ /* add link to response frame, if available */
+ if ( gcamel_DisplaySRT &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].rsp_num,
+ "Linked response %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ } /* frame valid */
+ } /* call reference */
+}
+
+/*
+ * Display the delta time between two messages in a field corresponding
+ * to the category (hf_camelsrt_DeltaTimexx).
+ */
+static void
+camelsrt_display_DeltaTime(proto_tree *tree, tvbuff_t *tvb, nstime_t *value_ptr,
+ guint category)
+{
+ proto_item *ti;
+
+ if ( gcamel_DisplaySRT ) {
+ switch(category) {
+ case CAMELSRT_VOICE_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_ACR1:
+ case CAMELSRT_VOICE_ACR2:
+ case CAMELSRT_VOICE_ACR3:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_DISC:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_REPORT:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_SMS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Check if the received message is a response to a previous request
+ * registered is the camel session context.
+ */
+static void
+camelsrt_report_call_matching(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info,
+ guint srt_type)
+{
+ struct camelsrt_call_t *p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+ proto_item *ti, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%u\n", val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+ /* look only for matching request, if matching conversation is available. */
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ if ( gcamel_DisplaySRT )
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Report ACR %u ",srt_type);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+ if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0)
+ && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
+ /* We have not yet seen a response to that call, so this must be the first response;
+ remember its frame number only if response comes after request */
+#ifdef DEBUG_CAMELSRT
+ dbg(14,"Set reslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
+
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(2,"badreslink #%u req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ } /* req_num != 0 */
+ } else { /* rsp_num != 0 */
+ /* We have seen a response to this call - but was it *this* response? */
+ if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if ( gcamel_DisplaySRT ){
+ hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ }
+ }
+ } /* rsp_num != 0 */
+
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
+
+ p_camelsrt_call->category[srt_type].responded = TRUE;
+ p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if ( gcamel_DisplaySRT ) {
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].req_num,
+ "Linked request %s in frame %u",
+ val_to_str_const(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
+
+ p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
+
+ /* display Service Response Time and make it filterable */
+ camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
+
+ } /*req_num != 0 && not duplicate */
+ } /* call reference found */
+}
+
+/*
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void
+camelsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct camelsrt_info_t *p_camelsrt_info)
+{
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
+#endif
+
+ switch (p_camelsrt_info->opcode) {
+
+ case 0: /*InitialDP*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 60: /*InitialDPSMS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 78: /*InitialDPGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ break;
+
+ case 23: /*RequestReportBCSMEvent*/
+ break;
+
+ case 63: /*RequestReportSMSEvent*/
+ break;
+
+ case 81: /*RequestReportGPRSEvent*/
+ break;
+
+ case 24: /*EventReportBCSMEvent*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC );
+ break;
+
+ case 64: /*EventReportSMS*/
+ /* Session has been explicity closed without TC_END */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
+ break;
+
+ case 80: /*EventReportGPRS*/
+ camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 35: /*ApplyCharging*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 71: /*ApplyChargingGPRS*/
+ break;
+
+ case 36: /*ApplyChargingReport*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 72: /*ApplyChargingReportGPRS*/
+ break;
+
+ case 31: /*Continue*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 65: /*ContinueSMS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 75: /*ContinueGPRS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 22: /*ReleaseCall*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC);
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+
+ case 66: /*ReleaseSMS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
+ break;
+
+ case 79: /*ReleaseGPRS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+ break;
+ } /* switch opcode */
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t *
+camelsrt_razinfo(void)
+{
+ struct camelsrt_info_t *p_camelsrt_info ;
+
+ /* Global buffer for packet extraction */
+ camelsrt_global_current++;
+ if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
+ camelsrt_global_current=0;
+ }
+
+ p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
+ memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
+
+ p_camelsrt_info->opcode=255;
+
+ return p_camelsrt_info;
+}
static guint8 camel_pdu_type = 0;
/*--- End of included file: packet-camel-dis-tab.c ---*/
-#line 523 "../../asn1/camel/packet-camel-template.c"
+#line 1225 "../../asn1/camel/packet-camel-template.c"
} else {
range_foreach(ssn_range, range_delete_callback);
g_free(ssn_range);
"InvokeId_present", HFILL }},
/*--- End of included file: packet-camel-hfarr.c ---*/
-#line 696 "../../asn1/camel/packet-camel-template.c"
+#line 1398 "../../asn1/camel/packet-camel-template.c"
};
/* List of subtrees */
&ett_camel_InvokeId,
/*--- End of included file: packet-camel-ettarr.c ---*/
-#line 712 "../../asn1/camel/packet-camel-template.c"
+#line 1414 "../../asn1/camel/packet-camel-template.c"
};
static ei_register_info ei[] = {
WS_DLL_PUBLIC const value_string camel_opr_code_strings[];
/* #include "packet-camel-exp.h"*/
+/** @file
+*/
+#define NB_CAMELSRT_CATEGORY 9+1 /**< Number of type of message */
+/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
+ is a category, we want to measure the delay between the two messages */
+
+#define CAMELSRT_SESSION 1
+
+#define CAMELSRT_VOICE_INITIALDP 2
+#define CAMELSRT_VOICE_ACR1 3
+#define CAMELSRT_VOICE_ACR2 4
+#define CAMELSRT_VOICE_ACR3 5
+#define CAMELSRT_VOICE_DISC 6
+
+#define CAMELSRT_GPRS_INITIALDP 7
+#define CAMELSRT_GPRS_REPORT 8
+
+#define CAMELSRT_SMS_INITIALDP 9
+
+WS_DLL_PUBLIC const value_string camelSRTtype_naming[];
+
+/** If we have a request message and its response,
+ (eg: ApplyCharging, ApplyChargingReport)
+ the frames numbers are stored in this structure */
+
+struct camelsrt_category_t {
+ guint32 req_num; /**< frame number request seen */
+ guint32 rsp_num; /**< frame number response seen */
+ nstime_t req_time; /**< arrival time of request */
+ gboolean responded; /**< true, if request has been responded */
+};
+
+/** List of stored parameters for a Camel dialogue
+ All this parameters are linked to the hash table key below (use of Tid)
+ In case of same Tid reused, the Camel parameters are chained.
+ The right dialogue will be identified with the arrival time of the InitialDP */
+
+struct camelsrt_call_t {
+ guint32 session_id; /**< Identify the session, with an internal number */
+ struct tcaphash_context_t * tcap_context;
+ struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
+};
+
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct camelsrt_call_info_key_t {
+ guint32 SessionIdKey;
+};
+
+/** Info for a couple of messages (or category)
+ The request must be available, not duplicated,
+ and once the corresponding response received,
+ we can deduce the Delta Time between Request/response */
+
+struct camelsrt_msginfo_t {
+ gboolean request_available;
+ gboolean is_duplicate;
+ gboolean is_delta_time;
+ nstime_t req_time;
+ nstime_t delta_time;
+};
+
+/** List of infos to store for the analyse */
+
+struct camelsrt_info_t {
+ guint32 tcap_session_id;
+ void * tcap_context;
+ guint8 opcode; /**< operation code of message received */
+ guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /**< category for the received message */
+ struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+/**
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void camelsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camel_info);
+
+WS_DLL_PUBLIC gboolean gcamel_StatSRT;
+
#endif /* PACKET_camel_H */
#include <string.h>
#include "packet-ber.h"
#include "packet-tcap.h"
-#include <epan/tcap-persistentdata.h>
+#include "packet-mtp3.h"
+
#define PNAME "Transaction Capabilities Application Part"
#define PSNAME "TCAP"
static int hf_tcap_AARE_protocol_version_version1 = -1;
/*--- End of included file: packet-tcap-hf.c ---*/
-#line 62 "../../asn1/tcap/packet-tcap-template.c"
+#line 63 "../../asn1/tcap/packet-tcap-template.c"
/* Initialize the subtree pointers */
static gint ett_tcap = -1;
static gint ett_tcap_Associate_source_diagnostic = -1;
/*--- End of included file: packet-tcap-ett.c ---*/
-#line 78 "../../asn1/tcap/packet-tcap-template.c"
+#line 79 "../../asn1/tcap/packet-tcap-template.c"
+
+/* When several Tcap components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_TCAP_INSTANCE 10
+static int tcapsrt_global_current=0;
+static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
#define MAX_SSN 254
static range_t *global_ssn_range;
struct tcap_private_t tcap_private;
gboolean gtcap_HandleSRT=FALSE;
-extern gboolean gtcap_PersistentSRT;
-extern gboolean gtcap_DisplaySRT;
-extern guint gtcap_RepetitionTimeout;
-extern guint gtcap_LostTimeout;
+/* These two timeout (in second) are used when some message are lost,
+ or when the same TCAP transcation identifier is reused */
+guint gtcap_RepetitionTimeout = 10;
+guint gtcap_LostTimeout = 30;
+gboolean gtcap_PersistentSRT=FALSE;
+gboolean gtcap_DisplaySRT=FALSE;
+gboolean gtcap_StatSRT=FALSE;
+
+/* Global hash tables*/
+static GHashTable *tcaphash_context = NULL;
+static GHashTable *tcaphash_begin = NULL;
+static GHashTable *tcaphash_cont = NULL;
+static GHashTable *tcaphash_end = NULL;
+static GHashTable *tcaphash_ansi = NULL;
+
+static guint32 tcapsrt_global_SessionId=1;
static dissector_handle_t tcap_handle = NULL;
static dissector_table_t ber_oid_dissector_table;
}
-
-
/*--- Included file: packet-tcap-fn.c ---*/
#line 1 "../../asn1/tcap/packet-tcap-fn.c"
/*--- End of included file: packet-tcap-fn.c ---*/
-#line 141 "../../asn1/tcap/packet-tcap-template.c"
+#line 159 "../../asn1/tcap/packet-tcap-template.c"
+
+/*
+ * DEBUG functions
+ */
+#undef MEM_TCAPSRT
+/* #define MEM_TCAPSRT */
+
+#undef DEBUG_TCAPSRT
+/* #define DEBUG_TCAPSRT */
+
+#ifdef DEBUG_TCAPSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void
+dbg(guint level, char* fmt, ...)
+{
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
+static gint
+tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
+ const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
+
+ return (key1->session_id == key2->session_id);
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_context_calchash(gconstpointer k)
+{
+ const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
+ return key->session_id;
+}
+
+
+static gint
+tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
+ const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) )
+ )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_begin_calchash(gconstpointer k)
+{
+ const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
+ guint hashkey;
+ /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+ hashkey = key->tid;
+ return hashkey;
+}
+
+static gint
+tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
+ const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->src_tid == key2->src_tid) &&
+ (key1->dst_tid == key2->dst_tid) ) {
+ return TRUE;
+ }
+ else if ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->src_tid == key2->dst_tid) &&
+ (key1->dst_tid == key2->src_tid) ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_cont_calchash(gconstpointer k)
+{
+ const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->src_tid + key->dst_tid;
+ return hashkey;
+}
+
+
+static gint
+tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
+ const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_end_calchash(gconstpointer k)
+{
+ const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
+ guint hashkey;
+ hashkey = key->tid;
+ return hashkey;
+}
+
+static gint
+tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
+ const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
+
+ if (key1->hashKey == key2->hashKey) {
+
+ if ( ( (key1->opc_hash == key2->opc_hash) &&
+ (key1->dpc_hash == key2->dpc_hash) &&
+ (key1->tid == key2->tid) )
+ ||
+ ( (key1->opc_hash == key2->dpc_hash) &&
+ (key1->dpc_hash == key2->opc_hash) &&
+ (key1->tid == key2->tid) )
+ )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_ansi_calchash(gconstpointer k)
+{
+ const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
+ guint hashkey;
+ /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+ hashkey = key->tid;
+ return hashkey;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
+ packet_info *pinfo)
+{
+ p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_tcaphash_begincall->context->last_frame = 0;
+ p_tcaphash_begincall->context->responded = FALSE;
+ p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_begincall_t *
+append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
+ struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
+ p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=prev_begincall;
+ p_new_tcaphash_begincall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_begincall->next_begincall = p_new_tcaphash_begincall;
+ if (prev_begincall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"last ");
+#endif
+ prev_begincall->context->last_frame = pinfo->fd->num-1;
+ }
+ return p_new_tcaphash_begincall;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
+ packet_info *pinfo)
+{
+ p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+ p_tcaphash_ansicall->context->last_frame = 0;
+ p_tcaphash_ansicall->context->responded = FALSE;
+ p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_ansicall_t *
+append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
+ struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+ struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+ p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+ p_new_tcaphash_ansicall->context=p_tcaphash_context;
+ p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+ p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
+ p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+ p_new_tcaphash_ansicall->next_ansicall=NULL;
+ p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
+ p_new_tcaphash_ansicall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
+ if (prev_ansicall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"last ");
+#endif
+ prev_ansicall->context->last_frame = pinfo->fd->num-1;
+ }
+ return p_new_tcaphash_ansicall;
+}
+
+
+static struct tcaphash_contcall_t *
+append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+ p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=prev_contcall;
+ p_new_tcaphash_contcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_contcall->next_contcall = p_new_tcaphash_contcall;
+ return p_new_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+ /* Append the transaction to the list, when the same key is found
+ This should append when the tcap-transaction Id is reused */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+ p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=prev_endcall;
+ p_new_tcaphash_endcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* Insert in the chained list */
+ prev_endcall->next_endcall = p_new_tcaphash_endcall;
+ return p_new_tcaphash_endcall;
+}
+
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct tcaphash_begincall_t *
+find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+ packet_info *pinfo, gboolean isBegin)
+{
+ struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
+
+ if(p_tcaphash_begincall) {
+ do {
+ if ( p_tcaphash_begincall->context ) {
+ if ( ( isBegin &&
+ pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
+ ||
+ ( !isBegin &&
+ pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
+ ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
+#endif
+ return p_tcaphash_begincall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_begincall->next_begincall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Blist ");
+#endif
+ break;
+ }
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Bhash ");
+#endif
+ }
+ return NULL;
+}
+
+
+
+static struct tcaphash_contcall_t *
+find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+ p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if(p_tcaphash_contcall) {
+ do {
+ if ( p_tcaphash_contcall->context ) {
+ if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
+ (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
+#endif
+ return p_tcaphash_contcall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_contcall->next_contcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Clist ");
+#endif
+ break;
+ }
+ p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
+ } while (p_tcaphash_contcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Chash ");
+#endif
+ }
+ return NULL;
+}
+
+static struct tcaphash_endcall_t *
+find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ packet_info *pinfo, gboolean isEnd)
+{
+ struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+ p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if(p_tcaphash_endcall) {
+ do {
+ if ( p_tcaphash_endcall->context ) {
+ if ( ( isEnd &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
+ )
+ ||
+ ( !isEnd &&
+ pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
+ (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
+ )
+ ) {
+ /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
+#endif
+ return p_tcaphash_endcall;
+ }
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
+#endif
+ }
+ /* Break when list end is reached */
+ if(p_tcaphash_endcall->next_endcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"End of Elist ");
+#endif
+ break;
+ }
+ p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
+ } while (p_tcaphash_endcall != NULL) ;
+ } else {
+#ifdef DEBUG_TCAPSRT
+ dbg(23,"Not in Ehash ");
+#endif
+ }
+ return NULL;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_context_t *
+new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
+ packet_info *pinfo)
+{
+ struct tcaphash_context_key_t *p_new_tcaphash_context_key;
+ struct tcaphash_context_t *p_new_tcaphash_context = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
+#else
+ p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
+#endif
+ p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
+#else
+ p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
+#endif
+ p_new_tcaphash_context->key = p_new_tcaphash_context_key;
+ p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
+ p_new_tcaphash_context->first_frame = pinfo->fd->num;
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"S%d ", p_new_tcaphash_context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
+ return p_new_tcaphash_context;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_begincall_t *
+new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
+#else
+ p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
+#endif
+ p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
+ p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
+ p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
+ p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+ p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
+ p_new_tcaphash_begincall->context=p_tcaphash_context;
+ p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+ p_new_tcaphash_begincall->father=TRUE;
+ p_new_tcaphash_begincall->next_begincall=NULL;
+ p_new_tcaphash_begincall->previous_begincall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
+ return p_new_tcaphash_begincall;
+}
+
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_contcall_t *
+new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
+ struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
+#else
+ p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
+#endif
+ p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
+ p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
+ p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
+ p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
+ p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+ p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+ p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
+ p_new_tcaphash_contcall->context=p_tcaphash_context;
+ p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+ p_new_tcaphash_contcall->father=TRUE;
+ p_new_tcaphash_contcall->next_contcall=NULL;
+ p_new_tcaphash_contcall->previous_contcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
+ return p_new_tcaphash_contcall;
+}
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_endcall_t *
+new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
+ struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
+#else
+ p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
+#endif
+ p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
+ p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
+ p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
+ p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+ p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+ p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
+ p_new_tcaphash_endcall->context=p_tcaphash_context;
+ p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+ p_new_tcaphash_endcall->father=TRUE;
+ p_new_tcaphash_endcall->next_endcall=NULL;
+ p_new_tcaphash_endcall->previous_endcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
+ return p_new_tcaphash_endcall;
+}
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_ansicall_t *
+new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
+ struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as Main Key
+ Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
+#else
+ p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
+#endif
+ p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
+ p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
+ p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
+ p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+ p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+ p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+ p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
+ p_new_tcaphash_ansicall->context=p_tcaphash_context;
+ p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+ p_new_tcaphash_ansicall->father=TRUE;
+ p_new_tcaphash_ansicall->next_ansicall=NULL;
+ p_new_tcaphash_ansicall->previous_ansicall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
+ return p_new_tcaphash_ansicall;
+}
+
+static struct tcaphash_contcall_t *
+create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
+ struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+
+ p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
+ g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+ if (p_tcaphash_contcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_contcall1->next_contcall) {
+ p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
+ p_tcaphash_context);
+ break;
+ }
+ p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
+ } while (p_tcaphash_contcall1 != NULL );
+ } else {
+ p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
+ p_tcaphash_context);
+ }
+ return p_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+ struct tcaphash_context_t *p_tcaphash_context)
+{
+ struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
+ struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+
+ p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
+ g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+ if (p_tcaphash_endcall1) {
+ /* Walk through list of transaction with identical keys */
+ /* go the the end to insert new record */
+ do {
+ if (!p_tcaphash_endcall1->next_endcall) {
+ p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
+ p_tcaphash_context);
+ break;
+ }
+ p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
+ } while (p_tcaphash_endcall1 != NULL );
+ } else {
+ p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
+ p_tcaphash_context);
+ }
+ return p_tcaphash_endcall;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+tcapsrt_init_routine(void)
+{
+
+ /* free hash-table for SRT */
+ if (tcaphash_context != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_context \n");
+#endif
+ g_hash_table_destroy(tcaphash_context);
+ }
+
+ if (tcaphash_begin != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_begin \n");
+#endif
+ g_hash_table_destroy(tcaphash_begin);
+ }
+
+ if (tcaphash_cont != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_cont \n");
+#endif
+ g_hash_table_destroy(tcaphash_cont);
+ }
+
+ if (tcaphash_end != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_end \n");
+#endif
+ g_hash_table_destroy(tcaphash_end);
+ }
+
+ if (tcaphash_ansi != NULL) {
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Destroy hash_ansi \n");
+#endif
+ g_hash_table_destroy(tcaphash_ansi);
+ }
+
+#ifdef DEBUG_TCAPSRT
+ dbg(16,"Create hash \n");
+#endif
+ /* create new hash-tables for SRT */
+ tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
+ tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
+ tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
+ tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
+ tcaphash_ansi = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
+
+ /* Reset the session counter */
+ tcapsrt_global_SessionId=1;
+
+ /* Display of SRT only if Persistent Stat */
+ gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT>cap_StatSRT;
+}
+
+/*
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_context_key_t tcaphash_context_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ proto_item *pi;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+ /* prepare the key data */
+ tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+ /* look up the request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
+ dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+
+ p_tcaphash_begincall = (struct tcaphash_begincall_t *)
+ g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
+
+ if (p_tcaphash_begincall) {
+ /* Walk through list of transaction with identical keys */
+ do {
+ /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
+ if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Already seen ");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ break;
+ }
+ /* If the last record for Tcap transaction with identifier has not been reached */
+ if (!p_tcaphash_begincall->next_begincall) {
+ /* check if we have to create a new record or not */
+ /* if last request has been responded (response number is known)
+ and this request appears after last response (has bigger frame number)
+ and last request occurred after the timeout for repetition,
+ or
+ if last request hasn't been responded (so number unknown)
+ and this request appears after last request (has bigger frame number)
+ and this request occurred after the timeout for message lost */
+ if ( ( p_tcaphash_begincall->context->last_frame != 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
+ ) ||
+ ( p_tcaphash_begincall->context->last_frame == 0
+ && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+ && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
+ )
+ )
+ {
+ /* we decide that we have a new request */
+ /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+ } else { /* timeout or message lost */
+
+ /* If the Tid is reused for a closed Transaction */
+ /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
+ /* (this is the case, for pre-arranged END, the transaction is marked as closed */
+ /* by the upper layer, thank to a callback method close) */
+ if ( p_tcaphash_begincall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
+#endif
+ update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+
+ } else {
+ /* the TCAP session is not closed, so, either messages have been lost */
+ /* or it's a duplicate request. Mark it as such. */
+#ifdef DEBUG_TCAPSRT
+ dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Duplicate with session %u in frame %u",
+ p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ return p_tcaphash_context;
+ } /* Previous session closed */
+ } /* test with Timeout or message Lost */
+ break;
+ } /* Next call is NULL */
+ /* Repeat the tests for the next record with the same transaction identifier */
+ p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+ } while (p_tcaphash_begincall != NULL );
+ /*
+ * End of analyze for the list be TC_BEGIN with same transaction ID
+ */
+ } else { /* p_tcaphash_begincall has not been found */
+ /*
+ * Create a new TCAP context
+ */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
+#endif
+
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
+ }
+
+ /* display tcap session, if available */
+ if ( gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+ /* add link to response frame, if available */
+ /* p_tcaphash_begincall->context->last_frame) */
+ if( p_tcaphash_context->last_frame != 0 ){
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
+#endif
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+ p_tcaphash_context->last_frame,
+ "End of session in frame %u",
+ p_tcaphash_context->last_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ }
+ return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the source and destination
+* Identifier given in the TC_CONT
+* If nothing is found, it is probably a session in opening state, so try to find
+* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
+* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
+* and display the available info for the TCAP context
+*/
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_contcall_t *p_tcaphash_contcall;
+ struct tcaphash_cont_info_key_t tcaphash_cont_key;
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall;
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ proto_item *pi;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hcont #%u ", pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
+ tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
+#endif
+ p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
+ if(p_tcaphash_contcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CFound ");
+#endif
+ p_tcaphash_context=p_tcaphash_contcall->context;
+ } else { /* cont not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"CnotFound ");
+#endif
+ /* Find the TCAP transaction according to the TC_BEGIN */
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
+ if(!p_tcaphash_begincall){
+ /* Do we have a continue from the same source? */
+ tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ }
+ if(p_tcaphash_begincall &&
+ !p_tcaphash_begincall->context->contcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BFound \n");
+#endif
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ p_tcaphash_context->responded=TRUE;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
+ dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
+#endif
+ create_tcaphash_cont(&tcaphash_cont_key,
+ p_tcaphash_begincall->context);
+
+ tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ create_tcaphash_end(&tcaphash_end_key,
+ p_tcaphash_begincall->context);
+
+ } else { /* Begin not found */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BnotFound ");
+#endif
+ } /* begin found */
+ } /* cont found */
+ /* display tcap session, if available */
+ if (gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+ return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
+* If nothing is found,
+* - either it is a session in opening state,
+* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
+* so try to find a tcap session registered with a TC_BEGIN "key",
+* matching the destination Id of the TC_END
+* Then associate the TC_CONT "key" to the TCAP context
+* and display the available info for the TCAP context
+*/
+
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+
+ struct tcaphash_end_info_key_t tcaphash_end_key;
+ struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
+
+ struct tcaphash_begin_info_key_t tcaphash_begin_key;
+ struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
+ proto_item *pi;
+ nstime_t delta;
+ proto_item *stat_item=NULL;
+ proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hend #%u ", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
+ dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_end_key.tid);
+#endif
+ p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
+
+ if(!p_tcaphash_endcall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"EnotFound ");
+#endif
+ tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+ p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+ if(!p_tcaphash_begincall) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"BnotFound ");
+#endif
+ }
+ }
+ if (p_tcaphash_endcall) {
+ /* Use the TC_BEGIN Destination reference */
+ p_tcaphash_context=p_tcaphash_endcall->context;
+ } else if (p_tcaphash_begincall) {
+ /* Use the TC_BEGIN Source reference */
+ p_tcaphash_context=p_tcaphash_begincall->context;
+ }
+
+ if (p_tcaphash_context) {
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if (gtcap_DisplaySRT && stat_tree) {
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ /* Close the context and remove it (if needed) */
+ tcapsrt_close(p_tcaphash_context,pinfo);
+
+ } else {/* context present */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Context notFound ");
+#endif
+ }
+ return p_tcaphash_context;
+}
+
+/*
+ * ANSI PART
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *p_tcaphash_context=NULL;
+ struct tcaphash_context_key_t tcaphash_context_key;
+ struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
+ struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
+ proto_item *pi;
+ nstime_t delta;
+ gboolean isResponse=FALSE;
+ proto_tree * stat_tree=NULL;
+ proto_item * stat_item=NULL;
+
+ /* prepare the key data */
+ tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
+ if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+ {
+ /* We have MTP3 PCs (so we can safely do this cast) */
+ tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+ tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+ } else {
+ /* Don't have MTP3 PCs (maybe we're over SUA?) */
+ tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+ tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+ }
+ tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
+
+ /* look up the request */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"\n Hansi #%u ", pinfo->fd->num);
+ dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+ dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
+#endif
+ p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
+ g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
+
+ if (p_tcaphash_ansicall) {
+ /* Walk through list of transaction with identical keys */
+ do {
+ /* Check if the request with this reqSeqNum has been seen */
+ if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Request already seen ");
+#endif
+ isResponse=FALSE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ break;
+ }
+
+ /* Check if the reponse with this reqSeqNum has been seen */
+ if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
+ /* We have seen this response before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+ dbg(22,"Response already seen ");
+#endif
+ isResponse=TRUE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ break;
+ }
+
+ /* Check for the first Request without Response
+ received before this frame */
+ if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
+ p_tcaphash_ansicall->context->last_frame==0 ) {
+ /* Take it, and update the context */
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+ p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
+ p_tcaphash_ansicall->context->responded = TRUE;
+ p_tcaphash_ansicall->context->closed = TRUE;
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ isResponse=TRUE;
+
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ break;
+ } /* Lastframe=0, so take it */
+
+
+ /* If the last record for Tcap transaction with identifier has been reached */
+ if (!p_tcaphash_ansicall->next_ansicall) {
+ /* check if we have to create a new record or not */
+ /* if last request has been responded (response number in known)
+ and this request appears after last response (has bigger frame number)
+ and last request occurred after the timeout for repetition,
+ or
+ if last request hasn't been responded (so number unknown)
+ and this request appears after last request (has bigger frame number)
+ and this request occurred after the timeout for message lost */
+ if ( ( p_tcaphash_ansicall->context->last_frame != 0
+ && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+ && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
+ ) ||
+ ( p_tcaphash_ansicall->context->last_frame == 0
+ && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+ && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
+ )
+ )
+ {
+ /* we decide that we have a new request */
+ /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+ update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+ p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+ } else {
+
+ /* If the Tid is reused for a closed Transaction */
+ if ( p_tcaphash_ansicall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
+ dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+ p_tcaphash_context,
+ pinfo);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
+#endif
+ update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+ p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+
+ } else {
+ /* the Tid is reused for an opened Transaction */
+ /* so, this is the reply to the request of our context */
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+#ifdef DEBUG_TCAPSRT
+ dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+
+ if (gtcap_DisplaySRT && tree) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ p_tcaphash_context=p_tcaphash_ansicall->context;
+ } /* test with Timeout */
+ } /* closed */
+ break;
+ } /* Next call is NULL */
+ p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
+ } while (p_tcaphash_ansicall != NULL );
+ /*
+ * New TCAP context
+ */
+ } else { /* p_tcaphash_ansicall has not been found */
+#ifdef DEBUG_TCAPSRT
+ dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+
+ tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+ p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+ p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+ dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
+ dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+ update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
+ }
+
+ /* display tcap session, if available */
+ if ( gtcap_DisplaySRT && tree &&
+ p_tcaphash_context &&
+ p_tcaphash_context->session_id) {
+ stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+ PROTO_ITEM_SET_GENERATED(stat_item);
+ stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+ pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+
+ /* add link to response frame, if available */
+ if( gtcap_DisplaySRT && stat_tree &&
+ p_tcaphash_ansicall->context->last_frame != 0){
+ if (!isResponse) { /* Request */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
+#endif
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+ p_tcaphash_ansicall->context->last_frame,
+ "End of session in frame %u",
+ p_tcaphash_ansicall->context->last_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ } else { /* Response */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if (gtcap_DisplaySRT) {
+ pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+ p_tcaphash_context->first_frame,
+ "Begin of session in frame %u",
+ p_tcaphash_context->first_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+ /* display Service Response Time and make it filterable */
+ pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ } /* Request or Response */
+ }
+ return p_tcaphash_context;
+}
+
+/*
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t *
+tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ struct tcapsrt_info_t *p_tcapsrt_info)
+{
+ struct tcaphash_context_t *tcap_context=NULL;
+
+ /* if this packet isn't loaded because of a read filter, don't output anything */
+ if(pinfo == NULL || pinfo->fd->num == 0) {
+ return NULL;
+ }
+
+ switch (p_tcapsrt_info->ope) {
+
+ case TC_BEGIN:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_BEGIN ");
+#endif
+ tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_CONT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_CONT ");
+#endif
+ tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_ABORT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_ABORT ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_END:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_END ");
+#endif
+ tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ case TC_ANSI_ALL:
+ case TC_ANSI_ABORT:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nTC_ANSI ");
+#endif
+ tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
+ break;
+
+ default:
+#ifdef DEBUG_TCAPSRT
+ dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
+#endif
+ break;
+ } /* switch tcapop */
+#ifdef DEBUG_TCAPSRT
+ if (tcap_context)
+ dbg(1,"session %d ", tcap_context->session_id);
+#endif
+ return tcap_context;
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t *
+tcapsrt_razinfo(void)
+{
+ struct tcapsrt_info_t *p_tcapsrt_info ;
+
+ /* Global buffer for packet extraction */
+ tcapsrt_global_current++;
+ if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
+ tcapsrt_global_current=0;
+ }
+
+ p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
+ memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
+
+ return p_tcapsrt_info;
+}
+
+void
+tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
+ packet_info *pinfo)
+{
+#ifdef DEBUG_TCAPSRT
+ dbg(60,"Force close ");
+#endif
+ if (p_tcaphash_context) {
+ p_tcaphash_context->responded=TRUE;
+ p_tcaphash_context->last_frame = pinfo->fd->num;
+ p_tcaphash_context->end_time = pinfo->fd->abs_ts;
+ p_tcaphash_context->closed=TRUE;
+
+ /* If the endkey is present */
+ if (p_tcaphash_context->endcall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->endcall->next_endcall) {
+ if (p_tcaphash_context->endcall->previous_endcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Ehash ");
+#endif
+ p_tcaphash_context->endcall->previous_endcall->next_endcall
+ = p_tcaphash_context->endcall->next_endcall;
+ p_tcaphash_context->endcall->next_endcall->previous_endcall
+ = p_tcaphash_context->endcall->previous_endcall;
+ g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->endcall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Ehash ");
+#endif
+ } /* no previous link, so father */
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Ehash ");
+#endif
+ g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->endcall->endkey);
+ g_free(p_tcaphash_context->endcall);
+#endif
+
+ } /* endcall without chained string */
+ } /* no endcall */
+
+ /* If the contkey is present */
+ if (p_tcaphash_context->contcall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->contcall->next_contcall) {
+ if (p_tcaphash_context->contcall->previous_contcall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Chash ");
+#endif
+ p_tcaphash_context->contcall->previous_contcall->next_contcall
+ = p_tcaphash_context->contcall->next_contcall;
+ p_tcaphash_context->contcall->next_contcall->previous_contcall
+ = p_tcaphash_context->contcall->previous_contcall;
+ g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->contcall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Chash ");
+#endif
+ } /* no previous link, so father */
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Chash ");
+#endif
+ g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->contcall->contkey);
+ g_free(p_tcaphash_context->contcall);
+#endif
+ } /* contcall without chained string */
+ } /* no contcall */
+
+
+ /* If the beginkey is present */
+ if (p_tcaphash_context->begincall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->begincall->next_begincall) {
+ if (p_tcaphash_context->begincall->previous_begincall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Bhash ");
+#endif
+ p_tcaphash_context->begincall->previous_begincall->next_begincall
+ = p_tcaphash_context->begincall->next_begincall;
+ p_tcaphash_context->begincall->next_begincall->previous_begincall
+ = p_tcaphash_context->begincall->previous_begincall;
+ g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->begincall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Bhash ");
+#endif
+ }
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Bhash ");
+#endif
+ g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->begincall->beginkey);
+ g_free(p_tcaphash_context->begincall);
+#endif
+ } /* begincall without chained string */
+ } /* no begincall */
+
+ /* If the ansikey is present */
+ if (p_tcaphash_context->ansicall
+ && !gtcap_PersistentSRT) {
+ if (p_tcaphash_context->ansicall->next_ansicall) {
+ if (p_tcaphash_context->ansicall->previous_ansicall ) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"deplace Ahash ");
+#endif
+ p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
+ = p_tcaphash_context->ansicall->next_ansicall;
+ p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
+ = p_tcaphash_context->ansicall->previous_ansicall;
+ g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->ansicall);
+#endif
+ } else {
+ /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"father Ahash ");
+#endif
+ }
+ } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove Ahash ");
+#endif
+ g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->ansicall->ansikey);
+ g_free(p_tcaphash_context->ansicall);
+#endif
+ } /* ansicall without chained string */
+ } /* no ansicall */
+ if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"remove context ");
+#endif
+ g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
+#ifdef MEM_TCAPSRT
+ g_free(p_tcaphash_context->key);
+ g_free(p_tcaphash_context);
+#endif
+ }
+ } else { /* no context */
+#ifdef DEBUG_TCAPSRT
+ dbg(20,"No context to remove ");
+#endif
+ }
+}
const value_string tcap_component_type_str[] = {
{ TCAP_COMP_INVOKE, "Invoke" },
/*--- End of included file: packet-tcap-dis-tab.c ---*/
-#line 253 "../../asn1/tcap/packet-tcap-template.c"
+#line 2079 "../../asn1/tcap/packet-tcap-template.c"
}
static void init_tcap(void);
NULL, HFILL }},
/*--- End of included file: packet-tcap-hfarr.c ---*/
-#line 315 "../../asn1/tcap/packet-tcap-template.c"
+#line 2141 "../../asn1/tcap/packet-tcap-template.c"
};
/* Setup protocol subtree array */
&ett_tcap_Associate_source_diagnostic,
/*--- End of included file: packet-tcap-ettarr.c ---*/
-#line 325 "../../asn1/tcap/packet-tcap-template.c"
+#line 2151 "../../asn1/tcap/packet-tcap-template.c"
};
/*static enum_val_t tcap_options[] = {
gchar *TransactionID_str;
};
+/** @file
+ * lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-calls
+ */
+
+#define LENGTH_OID 23
+struct tcaphash_context_t {
+ struct tcaphash_context_key_t * key;
+ guint32 session_id;
+ guint32 first_frame;
+ guint32 last_frame;
+ nstime_t begin_time; /**< time of arrival of TC_BEGIN */
+ nstime_t end_time; /**< time of closing message */
+ gboolean responded; /**< true, if request has been responded */
+ gboolean closed;
+ gboolean upper_dissector;
+ gboolean oid_present;
+ gchar oid[LENGTH_OID+1];
+ gboolean subdissector_present;
+ dissector_handle_t subdissector_handle;
+ void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
+ struct tcaphash_begincall_t * begincall;
+ struct tcaphash_contcall_t * contcall;
+ struct tcaphash_endcall_t * endcall;
+ struct tcaphash_ansicall_t * ansicall;
+};
+
+struct tcaphash_begincall_t {
+ struct tcaphash_begin_info_key_t * beginkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_begincall_t * next_begincall;
+ struct tcaphash_begincall_t * previous_begincall;
+};
+
+struct tcaphash_contcall_t {
+ struct tcaphash_cont_info_key_t * contkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_contcall_t * next_contcall;
+ struct tcaphash_contcall_t * previous_contcall;
+};
+
+struct tcaphash_endcall_t {
+ struct tcaphash_end_info_key_t * endkey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_endcall_t * next_endcall;
+ struct tcaphash_endcall_t * previous_endcall;
+};
+
+struct tcaphash_ansicall_t {
+ struct tcaphash_ansi_info_key_t * ansikey;
+ struct tcaphash_context_t * context;
+ gboolean father;
+ struct tcaphash_ansicall_t * next_ansicall;
+ struct tcaphash_ansicall_t * previous_ansicall;
+};
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct tcaphash_context_key_t {
+ guint32 session_id;
+};
+
+struct tcaphash_begin_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_cont_info_key_t {
+ guint32 hashKey;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_end_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+struct tcaphash_ansi_info_key_t {
+ guint32 hashKey;
+ guint32 tid;
+ guint32 opc_hash;
+ guint32 dpc_hash;
+};
+
+
+/** List of infos to store for the analyse */
+struct tcapsrt_info_t {
+ guint32 tcap_session_id;
+ guint32 src_tid;
+ guint32 dst_tid;
+ guint8 ope;
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void tcapsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+ packet_info * pinfo _U_);
+
+/**
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcapsrt_info_t * p_tcap_info);
+
+WS_DLL_PUBLIC gboolean gtcap_StatSRT;
+
extern gint tcap_standard;
extern const value_string tcap_component_type_str[];
int dissect_tcap_DialoguePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
/*--- End of included file: packet-tcap-exp.h ---*/
-#line 91 "../../asn1/tcap/packet-tcap-template.h"
+#line 232 "../../asn1/tcap/packet-tcap-template.h"
#endif /* PACKET_tcap_H */
+++ /dev/null
-/*
- * tcap-persistentdata.c
- * Source for lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-calls
- * Copyright 2006 Florent Drouin (based on h225-persistentdata.c from Lars Roland)
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * $Id$
- *
- * 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 <glib.h>
-#include <string.h>
-
-#include <epan/emem.h>
-#include <epan/packet.h>
-#include <epan/to_str.h>
-#include <epan/asn1.h>
-#include <epan/tcap-persistentdata.h>
-#include <epan/dissectors/packet-tcap.h>
-#include <epan/dissectors/packet-mtp3.h>
-
-static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_context_calchash(gconstpointer k);
-static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_begin_calchash(gconstpointer k);
-static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_cont_calchash(gconstpointer k);
-static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_end_calchash(gconstpointer k);
-static gint tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_ansi_calchash(gconstpointer k);
-
-static void update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
- packet_info *pinfo );
-
-static struct tcaphash_begincall_t *append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
- struct tcaphash_context_t *p_tcaphash_context,
- packet_info *pinfo);
-
-
-static struct tcaphash_begincall_t *find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
- packet_info *pinfo,
- gboolean isBegin);
-
-
-static struct tcaphash_contcall_t *find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
- packet_info *pinfo);
-
-static struct tcaphash_endcall_t *find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
- packet_info *pinfo,
- gboolean isEnd);
-/* new key */
-static struct tcaphash_context_t *new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
- packet_info *pinfo);
-
-static struct tcaphash_begincall_t *new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
- struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_contcall_t *new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
- struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_endcall_t *new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
- struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_context_t *tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info);
-
-/* When several Tcap components are received in a single TCAP message,
- we have to use several buffers for the stored parameters
- because else this data are erased during TAP dissector call */
-#define MAX_TCAP_INSTANCE 10
-int tcapsrt_global_current=0;
-struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
-
-/* These two timeout (in second) are used when some message are lost,
- or when the same TCAP transcation identifier is reused */
-guint gtcap_RepetitionTimeout = 10;
-guint gtcap_LostTimeout = 30;
-extern gboolean gtcap_HandleSRT;
-gboolean gtcap_PersistentSRT=FALSE;
-gboolean gtcap_DisplaySRT=FALSE;
-gboolean gtcap_StatSRT=FALSE;
-
-extern gint ett_tcap_stat;
-
-extern int hf_tcapsrt_SessionId;
-extern int hf_tcapsrt_Duplicate;
-extern int hf_tcapsrt_BeginSession;
-extern int hf_tcapsrt_EndSession;
-extern int hf_tcapsrt_SessionTime;
-
-/* Global hash tables*/
-static GHashTable *tcaphash_context = NULL;
-static GHashTable *tcaphash_begin = NULL;
-static GHashTable *tcaphash_cont = NULL;
-static GHashTable *tcaphash_end = NULL;
-static GHashTable *tcaphash_ansi = NULL;
-
-guint32 tcapsrt_global_SessionId=1;
-
-/*
- * DEBUG functions
- */
-#undef MEM_TCAPSRT
-/* #define MEM_TCAPSRT */
-
-#undef DEBUG_TCAPSRT
-/* #define DEBUG_TCAPSRT */
-
-#ifdef DEBUG_TCAPSRT
-#include <stdio.h>
-#include <stdarg.h>
-static guint debug_level = 99;
-
-static void
-dbg(guint level, char* fmt, ...)
-{
- va_list ap;
-
- if (level > debug_level) return;
- va_start(ap,fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-#endif
-
-static gint
-tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
- const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
-
- return (key1->session_id == key2->session_id);
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_context_calchash(gconstpointer k)
-{
- const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
- return key->session_id;
-}
-
-
-static gint
-tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
- const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
-
- if (key1->hashKey == key2->hashKey) {
-
- if ( ( (key1->opc_hash == key2->opc_hash) &&
- (key1->dpc_hash == key2->dpc_hash) &&
- (key1->tid == key2->tid) )
- ||
- ( (key1->opc_hash == key2->dpc_hash) &&
- (key1->dpc_hash == key2->opc_hash) &&
- (key1->tid == key2->tid) )
- )
- return TRUE;
- }
- return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_begin_calchash(gconstpointer k)
-{
- const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
- guint hashkey;
- /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
- hashkey = key->tid;
- return hashkey;
-}
-
-static gint
-tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
- const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
-
- if (key1->hashKey == key2->hashKey) {
-
- if ( (key1->opc_hash == key2->opc_hash) &&
- (key1->dpc_hash == key2->dpc_hash) &&
- (key1->src_tid == key2->src_tid) &&
- (key1->dst_tid == key2->dst_tid) ) {
- return TRUE;
- }
- else if ( (key1->opc_hash == key2->dpc_hash) &&
- (key1->dpc_hash == key2->opc_hash) &&
- (key1->src_tid == key2->dst_tid) &&
- (key1->dst_tid == key2->src_tid) ) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_cont_calchash(gconstpointer k)
-{
- const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
- guint hashkey;
- hashkey = key->src_tid + key->dst_tid;
- return hashkey;
-}
-
-
-static gint
-tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
- const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
-
- if (key1->hashKey == key2->hashKey) {
- if ( ( (key1->opc_hash == key2->opc_hash) &&
- (key1->dpc_hash == key2->dpc_hash) &&
- (key1->tid == key2->tid) )
- ||
- ( (key1->opc_hash == key2->dpc_hash) &&
- (key1->dpc_hash == key2->opc_hash) &&
- (key1->tid == key2->tid) ) )
- return TRUE;
- }
- return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_end_calchash(gconstpointer k)
-{
- const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
- guint hashkey;
- hashkey = key->tid;
- return hashkey;
-}
-
-static gint
-tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
-{
- const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
- const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
-
- if (key1->hashKey == key2->hashKey) {
-
- if ( ( (key1->opc_hash == key2->opc_hash) &&
- (key1->dpc_hash == key2->dpc_hash) &&
- (key1->tid == key2->tid) )
- ||
- ( (key1->opc_hash == key2->dpc_hash) &&
- (key1->dpc_hash == key2->opc_hash) &&
- (key1->tid == key2->tid) )
- )
- return TRUE;
- }
- return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_ansi_calchash(gconstpointer k)
-{
- const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
- guint hashkey;
- /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
- hashkey = key->tid;
- return hashkey;
-}
-
-/*
- * Update a record with the data of the Request
- */
-static void
-update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
- packet_info *pinfo)
-{
- p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
- p_tcaphash_begincall->context->last_frame = 0;
- p_tcaphash_begincall->context->responded = FALSE;
- p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
-}
-
-/*
- * Append a new dialogue, using the same Key, to the chained list
- * The time is stored too
- */
-static struct tcaphash_begincall_t *
-append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
- struct tcaphash_context_t *p_tcaphash_context,
- packet_info *pinfo)
-{
- struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
-
- /* Append the transaction to the list, when the same key is found
- This should append when the tcap-transaction Id is reused */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
-#else
- p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
-#endif
- p_new_tcaphash_begincall->context=p_tcaphash_context;
- p_tcaphash_context->begincall=p_new_tcaphash_begincall;
- p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
- p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
- p_new_tcaphash_begincall->next_begincall=NULL;
- p_new_tcaphash_begincall->previous_begincall=prev_begincall;
- p_new_tcaphash_begincall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
-#endif
- /* Insert in the chained list */
- prev_begincall->next_begincall = p_new_tcaphash_begincall;
- if (prev_begincall->context->last_frame == 0) {
-#ifdef DEBUG_TCAPSRT
- dbg(10,"last ");
-#endif
- prev_begincall->context->last_frame = pinfo->fd->num-1;
- }
- return p_new_tcaphash_begincall;
-}
-
-/*
- * Update a record with the data of the Request
- */
-static void
-update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
- packet_info *pinfo)
-{
- p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
- p_tcaphash_ansicall->context->last_frame = 0;
- p_tcaphash_ansicall->context->responded = FALSE;
- p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
-}
-
-/*
- * Append a new dialogue, using the same Key, to the chained list
- * The time is stored too
- */
-static struct tcaphash_ansicall_t *
-append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
- struct tcaphash_context_t *p_tcaphash_context,
- packet_info *pinfo)
-{
- struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
-
- /* Append the transaction to the list, when the same key is found
- This should append when the tcap-transaction Id is reused */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
-#else
- p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
-#endif
- p_new_tcaphash_ansicall->context=p_tcaphash_context;
- p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
- p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
- p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
- p_new_tcaphash_ansicall->next_ansicall=NULL;
- p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
- p_new_tcaphash_ansicall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
-#endif
- /* Insert in the chained list */
- prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
- if (prev_ansicall->context->last_frame == 0) {
-#ifdef DEBUG_TCAPSRT
- dbg(10,"last ");
-#endif
- prev_ansicall->context->last_frame = pinfo->fd->num-1;
- }
- return p_new_tcaphash_ansicall;
-}
-
-
-static struct tcaphash_contcall_t *
-append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
-
- /* Append the transaction to the list, when the same key is found
- This should append when the tcap-transaction Id is reused */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
-#else
- p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
-#endif
- p_new_tcaphash_contcall->context=p_tcaphash_context;
- p_tcaphash_context->contcall=p_new_tcaphash_contcall;
- p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
- p_new_tcaphash_contcall->next_contcall=NULL;
- p_new_tcaphash_contcall->previous_contcall=prev_contcall;
- p_new_tcaphash_contcall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
-#endif
- /* Insert in the chained list */
- prev_contcall->next_contcall = p_new_tcaphash_contcall;
- return p_new_tcaphash_contcall;
-}
-
-
-static struct tcaphash_endcall_t *
-append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
-
- /* Append the transaction to the list, when the same key is found
- This should append when the tcap-transaction Id is reused */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
-#else
- p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
-#endif
- p_new_tcaphash_endcall->context=p_tcaphash_context;
- p_tcaphash_context->endcall=p_new_tcaphash_endcall;
- p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
- p_new_tcaphash_endcall->next_endcall=NULL;
- p_new_tcaphash_endcall->previous_endcall=prev_endcall;
- p_new_tcaphash_endcall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
-#endif
- /* Insert in the chained list */
- prev_endcall->next_endcall = p_new_tcaphash_endcall;
- return p_new_tcaphash_endcall;
-}
-
-
-/*
- * Find the dialog by Key and Time
- */
-static struct tcaphash_begincall_t *
-find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
- packet_info *pinfo, gboolean isBegin)
-{
- struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
- p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
-
- if(p_tcaphash_begincall) {
- do {
- if ( p_tcaphash_begincall->context ) {
- if ( ( isBegin &&
- pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
- ||
- ( !isBegin &&
- pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
- ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
- )
- ) {
- /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
-#endif
- return p_tcaphash_begincall;
- }
-#ifdef DEBUG_TCAPSRT
- dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
-#endif
- }
- /* Break when list end is reached */
- if(p_tcaphash_begincall->next_begincall == NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"End of Blist ");
-#endif
- break;
- }
- p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
- } while (p_tcaphash_begincall != NULL) ;
- } else {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"Not in Bhash ");
-#endif
- }
- return NULL;
-}
-
-
-
-static struct tcaphash_contcall_t *
-find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
- packet_info *pinfo)
-{
- struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
- p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
-
- if(p_tcaphash_contcall) {
- do {
- if ( p_tcaphash_contcall->context ) {
- if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
- (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
- /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
-#endif
- return p_tcaphash_contcall;
- }
-#ifdef DEBUG_TCAPSRT
- dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
-#endif
- }
- /* Break when list end is reached */
- if(p_tcaphash_contcall->next_contcall == NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"End of Clist ");
-#endif
- break;
- }
- p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
- } while (p_tcaphash_contcall != NULL) ;
- } else {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"Not in Chash ");
-#endif
- }
- return NULL;
-}
-
-static struct tcaphash_endcall_t *
-find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
- packet_info *pinfo, gboolean isEnd)
-{
- struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
- p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
-
- if(p_tcaphash_endcall) {
- do {
- if ( p_tcaphash_endcall->context ) {
- if ( ( isEnd &&
- (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
- )
- ||
- ( !isEnd &&
- pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
- (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
- )
- ) {
- /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
-#endif
- return p_tcaphash_endcall;
- }
-#ifdef DEBUG_TCAPSRT
- dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
-#endif
- }
- /* Break when list end is reached */
- if(p_tcaphash_endcall->next_endcall == NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"End of Elist ");
-#endif
- break;
- }
- p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
- } while (p_tcaphash_endcall != NULL) ;
- } else {
-#ifdef DEBUG_TCAPSRT
- dbg(23,"Not in Ehash ");
-#endif
- }
- return NULL;
-}
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_context_t *
-new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
- packet_info *pinfo)
-{
- struct tcaphash_context_key_t *p_new_tcaphash_context_key;
- struct tcaphash_context_t *p_new_tcaphash_context = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as Main Key
- Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
-#else
- p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
-#endif
- p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
-#else
- p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
-#endif
- p_new_tcaphash_context->key = p_new_tcaphash_context_key;
- p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
- p_new_tcaphash_context->first_frame = pinfo->fd->num;
-#ifdef DEBUG_TCAPSRT
- dbg(10,"S%d ", p_new_tcaphash_context->session_id);
-#endif
- /* store it */
- g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
- return p_new_tcaphash_context;
-}
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_begincall_t *
-new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
- struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as Main Key
- Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
-#else
- p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
-#endif
- p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
- p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
- p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
- p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
-#else
- p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
-#endif
- p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
- p_new_tcaphash_begincall->context=p_tcaphash_context;
- p_tcaphash_context->begincall=p_new_tcaphash_begincall;
- p_new_tcaphash_begincall->father=TRUE;
- p_new_tcaphash_begincall->next_begincall=NULL;
- p_new_tcaphash_begincall->previous_begincall=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
-#endif
- /* store it */
- g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
- return p_new_tcaphash_begincall;
-}
-
-
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_contcall_t *
-new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
- struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as Main Key
- Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
-#else
- p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
-#endif
- p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
- p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
- p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
- p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
- p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
-#else
- p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
-#endif
- p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
- p_new_tcaphash_contcall->context=p_tcaphash_context;
- p_tcaphash_context->contcall=p_new_tcaphash_contcall;
- p_new_tcaphash_contcall->father=TRUE;
- p_new_tcaphash_contcall->next_contcall=NULL;
- p_new_tcaphash_contcall->previous_contcall=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
-#endif
- /* store it */
- g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
- return p_new_tcaphash_contcall;
-}
-
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_endcall_t *
-new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
- struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as Main Key
- Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
-#else
- p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
-#endif
- p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
- p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
- p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
- p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
-#else
- p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
-#endif
- p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
- p_new_tcaphash_endcall->context=p_tcaphash_context;
- p_tcaphash_context->endcall=p_new_tcaphash_endcall;
- p_new_tcaphash_endcall->father=TRUE;
- p_new_tcaphash_endcall->next_endcall=NULL;
- p_new_tcaphash_endcall->previous_endcall=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
-#endif
- /* store it */
- g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
- return p_new_tcaphash_endcall;
-}
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_ansicall_t *
-new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
- struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
-
- /* Register the transaction in the hash table
- with the tcap transaction Id as Main Key
- Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
-#else
- p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
-#endif
- p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
- p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
- p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
- p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
- p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
-#else
- p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
-#endif
- p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
- p_new_tcaphash_ansicall->context=p_tcaphash_context;
- p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
- p_new_tcaphash_ansicall->father=TRUE;
- p_new_tcaphash_ansicall->next_ansicall=NULL;
- p_new_tcaphash_ansicall->previous_ansicall=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
-#endif
- /* store it */
- g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
- return p_new_tcaphash_ansicall;
-}
-
-static struct tcaphash_contcall_t *
-create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
- struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
-
- p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
- g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
-
- if (p_tcaphash_contcall1) {
- /* Walk through list of transaction with identical keys */
- /* go the the end to insert new record */
- do {
- if (!p_tcaphash_contcall1->next_contcall) {
- p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
- p_tcaphash_context);
- break;
- }
- p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
- } while (p_tcaphash_contcall1 != NULL );
- } else {
- p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
- p_tcaphash_context);
- }
- return p_tcaphash_contcall;
-}
-
-
-static struct tcaphash_endcall_t *
-create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
- struct tcaphash_context_t *p_tcaphash_context)
-{
- struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
- struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
-
- p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
- g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
-
- if (p_tcaphash_endcall1) {
- /* Walk through list of transaction with identical keys */
- /* go the the end to insert new record */
- do {
- if (!p_tcaphash_endcall1->next_endcall) {
- p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
- p_tcaphash_context);
- break;
- }
- p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
- } while (p_tcaphash_endcall1 != NULL );
- } else {
- p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
- p_tcaphash_context);
- }
- return p_tcaphash_endcall;
-}
-
-
-/*
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void
-tcapsrt_init_routine(void)
-{
-
- /* free hash-table for SRT */
- if (tcaphash_context != NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Destroy hash_context \n");
-#endif
- g_hash_table_destroy(tcaphash_context);
- }
-
- if (tcaphash_begin != NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Destroy hash_begin \n");
-#endif
- g_hash_table_destroy(tcaphash_begin);
- }
-
- if (tcaphash_cont != NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Destroy hash_cont \n");
-#endif
- g_hash_table_destroy(tcaphash_cont);
- }
-
- if (tcaphash_end != NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Destroy hash_end \n");
-#endif
- g_hash_table_destroy(tcaphash_end);
- }
-
- if (tcaphash_ansi != NULL) {
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Destroy hash_ansi \n");
-#endif
- g_hash_table_destroy(tcaphash_ansi);
- }
-
-#ifdef DEBUG_TCAPSRT
- dbg(16,"Create hash \n");
-#endif
- /* create new hash-tables for SRT */
- tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
- tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
- tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
- tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
- tcaphash_ansi = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
-
- /* Reset the session counter */
- tcapsrt_global_SessionId=1;
-
- /* Display of SRT only if Persistent Stat */
- gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT>cap_StatSRT;
-}
-
-/*
- * Service Response Time analyze
- * Called just after dissector call
- * Associate a TCAP context to a tcap session and display session related infomations
- * like the first frame, the last, the session duration,
- * and a uniq session identifier for the filtering
- *
- * For ETSI tcap, the TCAP context can be reached through three keys
- * - a key (BEGIN) identifying the session according to the tcap source identifier
- * - a key (CONT) identifying the established session (src_id and dst_id)
- * - a key (END) identifying the session according to the tcap destination identifier
- *
- * For ANSI tcap, the TCAP context is reached through a uniq key
- * - a key (ANSI) identifying the session according to the tcap identifier
-*/
-struct tcaphash_context_t *
-tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info)
-{
- struct tcaphash_context_t *tcap_context=NULL;
-
- /* if this packet isn't loaded because of a read filter, don't output anything */
- if(pinfo == NULL || pinfo->fd->num == 0) {
- return NULL;
- }
-
- switch (p_tcapsrt_info->ope) {
-
- case TC_BEGIN:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nTC_BEGIN ");
-#endif
- tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
- break;
-
- case TC_CONT:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nTC_CONT ");
-#endif
- tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
- break;
-
- case TC_ABORT:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nTC_ABORT ");
-#endif
- tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
- break;
-
- case TC_END:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nTC_END ");
-#endif
- tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
- break;
-
- case TC_ANSI_ALL:
- case TC_ANSI_ABORT:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nTC_ANSI ");
-#endif
- tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
- break;
-
- default:
-#ifdef DEBUG_TCAPSRT
- dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
-#endif
- break;
- } /* switch tcapop */
-#ifdef DEBUG_TCAPSRT
- if (tcap_context)
- dbg(1,"session %d ", tcap_context->session_id);
-#endif
- return tcap_context;
-}
-
-
-/*
- * Create the record identifiying the TCAP transaction
- * When the identifier for the transaction is reused, check
- * the following criteria before to append a new record:
- * - a timeout corresponding to a message retransmission is detected,
- * - a message hast been lost
- * - or the previous transaction has been be closed
- */
-static struct tcaphash_context_t *
-tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info)
-{
- struct tcaphash_context_t *p_tcaphash_context=NULL;
- struct tcaphash_context_key_t tcaphash_context_key;
- struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
- struct tcaphash_begin_info_key_t tcaphash_begin_key;
- proto_item *pi;
- proto_item *stat_item=NULL;
- proto_tree *stat_tree=NULL;
-
- /* prepare the key data */
- tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
- /* look up the request */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
- dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
- dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
-#endif
-
- p_tcaphash_begincall = (struct tcaphash_begincall_t *)
- g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
-
- if (p_tcaphash_begincall) {
- /* Walk through list of transaction with identical keys */
- do {
- /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
- if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
- /* We have seen this request before -> do nothing */
-#ifdef DEBUG_TCAPSRT
- dbg(22,"Already seen ");
-#endif
- p_tcaphash_context=p_tcaphash_begincall->context;
- break;
- }
- /* If the last record for Tcap transaction with identifier has not been reached */
- if (!p_tcaphash_begincall->next_begincall) {
- /* check if we have to create a new record or not */
- /* if last request has been responded (response number is known)
- and this request appears after last response (has bigger frame number)
- and last request occurred after the timeout for repetition,
- or
- if last request hasn't been responded (so number unknown)
- and this request appears after last request (has bigger frame number)
- and this request occurred after the timeout for message lost */
- if ( ( p_tcaphash_begincall->context->last_frame != 0
- && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
- && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
- ) ||
- ( p_tcaphash_begincall->context->last_frame == 0
- && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
- && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
- )
- )
- {
- /* we decide that we have a new request */
- /* Append new record to the list */
-#ifdef DEBUG_TCAPSRT
- dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
- dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
-#endif
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-
- p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
- p_tcaphash_context,
- pinfo);
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
-#endif
- update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
- } else { /* timeout or message lost */
-
- /* If the Tid is reused for a closed Transaction */
- /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
- /* (this is the case, for pre-arranged END, the transaction is marked as closed */
- /* by the upper layer, thank to a callback method close) */
- if ( p_tcaphash_begincall->context->closed) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
- dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
-#endif
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
- p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
- p_tcaphash_context,
- pinfo);
-
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
-#endif
- update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
-
- } else {
- /* the TCAP session is not closed, so, either messages have been lost */
- /* or it's a duplicate request. Mark it as such. */
-#ifdef DEBUG_TCAPSRT
- dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
-#endif
- p_tcaphash_context=p_tcaphash_begincall->context;
- if (gtcap_DisplaySRT && tree) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
- p_tcaphash_context->first_frame,
- "Duplicate with session %u in frame %u",
- p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- return p_tcaphash_context;
- } /* Previous session closed */
- } /* test with Timeout or message Lost */
- break;
- } /* Next call is NULL */
- /* Repeat the tests for the next record with the same transaction identifier */
- p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
- } while (p_tcaphash_begincall != NULL );
- /*
- * End of analyze for the list be TC_BEGIN with same transaction ID
- */
- } else { /* p_tcaphash_begincall has not been found */
- /*
- * Create a new TCAP context
- */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
-#endif
-
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
- p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
- dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
- update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
- }
-
- /* display tcap session, if available */
- if ( gtcap_DisplaySRT && tree &&
- p_tcaphash_context &&
- p_tcaphash_context->session_id) {
- stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
-
- /* add link to response frame, if available */
- /* p_tcaphash_begincall->context->last_frame) */
- if( p_tcaphash_context->last_frame != 0 ){
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
-#endif
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
- p_tcaphash_context->last_frame,
- "End of session in frame %u",
- p_tcaphash_context->last_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- }
- return p_tcaphash_context;
-}
-
-
-/*
-* Try to find a TCAP session according to the source and destination
-* Identifier given in the TC_CONT
-* If nothing is found, it is probably a session in opening state, so try to find
-* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
-* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
-* and display the available info for the TCAP context
-*/
-static struct tcaphash_context_t *
-tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info)
-{
- struct tcaphash_context_t *p_tcaphash_context=NULL;
- struct tcaphash_contcall_t *p_tcaphash_contcall;
- struct tcaphash_cont_info_key_t tcaphash_cont_key;
- struct tcaphash_begin_info_key_t tcaphash_begin_key;
- struct tcaphash_begincall_t *p_tcaphash_begincall;
- struct tcaphash_end_info_key_t tcaphash_end_key;
- proto_item *pi;
- proto_item *stat_item=NULL;
- proto_tree *stat_tree=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"\n Hcont #%u ", pinfo->fd->num);
-#endif
-
- /* look only for matching request, if matching conversation is available. */
- tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
- tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
- dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
-#endif
- p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
- if(p_tcaphash_contcall) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"CFound ");
-#endif
- p_tcaphash_context=p_tcaphash_contcall->context;
- } else { /* cont not found */
-#ifdef DEBUG_TCAPSRT
- dbg(12,"CnotFound ");
-#endif
- /* Find the TCAP transaction according to the TC_BEGIN */
- tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
- dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
-#endif
- p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
- if(!p_tcaphash_begincall){
- /* Do we have a continue from the same source? */
- tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
- tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
- p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
- }
- if(p_tcaphash_begincall &&
- !p_tcaphash_begincall->context->contcall ) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"BFound \n");
-#endif
- p_tcaphash_context=p_tcaphash_begincall->context;
- p_tcaphash_context->responded=TRUE;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
- dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
-#endif
- create_tcaphash_cont(&tcaphash_cont_key,
- p_tcaphash_begincall->context);
-
- tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
- dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
- create_tcaphash_end(&tcaphash_end_key,
- p_tcaphash_begincall->context);
-
- } else { /* Begin not found */
-#ifdef DEBUG_TCAPSRT
- dbg(12,"BnotFound ");
-#endif
- } /* begin found */
- } /* cont found */
- /* display tcap session, if available */
- if (gtcap_DisplaySRT && tree &&
- p_tcaphash_context &&
- p_tcaphash_context->session_id) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
- }
-
- return p_tcaphash_context;
-}
-
-/*
-* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
-* If nothing is found,
-* - either it is a session in opening state,
-* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
-* so try to find a tcap session registered with a TC_BEGIN "key",
-* matching the destination Id of the TC_END
-* Then associate the TC_CONT "key" to the TCAP context
-* and display the available info for the TCAP context
-*/
-
-static struct tcaphash_context_t *
-tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info)
-{
- struct tcaphash_context_t *p_tcaphash_context=NULL;
-
- struct tcaphash_end_info_key_t tcaphash_end_key;
- struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
-
- struct tcaphash_begin_info_key_t tcaphash_begin_key;
- struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
- proto_item *pi;
- nstime_t delta;
- proto_item *stat_item=NULL;
- proto_tree *stat_tree=NULL;
-
-#ifdef DEBUG_TCAPSRT
- dbg(10,"\n Hend #%u ", pinfo->fd->num);
-#endif
- /* look only for matching request, if matching conversation is available. */
- tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
- dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx ",tcaphash_end_key.tid);
-#endif
- p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
-
- if(!p_tcaphash_endcall) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"EnotFound ");
-#endif
- tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
- dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
-#endif
- p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
- if(!p_tcaphash_begincall) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"BnotFound ");
-#endif
- }
- }
- if (p_tcaphash_endcall) {
- /* Use the TC_BEGIN Destination reference */
- p_tcaphash_context=p_tcaphash_endcall->context;
- } else if (p_tcaphash_begincall) {
- /* Use the TC_BEGIN Source reference */
- p_tcaphash_context=p_tcaphash_begincall->context;
- }
-
- if (p_tcaphash_context) {
-
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
-#endif
- if (gtcap_DisplaySRT && tree) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
- }
-
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
- /* Indicate the frame to which this is a reply. */
- if (gtcap_DisplaySRT && stat_tree) {
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
- p_tcaphash_context->first_frame,
- "Begin of session in frame %u",
- p_tcaphash_context->first_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
- /* display Service Response Time and make it filterable */
- pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- /* Close the context and remove it (if needed) */
- tcapsrt_close(p_tcaphash_context,pinfo);
-
- } else {/* context present */
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Context notFound ");
-#endif
- }
- return p_tcaphash_context;
-}
-
-/*
- * ANSI PART
- * Create the record identifiying the TCAP transaction
- * When the identifier for the transaction is reused, check
- * the following criteria before to append a new record:
- * - a timeout corresponding to a message retransmission is detected,
- * - a message hast been lost
- * - or the previous transaction has been be closed
- */
-static struct tcaphash_context_t *
-tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- struct tcapsrt_info_t *p_tcapsrt_info)
-{
- struct tcaphash_context_t *p_tcaphash_context=NULL;
- struct tcaphash_context_key_t tcaphash_context_key;
- struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
- struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
- proto_item *pi;
- nstime_t delta;
- gboolean isResponse=FALSE;
- proto_tree * stat_tree=NULL;
- proto_item * stat_item=NULL;
-
- /* prepare the key data */
- tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
- if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
- {
- /* We have MTP3 PCs (so we can safely do this cast) */
- tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
- tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
- } else {
- /* Don't have MTP3 PCs (maybe we're over SUA?) */
- tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
- tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
- }
- tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
-
- /* look up the request */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"\n Hansi #%u ", pinfo->fd->num);
- dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
- dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
- dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
-#endif
- p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
- g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
-
- if (p_tcaphash_ansicall) {
- /* Walk through list of transaction with identical keys */
- do {
- /* Check if the request with this reqSeqNum has been seen */
- if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
- /* We have seen this request before -> do nothing */
-#ifdef DEBUG_TCAPSRT
- dbg(22,"Request already seen ");
-#endif
- isResponse=FALSE;
- p_tcaphash_context=p_tcaphash_ansicall->context;
- break;
- }
-
- /* Check if the reponse with this reqSeqNum has been seen */
- if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
- /* We have seen this response before -> do nothing */
-#ifdef DEBUG_TCAPSRT
- dbg(22,"Response already seen ");
-#endif
- isResponse=TRUE;
- p_tcaphash_context=p_tcaphash_ansicall->context;
- break;
- }
-
- /* Check for the first Request without Response
- received before this frame */
- if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
- p_tcaphash_ansicall->context->last_frame==0 ) {
- /* Take it, and update the context */
-
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
-#endif
- p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
- p_tcaphash_ansicall->context->responded = TRUE;
- p_tcaphash_ansicall->context->closed = TRUE;
- p_tcaphash_context=p_tcaphash_ansicall->context;
- isResponse=TRUE;
-
- if (gtcap_DisplaySRT && tree) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
-
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
- /* Indicate the frame to which this is a reply. */
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
- p_tcaphash_context->first_frame,
- "Begin of session in frame %u",
- p_tcaphash_context->first_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
- /* display Service Response Time and make it filterable */
- pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- break;
- } /* Lastframe=0, so take it */
-
-
- /* If the last record for Tcap transaction with identifier has been reached */
- if (!p_tcaphash_ansicall->next_ansicall) {
- /* check if we have to create a new record or not */
- /* if last request has been responded (response number in known)
- and this request appears after last response (has bigger frame number)
- and last request occurred after the timeout for repetition,
- or
- if last request hasn't been responded (so number unknown)
- and this request appears after last request (has bigger frame number)
- and this request occurred after the timeout for message lost */
- if ( ( p_tcaphash_ansicall->context->last_frame != 0
- && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
- && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
- ) ||
- ( p_tcaphash_ansicall->context->last_frame == 0
- && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
- && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
- )
- )
- {
- /* we decide that we have a new request */
- /* Append new record to the list */
-#ifdef DEBUG_TCAPSRT
- dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
- dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
-#endif
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
- p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
- p_tcaphash_context,
- pinfo);
-
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
-#endif
- update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
- p_tcaphash_ansicall=p_new_tcaphash_ansicall;
- } else {
-
- /* If the Tid is reused for a closed Transaction */
- if ( p_tcaphash_ansicall->context->closed) {
-#ifdef DEBUG_TCAPSRT
- dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
- dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
-#endif
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
- p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
- p_tcaphash_context,
- pinfo);
-
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
-#endif
- update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
- p_tcaphash_ansicall=p_new_tcaphash_ansicall;
-
- } else {
- /* the Tid is reused for an opened Transaction */
- /* so, this is the reply to the request of our context */
- p_tcaphash_context=p_tcaphash_ansicall->context;
-#ifdef DEBUG_TCAPSRT
- dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
-#endif
-
- if (gtcap_DisplaySRT && tree) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
-
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
- /* Indicate the frame to which this is a reply. */
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
- p_tcaphash_context->first_frame,
- "Begin of session in frame %u",
- p_tcaphash_context->first_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
- /* display Service Response Time and make it filterable */
- pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- p_tcaphash_context=p_tcaphash_ansicall->context;
- } /* test with Timeout */
- } /* closed */
- break;
- } /* Next call is NULL */
- p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
- } while (p_tcaphash_ansicall != NULL );
- /*
- * New TCAP context
- */
- } else { /* p_tcaphash_ansicall has not been found */
-#ifdef DEBUG_TCAPSRT
- dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
-#endif
-
- tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
- p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
- p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
-
-#ifdef DEBUG_TCAPSRT
- dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
- dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
- update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
- }
-
- /* display tcap session, if available */
- if ( gtcap_DisplaySRT && tree &&
- p_tcaphash_context &&
- p_tcaphash_context->session_id) {
- stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
- PROTO_ITEM_SET_GENERATED(stat_item);
- stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
- pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
- PROTO_ITEM_SET_GENERATED(pi);
- }
-
-
- /* add link to response frame, if available */
- if( gtcap_DisplaySRT && stat_tree &&
- p_tcaphash_ansicall->context->last_frame != 0){
- if (!isResponse) { /* Request */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
-#endif
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
- p_tcaphash_ansicall->context->last_frame,
- "End of session in frame %u",
- p_tcaphash_ansicall->context->last_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- } else { /* Response */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
- /* Indicate the frame to which this is a reply. */
- if (gtcap_DisplaySRT) {
- pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
- p_tcaphash_context->first_frame,
- "Begin of session in frame %u",
- p_tcaphash_context->first_frame);
- PROTO_ITEM_SET_GENERATED(pi);
- /* Calculate Service Response Time */
- nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
- /* display Service Response Time and make it filterable */
- pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
- PROTO_ITEM_SET_GENERATED(pi);
- }
- } /* Request or Response */
- }
- return p_tcaphash_context;
-}
-
-
-/*
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct tcapsrt_info_t *
-tcapsrt_razinfo(void)
-{
- struct tcapsrt_info_t *p_tcapsrt_info ;
-
- /* Global buffer for packet extraction */
- tcapsrt_global_current++;
- if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
- tcapsrt_global_current=0;
- }
-
- p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
- memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
-
- return p_tcapsrt_info;
-}
-
-void
-tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
- packet_info *pinfo)
-{
-#ifdef DEBUG_TCAPSRT
- dbg(60,"Force close ");
-#endif
- if (p_tcaphash_context) {
- p_tcaphash_context->responded=TRUE;
- p_tcaphash_context->last_frame = pinfo->fd->num;
- p_tcaphash_context->end_time = pinfo->fd->abs_ts;
- p_tcaphash_context->closed=TRUE;
-
- /* If the endkey is present */
- if (p_tcaphash_context->endcall
- && !gtcap_PersistentSRT) {
- if (p_tcaphash_context->endcall->next_endcall) {
- if (p_tcaphash_context->endcall->previous_endcall ) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"deplace Ehash ");
-#endif
- p_tcaphash_context->endcall->previous_endcall->next_endcall
- = p_tcaphash_context->endcall->next_endcall;
- p_tcaphash_context->endcall->next_endcall->previous_endcall
- = p_tcaphash_context->endcall->previous_endcall;
- g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->endcall);
-#endif
- } else {
- /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"father Ehash ");
-#endif
- } /* no previous link, so father */
- } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"remove Ehash ");
-#endif
- g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->endcall->endkey);
- g_free(p_tcaphash_context->endcall);
-#endif
-
- } /* endcall without chained string */
- } /* no endcall */
-
-
- /* If the contkey is present */
- if (p_tcaphash_context->contcall
- && !gtcap_PersistentSRT) {
- if (p_tcaphash_context->contcall->next_contcall) {
- if (p_tcaphash_context->contcall->previous_contcall ) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"deplace Chash ");
-#endif
- p_tcaphash_context->contcall->previous_contcall->next_contcall
- = p_tcaphash_context->contcall->next_contcall;
- p_tcaphash_context->contcall->next_contcall->previous_contcall
- = p_tcaphash_context->contcall->previous_contcall;
- g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->contcall);
-#endif
- } else {
- /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"father Chash ");
-#endif
- } /* no previous link, so father */
- } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"remove Chash ");
-#endif
- g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->contcall->contkey);
- g_free(p_tcaphash_context->contcall);
-#endif
- } /* contcall without chained string */
- } /* no contcall */
-
-
- /* If the beginkey is present */
- if (p_tcaphash_context->begincall
- && !gtcap_PersistentSRT) {
- if (p_tcaphash_context->begincall->next_begincall) {
- if (p_tcaphash_context->begincall->previous_begincall ) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"deplace Bhash ");
-#endif
- p_tcaphash_context->begincall->previous_begincall->next_begincall
- = p_tcaphash_context->begincall->next_begincall;
- p_tcaphash_context->begincall->next_begincall->previous_begincall
- = p_tcaphash_context->begincall->previous_begincall;
- g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->begincall);
-#endif
- } else {
- /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"father Bhash ");
-#endif
- }
- } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"remove Bhash ");
-#endif
- g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->begincall->beginkey);
- g_free(p_tcaphash_context->begincall);
-#endif
- } /* begincall without chained string */
- } /* no begincall */
-
- /* If the ansikey is present */
- if (p_tcaphash_context->ansicall
- && !gtcap_PersistentSRT) {
- if (p_tcaphash_context->ansicall->next_ansicall) {
- if (p_tcaphash_context->ansicall->previous_ansicall ) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"deplace Ahash ");
-#endif
- p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
- = p_tcaphash_context->ansicall->next_ansicall;
- p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
- = p_tcaphash_context->ansicall->previous_ansicall;
- g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->ansicall);
-#endif
- } else {
- /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"father Ahash ");
-#endif
- }
- } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"remove Ahash ");
-#endif
- g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->ansicall->ansikey);
- g_free(p_tcaphash_context->ansicall);
-#endif
- } /* ansicall without chained string */
- } /* no ansicall */
-
- if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
- dbg(20,"remove context ");
-#endif
- g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
-#ifdef MEM_TCAPSRT
- g_free(p_tcaphash_context->key);
- g_free(p_tcaphash_context);
-#endif
- }
- } else { /* no context */
-#ifdef DEBUG_TCAPSRT
- dbg(20,"No context to remove ");
-#endif
- }
-}
+++ /dev/null
-/*
- * tcap-persistentdata.h
- * Definitions for lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-transactions
- * Copyright 2006 Florent Drouin (based on h225-persistentdata from Lars Roland)
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * $Id$
- *
- * 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 __tcapsrt_HASH__
-#define __tcapsrt_HASH__
-
-#include <epan/packet.h>
-#include <epan/conversation.h>
-#include <epan/dissectors/packet-tcap.h>
-#include "ws_symbol_export.h"
-
-/** @file
- * lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-calls
- */
-
-#define LENGTH_OID 23
-struct tcaphash_context_t {
- struct tcaphash_context_key_t * key;
- guint32 session_id;
- guint32 first_frame;
- guint32 last_frame;
- nstime_t begin_time; /**< time of arrival of TC_BEGIN */
- nstime_t end_time; /**< time of closing message */
- gboolean responded; /**< true, if request has been responded */
- gboolean closed;
- gboolean upper_dissector;
- gboolean oid_present;
- gchar oid[LENGTH_OID+1];
- gboolean subdissector_present;
- dissector_handle_t subdissector_handle;
- void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
- struct tcaphash_begincall_t * begincall;
- struct tcaphash_contcall_t * contcall;
- struct tcaphash_endcall_t * endcall;
- struct tcaphash_ansicall_t * ansicall;
-};
-
-struct tcaphash_begincall_t {
- struct tcaphash_begin_info_key_t * beginkey;
- struct tcaphash_context_t * context;
- gboolean father;
- struct tcaphash_begincall_t * next_begincall;
- struct tcaphash_begincall_t * previous_begincall;
-};
-
-struct tcaphash_contcall_t {
- struct tcaphash_cont_info_key_t * contkey;
- struct tcaphash_context_t * context;
- gboolean father;
- struct tcaphash_contcall_t * next_contcall;
- struct tcaphash_contcall_t * previous_contcall;
-};
-
-struct tcaphash_endcall_t {
- struct tcaphash_end_info_key_t * endkey;
- struct tcaphash_context_t * context;
- gboolean father;
- struct tcaphash_endcall_t * next_endcall;
- struct tcaphash_endcall_t * previous_endcall;
-};
-
-struct tcaphash_ansicall_t {
- struct tcaphash_ansi_info_key_t * ansikey;
- struct tcaphash_context_t * context;
- gboolean father;
- struct tcaphash_ansicall_t * next_ansicall;
- struct tcaphash_ansicall_t * previous_ansicall;
-};
-
-/** The Key for the hash table is the TCAP origine transaction identifier
- of the TC_BEGIN containing the InitialDP */
-
-struct tcaphash_context_key_t {
- guint32 session_id;
-};
-
-struct tcaphash_begin_info_key_t {
- guint32 hashKey;
- guint32 tid;
- guint32 opc_hash;
- guint32 dpc_hash;
-};
-
-struct tcaphash_cont_info_key_t {
- guint32 hashKey;
- guint32 src_tid;
- guint32 dst_tid;
- guint32 opc_hash;
- guint32 dpc_hash;
-};
-
-struct tcaphash_end_info_key_t {
- guint32 hashKey;
- guint32 tid;
- guint32 opc_hash;
- guint32 dpc_hash;
-};
-
-struct tcaphash_ansi_info_key_t {
- guint32 hashKey;
- guint32 tid;
- guint32 opc_hash;
- guint32 dpc_hash;
-};
-
-
-/** List of infos to store for the analyse */
-struct tcapsrt_info_t {
- guint32 tcap_session_id;
- guint32 src_tid;
- guint32 dst_tid;
- guint8 ope;
-};
-
-/**
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void tcapsrt_init_routine(void);
-
-/**
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct tcapsrt_info_t * tcapsrt_razinfo(void);
-
-void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
- packet_info * pinfo _U_);
-
-/**
- * Service Response Time analyze
- * Called just after dissector call
- * Associate a TCAP context to a tcap session and display session related infomations
- * like the first frame, the last, the session duration,
- * and a uniq session identifier for the filtering
- *
- * For ETSI tcap, the TCAP context can be reached through three keys
- * - a key (BEGIN) identifying the session according to the tcap source identifier
- * - a key (CONT) identifying the established session (src_id and dst_id)
- * - a key (END) identifying the session according to the tcap destination identifier
- *
- * For ANSI tcap, the TCAP context is reached through a uniq key
- * - a key (ANSI) identifying the session according to the tcap identifier
-*/
-struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
- packet_info * pinfo _U_,
- proto_tree *tree,
- struct tcapsrt_info_t * p_tcap_info);
-
-WS_DLL_PUBLIC gboolean gtcap_StatSRT;
-
-#endif /* __tcapsrt_HASH__*/
#include "epan/value_string.h"
#include "epan/stat_cmd_args.h"
#include "epan/asn1.h"
-#include "epan/camel-persistentdata.h"
+#include "epan/dissectors/packet-camel.h"
void register_tap_listener_camelcounter(void);
#include "epan/value_string.h"
#include "epan/asn1.h"
#include "epan/dissectors/packet-camel.h"
-#include "epan/camel-persistentdata.h"
+#include "epan/dissectors/packet-tcap.h"
#include "epan/timestats.h"
#include "epan/stat_cmd_args.h"
#include <epan/tap.h>
#include <epan/packet.h>
#include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
+#include <epan/dissectors/packet-camel.h>
#include "../stat_menu.h"
#include <epan/tap.h>
#include <epan/packet.h>
#include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
+#include <epan/dissectors/packet-camel.h>
#include "../file.h"
#include "../stat_menu.h"