diff options
author | Michael Mann <mmann78@netscape.net> | 2013-12-30 22:07:38 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2013-12-30 22:07:38 +0000 |
commit | 58346b632786cebda787c8519b2d3e70207ab6b5 (patch) | |
tree | 40afe325045aa3de70f202f91d7c2d08b8214d69 /asn1/tcap | |
parent | 94387fdcbd451cf0762ed898a5e63fbf85f3904c (diff) |
Move tcap and camel "persistent data" functionality to the dissectors themselves instead of being part of epan directory.
svn path=/trunk/; revision=54499
Diffstat (limited to 'asn1/tcap')
-rw-r--r-- | asn1/tcap/packet-tcap-template.c | 1838 | ||||
-rw-r--r-- | asn1/tcap/packet-tcap-template.h | 141 |
2 files changed, 1973 insertions, 6 deletions
diff --git a/asn1/tcap/packet-tcap-template.c b/asn1/tcap/packet-tcap-template.c index 869ac0f9c9..bc338ab08f 100644 --- a/asn1/tcap/packet-tcap-template.c +++ b/asn1/tcap/packet-tcap-template.c @@ -39,7 +39,8 @@ #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" @@ -76,16 +77,35 @@ static struct tcaphash_context_t * gp_tcap_context=NULL; #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; @@ -135,11 +155,1817 @@ dissector_handle_t get_itu_tcap_subdissector(guint32 ssn) { 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" }, diff --git a/asn1/tcap/packet-tcap-template.h b/asn1/tcap/packet-tcap-template.h index 8d057c3713..fe0ab464cf 100644 --- a/asn1/tcap/packet-tcap-template.h +++ b/asn1/tcap/packet-tcap-template.h @@ -70,6 +70,147 @@ struct tcap_private_t { 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[]; |