Witness: add pidl output
[wireshark-wip.git] / epan / tcap-persistentdata.c
blobf046452debb28f8e578fc3a6e863cebb023110ec
1 /*
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 * $Id$
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <glib.h>
31 #include <string.h>
33 #include <epan/emem.h>
34 #include <epan/packet.h>
35 #include <epan/to_str.h>
36 #include <epan/asn1.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);
49 static gint tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2);
50 static guint tcaphash_ansi_calchash(gconstpointer k);
52 static void update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
53 packet_info *pinfo );
55 static struct tcaphash_begincall_t *append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
56 struct tcaphash_context_t *p_tcaphash_context,
57 packet_info *pinfo);
60 static struct tcaphash_begincall_t *find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
61 packet_info *pinfo,
62 gboolean isBegin);
65 static struct tcaphash_contcall_t *find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
66 packet_info *pinfo);
68 static struct tcaphash_endcall_t *find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
69 packet_info *pinfo,
70 gboolean isEnd);
71 /* new key */
72 static struct tcaphash_context_t *new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
73 packet_info *pinfo);
75 static struct tcaphash_begincall_t *new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
76 struct tcaphash_context_t *p_tcaphash_context);
78 static struct tcaphash_contcall_t *new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
79 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);
84 static struct tcaphash_context_t *tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
85 struct tcapsrt_info_t *p_tcapsrt_info);
87 static struct tcaphash_context_t *tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
88 struct tcapsrt_info_t *p_tcapsrt_info);
90 static struct tcaphash_context_t *tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
91 struct tcapsrt_info_t *p_tcapsrt_info);
93 static struct tcaphash_context_t *tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
94 struct tcapsrt_info_t *p_tcapsrt_info);
96 struct tcapsrt_info_t *tcapsrt_razinfo(void);
98 /* When several Tcap components are received in a single TCAP message,
99 we have to use several buffers for the stored parameters
100 because else this data are erased during TAP dissector call */
101 #define MAX_TCAP_INSTANCE 10
102 int tcapsrt_global_current=0;
103 struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
105 /* These two timeout (in second) are used when some message are lost,
106 or when the same TCAP transcation identifier is reused */
107 guint gtcap_RepetitionTimeout = 10;
108 guint gtcap_LostTimeout = 30;
109 extern gboolean gtcap_HandleSRT;
110 gboolean gtcap_PersistentSRT=FALSE;
111 gboolean gtcap_DisplaySRT=FALSE;
112 gboolean gtcap_StatSRT=FALSE;
114 extern gint ett_tcap_stat;
116 extern int hf_tcapsrt_SessionId;
117 extern int hf_tcapsrt_Duplicate;
118 extern int hf_tcapsrt_BeginSession;
119 extern int hf_tcapsrt_EndSession;
120 extern int hf_tcapsrt_SessionTime;
122 /* Global hash tables*/
123 static GHashTable *tcaphash_context = NULL;
124 static GHashTable *tcaphash_begin = NULL;
125 static GHashTable *tcaphash_cont = NULL;
126 static GHashTable *tcaphash_end = NULL;
127 static GHashTable *tcaphash_ansi = NULL;
129 guint32 tcapsrt_global_SessionId=1;
132 * DEBUG functions
134 #undef MEM_TCAPSRT
135 /* #define MEM_TCAPSRT */
137 #undef DEBUG_TCAPSRT
138 /* #define DEBUG_TCAPSRT */
140 #ifdef DEBUG_TCAPSRT
141 #include <stdio.h>
142 #include <stdarg.h>
143 static guint debug_level = 99;
145 static void
146 dbg(guint level, char* fmt, ...)
148 va_list ap;
150 if (level > debug_level) return;
151 va_start(ap,fmt);
152 vfprintf(stderr, fmt, ap);
153 va_end(ap);
155 #endif
157 static gint
158 tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
160 const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
161 const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
163 return (key1->session_id == key2->session_id);
166 /* calculate a hash key */
167 static guint
168 tcaphash_context_calchash(gconstpointer k)
170 const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
171 return key->session_id;
175 static gint
176 tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
178 const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
179 const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
181 if (key1->hashKey == key2->hashKey) {
183 if ( ( (key1->opc_hash == key2->opc_hash) &&
184 (key1->dpc_hash == key2->dpc_hash) &&
185 (key1->tid == key2->tid) )
187 ( (key1->opc_hash == key2->dpc_hash) &&
188 (key1->dpc_hash == key2->opc_hash) &&
189 (key1->tid == key2->tid) )
191 return TRUE;
193 return FALSE;
196 /* calculate a hash key */
197 static guint
198 tcaphash_begin_calchash(gconstpointer k)
200 const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
201 guint hashkey;
202 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
203 hashkey = key->tid;
204 return hashkey;
207 static gint
208 tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
210 const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
211 const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
213 if (key1->hashKey == key2->hashKey) {
215 if ( (key1->opc_hash == key2->opc_hash) &&
216 (key1->dpc_hash == key2->dpc_hash) &&
217 (key1->src_tid == key2->src_tid) &&
218 (key1->dst_tid == key2->dst_tid) ) {
219 return TRUE;
221 else if ( (key1->opc_hash == key2->dpc_hash) &&
222 (key1->dpc_hash == key2->opc_hash) &&
223 (key1->src_tid == key2->dst_tid) &&
224 (key1->dst_tid == key2->src_tid) ) {
225 return TRUE;
228 return FALSE;
231 /* calculate a hash key */
232 static guint
233 tcaphash_cont_calchash(gconstpointer k)
235 const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
236 guint hashkey;
237 hashkey = key->src_tid + key->dst_tid;
238 return hashkey;
242 static gint
243 tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
245 const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
246 const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
248 if (key1->hashKey == key2->hashKey) {
249 if ( ( (key1->opc_hash == key2->opc_hash) &&
250 (key1->dpc_hash == key2->dpc_hash) &&
251 (key1->tid == key2->tid) )
253 ( (key1->opc_hash == key2->dpc_hash) &&
254 (key1->dpc_hash == key2->opc_hash) &&
255 (key1->tid == key2->tid) ) )
256 return TRUE;
258 return FALSE;
261 /* calculate a hash key */
262 static guint
263 tcaphash_end_calchash(gconstpointer k)
265 const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
266 guint hashkey;
267 hashkey = key->tid;
268 return hashkey;
271 static gint
272 tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
274 const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
275 const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
277 if (key1->hashKey == key2->hashKey) {
279 if ( ( (key1->opc_hash == key2->opc_hash) &&
280 (key1->dpc_hash == key2->dpc_hash) &&
281 (key1->tid == key2->tid) )
283 ( (key1->opc_hash == key2->dpc_hash) &&
284 (key1->dpc_hash == key2->opc_hash) &&
285 (key1->tid == key2->tid) )
287 return TRUE;
289 return FALSE;
292 /* calculate a hash key */
293 static guint
294 tcaphash_ansi_calchash(gconstpointer k)
296 const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
297 guint hashkey;
298 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
299 hashkey = key->tid;
300 return hashkey;
304 * Update a record with the data of the Request
306 static void
307 update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
308 packet_info *pinfo)
310 p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
311 p_tcaphash_begincall->context->last_frame = 0;
312 p_tcaphash_begincall->context->responded = FALSE;
313 p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
317 * Append a new dialogue, using the same Key, to the chained list
318 * The time is stored too
320 static struct tcaphash_begincall_t *
321 append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
322 struct tcaphash_context_t *p_tcaphash_context,
323 packet_info *pinfo)
325 struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
327 /* Append the transaction to the list, when the same key is found
328 This should append when the tcap-transaction Id is reused */
330 #ifdef MEM_TCAPSRT
331 p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
332 #else
333 p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
334 #endif
335 p_new_tcaphash_begincall->context=p_tcaphash_context;
336 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
337 p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
338 p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
339 p_new_tcaphash_begincall->next_begincall=NULL;
340 p_new_tcaphash_begincall->previous_begincall=prev_begincall;
341 p_new_tcaphash_begincall->father=FALSE;
343 #ifdef DEBUG_TCAPSRT
344 dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
345 #endif
346 /* Insert in the chained list */
347 prev_begincall->next_begincall = p_new_tcaphash_begincall;
348 if (prev_begincall->context->last_frame == 0) {
349 #ifdef DEBUG_TCAPSRT
350 dbg(10,"last ");
351 #endif
352 prev_begincall->context->last_frame = pinfo->fd->num-1;
354 return p_new_tcaphash_begincall;
358 * Update a record with the data of the Request
360 static void
361 update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
362 packet_info *pinfo)
364 p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
365 p_tcaphash_ansicall->context->last_frame = 0;
366 p_tcaphash_ansicall->context->responded = FALSE;
367 p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
371 * Append a new dialogue, using the same Key, to the chained list
372 * The time is stored too
374 static struct tcaphash_ansicall_t *
375 append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
376 struct tcaphash_context_t *p_tcaphash_context,
377 packet_info *pinfo)
379 struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
381 /* Append the transaction to the list, when the same key is found
382 This should append when the tcap-transaction Id is reused */
384 #ifdef MEM_TCAPSRT
385 p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
386 #else
387 p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
388 #endif
389 p_new_tcaphash_ansicall->context=p_tcaphash_context;
390 p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
391 p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
392 p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
393 p_new_tcaphash_ansicall->next_ansicall=NULL;
394 p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
395 p_new_tcaphash_ansicall->father=FALSE;
397 #ifdef DEBUG_TCAPSRT
398 dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
399 #endif
400 /* Insert in the chained list */
401 prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
402 if (prev_ansicall->context->last_frame == 0) {
403 #ifdef DEBUG_TCAPSRT
404 dbg(10,"last ");
405 #endif
406 prev_ansicall->context->last_frame = pinfo->fd->num-1;
408 return p_new_tcaphash_ansicall;
412 static struct tcaphash_contcall_t *
413 append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
414 struct tcaphash_context_t *p_tcaphash_context)
416 struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
418 /* Append the transaction to the list, when the same key is found
419 This should append when the tcap-transaction Id is reused */
421 #ifdef MEM_TCAPSRT
422 p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
423 #else
424 p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
425 #endif
426 p_new_tcaphash_contcall->context=p_tcaphash_context;
427 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
428 p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
429 p_new_tcaphash_contcall->next_contcall=NULL;
430 p_new_tcaphash_contcall->previous_contcall=prev_contcall;
431 p_new_tcaphash_contcall->father=FALSE;
433 #ifdef DEBUG_TCAPSRT
434 dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
435 #endif
436 /* Insert in the chained list */
437 prev_contcall->next_contcall = p_new_tcaphash_contcall;
438 return p_new_tcaphash_contcall;
442 static struct tcaphash_endcall_t *
443 append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
444 struct tcaphash_context_t *p_tcaphash_context)
446 struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
448 /* Append the transaction to the list, when the same key is found
449 This should append when the tcap-transaction Id is reused */
451 #ifdef MEM_TCAPSRT
452 p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
453 #else
454 p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
455 #endif
456 p_new_tcaphash_endcall->context=p_tcaphash_context;
457 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
458 p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
459 p_new_tcaphash_endcall->next_endcall=NULL;
460 p_new_tcaphash_endcall->previous_endcall=prev_endcall;
461 p_new_tcaphash_endcall->father=FALSE;
463 #ifdef DEBUG_TCAPSRT
464 dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
465 #endif
466 /* Insert in the chained list */
467 prev_endcall->next_endcall = p_new_tcaphash_endcall;
468 return p_new_tcaphash_endcall;
473 * Find the dialog by Key and Time
475 static struct tcaphash_begincall_t *
476 find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
477 packet_info *pinfo, gboolean isBegin)
479 struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
480 p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
482 if(p_tcaphash_begincall) {
483 do {
484 if ( p_tcaphash_begincall->context ) {
485 if ( ( isBegin &&
486 pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
488 ( !isBegin &&
489 pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
490 ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
493 /* We have a dialogue, with this key, opened before this request */
494 #ifdef DEBUG_TCAPSRT
495 dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
496 #endif
497 return p_tcaphash_begincall;
499 #ifdef DEBUG_TCAPSRT
500 dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
501 #endif
503 /* Break when list end is reached */
504 if(p_tcaphash_begincall->next_begincall == NULL) {
505 #ifdef DEBUG_TCAPSRT
506 dbg(23,"End of Blist ");
507 #endif
508 break;
510 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
511 } while (p_tcaphash_begincall != NULL) ;
512 } else {
513 #ifdef DEBUG_TCAPSRT
514 dbg(23,"Not in Bhash ");
515 #endif
517 return NULL;
522 static struct tcaphash_contcall_t *
523 find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
524 packet_info *pinfo)
526 struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
527 p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
529 if(p_tcaphash_contcall) {
530 do {
531 if ( p_tcaphash_contcall->context ) {
532 if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
533 (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
534 /* We have a dialogue, with this key, opened before this request */
535 #ifdef DEBUG_TCAPSRT
536 dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
537 #endif
538 return p_tcaphash_contcall;
540 #ifdef DEBUG_TCAPSRT
541 dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
542 #endif
544 /* Break when list end is reached */
545 if(p_tcaphash_contcall->next_contcall == NULL) {
546 #ifdef DEBUG_TCAPSRT
547 dbg(23,"End of Clist ");
548 #endif
549 break;
551 p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
552 } while (p_tcaphash_contcall != NULL) ;
553 } else {
554 #ifdef DEBUG_TCAPSRT
555 dbg(23,"Not in Chash ");
556 #endif
558 return NULL;
561 static struct tcaphash_endcall_t *
562 find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
563 packet_info *pinfo, gboolean isEnd)
565 struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
566 p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
568 if(p_tcaphash_endcall) {
569 do {
570 if ( p_tcaphash_endcall->context ) {
571 if ( ( isEnd &&
572 (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
575 ( !isEnd &&
576 pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
577 (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
580 /* We have a dialogue, with this key, opened before this request */
581 #ifdef DEBUG_TCAPSRT
582 dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
583 #endif
584 return p_tcaphash_endcall;
586 #ifdef DEBUG_TCAPSRT
587 dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
588 #endif
590 /* Break when list end is reached */
591 if(p_tcaphash_endcall->next_endcall == NULL) {
592 #ifdef DEBUG_TCAPSRT
593 dbg(23,"End of Elist ");
594 #endif
595 break;
597 p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
598 } while (p_tcaphash_endcall != NULL) ;
599 } else {
600 #ifdef DEBUG_TCAPSRT
601 dbg(23,"Not in Ehash ");
602 #endif
604 return NULL;
608 * New record to create, to identify a new transaction
610 static struct tcaphash_context_t *
611 new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
612 packet_info *pinfo)
614 struct tcaphash_context_key_t *p_new_tcaphash_context_key;
615 struct tcaphash_context_t *p_new_tcaphash_context = NULL;
617 /* Register the transaction in the hash table
618 with the tcap transaction Id as Main Key
619 Once created, this entry will be updated later */
621 #ifdef MEM_TCAPSRT
622 p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
623 #else
624 p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
625 #endif
626 p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
628 #ifdef MEM_TCAPSRT
629 p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
630 #else
631 p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
632 #endif
633 p_new_tcaphash_context->key = p_new_tcaphash_context_key;
634 p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
635 p_new_tcaphash_context->first_frame = pinfo->fd->num;
636 #ifdef DEBUG_TCAPSRT
637 dbg(10,"S%d ", p_new_tcaphash_context->session_id);
638 #endif
639 /* store it */
640 g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
641 return p_new_tcaphash_context;
645 * New record to create, to identify a new transaction
647 static struct tcaphash_begincall_t *
648 new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
649 struct tcaphash_context_t *p_tcaphash_context)
651 struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
652 struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
654 /* Register the transaction in the hash table
655 with the tcap transaction Id as Main Key
656 Once created, this entry will be updated later */
658 #ifdef MEM_TCAPSRT
659 p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
660 #else
661 p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
662 #endif
663 p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
664 p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
665 p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
666 p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
668 #ifdef MEM_TCAPSRT
669 p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
670 #else
671 p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
672 #endif
673 p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
674 p_new_tcaphash_begincall->context=p_tcaphash_context;
675 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
676 p_new_tcaphash_begincall->father=TRUE;
677 p_new_tcaphash_begincall->next_begincall=NULL;
678 p_new_tcaphash_begincall->previous_begincall=NULL;
680 #ifdef DEBUG_TCAPSRT
681 dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
682 #endif
683 /* store it */
684 g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
685 return p_new_tcaphash_begincall;
691 * New record to create, to identify a new transaction
693 static struct tcaphash_contcall_t *
694 new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
695 struct tcaphash_context_t *p_tcaphash_context)
697 struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
698 struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
700 /* Register the transaction in the hash table
701 with the tcap transaction Id as Main Key
702 Once created, this entry will be updated later */
704 #ifdef MEM_TCAPSRT
705 p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
706 #else
707 p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
708 #endif
709 p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
710 p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
711 p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
712 p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
713 p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
715 #ifdef MEM_TCAPSRT
716 p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
717 #else
718 p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
719 #endif
720 p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
721 p_new_tcaphash_contcall->context=p_tcaphash_context;
722 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
723 p_new_tcaphash_contcall->father=TRUE;
724 p_new_tcaphash_contcall->next_contcall=NULL;
725 p_new_tcaphash_contcall->previous_contcall=NULL;
727 #ifdef DEBUG_TCAPSRT
728 dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
729 #endif
730 /* store it */
731 g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
732 return p_new_tcaphash_contcall;
737 * New record to create, to identify a new transaction
739 static struct tcaphash_endcall_t *
740 new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
741 struct tcaphash_context_t *p_tcaphash_context)
743 struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
744 struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
746 /* Register the transaction in the hash table
747 with the tcap transaction Id as Main Key
748 Once created, this entry will be updated later */
750 #ifdef MEM_TCAPSRT
751 p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
752 #else
753 p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
754 #endif
755 p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
756 p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
757 p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
758 p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
760 #ifdef MEM_TCAPSRT
761 p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
762 #else
763 p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
764 #endif
765 p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
766 p_new_tcaphash_endcall->context=p_tcaphash_context;
767 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
768 p_new_tcaphash_endcall->father=TRUE;
769 p_new_tcaphash_endcall->next_endcall=NULL;
770 p_new_tcaphash_endcall->previous_endcall=NULL;
772 #ifdef DEBUG_TCAPSRT
773 dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
774 #endif
775 /* store it */
776 g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
777 return p_new_tcaphash_endcall;
780 * New record to create, to identify a new transaction
782 static struct tcaphash_ansicall_t *
783 new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
784 struct tcaphash_context_t *p_tcaphash_context)
786 struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
787 struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
789 /* Register the transaction in the hash table
790 with the tcap transaction Id as Main Key
791 Once created, this entry will be updated later */
793 #ifdef MEM_TCAPSRT
794 p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
795 #else
796 p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
797 #endif
798 p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
799 p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
800 p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
801 p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
803 #ifdef MEM_TCAPSRT
804 p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
805 #else
806 p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
807 #endif
808 p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
809 p_new_tcaphash_ansicall->context=p_tcaphash_context;
810 p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
811 p_new_tcaphash_ansicall->father=TRUE;
812 p_new_tcaphash_ansicall->next_ansicall=NULL;
813 p_new_tcaphash_ansicall->previous_ansicall=NULL;
815 #ifdef DEBUG_TCAPSRT
816 dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
817 #endif
818 /* store it */
819 g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
820 return p_new_tcaphash_ansicall;
823 static struct tcaphash_contcall_t *
824 create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
825 struct tcaphash_context_t *p_tcaphash_context)
827 struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
828 struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
830 p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
831 g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
833 if (p_tcaphash_contcall1) {
834 /* Walk through list of transaction with identical keys */
835 /* go the the end to insert new record */
836 do {
837 if (!p_tcaphash_contcall1->next_contcall) {
838 p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
839 p_tcaphash_context);
840 break;
842 p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
843 } while (p_tcaphash_contcall1 != NULL );
844 } else {
845 p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
846 p_tcaphash_context);
848 return p_tcaphash_contcall;
852 static struct tcaphash_endcall_t *
853 create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
854 struct tcaphash_context_t *p_tcaphash_context)
856 struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
857 struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
859 p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
860 g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
862 if (p_tcaphash_endcall1) {
863 /* Walk through list of transaction with identical keys */
864 /* go the the end to insert new record */
865 do {
866 if (!p_tcaphash_endcall1->next_endcall) {
867 p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
868 p_tcaphash_context);
869 break;
871 p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
872 } while (p_tcaphash_endcall1 != NULL );
873 } else {
874 p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
875 p_tcaphash_context);
877 return p_tcaphash_endcall;
882 * Routine called when the TAP is initialized.
883 * so hash table are (re)created
885 void
886 tcapsrt_init_routine(void)
889 /* free hash-table for SRT */
890 if (tcaphash_context != NULL) {
891 #ifdef DEBUG_TCAPSRT
892 dbg(16,"Destroy hash_context \n");
893 #endif
894 g_hash_table_destroy(tcaphash_context);
897 if (tcaphash_begin != NULL) {
898 #ifdef DEBUG_TCAPSRT
899 dbg(16,"Destroy hash_begin \n");
900 #endif
901 g_hash_table_destroy(tcaphash_begin);
904 if (tcaphash_cont != NULL) {
905 #ifdef DEBUG_TCAPSRT
906 dbg(16,"Destroy hash_cont \n");
907 #endif
908 g_hash_table_destroy(tcaphash_cont);
911 if (tcaphash_end != NULL) {
912 #ifdef DEBUG_TCAPSRT
913 dbg(16,"Destroy hash_end \n");
914 #endif
915 g_hash_table_destroy(tcaphash_end);
918 if (tcaphash_ansi != NULL) {
919 #ifdef DEBUG_TCAPSRT
920 dbg(16,"Destroy hash_ansi \n");
921 #endif
922 g_hash_table_destroy(tcaphash_ansi);
925 #ifdef DEBUG_TCAPSRT
926 dbg(16,"Create hash \n");
927 #endif
928 /* create new hash-tables for SRT */
929 tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
930 tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
931 tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
932 tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
933 tcaphash_ansi = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
935 /* Reset the session counter */
936 tcapsrt_global_SessionId=1;
938 /* Display of SRT only if Persistent Stat */
939 gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
943 * Service Response Time analyze
944 * Called just after dissector call
945 * Associate a TCAP context to a tcap session and display session related infomations
946 * like the first frame, the last, the session duration,
947 * and a uniq session identifier for the filtering
949 * For ETSI tcap, the TCAP context can be reached through three keys
950 * - a key (BEGIN) identifying the session according to the tcap source identifier
951 * - a key (CONT) identifying the established session (src_id and dst_id)
952 * - a key (END) identifying the session according to the tcap destination identifier
954 * For ANSI tcap, the TCAP context is reached through a uniq key
955 * - a key (ANSI) identifying the session according to the tcap identifier
957 struct tcaphash_context_t *
958 tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
959 struct tcapsrt_info_t *p_tcapsrt_info)
961 struct tcaphash_context_t *tcap_context=NULL;
963 /* if this packet isn't loaded because of a read filter, don't output anything */
964 if(pinfo == NULL || pinfo->fd->num == 0) {
965 return NULL;
968 switch (p_tcapsrt_info->ope) {
970 case TC_BEGIN:
971 #ifdef DEBUG_TCAPSRT
972 dbg(1,"\nTC_BEGIN ");
973 #endif
974 tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
975 break;
977 case TC_CONT:
978 #ifdef DEBUG_TCAPSRT
979 dbg(1,"\nTC_CONT ");
980 #endif
981 tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
982 break;
984 case TC_ABORT:
985 #ifdef DEBUG_TCAPSRT
986 dbg(1,"\nTC_ABORT ");
987 #endif
988 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
989 break;
991 case TC_END:
992 #ifdef DEBUG_TCAPSRT
993 dbg(1,"\nTC_END ");
994 #endif
995 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
996 break;
998 case TC_ANSI_ALL:
999 case TC_ANSI_ABORT:
1000 #ifdef DEBUG_TCAPSRT
1001 dbg(1,"\nTC_ANSI ");
1002 #endif
1003 tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
1004 break;
1006 default:
1007 #ifdef DEBUG_TCAPSRT
1008 dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
1009 #endif
1010 break;
1011 } /* switch tcapop */
1012 #ifdef DEBUG_TCAPSRT
1013 if (tcap_context)
1014 dbg(1,"session %d ", tcap_context->session_id);
1015 #endif
1016 return tcap_context;
1021 * Create the record identifiying the TCAP transaction
1022 * When the identifier for the transaction is reused, check
1023 * the following criteria before to append a new record:
1024 * - a timeout corresponding to a message retransmission is detected,
1025 * - a message hast been lost
1026 * - or the previous transaction has been be closed
1028 static struct tcaphash_context_t *
1029 tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1030 struct tcapsrt_info_t *p_tcapsrt_info)
1032 struct tcaphash_context_t *p_tcaphash_context=NULL;
1033 struct tcaphash_context_key_t tcaphash_context_key;
1034 struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
1035 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1036 proto_item *pi;
1037 proto_item *stat_item=NULL;
1038 proto_tree *stat_tree=NULL;
1040 /* prepare the key data */
1041 tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
1042 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1044 /* We have MTP3 PCs (so we can safely do this cast) */
1045 tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1046 tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1047 } else {
1048 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1049 tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1050 tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1052 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1054 /* look up the request */
1055 #ifdef DEBUG_TCAPSRT
1056 dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
1057 dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
1058 dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1059 dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
1060 #endif
1062 p_tcaphash_begincall = (struct tcaphash_begincall_t *)
1063 g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
1065 if (p_tcaphash_begincall) {
1066 /* Walk through list of transaction with identical keys */
1067 do {
1068 /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
1069 if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
1070 /* We have seen this request before -> do nothing */
1071 #ifdef DEBUG_TCAPSRT
1072 dbg(22,"Already seen ");
1073 #endif
1074 p_tcaphash_context=p_tcaphash_begincall->context;
1075 break;
1077 /* If the last record for Tcap transaction with identifier has not been reached */
1078 if (!p_tcaphash_begincall->next_begincall) {
1079 /* check if we have to create a new record or not */
1080 /* if last request has been responded (response number is known)
1081 and this request appears after last response (has bigger frame number)
1082 and last request occurred after the timeout for repetition,
1084 if last request hasn't been responded (so number unknown)
1085 and this request appears after last request (has bigger frame number)
1086 and this request occurred after the timeout for message lost */
1087 if ( ( p_tcaphash_begincall->context->last_frame != 0
1088 && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
1089 && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
1090 ) ||
1091 ( p_tcaphash_begincall->context->last_frame == 0
1092 && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
1093 && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
1097 /* we decide that we have a new request */
1098 /* Append new record to the list */
1099 #ifdef DEBUG_TCAPSRT
1100 dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
1101 dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
1102 #endif
1103 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1104 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1106 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
1107 p_tcaphash_context,
1108 pinfo);
1109 #ifdef DEBUG_TCAPSRT
1110 dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
1111 #endif
1112 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
1113 } else { /* timeout or message lost */
1115 /* If the Tid is reused for a closed Transaction */
1116 /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
1117 /* (this is the case, for pre-arranged END, the transaction is marked as closed */
1118 /* by the upper layer, thank to a callback method close) */
1119 if ( p_tcaphash_begincall->context->closed) {
1120 #ifdef DEBUG_TCAPSRT
1121 dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
1122 dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
1123 #endif
1124 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1125 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1126 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
1127 p_tcaphash_context,
1128 pinfo);
1130 #ifdef DEBUG_TCAPSRT
1131 dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
1132 #endif
1133 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
1135 } else {
1136 /* the TCAP session is not closed, so, either messages have been lost */
1137 /* or it's a duplicate request. Mark it as such. */
1138 #ifdef DEBUG_TCAPSRT
1139 dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
1140 #endif
1141 p_tcaphash_context=p_tcaphash_begincall->context;
1142 if (gtcap_DisplaySRT && tree) {
1143 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1144 PROTO_ITEM_SET_GENERATED(stat_item);
1145 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1146 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
1147 p_tcaphash_context->first_frame,
1148 "Duplicate with session %u in frame %u",
1149 p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
1150 PROTO_ITEM_SET_GENERATED(pi);
1152 return p_tcaphash_context;
1153 } /* Previous session closed */
1154 } /* test with Timeout or message Lost */
1155 break;
1156 } /* Next call is NULL */
1157 /* Repeat the tests for the next record with the same transaction identifier */
1158 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
1159 } while (p_tcaphash_begincall != NULL );
1161 * End of analyze for the list be TC_BEGIN with same transaction ID
1163 } else { /* p_tcaphash_begincall has not been found */
1165 * Create a new TCAP context
1167 #ifdef DEBUG_TCAPSRT
1168 dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
1169 #endif
1171 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1172 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1173 p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
1175 #ifdef DEBUG_TCAPSRT
1176 dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
1177 dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1178 #endif
1179 update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
1182 /* display tcap session, if available */
1183 if ( gtcap_DisplaySRT && tree &&
1184 p_tcaphash_context &&
1185 p_tcaphash_context->session_id) {
1186 stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
1187 PROTO_ITEM_SET_GENERATED(stat_item);
1188 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1189 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1190 PROTO_ITEM_SET_GENERATED(pi);
1192 /* add link to response frame, if available */
1193 /* p_tcaphash_begincall->context->last_frame) */
1194 if( p_tcaphash_context->last_frame != 0 ){
1195 #ifdef DEBUG_TCAPSRT
1196 dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
1197 #endif
1198 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1199 p_tcaphash_context->last_frame,
1200 "End of session in frame %u",
1201 p_tcaphash_context->last_frame);
1202 PROTO_ITEM_SET_GENERATED(pi);
1205 return p_tcaphash_context;
1210 * Try to find a TCAP session according to the source and destination
1211 * Identifier given in the TC_CONT
1212 * If nothing is found, it is probably a session in opening state, so try to find
1213 * a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
1214 * Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
1215 * and display the available info for the TCAP context
1217 static struct tcaphash_context_t *
1218 tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1219 struct tcapsrt_info_t *p_tcapsrt_info)
1221 struct tcaphash_context_t *p_tcaphash_context=NULL;
1222 struct tcaphash_contcall_t *p_tcaphash_contcall;
1223 struct tcaphash_cont_info_key_t tcaphash_cont_key;
1224 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1225 struct tcaphash_begincall_t *p_tcaphash_begincall;
1226 struct tcaphash_end_info_key_t tcaphash_end_key;
1227 proto_item *pi;
1228 proto_item *stat_item=NULL;
1229 proto_tree *stat_tree=NULL;
1231 #ifdef DEBUG_TCAPSRT
1232 dbg(10,"\n Hcont #%u ", pinfo->fd->num);
1233 #endif
1235 /* look only for matching request, if matching conversation is available. */
1236 tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
1237 tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
1238 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1240 /* We have MTP3 PCs (so we can safely do this cast) */
1241 tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1242 tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1243 } else {
1244 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1245 tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1246 tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1248 tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1250 #ifdef DEBUG_TCAPSRT
1251 dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1252 dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1253 dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1254 #endif
1255 p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1256 if(p_tcaphash_contcall) {
1257 #ifdef DEBUG_TCAPSRT
1258 dbg(12,"CFound ");
1259 #endif
1260 p_tcaphash_context=p_tcaphash_contcall->context;
1261 } else { /* cont not found */
1262 #ifdef DEBUG_TCAPSRT
1263 dbg(12,"CnotFound ");
1264 #endif
1265 /* Find the TCAP transaction according to the TC_BEGIN */
1266 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1267 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1269 /* We have MTP3 PCs (so we can safely do this cast) */
1270 tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1271 tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1272 } else {
1273 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1274 tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1275 tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1277 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1279 #ifdef DEBUG_TCAPSRT
1280 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1281 dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1282 dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
1283 #endif
1284 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
1285 if(!p_tcaphash_begincall){
1286 /* Do we have a continue from the same source? */
1287 tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
1288 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1289 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1291 if(p_tcaphash_begincall &&
1292 !p_tcaphash_begincall->context->contcall ) {
1293 #ifdef DEBUG_TCAPSRT
1294 dbg(12,"BFound \n");
1295 #endif
1296 p_tcaphash_context=p_tcaphash_begincall->context;
1297 p_tcaphash_context->responded=TRUE;
1299 #ifdef DEBUG_TCAPSRT
1300 dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1301 dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
1302 #endif
1303 create_tcaphash_cont(&tcaphash_cont_key,
1304 p_tcaphash_begincall->context);
1306 tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
1307 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1309 /* We have MTP3 PCs (so we can safely do this cast) */
1310 tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1311 tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1312 } else {
1313 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1314 tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1315 tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1317 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1319 #ifdef DEBUG_TCAPSRT
1320 dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1321 dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1322 #endif
1323 create_tcaphash_end(&tcaphash_end_key,
1324 p_tcaphash_begincall->context);
1326 } else { /* Begin not found */
1327 #ifdef DEBUG_TCAPSRT
1328 dbg(12,"BnotFound ");
1329 #endif
1330 } /* begin found */
1331 } /* cont found */
1332 /* display tcap session, if available */
1333 if (gtcap_DisplaySRT && tree &&
1334 p_tcaphash_context &&
1335 p_tcaphash_context->session_id) {
1336 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1337 PROTO_ITEM_SET_GENERATED(stat_item);
1338 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1339 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1340 PROTO_ITEM_SET_GENERATED(pi);
1343 return p_tcaphash_context;
1347 * Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
1348 * If nothing is found,
1349 * - either it is a session in opening state,
1350 * - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
1351 * so try to find a tcap session registered with a TC_BEGIN "key",
1352 * matching the destination Id of the TC_END
1353 * Then associate the TC_CONT "key" to the TCAP context
1354 * and display the available info for the TCAP context
1357 static struct tcaphash_context_t *
1358 tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1359 struct tcapsrt_info_t *p_tcapsrt_info)
1361 struct tcaphash_context_t *p_tcaphash_context=NULL;
1363 struct tcaphash_end_info_key_t tcaphash_end_key;
1364 struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
1366 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1367 struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
1368 proto_item *pi;
1369 nstime_t delta;
1370 proto_item *stat_item=NULL;
1371 proto_tree *stat_tree=NULL;
1373 #ifdef DEBUG_TCAPSRT
1374 dbg(10,"\n Hend #%u ", pinfo->fd->num);
1375 #endif
1376 /* look only for matching request, if matching conversation is available. */
1377 tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1378 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1380 /* We have MTP3 PCs (so we can safely do this cast) */
1381 tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1382 tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1383 } else {
1384 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1385 tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1386 tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1388 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1390 #ifdef DEBUG_TCAPSRT
1391 dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1392 dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1393 dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1394 #endif
1395 p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
1397 if(!p_tcaphash_endcall) {
1398 #ifdef DEBUG_TCAPSRT
1399 dbg(12,"EnotFound ");
1400 #endif
1401 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1402 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1404 /* We have MTP3 PCs (so we can safely do this cast) */
1405 tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1406 tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1407 } else {
1408 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1409 tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1410 tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1412 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1414 #ifdef DEBUG_TCAPSRT
1415 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1416 dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1417 dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1418 #endif
1419 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1420 if(!p_tcaphash_begincall) {
1421 #ifdef DEBUG_TCAPSRT
1422 dbg(12,"BnotFound ");
1423 #endif
1426 if (p_tcaphash_endcall) {
1427 /* Use the TC_BEGIN Destination reference */
1428 p_tcaphash_context=p_tcaphash_endcall->context;
1429 } else if (p_tcaphash_begincall) {
1430 /* Use the TC_BEGIN Source reference */
1431 p_tcaphash_context=p_tcaphash_begincall->context;
1434 if (p_tcaphash_context) {
1436 #ifdef DEBUG_TCAPSRT
1437 dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1438 #endif
1439 if (gtcap_DisplaySRT && tree) {
1440 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1441 PROTO_ITEM_SET_GENERATED(stat_item);
1442 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1444 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1445 PROTO_ITEM_SET_GENERATED(pi);
1448 #ifdef DEBUG_TCAPSRT
1449 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1450 #endif
1451 /* Indicate the frame to which this is a reply. */
1452 if (gtcap_DisplaySRT && stat_tree) {
1453 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1454 p_tcaphash_context->first_frame,
1455 "Begin of session in frame %u",
1456 p_tcaphash_context->first_frame);
1457 PROTO_ITEM_SET_GENERATED(pi);
1458 /* Calculate Service Response Time */
1459 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1461 /* display Service Response Time and make it filterable */
1462 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1463 PROTO_ITEM_SET_GENERATED(pi);
1465 /* Close the context and remove it (if needed) */
1466 tcapsrt_close(p_tcaphash_context,pinfo);
1468 } else {/* context present */
1469 #ifdef DEBUG_TCAPSRT
1470 dbg(12,"Context notFound ");
1471 #endif
1473 return p_tcaphash_context;
1477 * ANSI PART
1478 * Create the record identifiying the TCAP transaction
1479 * When the identifier for the transaction is reused, check
1480 * the following criteria before to append a new record:
1481 * - a timeout corresponding to a message retransmission is detected,
1482 * - a message hast been lost
1483 * - or the previous transaction has been be closed
1485 static struct tcaphash_context_t *
1486 tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1487 struct tcapsrt_info_t *p_tcapsrt_info)
1489 struct tcaphash_context_t *p_tcaphash_context=NULL;
1490 struct tcaphash_context_key_t tcaphash_context_key;
1491 struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
1492 struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
1493 proto_item *pi;
1494 nstime_t delta;
1495 gboolean isResponse=FALSE;
1496 proto_tree * stat_tree=NULL;
1497 proto_item * stat_item=NULL;
1499 /* prepare the key data */
1500 tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
1501 if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1503 /* We have MTP3 PCs (so we can safely do this cast) */
1504 tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1505 tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1506 } else {
1507 /* Don't have MTP3 PCs (maybe we're over SUA?) */
1508 tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1509 tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1511 tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
1513 /* look up the request */
1514 #ifdef DEBUG_TCAPSRT
1515 dbg(10,"\n Hansi #%u ", pinfo->fd->num);
1516 dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
1517 dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1518 dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
1519 #endif
1520 p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
1521 g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
1523 if (p_tcaphash_ansicall) {
1524 /* Walk through list of transaction with identical keys */
1525 do {
1526 /* Check if the request with this reqSeqNum has been seen */
1527 if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
1528 /* We have seen this request before -> do nothing */
1529 #ifdef DEBUG_TCAPSRT
1530 dbg(22,"Request already seen ");
1531 #endif
1532 isResponse=FALSE;
1533 p_tcaphash_context=p_tcaphash_ansicall->context;
1534 break;
1537 /* Check if the reponse with this reqSeqNum has been seen */
1538 if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
1539 /* We have seen this response before -> do nothing */
1540 #ifdef DEBUG_TCAPSRT
1541 dbg(22,"Response already seen ");
1542 #endif
1543 isResponse=TRUE;
1544 p_tcaphash_context=p_tcaphash_ansicall->context;
1545 break;
1548 /* Check for the first Request without Response
1549 received before this frame */
1550 if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
1551 p_tcaphash_ansicall->context->last_frame==0 ) {
1552 /* Take it, and update the context */
1554 #ifdef DEBUG_TCAPSRT
1555 dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1556 #endif
1557 p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
1558 p_tcaphash_ansicall->context->responded = TRUE;
1559 p_tcaphash_ansicall->context->closed = TRUE;
1560 p_tcaphash_context=p_tcaphash_ansicall->context;
1561 isResponse=TRUE;
1563 if (gtcap_DisplaySRT && tree) {
1564 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1565 PROTO_ITEM_SET_GENERATED(stat_item);
1566 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1568 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1569 PROTO_ITEM_SET_GENERATED(pi);
1571 #ifdef DEBUG_TCAPSRT
1572 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1573 #endif
1574 /* Indicate the frame to which this is a reply. */
1575 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1576 p_tcaphash_context->first_frame,
1577 "Begin of session in frame %u",
1578 p_tcaphash_context->first_frame);
1579 PROTO_ITEM_SET_GENERATED(pi);
1580 /* Calculate Service Response Time */
1581 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1583 /* display Service Response Time and make it filterable */
1584 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1585 PROTO_ITEM_SET_GENERATED(pi);
1587 break;
1588 } /* Lastframe=0, so take it */
1591 /* If the last record for Tcap transaction with identifier has been reached */
1592 if (!p_tcaphash_ansicall->next_ansicall) {
1593 /* check if we have to create a new record or not */
1594 /* if last request has been responded (response number in known)
1595 and this request appears after last response (has bigger frame number)
1596 and last request occurred after the timeout for repetition,
1598 if last request hasn't been responded (so number unknown)
1599 and this request appears after last request (has bigger frame number)
1600 and this request occurred after the timeout for message lost */
1601 if ( ( p_tcaphash_ansicall->context->last_frame != 0
1602 && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1603 && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
1604 ) ||
1605 ( p_tcaphash_ansicall->context->last_frame == 0
1606 && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1607 && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
1611 /* we decide that we have a new request */
1612 /* Append new record to the list */
1613 #ifdef DEBUG_TCAPSRT
1614 dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
1615 dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1616 #endif
1617 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1618 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1619 p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1620 p_tcaphash_context,
1621 pinfo);
1623 #ifdef DEBUG_TCAPSRT
1624 dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1625 #endif
1626 update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1627 p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1628 } else {
1630 /* If the Tid is reused for a closed Transaction */
1631 if ( p_tcaphash_ansicall->context->closed) {
1632 #ifdef DEBUG_TCAPSRT
1633 dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
1634 dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1635 #endif
1636 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1637 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1638 p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1639 p_tcaphash_context,
1640 pinfo);
1642 #ifdef DEBUG_TCAPSRT
1643 dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
1644 #endif
1645 update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1646 p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1648 } else {
1649 /* the Tid is reused for an opened Transaction */
1650 /* so, this is the reply to the request of our context */
1651 p_tcaphash_context=p_tcaphash_ansicall->context;
1652 #ifdef DEBUG_TCAPSRT
1653 dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1654 #endif
1656 if (gtcap_DisplaySRT && tree) {
1657 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1658 PROTO_ITEM_SET_GENERATED(stat_item);
1659 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1661 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1662 PROTO_ITEM_SET_GENERATED(pi);
1664 #ifdef DEBUG_TCAPSRT
1665 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1666 #endif
1667 /* Indicate the frame to which this is a reply. */
1668 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1669 p_tcaphash_context->first_frame,
1670 "Begin of session in frame %u",
1671 p_tcaphash_context->first_frame);
1672 PROTO_ITEM_SET_GENERATED(pi);
1673 /* Calculate Service Response Time */
1674 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1676 /* display Service Response Time and make it filterable */
1677 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1678 PROTO_ITEM_SET_GENERATED(pi);
1680 p_tcaphash_context=p_tcaphash_ansicall->context;
1681 } /* test with Timeout */
1682 } /* closed */
1683 break;
1684 } /* Next call is NULL */
1685 p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
1686 } while (p_tcaphash_ansicall != NULL );
1688 * New TCAP context
1690 } else { /* p_tcaphash_ansicall has not been found */
1691 #ifdef DEBUG_TCAPSRT
1692 dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
1693 #endif
1695 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1696 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1697 p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
1699 #ifdef DEBUG_TCAPSRT
1700 dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
1701 dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1702 #endif
1703 update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
1706 /* display tcap session, if available */
1707 if ( gtcap_DisplaySRT && tree &&
1708 p_tcaphash_context &&
1709 p_tcaphash_context->session_id) {
1710 stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1711 PROTO_ITEM_SET_GENERATED(stat_item);
1712 stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1713 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1714 PROTO_ITEM_SET_GENERATED(pi);
1718 /* add link to response frame, if available */
1719 if( gtcap_DisplaySRT && stat_tree &&
1720 p_tcaphash_ansicall->context->last_frame != 0){
1721 if (!isResponse) { /* Request */
1722 #ifdef DEBUG_TCAPSRT
1723 dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
1724 #endif
1725 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1726 p_tcaphash_ansicall->context->last_frame,
1727 "End of session in frame %u",
1728 p_tcaphash_ansicall->context->last_frame);
1729 PROTO_ITEM_SET_GENERATED(pi);
1730 } else { /* Response */
1731 #ifdef DEBUG_TCAPSRT
1732 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1733 #endif
1734 /* Indicate the frame to which this is a reply. */
1735 if (gtcap_DisplaySRT) {
1736 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1737 p_tcaphash_context->first_frame,
1738 "Begin of session in frame %u",
1739 p_tcaphash_context->first_frame);
1740 PROTO_ITEM_SET_GENERATED(pi);
1741 /* Calculate Service Response Time */
1742 nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1744 /* display Service Response Time and make it filterable */
1745 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1746 PROTO_ITEM_SET_GENERATED(pi);
1748 } /* Request or Response */
1750 return p_tcaphash_context;
1755 * Initialize the Message Info used by the main dissector
1756 * Data are linked to a TCAP transaction
1758 struct tcapsrt_info_t *
1759 tcapsrt_razinfo(void)
1761 struct tcapsrt_info_t *p_tcapsrt_info ;
1763 /* Global buffer for packet extraction */
1764 tcapsrt_global_current++;
1765 if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1766 tcapsrt_global_current=0;
1769 p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1770 memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
1772 return p_tcapsrt_info;
1775 void
1776 tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
1777 packet_info *pinfo)
1779 #ifdef DEBUG_TCAPSRT
1780 dbg(60,"Force close ");
1781 #endif
1782 if (p_tcaphash_context) {
1783 p_tcaphash_context->responded=TRUE;
1784 p_tcaphash_context->last_frame = pinfo->fd->num;
1785 p_tcaphash_context->end_time = pinfo->fd->abs_ts;
1786 p_tcaphash_context->closed=TRUE;
1788 /* If the endkey is present */
1789 if (p_tcaphash_context->endcall
1790 && !gtcap_PersistentSRT) {
1791 if (p_tcaphash_context->endcall->next_endcall) {
1792 if (p_tcaphash_context->endcall->previous_endcall ) {
1793 #ifdef DEBUG_TCAPSRT
1794 dbg(20,"deplace Ehash ");
1795 #endif
1796 p_tcaphash_context->endcall->previous_endcall->next_endcall
1797 = p_tcaphash_context->endcall->next_endcall;
1798 p_tcaphash_context->endcall->next_endcall->previous_endcall
1799 = p_tcaphash_context->endcall->previous_endcall;
1800 g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1801 #ifdef MEM_TCAPSRT
1802 g_free(p_tcaphash_context->endcall);
1803 #endif
1804 } else {
1805 /* cannot remove the father */
1806 #ifdef DEBUG_TCAPSRT
1807 dbg(20,"father Ehash ");
1808 #endif
1809 } /* no previous link, so father */
1810 } else if (!gtcap_PersistentSRT) {
1811 #ifdef DEBUG_TCAPSRT
1812 dbg(20,"remove Ehash ");
1813 #endif
1814 g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1815 #ifdef MEM_TCAPSRT
1816 g_free(p_tcaphash_context->endcall->endkey);
1817 g_free(p_tcaphash_context->endcall);
1818 #endif
1820 } /* endcall without chained string */
1821 } /* no endcall */
1824 /* If the contkey is present */
1825 if (p_tcaphash_context->contcall
1826 && !gtcap_PersistentSRT) {
1827 if (p_tcaphash_context->contcall->next_contcall) {
1828 if (p_tcaphash_context->contcall->previous_contcall ) {
1829 #ifdef DEBUG_TCAPSRT
1830 dbg(20,"deplace Chash ");
1831 #endif
1832 p_tcaphash_context->contcall->previous_contcall->next_contcall
1833 = p_tcaphash_context->contcall->next_contcall;
1834 p_tcaphash_context->contcall->next_contcall->previous_contcall
1835 = p_tcaphash_context->contcall->previous_contcall;
1836 g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1837 #ifdef MEM_TCAPSRT
1838 g_free(p_tcaphash_context->contcall);
1839 #endif
1840 } else {
1841 /* cannot remove the father */
1842 #ifdef DEBUG_TCAPSRT
1843 dbg(20,"father Chash ");
1844 #endif
1845 } /* no previous link, so father */
1846 } else if (!gtcap_PersistentSRT) {
1847 #ifdef DEBUG_TCAPSRT
1848 dbg(20,"remove Chash ");
1849 #endif
1850 g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1851 #ifdef MEM_TCAPSRT
1852 g_free(p_tcaphash_context->contcall->contkey);
1853 g_free(p_tcaphash_context->contcall);
1854 #endif
1855 } /* contcall without chained string */
1856 } /* no contcall */
1859 /* If the beginkey is present */
1860 if (p_tcaphash_context->begincall
1861 && !gtcap_PersistentSRT) {
1862 if (p_tcaphash_context->begincall->next_begincall) {
1863 if (p_tcaphash_context->begincall->previous_begincall ) {
1864 #ifdef DEBUG_TCAPSRT
1865 dbg(20,"deplace Bhash ");
1866 #endif
1867 p_tcaphash_context->begincall->previous_begincall->next_begincall
1868 = p_tcaphash_context->begincall->next_begincall;
1869 p_tcaphash_context->begincall->next_begincall->previous_begincall
1870 = p_tcaphash_context->begincall->previous_begincall;
1871 g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1872 #ifdef MEM_TCAPSRT
1873 g_free(p_tcaphash_context->begincall);
1874 #endif
1875 } else {
1876 /* cannot remove the father */
1877 #ifdef DEBUG_TCAPSRT
1878 dbg(20,"father Bhash ");
1879 #endif
1881 } else if (!gtcap_PersistentSRT) {
1882 #ifdef DEBUG_TCAPSRT
1883 dbg(20,"remove Bhash ");
1884 #endif
1885 g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1886 #ifdef MEM_TCAPSRT
1887 g_free(p_tcaphash_context->begincall->beginkey);
1888 g_free(p_tcaphash_context->begincall);
1889 #endif
1890 } /* begincall without chained string */
1891 } /* no begincall */
1893 /* If the ansikey is present */
1894 if (p_tcaphash_context->ansicall
1895 && !gtcap_PersistentSRT) {
1896 if (p_tcaphash_context->ansicall->next_ansicall) {
1897 if (p_tcaphash_context->ansicall->previous_ansicall ) {
1898 #ifdef DEBUG_TCAPSRT
1899 dbg(20,"deplace Ahash ");
1900 #endif
1901 p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
1902 = p_tcaphash_context->ansicall->next_ansicall;
1903 p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
1904 = p_tcaphash_context->ansicall->previous_ansicall;
1905 g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1906 #ifdef MEM_TCAPSRT
1907 g_free(p_tcaphash_context->ansicall);
1908 #endif
1909 } else {
1910 /* cannot remove the father */
1911 #ifdef DEBUG_TCAPSRT
1912 dbg(20,"father Ahash ");
1913 #endif
1915 } else if (!gtcap_PersistentSRT) {
1916 #ifdef DEBUG_TCAPSRT
1917 dbg(20,"remove Ahash ");
1918 #endif
1919 g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1920 #ifdef MEM_TCAPSRT
1921 g_free(p_tcaphash_context->ansicall->ansikey);
1922 g_free(p_tcaphash_context->ansicall);
1923 #endif
1924 } /* ansicall without chained string */
1925 } /* no ansicall */
1927 if (!gtcap_PersistentSRT) {
1928 #ifdef DEBUG_TCAPSRT
1929 dbg(20,"remove context ");
1930 #endif
1931 g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
1932 #ifdef MEM_TCAPSRT
1933 g_free(p_tcaphash_context->key);
1934 g_free(p_tcaphash_context);
1935 #endif
1937 } else { /* no context */
1938 #ifdef DEBUG_TCAPSRT
1939 dbg(20,"No context to remove ");
1940 #endif