1 /* packet-tcap-template.c
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
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"
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 */
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
];
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"
148 /* #define DEBUG_TCAPSRT */
153 static unsigned debug_level
= 99;
156 dbg(unsigned level
, const char* fmt
, ...)
160 if (level
> debug_level
) return;
162 vfprintf(stderr
, fmt
, ap
);
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 */
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
;
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
) )
198 /* calculate a hash key */
200 tcaphash_begin_calchash(const void *k
)
202 const struct tcaphash_begin_info_key_t
*key
= (const struct tcaphash_begin_info_key_t
*) k
;
204 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
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
) ) {
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
) ) {
233 /* calculate a hash key */
235 tcaphash_cont_calchash(const void *k
)
237 const struct tcaphash_cont_info_key_t
*key
= (const struct tcaphash_cont_info_key_t
*) k
;
239 hashkey
= key
->src_tid
+ key
->dst_tid
;
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
) )
259 /* calculate a hash key */
261 tcaphash_end_calchash(const void *k
)
263 const struct tcaphash_end_info_key_t
*key
= (const struct tcaphash_end_info_key_t
*) k
;
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
) )
290 /* calculate a hash key */
292 tcaphash_ansi_calchash(const void *k
)
294 const struct tcaphash_ansi_info_key_t
*key
= (const struct tcaphash_ansi_info_key_t
*) k
;
296 /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
302 * Update a record with the data of the Request
305 update_tcaphash_begincall(struct tcaphash_begincall_t
*p_tcaphash_begincall
,
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
,
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;
338 dbg(10,"+B%d ", p_new_tcaphash_begincall
->context
->session_id
);
340 /* Insert in the chained list */
341 prev_begincall
->next_begincall
= p_new_tcaphash_begincall
;
342 if (prev_begincall
->context
->last_frame
== 0) {
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
355 update_tcaphash_ansicall(struct tcaphash_ansicall_t
*p_tcaphash_ansicall
,
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
,
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;
388 dbg(10,"+A%d ", p_new_tcaphash_ansicall
->context
->session_id
);
390 /* Insert in the chained list */
391 prev_ansicall
->next_ansicall
= p_new_tcaphash_ansicall
;
392 if (prev_ansicall
->context
->last_frame
== 0) {
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;
420 dbg(10,"+C%d ", p_new_tcaphash_contcall
->context
->session_id
);
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;
446 dbg(10,"+E%d ", p_new_tcaphash_endcall
->context
->session_id
);
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
) {
466 if ( p_tcaphash_begincall
->context
) {
468 pinfo
->num
== p_tcaphash_begincall
->context
->first_frame
)
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 */
477 dbg(10,"B%d ", p_tcaphash_begincall
->context
->session_id
);
479 return p_tcaphash_begincall
;
482 dbg(60,"[B%d] ", p_tcaphash_begincall
->context
->session_id
);
485 /* Break when list end is reached */
486 if(p_tcaphash_begincall
->next_begincall
== NULL
) {
488 dbg(23,"End of Blist ");
492 p_tcaphash_begincall
= p_tcaphash_begincall
->next_begincall
;
493 } while (p_tcaphash_begincall
!= NULL
) ;
496 dbg(23,"Not in Bhash ");
504 static struct tcaphash_contcall_t
*
505 find_tcaphash_cont(struct tcaphash_cont_info_key_t
*p_tcaphash_cont_key
,
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
) {
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 */
518 dbg(10,"C%d ", p_tcaphash_contcall
->context
->session_id
);
520 return p_tcaphash_contcall
;
523 dbg(60,"[C%d] ", p_tcaphash_contcall
->context
->session_id
);
526 /* Break when list end is reached */
527 if(p_tcaphash_contcall
->next_contcall
== NULL
) {
529 dbg(23,"End of Clist ");
533 p_tcaphash_contcall
= p_tcaphash_contcall
->next_contcall
;
534 } while (p_tcaphash_contcall
!= NULL
) ;
537 dbg(23,"Not in Chash ");
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
) {
552 if ( p_tcaphash_endcall
->context
) {
554 (p_tcaphash_endcall
->context
->last_frame
?pinfo
->num
== p_tcaphash_endcall
->context
->last_frame
:1)
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 */
564 dbg(10,"E%d ", p_tcaphash_endcall
->context
->session_id
);
566 return p_tcaphash_endcall
;
569 dbg(60,"[E%d] ", p_tcaphash_endcall
->context
->session_id
);
572 /* Break when list end is reached */
573 if(p_tcaphash_endcall
->next_endcall
== NULL
) {
575 dbg(23,"End of Elist ");
579 p_tcaphash_endcall
= p_tcaphash_endcall
->next_endcall
;
580 } while (p_tcaphash_endcall
!= NULL
) ;
583 dbg(23,"Not in Ehash ");
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
,
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
;
611 dbg(10,"S%d ", p_new_tcaphash_context
->session_id
);
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
;
646 dbg(10,"B%d ", p_new_tcaphash_begincall
->context
->session_id
);
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
;
685 dbg(10,"C%d ", p_new_tcaphash_contcall
->context
->session_id
);
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
;
722 dbg(10,"E%d ", p_new_tcaphash_endcall
->context
->session_id
);
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
;
757 dbg(10,"A%d ", p_new_tcaphash_ansicall
->context
->session_id
);
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 */
778 if (!p_tcaphash_contcall1
->next_contcall
) {
779 p_tcaphash_contcall
=append_tcaphash_contcall(p_tcaphash_contcall1
,
783 p_tcaphash_contcall1
= p_tcaphash_contcall1
->next_contcall
;
784 } while (p_tcaphash_contcall1
!= NULL
);
786 p_tcaphash_contcall
= new_tcaphash_cont(p_tcaphash_cont_key
,
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 */
807 if (!p_tcaphash_endcall1
->next_endcall
) {
808 p_tcaphash_endcall
=append_tcaphash_endcall(p_tcaphash_endcall1
,
812 p_tcaphash_endcall1
= p_tcaphash_endcall1
->next_endcall
;
813 } while (p_tcaphash_endcall1
!= NULL
);
815 p_tcaphash_endcall
= new_tcaphash_end(p_tcaphash_end_key
,
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
;
838 proto_item
*stat_item
=NULL
;
839 proto_tree
*stat_tree
=NULL
;
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
));
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
);
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 */
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
);
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 */
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 */
875 dbg(22,"Already seen ");
877 p_tcaphash_context
=p_tcaphash_begincall
->context
;
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
)
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 */
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
);
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
,
913 dbg(12,"Update key %lx ",tcaphash_begin_key
.hashKey
);
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
) {
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
);
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
,
934 dbg(12,"Update key %lu ",tcaphash_begin_key
.hashKey
);
936 update_tcaphash_begincall(p_new_tcaphash_begincall
, pinfo
);
939 /* the TCAP session is not closed, so, either messages have been lost */
940 /* or it's a duplicate request. Mark it as such. */
942 dbg(21,"Display_duplicate %d ",p_tcaphash_begincall
->context
->first_frame
);
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 */
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
970 dbg(10,"New key %lx ",tcaphash_begin_key
.hashKey
);
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
);
978 dbg(11,"Update key %lx ",tcaphash_begin_key
.hashKey
);
979 dbg(11,"Frame reqlink #%u ", pinfo
->num
);
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 ){
997 dbg(20,"Display_frameRsplink %d ",p_tcaphash_context
->last_frame
);
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
;
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
);
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
);
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
);
1057 p_tcaphash_contcall
= find_tcaphash_cont(&tcaphash_cont_key
, pinfo
);
1058 if(p_tcaphash_contcall
) {
1059 #ifdef DEBUG_TCAPSRT
1062 p_tcaphash_context
=p_tcaphash_contcall
->context
;
1063 } else { /* cont not found */
1064 #ifdef DEBUG_TCAPSRT
1065 dbg(12,"CnotFound ");
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
);
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
);
1084 p_tcaphash_begincall
= find_tcaphash_begin(&tcaphash_begin_key
, pinfo
, false);
1085 if(!p_tcaphash_begincall
){
1087 /* can this actually happen? */
1088 #ifdef DEBUG_TCAPSRT
1089 dbg(12,"BNotFound trying stid,src");
1091 /* Do we have a continue from the same source? (stid,src) */
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
);
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
);
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");
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
);
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
));
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
);
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 ");
1153 /* make another try with src tid / address */
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
;
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
);
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
);
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
);
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 ");
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
);
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
);
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 ");
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
);
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
);
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 ");
1296 return p_tcaphash_context
;
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
;
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
);
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
);
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 */
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 ");
1356 p_tcaphash_context
=p_tcaphash_ansicall
->context
;
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 ");
1367 p_tcaphash_context
=p_tcaphash_ansicall
->context
;
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
);
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
;
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
);
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
);
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
)
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
);
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
,
1445 #ifdef DEBUG_TCAPSRT
1446 dbg(12,"Update key %lx ",tcaphash_ansi_key
.hashKey
);
1448 update_tcaphash_ansicall(p_new_tcaphash_ansicall
, pinfo
);
1449 p_tcaphash_ansicall
=p_new_tcaphash_ansicall
;
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
);
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
,
1464 #ifdef DEBUG_TCAPSRT
1465 dbg(12,"Update key %lu ",tcaphash_ansi_key
.hashKey
);
1467 update_tcaphash_ansicall(p_new_tcaphash_ansicall
, pinfo
);
1468 p_tcaphash_ansicall
=p_new_tcaphash_ansicall
;
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
);
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
);
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 */
1505 } /* Next call is NULL */
1506 p_tcaphash_ansicall
= p_tcaphash_ansicall
->next_ansicall
;
1507 } while (p_tcaphash_ansicall
!= NULL
);
1511 } else { /* p_tcaphash_ansicall has not been found */
1512 #ifdef DEBUG_TCAPSRT
1513 dbg(10,"New key %lx ",tcaphash_ansi_key
.hashKey
);
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
);
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
);
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
);
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) {
1599 switch (p_tcapsrt_info
->ope
) {
1602 #ifdef DEBUG_TCAPSRT
1603 dbg(1,"\nTC_BEGIN ");
1605 tcap_context
=tcaphash_begin_matching(tvb
, pinfo
, tree
, p_tcapsrt_info
);
1609 #ifdef DEBUG_TCAPSRT
1610 dbg(1,"\nTC_CONT ");
1612 tcap_context
=tcaphash_cont_matching(tvb
, pinfo
, tree
, p_tcapsrt_info
);
1616 #ifdef DEBUG_TCAPSRT
1617 dbg(1,"\nTC_ABORT ");
1619 tcap_context
=tcaphash_end_matching(tvb
, pinfo
, tree
, p_tcapsrt_info
);
1623 #ifdef DEBUG_TCAPSRT
1626 tcap_context
=tcaphash_end_matching(tvb
, pinfo
, tree
, p_tcapsrt_info
);
1631 #ifdef DEBUG_TCAPSRT
1632 dbg(1,"\nTC_ANSI ");
1634 tcap_context
=tcaphash_ansi_matching(tvb
, pinfo
, tree
, p_tcapsrt_info
);
1638 #ifdef DEBUG_TCAPSRT
1639 dbg(1,"\nUnknown %d ", p_tcapsrt_info
->ope
);
1642 } /* switch tcapop */
1643 #ifdef DEBUG_TCAPSRT
1645 dbg(1,"session %d ", tcap_context
->session_id
);
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
;
1672 tcapsrt_close(struct tcaphash_context_t
*p_tcaphash_context
,
1675 #ifdef DEBUG_TCAPSRT
1676 dbg(60,"Force close ");
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 ");
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
);
1698 /* cannot remove the father */
1699 #ifdef DEBUG_TCAPSRT
1700 dbg(20,"father Ehash ");
1702 } /* no previous link, so father */
1703 } else if (!gtcap_PersistentSRT
) {
1704 #ifdef DEBUG_TCAPSRT
1705 dbg(20,"remove Ehash ");
1707 wmem_map_remove(tcaphash_end
, p_tcaphash_context
->endcall
->endkey
);
1709 } /* endcall without chained string */
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 ");
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
);
1727 /* cannot remove the father */
1728 #ifdef DEBUG_TCAPSRT
1729 dbg(20,"father Chash ");
1731 } /* no previous link, so father */
1732 } else if (!gtcap_PersistentSRT
) {
1733 #ifdef DEBUG_TCAPSRT
1734 dbg(20,"remove Chash ");
1736 wmem_map_remove(tcaphash_cont
, p_tcaphash_context
->contcall
->contkey
);
1737 } /* contcall without chained string */
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 ");
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
);
1755 /* cannot remove the father */
1756 #ifdef DEBUG_TCAPSRT
1757 dbg(20,"father Bhash ");
1760 } else if (!gtcap_PersistentSRT
) {
1761 #ifdef DEBUG_TCAPSRT
1762 dbg(20,"remove Bhash ");
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 ");
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
);
1782 /* cannot remove the father */
1783 #ifdef DEBUG_TCAPSRT
1784 dbg(20,"father Ahash ");
1787 } else if (!gtcap_PersistentSRT
) {
1788 #ifdef DEBUG_TCAPSRT
1789 dbg(20,"remove Ahash ");
1791 wmem_map_remove(tcaphash_ansi
, p_tcaphash_context
->ansicall
->ansikey
);
1792 } /* ansicall without chained string */
1795 if (!gtcap_PersistentSRT
) {
1796 #ifdef DEBUG_TCAPSRT
1797 dbg(20,"remove context ");
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 ");
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)" },
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
;
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
){
1855 return call_dissector(ansi_tcap_handle
, tvb
, pinfo
, parent_tree
);
1858 return tvb_captured_length(tvb
);
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 */
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
;
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
);
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);
1927 proto_register_tcap(void)
1930 /* Setup list of header fields See Section 1.6.1 for details*/
1931 static hf_register_info hf
[] = {
1935 FT_UINT8
, BASE_HEX
, NULL
, 0,
1941 FT_UINT8
, BASE_DEC
, NULL
, 0,
1947 FT_BYTES
, BASE_NONE
, NULL
, 0,
1953 FT_BYTES
, BASE_NONE
, NULL
, 0,
1956 { &hf_tcap_constructor_eoc
,
1957 { "CONSTRUCTOR EOC",
1958 "tcap.constructor_eoc",
1959 FT_UINT16
, BASE_HEX
, NULL
, 0,
1962 /* Tcap Service Response Time */
1963 { &hf_tcapsrt_SessionId
,
1965 "tcap.srt.session_id",
1966 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1969 { &hf_tcapsrt_BeginSession
,
1972 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1973 "SRT Begin of Session", HFILL
}
1975 { &hf_tcapsrt_EndSession
,
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
[] = {
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 },
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
);
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);
2031 prefs_register_obsolete_preference(tcap_module
, "standard");
2035 prefs_register_bool_preference(tcap_module
, "lock_info_col", "Lock Info column",
2036 "Always show TCAP in Info column",
2039 prefs_register_obsolete_preference(tcap_module
, "lock_info_col");
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 >cap_PersistentSRT
);
2056 prefs_register_uint_preference(tcap_module
, "repetitiontimeout",
2057 "Repetition timeout",
2058 "Maximal delay for message repetition",
2059 10, >cap_RepetitionTimeout
);
2061 prefs_register_uint_preference(tcap_module
, "losttimeout",
2063 "Maximal delay for message lost",
2064 10, >cap_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
);
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
;
2123 proto_tree
*subtree
;
2128 uint32_t tag_length
;
2129 uint32_t len_length
;
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
;
2146 subtree
= proto_tree_add_subtree(tree
, tvb
, saved_offset
,
2147 len
+ (len_offset
- saved_offset
), ett_param
, NULL
,
2149 proto_tree_add_uint_format(subtree
, hf_tcap_tag
, tvb
,
2150 saved_offset
, tag_length
, 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
,
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
);
2167 proto_tree_add_item(subtree
, hf_tcap_constructor_eoc
, tvb
, offset
+len
-2, 2, ENC_BIG_ENDIAN
);
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
,
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
);
2197 * Call ITU Subdissector to decode the Tcap Component
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
;
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
) {
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;
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;
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;
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;
2264 } /* no 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
))) {
2292 is_subdissector
= true;
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;
2300 /* Nothing found, take the Data handler */
2301 subdissector_handle
= data_handle
;
2302 is_subdissector
= true;
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;
2311 subdissector_handle
= data_handle
;
2312 is_subdissector
= true;
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
);
2331 call_tcap_dissector(dissector_handle_t handle
, tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
2333 requested_subdissector_handle
= handle
;
2336 dissect_tcap(tvb
, pinfo
, tree
, NULL
);
2338 requested_subdissector_handle
= NULL
;
2342 requested_subdissector_handle
= NULL
;
2351 * indent-tabs-mode: nil
2354 * ex: set shiftwidth=2 tabstop=8 expandtab:
2355 * :indentSize=2:tabSize=8:noTabs=true: