Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / epan / dissectors / asn1 / tcap / packet-tcap-template.c
blobd21938edd108921076bbe4dec7ffcfa22942fb74
1 /* packet-tcap-template.c
2 * Routines for TCAP
3 * Copyright 2004 - 2005, Tim Endean <endeant@hotmail.com>
4 * Built from the gsm-map dissector Copyright 2004 - 2005, Anders Broman <anders.broman@ericsson.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 * References: ETSI 300 374
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/exceptions.h>
18 #include <epan/prefs.h>
19 #include <epan/oids.h>
20 #include <epan/asn1.h>
21 #include <epan/address_types.h>
22 #include <epan/strutil.h>
23 #include <epan/show_exception.h>
24 #include <wsutil/array.h>
26 #include "packet-ber.h"
27 #include "packet-tcap.h"
28 #include "packet-mtp3.h"
31 #define PNAME "Transaction Capabilities Application Part"
32 #define PSNAME "TCAP"
33 #define PFNAME "tcap"
35 /* Initialize the protocol and registered fields */
36 static int proto_tcap;
37 static int hf_tcap_tag;
38 static int hf_tcap_length;
39 static int hf_tcap_data;
40 static int hf_tcap_tid;
41 static int hf_tcap_constructor_eoc;
43 int hf_tcapsrt_SessionId;
44 int hf_tcapsrt_Duplicate;
45 int hf_tcapsrt_BeginSession;
46 int hf_tcapsrt_EndSession;
47 int hf_tcapsrt_SessionTime;
49 #include "packet-tcap-hf.c"
51 /* Initialize the subtree pointers */
52 static int ett_tcap;
53 static int ett_param;
55 static int ett_otid;
56 static int ett_dtid;
57 int ett_tcap_stat;
59 static struct tcapsrt_info_t * gp_tcapsrt_info;
60 static bool tcap_subdissector_used=false;
61 static dissector_handle_t requested_subdissector_handle;
63 static int ss7pc_address_type = -1;
65 static struct tcaphash_context_t * gp_tcap_context;
67 #include "packet-tcap-ett.c"
69 /* When several Tcap components are received in a single TCAP message,
70 we have to use several buffers for the stored parameters
71 because else this data are erased during TAP dissector call */
72 #define MAX_TCAP_INSTANCE 10
73 static int tcapsrt_global_current=0;
74 static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
76 #define MAX_SSN 254
77 static range_t *global_ssn_range;
78 static range_t *ssn_range;
80 /* These two timeout (in second) are used when some message are lost,
81 or when the same TCAP transcation identifier is reused */
82 static unsigned gtcap_RepetitionTimeout = 10;
83 static unsigned gtcap_LostTimeout = 30;
84 static bool gtcap_PersistentSRT=false;
85 bool gtcap_DisplaySRT=false;
86 bool gtcap_StatSRT=false;
88 /* Global hash tables*/
89 static wmem_map_t *tcaphash_context;
90 static wmem_map_t *tcaphash_begin;
91 static wmem_map_t *tcaphash_cont;
92 static wmem_map_t *tcaphash_end;
93 static wmem_map_t *tcaphash_ansi;
95 static uint32_t tcapsrt_global_SessionId=1;
97 static dissector_handle_t tcap_handle;
98 static dissector_table_t ber_oid_dissector_table;
99 static const char * cur_oid;
100 static const char * tcapext_oid;
101 static proto_tree * tcap_top_tree;
102 static proto_tree * tcap_stat_tree;
104 static dissector_handle_t data_handle;
105 static dissector_handle_t ansi_tcap_handle;
107 static int dissect_tcap_param(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset);
108 static bool dissect_tcap_ITU_ComponentPDU(bool implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_);
110 static dissector_table_t ansi_sub_dissectors;
111 static dissector_table_t itu_sub_dissectors;
113 extern void add_ansi_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) {
114 dissector_add_uint("ansi_tcap.ssn",ssn,dissector);
115 dissector_add_uint("sccp.ssn",ssn,tcap_handle);
118 extern void add_itu_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) {
119 dissector_add_uint("itu_tcap.ssn",ssn,dissector);
120 dissector_add_uint("sccp.ssn",ssn,tcap_handle);
123 extern void delete_ansi_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) {
124 dissector_delete_uint("ansi_tcap.ssn",ssn,dissector);
125 if (!get_itu_tcap_subdissector(ssn))
126 dissector_delete_uint("sccp.ssn",ssn,tcap_handle);
128 extern void delete_itu_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector _U_) {
129 dissector_delete_uint("itu_tcap.ssn",ssn,dissector);
130 if (!get_ansi_tcap_subdissector(ssn))
131 dissector_delete_uint("sccp.ssn", ssn,tcap_handle);
134 dissector_handle_t get_ansi_tcap_subdissector(uint32_t ssn) {
135 return dissector_get_uint_handle(ansi_sub_dissectors, ssn);
138 dissector_handle_t get_itu_tcap_subdissector(uint32_t ssn) {
139 return dissector_get_uint_handle(itu_sub_dissectors, ssn);
142 #include "packet-tcap-fn.c"
145 * DEBUG functions
147 #undef DEBUG_TCAPSRT
148 /* #define DEBUG_TCAPSRT */
150 #ifdef DEBUG_TCAPSRT
151 #include <stdio.h>
152 #include <stdarg.h>
153 static unsigned debug_level = 99;
155 static void
156 dbg(unsigned level, const char* fmt, ...)
158 va_list ap;
160 if (level > debug_level) return;
161 va_start(ap,fmt);
162 vfprintf(stderr, fmt, ap);
163 va_end(ap);
165 #endif
167 static int
168 tcaphash_context_equal(const void *k1, const void *k2)
170 const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
171 const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
173 return (key1->session_id == key2->session_id);
176 /* calculate a hash key */
177 static unsigned
178 tcaphash_context_calchash(const void *k)
180 const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
181 return key->session_id;
185 static int
186 tcaphash_begin_equal(const void *k1, const void *k2)
188 const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
189 const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
191 if (key1->hashKey == key2->hashKey) {
192 if ( (key1->pc_hash == key2->pc_hash) && (key1->tid == key2->tid) )
193 return true;
195 return false;
198 /* calculate a hash key */
199 static unsigned
200 tcaphash_begin_calchash(const void *k)
202 const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
203 unsigned hashkey;
204 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
205 hashkey = key->tid;
206 return hashkey;
209 static int
210 tcaphash_cont_equal(const void *k1, const void *k2)
212 const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
213 const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
215 if (key1->hashKey == key2->hashKey) {
217 if ( (key1->opc_hash == key2->opc_hash) &&
218 (key1->dpc_hash == key2->dpc_hash) &&
219 (key1->src_tid == key2->src_tid) &&
220 (key1->dst_tid == key2->dst_tid) ) {
221 return true;
223 else if ( (key1->opc_hash == key2->dpc_hash) &&
224 (key1->dpc_hash == key2->opc_hash) &&
225 (key1->src_tid == key2->dst_tid) &&
226 (key1->dst_tid == key2->src_tid) ) {
227 return true;
230 return false;
233 /* calculate a hash key */
234 static unsigned
235 tcaphash_cont_calchash(const void *k)
237 const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
238 unsigned hashkey;
239 hashkey = key->src_tid + key->dst_tid;
240 return hashkey;
244 static int
245 tcaphash_end_equal(const void *k1, const void *k2)
247 const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
248 const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
250 if (key1->hashKey == key2->hashKey) {
251 if ( (key1->opc_hash == key2->opc_hash) &&
252 (key1->dpc_hash == key2->dpc_hash) &&
253 (key1->tid == key2->tid) )
254 return true;
256 return false;
259 /* calculate a hash key */
260 static unsigned
261 tcaphash_end_calchash(const void *k)
263 const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
264 unsigned hashkey;
265 hashkey = key->tid;
266 return hashkey;
269 static int
270 tcaphash_ansi_equal(const void *k1, const void *k2)
272 const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
273 const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
275 if (key1->hashKey == key2->hashKey) {
277 if ( ( (key1->opc_hash == key2->opc_hash) &&
278 (key1->dpc_hash == key2->dpc_hash) &&
279 (key1->tid == key2->tid) )
281 ( (key1->opc_hash == key2->dpc_hash) &&
282 (key1->dpc_hash == key2->opc_hash) &&
283 (key1->tid == key2->tid) )
285 return true;
287 return false;
290 /* calculate a hash key */
291 static unsigned
292 tcaphash_ansi_calchash(const void *k)
294 const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
295 unsigned hashkey;
296 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
297 hashkey = key->tid;
298 return hashkey;
302 * Update a record with the data of the Request
304 static void
305 update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
306 packet_info *pinfo)
308 p_tcaphash_begincall->context->first_frame = pinfo->num;
309 p_tcaphash_begincall->context->last_frame = 0;
310 p_tcaphash_begincall->context->responded = false;
311 p_tcaphash_begincall->context->begin_time = pinfo->abs_ts;
315 * Append a new dialogue, using the same Key, to the chained list
316 * The time is stored too
318 static struct tcaphash_begincall_t *
319 append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
320 struct tcaphash_context_t *p_tcaphash_context,
321 packet_info *pinfo)
323 struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
325 /* Append the transaction to the list, when the same key is found
326 This should append when the tcap-transaction Id is reused */
328 p_new_tcaphash_begincall = wmem_new0(wmem_file_scope(), struct tcaphash_begincall_t);
329 p_new_tcaphash_begincall->context=p_tcaphash_context;
330 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
331 p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
332 p_new_tcaphash_begincall->context->first_frame = pinfo->num;
333 p_new_tcaphash_begincall->next_begincall=NULL;
334 p_new_tcaphash_begincall->previous_begincall=prev_begincall;
335 p_new_tcaphash_begincall->father=false;
337 #ifdef DEBUG_TCAPSRT
338 dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
339 #endif
340 /* Insert in the chained list */
341 prev_begincall->next_begincall = p_new_tcaphash_begincall;
342 if (prev_begincall->context->last_frame == 0) {
343 #ifdef DEBUG_TCAPSRT
344 dbg(10,"last ");
345 #endif
346 prev_begincall->context->last_frame = pinfo->num-1;
348 return p_new_tcaphash_begincall;
352 * Update a record with the data of the Request
354 static void
355 update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
356 packet_info *pinfo)
358 p_tcaphash_ansicall->context->first_frame = pinfo->num;
359 p_tcaphash_ansicall->context->last_frame = 0;
360 p_tcaphash_ansicall->context->responded = false;
361 p_tcaphash_ansicall->context->begin_time = pinfo->abs_ts;
365 * Append a new dialogue, using the same Key, to the chained list
366 * The time is stored too
368 static struct tcaphash_ansicall_t *
369 append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
370 struct tcaphash_context_t *p_tcaphash_context,
371 packet_info *pinfo)
373 struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
375 /* Append the transaction to the list, when the same key is found
376 This should append when the tcap-transaction Id is reused */
378 p_new_tcaphash_ansicall = wmem_new0(wmem_file_scope(), struct tcaphash_ansicall_t);
379 p_new_tcaphash_ansicall->context=p_tcaphash_context;
380 p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
381 p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
382 p_new_tcaphash_ansicall->context->first_frame = pinfo->num;
383 p_new_tcaphash_ansicall->next_ansicall=NULL;
384 p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
385 p_new_tcaphash_ansicall->father=false;
387 #ifdef DEBUG_TCAPSRT
388 dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
389 #endif
390 /* Insert in the chained list */
391 prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
392 if (prev_ansicall->context->last_frame == 0) {
393 #ifdef DEBUG_TCAPSRT
394 dbg(10,"last ");
395 #endif
396 prev_ansicall->context->last_frame = pinfo->num-1;
398 return p_new_tcaphash_ansicall;
402 static struct tcaphash_contcall_t *
403 append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
404 struct tcaphash_context_t *p_tcaphash_context)
406 struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
408 /* Append the transaction to the list, when the same key is found
409 This should append when the tcap-transaction Id is reused */
411 p_new_tcaphash_contcall = wmem_new0(wmem_file_scope(), struct tcaphash_contcall_t);
412 p_new_tcaphash_contcall->context=p_tcaphash_context;
413 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
414 p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
415 p_new_tcaphash_contcall->next_contcall=NULL;
416 p_new_tcaphash_contcall->previous_contcall=prev_contcall;
417 p_new_tcaphash_contcall->father=false;
419 #ifdef DEBUG_TCAPSRT
420 dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
421 #endif
422 /* Insert in the chained list */
423 prev_contcall->next_contcall = p_new_tcaphash_contcall;
424 return p_new_tcaphash_contcall;
428 static struct tcaphash_endcall_t *
429 append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
430 struct tcaphash_context_t *p_tcaphash_context)
432 struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
434 /* Append the transaction to the list, when the same key is found
435 This should append when the tcap-transaction Id is reused */
437 p_new_tcaphash_endcall = wmem_new0(wmem_file_scope(), struct tcaphash_endcall_t);
438 p_new_tcaphash_endcall->context=p_tcaphash_context;
439 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
440 p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
441 p_new_tcaphash_endcall->next_endcall=NULL;
442 p_new_tcaphash_endcall->previous_endcall=prev_endcall;
443 p_new_tcaphash_endcall->father=false;
445 #ifdef DEBUG_TCAPSRT
446 dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
447 #endif
448 /* Insert in the chained list */
449 prev_endcall->next_endcall = p_new_tcaphash_endcall;
450 return p_new_tcaphash_endcall;
455 * Find the dialog by Key and Time
457 static struct tcaphash_begincall_t *
458 find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
459 packet_info *pinfo, bool isBegin)
461 struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
462 p_tcaphash_begincall = (struct tcaphash_begincall_t *)wmem_map_lookup(tcaphash_begin, p_tcaphash_begin_key);
464 if(p_tcaphash_begincall) {
465 do {
466 if ( p_tcaphash_begincall->context ) {
467 if ( ( isBegin &&
468 pinfo->num == p_tcaphash_begincall->context->first_frame )
470 ( !isBegin &&
471 pinfo->num >= p_tcaphash_begincall->context->first_frame &&
472 ( p_tcaphash_begincall->context->last_frame?pinfo->num <= p_tcaphash_begincall->context->last_frame:1 )
475 /* We have a dialogue, with this key, opened before this request */
476 #ifdef DEBUG_TCAPSRT
477 dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
478 #endif
479 return p_tcaphash_begincall;
481 #ifdef DEBUG_TCAPSRT
482 dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
483 #endif
485 /* Break when list end is reached */
486 if(p_tcaphash_begincall->next_begincall == NULL) {
487 #ifdef DEBUG_TCAPSRT
488 dbg(23,"End of Blist ");
489 #endif
490 break;
492 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
493 } while (p_tcaphash_begincall != NULL) ;
494 } else {
495 #ifdef DEBUG_TCAPSRT
496 dbg(23,"Not in Bhash ");
497 #endif
499 return NULL;
504 static struct tcaphash_contcall_t *
505 find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
506 packet_info *pinfo)
508 struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
509 p_tcaphash_contcall = (struct tcaphash_contcall_t *)wmem_map_lookup(tcaphash_cont, p_tcaphash_cont_key);
511 if(p_tcaphash_contcall) {
512 do {
513 if ( p_tcaphash_contcall->context ) {
514 if (pinfo->num >= p_tcaphash_contcall->context->first_frame &&
515 (p_tcaphash_contcall->context->last_frame?pinfo->num <= p_tcaphash_contcall->context->last_frame:1) ) {
516 /* We have a dialogue, with this key, opened before this request */
517 #ifdef DEBUG_TCAPSRT
518 dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
519 #endif
520 return p_tcaphash_contcall;
522 #ifdef DEBUG_TCAPSRT
523 dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
524 #endif
526 /* Break when list end is reached */
527 if(p_tcaphash_contcall->next_contcall == NULL) {
528 #ifdef DEBUG_TCAPSRT
529 dbg(23,"End of Clist ");
530 #endif
531 break;
533 p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
534 } while (p_tcaphash_contcall != NULL) ;
535 } else {
536 #ifdef DEBUG_TCAPSRT
537 dbg(23,"Not in Chash ");
538 #endif
540 return NULL;
543 static struct tcaphash_endcall_t *
544 find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
545 packet_info *pinfo, bool isEnd)
547 struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
548 p_tcaphash_endcall = (struct tcaphash_endcall_t *)wmem_map_lookup(tcaphash_end, p_tcaphash_end_key);
550 if(p_tcaphash_endcall) {
551 do {
552 if ( p_tcaphash_endcall->context ) {
553 if ( ( isEnd &&
554 (p_tcaphash_endcall->context->last_frame?pinfo->num == p_tcaphash_endcall->context->last_frame:1)
557 ( !isEnd &&
558 pinfo->num >= p_tcaphash_endcall->context->first_frame &&
559 (p_tcaphash_endcall->context->last_frame?pinfo->num <= p_tcaphash_endcall->context->last_frame:1)
562 /* We have a dialogue, with this key, opened before this request */
563 #ifdef DEBUG_TCAPSRT
564 dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
565 #endif
566 return p_tcaphash_endcall;
568 #ifdef DEBUG_TCAPSRT
569 dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
570 #endif
572 /* Break when list end is reached */
573 if(p_tcaphash_endcall->next_endcall == NULL) {
574 #ifdef DEBUG_TCAPSRT
575 dbg(23,"End of Elist ");
576 #endif
577 break;
579 p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
580 } while (p_tcaphash_endcall != NULL) ;
581 } else {
582 #ifdef DEBUG_TCAPSRT
583 dbg(23,"Not in Ehash ");
584 #endif
586 return NULL;
590 * New record to create, to identify a new transaction
592 static struct tcaphash_context_t *
593 new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
594 packet_info *pinfo)
596 struct tcaphash_context_key_t *p_new_tcaphash_context_key;
597 struct tcaphash_context_t *p_new_tcaphash_context = NULL;
599 /* Register the transaction in the hash table
600 with the tcap transaction Id as Main Key
601 Once created, this entry will be updated later */
603 p_new_tcaphash_context_key = wmem_new(wmem_file_scope(), struct tcaphash_context_key_t);
604 p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
606 p_new_tcaphash_context = wmem_new0(wmem_file_scope(), struct tcaphash_context_t);
607 p_new_tcaphash_context->key = p_new_tcaphash_context_key;
608 p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
609 p_new_tcaphash_context->first_frame = pinfo->num;
610 #ifdef DEBUG_TCAPSRT
611 dbg(10,"S%d ", p_new_tcaphash_context->session_id);
612 #endif
613 /* store it */
614 wmem_map_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
615 return p_new_tcaphash_context;
619 * New record to create, to identify a new transaction
621 static struct tcaphash_begincall_t *
622 new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
623 struct tcaphash_context_t *p_tcaphash_context)
625 struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
626 struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
628 /* Register the transaction in the hash table
629 with the tcap transaction Id as Main Key
630 Once created, this entry will be updated later */
632 p_new_tcaphash_begin_key = wmem_new(wmem_file_scope(), struct tcaphash_begin_info_key_t);
633 p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
634 p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
635 p_new_tcaphash_begin_key->pc_hash = p_tcaphash_begin_key->pc_hash;
637 p_new_tcaphash_begincall = wmem_new0(wmem_file_scope(), struct tcaphash_begincall_t);
638 p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
639 p_new_tcaphash_begincall->context=p_tcaphash_context;
640 p_tcaphash_context->begincall=p_new_tcaphash_begincall;
641 p_new_tcaphash_begincall->father=true;
642 p_new_tcaphash_begincall->next_begincall=NULL;
643 p_new_tcaphash_begincall->previous_begincall=NULL;
645 #ifdef DEBUG_TCAPSRT
646 dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
647 #endif
648 /* store it */
649 wmem_map_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
650 return p_new_tcaphash_begincall;
656 * New record to create, to identify a new transaction
658 static struct tcaphash_contcall_t *
659 new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
660 struct tcaphash_context_t *p_tcaphash_context)
662 struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
663 struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
665 /* Register the transaction in the hash table
666 with the tcap transaction Id as Main Key
667 Once created, this entry will be updated later */
669 p_new_tcaphash_cont_key = wmem_new(wmem_file_scope(), struct tcaphash_cont_info_key_t);
670 p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
671 p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
672 p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
673 p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
674 p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
676 p_new_tcaphash_contcall = wmem_new0(wmem_file_scope(), struct tcaphash_contcall_t);
677 p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
678 p_new_tcaphash_contcall->context=p_tcaphash_context;
679 p_tcaphash_context->contcall=p_new_tcaphash_contcall;
680 p_new_tcaphash_contcall->father=true;
681 p_new_tcaphash_contcall->next_contcall=NULL;
682 p_new_tcaphash_contcall->previous_contcall=NULL;
684 #ifdef DEBUG_TCAPSRT
685 dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
686 #endif
687 /* store it */
688 wmem_map_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
689 return p_new_tcaphash_contcall;
694 * New record to create, to identify a new transaction
696 static struct tcaphash_endcall_t *
697 new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
698 struct tcaphash_context_t *p_tcaphash_context)
700 struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
701 struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
703 /* Register the transaction in the hash table
704 with the tcap transaction Id as Main Key
705 Once created, this entry will be updated later */
707 p_new_tcaphash_end_key = wmem_new(wmem_file_scope(), struct tcaphash_end_info_key_t);
708 p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
709 p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
710 p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
711 p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
713 p_new_tcaphash_endcall = wmem_new0(wmem_file_scope(), struct tcaphash_endcall_t);
714 p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
715 p_new_tcaphash_endcall->context=p_tcaphash_context;
716 p_tcaphash_context->endcall=p_new_tcaphash_endcall;
717 p_new_tcaphash_endcall->father=true;
718 p_new_tcaphash_endcall->next_endcall=NULL;
719 p_new_tcaphash_endcall->previous_endcall=NULL;
721 #ifdef DEBUG_TCAPSRT
722 dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
723 #endif
724 /* store it */
725 wmem_map_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
726 return p_new_tcaphash_endcall;
729 * New record to create, to identify a new transaction
731 static struct tcaphash_ansicall_t *
732 new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
733 struct tcaphash_context_t *p_tcaphash_context)
735 struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
736 struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
738 /* Register the transaction in the hash table
739 with the tcap transaction Id as Main Key
740 Once created, this entry will be updated later */
742 p_new_tcaphash_ansi_key = wmem_new(wmem_file_scope(), struct tcaphash_ansi_info_key_t);
743 p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
744 p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
745 p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
746 p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
748 p_new_tcaphash_ansicall = wmem_new0(wmem_file_scope(), struct tcaphash_ansicall_t);
749 p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
750 p_new_tcaphash_ansicall->context=p_tcaphash_context;
751 p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
752 p_new_tcaphash_ansicall->father=true;
753 p_new_tcaphash_ansicall->next_ansicall=NULL;
754 p_new_tcaphash_ansicall->previous_ansicall=NULL;
756 #ifdef DEBUG_TCAPSRT
757 dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
758 #endif
759 /* store it */
760 wmem_map_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
761 return p_new_tcaphash_ansicall;
764 static struct tcaphash_contcall_t *
765 create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
766 struct tcaphash_context_t *p_tcaphash_context)
768 struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
769 struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
771 p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
772 wmem_map_lookup(tcaphash_cont, p_tcaphash_cont_key);
774 if (p_tcaphash_contcall1) {
775 /* Walk through list of transaction with identical keys */
776 /* go to the end to insert new record */
777 do {
778 if (!p_tcaphash_contcall1->next_contcall) {
779 p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
780 p_tcaphash_context);
781 break;
783 p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
784 } while (p_tcaphash_contcall1 != NULL );
785 } else {
786 p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
787 p_tcaphash_context);
789 return p_tcaphash_contcall;
793 static struct tcaphash_endcall_t *
794 create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
795 struct tcaphash_context_t *p_tcaphash_context)
797 struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
798 struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
800 p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
801 wmem_map_lookup(tcaphash_end, p_tcaphash_end_key);
803 if (p_tcaphash_endcall1) {
804 /* Walk through list of transaction with identical keys */
805 /* go to the end to insert new record */
806 do {
807 if (!p_tcaphash_endcall1->next_endcall) {
808 p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
809 p_tcaphash_context);
810 break;
812 p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
813 } while (p_tcaphash_endcall1 != NULL );
814 } else {
815 p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
816 p_tcaphash_context);
818 return p_tcaphash_endcall;
822 * Create the record identifiying the TCAP transaction
823 * When the identifier for the transaction is reused, check
824 * the following criteria before to append a new record:
825 * - a timeout corresponding to a message retransmission is detected,
826 * - a message hast been lost
827 * - or the previous transaction has been be closed
829 static struct tcaphash_context_t *
830 tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
831 struct tcapsrt_info_t *p_tcapsrt_info)
833 struct tcaphash_context_t *p_tcaphash_context=NULL;
834 struct tcaphash_context_key_t tcaphash_context_key;
835 struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
836 struct tcaphash_begin_info_key_t tcaphash_begin_key;
837 proto_item *pi;
838 proto_item *stat_item=NULL;
839 proto_tree *stat_tree=NULL;
841 #ifdef DEBUG_TCAPSRT
842 dbg(51,"src %s srcTid %lx dst %s ", address_to_str(pinfo->pool, &pinfo->src), p_tcapsrt_info->src_tid, address_to_str(pinfo->pool, &pinfo->dst));
843 #endif
845 /* prepare the key data */
846 tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
847 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
849 /* We have MTP3 PCs (so we can safely do this cast) */
850 tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
851 } else {
852 /* Don't have MTP3 PCs (have SCCP GT ?) */
853 tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src));
855 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
857 /* look up the request */
858 #ifdef DEBUG_TCAPSRT
859 dbg(10,"\n Hbegin #%u ", pinfo->num);
860 dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
861 dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->src));
862 dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
863 #endif
865 p_tcaphash_begincall = (struct tcaphash_begincall_t *)
866 wmem_map_lookup(tcaphash_begin, &tcaphash_begin_key);
868 if (p_tcaphash_begincall) {
869 /* Walk through list of transaction with identical keys */
870 do {
871 /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
872 if (pinfo->num == p_tcaphash_begincall->context->first_frame) {
873 /* We have seen this request before -> do nothing */
874 #ifdef DEBUG_TCAPSRT
875 dbg(22,"Already seen ");
876 #endif
877 p_tcaphash_context=p_tcaphash_begincall->context;
878 break;
880 /* If the last record for Tcap transaction with identifier has not been reached */
881 if (!p_tcaphash_begincall->next_begincall) {
882 /* check if we have to create a new record or not */
883 /* if last request has been responded (response number is known)
884 and this request appears after last response (has bigger frame number)
885 and last request occurred after the timeout for repetition,
887 if last request hasn't been responded (so number unknown)
888 and this request appears after last request (has bigger frame number)
889 and this request occurred after the timeout for message lost */
890 if ( ( p_tcaphash_begincall->context->last_frame != 0
891 && pinfo->num > p_tcaphash_begincall->context->first_frame
892 && (unsigned) pinfo->abs_ts.secs > (unsigned)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
893 ) ||
894 ( p_tcaphash_begincall->context->last_frame == 0
895 && pinfo->num > p_tcaphash_begincall->context->first_frame
896 && (unsigned)pinfo->abs_ts.secs > (unsigned)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
900 /* we decide that we have a new request */
901 /* Append new record to the list */
902 #ifdef DEBUG_TCAPSRT
903 dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
904 dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_begincall->context->last_frame );
905 #endif
906 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
907 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
909 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
910 p_tcaphash_context,
911 pinfo);
912 #ifdef DEBUG_TCAPSRT
913 dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
914 #endif
915 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
916 } else { /* timeout or message lost */
918 /* If the Tid is reused for a closed Transaction */
919 /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
920 /* (this is the case, for pre-arranged END, the transaction is marked as closed */
921 /* by the upper layer, thank to a callback method close) */
922 if ( p_tcaphash_begincall->context->closed) {
923 #ifdef DEBUG_TCAPSRT
924 dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
925 dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_begincall->context->last_frame );
926 #endif
927 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
928 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
929 p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
930 p_tcaphash_context,
931 pinfo);
933 #ifdef DEBUG_TCAPSRT
934 dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
935 #endif
936 update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
938 } else {
939 /* the TCAP session is not closed, so, either messages have been lost */
940 /* or it's a duplicate request. Mark it as such. */
941 #ifdef DEBUG_TCAPSRT
942 dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
943 #endif
944 p_tcaphash_context=p_tcaphash_begincall->context;
945 if (gtcap_DisplaySRT && tree) {
946 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
947 proto_item_set_generated(stat_item);
948 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
949 p_tcaphash_context->first_frame,
950 "Duplicate with session %u in frame %u",
951 p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
952 proto_item_set_generated(pi);
954 return p_tcaphash_context;
955 } /* Previous session closed */
956 } /* test with Timeout or message Lost */
957 break;
958 } /* Next call is NULL */
959 /* Repeat the tests for the next record with the same transaction identifier */
960 p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
961 } while (p_tcaphash_begincall != NULL );
963 * End of analyze for the list be TC_BEGIN with same transaction ID
965 } else { /* p_tcaphash_begincall has not been found */
967 * Create a new TCAP context
969 #ifdef DEBUG_TCAPSRT
970 dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
971 #endif
973 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
974 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
975 p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
977 #ifdef DEBUG_TCAPSRT
978 dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
979 dbg(11,"Frame reqlink #%u ", pinfo->num);
980 #endif
981 update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
984 /* display tcap session, if available */
985 if ( gtcap_DisplaySRT && tree &&
986 p_tcaphash_context &&
987 p_tcaphash_context->session_id) {
988 stat_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_tcap_stat, &stat_item, "Stat");
989 proto_item_set_generated(stat_item);
990 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
991 proto_item_set_generated(pi);
993 /* add link to response frame, if available */
994 /* p_tcaphash_begincall->context->last_frame) */
995 if( p_tcaphash_context->last_frame != 0 ){
996 #ifdef DEBUG_TCAPSRT
997 dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
998 #endif
999 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1000 p_tcaphash_context->last_frame,
1001 "End of session in frame %u",
1002 p_tcaphash_context->last_frame);
1003 proto_item_set_generated(pi);
1006 return p_tcaphash_context;
1010 * Try to find a TCAP session according to the source and destination
1011 * Identifier given in the TC_CONT
1012 * If nothing is found, it is probably a session in opening state, so try to find
1013 * a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
1014 * Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
1015 * and display the available info for the TCAP context
1017 static struct tcaphash_context_t *
1018 tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1019 struct tcapsrt_info_t *p_tcapsrt_info)
1021 struct tcaphash_context_t *p_tcaphash_context=NULL;
1022 struct tcaphash_contcall_t *p_tcaphash_contcall;
1023 struct tcaphash_cont_info_key_t tcaphash_cont_key;
1024 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1025 struct tcaphash_begincall_t *p_tcaphash_begincall;
1026 struct tcaphash_end_info_key_t tcaphash_end_key;
1027 proto_item *pi;
1028 proto_item *stat_item=NULL;
1029 proto_tree *stat_tree=NULL;
1030 bool use_dst = false;
1032 #ifdef DEBUG_TCAPSRT
1033 dbg(51,"src %s srcTid %lx dst %s dstTid %lx ", address_to_str(pinfo->pool, &pinfo->src), p_tcapsrt_info->src_tid, address_to_str(pinfo->pool, &pinfo->dst), p_tcapsrt_info->dst_tid);
1034 dbg(10,"\n Hcont #%u ", pinfo->num);
1035 #endif
1037 /* look only for matching request, if matching conversation is available. */
1038 tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
1039 tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
1040 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1042 /* We have MTP3 PCs (so we can safely do this cast) */
1043 tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1044 tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1045 } else {
1046 /* Don't have MTP3 PCs (have SCCP GT ?) */
1047 tcaphash_cont_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src));
1048 tcaphash_cont_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst));
1050 tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
1052 #ifdef DEBUG_TCAPSRT
1053 dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
1054 dbg(51,"addr %s %s ", address_to_str(pinfo->pool, &pinfo->src), address_to_str(pinfo->pool, &pinfo->dst));
1055 dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
1056 #endif
1057 p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
1058 if(p_tcaphash_contcall) {
1059 #ifdef DEBUG_TCAPSRT
1060 dbg(12,"CFound ");
1061 #endif
1062 p_tcaphash_context=p_tcaphash_contcall->context;
1063 } else { /* cont not found */
1064 #ifdef DEBUG_TCAPSRT
1065 dbg(12,"CnotFound ");
1066 #endif
1067 /* Find the TCAP transaction according to the TC_BEGIN (from dtid,dst) */
1068 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1069 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1071 /* We have MTP3 PCs (so we can safely do this cast) */
1072 tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1073 } else {
1074 /* Don't have MTP3 PCs (have SCCP GT ?) */
1075 tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst));
1077 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1079 #ifdef DEBUG_TCAPSRT
1080 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1081 dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst));
1082 dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
1083 #endif
1084 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, false);
1085 if(!p_tcaphash_begincall){
1086 try_src:
1087 /* can this actually happen? */
1088 #ifdef DEBUG_TCAPSRT
1089 dbg(12,"BNotFound trying stid,src");
1090 #endif
1091 /* Do we have a continue from the same source? (stid,src) */
1092 use_dst = true;
1093 tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
1094 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1096 /* We have MTP3 PCs (so we can safely do this cast) */
1097 tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1098 } else {
1099 /* Don't have MTP3 PCs (have SCCP GT ?) */
1100 tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src));
1102 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1103 #ifdef DEBUG_TCAPSRT
1104 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1105 dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->src));
1106 dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
1107 #endif
1108 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,false);
1110 if(p_tcaphash_begincall &&
1111 !p_tcaphash_begincall->context->contcall ) {
1112 #ifdef DEBUG_TCAPSRT
1113 dbg(12,"BFound \n");
1114 #endif
1115 p_tcaphash_context=p_tcaphash_begincall->context;
1116 p_tcaphash_context->responded=true;
1118 #ifdef DEBUG_TCAPSRT
1119 dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
1120 dbg(11,"Frame reqlink #%u \n", pinfo->num);
1121 #endif
1122 create_tcaphash_cont(&tcaphash_cont_key,
1123 p_tcaphash_begincall->context);
1125 /* Create END for (stid,src) or (dtid,dst) */
1126 tcaphash_end_key.tid = use_dst ? p_tcapsrt_info->dst_tid : p_tcapsrt_info->src_tid;
1127 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1129 /* We have MTP3 PCs (so we can safely do this cast) */
1130 tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)(use_dst ? pinfo->dst.data : pinfo->src.data));
1131 tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)(use_dst ? pinfo->src.data : pinfo->dst.data));
1132 } else {
1133 /* Don't have MTP3 PCs (have SCCP GT ?) */
1134 tcaphash_end_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, use_dst ? &pinfo->dst : &pinfo->src));
1135 tcaphash_end_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, use_dst ? &pinfo->src : &pinfo->dst));
1137 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1139 #ifdef DEBUG_TCAPSRT
1140 dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
1141 dbg(51,"addr %s ", address_to_str(pinfo->pool, use_dst ? &pinfo->dst : &pinfo->src));
1142 dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1143 dbg(11,"Frame reqlink #%u ", pinfo->num);
1144 #endif
1145 create_tcaphash_end(&tcaphash_end_key,
1146 p_tcaphash_begincall->context);
1148 } else { /* Begin not found */
1149 #ifdef DEBUG_TCAPSRT
1150 dbg(12,"BnotFound ");
1151 #endif
1152 if (!use_dst) {
1153 /* make another try with src tid / address */
1154 goto try_src;
1156 } /* begin found */
1157 } /* cont found */
1158 /* display tcap session, if available */
1159 if (gtcap_DisplaySRT && tree &&
1160 p_tcaphash_context &&
1161 p_tcaphash_context->session_id) {
1162 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
1163 proto_item_set_generated(stat_item);
1164 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1165 proto_item_set_generated(pi);
1168 return p_tcaphash_context;
1172 * Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
1173 * If nothing is found,
1174 * - either it is a session in opening state,
1175 * - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
1176 * so try to find a tcap session registered with a TC_BEGIN "key",
1177 * matching the destination Id of the TC_END
1178 * Then associate the TC_CONT "key" to the TCAP context
1179 * and display the available info for the TCAP context
1182 static struct tcaphash_context_t *
1183 tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1184 struct tcapsrt_info_t *p_tcapsrt_info)
1186 struct tcaphash_context_t *p_tcaphash_context=NULL;
1188 struct tcaphash_end_info_key_t tcaphash_end_key;
1189 struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
1191 struct tcaphash_begin_info_key_t tcaphash_begin_key;
1192 struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
1193 proto_item *pi;
1194 nstime_t delta;
1195 proto_item *stat_item=NULL;
1196 proto_tree *stat_tree=NULL;
1198 #ifdef DEBUG_TCAPSRT
1199 dbg(51,"src %s dst %s dstTid %lx ", address_to_str(pinfo->pool, &pinfo->src), address_to_str(pinfo->pool, &pinfo->dst), p_tcapsrt_info->dst_tid);
1200 dbg(10,"\n Hend #%u ", pinfo->num);
1201 #endif
1202 /* look only for matching request, if matching conversation is available. */
1203 tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
1204 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1206 /* We have MTP3 PCs (so we can safely do this cast) */
1207 tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1208 tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1209 } else {
1210 /* Don't have MTP3 PCs (have SCCP GT ?) */
1211 tcaphash_end_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src));
1212 tcaphash_end_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst));
1214 tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
1216 #ifdef DEBUG_TCAPSRT
1217 dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
1218 dbg(11,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst));
1219 dbg(51,"Tid %lx ",tcaphash_end_key.tid);
1220 #endif
1221 p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,true);
1223 if(!p_tcaphash_endcall) {
1224 #ifdef DEBUG_TCAPSRT
1225 dbg(12,"EnotFound ");
1226 #endif
1227 tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
1228 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1230 /* We have MTP3 PCs (so we can safely do this cast) */
1231 tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1232 } else {
1233 /* Don't have MTP3 PCs (have SCCP GT ?) */
1234 tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst));
1236 tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
1238 #ifdef DEBUG_TCAPSRT
1239 dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
1240 dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst));
1241 dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
1242 #endif
1243 p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,false);
1244 if(!p_tcaphash_begincall) {
1245 #ifdef DEBUG_TCAPSRT
1246 dbg(12,"BnotFound ");
1247 #endif
1250 if (p_tcaphash_endcall) {
1251 /* Use the TC_BEGIN Destination reference */
1252 p_tcaphash_context=p_tcaphash_endcall->context;
1253 } else if (p_tcaphash_begincall) {
1254 /* Use the TC_BEGIN Source reference */
1255 p_tcaphash_context=p_tcaphash_begincall->context;
1258 if (p_tcaphash_context) {
1260 #ifdef DEBUG_TCAPSRT
1261 dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1262 #endif
1263 if (gtcap_DisplaySRT && tree) {
1264 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
1265 proto_item_set_generated(stat_item);
1267 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1268 proto_item_set_generated(pi);
1271 #ifdef DEBUG_TCAPSRT
1272 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1273 #endif
1274 /* Indicate the frame to which this is a reply. */
1275 if (gtcap_DisplaySRT && stat_tree) {
1276 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1277 p_tcaphash_context->first_frame,
1278 "Begin of session in frame %u",
1279 p_tcaphash_context->first_frame);
1280 proto_item_set_generated(pi);
1281 /* Calculate Service Response Time */
1282 nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time);
1284 /* display Service Response Time and make it filterable */
1285 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1286 proto_item_set_generated(pi);
1288 /* Close the context and remove it (if needed) */
1289 tcapsrt_close(p_tcaphash_context,pinfo);
1291 } else {/* context present */
1292 #ifdef DEBUG_TCAPSRT
1293 dbg(12,"Context notFound ");
1294 #endif
1296 return p_tcaphash_context;
1300 * ANSI PART
1301 * Create the record identifiying the TCAP transaction
1302 * When the identifier for the transaction is reused, check
1303 * the following criteria before to append a new record:
1304 * - a timeout corresponding to a message retransmission is detected,
1305 * - a message hast been lost
1306 * - or the previous transaction has been be closed
1308 static struct tcaphash_context_t *
1309 tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1310 struct tcapsrt_info_t *p_tcapsrt_info)
1312 struct tcaphash_context_t *p_tcaphash_context=NULL;
1313 struct tcaphash_context_key_t tcaphash_context_key;
1314 struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
1315 struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
1316 proto_item *pi;
1317 nstime_t delta;
1318 bool isResponse=false;
1319 proto_tree * stat_tree=NULL;
1320 proto_item * stat_item=NULL;
1322 /* prepare the key data */
1323 tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
1324 if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type)
1326 /* We have MTP3 PCs (so we can safely do this cast) */
1327 tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
1328 tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
1329 } else {
1330 /* Don't have MTP3 PCs (have SCCP GT ?) */
1331 tcaphash_ansi_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src));
1332 tcaphash_ansi_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst));
1334 tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
1336 /* look up the request */
1337 #ifdef DEBUG_TCAPSRT
1338 dbg(10,"\n Hansi #%u ", pinfo->num);
1339 dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
1340 dbg(51,"PC %s %s ",address_to_str(pinfo->pool, &pinfo->src), address_to_str(pinfo->pool, &pinfo->dst));
1341 dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
1342 #endif
1343 p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
1344 wmem_map_lookup(tcaphash_ansi, &tcaphash_ansi_key);
1346 if (p_tcaphash_ansicall) {
1347 /* Walk through list of transaction with identical keys */
1348 do {
1349 /* Check if the request with this reqSeqNum has been seen */
1350 if (pinfo->num == p_tcaphash_ansicall->context->first_frame) {
1351 /* We have seen this request before -> do nothing */
1352 #ifdef DEBUG_TCAPSRT
1353 dbg(22,"Request already seen ");
1354 #endif
1355 isResponse=false;
1356 p_tcaphash_context=p_tcaphash_ansicall->context;
1357 break;
1360 /* Check if the response with this reqSeqNum has been seen */
1361 if (pinfo->num == p_tcaphash_ansicall->context->last_frame) {
1362 /* We have seen this response before -> do nothing */
1363 #ifdef DEBUG_TCAPSRT
1364 dbg(22,"Response already seen ");
1365 #endif
1366 isResponse=true;
1367 p_tcaphash_context=p_tcaphash_ansicall->context;
1368 break;
1371 /* Check for the first Request without Response
1372 received before this frame */
1373 if ( pinfo->num > p_tcaphash_ansicall->context->first_frame &&
1374 p_tcaphash_ansicall->context->last_frame==0 ) {
1375 /* Take it, and update the context */
1377 #ifdef DEBUG_TCAPSRT
1378 dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1379 #endif
1380 p_tcaphash_ansicall->context->last_frame = pinfo->num;
1381 p_tcaphash_ansicall->context->responded = true;
1382 p_tcaphash_ansicall->context->closed = true;
1383 p_tcaphash_context=p_tcaphash_ansicall->context;
1384 isResponse=true;
1386 if (gtcap_DisplaySRT && tree) {
1387 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
1388 proto_item_set_generated(stat_item);
1390 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1391 proto_item_set_generated(pi);
1393 #ifdef DEBUG_TCAPSRT
1394 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1395 #endif
1396 /* Indicate the frame to which this is a reply. */
1397 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1398 p_tcaphash_context->first_frame,
1399 "Begin of session in frame %u",
1400 p_tcaphash_context->first_frame);
1401 proto_item_set_generated(pi);
1402 /* Calculate Service Response Time */
1403 nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time);
1405 /* display Service Response Time and make it filterable */
1406 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1407 proto_item_set_generated(pi);
1409 break;
1410 } /* Lastframe=0, so take it */
1413 /* If the last record for Tcap transaction with identifier has been reached */
1414 if (!p_tcaphash_ansicall->next_ansicall) {
1415 /* check if we have to create a new record or not */
1416 /* if last request has been responded (response number in known)
1417 and this request appears after last response (has bigger frame number)
1418 and last request occurred after the timeout for repetition,
1420 if last request hasn't been responded (so number unknown)
1421 and this request appears after last request (has bigger frame number)
1422 and this request occurred after the timeout for message lost */
1423 if ( ( p_tcaphash_ansicall->context->last_frame != 0
1424 && pinfo->num > p_tcaphash_ansicall->context->first_frame
1425 && (unsigned) pinfo->abs_ts.secs > (unsigned)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
1426 ) ||
1427 ( p_tcaphash_ansicall->context->last_frame == 0
1428 && pinfo->num > p_tcaphash_ansicall->context->first_frame
1429 && (unsigned)pinfo->abs_ts.secs > (unsigned)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
1433 /* we decide that we have a new request */
1434 /* Append new record to the list */
1435 #ifdef DEBUG_TCAPSRT
1436 dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
1437 dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_ansicall->context->last_frame );
1438 #endif
1439 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1440 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1441 p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1442 p_tcaphash_context,
1443 pinfo);
1445 #ifdef DEBUG_TCAPSRT
1446 dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
1447 #endif
1448 update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1449 p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1450 } else {
1452 /* If the Tid is reused for a closed Transaction */
1453 if ( p_tcaphash_ansicall->context->closed) {
1454 #ifdef DEBUG_TCAPSRT
1455 dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
1456 dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_ansicall->context->last_frame );
1457 #endif
1458 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1459 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1460 p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
1461 p_tcaphash_context,
1462 pinfo);
1464 #ifdef DEBUG_TCAPSRT
1465 dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
1466 #endif
1467 update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
1468 p_tcaphash_ansicall=p_new_tcaphash_ansicall;
1470 } else {
1471 /* the Tid is reused for an opened Transaction */
1472 /* so, this is the reply to the request of our context */
1473 p_tcaphash_context=p_tcaphash_ansicall->context;
1474 #ifdef DEBUG_TCAPSRT
1475 dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
1476 #endif
1478 if (gtcap_DisplaySRT && tree) {
1479 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
1480 proto_item_set_generated(stat_item);
1482 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1483 proto_item_set_generated(pi);
1485 #ifdef DEBUG_TCAPSRT
1486 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1487 #endif
1488 /* Indicate the frame to which this is a reply. */
1489 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1490 p_tcaphash_context->first_frame,
1491 "Begin of session in frame %u",
1492 p_tcaphash_context->first_frame);
1493 proto_item_set_generated(pi);
1494 /* Calculate Service Response Time */
1495 nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time);
1497 /* display Service Response Time and make it filterable */
1498 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1499 proto_item_set_generated(pi);
1501 p_tcaphash_context=p_tcaphash_ansicall->context;
1502 } /* test with Timeout */
1503 } /* closed */
1504 break;
1505 } /* Next call is NULL */
1506 p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
1507 } while (p_tcaphash_ansicall != NULL );
1509 * New TCAP context
1511 } else { /* p_tcaphash_ansicall has not been found */
1512 #ifdef DEBUG_TCAPSRT
1513 dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
1514 #endif
1516 tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
1517 p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
1518 p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
1520 #ifdef DEBUG_TCAPSRT
1521 dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
1522 dbg(11,"Frame reqlink #%u ", pinfo->num);
1523 #endif
1524 update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
1527 /* display tcap session, if available */
1528 if ( gtcap_DisplaySRT && tree &&
1529 p_tcaphash_context &&
1530 p_tcaphash_context->session_id) {
1531 stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat");
1532 proto_item_set_generated(stat_item);
1533 pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
1534 proto_item_set_generated(pi);
1538 /* add link to response frame, if available */
1539 if( gtcap_DisplaySRT && stat_tree &&
1540 p_tcaphash_ansicall->context->last_frame != 0){
1541 if (!isResponse) { /* Request */
1542 #ifdef DEBUG_TCAPSRT
1543 dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
1544 #endif
1545 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
1546 p_tcaphash_ansicall->context->last_frame,
1547 "End of session in frame %u",
1548 p_tcaphash_ansicall->context->last_frame);
1549 proto_item_set_generated(pi);
1550 } else { /* Response */
1551 #ifdef DEBUG_TCAPSRT
1552 dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
1553 #endif
1554 /* Indicate the frame to which this is a reply. */
1555 if (gtcap_DisplaySRT) {
1556 pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
1557 p_tcaphash_context->first_frame,
1558 "Begin of session in frame %u",
1559 p_tcaphash_context->first_frame);
1560 proto_item_set_generated(pi);
1561 /* Calculate Service Response Time */
1562 nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time);
1564 /* display Service Response Time and make it filterable */
1565 pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
1566 proto_item_set_generated(pi);
1568 } /* Request or Response */
1570 return p_tcaphash_context;
1574 * Service Response Time analyze
1575 * Called just after dissector call
1576 * Associate a TCAP context to a tcap session and display session related infomations
1577 * like the first frame, the last, the session duration,
1578 * and a uniq session identifier for the filtering
1580 * For ETSI tcap, the TCAP context can be reached through three keys
1581 * - a key (BEGIN) identifying the session according to the tcap source identifier
1582 * - a key (CONT) identifying the established session (src_id and dst_id)
1583 * - a key (END) identifying the session according to the tcap destination identifier
1585 * For ANSI tcap, the TCAP context is reached through a uniq key
1586 * - a key (ANSI) identifying the session according to the tcap identifier
1588 struct tcaphash_context_t *
1589 tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1590 struct tcapsrt_info_t *p_tcapsrt_info)
1592 struct tcaphash_context_t *tcap_context=NULL;
1594 /* if this packet isn't loaded because of a read filter, don't output anything */
1595 if(pinfo == NULL || pinfo->num == 0) {
1596 return NULL;
1599 switch (p_tcapsrt_info->ope) {
1601 case TC_BEGIN:
1602 #ifdef DEBUG_TCAPSRT
1603 dbg(1,"\nTC_BEGIN ");
1604 #endif
1605 tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
1606 break;
1608 case TC_CONT:
1609 #ifdef DEBUG_TCAPSRT
1610 dbg(1,"\nTC_CONT ");
1611 #endif
1612 tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
1613 break;
1615 case TC_ABORT:
1616 #ifdef DEBUG_TCAPSRT
1617 dbg(1,"\nTC_ABORT ");
1618 #endif
1619 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
1620 break;
1622 case TC_END:
1623 #ifdef DEBUG_TCAPSRT
1624 dbg(1,"\nTC_END ");
1625 #endif
1626 tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
1627 break;
1629 case TC_ANSI_ALL:
1630 case TC_ANSI_ABORT:
1631 #ifdef DEBUG_TCAPSRT
1632 dbg(1,"\nTC_ANSI ");
1633 #endif
1634 tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
1635 break;
1637 default:
1638 #ifdef DEBUG_TCAPSRT
1639 dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
1640 #endif
1641 break;
1642 } /* switch tcapop */
1643 #ifdef DEBUG_TCAPSRT
1644 if (tcap_context)
1645 dbg(1,"session %d ", tcap_context->session_id);
1646 #endif
1647 return tcap_context;
1651 * Initialize the Message Info used by the main dissector
1652 * Data are linked to a TCAP transaction
1654 struct tcapsrt_info_t *
1655 tcapsrt_razinfo(void)
1657 struct tcapsrt_info_t *p_tcapsrt_info ;
1659 /* Global buffer for packet extraction */
1660 tcapsrt_global_current++;
1661 if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
1662 tcapsrt_global_current=0;
1665 p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
1666 memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
1668 return p_tcapsrt_info;
1671 void
1672 tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
1673 packet_info *pinfo)
1675 #ifdef DEBUG_TCAPSRT
1676 dbg(60,"Force close ");
1677 #endif
1678 if (p_tcaphash_context) {
1679 p_tcaphash_context->responded=true;
1680 p_tcaphash_context->last_frame = pinfo->num;
1681 p_tcaphash_context->end_time = pinfo->abs_ts;
1682 p_tcaphash_context->closed=true;
1684 /* If the endkey is present */
1685 if (p_tcaphash_context->endcall
1686 && !gtcap_PersistentSRT) {
1687 if (p_tcaphash_context->endcall->next_endcall) {
1688 if (p_tcaphash_context->endcall->previous_endcall ) {
1689 #ifdef DEBUG_TCAPSRT
1690 dbg(20,"deplace Ehash ");
1691 #endif
1692 p_tcaphash_context->endcall->previous_endcall->next_endcall
1693 = p_tcaphash_context->endcall->next_endcall;
1694 p_tcaphash_context->endcall->next_endcall->previous_endcall
1695 = p_tcaphash_context->endcall->previous_endcall;
1696 wmem_map_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1697 } else {
1698 /* cannot remove the father */
1699 #ifdef DEBUG_TCAPSRT
1700 dbg(20,"father Ehash ");
1701 #endif
1702 } /* no previous link, so father */
1703 } else if (!gtcap_PersistentSRT) {
1704 #ifdef DEBUG_TCAPSRT
1705 dbg(20,"remove Ehash ");
1706 #endif
1707 wmem_map_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
1709 } /* endcall without chained string */
1710 } /* no endcall */
1713 /* If the contkey is present */
1714 if (p_tcaphash_context->contcall
1715 && !gtcap_PersistentSRT) {
1716 if (p_tcaphash_context->contcall->next_contcall) {
1717 if (p_tcaphash_context->contcall->previous_contcall ) {
1718 #ifdef DEBUG_TCAPSRT
1719 dbg(20,"deplace Chash ");
1720 #endif
1721 p_tcaphash_context->contcall->previous_contcall->next_contcall
1722 = p_tcaphash_context->contcall->next_contcall;
1723 p_tcaphash_context->contcall->next_contcall->previous_contcall
1724 = p_tcaphash_context->contcall->previous_contcall;
1725 wmem_map_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1726 } else {
1727 /* cannot remove the father */
1728 #ifdef DEBUG_TCAPSRT
1729 dbg(20,"father Chash ");
1730 #endif
1731 } /* no previous link, so father */
1732 } else if (!gtcap_PersistentSRT) {
1733 #ifdef DEBUG_TCAPSRT
1734 dbg(20,"remove Chash ");
1735 #endif
1736 wmem_map_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
1737 } /* contcall without chained string */
1738 } /* no contcall */
1741 /* If the beginkey is present */
1742 if (p_tcaphash_context->begincall
1743 && !gtcap_PersistentSRT) {
1744 if (p_tcaphash_context->begincall->next_begincall) {
1745 if (p_tcaphash_context->begincall->previous_begincall ) {
1746 #ifdef DEBUG_TCAPSRT
1747 dbg(20,"deplace Bhash ");
1748 #endif
1749 p_tcaphash_context->begincall->previous_begincall->next_begincall
1750 = p_tcaphash_context->begincall->next_begincall;
1751 p_tcaphash_context->begincall->next_begincall->previous_begincall
1752 = p_tcaphash_context->begincall->previous_begincall;
1753 wmem_map_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1754 } else {
1755 /* cannot remove the father */
1756 #ifdef DEBUG_TCAPSRT
1757 dbg(20,"father Bhash ");
1758 #endif
1760 } else if (!gtcap_PersistentSRT) {
1761 #ifdef DEBUG_TCAPSRT
1762 dbg(20,"remove Bhash ");
1763 #endif
1764 wmem_map_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
1765 } /* begincall without chained string */
1766 } /* no begincall */
1768 /* If the ansikey is present */
1769 if (p_tcaphash_context->ansicall
1770 && !gtcap_PersistentSRT) {
1771 if (p_tcaphash_context->ansicall->next_ansicall) {
1772 if (p_tcaphash_context->ansicall->previous_ansicall ) {
1773 #ifdef DEBUG_TCAPSRT
1774 dbg(20,"deplace Ahash ");
1775 #endif
1776 p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
1777 = p_tcaphash_context->ansicall->next_ansicall;
1778 p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
1779 = p_tcaphash_context->ansicall->previous_ansicall;
1780 wmem_map_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1781 } else {
1782 /* cannot remove the father */
1783 #ifdef DEBUG_TCAPSRT
1784 dbg(20,"father Ahash ");
1785 #endif
1787 } else if (!gtcap_PersistentSRT) {
1788 #ifdef DEBUG_TCAPSRT
1789 dbg(20,"remove Ahash ");
1790 #endif
1791 wmem_map_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
1792 } /* ansicall without chained string */
1793 } /* no ansicall */
1795 if (!gtcap_PersistentSRT) {
1796 #ifdef DEBUG_TCAPSRT
1797 dbg(20,"remove context ");
1798 #endif
1799 wmem_map_remove(tcaphash_context, p_tcaphash_context->key);
1801 } else { /* no context */
1802 #ifdef DEBUG_TCAPSRT
1803 dbg(20,"No context to remove ");
1804 #endif
1808 const value_string tcap_component_type_str[] = {
1809 { TCAP_COMP_INVOKE, "Invoke" },
1810 { TCAP_COMP_RRL, "Return Result(L)" },
1811 { TCAP_COMP_RE, "Return Error" },
1812 { TCAP_COMP_REJECT, "Reject" },
1813 { TCAP_COMP_RRN, "Return Result(NL)" },
1814 { 0, NULL }
1817 static int
1818 dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
1820 proto_item *item=NULL;
1821 proto_tree *tree=NULL;
1823 struct tcaphash_context_t * p_tcap_context;
1824 dissector_handle_t subdissector_handle;
1825 asn1_ctx_t asn1_ctx;
1826 int8_t ber_class;
1827 bool pc;
1828 int tag;
1829 struct tcap_private_t *p_tcap_private;
1831 /* Check if ANSI TCAP and call the ANSI TCAP dissector if that's the case
1832 * PackageType ::= CHOICE { unidirectional [PRIVATE 1] IMPLICIT UniTransactionPDU,
1833 * queryWithPerm [PRIVATE 2] IMPLICIT TransactionPDU,
1834 * queryWithoutPerm [PRIVATE 3] IMPLICIT TransactionPDU,
1835 * response [PRIVATE 4] IMPLICIT TransactionPDU,
1836 * conversationWithPerm [PRIVATE 5] IMPLICIT TransactionPDU,
1837 * conversationWithoutPerm [PRIVATE 6] IMPLICIT TransactionPDU,
1838 * abort [PRIVATE 22] IMPLICIT Abort
1843 get_ber_identifier(tvb, 0, &ber_class, &pc, &tag);
1845 if(ber_class == BER_CLASS_PRI){
1846 switch (tag){
1848 case 1:
1849 case 2:
1850 case 3:
1851 case 4:
1852 case 5:
1853 case 6:
1854 case 22:
1855 return call_dissector(ansi_tcap_handle, tvb, pinfo, parent_tree);
1857 default:
1858 return tvb_captured_length(tvb);
1862 /* ITU TCAP */
1863 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
1865 tcap_top_tree = parent_tree;
1866 tcap_stat_tree = NULL;
1868 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCAP");
1870 /* create display subtree for the protocol */
1871 if(parent_tree){
1872 item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, ENC_NA);
1873 tree = proto_item_add_subtree(item, ett_tcap);
1874 tcap_stat_tree=tree;
1876 cur_oid = NULL;
1877 tcapext_oid = NULL;
1879 p_tcap_private = wmem_new0(pinfo->pool, struct tcap_private_t);
1880 asn1_ctx.value_ptr = p_tcap_private;
1881 gp_tcapsrt_info=tcapsrt_razinfo();
1882 tcap_subdissector_used=false;
1883 gp_tcap_context=NULL;
1884 dissect_tcap_TCMessage(false, tvb, 0, &asn1_ctx, tree, -1);
1886 if (!tcap_subdissector_used ) {
1887 p_tcap_context=tcapsrt_call_matching(tvb, pinfo, tcap_stat_tree, gp_tcapsrt_info);
1888 p_tcap_private->context=p_tcap_context;
1890 /* If the current message is TCAP only,
1891 * save the Application Context Name for the next messages
1893 if ( p_tcap_context && cur_oid && !p_tcap_context->oid_present ) {
1894 /* Save the application context and the sub dissector */
1895 (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid));
1896 p_tcap_context->oid_present=true;
1897 if ( (subdissector_handle = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) {
1898 p_tcap_context->subdissector_handle=subdissector_handle;
1899 p_tcap_context->subdissector_present=true;
1902 if (p_tcap_context && p_tcap_context->callback) {
1903 /* Callback function for the upper layer */
1904 (p_tcap_context->callback)(tvb, pinfo, tcap_stat_tree, p_tcap_context);
1907 return tvb_captured_length(tvb);
1910 void
1911 proto_reg_handoff_tcap(void)
1914 data_handle = find_dissector("data");
1915 ansi_tcap_handle = find_dissector_add_dependency("ansi_tcap", proto_tcap);
1916 ber_oid_dissector_table = find_dissector_table("ber.oid");
1918 ss7pc_address_type = address_type_get_by_name("AT_SS7PC");
1920 #include "packet-tcap-dis-tab.c"
1923 static void init_tcap(void);
1924 static void cleanup_tcap(void);
1926 void
1927 proto_register_tcap(void)
1930 /* Setup list of header fields See Section 1.6.1 for details*/
1931 static hf_register_info hf[] = {
1932 { &hf_tcap_tag,
1933 { "Tag",
1934 "tcap.msgtype",
1935 FT_UINT8, BASE_HEX, NULL, 0,
1936 NULL, HFILL }
1938 { &hf_tcap_length,
1939 { "Length",
1940 "tcap.len",
1941 FT_UINT8, BASE_DEC, NULL, 0,
1942 NULL, HFILL }
1944 { &hf_tcap_data,
1945 { "Data",
1946 "tcap.data",
1947 FT_BYTES, BASE_NONE, NULL, 0,
1948 NULL, HFILL }
1950 { &hf_tcap_tid,
1951 { "Transaction Id",
1952 "tcap.tid",
1953 FT_BYTES, BASE_NONE, NULL, 0,
1954 NULL, HFILL }
1956 { &hf_tcap_constructor_eoc,
1957 { "CONSTRUCTOR EOC",
1958 "tcap.constructor_eoc",
1959 FT_UINT16, BASE_HEX, NULL, 0,
1960 NULL, HFILL }
1962 /* Tcap Service Response Time */
1963 { &hf_tcapsrt_SessionId,
1964 { "Session Id",
1965 "tcap.srt.session_id",
1966 FT_UINT32, BASE_DEC, NULL, 0x0,
1967 NULL, HFILL }
1969 { &hf_tcapsrt_BeginSession,
1970 { "Begin Session",
1971 "tcap.srt.begin",
1972 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1973 "SRT Begin of Session", HFILL }
1975 { &hf_tcapsrt_EndSession,
1976 { "End Session",
1977 "tcap.srt.end",
1978 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1979 "SRT End of Session", HFILL }
1981 { &hf_tcapsrt_SessionTime,
1982 { "Session duration",
1983 "tcap.srt.sessiontime",
1984 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1985 "Duration of the TCAP session", HFILL }
1987 { &hf_tcapsrt_Duplicate,
1988 { "Session Duplicate",
1989 "tcap.srt.duplicate",
1990 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1991 "SRT Duplicated with Session", HFILL }
1993 #include "packet-tcap-hfarr.c"
1996 /* Setup protocol subtree array */
1997 static int *ett[] = {
1998 &ett_tcap,
1999 &ett_param,
2000 &ett_otid,
2001 &ett_dtid,
2002 &ett_tcap_stat,
2003 #include "packet-tcap-ettarr.c"
2006 /*static enum_val_t tcap_options[] = {
2007 { "itu", "ITU", ITU_TCAP_STANDARD },
2008 { "ansi", "ANSI", ANSI_TCAP_STANDARD },
2009 { NULL, NULL, 0 }
2010 };*/
2012 module_t *tcap_module;
2014 /* Register the protocol name and description */
2015 proto_tcap = proto_register_protocol(PNAME, PSNAME, PFNAME);
2017 /* Required function calls to register the header fields and subtrees used */
2018 proto_register_field_array(proto_tcap, hf, array_length(hf));
2019 proto_register_subtree_array(ett, array_length(ett));
2021 ansi_sub_dissectors = register_dissector_table("ansi_tcap.ssn", "ANSI SSN", proto_tcap, FT_UINT8, BASE_DEC);
2022 itu_sub_dissectors = register_dissector_table("itu_tcap.ssn", "ITU SSN", proto_tcap, FT_UINT8, BASE_DEC);
2024 tcap_module = prefs_register_protocol(proto_tcap, NULL);
2026 #if 0
2027 prefs_register_enum_preference(tcap_module, "standard", "ITU TCAP standard",
2028 "The SS7 standard used in ITU TCAP packets",
2029 &tcap_standard, tcap_options, false);
2030 #else
2031 prefs_register_obsolete_preference(tcap_module, "standard");
2032 #endif
2034 #if 0
2035 prefs_register_bool_preference(tcap_module, "lock_info_col", "Lock Info column",
2036 "Always show TCAP in Info column",
2037 &lock_info_col);
2038 #else
2039 prefs_register_obsolete_preference(tcap_module, "lock_info_col");
2040 #endif
2042 /* Set default SSNs */
2043 range_convert_str(wmem_epan_scope(), &global_ssn_range, "", MAX_SSN);
2045 prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs",
2046 "SCCP (and SUA) SSNs to decode as TCAP",
2047 &global_ssn_range, MAX_SSN);
2049 prefs_register_obsolete_preference(tcap_module, "srt");
2051 prefs_register_bool_preference(tcap_module, "persistentsrt",
2052 "Persistent stats for SRT",
2053 "Statistics for Response Time",
2054 &gtcap_PersistentSRT);
2056 prefs_register_uint_preference(tcap_module, "repetitiontimeout",
2057 "Repetition timeout",
2058 "Maximal delay for message repetition",
2059 10, &gtcap_RepetitionTimeout);
2061 prefs_register_uint_preference(tcap_module, "losttimeout",
2062 "Lost timeout",
2063 "Maximal delay for message lost",
2064 10, &gtcap_LostTimeout);
2066 /* 'globally' register dissector */
2067 tcap_handle = register_dissector("tcap", dissect_tcap, proto_tcap);
2069 /* hash-tables for SRT */
2070 tcaphash_context = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_context_calchash, tcaphash_context_equal);
2071 tcaphash_begin = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_begin_calchash, tcaphash_begin_equal);
2072 tcaphash_cont = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_cont_calchash, tcaphash_cont_equal);
2073 tcaphash_end = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_end_calchash, tcaphash_end_equal);
2074 tcaphash_ansi = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_ansi_calchash, tcaphash_ansi_equal);
2076 register_init_routine(&init_tcap);
2077 register_cleanup_routine(&cleanup_tcap);
2081 static void range_delete_callback(uint32_t ssn, void *ptr _U_)
2083 if ( ssn && !get_ansi_tcap_subdissector(ssn) && !get_itu_tcap_subdissector(ssn) ) {
2084 dissector_delete_uint("sccp.ssn", ssn, tcap_handle);
2088 static void range_add_callback(uint32_t ssn, void *ptr _U_)
2090 if (ssn && !get_ansi_tcap_subdissector(ssn) && !get_itu_tcap_subdissector(ssn) ) {
2091 dissector_add_uint("sccp.ssn", ssn, tcap_handle);
2096 static void init_tcap(void)
2098 ssn_range = range_copy(wmem_epan_scope(), global_ssn_range);
2099 range_foreach(ssn_range, range_add_callback, NULL);
2101 /* Reset the session counter */
2102 tcapsrt_global_SessionId=1;
2104 /* Display of SRT is enabled
2105 * 1) For wireshark only if Persistent Stat is enabled
2106 * 2) For tshark, if the CLI SRT tap is registered
2108 gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_StatSRT;
2111 static void cleanup_tcap(void)
2113 range_foreach(ssn_range, range_delete_callback, NULL);
2114 wmem_free(wmem_epan_scope(), ssn_range);
2117 static int
2118 // NOLINTNEXTLINE(misc-no-recursion)
2119 dissect_tcap_param(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset)
2121 int tag_offset, saved_offset, len_offset;
2122 tvbuff_t *next_tvb;
2123 proto_tree *subtree;
2124 int8_t ber_class;
2125 bool pc;
2126 int32_t tag;
2127 uint32_t len;
2128 uint32_t tag_length;
2129 uint32_t len_length;
2130 bool ind_field;
2132 while (tvb_reported_length_remaining(tvb, offset) > 0)
2134 saved_offset = offset;
2136 offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
2137 tag_offset = offset;
2138 offset = get_ber_length(tvb, offset, &len, &ind_field);
2139 len_offset = offset;
2141 tag_length = tag_offset - saved_offset;
2142 len_length = len_offset - tag_offset;
2144 if (pc)
2146 subtree = proto_tree_add_subtree(tree, tvb, saved_offset,
2147 len + (len_offset - saved_offset), ett_param, NULL,
2148 "CONSTRUCTOR");
2149 proto_tree_add_uint_format(subtree, hf_tcap_tag, tvb,
2150 saved_offset, tag_length, tag,
2151 "CONSTRUCTOR Tag");
2152 proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset,
2153 tag_length, ber_class);
2155 proto_tree_add_uint(subtree, hf_tcap_length, tvb, tag_offset,
2156 len_length, len);
2158 if (len - (ind_field ? 2 : 0)) /*should always be positive unless we get an empty constructor pointless? */
2160 next_tvb = tvb_new_subset_length(tvb, offset, len - (ind_field ? 2 : 0));
2161 increment_dissection_depth(actx->pinfo);
2162 dissect_tcap_param(actx, subtree,next_tvb,0);
2163 decrement_dissection_depth(actx->pinfo);
2166 if (ind_field)
2167 proto_tree_add_item(subtree, hf_tcap_constructor_eoc, tvb, offset+len-2, 2, ENC_BIG_ENDIAN);
2169 offset += len;
2171 else
2173 subtree = proto_tree_add_subtree_format(tree, tvb, saved_offset,
2174 len + (len_offset - saved_offset), ett_param, NULL,
2175 "Parameter (0x%.2x)", tag);
2177 proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset,
2178 tag_length, tag);
2180 proto_tree_add_uint(subtree, hf_tcap_length, tvb,
2181 saved_offset+tag_length, len_length, len);
2183 if (len) /* check for NULLS */
2185 next_tvb = tvb_new_subset_length(tvb, offset, len);
2186 dissect_ber_octet_string(true, actx, tree, next_tvb, 0,
2187 hf_tcap_data, NULL);
2190 offset += len;
2193 return offset;
2197 * Call ITU Subdissector to decode the Tcap Component
2199 static bool
2200 dissect_tcap_ITU_ComponentPDU(bool implicit_tag _U_, tvbuff_t *tvb, int offset _U_, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
2202 dissector_handle_t subdissector_handle=NULL;
2203 bool is_subdissector=false;
2204 struct tcaphash_context_t * p_tcap_context=NULL;
2205 struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr;
2208 * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it.
2212 * Handle The TCAP Service Response Time
2214 if (!tcap_subdissector_used) {
2215 p_tcap_context=tcapsrt_call_matching(tvb, actx->pinfo, tcap_stat_tree, gp_tcapsrt_info);
2216 tcap_subdissector_used=false;
2217 gp_tcap_context=p_tcap_context;
2218 p_tcap_private->context=p_tcap_context;
2219 } else {
2220 /* Take the last TCAP context */
2221 p_tcap_context = gp_tcap_context;
2222 p_tcap_private->context=p_tcap_context;
2224 if (p_tcap_context) {
2225 if (cur_oid) {
2226 if (p_tcap_context->oid_present) {
2227 /* We have already an Application Context, check if we have
2228 to fallback to a lower version */
2229 if (strncmp(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid)) != 0) {
2230 /* ACN, changed, Fallback to lower version
2231 * and update the subdissector (purely formal)
2233 (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid));
2234 if ((subdissector_handle = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) {
2235 p_tcap_context->subdissector_handle = subdissector_handle;
2236 p_tcap_context->subdissector_present = true;
2239 } else {
2240 /* We do not have the OID in the TCAP context, so store it */
2241 (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid));
2242 p_tcap_context->oid_present = true;
2243 /* Try to find a subdissector according to OID */
2244 if ((subdissector_handle
2245 = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) {
2246 p_tcap_context->subdissector_handle = subdissector_handle;
2247 p_tcap_context->subdissector_present = true;
2248 } else {
2249 /* Not found, so try to find a subdissector according to SSN */
2250 if ((subdissector_handle = get_itu_tcap_subdissector(actx->pinfo->match_uint))) {
2251 /* Found according to SSN */
2252 p_tcap_context->subdissector_handle = subdissector_handle;
2253 p_tcap_context->subdissector_present = true;
2256 } /* context OID */
2257 } else {
2258 /* Copy the OID from the TCAP context to the current oid */
2259 if (p_tcap_context->oid_present) {
2260 p_tcap_private->oid = (void*)p_tcap_context->oid;
2261 p_tcap_private->acv = true;
2263 } /* no OID */
2264 } /* no TCAP context */
2267 if (p_tcap_context
2268 && p_tcap_context->subdissector_present) {
2269 /* Take the subdissector from the context */
2270 subdissector_handle = p_tcap_context->subdissector_handle;
2271 is_subdissector = true;
2274 /* Have SccpUsersTable protocol taking precedence over sccp.ssn table */
2275 if (!is_subdissector && requested_subdissector_handle) {
2276 is_subdissector = true;
2277 subdissector_handle = requested_subdissector_handle;
2280 if (!is_subdissector) {
2282 * If we do not currently know the subdissector, we have to find it
2283 * - first, according to the OID
2284 * - then according to the SSN
2285 * - and at least, take the default Data handler
2287 if (ber_oid_dissector_table && cur_oid) {
2288 /* Search if we can find the sub protocol according to the A.C.N */
2289 if ((subdissector_handle
2290 = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) {
2291 /* found */
2292 is_subdissector = true;
2293 } else {
2294 /* Search if we can found the sub protocol according to the SSN table */
2295 if ((subdissector_handle
2296 = get_itu_tcap_subdissector(actx->pinfo->match_uint))) {
2297 /* Found according to SSN */
2298 is_subdissector = true;
2299 } else {
2300 /* Nothing found, take the Data handler */
2301 subdissector_handle = data_handle;
2302 is_subdissector = true;
2303 } /* SSN */
2304 } /* ACN */
2305 } else {
2306 /* There is no A.C.N for this transaction, so search in the SSN table */
2307 if ((subdissector_handle = get_itu_tcap_subdissector(actx->pinfo->match_uint))) {
2308 /* Found according to SSN */
2309 is_subdissector = true;
2310 } else {
2311 subdissector_handle = data_handle;
2312 is_subdissector = true;
2314 } /* OID */
2315 } else {
2316 /* We have it already */
2319 /* Call the sub dissector if present, and not already called */
2320 if (is_subdissector) {
2321 bool is_active = call_dissector_only(subdissector_handle, tvb, actx->pinfo, tree, actx->value_ptr);
2322 col_set_fence(actx->pinfo->cinfo, COL_INFO);
2323 if(!is_active){
2324 return false;
2327 return true;
2330 void
2331 call_tcap_dissector(dissector_handle_t handle, tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
2333 requested_subdissector_handle = handle;
2335 TRY {
2336 dissect_tcap(tvb, pinfo, tree, NULL);
2337 } CATCH_ALL {
2338 requested_subdissector_handle = NULL;
2339 RETHROW;
2340 } ENDTRY;
2342 requested_subdissector_handle = NULL;
2346 * Editor modelines
2348 * Local Variables:
2349 * c-basic-offset: 2
2350 * tab-width: 8
2351 * indent-tabs-mode: nil
2352 * End:
2354 * ex: set shiftwidth=2 tabstop=8 expandtab:
2355 * :indentSize=2:tabSize=8:noTabs=true: