The UAT gui starts to work
[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  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "epan/emem.h"
35 #include "epan/packet.h"
36 #include "epan/conversation.h"
37 #include "epan/tcap-persistentdata.h"
38 #include "epan/dissectors/packet-tcap.h"
39 #include "epan/dissectors/packet-mtp3.h"
40
41 static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
42 static guint tcaphash_context_calchash(gconstpointer k);
43 static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
44 static guint tcaphash_begin_calchash(gconstpointer k);
45 static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
46 static guint tcaphash_cont_calchash(gconstpointer k);
47 static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
48 static guint tcaphash_end_calchash(gconstpointer k);
49
50 static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
51                                       packet_info *pinfo );
52
53 static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
54                                                                struct tcaphash_context_t * p_tcaphash_context,
55                                                                packet_info *pinfo);
56
57
58 static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
59                                                          packet_info *pinfo,
60                                                          gboolean isBegin);
61
62
63 static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
64                                                        packet_info *pinfo);
65
66 static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
67                                                      packet_info *pinfo,
68                                                      gboolean isEnd);
69 /* new key */
70 static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
71                                                         packet_info *pinfo);
72
73 static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
74                                                         struct tcaphash_context_t * p_tcaphash_context,
75                                                         packet_info *pinfo);
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                                                       packet_info *pinfo);
80
81 static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
82                                                     struct tcaphash_context_t * p_tcaphash_context,
83                                                     packet_info *pinfo);
84
85 static struct tcaphash_context_t *
86 tcaphash_begin_matching(tvbuff_t *tvb,
87                         packet_info * pinfo _U_,
88                         proto_tree *tree,
89                         struct tcapsrt_info_t * p_tcapsrt_info);
90
91 static struct tcaphash_context_t *
92 tcaphash_cont_matching(tvbuff_t *tvb,
93                        packet_info * pinfo _U_,
94                        proto_tree *tree,
95                        struct tcapsrt_info_t * p_tcapsrt_info);
96
97 static struct tcaphash_context_t *
98 tcaphash_end_matching(tvbuff_t *tvb,
99                       packet_info * pinfo _U_,
100                       proto_tree *tree,
101                       struct tcapsrt_info_t * p_tcapsrt_info);
102
103 struct tcapsrt_info_t * tcapsrt_razinfo(void);
104
105 /* When several Tcap components are received in a single TCAP message,
106    we have to use several buffers for the stored parameters
107    because else this data are erased during TAP dissector call */
108 #define MAX_TCAP_INSTANCE 10
109 int tcapsrt_global_current=0;
110 struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
111
112 /* These two timeout (in second) are used when some message are lost,
113    or when the same TCAP transcation identifier is reused */
114 guint gtcap_RepetitionTimeout = 10;
115 guint gtcap_LostTimeout = 30;
116 extern gboolean gtcap_HandleSRT;
117 gboolean gtcap_PersistentSRT=FALSE;
118 gboolean gtcap_DisplaySRT=FALSE;
119 gboolean gtcap_StatSRT=FALSE;
120
121 extern int hf_tcapsrt_SessionId;
122 extern int hf_tcapsrt_Duplicate;
123 extern int hf_tcapsrt_BeginSession;
124 extern int hf_tcapsrt_EndSession;
125 extern int hf_tcapsrt_SessionTime;
126
127 /* Global hash tables*/
128 static GHashTable * tcaphash_context = NULL;
129 static GHashTable * tcaphash_begin = NULL;
130 static GHashTable * tcaphash_cont = NULL;
131 static GHashTable * tcaphash_end = NULL;
132
133 guint32 tcapsrt_global_SessionId=1;
134
135 /*
136  * DEBUG fonctions
137  */
138
139 #undef DEBUG_TCAPSRT
140 /* #define DEBUG_TCAPSRT */
141
142 #ifdef DEBUG_TCAPSRT
143 #include <stdio.h>
144 #include <stdarg.h>
145 static unsigned debug_level = 99;
146
147 static void dbg(unsigned  level, char* fmt, ...) {
148   va_list ap;
149   
150   if (level > debug_level) return;
151   va_start(ap,fmt);
152   vfprintf(stderr, fmt, ap);
153   va_end(ap);
154 }
155 #endif
156
157 static gint 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 tcaphash_context_calchash(gconstpointer k)
167 {
168   const struct tcaphash_context_key_t * key = (const struct tcaphash_context_key_t *) k;
169   return key->session_id;
170 }
171
172
173 static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
174 {
175   const struct tcaphash_begin_info_key_t * key1 = (const struct tcaphash_begin_info_key_t *) k1;
176   const struct tcaphash_begin_info_key_t * key2 = (const struct tcaphash_begin_info_key_t *) k2;
177
178   if (key1->hashKey == key2->hashKey) {
179     
180     if ( ( (key1->opc_hash == key2->opc_hash) &&
181            (key1->dpc_hash == key2->dpc_hash) &&
182            (key1->tid == key2->tid) ) 
183          ||
184          ( (key1->opc_hash == key2->dpc_hash) &&
185            (key1->dpc_hash == key2->opc_hash) &&
186            (key1->tid == key2->tid) ) 
187          )
188       return TRUE;
189   }
190   return FALSE;
191 }
192
193 /* calculate a hash key */
194 static guint tcaphash_begin_calchash(gconstpointer k)
195 {
196   const struct tcaphash_begin_info_key_t * key = (const struct tcaphash_begin_info_key_t *) k;
197   guint hashkey;
198   /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
199   hashkey = key->tid;
200   return hashkey;
201 }
202
203 static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
204 {
205   const struct tcaphash_cont_info_key_t * key1 = (const struct tcaphash_cont_info_key_t *) k1;
206   const struct tcaphash_cont_info_key_t * key2 = (const struct tcaphash_cont_info_key_t *) k2;
207
208   if (key1->hashKey == key2->hashKey) {
209
210     if ( (key1->opc_hash == key2->opc_hash) &&
211          (key1->dpc_hash == key2->dpc_hash) &&
212          (key1->src_tid == key2->src_tid) &&
213          (key1->dst_tid == key2->dst_tid) ) {
214       return TRUE;
215     } 
216     else if ( (key1->opc_hash == key2->dpc_hash) &&
217               (key1->dpc_hash == key2->opc_hash) &&
218               (key1->src_tid == key2->dst_tid) &&
219               (key1->dst_tid == key2->src_tid) ) {
220       return TRUE;
221     }
222   }
223   return FALSE;
224 }
225
226 /* calculate a hash key */
227 static guint tcaphash_cont_calchash(gconstpointer k)
228 {
229   const struct tcaphash_cont_info_key_t * key = (const struct tcaphash_cont_info_key_t *) k;
230   guint hashkey;
231   hashkey = key->src_tid + key->dst_tid;
232   return hashkey;
233 }
234
235
236 static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
237 {
238   const struct tcaphash_end_info_key_t * key1 = (const struct tcaphash_end_info_key_t *) k1;
239   const struct tcaphash_end_info_key_t * key2 = (const struct tcaphash_end_info_key_t *) k2;
240
241   if (key1->hashKey == key2->hashKey) {
242     if ( ( (key1->opc_hash == key2->opc_hash) &&
243            (key1->dpc_hash == key2->dpc_hash) &&
244            (key1->tid == key2->tid) ) 
245          ||
246          ( (key1->opc_hash == key2->dpc_hash) &&
247            (key1->dpc_hash == key2->opc_hash) &&
248            (key1->tid == key2->tid) ) ) 
249       return TRUE;
250   }
251   return FALSE;
252 }
253
254 /* calculate a hash key */
255 static guint tcaphash_end_calchash(gconstpointer k)
256 {
257   const struct tcaphash_end_info_key_t * key = (const struct tcaphash_end_info_key_t *) k;
258   guint hashkey;
259   hashkey = key->tid;
260   return hashkey;
261 }
262
263 /* 
264  * Update a record with the data of the Request 
265  */
266 static void update_tcaphash_begincall(struct tcaphash_begincall_t * p_tcaphash_begincall,
267                                       packet_info *pinfo )
268 {
269   p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
270   p_tcaphash_begincall->context->last_frame = 0;
271   p_tcaphash_begincall->context->responded = FALSE;
272   p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
273 }
274
275 /* 
276  * Append a new dialogue, using the same Key, to the chained list
277  * The time is stored too 
278  */
279 static struct tcaphash_begincall_t * append_tcaphash_begincall(struct tcaphash_begincall_t * prev_begincall,
280                                                                struct tcaphash_context_t * p_tcaphash_context,
281                                                                packet_info *pinfo)
282   
283 {
284   struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
285   
286   /* Append the transaction to the list, when the same key is found
287      This should append when the tcap-transaction Id is reused  */
288
289   p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
290   p_new_tcaphash_begincall->context=p_tcaphash_context;
291   p_tcaphash_context->begincall=p_new_tcaphash_begincall;
292   p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
293   p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
294   p_new_tcaphash_begincall->next_begincall=NULL; 
295   p_new_tcaphash_begincall->previous_begincall=prev_begincall;
296   p_new_tcaphash_begincall->father=FALSE;
297
298 #ifdef DEBUG_TCAPSRT
299   dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
300 #endif
301   /* Insert in the chained list */
302   prev_begincall->next_begincall = p_new_tcaphash_begincall;
303   if (prev_begincall->context->last_frame == 0) {
304 #ifdef DEBUG_TCAPSRT
305     dbg(10,"last ");
306 #endif
307     prev_begincall->context->last_frame = pinfo->fd->num-1;
308   }
309   return p_new_tcaphash_begincall;
310 }
311
312 static struct tcaphash_contcall_t * append_tcaphash_contcall(struct tcaphash_contcall_t * prev_contcall,
313                                                              struct tcaphash_context_t * p_tcaphash_context,
314                                                              packet_info *pinfo)
315   
316 {
317   struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
318   
319   /* Append the transaction to the list, when the same key is found
320      This should append when the tcap-transaction Id is reused  */
321   
322   p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
323   p_new_tcaphash_contcall->context=p_tcaphash_context;
324   p_tcaphash_context->contcall=p_new_tcaphash_contcall;
325   p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
326   p_new_tcaphash_contcall->next_contcall=NULL; 
327   p_new_tcaphash_contcall->previous_contcall=prev_contcall;
328   p_new_tcaphash_contcall->father=FALSE;
329
330 #ifdef DEBUG_TCAPSRT
331   dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
332 #endif
333   /* Insert in the chained list */
334   prev_contcall->next_contcall = p_new_tcaphash_contcall;
335   return p_new_tcaphash_contcall;
336 }
337
338
339 static struct tcaphash_endcall_t * append_tcaphash_endcall(struct tcaphash_endcall_t * prev_endcall,
340                                                            struct tcaphash_context_t * p_tcaphash_context,
341                                                            packet_info *pinfo)
342   
343 {
344   struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
345   
346   /* Append the transaction to the list, when the same key is found
347      This should append when the tcap-transaction Id is reused  */
348
349   p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
350   p_new_tcaphash_endcall->context=p_tcaphash_context;
351   p_tcaphash_context->endcall=p_new_tcaphash_endcall;
352   p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
353   p_new_tcaphash_endcall->next_endcall=NULL; 
354   p_new_tcaphash_endcall->previous_endcall=prev_endcall;
355   p_new_tcaphash_endcall->father=FALSE;
356
357 #ifdef DEBUG_TCAPSRT
358   dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
359 #endif
360   /* Insert in the chained list */
361   prev_endcall->next_endcall = p_new_tcaphash_endcall;
362   return p_new_tcaphash_endcall;
363 }
364
365
366 /* 
367  * Find the dialog by Key and Time 
368  */
369 static struct tcaphash_begincall_t * find_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
370                                                          packet_info *pinfo,
371                                                          gboolean isBegin)
372 {
373   struct tcaphash_begincall_t * p_tcaphash_begincall = NULL;
374   p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
375   
376   if(p_tcaphash_begincall) {
377     do {
378       if ( p_tcaphash_begincall->context ) {
379         if ( ( isBegin &&
380                pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
381              ||
382              ( !isBegin &&
383                pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
384                ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
385                ) 
386              ) {
387           /* We have a dialogue, with this key, opened before this request */
388 #ifdef DEBUG_TCAPSRT
389           dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
390 #endif
391           return p_tcaphash_begincall;
392           break;
393         }
394       }
395       /* Break when list end is reached */
396       if(p_tcaphash_begincall->next_begincall == NULL) {
397 #ifdef DEBUG_TCAPSRT
398         dbg(23,"End of Blist ");
399 #endif
400         break;
401       }
402       p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
403     } while (p_tcaphash_begincall != NULL) ;
404   } else {
405 #ifdef DEBUG_TCAPSRT
406     dbg(23,"Not in Bhash ");
407 #endif  
408   }
409   return NULL;
410 }
411
412
413
414 static struct tcaphash_contcall_t * find_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
415                                                        packet_info *pinfo)
416 {
417   struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
418   p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
419   
420   if(p_tcaphash_contcall) {
421     do {
422       if ( p_tcaphash_contcall->context &&
423            pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
424            (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
425         /* We have a dialogue, with this key, opened before this request */
426 #ifdef DEBUG_TCAPSRT
427         dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
428 #endif  
429         return p_tcaphash_contcall;
430         break;
431       } else {
432 #ifdef DEBUG_TCAPSRT
433         dbg(23,"Bug in Clist ");
434 #endif
435       }
436       /* Break when list end is reached */
437       if(p_tcaphash_contcall->next_contcall == NULL) {
438 #ifdef DEBUG_TCAPSRT
439         dbg(23,"End of Clist ");
440 #endif
441         break;
442       }
443       p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
444     } while (p_tcaphash_contcall != NULL) ;
445   } else {
446 #ifdef DEBUG_TCAPSRT
447     dbg(23,"Not in Chash ");
448 #endif
449   }  
450   return NULL;
451 }
452
453 static struct tcaphash_endcall_t * find_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
454                                                      packet_info *pinfo,
455                                                      gboolean isEnd)
456 {
457   struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
458   p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
459     
460   if(p_tcaphash_endcall) {
461     do {
462       if ( p_tcaphash_endcall->context ) {
463         if ( ( isEnd &&
464                (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1) 
465                )
466              ||
467              ( !isEnd &&
468                pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
469                (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1) 
470                )
471              ) {
472           /* We have a dialogue, with this key, opened before this request */
473 #ifdef DEBUG_TCAPSRT
474           dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
475 #endif  
476           return p_tcaphash_endcall;
477           break;
478         } else {
479 #ifdef DEBUG_TCAPSRT
480           dbg(23,"Bug in Elist ");
481 #endif
482         }
483       }
484       /* Break when list end is reached */
485       if(p_tcaphash_endcall->next_endcall == NULL) {
486 #ifdef DEBUG_TCAPSRT
487         dbg(23,"End of Elist ");
488 #endif
489         break;
490       }
491       p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
492     } while (p_tcaphash_endcall != NULL) ;
493   } else {
494 #ifdef DEBUG_TCAPSRT
495     dbg(23,"Not in Ehash ");
496 #endif
497   }  
498   return NULL;
499 }
500
501 /*
502  * New record to create, to identify a new transaction 
503  */
504 static struct tcaphash_context_t * new_tcaphash_context(struct tcaphash_context_key_t * p_tcaphash_context_key,
505                                                         packet_info *pinfo)
506 {
507   struct tcaphash_context_key_t * p_new_tcaphash_context_key;
508   struct tcaphash_context_t * p_new_tcaphash_context = NULL;
509   
510   /* Register the transaction in the hash table 
511      with the tcap transaction Id as Main Key
512      Once created, this entry will be updated later */
513
514   p_new_tcaphash_context_key = se_alloc(sizeof(struct tcaphash_context_key_t));
515   p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
516
517   p_new_tcaphash_context = se_alloc0(sizeof(struct tcaphash_context_t));
518   p_new_tcaphash_context->key = p_new_tcaphash_context_key;
519   p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
520   p_new_tcaphash_context->first_frame = pinfo->fd->num;
521 #ifdef DEBUG_TCAPSRT
522   dbg(10,"S%d ", p_new_tcaphash_context->session_id);
523 #endif
524   /* store it */
525   g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
526   return p_new_tcaphash_context;
527 }
528
529 /*
530  * New record to create, to identify a new transaction 
531  */
532 static struct tcaphash_begincall_t * new_tcaphash_begin(struct tcaphash_begin_info_key_t * p_tcaphash_begin_key,
533                                                         struct tcaphash_context_t * p_tcaphash_context,
534                                                         packet_info *pinfo)
535 {
536   struct tcaphash_begin_info_key_t * p_new_tcaphash_begin_key;
537   struct tcaphash_begincall_t * p_new_tcaphash_begincall = NULL;
538   
539   /* Register the transaction in the hash table 
540      with the tcap transaction Id as Main Key
541      Once created, this entry will be updated later */
542
543   p_new_tcaphash_begin_key = se_alloc(sizeof(struct tcaphash_begin_info_key_t));
544   p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
545   p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
546   p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
547   p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
548
549   p_new_tcaphash_begincall = se_alloc0(sizeof(struct tcaphash_begincall_t));
550   p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
551   p_new_tcaphash_begincall->context=p_tcaphash_context;
552   p_tcaphash_context->begincall=p_new_tcaphash_begincall;
553   p_new_tcaphash_begincall->father=TRUE;
554   p_new_tcaphash_begincall->next_begincall=NULL;
555   p_new_tcaphash_begincall->previous_begincall=NULL;
556
557 #ifdef DEBUG_TCAPSRT
558   dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
559 #endif
560   /* store it */
561   g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
562   return p_new_tcaphash_begincall;
563 }
564
565
566
567 /*
568  * New record to create, to identify a new transaction 
569  */
570 static struct tcaphash_contcall_t * new_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
571                                                       struct tcaphash_context_t * p_tcaphash_context,
572                                                       packet_info *pinfo)
573 {
574   struct tcaphash_cont_info_key_t * p_new_tcaphash_cont_key;
575   struct tcaphash_contcall_t * p_new_tcaphash_contcall = NULL;
576   
577   /* Register the transaction in the hash table 
578      with the tcap transaction Id as Main Key
579      Once created, this entry will be updated later */
580
581   p_new_tcaphash_cont_key = se_alloc(sizeof(struct tcaphash_cont_info_key_t));
582   p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
583   p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
584   p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
585   p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
586   p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
587   
588   p_new_tcaphash_contcall = se_alloc0(sizeof(struct tcaphash_contcall_t));
589   p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key; 
590   p_new_tcaphash_contcall->context=p_tcaphash_context;
591   p_tcaphash_context->contcall=p_new_tcaphash_contcall;
592   p_new_tcaphash_contcall->father=TRUE;
593   p_new_tcaphash_contcall->next_contcall=NULL;
594   p_new_tcaphash_contcall->previous_contcall=NULL;
595
596 #ifdef DEBUG_TCAPSRT
597   dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
598 #endif
599   /* store it */
600   g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
601   return p_new_tcaphash_contcall;
602 }
603
604
605 /*
606  * New record to create, to identify a new transaction 
607  */
608 static struct tcaphash_endcall_t * new_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
609                                                     struct tcaphash_context_t * p_tcaphash_context,
610                                                     packet_info *pinfo)
611 {
612   struct tcaphash_end_info_key_t * p_new_tcaphash_end_key;
613   struct tcaphash_endcall_t * p_new_tcaphash_endcall = NULL;
614   
615   /* Register the transaction in the hash table 
616      with the tcap transaction Id as Main Key
617      Once created, this entry will be updated later */
618
619   p_new_tcaphash_end_key = se_alloc(sizeof(struct tcaphash_end_info_key_t));
620   p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
621   p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
622   p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
623   p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
624
625   p_new_tcaphash_endcall = se_alloc0(sizeof(struct tcaphash_endcall_t));
626   p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
627   p_new_tcaphash_endcall->context=p_tcaphash_context;
628   p_tcaphash_context->endcall=p_new_tcaphash_endcall; 
629   p_new_tcaphash_endcall->father=TRUE;
630   p_new_tcaphash_endcall->next_endcall=NULL;
631   p_new_tcaphash_endcall->previous_endcall=NULL;
632   
633 #ifdef DEBUG_TCAPSRT
634   dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
635 #endif
636   /* store it */
637   g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
638   return p_new_tcaphash_endcall;
639 }
640
641
642
643 static struct tcaphash_contcall_t * 
644 create_tcaphash_cont(struct tcaphash_cont_info_key_t * p_tcaphash_cont_key,
645                      struct tcaphash_context_t * p_tcaphash_context,
646                      packet_info *pinfo)
647 {
648   struct tcaphash_contcall_t * p_tcaphash_contcall1 = NULL;
649   struct tcaphash_contcall_t * p_tcaphash_contcall = NULL;
650
651   p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
652     g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
653   
654   if (p_tcaphash_contcall1) {
655     /* Walk through list of transaction with identical keys */
656     /* go the the end to insert new record */
657     do {
658       if (!p_tcaphash_contcall1->next_contcall) {
659         p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
660                                                      p_tcaphash_context,
661                                                      pinfo);
662         break;
663       }
664       p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
665     } while (p_tcaphash_contcall1 != NULL );
666   } else {
667     p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
668                                             p_tcaphash_context,
669                                             pinfo);
670   }
671   return p_tcaphash_contcall;
672 }
673
674
675 static struct tcaphash_endcall_t * 
676 create_tcaphash_end(struct tcaphash_end_info_key_t * p_tcaphash_end_key,
677                     struct tcaphash_context_t * p_tcaphash_context,
678                     packet_info *pinfo)
679 {
680   struct tcaphash_endcall_t * p_tcaphash_endcall1 = NULL;
681   struct tcaphash_endcall_t * p_tcaphash_endcall = NULL;
682   
683   p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
684     g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
685   
686   if (p_tcaphash_endcall1) {
687     /* Walk through list of transaction with identical keys */
688     /* go the the end to insert new record */
689     do {
690       if (!p_tcaphash_endcall1->next_endcall) {
691         p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
692                                                    p_tcaphash_context,
693                                                    pinfo);
694         break;
695       }
696       p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
697     } while (p_tcaphash_endcall1 != NULL );
698   } else {
699     p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
700                                           p_tcaphash_context,
701                                           pinfo);
702   }
703   return p_tcaphash_endcall;
704 }
705
706
707 /*
708  * Routine called when the TAP is initialized.
709  * so hash table are (re)created
710  */
711 void tcapsrt_init_routine(void)
712 {
713
714   /* free hash-tables and mem_chunks for SRT */
715   if (tcaphash_context != NULL) {
716 #ifdef DEBUG_TCAPSRT
717     dbg(16,"Destroy hash_context ");
718 #endif
719     g_hash_table_destroy(tcaphash_context);
720   }
721
722   if (tcaphash_begin != NULL) {
723 #ifdef DEBUG_TCAPSRT
724     dbg(16,"Destroy hash_begin ");
725 #endif
726     g_hash_table_destroy(tcaphash_begin);
727   }  
728
729   if (tcaphash_cont != NULL) {
730 #ifdef DEBUG_TCAPSRT
731     dbg(16,"Destroy hash_cont ");
732 #endif
733     g_hash_table_destroy(tcaphash_cont);
734   }
735
736   if (tcaphash_end != NULL) {
737 #ifdef DEBUG_TCAPSRT
738     dbg(16,"Destroy hash_end ");
739 #endif
740     g_hash_table_destroy(tcaphash_end);
741   }
742
743 #ifdef DEBUG_TCAPSRT
744   dbg(16,"Create hash ");
745 #endif
746   /* create new hash-tables and mem_chunks for SRT */
747   tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
748   tcaphash_begin = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
749   tcaphash_cont = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
750   tcaphash_end = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
751
752   /* Reset the session counter */
753   tcapsrt_global_SessionId=1;
754
755   /* Display of SRT only if Persistent Stat */
756   gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
757 }
758
759 /*
760  * Service Responsee Time analyze
761  * Called just after dissector call 
762  */
763 struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
764                                                   packet_info * pinfo _U_,
765                                                   proto_tree *tree,
766                                                   struct tcapsrt_info_t * p_tcapsrt_info)
767 {
768   struct tcaphash_context_t * tcap_context=NULL;
769
770   switch (p_tcapsrt_info->ope) {
771     
772   case TC_BEGIN:  /*InitialDP*/
773 #ifdef DEBUG_TCAPSRT
774     dbg(1,"TC_BEGIN ");
775 #endif
776     tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
777     break;
778
779   case TC_CONT:
780 #ifdef DEBUG_TCAPSRT
781     dbg(1,"TC_CONT ");
782 #endif 
783     tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
784     break;
785
786   case TC_ABORT:
787 #ifdef DEBUG_TCAPSRT
788     dbg(1,"TC_ABORT ");
789 #endif 
790     tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
791     break;
792     
793   case TC_END:
794 #ifdef DEBUG_TCAPSRT
795     dbg(1,"TC_END ");
796 #endif
797     tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
798     break;
799     
800   default:
801 #ifdef DEBUG_TCAPSRT
802     dbg(1,"Unknow %d ", p_tcapsrt_info->ope);
803 #endif
804     break;
805   } /* switch tcapop */
806 #ifdef DEBUG_TCAPSRT
807   if (tcap_context)
808     dbg(1,"session %d ", tcap_context->session_id);
809 #endif
810   return tcap_context;
811 }
812
813
814 /* 
815  * Create the record identifiying the TCAP transaction
816  * When the identifier for the transaction is reused, check 
817  * the following criteria before to append a new record:
818  * - a timeout corresponding to a message retransmission is detected, 
819  * - a message hast been lost 
820  * - or the previous transaction has been  be closed
821  */
822 static struct tcaphash_context_t *
823 tcaphash_begin_matching(tvbuff_t *tvb,
824                         packet_info * pinfo _U_,
825                         proto_tree *tree,
826                         struct tcapsrt_info_t * p_tcapsrt_info)
827 {
828   struct tcaphash_context_t * p_tcaphash_context=NULL;
829   struct tcaphash_context_key_t tcaphash_context_key; 
830   struct tcaphash_begincall_t * p_tcaphash_begincall, * p_new_tcaphash_begincall;
831   struct tcaphash_begin_info_key_t tcaphash_begin_key;
832   proto_item *ti;
833   
834   /* prepare the key data */
835   tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
836   tcaphash_begin_key.opc_hash = mtp3_pc_hash( ((address *)(&pinfo->src))->data);
837   tcaphash_begin_key.dpc_hash = mtp3_pc_hash( ((address *)(&pinfo->dst))->data);
838   tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
839
840   /* look up the request */
841 #ifdef DEBUG_TCAPSRT
842   dbg(10,"\n Hbegin #%d ", pinfo->fd->num);
843   dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
844   dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst));
845   dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
846 #endif
847   p_tcaphash_begincall = (struct tcaphash_begincall_t *)
848     g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
849
850   if (p_tcaphash_begincall) {
851     /* Walk through list of transaction with identical keys */
852     do { 
853       /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
854       if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
855         /* We have seen this request before -> do nothing */
856 #ifdef DEBUG_TCAPSRT
857         dbg(22,"Already seen ");
858 #endif
859         p_tcaphash_context=p_tcaphash_begincall->context;
860         break;
861       }
862       /* If the last record for Tcap transaction with identifier has been reached */
863       if (!p_tcaphash_begincall->next_begincall) {
864         /* check if we have to create a new record or not */
865         /* if last request has been responded (response number in known)
866            and this request appears after last response (has bigger frame number)
867            and last request occured after the timeout for repetition,
868            or 
869            if last request hasn't been responded (so number unknown)
870            and this request appears after last request (has bigger frame number)
871            and this request occured after the timeout for message lost */
872         if ( ( p_tcaphash_begincall->context->last_frame != 0
873                && pinfo->fd->num > p_tcaphash_begincall->context->first_frame 
874                && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
875                ) ||
876              ( p_tcaphash_begincall->context->last_frame == 0
877                && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
878                && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout) 
879                ) 
880              )
881           {
882             /* we decide that we have a new request */
883             /* Append new record to the list */
884 #ifdef DEBUG_TCAPSRT
885             dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
886             dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
887 #endif  
888             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
889             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); 
890             p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
891                                                                  p_tcaphash_context,
892                                                                  pinfo);
893             
894 #ifdef DEBUG_TCAPSRT
895             dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
896 #endif
897             update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
898             p_tcaphash_begincall=p_new_tcaphash_begincall;
899           } else {
900           
901           /* If the Tid is reused for a closed Transaction */
902           /* Or if we received an InitialDP for a non closed Transaction */
903           if ( p_tcaphash_begincall->context->closed) {
904 #ifdef DEBUG_TCAPSRT
905             dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
906             dbg(12,"Frame %d rsp %d ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
907 #endif 
908             tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
909             p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); 
910             p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
911                                                                  p_tcaphash_context,
912                                                                  pinfo);
913             
914 #ifdef DEBUG_TCAPSRT
915             dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
916 #endif
917             update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
918             p_tcaphash_begincall=p_new_tcaphash_begincall;
919             
920           } else {
921             /* No, so it's a duplicate request.Mark it as such. */
922 #ifdef DEBUG_TCAPSRT
923             dbg(21,"Display_duplicate ");
924 #endif
925             if (gtcap_DisplaySRT) 
926               proto_tree_add_uint_hidden(tree, hf_tcapsrt_Duplicate, tvb, 0,0, p_tcapsrt_info->src_tid);
927             p_tcaphash_context=p_tcaphash_begincall->context;
928           } /* test with Timeout */
929         } /* closed */
930         break;
931       } /* Next call is NULL */
932       p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
933     } while (p_tcaphash_begincall != NULL );
934     /*
935      * New TCAP context
936      */
937   } else { /* p_tcaphash_begincall has not been found */
938 #ifdef DEBUG_TCAPSRT
939     dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
940 #endif 
941
942     tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
943     p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); 
944     p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context, pinfo); 
945     
946 #ifdef DEBUG_TCAPSRT
947     dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
948     dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
949 #endif
950     update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
951   }
952   
953   /* display tcap session, if available */
954   if ( gtcap_DisplaySRT &&
955        p_tcaphash_context &&
956        p_tcaphash_context->session_id)
957     proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
958   
959   /* add link to response frame, if available */
960   if( gtcap_DisplaySRT &&
961       p_tcaphash_begincall->context->last_frame != 0){
962 #ifdef DEBUG_TCAPSRT
963     dbg(20,"Display_frameRsplink %d ",p_tcaphash_begincall->context->last_frame);
964 #endif
965     ti = proto_tree_add_uint_format(tree, hf_tcapsrt_BeginSession, tvb, 0, 0, 
966                                     p_tcaphash_begincall->context->last_frame,
967                                     "End of session in frame %u",
968                                     p_tcaphash_begincall->context->last_frame);
969     PROTO_ITEM_SET_GENERATED(ti);
970   } 
971   return p_tcaphash_context;
972 }
973
974
975 /*
976  * Register the request, and try to find the response
977  *
978  */
979 static struct tcaphash_context_t *
980 tcaphash_cont_matching(tvbuff_t *tvb,
981                        packet_info * pinfo _U_,
982                        proto_tree *tree,
983                        struct tcapsrt_info_t * p_tcapsrt_info)
984 {
985   struct tcaphash_context_t * p_tcaphash_context=NULL;
986   struct tcaphash_contcall_t * p_tcaphash_contcall;
987   struct tcaphash_cont_info_key_t tcaphash_cont_key;
988   proto_item *ti;
989
990 #ifdef DEBUG_TCAPSRT
991   dbg(10,"\n Hcont #%d ", pinfo->fd->num);
992 #endif 
993
994   /* look only for matching request, if matching conversation is available. */
995   tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
996   tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
997   tcaphash_cont_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
998   tcaphash_cont_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
999   tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1000
1001 #ifdef DEBUG_TCAPSRT
1002   dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1003   dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst)); 
1004   dbg(51,"Tid %lx %lx ",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1005 #endif
1006   p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1007   if(p_tcaphash_contcall) {
1008 #ifdef DEBUG_TCAPSRT
1009     dbg(12,"CFound ");
1010 #endif
1011     p_tcaphash_context=p_tcaphash_contcall->context;
1012   } else { /* Not found */
1013 #ifdef DEBUG_TCAPSRT
1014     dbg(12,"CnotFound ");
1015 #endif
1016     struct tcaphash_begin_info_key_t tcaphash_begin_key;
1017     struct tcaphash_begincall_t * p_tcaphash_begincall;
1018
1019     struct tcaphash_end_info_key_t tcaphash_end_key;
1020     struct tcaphash_endcall_t * p_tcaphash_endcall;
1021
1022     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1023     tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1024     tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1025     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1026
1027 #ifdef DEBUG_TCAPSRT
1028     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1029     dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst)); 
1030     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1031 #endif
1032     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1033     if(p_tcaphash_begincall &&
1034        !p_tcaphash_begincall->context->contcall ) {
1035 #ifdef DEBUG_TCAPSRT
1036       dbg(12,"BFound ");
1037 #endif  
1038       p_tcaphash_context=p_tcaphash_begincall->context;
1039       p_tcaphash_context->responded=TRUE;
1040
1041 #ifdef DEBUG_TCAPSRT
1042       dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1043 #endif
1044       p_tcaphash_contcall = create_tcaphash_cont(&tcaphash_cont_key,
1045                                                  p_tcaphash_begincall->context,
1046                                                  pinfo);
1047       
1048 #ifdef DEBUG_TCAPSRT
1049       dbg(11,"Update Ckey %lx ",tcaphash_begin_key.hashKey);
1050       dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
1051 #endif
1052       tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
1053       tcaphash_end_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1054       tcaphash_end_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1055       tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1056
1057 #ifdef DEBUG_TCAPSRT
1058       dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1059 #endif
1060       p_tcaphash_endcall = create_tcaphash_end(&tcaphash_end_key,
1061                                                p_tcaphash_begincall->context,
1062                                                pinfo);
1063       
1064 #ifdef DEBUG_TCAPSRT
1065       dbg(11,"Update Ekey %lx ",tcaphash_end_key.hashKey);
1066       dbg(11,"Frame reqlink #%d ", pinfo->fd->num);
1067 #endif
1068     } else { /* Begin not found */
1069 #ifdef DEBUG_TCAPSRT
1070       dbg(12,"BnotFound ");
1071 #endif 
1072     } /* begin found */
1073   } /* cont found */
1074     /* display tcap session, if available */
1075   if (gtcap_DisplaySRT &&
1076       p_tcaphash_context &&
1077       p_tcaphash_context->session_id)
1078     proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1079   
1080   return p_tcaphash_context;
1081 }
1082
1083
1084
1085 /*
1086  *
1087  *
1088  */
1089 static struct tcaphash_context_t *
1090 tcaphash_end_matching(tvbuff_t *tvb,
1091                       packet_info * pinfo _U_,
1092                       proto_tree *tree,
1093                       struct tcapsrt_info_t * p_tcapsrt_info)
1094 {  
1095   struct tcaphash_context_t * p_tcaphash_context=NULL;
1096
1097   struct tcaphash_end_info_key_t tcaphash_end_key;
1098   struct tcaphash_endcall_t * p_tcaphash_endcall=NULL;
1099
1100   struct tcaphash_begin_info_key_t tcaphash_begin_key;
1101   struct tcaphash_begincall_t * p_tcaphash_begincall=NULL; 
1102   proto_item *ti; 
1103   nstime_t delta;
1104
1105
1106 #ifdef DEBUG_TCAPSRT
1107   dbg(10,"\n Hend #%d ", pinfo->fd->num);
1108 #endif
1109   /* look only for matching request, if matching conversation is available. */
1110   tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1111   tcaphash_end_key.opc_hash = mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1112   tcaphash_end_key.dpc_hash = mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1113   tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1114
1115 #ifdef DEBUG_TCAPSRT
1116   dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1117   dbg(11,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst)); 
1118   dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1119 #endif
1120   p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
1121   
1122   if(!p_tcaphash_endcall) {
1123 #ifdef DEBUG_TCAPSRT
1124     dbg(12,"EnotFound "); 
1125 #endif   
1126     tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1127     tcaphash_begin_key.opc_hash=mtp3_pc_hash( ((address*)(&pinfo->src))->data);
1128     tcaphash_begin_key.dpc_hash=mtp3_pc_hash( ((address*)(&pinfo->dst))->data);
1129     tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1130     
1131 #ifdef DEBUG_TCAPSRT
1132     dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1133     dbg(51,"PC %s %s ",address_to_str(&pinfo->src), address_to_str(&pinfo->dst)); 
1134     dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1135 #endif
1136     p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
1137   }
1138   
1139   if (p_tcaphash_endcall) {
1140     /* Use the TC_BEGIN Destination reference */
1141     p_tcaphash_context=p_tcaphash_endcall->context;
1142   } else if (p_tcaphash_begincall) {
1143     /* Use the TC_BEGIN Source reference */ 
1144     p_tcaphash_context=p_tcaphash_begincall->context;
1145   }
1146
1147   if (p_tcaphash_context) {
1148     
1149 #ifdef DEBUG_TCAPSRT
1150     dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1151 #endif
1152     if (gtcap_DisplaySRT)
1153       proto_tree_add_uint(tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1154
1155 #ifdef DEBUG_TCAPSRT
1156     dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1157 #endif
1158     /* Indicate the frame to which this is a reply. */
1159     if (gtcap_DisplaySRT) {
1160       ti = proto_tree_add_uint_format(tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1161                                       p_tcaphash_context->first_frame,
1162                                       "Begin of session in frame %u",
1163                                       p_tcaphash_context->first_frame);
1164       PROTO_ITEM_SET_GENERATED(ti);
1165       /* Calculate Service Response Time */
1166       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
1167       
1168       /* display Service Response Time and make it filterable */
1169       ti = proto_tree_add_time(tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1170       PROTO_ITEM_SET_GENERATED(ti);
1171     }
1172     /* Close the context and remove it */
1173     tcapsrt_close(p_tcaphash_context,pinfo);
1174
1175   } /* context present */ 
1176   return p_tcaphash_context;
1177 }
1178
1179 /*
1180  * Initialize the Message Info used by the main dissector
1181  * Data are linked to a TCAP transaction 
1182  */
1183 struct tcapsrt_info_t * tcapsrt_razinfo(void)
1184 {
1185   struct tcapsrt_info_t * p_tcapsrt_info ;
1186
1187   /* Global buffer for packet extraction */
1188   tcapsrt_global_current++;
1189   if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1190     tcapsrt_global_current=0;
1191   }
1192   
1193   p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1194   memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));  
1195
1196   return p_tcapsrt_info;
1197 }
1198
1199 void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
1200                    packet_info * pinfo _U_)
1201 {
1202 #ifdef DEBUG_TCAPSRT
1203   dbg(60,"Force close ");
1204 #endif
1205   if (p_tcaphash_context) {
1206     p_tcaphash_context->responded=TRUE;
1207     p_tcaphash_context->last_frame = pinfo->fd->num;
1208     p_tcaphash_context->end_time = pinfo->fd->abs_ts;
1209     p_tcaphash_context->closed=TRUE;
1210
1211     /* If the endkey is present */
1212     if ( p_tcaphash_context->endcall
1213          && !gtcap_PersistentSRT ) {
1214 #ifdef DEBUG_TCAPSRT
1215       dbg(20,"remove Ehash ");
1216 #endif
1217       g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1218     }
1219     
1220     /* If the contkey is present */
1221     if ( p_tcaphash_context->contcall
1222          && !gtcap_PersistentSRT) {
1223 #ifdef DEBUG_TCAPSRT
1224       dbg(20,"remove Chash ");
1225 #endif
1226       g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1227     }
1228     
1229     /* If the beginkey is present */
1230     if (p_tcaphash_context->begincall->next_begincall) {
1231       if (p_tcaphash_context->begincall->previous_begincall ) {
1232 #ifdef DEBUG_TCAPSRT
1233         dbg(20,"deplace Bhash ");
1234 #endif
1235         p_tcaphash_context->begincall->previous_begincall->next_begincall
1236           = p_tcaphash_context->begincall->next_begincall;
1237         p_tcaphash_context->begincall->next_begincall->previous_begincall
1238           = p_tcaphash_context->begincall->previous_begincall;
1239       } else {
1240         /* cannot remove the father */
1241 #ifdef DEBUG_TCAPSRT
1242         dbg(20,"father Bhash ");
1243 #endif
1244       }
1245     } else  if (!gtcap_PersistentSRT) {
1246 #ifdef DEBUG_TCAPSRT
1247       dbg(20,"remove Bhash ");
1248 #endif
1249       g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1250 #ifdef DEBUG_TCAPSRT
1251       dbg(20,"remove context ");
1252 #endif
1253       g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
1254       
1255     } /* begincall without chained string */
1256   } else { /* no context */
1257 #ifdef DEBUG_TCAPSRT
1258     dbg(20,"No context to remove ");
1259 #endif
1260   }
1261 }