2 * tcap-persistentdata.c
3 * Source for lists and hash tables used in wireshark's tcap dissector
4 * for calculation of delays in tcap-calls
5 * Copyright 2006 Florent Drouin (based on h225-persistentdata.c from Lars Roland)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include "epan/emem.h"
35 #include "epan/packet.h"
36 #include "epan/conversation.h"
37 #include "epan/tcap-persistentdata.h"
38 #include "epan/dissectors/packet-tcap.h"
39 #include "epan/dissectors/packet-mtp3.h"
41 static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
42 static guint tcaphash_context_calchash(gconstpointer k);
43 static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
44 static guint tcaphash_begin_calchash(gconstpointer k);
45 static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
46 static guint tcaphash_cont_calchash(gconstpointer k);
47 static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
48 static guint tcaphash_end_calchash(gconstpointer k);
50 static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
53 static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
54 struct tcaphash_context_t * p_tcaphash_context,
58 static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
63 static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
66 static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
70 static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
73 static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
74 struct tcaphash_context_t * p_tcaphash_context,
77 static struct tcaphash_contcall_t * new_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
78 struct tcaphash_context_t * p_tcaphash_context,
81 static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
82 struct tcaphash_context_t * p_tcaphash_context,
85 static struct tcaphash_context_t *
86 tcaphash_begin_matching(tvbuff_t *tvb,
87 packet_info * pinfo _U_,
89 struct tcapsrt_info_t * p_tcapsrt_info);
91 static struct tcaphash_context_t *
92 tcaphash_cont_matching(tvbuff_t *tvb,
93 packet_info * pinfo _U_,
95 struct tcapsrt_info_t * p_tcapsrt_info);
97 static struct tcaphash_context_t *
98 tcaphash_end_matching(tvbuff_t *tvb,
99 packet_info * pinfo _U_,
101 struct tcapsrt_info_t * p_tcapsrt_info);
103 struct tcapsrt_info_t * tcapsrt_razinfo(void);
105 /* When several Tcap components are received in a single TCAP message,
106 we have to use several buffers for the stored parameters
107 because else this data are erased during TAP dissector call */
108 #define MAX_TCAP_INSTANCE 10
109 int tcapsrt_global_current=0;
110 struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
112 /* These two timeout (in second) are used when some message are lost,
113 or when the same TCAP transcation identifier is reused */
114 guint gtcap_RepetitionTimeout = 10;
115 guint gtcap_LostTimeout = 30;
116 extern gboolean gtcap_HandleSRT;
117 gboolean gtcap_PersistentSRT=FALSE;
118 gboolean gtcap_DisplaySRT=FALSE;
119 gboolean gtcap_StatSRT=FALSE;
121 extern int hf_tcapsrt_SessionId;
122 extern int hf_tcapsrt_Duplicate;
123 extern int hf_tcapsrt_BeginSession;
124 extern int hf_tcapsrt_EndSession;
125 extern int hf_tcapsrt_SessionTime;
127 /* Global hash tables*/
128 static GHashTable * tcaphash_context = NULL;
129 static GHashTable * tcaphash_begin = NULL;
130 static GHashTable * tcaphash_cont = NULL;
131 static GHashTable * tcaphash_end = NULL;
133 guint32 tcapsrt_global_SessionId=1;
140 /* #define DEBUG_TCAPSRT */
145 static unsigned debug_level = 99;
147 static void dbg(unsigned level, char* fmt, ...) {
150 if (level > debug_level) return;
152 vfprintf(stderr, fmt, ap);
157 static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
159 const struct tcaphash_context_key_t * key1 = (const struct tcaphash_context_key_t *) k1;
160 const struct tcaphash_context_key_t * key2 = (const struct tcaphash_context_key_t *) k2;
162 return (key1->session_id == key2->session_id);
165 /* calculate a hash key */
166 static guint tcaphash_context_calchash(gconstpointer k)
168 const struct tcaphash_context_key_t * key = (const struct tcaphash_context_key_t *) k;
169 return key->session_id;
173 static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
175 const struct tcaphash_begin_info_key_t * key1 = (const struct tcaphash_begin_info_key_t *) k1;
176 const struct tcaphash_begin_info_key_t * key2 = (const struct tcaphash_begin_info_key_t *) k2;
178 if (key1->hashKey == key2->hashKey) {
180 if ( ( (key1->opc_hash == key2->opc_hash) &&
181 (key1->dpc_hash == key2->dpc_hash) &&
182 (key1->tid == key2->tid) )
184 ( (key1->opc_hash == key2->dpc_hash) &&
185 (key1->dpc_hash == key2->opc_hash) &&
186 (key1->tid == key2->tid) )
193 /* calculate a hash key */
194 static guint tcaphash_begin_calchash(gconstpointer k)
196 const struct tcaphash_begin_info_key_t * key = (const struct tcaphash_begin_info_key_t *) k;
198 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
203 static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
205 const struct tcaphash_cont_info_key_t * key1 = (const struct tcaphash_cont_info_key_t *) k1;
206 const struct tcaphash_cont_info_key_t * key2 = (const struct tcaphash_cont_info_key_t *) k2;
208 if (key1->hashKey == key2->hashKey) {
210 if ( (key1->opc_hash == key2->opc_hash) &&
211 (key1->dpc_hash == key2->dpc_hash) &&
212 (key1->src_tid == key2->src_tid) &&
213 (key1->dst_tid == key2->dst_tid) ) {
216 else if ( (key1->opc_hash == key2->dpc_hash) &&
217 (key1->dpc_hash == key2->opc_hash) &&
218 (key1->src_tid == key2->dst_tid) &&
219 (key1->dst_tid == key2->src_tid) ) {
226 /* calculate a hash key */
227 static guint tcaphash_cont_calchash(gconstpointer k)
229 const struct tcaphash_cont_info_key_t * key = (const struct tcaphash_cont_info_key_t *) k;
231 hashkey = key->src_tid + key->dst_tid;
236 static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
238 const struct tcaphash_end_info_key_t * key1 = (const struct tcaphash_end_info_key_t *) k1;
239 const struct tcaphash_end_info_key_t * key2 = (const struct tcaphash_end_info_key_t *) k2;
241 if (key1->hashKey == key2->hashKey) {
242 if ( ( (key1->opc_hash == key2->opc_hash) &&
243 (key1->dpc_hash == key2->dpc_hash) &&
244 (key1->tid == key2->tid) )
246 ( (key1->opc_hash == key2->dpc_hash) &&
247 (key1->dpc_hash == key2->opc_hash) &&
248 (key1->tid == key2->tid) ) )
254 /* calculate a hash key */
255 static guint tcaphash_end_calchash(gconstpointer k)
257 const struct tcaphash_end_info_key_t * key = (const struct tcaphash_end_info_key_t *) k;
264 * Update a record with the data of the Request
266 static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
269 p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
270 p_tcaphash_begincall->context->last_frame = 0;
271 p_tcaphash_begincall->context->responded = FALSE;
272 p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
276 * Append a new dialogue, using the same Key, to the chained list
277 * The time is stored too
279 static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
280 struct tcaphash_context_t * p_tcaphash_context,
284 struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
286 /* Append the transaction to the list, when the same key is found
287 This should append when the tcap-transaction Id is reused */
289 p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
290 p_new_tcaphash_begincall->context=p_tcaphash_context;
291 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
292 p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
293 p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
294 p_new_tcaphash_begincall->next_begincall=NULL;
295 p_new_tcaphash_begincall->previous_begincall=prev_begincall;
296 p_new_tcaphash_begincall->father=FALSE;
299 dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
301 /* Insert in the chained list */
302 prev_begincall->next_begincall = p_new_tcaphash_begincall;
303 if (prev_begincall->context->last_frame == 0) {
307 prev_begincall->context->last_frame = pinfo->fd->num-1;
309 return p_new_tcaphash_begincall;
312 static struct tcaphash_contcall_t * append_tcaphash_contcall(struct tcaphash_contcall_t * prev_contcall,
313 struct tcaphash_context_t * p_tcaphash_context,
317 struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
319 /* Append the transaction to the list, when the same key is found
320 This should append when the tcap-transaction Id is reused */
322 p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
323 p_new_tcaphash_contcall->context=p_tcaphash_context;
324 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
325 p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
326 p_new_tcaphash_contcall->next_contcall=NULL;
327 p_new_tcaphash_contcall->previous_contcall=prev_contcall;
328 p_new_tcaphash_contcall->father=FALSE;
331 dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
333 /* Insert in the chained list */
334 prev_contcall->next_contcall = p_new_tcaphash_contcall;
335 return p_new_tcaphash_contcall;
339 static struct tcaphash_endcall_t * append_tcaphash_endcall(struct tcaphash_endcall_t * prev_endcall,
340 struct tcaphash_context_t * p_tcaphash_context,
344 struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
346 /* Append the transaction to the list, when the same key is found
347 This should append when the tcap-transaction Id is reused */
349 p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
350 p_new_tcaphash_endcall->context=p_tcaphash_context;
351 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
352 p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
353 p_new_tcaphash_endcall->next_endcall=NULL;
354 p_new_tcaphash_endcall->previous_endcall=prev_endcall;
355 p_new_tcaphash_endcall->father=FALSE;
358 dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
360 /* Insert in the chained list */
361 prev_endcall->next_endcall = p_new_tcaphash_endcall;
362 return p_new_tcaphash_endcall;
367 * Find the dialog by Key and Time
369 static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
373 struct tcaphash_begincall_t * p_tcaphash_begincall = NULL;
374 p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
376 if(p_tcaphash_begincall) {
378 if ( p_tcaphash_begincall->context ) {
380 pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
383 pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
384 ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
387 /* We have a dialogue, with this key, opened before this request */
389 dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
391 return p_tcaphash_begincall;
395 /* Break when list end is reached */
396 if(p_tcaphash_begincall->next_begincall == NULL) {
398 dbg(23,"End of Blist ");
402 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
403 } while (p_tcaphash_begincall != NULL) ;
406 dbg(23,"Not in Bhash ");
414 static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
417 struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
418 p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
420 if(p_tcaphash_contcall) {
422 if ( p_tcaphash_contcall->context &&
423 pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
424 (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
425 /* We have a dialogue, with this key, opened before this request */
427 dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
429 return p_tcaphash_contcall;
433 dbg(23,"Bug in Clist ");
436 /* Break when list end is reached */
437 if(p_tcaphash_contcall->next_contcall == NULL) {
439 dbg(23,"End of Clist ");
443 p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
444 } while (p_tcaphash_contcall != NULL) ;
447 dbg(23,"Not in Chash ");
453 static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
457 struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
458 p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
460 if(p_tcaphash_endcall) {
462 if ( p_tcaphash_endcall->context ) {
464 (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
468 pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
469 (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
472 /* We have a dialogue, with this key, opened before this request */
474 dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
476 return p_tcaphash_endcall;
480 dbg(23,"Bug in Elist ");
484 /* Break when list end is reached */
485 if(p_tcaphash_endcall->next_endcall == NULL) {
487 dbg(23,"End of Elist ");
491 p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
492 } while (p_tcaphash_endcall != NULL) ;
495 dbg(23,"Not in Ehash ");
502 * New record to create, to identify a new transaction
504 static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
507 struct tcaphash_context_key_t * p_new_tcaphash_context_key;
508 struct tcaphash_context_t * p_new_tcaphash_context = NULL;
510 /* Register the transaction in the hash table
511 with the tcap transaction Id as Main Key
512 Once created, this entry will be updated later */
514 p_new_tcaphash_context_key = se_alloc(sizeof(struct tcaphash_context_key_t));
515 p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
517 p_new_tcaphash_context = se_alloc0(sizeof(struct tcaphash_context_t));
518 p_new_tcaphash_context->key = p_new_tcaphash_context_key;
519 p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
520 p_new_tcaphash_context->first_frame = pinfo->fd->num;
522 dbg(10,"S%d ", p_new_tcaphash_context->session_id);
525 g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
526 return p_new_tcaphash_context;
530 * New record to create, to identify a new transaction
532 static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
533 struct tcaphash_context_t * p_tcaphash_context,
536 struct tcaphash_begin_info_key_t * p_new_tcaphash_begin_key;
537 struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
539 /* Register the transaction in the hash table
540 with the tcap transaction Id as Main Key
541 Once created, this entry will be updated later */
543 p_new_tcaphash_begin_key = se_alloc(sizeof(struct tcaphash_begin_info_key_t));
544 p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
545 p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
546 p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
547 p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
549 p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
550 p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
551 p_new_tcaphash_begincall->context=p_tcaphash_context;
552 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
553 p_new_tcaphash_begincall->father=TRUE;
554 p_new_tcaphash_begincall->next_begincall=NULL;
555 p_new_tcaphash_begincall->previous_begincall=NULL;
558 dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
561 g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
562 return p_new_tcaphash_begincall;
568 * New record to create, to identify a new transaction
570 static struct tcaphash_contcall_t * new_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
571 struct tcaphash_context_t * p_tcaphash_context,
574 struct tcaphash_cont_info_key_t * p_new_tcaphash_cont_key;
575 struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
577 /* Register the transaction in the hash table
578 with the tcap transaction Id as Main Key
579 Once created, this entry will be updated later */
581 p_new_tcaphash_cont_key = se_alloc(sizeof(struct tcaphash_cont_info_key_t));
582 p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
583 p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
584 p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
585 p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
586 p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
588 p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
589 p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
590 p_new_tcaphash_contcall->context=p_tcaphash_context;
591 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
592 p_new_tcaphash_contcall->father=TRUE;
593 p_new_tcaphash_contcall->next_contcall=NULL;
594 p_new_tcaphash_contcall->previous_contcall=NULL;
597 dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
600 g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
601 return p_new_tcaphash_contcall;
606 * New record to create, to identify a new transaction
608 static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
609 struct tcaphash_context_t * p_tcaphash_context,
612 struct tcaphash_end_info_key_t * p_new_tcaphash_end_key;
613 struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
615 /* Register the transaction in the hash table
616 with the tcap transaction Id as Main Key
617 Once created, this entry will be updated later */
619 p_new_tcaphash_end_key = se_alloc(sizeof(struct tcaphash_end_info_key_t));
620 p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
621 p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
622 p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
623 p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
625 p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
626 p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
627 p_new_tcaphash_endcall->context=p_tcaphash_context;
628 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
629 p_new_tcaphash_endcall->father=TRUE;
630 p_new_tcaphash_endcall->next_endcall=NULL;
631 p_new_tcaphash_endcall->previous_endcall=NULL;
634 dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
637 g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
638 return p_new_tcaphash_endcall;
643 static struct tcaphash_contcall_t *
644 create_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
645 struct tcaphash_context_t * p_tcaphash_context,
648 struct tcaphash_contcall_t * p_tcaphash_contcall1 = NULL;
649 struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
651 p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
652 g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
654 if (p_tcaphash_contcall1) {
655 /* Walk through list of transaction with identical keys */
656 /* go the the end to insert new record */
658 if (!p_tcaphash_contcall1->next_contcall) {
659 p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
664 p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
665 } while (p_tcaphash_contcall1 != NULL );
667 p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
671 return p_tcaphash_contcall;
675 static struct tcaphash_endcall_t *
676 create_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
677 struct tcaphash_context_t * p_tcaphash_context,
680 struct tcaphash_endcall_t * p_tcaphash_endcall1 = NULL;
681 struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
683 p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
684 g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
686 if (p_tcaphash_endcall1) {
687 /* Walk through list of transaction with identical keys */
688 /* go the the end to insert new record */
690 if (!p_tcaphash_endcall1->next_endcall) {
691 p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
696 p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
697 } while (p_tcaphash_endcall1 != NULL );
699 p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
703 return p_tcaphash_endcall;
708 * Routine called when the TAP is initialized.
709 * so hash table are (re)created
711 void tcapsrt_init_routine(void)
714 /* free hash-tables and mem_chunks for SRT */
715 if (tcaphash_context != NULL) {
717 dbg(16,"Destroy hash_context ");
719 g_hash_table_destroy(tcaphash_context);
722 if (tcaphash_begin != NULL) {
724 dbg(16,"Destroy hash_begin ");
726 g_hash_table_destroy(tcaphash_begin);
729 if (tcaphash_cont != NULL) {
731 dbg(16,"Destroy hash_cont ");
733 g_hash_table_destroy(tcaphash_cont);
736 if (tcaphash_end != NULL) {
738 dbg(16,"Destroy hash_end ");
740 g_hash_table_destroy(tcaphash_end);
744 dbg(16,"Create hash ");
746 /* create new hash-tables and mem_chunks for SRT */
747 tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
748 tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
749 tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
750 tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
752 /* Reset the session counter */
753 tcapsrt_global_SessionId=1;
755 /* Display of SRT only if Persistent Stat */
756 gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT>cap_StatSRT;
760 * Service Responsee Time analyze
761 * Called just after dissector call
763 struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
764 packet_info * pinfo _U_,
766 struct tcapsrt_info_t * p_tcapsrt_info)
768 struct tcaphash_context_t * tcap_context=NULL;
770 switch (p_tcapsrt_info->ope) {
772 case TC_BEGIN: /*InitialDP*/
776 tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
783 tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
790 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
797 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
802 dbg(1,"Unknow %d ", p_tcapsrt_info->ope);
805 } /* switch tcapop */
808 dbg(1,"session %d ", tcap_context->session_id);
815 * Create the record identifiying the TCAP transaction
816 * When the identifier for the transaction is reused, check
817 * the following criteria before to append a new record:
818 * - a timeout corresponding to a message retransmission is detected,
819 * - a message hast been lost
820 * - or the previous transaction has been be closed
822 static struct tcaphash_context_t *
823 tcaphash_begin_matching(tvbuff_t *tvb,
824 packet_info * pinfo _U_,
826 struct tcapsrt_info_t * p_tcapsrt_info)
828 struct tcaphash_context_t * p_tcaphash_context=NULL;
829 struct tcaphash_context_key_t tcaphash_context_key;
830 struct tcaphash_begincall_t * p_tcaphash_begincall, * p_new_tcaphash_begincall;
831 struct tcaphash_begin_info_key_t tcaphash_begin_key;
834 /* prepare the key data */
835 tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
836 tcaphash_begin_key.opc_hash = mtp3_pc_hash( ((address *)(&pinfo->src))->data);
837 tcaphash_begin_key.dpc_hash = mtp3_pc_hash( ((address *)(&pinfo->dst))->data);
838 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
840 /* look up the request */
842 dbg(10,"\n Hbegin #%d ", pinfo->fd->num);
843 dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
844 dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
845 dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
847 p_tcaphash_begincall = (struct tcaphash_begincall_t *)
848 g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
850 if (p_tcaphash_begincall) {
851 /* Walk through list of transaction with identical keys */
853 /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
854 if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
855 /* We have seen this request before -> do nothing */
857 dbg(22,"Already seen ");
859 p_tcaphash_context=p_tcaphash_begincall->context;
862 /* If the last record for Tcap transaction with identifier has been reached */
863 if (!p_tcaphash_begincall->next_begincall) {
864 /* check if we have to create a new record or not */
865 /* if last request has been responded (response number in known)
866 and this request appears after last response (has bigger frame number)
867 and last request occured after the timeout for repetition,
869 if last request hasn't been responded (so number unknown)
870 and this request appears after last request (has bigger frame number)
871 and this request occured after the timeout for message lost */
872 if ( ( p_tcaphash_begincall->context->last_frame != 0
873 && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
874 && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
876 ( p_tcaphash_begincall->context->last_frame == 0
877 && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
878 && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
882 /* we decide that we have a new request */
883 /* Append new record to the list */
885 dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
886 dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
888 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
889 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
890 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
895 dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
897 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
898 p_tcaphash_begincall=p_new_tcaphash_begincall;
901 /* If the Tid is reused for a closed Transaction */
902 /* Or if we received an InitialDP for a non closed Transaction */
903 if ( p_tcaphash_begincall->context->closed) {
905 dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
906 dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
908 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
909 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
910 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
915 dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
917 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
918 p_tcaphash_begincall=p_new_tcaphash_begincall;
921 /* No, so it's a duplicate request.Mark it as such. */
923 dbg(21,"Display_duplicate ");
925 if (gtcap_DisplaySRT)
926 proto_tree_add_uint_hidden(tree, hf_tcapsrt_Duplicate, tvb, 0,0, p_tcapsrt_info->src_tid);
927 p_tcaphash_context=p_tcaphash_begincall->context;
928 } /* test with Timeout */
931 } /* Next call is NULL */
932 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
933 } while (p_tcaphash_begincall != NULL );
937 } else { /* p_tcaphash_begincall has not been found */
939 dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
942 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
943 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
944 p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context, pinfo);
947 dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
948 dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
950 update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
953 /* display tcap session, if available */
954 if ( gtcap_DisplaySRT &&
955 p_tcaphash_context &&
956 p_tcaphash_context->session_id)
957 proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
959 /* add link to response frame, if available */
960 if( gtcap_DisplaySRT &&
961 p_tcaphash_begincall->context->last_frame != 0){
963 dbg(20,"Display_frameRsplink %d ",p_tcaphash_begincall->context->last_frame);
965 ti = proto_tree_add_uint_format(tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
966 p_tcaphash_begincall->context->last_frame,
967 "End of session in frame %u",
968 p_tcaphash_begincall->context->last_frame);
969 PROTO_ITEM_SET_GENERATED(ti);
971 return p_tcaphash_context;
976 * Register the request, and try to find the response
979 static struct tcaphash_context_t *
980 tcaphash_cont_matching(tvbuff_t *tvb,
981 packet_info * pinfo _U_,
983 struct tcapsrt_info_t * p_tcapsrt_info)
985 struct tcaphash_context_t * p_tcaphash_context=NULL;
986 struct tcaphash_contcall_t * p_tcaphash_contcall;
987 struct tcaphash_cont_info_key_t tcaphash_cont_key;
991 dbg(10,"\n Hcont #%d ", pinfo->fd->num);
994 /* look only for matching request, if matching conversation is available. */
995 tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
996 tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
997 tcaphash_cont_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
998 tcaphash_cont_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
999 tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1001 #ifdef DEBUG_TCAPSRT
1002 dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1003 dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
1004 dbg(51,"Tid %lx %lx ",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1006 p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1007 if(p_tcaphash_contcall) {
1008 #ifdef DEBUG_TCAPSRT
1011 p_tcaphash_context=p_tcaphash_contcall->context;
1012 } else { /* Not found */
1013 #ifdef DEBUG_TCAPSRT
1014 dbg(12,"CnotFound ");
1016 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1017 struct tcaphash_begincall_t * p_tcaphash_begincall;
1019 struct tcaphash_end_info_key_t tcaphash_end_key;
1020 struct tcaphash_endcall_t * p_tcaphash_endcall;
1022 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1023 tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1024 tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1025 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1027 #ifdef DEBUG_TCAPSRT
1028 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1029 dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
1030 dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1032 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1033 if(p_tcaphash_begincall &&
1034 !p_tcaphash_begincall->context->contcall ) {
1035 #ifdef DEBUG_TCAPSRT
1038 p_tcaphash_context=p_tcaphash_begincall->context;
1039 p_tcaphash_context->responded=TRUE;
1041 #ifdef DEBUG_TCAPSRT
1042 dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1044 p_tcaphash_contcall = create_tcaphash_cont(&tcaphash_cont_key,
1045 p_tcaphash_begincall->context,
1048 #ifdef DEBUG_TCAPSRT
1049 dbg(11,"Update Ckey %lx ",tcaphash_begin_key.hashKey);
1050 dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
1052 tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
1053 tcaphash_end_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1054 tcaphash_end_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1055 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1057 #ifdef DEBUG_TCAPSRT
1058 dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1060 p_tcaphash_endcall = create_tcaphash_end(&tcaphash_end_key,
1061 p_tcaphash_begincall->context,
1064 #ifdef DEBUG_TCAPSRT
1065 dbg(11,"Update Ekey %lx ",tcaphash_end_key.hashKey);
1066 dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
1068 } else { /* Begin not found */
1069 #ifdef DEBUG_TCAPSRT
1070 dbg(12,"BnotFound ");
1074 /* display tcap session, if available */
1075 if (gtcap_DisplaySRT &&
1076 p_tcaphash_context &&
1077 p_tcaphash_context->session_id)
1078 proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1080 return p_tcaphash_context;
1089 static struct tcaphash_context_t *
1090 tcaphash_end_matching(tvbuff_t *tvb,
1091 packet_info * pinfo _U_,
1093 struct tcapsrt_info_t * p_tcapsrt_info)
1095 struct tcaphash_context_t * p_tcaphash_context=NULL;
1097 struct tcaphash_end_info_key_t tcaphash_end_key;
1098 struct tcaphash_endcall_t * p_tcaphash_endcall=NULL;
1100 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1101 struct tcaphash_begincall_t * p_tcaphash_begincall=NULL;
1106 #ifdef DEBUG_TCAPSRT
1107 dbg(10,"\n Hend #%d ", pinfo->fd->num);
1109 /* look only for matching request, if matching conversation is available. */
1110 tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1111 tcaphash_end_key.opc_hash = mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1112 tcaphash_end_key.dpc_hash = mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1113 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1115 #ifdef DEBUG_TCAPSRT
1116 dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1117 dbg(11,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
1118 dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1120 p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
1122 if(!p_tcaphash_endcall) {
1123 #ifdef DEBUG_TCAPSRT
1124 dbg(12,"EnotFound ");
1126 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1127 tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1128 tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1129 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1131 #ifdef DEBUG_TCAPSRT
1132 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1133 dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
1134 dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1136 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1139 if (p_tcaphash_endcall) {
1140 /* Use the TC_BEGIN Destination reference */
1141 p_tcaphash_context=p_tcaphash_endcall->context;
1142 } else if (p_tcaphash_begincall) {
1143 /* Use the TC_BEGIN Source reference */
1144 p_tcaphash_context=p_tcaphash_begincall->context;
1147 if (p_tcaphash_context) {
1149 #ifdef DEBUG_TCAPSRT
1150 dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1152 if (gtcap_DisplaySRT)
1153 proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1155 #ifdef DEBUG_TCAPSRT
1156 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1158 /* Indicate the frame to which this is a reply. */
1159 if (gtcap_DisplaySRT) {
1160 ti = proto_tree_add_uint_format(tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1161 p_tcaphash_context->first_frame,
1162 "Begin of session in frame %u",
1163 p_tcaphash_context->first_frame);
1164 PROTO_ITEM_SET_GENERATED(ti);
1165 /* Calculate Service Response Time */
1166 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1168 /* display Service Response Time and make it filterable */
1169 ti = proto_tree_add_time(tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1170 PROTO_ITEM_SET_GENERATED(ti);
1172 /* Close the context and remove it */
1173 tcapsrt_close(p_tcaphash_context,pinfo);
1175 } /* context present */
1176 return p_tcaphash_context;
1180 * Initialize the Message Info used by the main dissector
1181 * Data are linked to a TCAP transaction
1183 struct tcapsrt_info_t * tcapsrt_razinfo(void)
1185 struct tcapsrt_info_t * p_tcapsrt_info ;
1187 /* Global buffer for packet extraction */
1188 tcapsrt_global_current++;
1189 if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1190 tcapsrt_global_current=0;
1193 p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1194 memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
1196 return p_tcapsrt_info;
1199 void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
1200 packet_info * pinfo _U_)
1202 #ifdef DEBUG_TCAPSRT
1203 dbg(60,"Force close ");
1205 if (p_tcaphash_context) {
1206 p_tcaphash_context->responded=TRUE;
1207 p_tcaphash_context->last_frame = pinfo->fd->num;
1208 p_tcaphash_context->end_time = pinfo->fd->abs_ts;
1209 p_tcaphash_context->closed=TRUE;
1211 /* If the endkey is present */
1212 if ( p_tcaphash_context->endcall
1213 && !gtcap_PersistentSRT ) {
1214 #ifdef DEBUG_TCAPSRT
1215 dbg(20,"remove Ehash ");
1217 g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1220 /* If the contkey is present */
1221 if ( p_tcaphash_context->contcall
1222 && !gtcap_PersistentSRT) {
1223 #ifdef DEBUG_TCAPSRT
1224 dbg(20,"remove Chash ");
1226 g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1229 /* If the beginkey is present */
1230 if (p_tcaphash_context->begincall->next_begincall) {
1231 if (p_tcaphash_context->begincall->previous_begincall ) {
1232 #ifdef DEBUG_TCAPSRT
1233 dbg(20,"deplace Bhash ");
1235 p_tcaphash_context->begincall->previous_begincall->next_begincall
1236 = p_tcaphash_context->begincall->next_begincall;
1237 p_tcaphash_context->begincall->next_begincall->previous_begincall
1238 = p_tcaphash_context->begincall->previous_begincall;
1240 /* cannot remove the father */
1241 #ifdef DEBUG_TCAPSRT
1242 dbg(20,"father Bhash ");
1245 } else if (!gtcap_PersistentSRT) {
1246 #ifdef DEBUG_TCAPSRT
1247 dbg(20,"remove Bhash ");
1249 g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1250 #ifdef DEBUG_TCAPSRT
1251 dbg(20,"remove context ");
1253 g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
1255 } /* begincall without chained string */
1256 } else { /* no context */
1257 #ifdef DEBUG_TCAPSRT
1258 dbg(20,"No context to remove ");