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