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