From Jakub Zawadzki via bug #4289: (Fix for) Frame arrival times (pcap)
[obnox/wireshark/wip.git] / epan / tcap-persistentdata.c
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)
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * $Id$
12  *
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.
17  *
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.
22  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include <epan/emem.h>
37 #include <epan/packet.h>
38 #include <epan/asn1.h>
39 #include <epan/tcap-persistentdata.h>
40 #include <epan/dissectors/packet-tcap.h>
41 #include <epan/dissectors/packet-mtp3.h>
42
43 static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
44 static guint tcaphash_context_calchash(gconstpointer k);
45 static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
46 static guint tcaphash_begin_calchash(gconstpointer k);
47 static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
48 static guint tcaphash_cont_calchash(gconstpointer k);
49 static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
50 static guint tcaphash_end_calchash(gconstpointer k);
51 static gint tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2);
52 static guint tcaphash_ansi_calchash(gconstpointer k);
53
54 static void update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
55                                       packet_info *pinfo );
56
57 static struct tcaphash_begincall_t *append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
58                                                               struct tcaphash_context_t *p_tcaphash_context,
59                                                               packet_info *pinfo);
60
61
62 static struct tcaphash_begincall_t *find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
63                                                         packet_info *pinfo,
64                                                         gboolean isBegin);
65
66
67 static struct tcaphash_contcall_t *find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
68                                                       packet_info *pinfo);
69
70 static struct tcaphash_endcall_t *find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
71                                                     packet_info *pinfo,
72                                                     gboolean isEnd);
73 /* new key */
74 static struct tcaphash_context_t *new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
75                                                        packet_info *pinfo);
76
77 static struct tcaphash_begincall_t *new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
78                                                        struct tcaphash_context_t *p_tcaphash_context);
79
80 static struct tcaphash_contcall_t *new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
81                                                      struct tcaphash_context_t *p_tcaphash_context);
82
83 static struct tcaphash_endcall_t *new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
84                                                    struct tcaphash_context_t *p_tcaphash_context);
85
86 static struct tcaphash_context_t *tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
87                                                           struct tcapsrt_info_t *p_tcapsrt_info);
88
89 static struct tcaphash_context_t *tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
90                                                          struct tcapsrt_info_t *p_tcapsrt_info);
91
92 static struct tcaphash_context_t *tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
93                                                         struct tcapsrt_info_t *p_tcapsrt_info);
94
95 static struct tcaphash_context_t *tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
96                                                          struct tcapsrt_info_t *p_tcapsrt_info);
97
98 struct tcapsrt_info_t *tcapsrt_razinfo(void);
99
100 /* When several Tcap components are received in a single TCAP message,
101    we have to use several buffers for the stored parameters
102    because else this data are erased during TAP dissector call */
103 #define MAX_TCAP_INSTANCE 10
104 int tcapsrt_global_current=0;
105 struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
106
107 /* These two timeout (in second) are used when some message are lost,
108    or when the same TCAP transcation identifier is reused */
109 guint gtcap_RepetitionTimeout = 10;
110 guint gtcap_LostTimeout = 30;
111 extern gboolean gtcap_HandleSRT;
112 gboolean gtcap_PersistentSRT=FALSE;
113 gboolean gtcap_DisplaySRT=FALSE;
114 gboolean gtcap_StatSRT=FALSE;
115
116 extern gint ett_tcap_stat;
117
118 extern int hf_tcapsrt_SessionId;
119 extern int hf_tcapsrt_Duplicate;
120 extern int hf_tcapsrt_BeginSession;
121 extern int hf_tcapsrt_EndSession;
122 extern int hf_tcapsrt_SessionTime;
123
124 /* Global hash tables*/
125 static GHashTable *tcaphash_context = NULL;
126 static GHashTable *tcaphash_begin = NULL;
127 static GHashTable *tcaphash_cont = NULL;
128 static GHashTable *tcaphash_end = NULL;
129 static GHashTable *tcaphash_ansi = NULL;
130
131 guint32 tcapsrt_global_SessionId=1;
132
133 /*
134  * DEBUG fonctions
135  */
136 #undef MEM_TCAPSRT
137 /* #define MEM_TCAPSRT */
138
139 #undef DEBUG_TCAPSRT
140 /* #define DEBUG_TCAPSRT */
141
142 #ifdef DEBUG_TCAPSRT
143 #include <stdio.h>
144 #include <stdarg.h>
145 static unsigned debug_level = 99;
146
147 static void
148 dbg(unsigned  level, char* fmt, ...)
149 {
150   va_list ap;
151
152   if (level > debug_level) return;
153   va_start(ap,fmt);
154   vfprintf(stderr, fmt, ap);
155   va_end(ap);
156 }
157 #endif
158
159 static gint
160 tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
161 {
162   const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
163   const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
164
165   return (key1->session_id == key2->session_id);
166 }
167
168 /* calculate a hash key */
169 static guint
170 tcaphash_context_calchash(gconstpointer k)
171 {
172   const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
173   return key->session_id;
174 }
175
176
177 static gint
178 tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
179 {
180   const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
181   const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
182
183   if (key1->hashKey == key2->hashKey) {
184
185     if ( ( (key1->opc_hash == key2->opc_hash) &&
186            (key1->dpc_hash == key2->dpc_hash) &&
187            (key1->tid == key2->tid) )
188          ||
189          ( (key1->opc_hash == key2->dpc_hash) &&
190            (key1->dpc_hash == key2->opc_hash) &&
191            (key1->tid == key2->tid) )
192          )
193       return TRUE;
194   }
195   return FALSE;
196 }
197
198 /* calculate a hash key */
199 static guint
200 tcaphash_begin_calchash(gconstpointer k)
201 {
202   const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
203   guint hashkey;
204   /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
205   hashkey = key->tid;
206   return hashkey;
207 }
208
209 static gint
210 tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
211 {
212   const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
213   const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
214
215   if (key1->hashKey == key2->hashKey) {
216
217     if ( (key1->opc_hash == key2->opc_hash) &&
218          (key1->dpc_hash == key2->dpc_hash) &&
219          (key1->src_tid == key2->src_tid) &&
220          (key1->dst_tid == key2->dst_tid) ) {
221       return TRUE;
222     }
223     else if ( (key1->opc_hash == key2->dpc_hash) &&
224               (key1->dpc_hash == key2->opc_hash) &&
225               (key1->src_tid == key2->dst_tid) &&
226               (key1->dst_tid == key2->src_tid) ) {
227       return TRUE;
228     }
229   }
230   return FALSE;
231 }
232
233 /* calculate a hash key */
234 static guint
235 tcaphash_cont_calchash(gconstpointer k)
236 {
237   const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
238   guint hashkey;
239   hashkey = key->src_tid + key->dst_tid;
240   return hashkey;
241 }
242
243
244 static gint
245 tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
246 {
247   const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
248   const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
249
250   if (key1->hashKey == key2->hashKey) {
251     if ( ( (key1->opc_hash == key2->opc_hash) &&
252            (key1->dpc_hash == key2->dpc_hash) &&
253            (key1->tid == key2->tid) )
254          ||
255          ( (key1->opc_hash == key2->dpc_hash) &&
256            (key1->dpc_hash == key2->opc_hash) &&
257            (key1->tid == key2->tid) ) )
258       return TRUE;
259   }
260   return FALSE;
261 }
262
263 /* calculate a hash key */
264 static guint
265 tcaphash_end_calchash(gconstpointer k)
266 {
267   const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
268   guint hashkey;
269   hashkey = key->tid;
270   return hashkey;
271 }
272
273 static gint
274 tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
275 {
276   const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
277   const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
278
279   if (key1->hashKey == key2->hashKey) {
280
281     if ( ( (key1->opc_hash == key2->opc_hash) &&
282            (key1->dpc_hash == key2->dpc_hash) &&
283            (key1->tid == key2->tid) )
284          ||
285          ( (key1->opc_hash == key2->dpc_hash) &&
286            (key1->dpc_hash == key2->opc_hash) &&
287            (key1->tid == key2->tid) )
288          )
289       return TRUE;
290   }
291   return FALSE;
292 }
293
294 /* calculate a hash key */
295 static guint
296 tcaphash_ansi_calchash(gconstpointer k)
297 {
298   const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
299   guint hashkey;
300   /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
301   hashkey = key->tid;
302   return hashkey;
303 }
304
305 /*
306  * Update a record with the data of the Request
307  */
308 static void
309 update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
310                           packet_info *pinfo)
311 {
312   p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
313   p_tcaphash_begincall->context->last_frame = 0;
314   p_tcaphash_begincall->context->responded = FALSE;
315   p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
316 }
317
318 /*
319  * Append a new dialogue, using the same Key, to the chained list
320  * The time is stored too
321  */
322 static struct tcaphash_begincall_t *
323 append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
324                           struct tcaphash_context_t *p_tcaphash_context,
325                           packet_info *pinfo)
326 {
327   struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
328
329   /* Append the transaction to the list, when the same key is found
330      This should append when the tcap-transaction Id is reused  */
331
332 #ifdef MEM_TCAPSRT
333   p_new_tcaphash_begincall = g_malloc0(sizeof(struct tcaphash_begincall_t));
334 #else
335   p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
336 #endif
337   p_new_tcaphash_begincall->context=p_tcaphash_context;
338   p_tcaphash_context->begincall=p_new_tcaphash_begincall;
339   p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
340   p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
341   p_new_tcaphash_begincall->next_begincall=NULL;
342   p_new_tcaphash_begincall->previous_begincall=prev_begincall;
343   p_new_tcaphash_begincall->father=FALSE;
344
345 #ifdef DEBUG_TCAPSRT
346   dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
347 #endif
348   /* Insert in the chained list */
349   prev_begincall->next_begincall = p_new_tcaphash_begincall;
350   if (prev_begincall->context->last_frame == 0) {
351 #ifdef DEBUG_TCAPSRT
352     dbg(10,"last ");
353 #endif
354     prev_begincall->context->last_frame = pinfo->fd->num-1;
355   }
356   return p_new_tcaphash_begincall;
357 }
358
359 /*
360  * Update a record with the data of the Request
361  */
362 static void
363 update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
364                           packet_info *pinfo)
365 {
366   p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
367   p_tcaphash_ansicall->context->last_frame = 0;
368   p_tcaphash_ansicall->context->responded = FALSE;
369   p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
370 }
371
372 /*
373  * Append a new dialogue, using the same Key, to the chained list
374  * The time is stored too
375  */
376 static struct tcaphash_ansicall_t *
377 append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
378                           struct tcaphash_context_t *p_tcaphash_context,
379                           packet_info *pinfo)
380 {
381   struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
382
383   /* Append the transaction to the list, when the same key is found
384      This should append when the tcap-transaction Id is reused  */
385
386 #ifdef MEM_TCAPSRT
387   p_new_tcaphash_ansicall = g_malloc0(sizeof(struct tcaphash_ansicall_t));
388 #else
389   p_new_tcaphash_ansicall = se_alloc0(sizeof(struct tcaphash_ansicall_t));
390 #endif
391   p_new_tcaphash_ansicall->context=p_tcaphash_context;
392   p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
393   p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
394   p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
395   p_new_tcaphash_ansicall->next_ansicall=NULL;
396   p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
397   p_new_tcaphash_ansicall->father=FALSE;
398
399 #ifdef DEBUG_TCAPSRT
400   dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
401 #endif
402   /* Insert in the chained list */
403   prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
404   if (prev_ansicall->context->last_frame == 0) {
405 #ifdef DEBUG_TCAPSRT
406     dbg(10,"last ");
407 #endif
408     prev_ansicall->context->last_frame = pinfo->fd->num-1;
409   }
410   return p_new_tcaphash_ansicall;
411 }
412
413
414 static struct tcaphash_contcall_t *
415 append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
416                          struct tcaphash_context_t *p_tcaphash_context)
417 {
418   struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
419
420   /* Append the transaction to the list, when the same key is found
421      This should append when the tcap-transaction Id is reused  */
422
423 #ifdef MEM_TCAPSRT
424   p_new_tcaphash_contcall = g_malloc0(sizeof(struct tcaphash_contcall_t));
425 #else
426   p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
427 #endif
428   p_new_tcaphash_contcall->context=p_tcaphash_context;
429   p_tcaphash_context->contcall=p_new_tcaphash_contcall;
430   p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
431   p_new_tcaphash_contcall->next_contcall=NULL;
432   p_new_tcaphash_contcall->previous_contcall=prev_contcall;
433   p_new_tcaphash_contcall->father=FALSE;
434
435 #ifdef DEBUG_TCAPSRT
436   dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
437 #endif
438   /* Insert in the chained list */
439   prev_contcall->next_contcall = p_new_tcaphash_contcall;
440   return p_new_tcaphash_contcall;
441 }
442
443
444 static struct tcaphash_endcall_t *
445 append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
446                         struct tcaphash_context_t *p_tcaphash_context)
447 {
448   struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
449
450   /* Append the transaction to the list, when the same key is found
451      This should append when the tcap-transaction Id is reused  */
452
453 #ifdef MEM_TCAPSRT
454   p_new_tcaphash_endcall = g_malloc0(sizeof(struct tcaphash_endcall_t));
455 #else
456   p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
457 #endif
458   p_new_tcaphash_endcall->context=p_tcaphash_context;
459   p_tcaphash_context->endcall=p_new_tcaphash_endcall;
460   p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
461   p_new_tcaphash_endcall->next_endcall=NULL;
462   p_new_tcaphash_endcall->previous_endcall=prev_endcall;
463   p_new_tcaphash_endcall->father=FALSE;
464
465 #ifdef DEBUG_TCAPSRT
466   dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
467 #endif
468   /* Insert in the chained list */
469   prev_endcall->next_endcall = p_new_tcaphash_endcall;
470   return p_new_tcaphash_endcall;
471 }
472
473
474 /*
475  * Find the dialog by Key and Time
476  */
477 static struct tcaphash_begincall_t *
478 find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
479                     packet_info *pinfo, gboolean isBegin)
480 {
481   struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
482   p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
483
484   if(p_tcaphash_begincall) {
485     do {
486       if ( p_tcaphash_begincall->context ) {
487         if ( ( isBegin &&
488                pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
489              ||
490              ( !isBegin &&
491                pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
492                ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
493                )
494              ) {
495           /* We have a dialogue, with this key, opened before this request */
496 #ifdef DEBUG_TCAPSRT
497           dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
498 #endif
499           return p_tcaphash_begincall;
500           break;
501         }
502 #ifdef DEBUG_TCAPSRT
503           dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
504 #endif
505       }
506       /* Break when list end is reached */
507       if(p_tcaphash_begincall->next_begincall == NULL) {
508 #ifdef DEBUG_TCAPSRT
509         dbg(23,"End of Blist ");
510 #endif
511         break;
512       }
513       p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
514     } while (p_tcaphash_begincall != NULL) ;
515   } else {
516 #ifdef DEBUG_TCAPSRT
517     dbg(23,"Not in Bhash ");
518 #endif
519   }
520   return NULL;
521 }
522
523
524
525 static struct tcaphash_contcall_t *
526 find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
527                    packet_info *pinfo)
528 {
529   struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
530   p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
531
532   if(p_tcaphash_contcall) {
533     do {
534       if ( p_tcaphash_contcall->context ) {
535         if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
536             (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
537           /* We have a dialogue, with this key, opened before this request */
538 #ifdef DEBUG_TCAPSRT
539           dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
540 #endif
541           return p_tcaphash_contcall;
542           break;
543         }
544 #ifdef DEBUG_TCAPSRT
545         dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
546 #endif
547       }
548       /* Break when list end is reached */
549       if(p_tcaphash_contcall->next_contcall == NULL) {
550 #ifdef DEBUG_TCAPSRT
551         dbg(23,"End of Clist ");
552 #endif
553         break;
554       }
555       p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
556     } while (p_tcaphash_contcall != NULL) ;
557   } else {
558 #ifdef DEBUG_TCAPSRT
559     dbg(23,"Not in Chash ");
560 #endif
561   }
562   return NULL;
563 }
564
565 static struct tcaphash_endcall_t *
566 find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
567                   packet_info *pinfo, gboolean isEnd)
568 {
569   struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
570   p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
571
572   if(p_tcaphash_endcall) {
573     do {
574       if ( p_tcaphash_endcall->context ) {
575         if ( ( isEnd &&
576                (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
577                )
578              ||
579              ( !isEnd &&
580                pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
581                (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
582                )
583              ) {
584           /* We have a dialogue, with this key, opened before this request */
585 #ifdef DEBUG_TCAPSRT
586           dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
587 #endif
588           return p_tcaphash_endcall;
589           break;
590         }
591 #ifdef DEBUG_TCAPSRT
592           dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
593 #endif
594       }
595       /* Break when list end is reached */
596       if(p_tcaphash_endcall->next_endcall == NULL) {
597 #ifdef DEBUG_TCAPSRT
598         dbg(23,"End of Elist ");
599 #endif
600         break;
601       }
602       p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
603     } while (p_tcaphash_endcall != NULL) ;
604   } else {
605 #ifdef DEBUG_TCAPSRT
606     dbg(23,"Not in Ehash ");
607 #endif
608   }
609   return NULL;
610 }
611
612 /*
613  * New record to create, to identify a new transaction
614  */
615 static struct tcaphash_context_t *
616 new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
617                      packet_info *pinfo)
618 {
619   struct tcaphash_context_key_t *p_new_tcaphash_context_key;
620   struct tcaphash_context_t *p_new_tcaphash_context = NULL;
621
622   /* Register the transaction in the hash table
623      with the tcap transaction Id as Main Key
624      Once created, this entry will be updated later */
625
626 #ifdef MEM_TCAPSRT
627   p_new_tcaphash_context_key = g_malloc(sizeof(struct tcaphash_context_key_t));
628 #else
629   p_new_tcaphash_context_key = se_alloc(sizeof(struct tcaphash_context_key_t));
630 #endif
631   p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
632
633 #ifdef MEM_TCAPSRT
634   p_new_tcaphash_context = g_malloc0(sizeof(struct tcaphash_context_t));
635 #else
636   p_new_tcaphash_context = se_alloc0(sizeof(struct tcaphash_context_t));
637 #endif
638   p_new_tcaphash_context->key = p_new_tcaphash_context_key;
639   p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
640   p_new_tcaphash_context->first_frame = pinfo->fd->num;
641 #ifdef DEBUG_TCAPSRT
642   dbg(10,"S%d ", p_new_tcaphash_context->session_id);
643 #endif
644   /* store it */
645   g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
646   return p_new_tcaphash_context;
647 }
648
649 /*
650  * New record to create, to identify a new transaction
651  */
652 static struct tcaphash_begincall_t *
653 new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
654                    struct tcaphash_context_t *p_tcaphash_context)
655 {
656   struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
657   struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
658
659   /* Register the transaction in the hash table
660      with the tcap transaction Id as Main Key
661      Once created, this entry will be updated later */
662
663 #ifdef MEM_TCAPSRT
664   p_new_tcaphash_begin_key = g_malloc(sizeof(struct tcaphash_begin_info_key_t));
665 #else
666   p_new_tcaphash_begin_key = se_alloc(sizeof(struct tcaphash_begin_info_key_t));
667 #endif
668   p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
669   p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
670   p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
671   p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
672
673 #ifdef MEM_TCAPSRT
674   p_new_tcaphash_begincall = g_malloc0(sizeof(struct tcaphash_begincall_t));
675 #else
676  p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
677 #endif
678   p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
679   p_new_tcaphash_begincall->context=p_tcaphash_context;
680   p_tcaphash_context->begincall=p_new_tcaphash_begincall;
681   p_new_tcaphash_begincall->father=TRUE;
682   p_new_tcaphash_begincall->next_begincall=NULL;
683   p_new_tcaphash_begincall->previous_begincall=NULL;
684
685 #ifdef DEBUG_TCAPSRT
686   dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
687 #endif
688   /* store it */
689   g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
690   return p_new_tcaphash_begincall;
691 }
692
693
694
695 /*
696  * New record to create, to identify a new transaction
697  */
698 static struct tcaphash_contcall_t *
699 new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
700                   struct tcaphash_context_t *p_tcaphash_context)
701 {
702   struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
703   struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
704
705   /* Register the transaction in the hash table
706      with the tcap transaction Id as Main Key
707      Once created, this entry will be updated later */
708
709 #ifdef MEM_TCAPSRT
710   p_new_tcaphash_cont_key = g_malloc(sizeof(struct tcaphash_cont_info_key_t));
711 #else
712   p_new_tcaphash_cont_key = se_alloc(sizeof(struct tcaphash_cont_info_key_t));
713 #endif
714   p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
715   p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
716   p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
717   p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
718   p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
719
720 #ifdef MEM_TCAPSRT
721   p_new_tcaphash_contcall = g_malloc0(sizeof(struct tcaphash_contcall_t));
722 #else
723   p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
724 #endif
725   p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
726   p_new_tcaphash_contcall->context=p_tcaphash_context;
727   p_tcaphash_context->contcall=p_new_tcaphash_contcall;
728   p_new_tcaphash_contcall->father=TRUE;
729   p_new_tcaphash_contcall->next_contcall=NULL;
730   p_new_tcaphash_contcall->previous_contcall=NULL;
731
732 #ifdef DEBUG_TCAPSRT
733   dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
734 #endif
735   /* store it */
736   g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
737   return p_new_tcaphash_contcall;
738 }
739
740
741 /*
742  * New record to create, to identify a new transaction
743  */
744 static struct tcaphash_endcall_t *
745 new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
746                  struct tcaphash_context_t *p_tcaphash_context)
747 {
748   struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
749   struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
750
751   /* Register the transaction in the hash table
752      with the tcap transaction Id as Main Key
753      Once created, this entry will be updated later */
754
755 #ifdef MEM_TCAPSRT
756   p_new_tcaphash_end_key = g_malloc(sizeof(struct tcaphash_end_info_key_t));
757 #else
758   p_new_tcaphash_end_key = se_alloc(sizeof(struct tcaphash_end_info_key_t));
759 #endif
760   p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
761   p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
762   p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
763   p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
764
765 #ifdef MEM_TCAPSRT
766   p_new_tcaphash_endcall = g_malloc0(sizeof(struct tcaphash_endcall_t));
767 #else
768   p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
769 #endif
770   p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
771   p_new_tcaphash_endcall->context=p_tcaphash_context;
772   p_tcaphash_context->endcall=p_new_tcaphash_endcall;
773   p_new_tcaphash_endcall->father=TRUE;
774   p_new_tcaphash_endcall->next_endcall=NULL;
775   p_new_tcaphash_endcall->previous_endcall=NULL;
776
777 #ifdef DEBUG_TCAPSRT
778   dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
779 #endif
780   /* store it */
781   g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
782   return p_new_tcaphash_endcall;
783 }
784 /*
785  * New record to create, to identify a new transaction
786  */
787 static struct tcaphash_ansicall_t *
788 new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
789                    struct tcaphash_context_t *p_tcaphash_context)
790 {
791   struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
792   struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
793
794   /* Register the transaction in the hash table
795      with the tcap transaction Id as Main Key
796      Once created, this entry will be updated later */
797
798 #ifdef MEM_TCAPSRT
799   p_new_tcaphash_ansi_key = g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
800 #else
801   p_new_tcaphash_ansi_key = se_alloc(sizeof(struct tcaphash_ansi_info_key_t));
802 #endif
803   p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
804   p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
805   p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
806   p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
807
808 #ifdef MEM_TCAPSRT
809   p_new_tcaphash_ansicall = g_malloc0(sizeof(struct tcaphash_ansicall_t));
810 #else
811   p_new_tcaphash_ansicall = se_alloc0(sizeof(struct tcaphash_ansicall_t));
812 #endif
813   p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
814   p_new_tcaphash_ansicall->context=p_tcaphash_context;
815   p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
816   p_new_tcaphash_ansicall->father=TRUE;
817   p_new_tcaphash_ansicall->next_ansicall=NULL;
818   p_new_tcaphash_ansicall->previous_ansicall=NULL;
819
820 #ifdef DEBUG_TCAPSRT
821   dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
822 #endif
823   /* store it */
824   g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
825   return p_new_tcaphash_ansicall;
826 }
827
828 static struct tcaphash_contcall_t *
829 create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
830                      struct tcaphash_context_t *p_tcaphash_context)
831 {
832   struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
833   struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
834
835   p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
836     g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
837
838   if (p_tcaphash_contcall1) {
839     /* Walk through list of transaction with identical keys */
840     /* go the the end to insert new record */
841     do {
842       if (!p_tcaphash_contcall1->next_contcall) {
843         p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
844                                                      p_tcaphash_context);
845         break;
846       }
847       p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
848     } while (p_tcaphash_contcall1 != NULL );
849   } else {
850     p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
851                                             p_tcaphash_context);
852   }
853   return p_tcaphash_contcall;
854 }
855
856
857 static struct tcaphash_endcall_t *
858 create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
859                     struct tcaphash_context_t *p_tcaphash_context)
860 {
861   struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
862   struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
863
864   p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
865     g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
866
867   if (p_tcaphash_endcall1) {
868     /* Walk through list of transaction with identical keys */
869     /* go the the end to insert new record */
870     do {
871       if (!p_tcaphash_endcall1->next_endcall) {
872         p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
873                                                    p_tcaphash_context);
874         break;
875       }
876       p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
877     } while (p_tcaphash_endcall1 != NULL );
878   } else {
879     p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
880                                           p_tcaphash_context);
881   }
882   return p_tcaphash_endcall;
883 }
884
885
886 /*
887  * Routine called when the TAP is initialized.
888  * so hash table are (re)created
889  */
890 void
891 tcapsrt_init_routine(void)
892 {
893
894   /* free hash-tables and mem_chunks for SRT */
895   if (tcaphash_context != NULL) {
896 #ifdef DEBUG_TCAPSRT
897     dbg(16,"Destroy hash_context ");
898 #endif
899     g_hash_table_destroy(tcaphash_context);
900   }
901
902   if (tcaphash_begin != NULL) {
903 #ifdef DEBUG_TCAPSRT
904     dbg(16,"Destroy hash_begin ");
905 #endif
906     g_hash_table_destroy(tcaphash_begin);
907   }
908
909   if (tcaphash_cont != NULL) {
910 #ifdef DEBUG_TCAPSRT
911     dbg(16,"Destroy hash_cont ");
912 #endif
913     g_hash_table_destroy(tcaphash_cont);
914   }
915
916   if (tcaphash_end != NULL) {
917 #ifdef DEBUG_TCAPSRT
918     dbg(16,"Destroy hash_end ");
919 #endif
920     g_hash_table_destroy(tcaphash_end);
921   }
922
923   if (tcaphash_ansi != NULL) {
924 #ifdef DEBUG_TCAPSRT
925     dbg(16,"Destroy hash_ansi ");
926 #endif
927     g_hash_table_destroy(tcaphash_ansi);
928   }
929
930 #ifdef DEBUG_TCAPSRT
931   dbg(16,"Create hash ");
932 #endif
933   /* create new hash-tables and mem_chunks for SRT */
934   tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
935   tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
936   tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
937   tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
938   tcaphash_ansi = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
939
940   /* Reset the session counter */
941   tcapsrt_global_SessionId=1;
942
943   /* Display of SRT only if Persistent Stat */
944   gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
945 }
946
947 /*
948  * Service Response Time analyze
949  * Called just after dissector call
950  * Associate a TCAP context to a tcap session and display session related infomations
951  * like the first frame, the last, the session duration,
952  * and a uniq session identifier for the filtering
953  *
954  * For ETSI tcap, the TCAP context can be reached through three keys
955  * - a key (BEGIN) identifying the session according to the tcap source identifier
956  * - a key (CONT) identifying the established session (src_id and dst_id)
957  * - a key (END) identifying the session according to the tcap destination identifier
958  *
959  * For ANSI tcap, the TCAP context is reached through a uniq key
960  * - a key (ANSI) identifying the session according to the tcap identifier
961 */
962 struct tcaphash_context_t *
963 tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
964                       struct tcapsrt_info_t *p_tcapsrt_info)
965 {
966   struct tcaphash_context_t *tcap_context=NULL;
967
968   /* if this packet isn't loaded because of a read filter, don't output anything */
969   if(pinfo == NULL || pinfo->fd->num == 0) {
970     return NULL;
971   }
972
973   switch (p_tcapsrt_info->ope) {
974
975   case TC_BEGIN:
976 #ifdef DEBUG_TCAPSRT
977     dbg(1,"TC_BEGIN ");
978 #endif
979     tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
980     break;
981
982   case TC_CONT:
983 #ifdef DEBUG_TCAPSRT
984     dbg(1,"TC_CONT ");
985 #endif
986     tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
987     break;
988
989   case TC_ABORT:
990 #ifdef DEBUG_TCAPSRT
991     dbg(1,"TC_ABORT ");
992 #endif
993     tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
994     break;
995
996   case TC_END:
997 #ifdef DEBUG_TCAPSRT
998     dbg(1,"TC_END ");
999 #endif
1000     tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
1001     break;
1002
1003   case TC_ANSI_ALL:
1004   case TC_ANSI_ABORT:
1005 #ifdef DEBUG_TCAPSRT
1006     dbg(1,"TC_ANSI ");
1007 #endif
1008     tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
1009     break;
1010
1011   default:
1012 #ifdef DEBUG_TCAPSRT
1013     dbg(1,"Unknown %d ", p_tcapsrt_info->ope);
1014 #endif
1015     break;
1016   } /* switch tcapop */
1017 #ifdef DEBUG_TCAPSRT
1018   if (tcap_context)
1019     dbg(1,"session %d ", tcap_context->session_id);
1020 #endif
1021   return tcap_context;
1022 }
1023
1024
1025 /*
1026  * Create the record identifiying the TCAP transaction
1027  * When the identifier for the transaction is reused, check
1028  * the following criteria before to append a new record:
1029  * - a timeout corresponding to a message retransmission is detected,
1030  * - a message hast been lost
1031  * - or the previous transaction has been  be closed
1032  */
1033 static struct tcaphash_context_t *
1034 tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1035                         struct tcapsrt_info_t *p_tcapsrt_info)
1036 {
1037   struct tcaphash_context_t *p_tcaphash_context=NULL;
1038   struct tcaphash_context_key_t tcaphash_context_key;
1039   struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
1040   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1041   proto_item *pi;
1042   proto_item *stat_item=NULL;
1043   proto_tree *stat_tree=NULL;
1044
1045   /* prepare the key data */
1046   tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
1047   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1048   {
1049     /* We have MTP3 PCs (so we can safely do this cast) */
1050     tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1051     tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1052   } else {
1053     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1054     tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1055     tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1056   }
1057   tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1058
1059   /* look up the request */
1060 #ifdef DEBUG_TCAPSRT
1061   dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
1062   dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
1063   dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1064   dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1065 #endif
1066
1067   p_tcaphash_begincall = (struct tcaphash_begincall_t *)
1068   g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
1069
1070   if (p_tcaphash_begincall) {
1071     /* Walk through list of transaction with identical keys */
1072     do {
1073       /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
1074       if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
1075         /* We have seen this request before -> do nothing */
1076 #ifdef DEBUG_TCAPSRT
1077         dbg(22,"Already seen ");
1078 #endif
1079         p_tcaphash_context=p_tcaphash_begincall->context;
1080         break;
1081       }
1082       /* If the last record for Tcap transaction with identifier has not been reached */
1083       if (!p_tcaphash_begincall->next_begincall) {
1084         /* check if we have to create a new record or not */
1085         /* if last request has been responded (response number is known)
1086            and this request appears after last response (has bigger frame number)
1087            and last request occured after the timeout for repetition,
1088            or
1089            if last request hasn't been responded (so number unknown)
1090            and this request appears after last request (has bigger frame number)
1091            and this request occured after the timeout for message lost */
1092         if ( ( p_tcaphash_begincall->context->last_frame != 0
1093                && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
1094                && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
1095                ) ||
1096              ( p_tcaphash_begincall->context->last_frame == 0
1097                && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
1098                && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
1099                )
1100              )
1101           {
1102             /* we decide that we have a new request */
1103             /* Append new record to the list */
1104 #ifdef DEBUG_TCAPSRT
1105             dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
1106             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
1107 #endif
1108             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1109             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1110
1111             p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
1112                                                                  p_tcaphash_context,
1113                                                                  pinfo);
1114 #ifdef DEBUG_TCAPSRT
1115             dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
1116 #endif
1117             update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
1118             p_tcaphash_begincall=p_new_tcaphash_begincall;
1119           } else { /* timeout or message lost */
1120
1121           /* If the Tid is reused for a closed Transaction */
1122           /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
1123           /* (this is the case, for pre-arranged END, the transaction is marked as closed */
1124           /* by the upper layer, thank to a callback method close) */
1125           if ( p_tcaphash_begincall->context->closed) {
1126 #ifdef DEBUG_TCAPSRT
1127             dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
1128             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
1129 #endif
1130             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1131             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1132             p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
1133                                                                  p_tcaphash_context,
1134                                                                  pinfo);
1135
1136 #ifdef DEBUG_TCAPSRT
1137             dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
1138 #endif
1139             update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
1140             p_tcaphash_begincall=p_new_tcaphash_begincall;
1141
1142           } else {
1143             /* the TCAP session is not closed, so, either messages have been lost */
1144             /* or it's a duplicate request. Mark it as such. */
1145 #ifdef DEBUG_TCAPSRT
1146             dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
1147 #endif
1148             p_tcaphash_context=p_tcaphash_begincall->context;
1149             if (gtcap_DisplaySRT && tree) {
1150               stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1151               PROTO_ITEM_SET_GENERATED(stat_item);
1152               stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1153               pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
1154                                               p_tcaphash_context->first_frame,
1155                                               "Duplicate with session %u in frame %u",
1156                                               p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
1157               PROTO_ITEM_SET_GENERATED(pi);
1158             }
1159             return p_tcaphash_context;
1160           } /* Previous session closed */
1161         } /* test with Timeout or message Lost */
1162         break;
1163       } /* Next call is NULL */
1164       /* Repeat the tests for the next record with the same transaction identifier */
1165       p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
1166     } while (p_tcaphash_begincall != NULL );
1167     /*
1168      * End of analyze for the list be TC_BEGIN with same transaction ID
1169      */
1170   } else { /* p_tcaphash_begincall has not been found */
1171     /*
1172      * Create a new TCAP context
1173      */
1174 #ifdef DEBUG_TCAPSRT
1175     dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
1176 #endif
1177
1178     tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1179     p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1180     p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
1181
1182 #ifdef DEBUG_TCAPSRT
1183     dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
1184     dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1185 #endif
1186     update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
1187   }
1188
1189   /* display tcap session, if available */
1190   if ( gtcap_DisplaySRT && tree &&
1191        p_tcaphash_context &&
1192        p_tcaphash_context->session_id) {
1193     stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
1194     PROTO_ITEM_SET_GENERATED(stat_item);
1195     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1196     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1197     PROTO_ITEM_SET_GENERATED(pi);
1198
1199     /* add link to response frame, if available */
1200     /* p_tcaphash_begincall->context->last_frame) */
1201     if( p_tcaphash_context->last_frame != 0 ){
1202 #ifdef DEBUG_TCAPSRT
1203       dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
1204 #endif
1205       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1206                                       p_tcaphash_context->last_frame,
1207                                       "End of session in frame %u",
1208                                       p_tcaphash_context->last_frame);
1209       PROTO_ITEM_SET_GENERATED(pi);
1210     }
1211   }
1212   return p_tcaphash_context;
1213 }
1214
1215
1216 /*
1217 * Try to find a TCAP session according to the source and destination
1218 * Identifier given in the TC_CONT
1219 * If nothing is found, it is probably a session in opening state, so try to find
1220 * a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
1221 * Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
1222 * and display the available info for the TCAP context
1223 */
1224 static struct tcaphash_context_t *
1225 tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1226                        struct tcapsrt_info_t *p_tcapsrt_info)
1227 {
1228   struct tcaphash_context_t *p_tcaphash_context=NULL;
1229   struct tcaphash_contcall_t *p_tcaphash_contcall;
1230   struct tcaphash_cont_info_key_t tcaphash_cont_key;
1231   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1232   struct tcaphash_begincall_t *p_tcaphash_begincall;
1233   struct tcaphash_end_info_key_t tcaphash_end_key;
1234   struct tcaphash_endcall_t *p_tcaphash_endcall;
1235   proto_item *pi;
1236   proto_item *stat_item=NULL;
1237   proto_tree *stat_tree=NULL;
1238
1239 #ifdef DEBUG_TCAPSRT
1240   dbg(10,"\n Hcont #%u ", pinfo->fd->num);
1241 #endif
1242
1243   /* look only for matching request, if matching conversation is available. */
1244   tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
1245   tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
1246   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1247   {
1248     /* We have MTP3 PCs (so we can safely do this cast) */
1249     tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1250     tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1251   } else {
1252     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1253     tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1254     tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1255   }
1256   tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1257
1258 #ifdef DEBUG_TCAPSRT
1259   dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1260   dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1261   dbg(51,"Tid %lx %lx ",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1262 #endif
1263   p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1264   if(p_tcaphash_contcall) {
1265 #ifdef DEBUG_TCAPSRT
1266     dbg(12,"CFound ");
1267 #endif
1268     p_tcaphash_context=p_tcaphash_contcall->context;
1269   } else { /* cont not found */
1270 #ifdef DEBUG_TCAPSRT
1271     dbg(12,"CnotFound ");
1272 #endif
1273     /* Find the TCAP transaction according to the TC_BEGIN */
1274     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1275     if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1276     {
1277       /* We have MTP3 PCs (so we can safely do this cast) */
1278       tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1279       tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1280     } else {
1281       /* Don't have MTP3 PCs (maybe we're over SUA?) */
1282       tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1283       tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1284     }
1285     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1286
1287 #ifdef DEBUG_TCAPSRT
1288     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1289     dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1290     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1291 #endif
1292     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1293     if(p_tcaphash_begincall &&
1294        !p_tcaphash_begincall->context->contcall ) {
1295 #ifdef DEBUG_TCAPSRT
1296       dbg(12,"BFound ");
1297 #endif
1298       p_tcaphash_context=p_tcaphash_begincall->context;
1299       p_tcaphash_context->responded=TRUE;
1300
1301 #ifdef DEBUG_TCAPSRT
1302       dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1303       dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1304 #endif
1305       p_tcaphash_contcall = create_tcaphash_cont(&tcaphash_cont_key,
1306                                                  p_tcaphash_begincall->context);
1307
1308       tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
1309       if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1310       {
1311         /* We have MTP3 PCs (so we can safely do this cast) */
1312         tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1313         tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1314       } else {
1315         /* Don't have MTP3 PCs (maybe we're over SUA?) */
1316         tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1317         tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1318       }
1319       tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1320
1321 #ifdef DEBUG_TCAPSRT
1322       dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1323       dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1324 #endif
1325       p_tcaphash_endcall = create_tcaphash_end(&tcaphash_end_key,
1326                                                p_tcaphash_begincall->context);
1327
1328     } else { /* Begin not found */
1329 #ifdef DEBUG_TCAPSRT
1330       dbg(12,"BnotFound ");
1331 #endif
1332     } /* begin found */
1333   } /* cont found */
1334     /* display tcap session, if available */
1335   if (gtcap_DisplaySRT && tree &&
1336       p_tcaphash_context &&
1337       p_tcaphash_context->session_id) {
1338     stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1339     PROTO_ITEM_SET_GENERATED(stat_item);
1340     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1341     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1342     PROTO_ITEM_SET_GENERATED(pi);
1343   }
1344
1345   return p_tcaphash_context;
1346 }
1347
1348 /*
1349 * Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
1350 * If nothing is found,
1351 * - either it is a session in opening state,
1352 * - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
1353 * so try to find a tcap session registered with a TC_BEGIN "key",
1354 * matching the destination Id of the TC_END
1355 * Then associate the TC_CONT "key" to the TCAP context
1356 * and display the available info for the TCAP context
1357 */
1358
1359 static struct tcaphash_context_t *
1360 tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1361                       struct tcapsrt_info_t *p_tcapsrt_info)
1362 {
1363   struct tcaphash_context_t *p_tcaphash_context=NULL;
1364
1365   struct tcaphash_end_info_key_t tcaphash_end_key;
1366   struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
1367
1368   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1369   struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
1370   proto_item *pi;
1371   nstime_t delta;
1372   proto_item *stat_item=NULL;
1373   proto_tree *stat_tree=NULL;
1374
1375 #ifdef DEBUG_TCAPSRT
1376   dbg(10,"\n Hend #%u ", pinfo->fd->num);
1377 #endif
1378   /* look only for matching request, if matching conversation is available. */
1379   tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1380   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1381   {
1382     /* We have MTP3 PCs (so we can safely do this cast) */
1383     tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1384     tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1385   } else {
1386     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1387     tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1388     tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1389   }
1390   tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1391
1392 #ifdef DEBUG_TCAPSRT
1393   dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1394   dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1395   dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1396 #endif
1397   p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
1398
1399   if(!p_tcaphash_endcall) {
1400 #ifdef DEBUG_TCAPSRT
1401     dbg(12,"EnotFound ");
1402 #endif
1403     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1404     if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1405     {
1406       /* We have MTP3 PCs (so we can safely do this cast) */
1407       tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1408       tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1409     } else {
1410       /* Don't have MTP3 PCs (maybe we're over SUA?) */
1411       tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1412       tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1413     }
1414     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1415
1416 #ifdef DEBUG_TCAPSRT
1417     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1418     dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1419     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1420 #endif
1421     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1422     if(!p_tcaphash_begincall) {
1423 #ifdef DEBUG_TCAPSRT
1424       dbg(12,"BnotFound ");
1425 #endif
1426     }
1427   }
1428   if (p_tcaphash_endcall) {
1429     /* Use the TC_BEGIN Destination reference */
1430     p_tcaphash_context=p_tcaphash_endcall->context;
1431   } else if (p_tcaphash_begincall) {
1432     /* Use the TC_BEGIN Source reference */
1433     p_tcaphash_context=p_tcaphash_begincall->context;
1434   }
1435
1436   if (p_tcaphash_context) {
1437
1438 #ifdef DEBUG_TCAPSRT
1439     dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1440 #endif
1441     if (gtcap_DisplaySRT && tree) {
1442       stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1443       PROTO_ITEM_SET_GENERATED(stat_item);
1444       stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1445
1446       pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1447       PROTO_ITEM_SET_GENERATED(pi);
1448     }
1449
1450 #ifdef DEBUG_TCAPSRT
1451     dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1452 #endif
1453     /* Indicate the frame to which this is a reply. */
1454     if (gtcap_DisplaySRT && stat_tree) {
1455       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1456                                       p_tcaphash_context->first_frame,
1457                                       "Begin of session in frame %u",
1458                                       p_tcaphash_context->first_frame);
1459       PROTO_ITEM_SET_GENERATED(pi);
1460       /* Calculate Service Response Time */
1461       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1462
1463       /* display Service Response Time and make it filterable */
1464       pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1465       PROTO_ITEM_SET_GENERATED(pi);
1466     }
1467     /* Close the context and remove it (if needed) */
1468     tcapsrt_close(p_tcaphash_context,pinfo);
1469
1470   } else {/* context present */
1471 #ifdef DEBUG_TCAPSRT
1472     dbg(12,"Context notFound ");
1473 #endif
1474   }
1475   return p_tcaphash_context;
1476 }
1477
1478 /*
1479  * ANSI PART
1480  * Create the record identifiying the TCAP transaction
1481  * When the identifier for the transaction is reused, check
1482  * the following criteria before to append a new record:
1483  * - a timeout corresponding to a message retransmission is detected,
1484  * - a message hast been lost
1485  * - or the previous transaction has been  be closed
1486  */
1487 static struct tcaphash_context_t *
1488 tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1489                        struct tcapsrt_info_t *p_tcapsrt_info)
1490 {
1491   struct tcaphash_context_t *p_tcaphash_context=NULL;
1492   struct tcaphash_context_key_t tcaphash_context_key;
1493   struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
1494   struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
1495   proto_item *pi;
1496   nstime_t delta;
1497   gboolean isResponse=FALSE;
1498   proto_tree * stat_tree=NULL;
1499   proto_item * stat_item=NULL;
1500
1501   /* prepare the key data */
1502   tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
1503   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1504   {
1505     /* We have MTP3 PCs (so we can safely do this cast) */
1506     tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1507     tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1508   } else {
1509     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1510     tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1511     tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1512   }
1513   tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
1514
1515   /* look up the request */
1516 #ifdef DEBUG_TCAPSRT
1517   dbg(10,"\n Hansi #%u ", pinfo->fd->num);
1518   dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
1519   dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1520   dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
1521 #endif
1522   p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
1523     g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
1524
1525   if (p_tcaphash_ansicall) {
1526     /* Walk through list of transaction with identical keys */
1527     do {
1528       /* Check if the request with this reqSeqNum has been seen */
1529       if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
1530         /* We have seen this request before -> do nothing */
1531 #ifdef DEBUG_TCAPSRT
1532         dbg(22,"Request already seen ");
1533 #endif
1534         isResponse=FALSE;
1535         p_tcaphash_context=p_tcaphash_ansicall->context;
1536         break;
1537       }
1538
1539       /* Check if the reponse with this reqSeqNum has been seen */
1540       if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
1541         /* We have seen this response before -> do nothing */
1542 #ifdef DEBUG_TCAPSRT
1543         dbg(22,"Response already seen ");
1544 #endif
1545         isResponse=TRUE;
1546         p_tcaphash_context=p_tcaphash_ansicall->context;
1547         break;
1548       }
1549
1550       /* Check for the first Request without Response
1551        received before this frame */
1552       if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
1553            p_tcaphash_ansicall->context->last_frame==0 ) {
1554         /* Take it, and update the context */
1555
1556 #ifdef DEBUG_TCAPSRT
1557         dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1558 #endif
1559         p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
1560         p_tcaphash_ansicall->context->responded = TRUE;
1561         p_tcaphash_ansicall->context->closed = TRUE;
1562         p_tcaphash_context=p_tcaphash_ansicall->context;
1563         isResponse=TRUE;
1564
1565         if (gtcap_DisplaySRT && tree) {
1566           stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1567           PROTO_ITEM_SET_GENERATED(stat_item);
1568           stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1569
1570           pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1571           PROTO_ITEM_SET_GENERATED(pi);
1572
1573 #ifdef DEBUG_TCAPSRT
1574           dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1575 #endif
1576           /* Indicate the frame to which this is a reply. */
1577           pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1578                                           p_tcaphash_context->first_frame,
1579                                           "Begin of session in frame %u",
1580                                           p_tcaphash_context->first_frame);
1581           PROTO_ITEM_SET_GENERATED(pi);
1582           /* Calculate Service Response Time */
1583           nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1584
1585           /* display Service Response Time and make it filterable */
1586           pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1587           PROTO_ITEM_SET_GENERATED(pi);
1588         }
1589         break;
1590       } /* Lastframe=0, so take it */
1591
1592
1593       /* If the last record for Tcap transaction with identifier has been reached */
1594       if (!p_tcaphash_ansicall->next_ansicall) {
1595         /* check if we have to create a new record or not */
1596         /* if last request has been responded (response number in known)
1597            and this request appears after last response (has bigger frame number)
1598            and last request occured after the timeout for repetition,
1599            or
1600            if last request hasn't been responded (so number unknown)
1601            and this request appears after last request (has bigger frame number)
1602            and this request occured after the timeout for message lost */
1603         if ( ( p_tcaphash_ansicall->context->last_frame != 0
1604                && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1605                && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
1606                ) ||
1607              ( p_tcaphash_ansicall->context->last_frame == 0
1608                && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1609                && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
1610                )
1611              )
1612           {
1613             /* we decide that we have a new request */
1614             /* Append new record to the list */
1615 #ifdef DEBUG_TCAPSRT
1616             dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
1617             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1618 #endif
1619             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1620             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1621             p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1622                                                                  p_tcaphash_context,
1623                                                                  pinfo);
1624
1625 #ifdef DEBUG_TCAPSRT
1626             dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1627 #endif
1628             update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1629             p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1630           } else {
1631
1632           /* If the Tid is reused for a closed Transaction */
1633           if ( p_tcaphash_ansicall->context->closed) {
1634 #ifdef DEBUG_TCAPSRT
1635             dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
1636             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1637 #endif
1638             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1639             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1640             p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1641                                                                  p_tcaphash_context,
1642                                                                  pinfo);
1643
1644 #ifdef DEBUG_TCAPSRT
1645             dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
1646 #endif
1647             update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1648             p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1649
1650           } else {
1651             /* the Tid is reused for an opened Transaction */
1652             /* so, this is the reply to the request of our context */
1653             p_tcaphash_context=p_tcaphash_ansicall->context;
1654 #ifdef DEBUG_TCAPSRT
1655             dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1656 #endif
1657
1658             if (gtcap_DisplaySRT && tree) {
1659               stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1660               PROTO_ITEM_SET_GENERATED(stat_item);
1661               stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1662
1663               pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1664               PROTO_ITEM_SET_GENERATED(pi);
1665
1666 #ifdef DEBUG_TCAPSRT
1667               dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1668 #endif
1669               /* Indicate the frame to which this is a reply. */
1670               pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1671                                               p_tcaphash_context->first_frame,
1672                                               "Begin of session in frame %u",
1673                                               p_tcaphash_context->first_frame);
1674               PROTO_ITEM_SET_GENERATED(pi);
1675               /* Calculate Service Response Time */
1676               nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1677
1678               /* display Service Response Time and make it filterable */
1679               pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1680               PROTO_ITEM_SET_GENERATED(pi);
1681             }
1682             p_tcaphash_context=p_tcaphash_ansicall->context;
1683           } /* test with Timeout */
1684         } /* closed */
1685         break;
1686       } /* Next call is NULL */
1687       p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
1688     } while (p_tcaphash_ansicall != NULL );
1689     /*
1690      * New TCAP context
1691      */
1692   } else { /* p_tcaphash_ansicall has not been found */
1693 #ifdef DEBUG_TCAPSRT
1694     dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
1695 #endif
1696
1697     tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1698     p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1699     p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
1700
1701 #ifdef DEBUG_TCAPSRT
1702     dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
1703     dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1704 #endif
1705     update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
1706   }
1707
1708   /* display tcap session, if available */
1709   if ( gtcap_DisplaySRT && tree &&
1710        p_tcaphash_context &&
1711        p_tcaphash_context->session_id) {
1712     stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1713     PROTO_ITEM_SET_GENERATED(stat_item);
1714     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1715     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1716     PROTO_ITEM_SET_GENERATED(pi);
1717   }
1718
1719
1720   /* add link to response frame, if available */
1721   if( gtcap_DisplaySRT && stat_tree &&
1722       p_tcaphash_ansicall->context->last_frame != 0){
1723     if (!isResponse) { /* Request */
1724 #ifdef DEBUG_TCAPSRT
1725       dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
1726 #endif
1727       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1728                                       p_tcaphash_ansicall->context->last_frame,
1729                                       "End of session in frame %u",
1730                                       p_tcaphash_ansicall->context->last_frame);
1731       PROTO_ITEM_SET_GENERATED(pi);
1732     } else { /* Response */
1733 #ifdef DEBUG_TCAPSRT
1734       dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1735 #endif
1736       /* Indicate the frame to which this is a reply. */
1737       if (gtcap_DisplaySRT) {
1738         pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1739                                         p_tcaphash_context->first_frame,
1740                                         "Begin of session in frame %u",
1741                                         p_tcaphash_context->first_frame);
1742         PROTO_ITEM_SET_GENERATED(pi);
1743         /* Calculate Service Response Time */
1744         nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1745
1746         /* display Service Response Time and make it filterable */
1747         pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1748         PROTO_ITEM_SET_GENERATED(pi);
1749       }
1750     } /* Request or Response */
1751   }
1752   return p_tcaphash_context;
1753 }
1754
1755
1756 /*
1757  * Initialize the Message Info used by the main dissector
1758  * Data are linked to a TCAP transaction
1759  */
1760 struct tcapsrt_info_t *
1761 tcapsrt_razinfo(void)
1762 {
1763   struct tcapsrt_info_t *p_tcapsrt_info ;
1764
1765   /* Global buffer for packet extraction */
1766   tcapsrt_global_current++;
1767   if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1768     tcapsrt_global_current=0;
1769   }
1770
1771   p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1772   memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
1773
1774   return p_tcapsrt_info;
1775 }
1776
1777 void
1778 tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
1779               packet_info *pinfo)
1780 {
1781 #ifdef DEBUG_TCAPSRT
1782   dbg(60,"Force close ");
1783 #endif
1784   if (p_tcaphash_context) {
1785     p_tcaphash_context->responded=TRUE;
1786     p_tcaphash_context->last_frame = pinfo->fd->num;
1787     p_tcaphash_context->end_time = pinfo->fd->abs_ts;
1788     p_tcaphash_context->closed=TRUE;
1789
1790     /* If the endkey is present */
1791     if (p_tcaphash_context->endcall
1792         && !gtcap_PersistentSRT) {
1793       if (p_tcaphash_context->endcall->next_endcall) {
1794         if (p_tcaphash_context->endcall->previous_endcall ) {
1795 #ifdef DEBUG_TCAPSRT
1796           dbg(20,"deplace Ehash ");
1797 #endif
1798           p_tcaphash_context->endcall->previous_endcall->next_endcall
1799             = p_tcaphash_context->endcall->next_endcall;
1800           p_tcaphash_context->endcall->next_endcall->previous_endcall
1801             = p_tcaphash_context->endcall->previous_endcall;
1802           g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1803 #ifdef MEM_TCAPSRT
1804           g_free(p_tcaphash_context->endcall);
1805 #endif
1806         } else {
1807           /* cannot remove the father */
1808 #ifdef DEBUG_TCAPSRT
1809           dbg(20,"father Ehash ");
1810 #endif
1811         } /* no previous link, so father */
1812       } else if (!gtcap_PersistentSRT) {
1813 #ifdef DEBUG_TCAPSRT
1814         dbg(20,"remove Ehash ");
1815 #endif
1816         g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1817 #ifdef MEM_TCAPSRT
1818         g_free(p_tcaphash_context->endcall->endkey);
1819         g_free(p_tcaphash_context->endcall);
1820 #endif
1821
1822       } /* endcall without chained string */
1823     } /* no endcall */
1824
1825
1826     /* If the contkey is present */
1827     if (p_tcaphash_context->contcall
1828         && !gtcap_PersistentSRT) {
1829       if (p_tcaphash_context->contcall->next_contcall) {
1830         if (p_tcaphash_context->contcall->previous_contcall ) {
1831 #ifdef DEBUG_TCAPSRT
1832           dbg(20,"deplace Chash ");
1833 #endif
1834           p_tcaphash_context->contcall->previous_contcall->next_contcall
1835             = p_tcaphash_context->contcall->next_contcall;
1836           p_tcaphash_context->contcall->next_contcall->previous_contcall
1837             = p_tcaphash_context->contcall->previous_contcall;
1838           g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1839 #ifdef MEM_TCAPSRT
1840           g_free(p_tcaphash_context->contcall);
1841 #endif
1842         } else {
1843           /* cannot remove the father */
1844 #ifdef DEBUG_TCAPSRT
1845           dbg(20,"father Chash ");
1846 #endif
1847         } /* no previous link, so father */
1848       } else if (!gtcap_PersistentSRT) {
1849 #ifdef DEBUG_TCAPSRT
1850         dbg(20,"remove Chash ");
1851 #endif
1852         g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1853 #ifdef MEM_TCAPSRT
1854         g_free(p_tcaphash_context->contcall->contkey);
1855         g_free(p_tcaphash_context->contcall);
1856 #endif
1857       } /* contcall without chained string */
1858     } /* no contcall */
1859
1860
1861     /* If the beginkey is present */
1862     if (p_tcaphash_context->begincall
1863         && !gtcap_PersistentSRT) {
1864       if (p_tcaphash_context->begincall->next_begincall) {
1865         if (p_tcaphash_context->begincall->previous_begincall ) {
1866 #ifdef DEBUG_TCAPSRT
1867           dbg(20,"deplace Bhash ");
1868 #endif
1869           p_tcaphash_context->begincall->previous_begincall->next_begincall
1870             = p_tcaphash_context->begincall->next_begincall;
1871           p_tcaphash_context->begincall->next_begincall->previous_begincall
1872             = p_tcaphash_context->begincall->previous_begincall;
1873           g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1874 #ifdef MEM_TCAPSRT
1875           g_free(p_tcaphash_context->begincall);
1876 #endif
1877         } else {
1878           /* cannot remove the father */
1879 #ifdef DEBUG_TCAPSRT
1880           dbg(20,"father Bhash ");
1881 #endif
1882         }
1883       } else  if (!gtcap_PersistentSRT) {
1884 #ifdef DEBUG_TCAPSRT
1885         dbg(20,"remove Bhash ");
1886 #endif
1887         g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1888 #ifdef MEM_TCAPSRT
1889         g_free(p_tcaphash_context->begincall->beginkey);
1890         g_free(p_tcaphash_context->begincall);
1891 #endif
1892       } /* begincall without chained string */
1893     } /* no begincall */
1894
1895     /* If the ansikey is present */
1896     if (p_tcaphash_context->ansicall
1897         && !gtcap_PersistentSRT) {
1898       if (p_tcaphash_context->ansicall->next_ansicall) {
1899         if (p_tcaphash_context->ansicall->previous_ansicall ) {
1900 #ifdef DEBUG_TCAPSRT
1901           dbg(20,"deplace Ahash ");
1902 #endif
1903           p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
1904             = p_tcaphash_context->ansicall->next_ansicall;
1905           p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
1906             = p_tcaphash_context->ansicall->previous_ansicall;
1907           g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1908 #ifdef MEM_TCAPSRT
1909           g_free(p_tcaphash_context->ansicall);
1910 #endif
1911         } else {
1912           /* cannot remove the father */
1913 #ifdef DEBUG_TCAPSRT
1914           dbg(20,"father Ahash ");
1915 #endif
1916         }
1917       } else  if (!gtcap_PersistentSRT) {
1918 #ifdef DEBUG_TCAPSRT
1919         dbg(20,"remove Ahash ");
1920 #endif
1921         g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1922 #ifdef MEM_TCAPSRT
1923         g_free(p_tcaphash_context->ansicall->ansikey);
1924         g_free(p_tcaphash_context->ansicall);
1925 #endif
1926       } /* ansicall without chained string */
1927     } /* no ansicall */
1928
1929     if (!gtcap_PersistentSRT) {
1930 #ifdef DEBUG_TCAPSRT
1931       dbg(20,"remove context ");
1932 #endif
1933       g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
1934 #ifdef MEM_TCAPSRT
1935       g_free(p_tcaphash_context->key);
1936       g_free(p_tcaphash_context);
1937 #endif
1938     }
1939   } else { /* no context */
1940 #ifdef DEBUG_TCAPSRT
1941     dbg(20,"No context to remove ");
1942 #endif
1943   }
1944 }