Use val_to_str_const().
[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-tables and mem_chunks for SRT */
894   if (tcaphash_context != NULL) {
895 #ifdef DEBUG_TCAPSRT
896     dbg(16,"Destroy hash_context ");
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 ");
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 ");
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 ");
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 ");
925 #endif
926     g_hash_table_destroy(tcaphash_ansi);
927   }
928
929 #ifdef DEBUG_TCAPSRT
930   dbg(16,"Create hash ");
931 #endif
932   /* create new hash-tables and mem_chunks 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,"TC_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,"TC_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,"TC_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,"TC_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,"TC_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,"Unknown %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 ",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             p_tcaphash_begincall=p_new_tcaphash_begincall;
1118           } else { /* timeout or message lost */
1119
1120           /* If the Tid is reused for a closed Transaction */
1121           /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
1122           /* (this is the case, for pre-arranged END, the transaction is marked as closed */
1123           /* by the upper layer, thank to a callback method close) */
1124           if ( p_tcaphash_begincall->context->closed) {
1125 #ifdef DEBUG_TCAPSRT
1126             dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
1127             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
1128 #endif
1129             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1130             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1131             p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
1132                                                                  p_tcaphash_context,
1133                                                                  pinfo);
1134
1135 #ifdef DEBUG_TCAPSRT
1136             dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
1137 #endif
1138             update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
1139             p_tcaphash_begincall=p_new_tcaphash_begincall;
1140
1141           } else {
1142             /* the TCAP session is not closed, so, either messages have been lost */
1143             /* or it's a duplicate request. Mark it as such. */
1144 #ifdef DEBUG_TCAPSRT
1145             dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
1146 #endif
1147             p_tcaphash_context=p_tcaphash_begincall->context;
1148             if (gtcap_DisplaySRT && tree) {
1149               stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1150               PROTO_ITEM_SET_GENERATED(stat_item);
1151               stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1152               pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
1153                                               p_tcaphash_context->first_frame,
1154                                               "Duplicate with session %u in frame %u",
1155                                               p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
1156               PROTO_ITEM_SET_GENERATED(pi);
1157             }
1158             return p_tcaphash_context;
1159           } /* Previous session closed */
1160         } /* test with Timeout or message Lost */
1161         break;
1162       } /* Next call is NULL */
1163       /* Repeat the tests for the next record with the same transaction identifier */
1164       p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
1165     } while (p_tcaphash_begincall != NULL );
1166     /*
1167      * End of analyze for the list be TC_BEGIN with same transaction ID
1168      */
1169   } else { /* p_tcaphash_begincall has not been found */
1170     /*
1171      * Create a new TCAP context
1172      */
1173 #ifdef DEBUG_TCAPSRT
1174     dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
1175 #endif
1176
1177     tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1178     p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1179     p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
1180
1181 #ifdef DEBUG_TCAPSRT
1182     dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
1183     dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1184 #endif
1185     update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
1186   }
1187
1188   /* display tcap session, if available */
1189   if ( gtcap_DisplaySRT && tree &&
1190        p_tcaphash_context &&
1191        p_tcaphash_context->session_id) {
1192     stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
1193     PROTO_ITEM_SET_GENERATED(stat_item);
1194     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1195     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1196     PROTO_ITEM_SET_GENERATED(pi);
1197
1198     /* add link to response frame, if available */
1199     /* p_tcaphash_begincall->context->last_frame) */
1200     if( p_tcaphash_context->last_frame != 0 ){
1201 #ifdef DEBUG_TCAPSRT
1202       dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
1203 #endif
1204       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1205                                       p_tcaphash_context->last_frame,
1206                                       "End of session in frame %u",
1207                                       p_tcaphash_context->last_frame);
1208       PROTO_ITEM_SET_GENERATED(pi);
1209     }
1210   }
1211   return p_tcaphash_context;
1212 }
1213
1214
1215 /*
1216 * Try to find a TCAP session according to the source and destination
1217 * Identifier given in the TC_CONT
1218 * If nothing is found, it is probably a session in opening state, so try to find
1219 * a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
1220 * Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
1221 * and display the available info for the TCAP context
1222 */
1223 static struct tcaphash_context_t *
1224 tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1225                        struct tcapsrt_info_t *p_tcapsrt_info)
1226 {
1227   struct tcaphash_context_t *p_tcaphash_context=NULL;
1228   struct tcaphash_contcall_t *p_tcaphash_contcall;
1229   struct tcaphash_cont_info_key_t tcaphash_cont_key;
1230   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1231   struct tcaphash_begincall_t *p_tcaphash_begincall;
1232   struct tcaphash_end_info_key_t tcaphash_end_key;
1233   proto_item *pi;
1234   proto_item *stat_item=NULL;
1235   proto_tree *stat_tree=NULL;
1236
1237 #ifdef DEBUG_TCAPSRT
1238   dbg(10,"\n Hcont #%u ", pinfo->fd->num);
1239 #endif
1240
1241   /* look only for matching request, if matching conversation is available. */
1242   tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
1243   tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
1244   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1245   {
1246     /* We have MTP3 PCs (so we can safely do this cast) */
1247     tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1248     tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1249   } else {
1250     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1251     tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1252     tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1253   }
1254   tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1255
1256 #ifdef DEBUG_TCAPSRT
1257   dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1258   dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1259   dbg(51,"Tid %lx %lx ",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1260 #endif
1261   p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1262   if(p_tcaphash_contcall) {
1263 #ifdef DEBUG_TCAPSRT
1264     dbg(12,"CFound ");
1265 #endif
1266     p_tcaphash_context=p_tcaphash_contcall->context;
1267   } else { /* cont not found */
1268 #ifdef DEBUG_TCAPSRT
1269     dbg(12,"CnotFound ");
1270 #endif
1271     /* Find the TCAP transaction according to the TC_BEGIN */
1272     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1273     if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1274     {
1275       /* We have MTP3 PCs (so we can safely do this cast) */
1276       tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1277       tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1278     } else {
1279       /* Don't have MTP3 PCs (maybe we're over SUA?) */
1280       tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1281       tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1282     }
1283     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1284
1285 #ifdef DEBUG_TCAPSRT
1286     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1287     dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1288     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1289 #endif
1290     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1291     if(p_tcaphash_begincall &&
1292        !p_tcaphash_begincall->context->contcall ) {
1293 #ifdef DEBUG_TCAPSRT
1294       dbg(12,"BFound ");
1295 #endif
1296       p_tcaphash_context=p_tcaphash_begincall->context;
1297       p_tcaphash_context->responded=TRUE;
1298
1299 #ifdef DEBUG_TCAPSRT
1300       dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1301       dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1302 #endif
1303       create_tcaphash_cont(&tcaphash_cont_key,
1304                            p_tcaphash_begincall->context);
1305
1306       tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
1307       if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1308       {
1309         /* We have MTP3 PCs (so we can safely do this cast) */
1310         tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1311         tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1312       } else {
1313         /* Don't have MTP3 PCs (maybe we're over SUA?) */
1314         tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1315         tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1316       }
1317       tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1318
1319 #ifdef DEBUG_TCAPSRT
1320       dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1321       dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1322 #endif
1323       create_tcaphash_end(&tcaphash_end_key,
1324                           p_tcaphash_begincall->context);
1325
1326     } else { /* Begin not found */
1327 #ifdef DEBUG_TCAPSRT
1328       dbg(12,"BnotFound ");
1329 #endif
1330     } /* begin found */
1331   } /* cont found */
1332     /* display tcap session, if available */
1333   if (gtcap_DisplaySRT && tree &&
1334       p_tcaphash_context &&
1335       p_tcaphash_context->session_id) {
1336     stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1337     PROTO_ITEM_SET_GENERATED(stat_item);
1338     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1339     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1340     PROTO_ITEM_SET_GENERATED(pi);
1341   }
1342
1343   return p_tcaphash_context;
1344 }
1345
1346 /*
1347 * Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
1348 * If nothing is found,
1349 * - either it is a session in opening state,
1350 * - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
1351 * so try to find a tcap session registered with a TC_BEGIN "key",
1352 * matching the destination Id of the TC_END
1353 * Then associate the TC_CONT "key" to the TCAP context
1354 * and display the available info for the TCAP context
1355 */
1356
1357 static struct tcaphash_context_t *
1358 tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1359                       struct tcapsrt_info_t *p_tcapsrt_info)
1360 {
1361   struct tcaphash_context_t *p_tcaphash_context=NULL;
1362
1363   struct tcaphash_end_info_key_t tcaphash_end_key;
1364   struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
1365
1366   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1367   struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
1368   proto_item *pi;
1369   nstime_t delta;
1370   proto_item *stat_item=NULL;
1371   proto_tree *stat_tree=NULL;
1372
1373 #ifdef DEBUG_TCAPSRT
1374   dbg(10,"\n Hend #%u ", pinfo->fd->num);
1375 #endif
1376   /* look only for matching request, if matching conversation is available. */
1377   tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1378   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1379   {
1380     /* We have MTP3 PCs (so we can safely do this cast) */
1381     tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1382     tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1383   } else {
1384     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1385     tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1386     tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1387   }
1388   tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1389
1390 #ifdef DEBUG_TCAPSRT
1391   dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1392   dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1393   dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1394 #endif
1395   p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
1396
1397   if(!p_tcaphash_endcall) {
1398 #ifdef DEBUG_TCAPSRT
1399     dbg(12,"EnotFound ");
1400 #endif
1401     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1402     if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1403     {
1404       /* We have MTP3 PCs (so we can safely do this cast) */
1405       tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1406       tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1407     } else {
1408       /* Don't have MTP3 PCs (maybe we're over SUA?) */
1409       tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1410       tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1411     }
1412     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1413
1414 #ifdef DEBUG_TCAPSRT
1415     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1416     dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1417     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1418 #endif
1419     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1420     if(!p_tcaphash_begincall) {
1421 #ifdef DEBUG_TCAPSRT
1422       dbg(12,"BnotFound ");
1423 #endif
1424     }
1425   }
1426   if (p_tcaphash_endcall) {
1427     /* Use the TC_BEGIN Destination reference */
1428     p_tcaphash_context=p_tcaphash_endcall->context;
1429   } else if (p_tcaphash_begincall) {
1430     /* Use the TC_BEGIN Source reference */
1431     p_tcaphash_context=p_tcaphash_begincall->context;
1432   }
1433
1434   if (p_tcaphash_context) {
1435
1436 #ifdef DEBUG_TCAPSRT
1437     dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1438 #endif
1439     if (gtcap_DisplaySRT && tree) {
1440       stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1441       PROTO_ITEM_SET_GENERATED(stat_item);
1442       stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1443
1444       pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1445       PROTO_ITEM_SET_GENERATED(pi);
1446     }
1447
1448 #ifdef DEBUG_TCAPSRT
1449     dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1450 #endif
1451     /* Indicate the frame to which this is a reply. */
1452     if (gtcap_DisplaySRT && stat_tree) {
1453       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1454                                       p_tcaphash_context->first_frame,
1455                                       "Begin of session in frame %u",
1456                                       p_tcaphash_context->first_frame);
1457       PROTO_ITEM_SET_GENERATED(pi);
1458       /* Calculate Service Response Time */
1459       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1460
1461       /* display Service Response Time and make it filterable */
1462       pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1463       PROTO_ITEM_SET_GENERATED(pi);
1464     }
1465     /* Close the context and remove it (if needed) */
1466     tcapsrt_close(p_tcaphash_context,pinfo);
1467
1468   } else {/* context present */
1469 #ifdef DEBUG_TCAPSRT
1470     dbg(12,"Context notFound ");
1471 #endif
1472   }
1473   return p_tcaphash_context;
1474 }
1475
1476 /*
1477  * ANSI PART
1478  * Create the record identifiying the TCAP transaction
1479  * When the identifier for the transaction is reused, check
1480  * the following criteria before to append a new record:
1481  * - a timeout corresponding to a message retransmission is detected,
1482  * - a message hast been lost
1483  * - or the previous transaction has been  be closed
1484  */
1485 static struct tcaphash_context_t *
1486 tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1487                        struct tcapsrt_info_t *p_tcapsrt_info)
1488 {
1489   struct tcaphash_context_t *p_tcaphash_context=NULL;
1490   struct tcaphash_context_key_t tcaphash_context_key;
1491   struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
1492   struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
1493   proto_item *pi;
1494   nstime_t delta;
1495   gboolean isResponse=FALSE;
1496   proto_tree * stat_tree=NULL;
1497   proto_item * stat_item=NULL;
1498
1499   /* prepare the key data */
1500   tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
1501   if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
1502   {
1503     /* We have MTP3 PCs (so we can safely do this cast) */
1504     tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1505     tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1506   } else {
1507     /* Don't have MTP3 PCs (maybe we're over SUA?) */
1508     tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
1509     tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
1510   }
1511   tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
1512
1513   /* look up the request */
1514 #ifdef DEBUG_TCAPSRT
1515   dbg(10,"\n Hansi #%u ", pinfo->fd->num);
1516   dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
1517   dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
1518   dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
1519 #endif
1520   p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
1521     g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
1522
1523   if (p_tcaphash_ansicall) {
1524     /* Walk through list of transaction with identical keys */
1525     do {
1526       /* Check if the request with this reqSeqNum has been seen */
1527       if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
1528         /* We have seen this request before -> do nothing */
1529 #ifdef DEBUG_TCAPSRT
1530         dbg(22,"Request already seen ");
1531 #endif
1532         isResponse=FALSE;
1533         p_tcaphash_context=p_tcaphash_ansicall->context;
1534         break;
1535       }
1536
1537       /* Check if the reponse with this reqSeqNum has been seen */
1538       if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
1539         /* We have seen this response before -> do nothing */
1540 #ifdef DEBUG_TCAPSRT
1541         dbg(22,"Response already seen ");
1542 #endif
1543         isResponse=TRUE;
1544         p_tcaphash_context=p_tcaphash_ansicall->context;
1545         break;
1546       }
1547
1548       /* Check for the first Request without Response
1549        received before this frame */
1550       if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
1551            p_tcaphash_ansicall->context->last_frame==0 ) {
1552         /* Take it, and update the context */
1553
1554 #ifdef DEBUG_TCAPSRT
1555         dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1556 #endif
1557         p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
1558         p_tcaphash_ansicall->context->responded = TRUE;
1559         p_tcaphash_ansicall->context->closed = TRUE;
1560         p_tcaphash_context=p_tcaphash_ansicall->context;
1561         isResponse=TRUE;
1562
1563         if (gtcap_DisplaySRT && tree) {
1564           stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1565           PROTO_ITEM_SET_GENERATED(stat_item);
1566           stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1567
1568           pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1569           PROTO_ITEM_SET_GENERATED(pi);
1570
1571 #ifdef DEBUG_TCAPSRT
1572           dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1573 #endif
1574           /* Indicate the frame to which this is a reply. */
1575           pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1576                                           p_tcaphash_context->first_frame,
1577                                           "Begin of session in frame %u",
1578                                           p_tcaphash_context->first_frame);
1579           PROTO_ITEM_SET_GENERATED(pi);
1580           /* Calculate Service Response Time */
1581           nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1582
1583           /* display Service Response Time and make it filterable */
1584           pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1585           PROTO_ITEM_SET_GENERATED(pi);
1586         }
1587         break;
1588       } /* Lastframe=0, so take it */
1589
1590
1591       /* If the last record for Tcap transaction with identifier has been reached */
1592       if (!p_tcaphash_ansicall->next_ansicall) {
1593         /* check if we have to create a new record or not */
1594         /* if last request has been responded (response number in known)
1595            and this request appears after last response (has bigger frame number)
1596            and last request occured after the timeout for repetition,
1597            or
1598            if last request hasn't been responded (so number unknown)
1599            and this request appears after last request (has bigger frame number)
1600            and this request occured after the timeout for message lost */
1601         if ( ( p_tcaphash_ansicall->context->last_frame != 0
1602                && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1603                && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
1604                ) ||
1605              ( p_tcaphash_ansicall->context->last_frame == 0
1606                && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
1607                && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
1608                )
1609              )
1610           {
1611             /* we decide that we have a new request */
1612             /* Append new record to the list */
1613 #ifdef DEBUG_TCAPSRT
1614             dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
1615             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1616 #endif
1617             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1618             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1619             p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1620                                                                  p_tcaphash_context,
1621                                                                  pinfo);
1622
1623 #ifdef DEBUG_TCAPSRT
1624             dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1625 #endif
1626             update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1627             p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1628           } else {
1629
1630           /* If the Tid is reused for a closed Transaction */
1631           if ( p_tcaphash_ansicall->context->closed) {
1632 #ifdef DEBUG_TCAPSRT
1633             dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
1634             dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
1635 #endif
1636             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1637             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1638             p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1639                                                                  p_tcaphash_context,
1640                                                                  pinfo);
1641
1642 #ifdef DEBUG_TCAPSRT
1643             dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
1644 #endif
1645             update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1646             p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1647
1648           } else {
1649             /* the Tid is reused for an opened Transaction */
1650             /* so, this is the reply to the request of our context */
1651             p_tcaphash_context=p_tcaphash_ansicall->context;
1652 #ifdef DEBUG_TCAPSRT
1653             dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1654 #endif
1655
1656             if (gtcap_DisplaySRT && tree) {
1657               stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1658               PROTO_ITEM_SET_GENERATED(stat_item);
1659               stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1660
1661               pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1662               PROTO_ITEM_SET_GENERATED(pi);
1663
1664 #ifdef DEBUG_TCAPSRT
1665               dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1666 #endif
1667               /* Indicate the frame to which this is a reply. */
1668               pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1669                                               p_tcaphash_context->first_frame,
1670                                               "Begin of session in frame %u",
1671                                               p_tcaphash_context->first_frame);
1672               PROTO_ITEM_SET_GENERATED(pi);
1673               /* Calculate Service Response Time */
1674               nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1675
1676               /* display Service Response Time and make it filterable */
1677               pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1678               PROTO_ITEM_SET_GENERATED(pi);
1679             }
1680             p_tcaphash_context=p_tcaphash_ansicall->context;
1681           } /* test with Timeout */
1682         } /* closed */
1683         break;
1684       } /* Next call is NULL */
1685       p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
1686     } while (p_tcaphash_ansicall != NULL );
1687     /*
1688      * New TCAP context
1689      */
1690   } else { /* p_tcaphash_ansicall has not been found */
1691 #ifdef DEBUG_TCAPSRT
1692     dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
1693 #endif
1694
1695     tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1696     p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1697     p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
1698
1699 #ifdef DEBUG_TCAPSRT
1700     dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
1701     dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
1702 #endif
1703     update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
1704   }
1705
1706   /* display tcap session, if available */
1707   if ( gtcap_DisplaySRT && tree &&
1708        p_tcaphash_context &&
1709        p_tcaphash_context->session_id) {
1710     stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
1711     PROTO_ITEM_SET_GENERATED(stat_item);
1712     stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
1713     pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1714     PROTO_ITEM_SET_GENERATED(pi);
1715   }
1716
1717
1718   /* add link to response frame, if available */
1719   if( gtcap_DisplaySRT && stat_tree &&
1720       p_tcaphash_ansicall->context->last_frame != 0){
1721     if (!isResponse) { /* Request */
1722 #ifdef DEBUG_TCAPSRT
1723       dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
1724 #endif
1725       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1726                                       p_tcaphash_ansicall->context->last_frame,
1727                                       "End of session in frame %u",
1728                                       p_tcaphash_ansicall->context->last_frame);
1729       PROTO_ITEM_SET_GENERATED(pi);
1730     } else { /* Response */
1731 #ifdef DEBUG_TCAPSRT
1732       dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1733 #endif
1734       /* Indicate the frame to which this is a reply. */
1735       if (gtcap_DisplaySRT) {
1736         pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1737                                         p_tcaphash_context->first_frame,
1738                                         "Begin of session in frame %u",
1739                                         p_tcaphash_context->first_frame);
1740         PROTO_ITEM_SET_GENERATED(pi);
1741         /* Calculate Service Response Time */
1742         nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1743
1744         /* display Service Response Time and make it filterable */
1745         pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1746         PROTO_ITEM_SET_GENERATED(pi);
1747       }
1748     } /* Request or Response */
1749   }
1750   return p_tcaphash_context;
1751 }
1752
1753
1754 /*
1755  * Initialize the Message Info used by the main dissector
1756  * Data are linked to a TCAP transaction
1757  */
1758 struct tcapsrt_info_t *
1759 tcapsrt_razinfo(void)
1760 {
1761   struct tcapsrt_info_t *p_tcapsrt_info ;
1762
1763   /* Global buffer for packet extraction */
1764   tcapsrt_global_current++;
1765   if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1766     tcapsrt_global_current=0;
1767   }
1768
1769   p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1770   memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
1771
1772   return p_tcapsrt_info;
1773 }
1774
1775 void
1776 tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
1777               packet_info *pinfo)
1778 {
1779 #ifdef DEBUG_TCAPSRT
1780   dbg(60,"Force close ");
1781 #endif
1782   if (p_tcaphash_context) {
1783     p_tcaphash_context->responded=TRUE;
1784     p_tcaphash_context->last_frame = pinfo->fd->num;
1785     p_tcaphash_context->end_time = pinfo->fd->abs_ts;
1786     p_tcaphash_context->closed=TRUE;
1787
1788     /* If the endkey is present */
1789     if (p_tcaphash_context->endcall
1790         && !gtcap_PersistentSRT) {
1791       if (p_tcaphash_context->endcall->next_endcall) {
1792         if (p_tcaphash_context->endcall->previous_endcall ) {
1793 #ifdef DEBUG_TCAPSRT
1794           dbg(20,"deplace Ehash ");
1795 #endif
1796           p_tcaphash_context->endcall->previous_endcall->next_endcall
1797             = p_tcaphash_context->endcall->next_endcall;
1798           p_tcaphash_context->endcall->next_endcall->previous_endcall
1799             = p_tcaphash_context->endcall->previous_endcall;
1800           g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1801 #ifdef MEM_TCAPSRT
1802           g_free(p_tcaphash_context->endcall);
1803 #endif
1804         } else {
1805           /* cannot remove the father */
1806 #ifdef DEBUG_TCAPSRT
1807           dbg(20,"father Ehash ");
1808 #endif
1809         } /* no previous link, so father */
1810       } else if (!gtcap_PersistentSRT) {
1811 #ifdef DEBUG_TCAPSRT
1812         dbg(20,"remove Ehash ");
1813 #endif
1814         g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1815 #ifdef MEM_TCAPSRT
1816         g_free(p_tcaphash_context->endcall->endkey);
1817         g_free(p_tcaphash_context->endcall);
1818 #endif
1819
1820       } /* endcall without chained string */
1821     } /* no endcall */
1822
1823
1824     /* If the contkey is present */
1825     if (p_tcaphash_context->contcall
1826         && !gtcap_PersistentSRT) {
1827       if (p_tcaphash_context->contcall->next_contcall) {
1828         if (p_tcaphash_context->contcall->previous_contcall ) {
1829 #ifdef DEBUG_TCAPSRT
1830           dbg(20,"deplace Chash ");
1831 #endif
1832           p_tcaphash_context->contcall->previous_contcall->next_contcall
1833             = p_tcaphash_context->contcall->next_contcall;
1834           p_tcaphash_context->contcall->next_contcall->previous_contcall
1835             = p_tcaphash_context->contcall->previous_contcall;
1836           g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1837 #ifdef MEM_TCAPSRT
1838           g_free(p_tcaphash_context->contcall);
1839 #endif
1840         } else {
1841           /* cannot remove the father */
1842 #ifdef DEBUG_TCAPSRT
1843           dbg(20,"father Chash ");
1844 #endif
1845         } /* no previous link, so father */
1846       } else if (!gtcap_PersistentSRT) {
1847 #ifdef DEBUG_TCAPSRT
1848         dbg(20,"remove Chash ");
1849 #endif
1850         g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1851 #ifdef MEM_TCAPSRT
1852         g_free(p_tcaphash_context->contcall->contkey);
1853         g_free(p_tcaphash_context->contcall);
1854 #endif
1855       } /* contcall without chained string */
1856     } /* no contcall */
1857
1858
1859     /* If the beginkey is present */
1860     if (p_tcaphash_context->begincall
1861         && !gtcap_PersistentSRT) {
1862       if (p_tcaphash_context->begincall->next_begincall) {
1863         if (p_tcaphash_context->begincall->previous_begincall ) {
1864 #ifdef DEBUG_TCAPSRT
1865           dbg(20,"deplace Bhash ");
1866 #endif
1867           p_tcaphash_context->begincall->previous_begincall->next_begincall
1868             = p_tcaphash_context->begincall->next_begincall;
1869           p_tcaphash_context->begincall->next_begincall->previous_begincall
1870             = p_tcaphash_context->begincall->previous_begincall;
1871           g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1872 #ifdef MEM_TCAPSRT
1873           g_free(p_tcaphash_context->begincall);
1874 #endif
1875         } else {
1876           /* cannot remove the father */
1877 #ifdef DEBUG_TCAPSRT
1878           dbg(20,"father Bhash ");
1879 #endif
1880         }
1881       } else  if (!gtcap_PersistentSRT) {
1882 #ifdef DEBUG_TCAPSRT
1883         dbg(20,"remove Bhash ");
1884 #endif
1885         g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1886 #ifdef MEM_TCAPSRT
1887         g_free(p_tcaphash_context->begincall->beginkey);
1888         g_free(p_tcaphash_context->begincall);
1889 #endif
1890       } /* begincall without chained string */
1891     } /* no begincall */
1892
1893     /* If the ansikey is present */
1894     if (p_tcaphash_context->ansicall
1895         && !gtcap_PersistentSRT) {
1896       if (p_tcaphash_context->ansicall->next_ansicall) {
1897         if (p_tcaphash_context->ansicall->previous_ansicall ) {
1898 #ifdef DEBUG_TCAPSRT
1899           dbg(20,"deplace Ahash ");
1900 #endif
1901           p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
1902             = p_tcaphash_context->ansicall->next_ansicall;
1903           p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
1904             = p_tcaphash_context->ansicall->previous_ansicall;
1905           g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1906 #ifdef MEM_TCAPSRT
1907           g_free(p_tcaphash_context->ansicall);
1908 #endif
1909         } else {
1910           /* cannot remove the father */
1911 #ifdef DEBUG_TCAPSRT
1912           dbg(20,"father Ahash ");
1913 #endif
1914         }
1915       } else  if (!gtcap_PersistentSRT) {
1916 #ifdef DEBUG_TCAPSRT
1917         dbg(20,"remove Ahash ");
1918 #endif
1919         g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1920 #ifdef MEM_TCAPSRT
1921         g_free(p_tcaphash_context->ansicall->ansikey);
1922         g_free(p_tcaphash_context->ansicall);
1923 #endif
1924       } /* ansicall without chained string */
1925     } /* no ansicall */
1926
1927     if (!gtcap_PersistentSRT) {
1928 #ifdef DEBUG_TCAPSRT
1929       dbg(20,"remove context ");
1930 #endif
1931       g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
1932 #ifdef MEM_TCAPSRT
1933       g_free(p_tcaphash_context->key);
1934       g_free(p_tcaphash_context);
1935 #endif
1936     }
1937   } else { /* no context */
1938 #ifdef DEBUG_TCAPSRT
1939     dbg(20,"No context to remove ");
1940 #endif
1941   }
1942 }