/src/wireshark/epan/dissectors/packet-tcap.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Do not modify this file. Changes will be overwritten. */ |
2 | | /* Generated automatically by the ASN.1 to Wireshark dissector compiler */ |
3 | | /* packet-tcap.c */ |
4 | | /* asn2wrs.py -b -q -L -p tcap -c ./tcap.cnf -s ./packet-tcap-template -D . -O ../.. tcap.asn UnidialoguePDUs.asn DialoguePDUs.asn */ |
5 | | |
6 | | /* packet-tcap-template.c |
7 | | * Routines for TCAP |
8 | | * Copyright 2004 - 2005, Tim Endean <endeant@hotmail.com> |
9 | | * Built from the gsm-map dissector Copyright 2004 - 2005, Anders Broman <anders.broman@ericsson.com> |
10 | | * |
11 | | * Wireshark - Network traffic analyzer |
12 | | * By Gerald Combs <gerald@wireshark.org> |
13 | | * Copyright 1998 Gerald Combs |
14 | | * |
15 | | * SPDX-License-Identifier: GPL-2.0-or-later |
16 | | * References: ETSI 300 374 |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <epan/packet.h> |
22 | | #include <epan/exceptions.h> |
23 | | #include <epan/prefs.h> |
24 | | #include <epan/oids.h> |
25 | | #include <epan/asn1.h> |
26 | | #include <epan/address_types.h> |
27 | | #include <epan/strutil.h> |
28 | | #include <epan/show_exception.h> |
29 | | #include <wsutil/array.h> |
30 | | |
31 | | #include "packet-ber.h" |
32 | | #include "packet-tcap.h" |
33 | | #include "packet-mtp3.h" |
34 | | |
35 | | |
36 | 14 | #define PNAME "Transaction Capabilities Application Part" |
37 | 14 | #define PSNAME "TCAP" |
38 | 14 | #define PFNAME "tcap" |
39 | | |
40 | | /* Initialize the protocol and registered fields */ |
41 | | static int proto_tcap; |
42 | | static int hf_tcap_tag; |
43 | | static int hf_tcap_length; |
44 | | static int hf_tcap_data; |
45 | | static int hf_tcap_tid; |
46 | | static int hf_tcap_constructor_eoc; |
47 | | |
48 | | int hf_tcapsrt_SessionId; |
49 | | int hf_tcapsrt_Duplicate; |
50 | | int hf_tcapsrt_BeginSession; |
51 | | int hf_tcapsrt_EndSession; |
52 | | int hf_tcapsrt_SessionTime; |
53 | | |
54 | | static int hf_tcap_UniDialoguePDU_PDU; /* UniDialoguePDU */ |
55 | | static int hf_tcap_DialoguePDU_PDU; /* DialoguePDU */ |
56 | | static int hf_tcap_oid; /* OBJECT_IDENTIFIER */ |
57 | | static int hf_tcap_dialog; /* Dialog1 */ |
58 | | static int hf_tcap_unidirectional; /* Unidirectional */ |
59 | | static int hf_tcap_begin; /* Begin */ |
60 | | static int hf_tcap_end; /* End */ |
61 | | static int hf_tcap_continue; /* Continue */ |
62 | | static int hf_tcap_abort; /* Abort */ |
63 | | static int hf_tcap_dialoguePortion; /* DialoguePortion */ |
64 | | static int hf_tcap_components; /* ComponentPortion */ |
65 | | static int hf_tcap_otid; /* OrigTransactionID */ |
66 | | static int hf_tcap_dtid; /* DestTransactionID */ |
67 | | static int hf_tcap_reason; /* Reason */ |
68 | | static int hf_tcap_p_abortCause; /* P_AbortCause */ |
69 | | static int hf_tcap_u_abortCause; /* DialoguePortion */ |
70 | | static int hf_tcap__untag_item; /* Component */ |
71 | | static int hf_tcap_invoke; /* Invoke */ |
72 | | static int hf_tcap_returnResultLast; /* ReturnResult */ |
73 | | static int hf_tcap_returnError; /* ReturnError */ |
74 | | static int hf_tcap_reject; /* Reject */ |
75 | | static int hf_tcap_returnResultNotLast; /* ReturnResult */ |
76 | | static int hf_tcap_invokeID; /* InvokeIdType */ |
77 | | static int hf_tcap_linkedID; /* InvokeIdType */ |
78 | | static int hf_tcap_opCode; /* OPERATION */ |
79 | | static int hf_tcap_parameter; /* Parameter */ |
80 | | static int hf_tcap_resultretres; /* T_resultretres */ |
81 | | static int hf_tcap_errorCode; /* ErrorCode */ |
82 | | static int hf_tcap_invokeIDRej; /* T_invokeIDRej */ |
83 | | static int hf_tcap_derivable; /* InvokeIdType */ |
84 | | static int hf_tcap_not_derivable; /* NULL */ |
85 | | static int hf_tcap_problem; /* T_problem */ |
86 | | static int hf_tcap_generalProblem; /* GeneralProblem */ |
87 | | static int hf_tcap_invokeProblem; /* InvokeProblem */ |
88 | | static int hf_tcap_returnResultProblem; /* ReturnResultProblem */ |
89 | | static int hf_tcap_returnErrorProblem; /* ReturnErrorProblem */ |
90 | | static int hf_tcap_localValue; /* INTEGER */ |
91 | | static int hf_tcap_globalValue; /* OBJECT_IDENTIFIER */ |
92 | | static int hf_tcap_nationaler; /* INTEGER_M32768_32767 */ |
93 | | static int hf_tcap_privateer; /* INTEGER */ |
94 | | static int hf_tcap_unidialoguePDU; /* AUDT_apdu */ |
95 | | static int hf_tcap_audt_protocol_version; /* AUDT_protocol_version */ |
96 | | static int hf_tcap_audt_application_context_name; /* AUDT_application_context_name */ |
97 | | static int hf_tcap_audt_user_information; /* AUDT_user_information */ |
98 | | static int hf_tcap_audt_user_information_item; /* EXTERNAL */ |
99 | | static int hf_tcap_dialogueRequest; /* AARQ_apdu */ |
100 | | static int hf_tcap_dialogueResponse; /* AARE_apdu */ |
101 | | static int hf_tcap_dialogueAbort; /* ABRT_apdu */ |
102 | | static int hf_tcap_aarq_protocol_version; /* AARQ_protocol_version */ |
103 | | static int hf_tcap_aarq_application_context_name; /* AARQ_application_context_name */ |
104 | | static int hf_tcap_aarq_user_information; /* AARQ_user_information */ |
105 | | static int hf_tcap_aarq_user_information_item; /* EXTERNAL */ |
106 | | static int hf_tcap_aare_protocol_version; /* AARE_protocol_version */ |
107 | | static int hf_tcap_aare_application_context_name; /* AARE_application_context_name */ |
108 | | static int hf_tcap_result; /* Associate_result */ |
109 | | static int hf_tcap_result_source_diagnostic; /* Associate_source_diagnostic */ |
110 | | static int hf_tcap_aare_user_information; /* AARE_user_information */ |
111 | | static int hf_tcap_aare_user_information_item; /* EXTERNAL */ |
112 | | static int hf_tcap_abort_source; /* ABRT_source */ |
113 | | static int hf_tcap_abrt_user_information; /* ABRT_user_information */ |
114 | | static int hf_tcap_abrt_user_information_item; /* EXTERNAL */ |
115 | | static int hf_tcap_dialogue_service_user; /* T_dialogue_service_user */ |
116 | | static int hf_tcap_dialogue_service_provider; /* T_dialogue_service_provider */ |
117 | | /* named bits */ |
118 | | static int hf_tcap_AUDT_protocol_version_version1; |
119 | | static int hf_tcap_AARQ_protocol_version_version1; |
120 | | static int hf_tcap_AARE_protocol_version_version1; |
121 | | |
122 | | /* Initialize the subtree pointers */ |
123 | | static int ett_tcap; |
124 | | static int ett_param; |
125 | | |
126 | | static int ett_otid; |
127 | | static int ett_dtid; |
128 | | int ett_tcap_stat; |
129 | | |
130 | | static struct tcapsrt_info_t * gp_tcapsrt_info; |
131 | | static bool tcap_subdissector_used=false; |
132 | | static dissector_handle_t requested_subdissector_handle; |
133 | | |
134 | | static int ss7pc_address_type = -1; |
135 | | |
136 | | static struct tcaphash_context_t * gp_tcap_context; |
137 | | |
138 | | static int ett_tcap_ExternalPDU_U; |
139 | | static int ett_tcap_TCMessage; |
140 | | static int ett_tcap_Unidirectional; |
141 | | static int ett_tcap_Begin; |
142 | | static int ett_tcap_End; |
143 | | static int ett_tcap_Continue; |
144 | | static int ett_tcap_Abort; |
145 | | static int ett_tcap_Reason; |
146 | | static int ett_tcap_SEQUENCE_SIZE_1_MAX_OF_Component; |
147 | | static int ett_tcap_Component; |
148 | | static int ett_tcap_Invoke; |
149 | | static int ett_tcap_ReturnResult; |
150 | | static int ett_tcap_T_resultretres; |
151 | | static int ett_tcap_ReturnError; |
152 | | static int ett_tcap_Reject; |
153 | | static int ett_tcap_T_invokeIDRej; |
154 | | static int ett_tcap_T_problem; |
155 | | static int ett_tcap_OPERATION; |
156 | | static int ett_tcap_ErrorCode; |
157 | | static int ett_tcap_UniDialoguePDU; |
158 | | static int ett_tcap_AUDT_apdu_U; |
159 | | static int ett_tcap_AUDT_protocol_version; |
160 | | static int ett_tcap_AUDT_user_information; |
161 | | static int ett_tcap_DialoguePDU; |
162 | | static int ett_tcap_AARQ_apdu_U; |
163 | | static int ett_tcap_AARQ_protocol_version; |
164 | | static int ett_tcap_AARQ_user_information; |
165 | | static int ett_tcap_AARE_apdu_U; |
166 | | static int ett_tcap_AARE_protocol_version; |
167 | | static int ett_tcap_AARE_user_information; |
168 | | static int ett_tcap_ABRT_apdu_U; |
169 | | static int ett_tcap_ABRT_user_information; |
170 | | static int ett_tcap_Associate_source_diagnostic; |
171 | | |
172 | | /* When several Tcap components are received in a single TCAP message, |
173 | | we have to use several buffers for the stored parameters |
174 | | because else this data are erased during TAP dissector call */ |
175 | 27 | #define MAX_TCAP_INSTANCE 10 |
176 | | static int tcapsrt_global_current=0; |
177 | | static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE]; |
178 | | |
179 | 28 | #define MAX_SSN 254 |
180 | | static range_t *global_ssn_range; |
181 | | static range_t *ssn_range; |
182 | | |
183 | | /* These two timeout (in second) are used when some message are lost, |
184 | | or when the same TCAP transcation identifier is reused */ |
185 | | static unsigned gtcap_RepetitionTimeout = 10; |
186 | | static unsigned gtcap_LostTimeout = 30; |
187 | | static bool gtcap_PersistentSRT=false; |
188 | | bool gtcap_DisplaySRT=false; |
189 | | bool gtcap_StatSRT=false; |
190 | | |
191 | | /* Global hash tables*/ |
192 | | static wmem_map_t *tcaphash_context; |
193 | | static wmem_map_t *tcaphash_begin; |
194 | | static wmem_map_t *tcaphash_cont; |
195 | | static wmem_map_t *tcaphash_end; |
196 | | static wmem_map_t *tcaphash_ansi; |
197 | | |
198 | | static uint32_t tcapsrt_global_SessionId=1; |
199 | | |
200 | | static dissector_handle_t tcap_handle; |
201 | | static dissector_table_t ber_oid_dissector_table; |
202 | | static const char * cur_oid; |
203 | | static const char * tcapext_oid; |
204 | | static proto_tree * tcap_top_tree; |
205 | | static proto_tree * tcap_stat_tree; |
206 | | |
207 | | static dissector_handle_t data_handle; |
208 | | static dissector_handle_t ansi_tcap_handle; |
209 | | |
210 | | static int dissect_tcap_param(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset); |
211 | | 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_); |
212 | | |
213 | | static dissector_table_t ansi_sub_dissectors; |
214 | | static dissector_table_t itu_sub_dissectors; |
215 | | |
216 | 140 | extern void add_ansi_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) { |
217 | 140 | dissector_add_uint("ansi_tcap.ssn",ssn,dissector); |
218 | 140 | dissector_add_uint("sccp.ssn",ssn,tcap_handle); |
219 | 140 | } |
220 | | |
221 | 154 | extern void add_itu_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) { |
222 | 154 | dissector_add_uint("itu_tcap.ssn",ssn,dissector); |
223 | 154 | dissector_add_uint("sccp.ssn",ssn,tcap_handle); |
224 | 154 | } |
225 | | |
226 | 0 | extern void delete_ansi_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector) { |
227 | 0 | dissector_delete_uint("ansi_tcap.ssn",ssn,dissector); |
228 | 0 | if (!get_itu_tcap_subdissector(ssn)) |
229 | 0 | dissector_delete_uint("sccp.ssn",ssn,tcap_handle); |
230 | 0 | } |
231 | 0 | extern void delete_itu_tcap_subdissector(uint32_t ssn, dissector_handle_t dissector _U_) { |
232 | 0 | dissector_delete_uint("itu_tcap.ssn",ssn,dissector); |
233 | 0 | if (!get_ansi_tcap_subdissector(ssn)) |
234 | 0 | dissector_delete_uint("sccp.ssn", ssn,tcap_handle); |
235 | 0 | } |
236 | | |
237 | 0 | dissector_handle_t get_ansi_tcap_subdissector(uint32_t ssn) { |
238 | 0 | return dissector_get_uint_handle(ansi_sub_dissectors, ssn); |
239 | 0 | } |
240 | | |
241 | 16 | dissector_handle_t get_itu_tcap_subdissector(uint32_t ssn) { |
242 | 16 | return dissector_get_uint_handle(itu_sub_dissectors, ssn); |
243 | 16 | } |
244 | | |
245 | | |
246 | | |
247 | | static int |
248 | 0 | dissect_tcap_OBJECT_IDENTIFIER(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
249 | 0 | offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL); |
250 | |
|
251 | 0 | return offset; |
252 | 0 | } |
253 | | |
254 | | |
255 | | |
256 | | static int |
257 | 0 | dissect_tcap_Dialog1(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
258 | |
|
259 | 0 | offset = dissect_tcap_DialoguePDU(true, tvb, offset, actx, tree, -1); |
260 | | |
261 | |
|
262 | 0 | return offset; |
263 | 0 | } |
264 | | |
265 | | |
266 | | static const ber_sequence_t ExternalPDU_U_sequence[] = { |
267 | | { &hf_tcap_oid , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_tcap_OBJECT_IDENTIFIER }, |
268 | | { &hf_tcap_dialog , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_tcap_Dialog1 }, |
269 | | { NULL, 0, 0, 0, NULL } |
270 | | }; |
271 | | |
272 | | static int |
273 | 0 | dissect_tcap_ExternalPDU_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
274 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
275 | 0 | ExternalPDU_U_sequence, hf_index, ett_tcap_ExternalPDU_U); |
276 | |
|
277 | 0 | return offset; |
278 | 0 | } |
279 | | |
280 | | |
281 | | |
282 | | static int |
283 | 0 | dissect_tcap_ExternalPDU(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
284 | |
|
285 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
286 | 0 | hf_index, BER_CLASS_UNI, 8, true, dissect_tcap_ExternalPDU_U); |
287 | | |
288 | | |
289 | |
|
290 | 0 | return offset; |
291 | 0 | } |
292 | | |
293 | | |
294 | | |
295 | | static int |
296 | 0 | dissect_tcap_DialogueOC(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
297 | |
|
298 | 0 | offset = dissect_tcap_ExternalPDU(false /*implicit_tag*/, tvb, offset, actx, tree, -1); |
299 | | |
300 | |
|
301 | 0 | return offset; |
302 | 0 | } |
303 | | |
304 | | |
305 | | |
306 | | static int |
307 | 0 | dissect_tcap_DialoguePortion(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
308 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
309 | 0 | hf_index, BER_CLASS_APP, 11, true, dissect_tcap_DialogueOC); |
310 | |
|
311 | 0 | return offset; |
312 | 0 | } |
313 | | |
314 | | |
315 | | |
316 | | static int |
317 | 0 | dissect_tcap_InvokeIdType(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
318 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
319 | 0 | NULL); |
320 | |
|
321 | 0 | return offset; |
322 | 0 | } |
323 | | |
324 | | |
325 | | |
326 | | static int |
327 | 0 | dissect_tcap_INTEGER(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
328 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
329 | 0 | NULL); |
330 | |
|
331 | 0 | return offset; |
332 | 0 | } |
333 | | |
334 | | |
335 | | static const value_string tcap_OPERATION_vals[] = { |
336 | | { 0, "localValue" }, |
337 | | { 1, "globalValue" }, |
338 | | { 0, NULL } |
339 | | }; |
340 | | |
341 | | static const ber_choice_t OPERATION_choice[] = { |
342 | | { 0, &hf_tcap_localValue , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_tcap_INTEGER }, |
343 | | { 1, &hf_tcap_globalValue , BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_tcap_OBJECT_IDENTIFIER }, |
344 | | { 0, NULL, 0, 0, 0, NULL } |
345 | | }; |
346 | | |
347 | | static int |
348 | 0 | dissect_tcap_OPERATION(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
349 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
350 | 0 | OPERATION_choice, hf_index, ett_tcap_OPERATION, |
351 | 0 | NULL); |
352 | |
|
353 | 0 | return offset; |
354 | 0 | } |
355 | | |
356 | | |
357 | | |
358 | | static int |
359 | 0 | dissect_tcap_Parameter(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
360 | |
|
361 | 0 | offset = dissect_tcap_param(actx,tree,tvb,offset); |
362 | | |
363 | |
|
364 | 0 | return offset; |
365 | 0 | } |
366 | | |
367 | | |
368 | | static const ber_sequence_t Invoke_sequence[] = { |
369 | | { &hf_tcap_invokeID , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_tcap_InvokeIdType }, |
370 | | { &hf_tcap_linkedID , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_InvokeIdType }, |
371 | | { &hf_tcap_opCode , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_OPERATION }, |
372 | | { &hf_tcap_parameter , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_Parameter }, |
373 | | { NULL, 0, 0, 0, NULL } |
374 | | }; |
375 | | |
376 | | static int |
377 | 0 | dissect_tcap_Invoke(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
378 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
379 | 0 | Invoke_sequence, hf_index, ett_tcap_Invoke); |
380 | |
|
381 | 0 | return offset; |
382 | 0 | } |
383 | | |
384 | | |
385 | | static const ber_sequence_t T_resultretres_sequence[] = { |
386 | | { &hf_tcap_opCode , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_OPERATION }, |
387 | | { &hf_tcap_parameter , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_Parameter }, |
388 | | { NULL, 0, 0, 0, NULL } |
389 | | }; |
390 | | |
391 | | static int |
392 | 0 | dissect_tcap_T_resultretres(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
393 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
394 | 0 | T_resultretres_sequence, hf_index, ett_tcap_T_resultretres); |
395 | |
|
396 | 0 | return offset; |
397 | 0 | } |
398 | | |
399 | | |
400 | | static const ber_sequence_t ReturnResult_sequence[] = { |
401 | | { &hf_tcap_invokeID , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_tcap_InvokeIdType }, |
402 | | { &hf_tcap_resultretres , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_T_resultretres }, |
403 | | { NULL, 0, 0, 0, NULL } |
404 | | }; |
405 | | |
406 | | static int |
407 | 0 | dissect_tcap_ReturnResult(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
408 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
409 | 0 | ReturnResult_sequence, hf_index, ett_tcap_ReturnResult); |
410 | |
|
411 | 0 | return offset; |
412 | 0 | } |
413 | | |
414 | | |
415 | | |
416 | | static int |
417 | 0 | dissect_tcap_INTEGER_M32768_32767(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
418 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
419 | 0 | NULL); |
420 | |
|
421 | 0 | return offset; |
422 | 0 | } |
423 | | |
424 | | |
425 | | static const value_string tcap_ErrorCode_vals[] = { |
426 | | { 19, "nationaler" }, |
427 | | { 20, "privateer" }, |
428 | | { 0, NULL } |
429 | | }; |
430 | | |
431 | | static const ber_choice_t ErrorCode_choice[] = { |
432 | | { 19, &hf_tcap_nationaler , BER_CLASS_PRI, 19, BER_FLAGS_IMPLTAG, dissect_tcap_INTEGER_M32768_32767 }, |
433 | | { 20, &hf_tcap_privateer , BER_CLASS_PRI, 20, BER_FLAGS_IMPLTAG, dissect_tcap_INTEGER }, |
434 | | { 0, NULL, 0, 0, 0, NULL } |
435 | | }; |
436 | | |
437 | | static int |
438 | 0 | dissect_tcap_ErrorCode(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
439 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
440 | 0 | ErrorCode_choice, hf_index, ett_tcap_ErrorCode, |
441 | 0 | NULL); |
442 | |
|
443 | 0 | return offset; |
444 | 0 | } |
445 | | |
446 | | |
447 | | static const ber_sequence_t ReturnError_sequence[] = { |
448 | | { &hf_tcap_invokeID , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_tcap_InvokeIdType }, |
449 | | { &hf_tcap_errorCode , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_ErrorCode }, |
450 | | { &hf_tcap_parameter , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_Parameter }, |
451 | | { NULL, 0, 0, 0, NULL } |
452 | | }; |
453 | | |
454 | | static int |
455 | 0 | dissect_tcap_ReturnError(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
456 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
457 | 0 | ReturnError_sequence, hf_index, ett_tcap_ReturnError); |
458 | |
|
459 | 0 | return offset; |
460 | 0 | } |
461 | | |
462 | | |
463 | | |
464 | | static int |
465 | 0 | dissect_tcap_NULL(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
466 | 0 | offset = dissect_ber_null(implicit_tag, actx, tree, tvb, offset, hf_index); |
467 | |
|
468 | 0 | return offset; |
469 | 0 | } |
470 | | |
471 | | |
472 | | static const value_string tcap_T_invokeIDRej_vals[] = { |
473 | | { 0, "derivable" }, |
474 | | { 1, "not-derivable" }, |
475 | | { 0, NULL } |
476 | | }; |
477 | | |
478 | | static const ber_choice_t T_invokeIDRej_choice[] = { |
479 | | { 0, &hf_tcap_derivable , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_tcap_InvokeIdType }, |
480 | | { 1, &hf_tcap_not_derivable , BER_CLASS_UNI, BER_UNI_TAG_NULL, BER_FLAGS_NOOWNTAG, dissect_tcap_NULL }, |
481 | | { 0, NULL, 0, 0, 0, NULL } |
482 | | }; |
483 | | |
484 | | static int |
485 | 0 | dissect_tcap_T_invokeIDRej(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
486 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
487 | 0 | T_invokeIDRej_choice, hf_index, ett_tcap_T_invokeIDRej, |
488 | 0 | NULL); |
489 | |
|
490 | 0 | return offset; |
491 | 0 | } |
492 | | |
493 | | |
494 | | static const value_string tcap_GeneralProblem_vals[] = { |
495 | | { 0, "unrecognizedComponent" }, |
496 | | { 1, "mistypedComponent" }, |
497 | | { 2, "badlyStructuredComponent" }, |
498 | | { 0, NULL } |
499 | | }; |
500 | | |
501 | | |
502 | | static int |
503 | 0 | dissect_tcap_GeneralProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
504 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
505 | 0 | NULL); |
506 | |
|
507 | 0 | return offset; |
508 | 0 | } |
509 | | |
510 | | |
511 | | static const value_string tcap_InvokeProblem_vals[] = { |
512 | | { 0, "duplicateInvokeID" }, |
513 | | { 1, "unrecognizedOperation" }, |
514 | | { 2, "mistypedParameter" }, |
515 | | { 3, "resourceLimitation" }, |
516 | | { 4, "initiatingRelease" }, |
517 | | { 5, "unrecognizedLinkedID" }, |
518 | | { 6, "linkedResponseUnexpected" }, |
519 | | { 7, "unexpectedLinkedOperation" }, |
520 | | { 0, NULL } |
521 | | }; |
522 | | |
523 | | |
524 | | static int |
525 | 0 | dissect_tcap_InvokeProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
526 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
527 | 0 | NULL); |
528 | |
|
529 | 0 | return offset; |
530 | 0 | } |
531 | | |
532 | | |
533 | | static const value_string tcap_ReturnResultProblem_vals[] = { |
534 | | { 0, "unrecognizedInvokeID" }, |
535 | | { 1, "returnResultUnexpected" }, |
536 | | { 2, "mistypedParameter" }, |
537 | | { 0, NULL } |
538 | | }; |
539 | | |
540 | | |
541 | | static int |
542 | 0 | dissect_tcap_ReturnResultProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
543 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
544 | 0 | NULL); |
545 | |
|
546 | 0 | return offset; |
547 | 0 | } |
548 | | |
549 | | |
550 | | static const value_string tcap_ReturnErrorProblem_vals[] = { |
551 | | { 0, "unrecognizedInvokeID" }, |
552 | | { 1, "returnErrorUnexpected" }, |
553 | | { 2, "unrecognizedError" }, |
554 | | { 3, "unexpectedError" }, |
555 | | { 4, "mistypedParameter" }, |
556 | | { 0, NULL } |
557 | | }; |
558 | | |
559 | | |
560 | | static int |
561 | 0 | dissect_tcap_ReturnErrorProblem(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
562 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
563 | 0 | NULL); |
564 | |
|
565 | 0 | return offset; |
566 | 0 | } |
567 | | |
568 | | |
569 | | static const value_string tcap_T_problem_vals[] = { |
570 | | { 0, "generalProblem" }, |
571 | | { 1, "invokeProblem" }, |
572 | | { 2, "returnResultProblem" }, |
573 | | { 3, "returnErrorProblem" }, |
574 | | { 0, NULL } |
575 | | }; |
576 | | |
577 | | static const ber_choice_t T_problem_choice[] = { |
578 | | { 0, &hf_tcap_generalProblem , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_tcap_GeneralProblem }, |
579 | | { 1, &hf_tcap_invokeProblem , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_tcap_InvokeProblem }, |
580 | | { 2, &hf_tcap_returnResultProblem, BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_tcap_ReturnResultProblem }, |
581 | | { 3, &hf_tcap_returnErrorProblem, BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_tcap_ReturnErrorProblem }, |
582 | | { 0, NULL, 0, 0, 0, NULL } |
583 | | }; |
584 | | |
585 | | static int |
586 | 0 | dissect_tcap_T_problem(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
587 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
588 | 0 | T_problem_choice, hf_index, ett_tcap_T_problem, |
589 | 0 | NULL); |
590 | |
|
591 | 0 | return offset; |
592 | 0 | } |
593 | | |
594 | | |
595 | | static const ber_sequence_t Reject_sequence[] = { |
596 | | { &hf_tcap_invokeIDRej , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_T_invokeIDRej }, |
597 | | { &hf_tcap_problem , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_T_problem }, |
598 | | { NULL, 0, 0, 0, NULL } |
599 | | }; |
600 | | |
601 | | static int |
602 | 0 | dissect_tcap_Reject(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
603 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
604 | 0 | Reject_sequence, hf_index, ett_tcap_Reject); |
605 | |
|
606 | 0 | return offset; |
607 | 0 | } |
608 | | |
609 | | |
610 | | static const value_string tcap_Component_vals[] = { |
611 | | { 1, "invoke" }, |
612 | | { 2, "returnResultLast" }, |
613 | | { 3, "returnError" }, |
614 | | { 4, "reject" }, |
615 | | { 7, "returnResultNotLast" }, |
616 | | { 0, NULL } |
617 | | }; |
618 | | |
619 | | static const ber_choice_t Component_choice[] = { |
620 | | { 1, &hf_tcap_invoke , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_tcap_Invoke }, |
621 | | { 2, &hf_tcap_returnResultLast, BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_tcap_ReturnResult }, |
622 | | { 3, &hf_tcap_returnError , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_tcap_ReturnError }, |
623 | | { 4, &hf_tcap_reject , BER_CLASS_CON, 4, BER_FLAGS_IMPLTAG, dissect_tcap_Reject }, |
624 | | { 7, &hf_tcap_returnResultNotLast, BER_CLASS_CON, 7, BER_FLAGS_IMPLTAG, dissect_tcap_ReturnResult }, |
625 | | { 0, NULL, 0, 0, 0, NULL } |
626 | | }; |
627 | | |
628 | | static int |
629 | 0 | dissect_tcap_Component(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
630 | 0 | tvbuff_t *next_tvb; |
631 | 0 | int8_t ber_class; |
632 | 0 | bool pc; |
633 | 0 | int tag; |
634 | 0 | uint32_t len, comp_offset; |
635 | 0 | volatile uint32_t _offset; |
636 | 0 | bool ind_field; |
637 | |
|
638 | 0 | comp_offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &ber_class, &pc, &tag); |
639 | 0 | comp_offset = dissect_ber_length(actx->pinfo, tree, tvb, comp_offset, &len, &ind_field); |
640 | | /* we can believe the length now */ |
641 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, len+comp_offset-offset); |
642 | |
|
643 | 0 | if (!next_tvb) |
644 | 0 | return comp_offset; |
645 | 0 | if(dissect_tcap_ITU_ComponentPDU(implicit_tag, next_tvb, 0, actx, tcap_top_tree, hf_index)){ |
646 | 0 | return comp_offset; |
647 | 0 | } |
648 | | |
649 | 0 | _offset = offset; |
650 | 0 | TRY { |
651 | 0 | _offset = dissect_ber_choice(actx, tree, tvb, _offset, |
652 | 0 | Component_choice, hf_index, ett_tcap_Component, |
653 | 0 | NULL); |
654 | 0 | } |
655 | 0 | CATCH_NONFATAL_ERRORS { |
656 | 0 | show_exception(tvb, actx->pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
657 | 0 | } |
658 | 0 | ENDTRY; |
659 | 0 | offset = _offset; |
660 | | |
661 | | /* return comp_offset+len; or return offset (will be automatically added) */ |
662 | | |
663 | |
|
664 | 0 | return offset; |
665 | 0 | } |
666 | | |
667 | | |
668 | | static const ber_sequence_t SEQUENCE_SIZE_1_MAX_OF_Component_sequence_of[1] = { |
669 | | { &hf_tcap__untag_item , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_Component }, |
670 | | }; |
671 | | |
672 | | static int |
673 | 0 | dissect_tcap_SEQUENCE_SIZE_1_MAX_OF_Component(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
674 | 0 | offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset, |
675 | 0 | SEQUENCE_SIZE_1_MAX_OF_Component_sequence_of, hf_index, ett_tcap_SEQUENCE_SIZE_1_MAX_OF_Component); |
676 | |
|
677 | 0 | return offset; |
678 | 0 | } |
679 | | |
680 | | |
681 | | |
682 | | static int |
683 | 0 | dissect_tcap_ComponentPortion(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
684 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
685 | 0 | hf_index, BER_CLASS_APP, 12, true, dissect_tcap_SEQUENCE_SIZE_1_MAX_OF_Component); |
686 | |
|
687 | 0 | return offset; |
688 | 0 | } |
689 | | |
690 | | |
691 | | static const ber_sequence_t Unidirectional_sequence[] = { |
692 | | { &hf_tcap_dialoguePortion, BER_CLASS_APP, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_DialoguePortion }, |
693 | | { &hf_tcap_components , BER_CLASS_APP, 12, BER_FLAGS_NOOWNTAG, dissect_tcap_ComponentPortion }, |
694 | | { NULL, 0, 0, 0, NULL } |
695 | | }; |
696 | | |
697 | | static int |
698 | 0 | dissect_tcap_Unidirectional(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
699 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
700 | 0 | Unidirectional_sequence, hf_index, ett_tcap_Unidirectional); |
701 | |
|
702 | 0 | return offset; |
703 | 0 | } |
704 | | |
705 | | |
706 | | |
707 | | static int |
708 | 0 | dissect_tcap_OCTET_STRING_SIZE_1_4(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
709 | 0 | offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index, |
710 | 0 | NULL); |
711 | |
|
712 | 0 | return offset; |
713 | 0 | } |
714 | | |
715 | | |
716 | | |
717 | | static int |
718 | 0 | dissect_tcap_OrigTransactionID(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
719 | 0 | tvbuff_t *parameter_tvb; |
720 | 0 | uint8_t len, i; |
721 | 0 | proto_tree *subtree; |
722 | 0 | int saved_offset; |
723 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
724 | |
|
725 | 0 | hf_index = hf_tcap_tid; |
726 | 0 | saved_offset = offset; |
727 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
728 | 0 | hf_index, BER_CLASS_APP, 8, true, dissect_tcap_OCTET_STRING_SIZE_1_4); |
729 | |
|
730 | 0 | proto_item_set_generated(actx->created_item); |
731 | 0 | offset = saved_offset; |
732 | |
|
733 | 0 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_otid, NULL, "Source Transaction ID"); |
734 | 0 | offset = dissect_ber_octet_string(implicit_tag, actx, subtree, tvb, offset, hf_tcap_otid, |
735 | 0 | ¶meter_tvb); |
736 | |
|
737 | 0 | if (parameter_tvb) { |
738 | 0 | len = tvb_reported_length_remaining(parameter_tvb, 0); |
739 | 0 | switch(len) { |
740 | 0 | case 1: |
741 | 0 | gp_tcapsrt_info->src_tid=tvb_get_uint8(parameter_tvb, 0); |
742 | 0 | break; |
743 | 0 | case 2: |
744 | 0 | gp_tcapsrt_info->src_tid=tvb_get_ntohs(parameter_tvb, 0); |
745 | 0 | break; |
746 | 0 | case 3: |
747 | 0 | gp_tcapsrt_info->src_tid=tvb_get_ntoh24(parameter_tvb, 0); |
748 | 0 | break; |
749 | 0 | case 4: |
750 | 0 | gp_tcapsrt_info->src_tid=tvb_get_ntohl(parameter_tvb, 0); |
751 | 0 | break; |
752 | 0 | default: |
753 | 0 | gp_tcapsrt_info->src_tid=0; |
754 | 0 | break; |
755 | 0 | } |
756 | 0 | if (p_tcap_private) |
757 | 0 | p_tcap_private->src_tid = gp_tcapsrt_info->src_tid; |
758 | |
|
759 | 0 | if (len) { |
760 | 0 | col_append_str(actx->pinfo->cinfo, COL_INFO, "otid("); |
761 | 0 | for (i = 0; i < len; i++) { |
762 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%02x",tvb_get_uint8(parameter_tvb,i)); |
763 | 0 | } |
764 | 0 | col_append_str(actx->pinfo->cinfo, COL_INFO, ") "); |
765 | 0 | } |
766 | 0 | } |
767 | | |
768 | | |
769 | 0 | return offset; |
770 | 0 | } |
771 | | |
772 | | |
773 | | static const ber_sequence_t Begin_sequence[] = { |
774 | | { &hf_tcap_otid , BER_CLASS_APP, 8, BER_FLAGS_NOOWNTAG, dissect_tcap_OrigTransactionID }, |
775 | | { &hf_tcap_dialoguePortion, BER_CLASS_APP, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_DialoguePortion }, |
776 | | { &hf_tcap_components , BER_CLASS_APP, 12, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_ComponentPortion }, |
777 | | { NULL, 0, 0, 0, NULL } |
778 | | }; |
779 | | |
780 | | static int |
781 | 0 | dissect_tcap_Begin(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
782 | 0 | gp_tcapsrt_info->ope=TC_BEGIN; |
783 | | |
784 | | /* Do not change col_add_str() to col_append_str() here: we _want_ this call |
785 | | * to overwrite whatever's currently in the INFO column (e.g., "UDT" from |
786 | | * the SCCP dissector). |
787 | | * |
788 | | * If there's something there that should not be overwritten, whoever |
789 | | * put that info there should call col_set_fence() to protect it. |
790 | | */ |
791 | 0 | col_set_str(actx->pinfo->cinfo, COL_INFO, "Begin "); |
792 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
793 | 0 | Begin_sequence, hf_index, ett_tcap_Begin); |
794 | |
|
795 | 0 | return offset; |
796 | 0 | } |
797 | | |
798 | | |
799 | | |
800 | | static int |
801 | 0 | dissect_tcap_DestTransactionID(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
802 | 0 | tvbuff_t *parameter_tvb; |
803 | 0 | uint8_t len , i; |
804 | 0 | proto_tree *subtree; |
805 | 0 | int saved_offset; |
806 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
807 | |
|
808 | 0 | hf_index = hf_tcap_tid; |
809 | 0 | saved_offset = offset; |
810 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
811 | 0 | hf_index, BER_CLASS_APP, 9, true, dissect_tcap_OCTET_STRING_SIZE_1_4); |
812 | |
|
813 | 0 | proto_item_set_generated(actx->created_item); |
814 | 0 | offset = saved_offset; |
815 | |
|
816 | 0 | subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_dtid, NULL, "Destination Transaction ID"); |
817 | 0 | offset = dissect_ber_octet_string(implicit_tag, actx, subtree, tvb, offset, hf_tcap_dtid, |
818 | 0 | ¶meter_tvb); |
819 | |
|
820 | 0 | if (parameter_tvb) { |
821 | 0 | len = tvb_reported_length_remaining(parameter_tvb, 0); |
822 | 0 | switch(len) { |
823 | 0 | case 1: |
824 | 0 | gp_tcapsrt_info->dst_tid=tvb_get_uint8(parameter_tvb, 0); |
825 | 0 | break; |
826 | 0 | case 2: |
827 | 0 | gp_tcapsrt_info->dst_tid=tvb_get_ntohs(parameter_tvb, 0); |
828 | 0 | break; |
829 | 0 | case 3: |
830 | 0 | gp_tcapsrt_info->dst_tid=tvb_get_ntoh24(parameter_tvb, 0); |
831 | 0 | break; |
832 | 0 | case 4: |
833 | 0 | gp_tcapsrt_info->dst_tid=tvb_get_ntohl(parameter_tvb, 0); |
834 | 0 | break; |
835 | 0 | default: |
836 | 0 | gp_tcapsrt_info->dst_tid=0; |
837 | 0 | break; |
838 | 0 | } |
839 | 0 | if (p_tcap_private) |
840 | 0 | p_tcap_private->dst_tid = gp_tcapsrt_info->dst_tid; |
841 | |
|
842 | 0 | if (len) { |
843 | 0 | col_append_str(actx->pinfo->cinfo, COL_INFO, "dtid("); |
844 | 0 | for(i = 0; i < len; i++) { |
845 | 0 | col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%02x",tvb_get_uint8(parameter_tvb,i)); |
846 | 0 | } |
847 | 0 | col_append_str(actx->pinfo->cinfo, COL_INFO, ") "); |
848 | 0 | } |
849 | 0 | } |
850 | | |
851 | 0 | return offset; |
852 | 0 | } |
853 | | |
854 | | |
855 | | static const ber_sequence_t End_sequence[] = { |
856 | | { &hf_tcap_dtid , BER_CLASS_APP, 9, BER_FLAGS_NOOWNTAG, dissect_tcap_DestTransactionID }, |
857 | | { &hf_tcap_dialoguePortion, BER_CLASS_APP, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_DialoguePortion }, |
858 | | { &hf_tcap_components , BER_CLASS_APP, 12, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_ComponentPortion }, |
859 | | { NULL, 0, 0, 0, NULL } |
860 | | }; |
861 | | |
862 | | static int |
863 | 0 | dissect_tcap_End(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
864 | 0 | gp_tcapsrt_info->ope=TC_END; |
865 | |
|
866 | 0 | col_set_str(actx->pinfo->cinfo, COL_INFO, "End "); |
867 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
868 | 0 | End_sequence, hf_index, ett_tcap_End); |
869 | |
|
870 | 0 | return offset; |
871 | 0 | } |
872 | | |
873 | | |
874 | | static const ber_sequence_t Continue_sequence[] = { |
875 | | { &hf_tcap_otid , BER_CLASS_APP, 8, BER_FLAGS_NOOWNTAG, dissect_tcap_OrigTransactionID }, |
876 | | { &hf_tcap_dtid , BER_CLASS_APP, 9, BER_FLAGS_NOOWNTAG, dissect_tcap_DestTransactionID }, |
877 | | { &hf_tcap_dialoguePortion, BER_CLASS_APP, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_DialoguePortion }, |
878 | | { &hf_tcap_components , BER_CLASS_APP, 12, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_tcap_ComponentPortion }, |
879 | | { NULL, 0, 0, 0, NULL } |
880 | | }; |
881 | | |
882 | | static int |
883 | 0 | dissect_tcap_Continue(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
884 | 0 | gp_tcapsrt_info->ope=TC_CONT; |
885 | |
|
886 | 0 | col_set_str(actx->pinfo->cinfo, COL_INFO, "Continue "); |
887 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
888 | 0 | Continue_sequence, hf_index, ett_tcap_Continue); |
889 | |
|
890 | 0 | return offset; |
891 | 0 | } |
892 | | |
893 | | |
894 | | static const value_string tcap_P_AbortCause_U_vals[] = { |
895 | | { 0, "unrecognizedMessageType" }, |
896 | | { 1, "unrecognizedTransactionID" }, |
897 | | { 2, "badlyFormattedTransactionPortion" }, |
898 | | { 3, "incorrectTransactionPortion" }, |
899 | | { 4, "resourceLimitation" }, |
900 | | { 0, NULL } |
901 | | }; |
902 | | |
903 | | |
904 | | static int |
905 | 0 | dissect_tcap_P_AbortCause_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
906 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
907 | 0 | NULL); |
908 | |
|
909 | 0 | return offset; |
910 | 0 | } |
911 | | |
912 | | |
913 | | |
914 | | static int |
915 | 0 | dissect_tcap_P_AbortCause(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
916 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
917 | 0 | hf_index, BER_CLASS_APP, 10, true, dissect_tcap_P_AbortCause_U); |
918 | |
|
919 | 0 | return offset; |
920 | 0 | } |
921 | | |
922 | | |
923 | | static const value_string tcap_Reason_vals[] = { |
924 | | { 10, "p-abortCause" }, |
925 | | { 11, "u-abortCause" }, |
926 | | { 0, NULL } |
927 | | }; |
928 | | |
929 | | static const ber_choice_t Reason_choice[] = { |
930 | | { 10, &hf_tcap_p_abortCause , BER_CLASS_APP, 10, BER_FLAGS_NOOWNTAG, dissect_tcap_P_AbortCause }, |
931 | | { 11, &hf_tcap_u_abortCause , BER_CLASS_APP, 11, BER_FLAGS_NOOWNTAG, dissect_tcap_DialoguePortion }, |
932 | | { 0, NULL, 0, 0, 0, NULL } |
933 | | }; |
934 | | |
935 | | static int |
936 | 0 | dissect_tcap_Reason(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
937 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
938 | 0 | Reason_choice, hf_index, ett_tcap_Reason, |
939 | 0 | NULL); |
940 | |
|
941 | 0 | return offset; |
942 | 0 | } |
943 | | |
944 | | |
945 | | static const ber_sequence_t Abort_sequence[] = { |
946 | | { &hf_tcap_dtid , BER_CLASS_APP, 9, BER_FLAGS_NOOWNTAG, dissect_tcap_DestTransactionID }, |
947 | | { &hf_tcap_reason , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_tcap_Reason }, |
948 | | { NULL, 0, 0, 0, NULL } |
949 | | }; |
950 | | |
951 | | static int |
952 | 0 | dissect_tcap_Abort(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
953 | 0 | gp_tcapsrt_info->ope=TC_ABORT; |
954 | |
|
955 | 0 | col_set_str(actx->pinfo->cinfo, COL_INFO, "Abort "); |
956 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
957 | 0 | Abort_sequence, hf_index, ett_tcap_Abort); |
958 | |
|
959 | 0 | return offset; |
960 | 0 | } |
961 | | |
962 | | |
963 | | static const ber_choice_t TCMessage_choice[] = { |
964 | | { 1, &hf_tcap_unidirectional , BER_CLASS_APP, 1, BER_FLAGS_IMPLTAG, dissect_tcap_Unidirectional }, |
965 | | { 2, &hf_tcap_begin , BER_CLASS_APP, 2, BER_FLAGS_IMPLTAG, dissect_tcap_Begin }, |
966 | | { 4, &hf_tcap_end , BER_CLASS_APP, 4, BER_FLAGS_IMPLTAG, dissect_tcap_End }, |
967 | | { 5, &hf_tcap_continue , BER_CLASS_APP, 5, BER_FLAGS_IMPLTAG, dissect_tcap_Continue }, |
968 | | { 7, &hf_tcap_abort , BER_CLASS_APP, 7, BER_FLAGS_IMPLTAG, dissect_tcap_Abort }, |
969 | | { 0, NULL, 0, 0, 0, NULL } |
970 | | }; |
971 | | |
972 | | static int |
973 | 27 | dissect_tcap_TCMessage(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
974 | 27 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
975 | 27 | TCMessage_choice, hf_index, ett_tcap_TCMessage, |
976 | 27 | NULL); |
977 | | |
978 | 27 | return offset; |
979 | 27 | } |
980 | | |
981 | | |
982 | | static int * const AUDT_protocol_version_bits[] = { |
983 | | &hf_tcap_AUDT_protocol_version_version1, |
984 | | NULL |
985 | | }; |
986 | | |
987 | | static int |
988 | 0 | dissect_tcap_AUDT_protocol_version(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
989 | 0 | offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset, |
990 | 0 | AUDT_protocol_version_bits, 1, hf_index, ett_tcap_AUDT_protocol_version, |
991 | 0 | NULL); |
992 | |
|
993 | 0 | return offset; |
994 | 0 | } |
995 | | |
996 | | |
997 | | |
998 | | static int |
999 | 0 | dissect_tcap_AUDT_application_context_name(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1000 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
1001 | 0 | offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &cur_oid); |
1002 | |
|
1003 | 0 | if (p_tcap_private) { |
1004 | 0 | p_tcap_private->oid= (const void*) cur_oid; |
1005 | 0 | p_tcap_private->acv=true; |
1006 | 0 | } |
1007 | |
|
1008 | 0 | return offset; |
1009 | 0 | } |
1010 | | |
1011 | | |
1012 | | |
1013 | | static int |
1014 | 0 | dissect_tcap_EXTERNAL(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1015 | 0 | offset = dissect_ber_external_type(implicit_tag, tree, tvb, offset, actx, hf_index, NULL); |
1016 | |
|
1017 | 0 | return offset; |
1018 | 0 | } |
1019 | | |
1020 | | |
1021 | | static const ber_sequence_t AUDT_user_information_sequence_of[1] = { |
1022 | | { &hf_tcap_audt_user_information_item, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, BER_FLAGS_NOOWNTAG, dissect_tcap_EXTERNAL }, |
1023 | | }; |
1024 | | |
1025 | | static int |
1026 | 0 | dissect_tcap_AUDT_user_information(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1027 | 0 | offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset, |
1028 | 0 | AUDT_user_information_sequence_of, hf_index, ett_tcap_AUDT_user_information); |
1029 | |
|
1030 | 0 | return offset; |
1031 | 0 | } |
1032 | | |
1033 | | |
1034 | | static const ber_sequence_t AUDT_apdu_U_sequence[] = { |
1035 | | { &hf_tcap_audt_protocol_version, BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AUDT_protocol_version }, |
1036 | | { &hf_tcap_audt_application_context_name, BER_CLASS_CON, 1, 0, dissect_tcap_AUDT_application_context_name }, |
1037 | | { &hf_tcap_audt_user_information, BER_CLASS_CON, 30, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AUDT_user_information }, |
1038 | | { NULL, 0, 0, 0, NULL } |
1039 | | }; |
1040 | | |
1041 | | static int |
1042 | 0 | dissect_tcap_AUDT_apdu_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1043 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
1044 | 0 | AUDT_apdu_U_sequence, hf_index, ett_tcap_AUDT_apdu_U); |
1045 | |
|
1046 | 0 | return offset; |
1047 | 0 | } |
1048 | | |
1049 | | |
1050 | | |
1051 | | static int |
1052 | 0 | dissect_tcap_AUDT_apdu(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1053 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
1054 | 0 | hf_index, BER_CLASS_APP, 0, true, dissect_tcap_AUDT_apdu_U); |
1055 | |
|
1056 | 0 | return offset; |
1057 | 0 | } |
1058 | | |
1059 | | |
1060 | | const value_string tcap_UniDialoguePDU_vals[] = { |
1061 | | { 0, "unidialoguePDU" }, |
1062 | | { 0, NULL } |
1063 | | }; |
1064 | | |
1065 | | static const ber_choice_t UniDialoguePDU_choice[] = { |
1066 | | { 0, &hf_tcap_unidialoguePDU , BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_tcap_AUDT_apdu }, |
1067 | | { 0, NULL, 0, 0, 0, NULL } |
1068 | | }; |
1069 | | |
1070 | | int |
1071 | 0 | dissect_tcap_UniDialoguePDU(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1072 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
1073 | 0 | UniDialoguePDU_choice, hf_index, ett_tcap_UniDialoguePDU, |
1074 | 0 | NULL); |
1075 | |
|
1076 | 0 | return offset; |
1077 | 0 | } |
1078 | | |
1079 | | |
1080 | | static int * const AARQ_protocol_version_bits[] = { |
1081 | | &hf_tcap_AARQ_protocol_version_version1, |
1082 | | NULL |
1083 | | }; |
1084 | | |
1085 | | static int |
1086 | 0 | dissect_tcap_AARQ_protocol_version(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1087 | 0 | offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset, |
1088 | 0 | AARQ_protocol_version_bits, 1, hf_index, ett_tcap_AARQ_protocol_version, |
1089 | 0 | NULL); |
1090 | |
|
1091 | 0 | return offset; |
1092 | 0 | } |
1093 | | |
1094 | | |
1095 | | |
1096 | | static int |
1097 | 0 | dissect_tcap_AARQ_application_context_name(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1098 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
1099 | 0 | offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &cur_oid); |
1100 | |
|
1101 | 0 | if (p_tcap_private) { |
1102 | 0 | p_tcap_private->oid= (const void*) cur_oid; |
1103 | 0 | p_tcap_private->acv=true; |
1104 | 0 | } |
1105 | |
|
1106 | 0 | return offset; |
1107 | 0 | } |
1108 | | |
1109 | | |
1110 | | static const ber_sequence_t AARQ_user_information_sequence_of[1] = { |
1111 | | { &hf_tcap_aarq_user_information_item, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, BER_FLAGS_NOOWNTAG, dissect_tcap_EXTERNAL }, |
1112 | | }; |
1113 | | |
1114 | | static int |
1115 | 0 | dissect_tcap_AARQ_user_information(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1116 | 0 | offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset, |
1117 | 0 | AARQ_user_information_sequence_of, hf_index, ett_tcap_AARQ_user_information); |
1118 | |
|
1119 | 0 | return offset; |
1120 | 0 | } |
1121 | | |
1122 | | |
1123 | | static const ber_sequence_t AARQ_apdu_U_sequence[] = { |
1124 | | { &hf_tcap_aarq_protocol_version, BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AARQ_protocol_version }, |
1125 | | { &hf_tcap_aarq_application_context_name, BER_CLASS_CON, 1, 0, dissect_tcap_AARQ_application_context_name }, |
1126 | | { &hf_tcap_aarq_user_information, BER_CLASS_CON, 30, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AARQ_user_information }, |
1127 | | { NULL, 0, 0, 0, NULL } |
1128 | | }; |
1129 | | |
1130 | | static int |
1131 | 0 | dissect_tcap_AARQ_apdu_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1132 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
1133 | 0 | AARQ_apdu_U_sequence, hf_index, ett_tcap_AARQ_apdu_U); |
1134 | |
|
1135 | 0 | return offset; |
1136 | 0 | } |
1137 | | |
1138 | | |
1139 | | |
1140 | | static int |
1141 | 0 | dissect_tcap_AARQ_apdu(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1142 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
1143 | 0 | hf_index, BER_CLASS_APP, 0, true, dissect_tcap_AARQ_apdu_U); |
1144 | |
|
1145 | 0 | return offset; |
1146 | 0 | } |
1147 | | |
1148 | | |
1149 | | static int * const AARE_protocol_version_bits[] = { |
1150 | | &hf_tcap_AARE_protocol_version_version1, |
1151 | | NULL |
1152 | | }; |
1153 | | |
1154 | | static int |
1155 | 0 | dissect_tcap_AARE_protocol_version(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1156 | 0 | offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset, |
1157 | 0 | AARE_protocol_version_bits, 1, hf_index, ett_tcap_AARE_protocol_version, |
1158 | 0 | NULL); |
1159 | |
|
1160 | 0 | return offset; |
1161 | 0 | } |
1162 | | |
1163 | | |
1164 | | |
1165 | | static int |
1166 | 0 | dissect_tcap_AARE_application_context_name(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1167 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
1168 | 0 | offset = dissect_ber_object_identifier_str(implicit_tag, actx, tree, tvb, offset, hf_index, &cur_oid); |
1169 | |
|
1170 | 0 | if (p_tcap_private) { |
1171 | 0 | p_tcap_private->oid= (const void*) cur_oid; |
1172 | 0 | p_tcap_private->acv=true; |
1173 | 0 | } |
1174 | |
|
1175 | 0 | return offset; |
1176 | 0 | } |
1177 | | |
1178 | | |
1179 | | static const value_string tcap_Associate_result_vals[] = { |
1180 | | { 0, "accepted" }, |
1181 | | { 1, "reject-permanent" }, |
1182 | | { 0, NULL } |
1183 | | }; |
1184 | | |
1185 | | |
1186 | | static int |
1187 | 0 | dissect_tcap_Associate_result(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1188 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
1189 | 0 | NULL); |
1190 | |
|
1191 | 0 | return offset; |
1192 | 0 | } |
1193 | | |
1194 | | |
1195 | | static const value_string tcap_T_dialogue_service_user_vals[] = { |
1196 | | { 0, "null" }, |
1197 | | { 1, "no-reason-given" }, |
1198 | | { 2, "application-context-name-not-supported" }, |
1199 | | { 0, NULL } |
1200 | | }; |
1201 | | |
1202 | | |
1203 | | static int |
1204 | 0 | dissect_tcap_T_dialogue_service_user(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1205 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
1206 | 0 | NULL); |
1207 | |
|
1208 | 0 | return offset; |
1209 | 0 | } |
1210 | | |
1211 | | |
1212 | | static const value_string tcap_T_dialogue_service_provider_vals[] = { |
1213 | | { 0, "null" }, |
1214 | | { 1, "no-reason-given" }, |
1215 | | { 2, "no-common-dialogue-portion" }, |
1216 | | { 0, NULL } |
1217 | | }; |
1218 | | |
1219 | | |
1220 | | static int |
1221 | 0 | dissect_tcap_T_dialogue_service_provider(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1222 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
1223 | 0 | NULL); |
1224 | |
|
1225 | 0 | return offset; |
1226 | 0 | } |
1227 | | |
1228 | | |
1229 | | static const value_string tcap_Associate_source_diagnostic_vals[] = { |
1230 | | { 1, "dialogue-service-user" }, |
1231 | | { 2, "dialogue-service-provider" }, |
1232 | | { 0, NULL } |
1233 | | }; |
1234 | | |
1235 | | static const ber_choice_t Associate_source_diagnostic_choice[] = { |
1236 | | { 1, &hf_tcap_dialogue_service_user, BER_CLASS_CON, 1, 0, dissect_tcap_T_dialogue_service_user }, |
1237 | | { 2, &hf_tcap_dialogue_service_provider, BER_CLASS_CON, 2, 0, dissect_tcap_T_dialogue_service_provider }, |
1238 | | { 0, NULL, 0, 0, 0, NULL } |
1239 | | }; |
1240 | | |
1241 | | static int |
1242 | 0 | dissect_tcap_Associate_source_diagnostic(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1243 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
1244 | 0 | Associate_source_diagnostic_choice, hf_index, ett_tcap_Associate_source_diagnostic, |
1245 | 0 | NULL); |
1246 | |
|
1247 | 0 | return offset; |
1248 | 0 | } |
1249 | | |
1250 | | |
1251 | | static const ber_sequence_t AARE_user_information_sequence_of[1] = { |
1252 | | { &hf_tcap_aare_user_information_item, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, BER_FLAGS_NOOWNTAG, dissect_tcap_EXTERNAL }, |
1253 | | }; |
1254 | | |
1255 | | static int |
1256 | 0 | dissect_tcap_AARE_user_information(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1257 | 0 | offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset, |
1258 | 0 | AARE_user_information_sequence_of, hf_index, ett_tcap_AARE_user_information); |
1259 | |
|
1260 | 0 | return offset; |
1261 | 0 | } |
1262 | | |
1263 | | |
1264 | | static const ber_sequence_t AARE_apdu_U_sequence[] = { |
1265 | | { &hf_tcap_aare_protocol_version, BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AARE_protocol_version }, |
1266 | | { &hf_tcap_aare_application_context_name, BER_CLASS_CON, 1, 0, dissect_tcap_AARE_application_context_name }, |
1267 | | { &hf_tcap_result , BER_CLASS_CON, 2, 0, dissect_tcap_Associate_result }, |
1268 | | { &hf_tcap_result_source_diagnostic, BER_CLASS_CON, 3, BER_FLAGS_NOTCHKTAG, dissect_tcap_Associate_source_diagnostic }, |
1269 | | { &hf_tcap_aare_user_information, BER_CLASS_CON, 30, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_AARE_user_information }, |
1270 | | { NULL, 0, 0, 0, NULL } |
1271 | | }; |
1272 | | |
1273 | | static int |
1274 | 0 | dissect_tcap_AARE_apdu_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1275 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
1276 | 0 | AARE_apdu_U_sequence, hf_index, ett_tcap_AARE_apdu_U); |
1277 | |
|
1278 | 0 | return offset; |
1279 | 0 | } |
1280 | | |
1281 | | |
1282 | | |
1283 | | static int |
1284 | 0 | dissect_tcap_AARE_apdu(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1285 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
1286 | 0 | hf_index, BER_CLASS_APP, 1, true, dissect_tcap_AARE_apdu_U); |
1287 | |
|
1288 | 0 | return offset; |
1289 | 0 | } |
1290 | | |
1291 | | |
1292 | | static const value_string tcap_ABRT_source_vals[] = { |
1293 | | { 0, "dialogue-service-user" }, |
1294 | | { 1, "dialogue-service-provider" }, |
1295 | | { 0, NULL } |
1296 | | }; |
1297 | | |
1298 | | |
1299 | | static int |
1300 | 0 | dissect_tcap_ABRT_source(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1301 | 0 | offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, |
1302 | 0 | NULL); |
1303 | |
|
1304 | 0 | return offset; |
1305 | 0 | } |
1306 | | |
1307 | | |
1308 | | static const ber_sequence_t ABRT_user_information_sequence_of[1] = { |
1309 | | { &hf_tcap_abrt_user_information_item, BER_CLASS_UNI, BER_UNI_TAG_EXTERNAL, BER_FLAGS_NOOWNTAG, dissect_tcap_EXTERNAL }, |
1310 | | }; |
1311 | | |
1312 | | static int |
1313 | 0 | dissect_tcap_ABRT_user_information(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1314 | 0 | offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset, |
1315 | 0 | ABRT_user_information_sequence_of, hf_index, ett_tcap_ABRT_user_information); |
1316 | |
|
1317 | 0 | return offset; |
1318 | 0 | } |
1319 | | |
1320 | | |
1321 | | static const ber_sequence_t ABRT_apdu_U_sequence[] = { |
1322 | | { &hf_tcap_abort_source , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_tcap_ABRT_source }, |
1323 | | { &hf_tcap_abrt_user_information, BER_CLASS_CON, 30, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_tcap_ABRT_user_information }, |
1324 | | { NULL, 0, 0, 0, NULL } |
1325 | | }; |
1326 | | |
1327 | | static int |
1328 | 0 | dissect_tcap_ABRT_apdu_U(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1329 | 0 | offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset, |
1330 | 0 | ABRT_apdu_U_sequence, hf_index, ett_tcap_ABRT_apdu_U); |
1331 | |
|
1332 | 0 | return offset; |
1333 | 0 | } |
1334 | | |
1335 | | |
1336 | | |
1337 | | static int |
1338 | 0 | dissect_tcap_ABRT_apdu(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1339 | 0 | offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset, |
1340 | 0 | hf_index, BER_CLASS_APP, 4, true, dissect_tcap_ABRT_apdu_U); |
1341 | |
|
1342 | 0 | return offset; |
1343 | 0 | } |
1344 | | |
1345 | | |
1346 | | const value_string tcap_DialoguePDU_vals[] = { |
1347 | | { 0, "dialogueRequest" }, |
1348 | | { 1, "dialogueResponse" }, |
1349 | | { 4, "dialogueAbort" }, |
1350 | | { 0, NULL } |
1351 | | }; |
1352 | | |
1353 | | static const ber_choice_t DialoguePDU_choice[] = { |
1354 | | { 0, &hf_tcap_dialogueRequest, BER_CLASS_APP, 0, BER_FLAGS_NOOWNTAG, dissect_tcap_AARQ_apdu }, |
1355 | | { 1, &hf_tcap_dialogueResponse, BER_CLASS_APP, 1, BER_FLAGS_NOOWNTAG, dissect_tcap_AARE_apdu }, |
1356 | | { 4, &hf_tcap_dialogueAbort , BER_CLASS_APP, 4, BER_FLAGS_NOOWNTAG, dissect_tcap_ABRT_apdu }, |
1357 | | { 0, NULL, 0, 0, 0, NULL } |
1358 | | }; |
1359 | | |
1360 | | int |
1361 | 0 | dissect_tcap_DialoguePDU(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { |
1362 | 0 | offset = dissect_ber_choice(actx, tree, tvb, offset, |
1363 | 0 | DialoguePDU_choice, hf_index, ett_tcap_DialoguePDU, |
1364 | 0 | NULL); |
1365 | |
|
1366 | 0 | return offset; |
1367 | 0 | } |
1368 | | |
1369 | | /*--- PDUs ---*/ |
1370 | | |
1371 | 0 | static int dissect_UniDialoguePDU_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_) { |
1372 | 0 | int offset = 0; |
1373 | 0 | asn1_ctx_t asn1_ctx; |
1374 | 0 | asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo); |
1375 | 0 | offset = dissect_tcap_UniDialoguePDU(false, tvb, offset, &asn1_ctx, tree, hf_tcap_UniDialoguePDU_PDU); |
1376 | 0 | return offset; |
1377 | 0 | } |
1378 | 0 | static int dissect_DialoguePDU_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_) { |
1379 | 0 | int offset = 0; |
1380 | 0 | asn1_ctx_t asn1_ctx; |
1381 | 0 | asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo); |
1382 | 0 | offset = dissect_tcap_DialoguePDU(false, tvb, offset, &asn1_ctx, tree, hf_tcap_DialoguePDU_PDU); |
1383 | 0 | return offset; |
1384 | 0 | } |
1385 | | |
1386 | | |
1387 | | /* |
1388 | | * DEBUG functions |
1389 | | */ |
1390 | | #undef DEBUG_TCAPSRT |
1391 | | /* #define DEBUG_TCAPSRT */ |
1392 | | |
1393 | | #ifdef DEBUG_TCAPSRT |
1394 | | #include <stdio.h> |
1395 | | #include <stdarg.h> |
1396 | | static unsigned debug_level = 99; |
1397 | | |
1398 | | static void |
1399 | | dbg(unsigned level, const char* fmt, ...) |
1400 | | { |
1401 | | va_list ap; |
1402 | | |
1403 | | if (level > debug_level) return; |
1404 | | va_start(ap,fmt); |
1405 | | vfprintf(stderr, fmt, ap); |
1406 | | va_end(ap); |
1407 | | } |
1408 | | #endif |
1409 | | |
1410 | | static int |
1411 | | tcaphash_context_equal(const void *k1, const void *k2) |
1412 | 0 | { |
1413 | 0 | const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1; |
1414 | 0 | const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2; |
1415 | |
|
1416 | 0 | return (key1->session_id == key2->session_id); |
1417 | 0 | } |
1418 | | |
1419 | | /* calculate a hash key */ |
1420 | | static unsigned |
1421 | | tcaphash_context_calchash(const void *k) |
1422 | 0 | { |
1423 | 0 | const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k; |
1424 | 0 | return key->session_id; |
1425 | 0 | } |
1426 | | |
1427 | | |
1428 | | static int |
1429 | | tcaphash_begin_equal(const void *k1, const void *k2) |
1430 | 0 | { |
1431 | 0 | const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1; |
1432 | 0 | const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2; |
1433 | |
|
1434 | 0 | if (key1->hashKey == key2->hashKey) { |
1435 | 0 | if ( (key1->pc_hash == key2->pc_hash) && (key1->tid == key2->tid) ) |
1436 | 0 | return true; |
1437 | 0 | } |
1438 | 0 | return false; |
1439 | 0 | } |
1440 | | |
1441 | | /* calculate a hash key */ |
1442 | | static unsigned |
1443 | | tcaphash_begin_calchash(const void *k) |
1444 | 0 | { |
1445 | 0 | const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k; |
1446 | 0 | unsigned hashkey; |
1447 | | /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */ |
1448 | 0 | hashkey = key->tid; |
1449 | 0 | return hashkey; |
1450 | 0 | } |
1451 | | |
1452 | | static int |
1453 | | tcaphash_cont_equal(const void *k1, const void *k2) |
1454 | 0 | { |
1455 | 0 | const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1; |
1456 | 0 | const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2; |
1457 | |
|
1458 | 0 | if (key1->hashKey == key2->hashKey) { |
1459 | |
|
1460 | 0 | if ( (key1->opc_hash == key2->opc_hash) && |
1461 | 0 | (key1->dpc_hash == key2->dpc_hash) && |
1462 | 0 | (key1->src_tid == key2->src_tid) && |
1463 | 0 | (key1->dst_tid == key2->dst_tid) ) { |
1464 | 0 | return true; |
1465 | 0 | } |
1466 | 0 | else if ( (key1->opc_hash == key2->dpc_hash) && |
1467 | 0 | (key1->dpc_hash == key2->opc_hash) && |
1468 | 0 | (key1->src_tid == key2->dst_tid) && |
1469 | 0 | (key1->dst_tid == key2->src_tid) ) { |
1470 | 0 | return true; |
1471 | 0 | } |
1472 | 0 | } |
1473 | 0 | return false; |
1474 | 0 | } |
1475 | | |
1476 | | /* calculate a hash key */ |
1477 | | static unsigned |
1478 | | tcaphash_cont_calchash(const void *k) |
1479 | 0 | { |
1480 | 0 | const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k; |
1481 | 0 | unsigned hashkey; |
1482 | 0 | hashkey = key->src_tid + key->dst_tid; |
1483 | 0 | return hashkey; |
1484 | 0 | } |
1485 | | |
1486 | | |
1487 | | static int |
1488 | | tcaphash_end_equal(const void *k1, const void *k2) |
1489 | 0 | { |
1490 | 0 | const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1; |
1491 | 0 | const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2; |
1492 | |
|
1493 | 0 | if (key1->hashKey == key2->hashKey) { |
1494 | 0 | if ( (key1->opc_hash == key2->opc_hash) && |
1495 | 0 | (key1->dpc_hash == key2->dpc_hash) && |
1496 | 0 | (key1->tid == key2->tid) ) |
1497 | 0 | return true; |
1498 | 0 | } |
1499 | 0 | return false; |
1500 | 0 | } |
1501 | | |
1502 | | /* calculate a hash key */ |
1503 | | static unsigned |
1504 | | tcaphash_end_calchash(const void *k) |
1505 | 0 | { |
1506 | 0 | const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k; |
1507 | 0 | unsigned hashkey; |
1508 | 0 | hashkey = key->tid; |
1509 | 0 | return hashkey; |
1510 | 0 | } |
1511 | | |
1512 | | static int |
1513 | | tcaphash_ansi_equal(const void *k1, const void *k2) |
1514 | 0 | { |
1515 | 0 | const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1; |
1516 | 0 | const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2; |
1517 | |
|
1518 | 0 | if (key1->hashKey == key2->hashKey) { |
1519 | |
|
1520 | 0 | if ( ( (key1->opc_hash == key2->opc_hash) && |
1521 | 0 | (key1->dpc_hash == key2->dpc_hash) && |
1522 | 0 | (key1->tid == key2->tid) ) |
1523 | 0 | || |
1524 | 0 | ( (key1->opc_hash == key2->dpc_hash) && |
1525 | 0 | (key1->dpc_hash == key2->opc_hash) && |
1526 | 0 | (key1->tid == key2->tid) ) |
1527 | 0 | ) |
1528 | 0 | return true; |
1529 | 0 | } |
1530 | 0 | return false; |
1531 | 0 | } |
1532 | | |
1533 | | /* calculate a hash key */ |
1534 | | static unsigned |
1535 | | tcaphash_ansi_calchash(const void *k) |
1536 | 0 | { |
1537 | 0 | const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k; |
1538 | 0 | unsigned hashkey; |
1539 | | /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */ |
1540 | 0 | hashkey = key->tid; |
1541 | 0 | return hashkey; |
1542 | 0 | } |
1543 | | |
1544 | | /* |
1545 | | * Update a record with the data of the Request |
1546 | | */ |
1547 | | static void |
1548 | | update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall, |
1549 | | packet_info *pinfo) |
1550 | 0 | { |
1551 | 0 | p_tcaphash_begincall->context->first_frame = pinfo->num; |
1552 | 0 | p_tcaphash_begincall->context->last_frame = 0; |
1553 | 0 | p_tcaphash_begincall->context->responded = false; |
1554 | 0 | p_tcaphash_begincall->context->begin_time = pinfo->abs_ts; |
1555 | 0 | } |
1556 | | |
1557 | | /* |
1558 | | * Append a new dialogue, using the same Key, to the chained list |
1559 | | * The time is stored too |
1560 | | */ |
1561 | | static struct tcaphash_begincall_t * |
1562 | | append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall, |
1563 | | struct tcaphash_context_t *p_tcaphash_context, |
1564 | | packet_info *pinfo) |
1565 | 0 | { |
1566 | 0 | struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL; |
1567 | | |
1568 | | /* Append the transaction to the list, when the same key is found |
1569 | | This should append when the tcap-transaction Id is reused */ |
1570 | |
|
1571 | 0 | p_new_tcaphash_begincall = wmem_new0(wmem_file_scope(), struct tcaphash_begincall_t); |
1572 | 0 | p_new_tcaphash_begincall->context=p_tcaphash_context; |
1573 | 0 | p_tcaphash_context->begincall=p_new_tcaphash_begincall; |
1574 | 0 | p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey; |
1575 | 0 | p_new_tcaphash_begincall->context->first_frame = pinfo->num; |
1576 | 0 | p_new_tcaphash_begincall->next_begincall=NULL; |
1577 | 0 | p_new_tcaphash_begincall->previous_begincall=prev_begincall; |
1578 | 0 | p_new_tcaphash_begincall->father=false; |
1579 | |
|
1580 | | #ifdef DEBUG_TCAPSRT |
1581 | | dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id); |
1582 | | #endif |
1583 | | /* Insert in the chained list */ |
1584 | 0 | prev_begincall->next_begincall = p_new_tcaphash_begincall; |
1585 | 0 | if (prev_begincall->context->last_frame == 0) { |
1586 | | #ifdef DEBUG_TCAPSRT |
1587 | | dbg(10,"last "); |
1588 | | #endif |
1589 | 0 | prev_begincall->context->last_frame = pinfo->num-1; |
1590 | 0 | } |
1591 | 0 | return p_new_tcaphash_begincall; |
1592 | 0 | } |
1593 | | |
1594 | | /* |
1595 | | * Update a record with the data of the Request |
1596 | | */ |
1597 | | static void |
1598 | | update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall, |
1599 | | packet_info *pinfo) |
1600 | 0 | { |
1601 | 0 | p_tcaphash_ansicall->context->first_frame = pinfo->num; |
1602 | 0 | p_tcaphash_ansicall->context->last_frame = 0; |
1603 | 0 | p_tcaphash_ansicall->context->responded = false; |
1604 | 0 | p_tcaphash_ansicall->context->begin_time = pinfo->abs_ts; |
1605 | 0 | } |
1606 | | |
1607 | | /* |
1608 | | * Append a new dialogue, using the same Key, to the chained list |
1609 | | * The time is stored too |
1610 | | */ |
1611 | | static struct tcaphash_ansicall_t * |
1612 | | append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall, |
1613 | | struct tcaphash_context_t *p_tcaphash_context, |
1614 | | packet_info *pinfo) |
1615 | 0 | { |
1616 | 0 | struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL; |
1617 | | |
1618 | | /* Append the transaction to the list, when the same key is found |
1619 | | This should append when the tcap-transaction Id is reused */ |
1620 | |
|
1621 | 0 | p_new_tcaphash_ansicall = wmem_new0(wmem_file_scope(), struct tcaphash_ansicall_t); |
1622 | 0 | p_new_tcaphash_ansicall->context=p_tcaphash_context; |
1623 | 0 | p_tcaphash_context->ansicall=p_new_tcaphash_ansicall; |
1624 | 0 | p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey; |
1625 | 0 | p_new_tcaphash_ansicall->context->first_frame = pinfo->num; |
1626 | 0 | p_new_tcaphash_ansicall->next_ansicall=NULL; |
1627 | 0 | p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall; |
1628 | 0 | p_new_tcaphash_ansicall->father=false; |
1629 | |
|
1630 | | #ifdef DEBUG_TCAPSRT |
1631 | | dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id); |
1632 | | #endif |
1633 | | /* Insert in the chained list */ |
1634 | 0 | prev_ansicall->next_ansicall = p_new_tcaphash_ansicall; |
1635 | 0 | if (prev_ansicall->context->last_frame == 0) { |
1636 | | #ifdef DEBUG_TCAPSRT |
1637 | | dbg(10,"last "); |
1638 | | #endif |
1639 | 0 | prev_ansicall->context->last_frame = pinfo->num-1; |
1640 | 0 | } |
1641 | 0 | return p_new_tcaphash_ansicall; |
1642 | 0 | } |
1643 | | |
1644 | | |
1645 | | static struct tcaphash_contcall_t * |
1646 | | append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall, |
1647 | | struct tcaphash_context_t *p_tcaphash_context) |
1648 | 0 | { |
1649 | 0 | struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL; |
1650 | | |
1651 | | /* Append the transaction to the list, when the same key is found |
1652 | | This should append when the tcap-transaction Id is reused */ |
1653 | |
|
1654 | 0 | p_new_tcaphash_contcall = wmem_new0(wmem_file_scope(), struct tcaphash_contcall_t); |
1655 | 0 | p_new_tcaphash_contcall->context=p_tcaphash_context; |
1656 | 0 | p_tcaphash_context->contcall=p_new_tcaphash_contcall; |
1657 | 0 | p_new_tcaphash_contcall->contkey=prev_contcall->contkey; |
1658 | 0 | p_new_tcaphash_contcall->next_contcall=NULL; |
1659 | 0 | p_new_tcaphash_contcall->previous_contcall=prev_contcall; |
1660 | 0 | p_new_tcaphash_contcall->father=false; |
1661 | |
|
1662 | | #ifdef DEBUG_TCAPSRT |
1663 | | dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id); |
1664 | | #endif |
1665 | | /* Insert in the chained list */ |
1666 | 0 | prev_contcall->next_contcall = p_new_tcaphash_contcall; |
1667 | 0 | return p_new_tcaphash_contcall; |
1668 | 0 | } |
1669 | | |
1670 | | |
1671 | | static struct tcaphash_endcall_t * |
1672 | | append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall, |
1673 | | struct tcaphash_context_t *p_tcaphash_context) |
1674 | 0 | { |
1675 | 0 | struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL; |
1676 | | |
1677 | | /* Append the transaction to the list, when the same key is found |
1678 | | This should append when the tcap-transaction Id is reused */ |
1679 | |
|
1680 | 0 | p_new_tcaphash_endcall = wmem_new0(wmem_file_scope(), struct tcaphash_endcall_t); |
1681 | 0 | p_new_tcaphash_endcall->context=p_tcaphash_context; |
1682 | 0 | p_tcaphash_context->endcall=p_new_tcaphash_endcall; |
1683 | 0 | p_new_tcaphash_endcall->endkey=prev_endcall->endkey; |
1684 | 0 | p_new_tcaphash_endcall->next_endcall=NULL; |
1685 | 0 | p_new_tcaphash_endcall->previous_endcall=prev_endcall; |
1686 | 0 | p_new_tcaphash_endcall->father=false; |
1687 | |
|
1688 | | #ifdef DEBUG_TCAPSRT |
1689 | | dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id); |
1690 | | #endif |
1691 | | /* Insert in the chained list */ |
1692 | 0 | prev_endcall->next_endcall = p_new_tcaphash_endcall; |
1693 | 0 | return p_new_tcaphash_endcall; |
1694 | 0 | } |
1695 | | |
1696 | | |
1697 | | /* |
1698 | | * Find the dialog by Key and Time |
1699 | | */ |
1700 | | static struct tcaphash_begincall_t * |
1701 | | find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key, |
1702 | | packet_info *pinfo, bool isBegin) |
1703 | 0 | { |
1704 | 0 | struct tcaphash_begincall_t *p_tcaphash_begincall = NULL; |
1705 | 0 | p_tcaphash_begincall = (struct tcaphash_begincall_t *)wmem_map_lookup(tcaphash_begin, p_tcaphash_begin_key); |
1706 | |
|
1707 | 0 | if(p_tcaphash_begincall) { |
1708 | 0 | do { |
1709 | 0 | if ( p_tcaphash_begincall->context ) { |
1710 | 0 | if ( ( isBegin && |
1711 | 0 | pinfo->num == p_tcaphash_begincall->context->first_frame ) |
1712 | 0 | || |
1713 | 0 | ( !isBegin && |
1714 | 0 | pinfo->num >= p_tcaphash_begincall->context->first_frame && |
1715 | 0 | ( p_tcaphash_begincall->context->last_frame?pinfo->num <= p_tcaphash_begincall->context->last_frame:1 ) |
1716 | 0 | ) |
1717 | 0 | ) { |
1718 | | /* We have a dialogue, with this key, opened before this request */ |
1719 | | #ifdef DEBUG_TCAPSRT |
1720 | | dbg(10,"B%d ", p_tcaphash_begincall->context->session_id); |
1721 | | #endif |
1722 | 0 | return p_tcaphash_begincall; |
1723 | 0 | } |
1724 | | #ifdef DEBUG_TCAPSRT |
1725 | | dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id); |
1726 | | #endif |
1727 | 0 | } |
1728 | | /* Break when list end is reached */ |
1729 | 0 | if(p_tcaphash_begincall->next_begincall == NULL) { |
1730 | | #ifdef DEBUG_TCAPSRT |
1731 | | dbg(23,"End of Blist "); |
1732 | | #endif |
1733 | 0 | break; |
1734 | 0 | } |
1735 | 0 | p_tcaphash_begincall = p_tcaphash_begincall->next_begincall; |
1736 | 0 | } while (p_tcaphash_begincall != NULL) ; |
1737 | 0 | } else { |
1738 | | #ifdef DEBUG_TCAPSRT |
1739 | | dbg(23,"Not in Bhash "); |
1740 | | #endif |
1741 | 0 | } |
1742 | 0 | return NULL; |
1743 | 0 | } |
1744 | | |
1745 | | |
1746 | | |
1747 | | static struct tcaphash_contcall_t * |
1748 | | find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key, |
1749 | | packet_info *pinfo) |
1750 | 0 | { |
1751 | 0 | struct tcaphash_contcall_t *p_tcaphash_contcall = NULL; |
1752 | 0 | p_tcaphash_contcall = (struct tcaphash_contcall_t *)wmem_map_lookup(tcaphash_cont, p_tcaphash_cont_key); |
1753 | |
|
1754 | 0 | if(p_tcaphash_contcall) { |
1755 | 0 | do { |
1756 | 0 | if ( p_tcaphash_contcall->context ) { |
1757 | 0 | if (pinfo->num >= p_tcaphash_contcall->context->first_frame && |
1758 | 0 | (p_tcaphash_contcall->context->last_frame?pinfo->num <= p_tcaphash_contcall->context->last_frame:1) ) { |
1759 | | /* We have a dialogue, with this key, opened before this request */ |
1760 | | #ifdef DEBUG_TCAPSRT |
1761 | | dbg(10,"C%d ", p_tcaphash_contcall->context->session_id); |
1762 | | #endif |
1763 | 0 | return p_tcaphash_contcall; |
1764 | 0 | } |
1765 | | #ifdef DEBUG_TCAPSRT |
1766 | | dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id); |
1767 | | #endif |
1768 | 0 | } |
1769 | | /* Break when list end is reached */ |
1770 | 0 | if(p_tcaphash_contcall->next_contcall == NULL) { |
1771 | | #ifdef DEBUG_TCAPSRT |
1772 | | dbg(23,"End of Clist "); |
1773 | | #endif |
1774 | 0 | break; |
1775 | 0 | } |
1776 | 0 | p_tcaphash_contcall = p_tcaphash_contcall->next_contcall; |
1777 | 0 | } while (p_tcaphash_contcall != NULL) ; |
1778 | 0 | } else { |
1779 | | #ifdef DEBUG_TCAPSRT |
1780 | | dbg(23,"Not in Chash "); |
1781 | | #endif |
1782 | 0 | } |
1783 | 0 | return NULL; |
1784 | 0 | } |
1785 | | |
1786 | | static struct tcaphash_endcall_t * |
1787 | | find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key, |
1788 | | packet_info *pinfo, bool isEnd) |
1789 | 0 | { |
1790 | 0 | struct tcaphash_endcall_t *p_tcaphash_endcall = NULL; |
1791 | 0 | p_tcaphash_endcall = (struct tcaphash_endcall_t *)wmem_map_lookup(tcaphash_end, p_tcaphash_end_key); |
1792 | |
|
1793 | 0 | if(p_tcaphash_endcall) { |
1794 | 0 | do { |
1795 | 0 | if ( p_tcaphash_endcall->context ) { |
1796 | 0 | if ( ( isEnd && |
1797 | 0 | (p_tcaphash_endcall->context->last_frame?pinfo->num == p_tcaphash_endcall->context->last_frame:1) |
1798 | 0 | ) |
1799 | 0 | || |
1800 | 0 | ( !isEnd && |
1801 | 0 | pinfo->num >= p_tcaphash_endcall->context->first_frame && |
1802 | 0 | (p_tcaphash_endcall->context->last_frame?pinfo->num <= p_tcaphash_endcall->context->last_frame:1) |
1803 | 0 | ) |
1804 | 0 | ) { |
1805 | | /* We have a dialogue, with this key, opened before this request */ |
1806 | | #ifdef DEBUG_TCAPSRT |
1807 | | dbg(10,"E%d ", p_tcaphash_endcall->context->session_id); |
1808 | | #endif |
1809 | 0 | return p_tcaphash_endcall; |
1810 | 0 | } |
1811 | | #ifdef DEBUG_TCAPSRT |
1812 | | dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id); |
1813 | | #endif |
1814 | 0 | } |
1815 | | /* Break when list end is reached */ |
1816 | 0 | if(p_tcaphash_endcall->next_endcall == NULL) { |
1817 | | #ifdef DEBUG_TCAPSRT |
1818 | | dbg(23,"End of Elist "); |
1819 | | #endif |
1820 | 0 | break; |
1821 | 0 | } |
1822 | 0 | p_tcaphash_endcall = p_tcaphash_endcall->next_endcall; |
1823 | 0 | } while (p_tcaphash_endcall != NULL) ; |
1824 | 0 | } else { |
1825 | | #ifdef DEBUG_TCAPSRT |
1826 | | dbg(23,"Not in Ehash "); |
1827 | | #endif |
1828 | 0 | } |
1829 | 0 | return NULL; |
1830 | 0 | } |
1831 | | |
1832 | | /* |
1833 | | * New record to create, to identify a new transaction |
1834 | | */ |
1835 | | static struct tcaphash_context_t * |
1836 | | new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key, |
1837 | | packet_info *pinfo) |
1838 | 0 | { |
1839 | 0 | struct tcaphash_context_key_t *p_new_tcaphash_context_key; |
1840 | 0 | struct tcaphash_context_t *p_new_tcaphash_context = NULL; |
1841 | | |
1842 | | /* Register the transaction in the hash table |
1843 | | with the tcap transaction Id as Main Key |
1844 | | Once created, this entry will be updated later */ |
1845 | |
|
1846 | 0 | p_new_tcaphash_context_key = wmem_new(wmem_file_scope(), struct tcaphash_context_key_t); |
1847 | 0 | p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id; |
1848 | |
|
1849 | 0 | p_new_tcaphash_context = wmem_new0(wmem_file_scope(), struct tcaphash_context_t); |
1850 | 0 | p_new_tcaphash_context->key = p_new_tcaphash_context_key; |
1851 | 0 | p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id; |
1852 | 0 | p_new_tcaphash_context->first_frame = pinfo->num; |
1853 | | #ifdef DEBUG_TCAPSRT |
1854 | | dbg(10,"S%d ", p_new_tcaphash_context->session_id); |
1855 | | #endif |
1856 | | /* store it */ |
1857 | 0 | wmem_map_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context); |
1858 | 0 | return p_new_tcaphash_context; |
1859 | 0 | } |
1860 | | |
1861 | | /* |
1862 | | * New record to create, to identify a new transaction |
1863 | | */ |
1864 | | static struct tcaphash_begincall_t * |
1865 | | new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key, |
1866 | | struct tcaphash_context_t *p_tcaphash_context) |
1867 | 0 | { |
1868 | 0 | struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key; |
1869 | 0 | struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL; |
1870 | | |
1871 | | /* Register the transaction in the hash table |
1872 | | with the tcap transaction Id as Main Key |
1873 | | Once created, this entry will be updated later */ |
1874 | |
|
1875 | 0 | p_new_tcaphash_begin_key = wmem_new(wmem_file_scope(), struct tcaphash_begin_info_key_t); |
1876 | 0 | p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey; |
1877 | 0 | p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid; |
1878 | 0 | p_new_tcaphash_begin_key->pc_hash = p_tcaphash_begin_key->pc_hash; |
1879 | |
|
1880 | 0 | p_new_tcaphash_begincall = wmem_new0(wmem_file_scope(), struct tcaphash_begincall_t); |
1881 | 0 | p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key; |
1882 | 0 | p_new_tcaphash_begincall->context=p_tcaphash_context; |
1883 | 0 | p_tcaphash_context->begincall=p_new_tcaphash_begincall; |
1884 | 0 | p_new_tcaphash_begincall->father=true; |
1885 | 0 | p_new_tcaphash_begincall->next_begincall=NULL; |
1886 | 0 | p_new_tcaphash_begincall->previous_begincall=NULL; |
1887 | |
|
1888 | | #ifdef DEBUG_TCAPSRT |
1889 | | dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id); |
1890 | | #endif |
1891 | | /* store it */ |
1892 | 0 | wmem_map_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall); |
1893 | 0 | return p_new_tcaphash_begincall; |
1894 | 0 | } |
1895 | | |
1896 | | |
1897 | | |
1898 | | /* |
1899 | | * New record to create, to identify a new transaction |
1900 | | */ |
1901 | | static struct tcaphash_contcall_t * |
1902 | | new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key, |
1903 | | struct tcaphash_context_t *p_tcaphash_context) |
1904 | 0 | { |
1905 | 0 | struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key; |
1906 | 0 | struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL; |
1907 | | |
1908 | | /* Register the transaction in the hash table |
1909 | | with the tcap transaction Id as Main Key |
1910 | | Once created, this entry will be updated later */ |
1911 | |
|
1912 | 0 | p_new_tcaphash_cont_key = wmem_new(wmem_file_scope(), struct tcaphash_cont_info_key_t); |
1913 | 0 | p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey; |
1914 | 0 | p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid; |
1915 | 0 | p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid; |
1916 | 0 | p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash; |
1917 | 0 | p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash; |
1918 | |
|
1919 | 0 | p_new_tcaphash_contcall = wmem_new0(wmem_file_scope(), struct tcaphash_contcall_t); |
1920 | 0 | p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key; |
1921 | 0 | p_new_tcaphash_contcall->context=p_tcaphash_context; |
1922 | 0 | p_tcaphash_context->contcall=p_new_tcaphash_contcall; |
1923 | 0 | p_new_tcaphash_contcall->father=true; |
1924 | 0 | p_new_tcaphash_contcall->next_contcall=NULL; |
1925 | 0 | p_new_tcaphash_contcall->previous_contcall=NULL; |
1926 | |
|
1927 | | #ifdef DEBUG_TCAPSRT |
1928 | | dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id); |
1929 | | #endif |
1930 | | /* store it */ |
1931 | 0 | wmem_map_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall); |
1932 | 0 | return p_new_tcaphash_contcall; |
1933 | 0 | } |
1934 | | |
1935 | | |
1936 | | /* |
1937 | | * New record to create, to identify a new transaction |
1938 | | */ |
1939 | | static struct tcaphash_endcall_t * |
1940 | | new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key, |
1941 | | struct tcaphash_context_t *p_tcaphash_context) |
1942 | 0 | { |
1943 | 0 | struct tcaphash_end_info_key_t *p_new_tcaphash_end_key; |
1944 | 0 | struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL; |
1945 | | |
1946 | | /* Register the transaction in the hash table |
1947 | | with the tcap transaction Id as Main Key |
1948 | | Once created, this entry will be updated later */ |
1949 | |
|
1950 | 0 | p_new_tcaphash_end_key = wmem_new(wmem_file_scope(), struct tcaphash_end_info_key_t); |
1951 | 0 | p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey; |
1952 | 0 | p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid; |
1953 | 0 | p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash; |
1954 | 0 | p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash; |
1955 | |
|
1956 | 0 | p_new_tcaphash_endcall = wmem_new0(wmem_file_scope(), struct tcaphash_endcall_t); |
1957 | 0 | p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key; |
1958 | 0 | p_new_tcaphash_endcall->context=p_tcaphash_context; |
1959 | 0 | p_tcaphash_context->endcall=p_new_tcaphash_endcall; |
1960 | 0 | p_new_tcaphash_endcall->father=true; |
1961 | 0 | p_new_tcaphash_endcall->next_endcall=NULL; |
1962 | 0 | p_new_tcaphash_endcall->previous_endcall=NULL; |
1963 | |
|
1964 | | #ifdef DEBUG_TCAPSRT |
1965 | | dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id); |
1966 | | #endif |
1967 | | /* store it */ |
1968 | 0 | wmem_map_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall); |
1969 | 0 | return p_new_tcaphash_endcall; |
1970 | 0 | } |
1971 | | /* |
1972 | | * New record to create, to identify a new transaction |
1973 | | */ |
1974 | | static struct tcaphash_ansicall_t * |
1975 | | new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key, |
1976 | | struct tcaphash_context_t *p_tcaphash_context) |
1977 | 0 | { |
1978 | 0 | struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key; |
1979 | 0 | struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL; |
1980 | | |
1981 | | /* Register the transaction in the hash table |
1982 | | with the tcap transaction Id as Main Key |
1983 | | Once created, this entry will be updated later */ |
1984 | |
|
1985 | 0 | p_new_tcaphash_ansi_key = wmem_new(wmem_file_scope(), struct tcaphash_ansi_info_key_t); |
1986 | 0 | p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey; |
1987 | 0 | p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid; |
1988 | 0 | p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash; |
1989 | 0 | p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash; |
1990 | |
|
1991 | 0 | p_new_tcaphash_ansicall = wmem_new0(wmem_file_scope(), struct tcaphash_ansicall_t); |
1992 | 0 | p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key; |
1993 | 0 | p_new_tcaphash_ansicall->context=p_tcaphash_context; |
1994 | 0 | p_tcaphash_context->ansicall=p_new_tcaphash_ansicall; |
1995 | 0 | p_new_tcaphash_ansicall->father=true; |
1996 | 0 | p_new_tcaphash_ansicall->next_ansicall=NULL; |
1997 | 0 | p_new_tcaphash_ansicall->previous_ansicall=NULL; |
1998 | |
|
1999 | | #ifdef DEBUG_TCAPSRT |
2000 | | dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id); |
2001 | | #endif |
2002 | | /* store it */ |
2003 | 0 | wmem_map_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall); |
2004 | 0 | return p_new_tcaphash_ansicall; |
2005 | 0 | } |
2006 | | |
2007 | | static struct tcaphash_contcall_t * |
2008 | | create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key, |
2009 | | struct tcaphash_context_t *p_tcaphash_context) |
2010 | 0 | { |
2011 | 0 | struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL; |
2012 | 0 | struct tcaphash_contcall_t *p_tcaphash_contcall = NULL; |
2013 | |
|
2014 | 0 | p_tcaphash_contcall1 = (struct tcaphash_contcall_t *) |
2015 | 0 | wmem_map_lookup(tcaphash_cont, p_tcaphash_cont_key); |
2016 | |
|
2017 | 0 | if (p_tcaphash_contcall1) { |
2018 | | /* Walk through list of transaction with identical keys */ |
2019 | | /* go to the end to insert new record */ |
2020 | 0 | do { |
2021 | 0 | if (!p_tcaphash_contcall1->next_contcall) { |
2022 | 0 | p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1, |
2023 | 0 | p_tcaphash_context); |
2024 | 0 | break; |
2025 | 0 | } |
2026 | 0 | p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall; |
2027 | 0 | } while (p_tcaphash_contcall1 != NULL ); |
2028 | 0 | } else { |
2029 | 0 | p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key, |
2030 | 0 | p_tcaphash_context); |
2031 | 0 | } |
2032 | 0 | return p_tcaphash_contcall; |
2033 | 0 | } |
2034 | | |
2035 | | |
2036 | | static struct tcaphash_endcall_t * |
2037 | | create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key, |
2038 | | struct tcaphash_context_t *p_tcaphash_context) |
2039 | 0 | { |
2040 | 0 | struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL; |
2041 | 0 | struct tcaphash_endcall_t *p_tcaphash_endcall = NULL; |
2042 | |
|
2043 | 0 | p_tcaphash_endcall1 = (struct tcaphash_endcall_t *) |
2044 | 0 | wmem_map_lookup(tcaphash_end, p_tcaphash_end_key); |
2045 | |
|
2046 | 0 | if (p_tcaphash_endcall1) { |
2047 | | /* Walk through list of transaction with identical keys */ |
2048 | | /* go to the end to insert new record */ |
2049 | 0 | do { |
2050 | 0 | if (!p_tcaphash_endcall1->next_endcall) { |
2051 | 0 | p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1, |
2052 | 0 | p_tcaphash_context); |
2053 | 0 | break; |
2054 | 0 | } |
2055 | 0 | p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall; |
2056 | 0 | } while (p_tcaphash_endcall1 != NULL ); |
2057 | 0 | } else { |
2058 | 0 | p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key, |
2059 | 0 | p_tcaphash_context); |
2060 | 0 | } |
2061 | 0 | return p_tcaphash_endcall; |
2062 | 0 | } |
2063 | | |
2064 | | /* |
2065 | | * Create the record identifiying the TCAP transaction |
2066 | | * When the identifier for the transaction is reused, check |
2067 | | * the following criteria before to append a new record: |
2068 | | * - a timeout corresponding to a message retransmission is detected, |
2069 | | * - a message hast been lost |
2070 | | * - or the previous transaction has been be closed |
2071 | | */ |
2072 | | static struct tcaphash_context_t * |
2073 | | tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2074 | | struct tcapsrt_info_t *p_tcapsrt_info) |
2075 | 0 | { |
2076 | 0 | struct tcaphash_context_t *p_tcaphash_context=NULL; |
2077 | 0 | struct tcaphash_context_key_t tcaphash_context_key; |
2078 | 0 | struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL; |
2079 | 0 | struct tcaphash_begin_info_key_t tcaphash_begin_key; |
2080 | 0 | proto_item *pi; |
2081 | 0 | proto_item *stat_item=NULL; |
2082 | 0 | proto_tree *stat_tree=NULL; |
2083 | |
|
2084 | | #ifdef DEBUG_TCAPSRT |
2085 | | 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)); |
2086 | | #endif |
2087 | | |
2088 | | /* prepare the key data */ |
2089 | 0 | tcaphash_begin_key.tid = p_tcapsrt_info->src_tid; |
2090 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2091 | 0 | { |
2092 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2093 | 0 | tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data); |
2094 | 0 | } else { |
2095 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2096 | 0 | tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src)); |
2097 | 0 | } |
2098 | 0 | tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key); |
2099 | | |
2100 | | /* look up the request */ |
2101 | | #ifdef DEBUG_TCAPSRT |
2102 | | dbg(10,"\n Hbegin #%u ", pinfo->num); |
2103 | | dbg(11,"key %lx ",tcaphash_begin_key.hashKey); |
2104 | | dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->src)); |
2105 | | dbg(51,"Tid %lx \n",tcaphash_begin_key.tid); |
2106 | | #endif |
2107 | |
|
2108 | 0 | p_tcaphash_begincall = (struct tcaphash_begincall_t *) |
2109 | 0 | wmem_map_lookup(tcaphash_begin, &tcaphash_begin_key); |
2110 | |
|
2111 | 0 | if (p_tcaphash_begincall) { |
2112 | | /* Walk through list of transaction with identical keys */ |
2113 | 0 | do { |
2114 | | /* Check if the request with this reqSeqNum has been seen, with the same Message Type */ |
2115 | 0 | if (pinfo->num == p_tcaphash_begincall->context->first_frame) { |
2116 | | /* We have seen this request before -> do nothing */ |
2117 | | #ifdef DEBUG_TCAPSRT |
2118 | | dbg(22,"Already seen "); |
2119 | | #endif |
2120 | 0 | p_tcaphash_context=p_tcaphash_begincall->context; |
2121 | 0 | break; |
2122 | 0 | } |
2123 | | /* If the last record for Tcap transaction with identifier has not been reached */ |
2124 | 0 | if (!p_tcaphash_begincall->next_begincall) { |
2125 | | /* check if we have to create a new record or not */ |
2126 | | /* if last request has been responded (response number is known) |
2127 | | and this request appears after last response (has bigger frame number) |
2128 | | and last request occurred after the timeout for repetition, |
2129 | | or |
2130 | | if last request hasn't been responded (so number unknown) |
2131 | | and this request appears after last request (has bigger frame number) |
2132 | | and this request occurred after the timeout for message lost */ |
2133 | 0 | if ( ( p_tcaphash_begincall->context->last_frame != 0 |
2134 | 0 | && pinfo->num > p_tcaphash_begincall->context->first_frame |
2135 | 0 | && (unsigned) pinfo->abs_ts.secs > (unsigned)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout) |
2136 | 0 | ) || |
2137 | 0 | ( p_tcaphash_begincall->context->last_frame == 0 |
2138 | 0 | && pinfo->num > p_tcaphash_begincall->context->first_frame |
2139 | 0 | && (unsigned)pinfo->abs_ts.secs > (unsigned)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout) |
2140 | 0 | ) |
2141 | 0 | ) |
2142 | 0 | { |
2143 | | /* we decide that we have a new request */ |
2144 | | /* Append new record to the list */ |
2145 | | #ifdef DEBUG_TCAPSRT |
2146 | | dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey); |
2147 | | dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_begincall->context->last_frame ); |
2148 | | #endif |
2149 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2150 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2151 | |
|
2152 | 0 | p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall, |
2153 | 0 | p_tcaphash_context, |
2154 | 0 | pinfo); |
2155 | | #ifdef DEBUG_TCAPSRT |
2156 | | dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey); |
2157 | | #endif |
2158 | 0 | update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo); |
2159 | 0 | } else { /* timeout or message lost */ |
2160 | | |
2161 | | /* If the Tid is reused for a closed Transaction */ |
2162 | | /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */ |
2163 | | /* (this is the case, for pre-arranged END, the transaction is marked as closed */ |
2164 | | /* by the upper layer, thank to a callback method close) */ |
2165 | 0 | if ( p_tcaphash_begincall->context->closed) { |
2166 | | #ifdef DEBUG_TCAPSRT |
2167 | | dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey); |
2168 | | dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_begincall->context->last_frame ); |
2169 | | #endif |
2170 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2171 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2172 | 0 | p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall, |
2173 | 0 | p_tcaphash_context, |
2174 | 0 | pinfo); |
2175 | |
|
2176 | | #ifdef DEBUG_TCAPSRT |
2177 | | dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey); |
2178 | | #endif |
2179 | 0 | update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo); |
2180 | |
|
2181 | 0 | } else { |
2182 | | /* the TCAP session is not closed, so, either messages have been lost */ |
2183 | | /* or it's a duplicate request. Mark it as such. */ |
2184 | | #ifdef DEBUG_TCAPSRT |
2185 | | dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame); |
2186 | | #endif |
2187 | 0 | p_tcaphash_context=p_tcaphash_begincall->context; |
2188 | 0 | if (gtcap_DisplaySRT && tree) { |
2189 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2190 | 0 | proto_item_set_generated(stat_item); |
2191 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0, |
2192 | 0 | p_tcaphash_context->first_frame, |
2193 | 0 | "Duplicate with session %u in frame %u", |
2194 | 0 | p_tcaphash_context->session_id,p_tcaphash_context->first_frame); |
2195 | 0 | proto_item_set_generated(pi); |
2196 | 0 | } |
2197 | 0 | return p_tcaphash_context; |
2198 | 0 | } /* Previous session closed */ |
2199 | 0 | } /* test with Timeout or message Lost */ |
2200 | 0 | break; |
2201 | 0 | } /* Next call is NULL */ |
2202 | | /* Repeat the tests for the next record with the same transaction identifier */ |
2203 | 0 | p_tcaphash_begincall = p_tcaphash_begincall->next_begincall; |
2204 | 0 | } while (p_tcaphash_begincall != NULL ); |
2205 | | /* |
2206 | | * End of analyze for the list be TC_BEGIN with same transaction ID |
2207 | | */ |
2208 | 0 | } else { /* p_tcaphash_begincall has not been found */ |
2209 | | /* |
2210 | | * Create a new TCAP context |
2211 | | */ |
2212 | | #ifdef DEBUG_TCAPSRT |
2213 | | dbg(10,"New key %lx ",tcaphash_begin_key.hashKey); |
2214 | | #endif |
2215 | |
|
2216 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2217 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2218 | 0 | p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context); |
2219 | |
|
2220 | | #ifdef DEBUG_TCAPSRT |
2221 | | dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey); |
2222 | | dbg(11,"Frame reqlink #%u ", pinfo->num); |
2223 | | #endif |
2224 | 0 | update_tcaphash_begincall(p_tcaphash_begincall, pinfo); |
2225 | 0 | } |
2226 | | |
2227 | | /* display tcap session, if available */ |
2228 | 0 | if ( gtcap_DisplaySRT && tree && |
2229 | 0 | p_tcaphash_context && |
2230 | 0 | p_tcaphash_context->session_id) { |
2231 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_tcap_stat, &stat_item, "Stat"); |
2232 | 0 | proto_item_set_generated(stat_item); |
2233 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2234 | 0 | proto_item_set_generated(pi); |
2235 | | |
2236 | | /* add link to response frame, if available */ |
2237 | | /* p_tcaphash_begincall->context->last_frame) */ |
2238 | 0 | if( p_tcaphash_context->last_frame != 0 ){ |
2239 | | #ifdef DEBUG_TCAPSRT |
2240 | | dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame); |
2241 | | #endif |
2242 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0, |
2243 | 0 | p_tcaphash_context->last_frame, |
2244 | 0 | "End of session in frame %u", |
2245 | 0 | p_tcaphash_context->last_frame); |
2246 | 0 | proto_item_set_generated(pi); |
2247 | 0 | } |
2248 | 0 | } |
2249 | 0 | return p_tcaphash_context; |
2250 | 0 | } |
2251 | | |
2252 | | /* |
2253 | | * Try to find a TCAP session according to the source and destination |
2254 | | * Identifier given in the TC_CONT |
2255 | | * If nothing is found, it is probably a session in opening state, so try to find |
2256 | | * a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT |
2257 | | * Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key" |
2258 | | * and display the available info for the TCAP context |
2259 | | */ |
2260 | | static struct tcaphash_context_t * |
2261 | | tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2262 | | struct tcapsrt_info_t *p_tcapsrt_info) |
2263 | 0 | { |
2264 | 0 | struct tcaphash_context_t *p_tcaphash_context=NULL; |
2265 | 0 | struct tcaphash_contcall_t *p_tcaphash_contcall; |
2266 | 0 | struct tcaphash_cont_info_key_t tcaphash_cont_key; |
2267 | 0 | struct tcaphash_begin_info_key_t tcaphash_begin_key; |
2268 | 0 | struct tcaphash_begincall_t *p_tcaphash_begincall; |
2269 | 0 | struct tcaphash_end_info_key_t tcaphash_end_key; |
2270 | 0 | proto_item *pi; |
2271 | 0 | proto_item *stat_item=NULL; |
2272 | 0 | proto_tree *stat_tree=NULL; |
2273 | 0 | bool use_dst = false; |
2274 | |
|
2275 | | #ifdef DEBUG_TCAPSRT |
2276 | | 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); |
2277 | | dbg(10,"\n Hcont #%u ", pinfo->num); |
2278 | | #endif |
2279 | | |
2280 | | /* look only for matching request, if matching conversation is available. */ |
2281 | 0 | tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid; |
2282 | 0 | tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid; |
2283 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2284 | 0 | { |
2285 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2286 | 0 | tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data); |
2287 | 0 | tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data); |
2288 | 0 | } else { |
2289 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2290 | 0 | tcaphash_cont_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src)); |
2291 | 0 | tcaphash_cont_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst)); |
2292 | 0 | } |
2293 | 0 | tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key); |
2294 | |
|
2295 | | #ifdef DEBUG_TCAPSRT |
2296 | | dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey); |
2297 | | dbg(51,"addr %s %s ", address_to_str(pinfo->pool, &pinfo->src), address_to_str(pinfo->pool, &pinfo->dst)); |
2298 | | dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid); |
2299 | | #endif |
2300 | 0 | p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo); |
2301 | 0 | if(p_tcaphash_contcall) { |
2302 | | #ifdef DEBUG_TCAPSRT |
2303 | | dbg(12,"CFound "); |
2304 | | #endif |
2305 | 0 | p_tcaphash_context=p_tcaphash_contcall->context; |
2306 | 0 | } else { /* cont not found */ |
2307 | | #ifdef DEBUG_TCAPSRT |
2308 | | dbg(12,"CnotFound "); |
2309 | | #endif |
2310 | | /* Find the TCAP transaction according to the TC_BEGIN (from dtid,dst) */ |
2311 | 0 | tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid; |
2312 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2313 | 0 | { |
2314 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2315 | 0 | tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data); |
2316 | 0 | } else { |
2317 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2318 | 0 | tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst)); |
2319 | 0 | } |
2320 | 0 | tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key); |
2321 | |
|
2322 | | #ifdef DEBUG_TCAPSRT |
2323 | | dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey); |
2324 | | dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst)); |
2325 | | dbg(51,"Tid %lx \n",tcaphash_begin_key.tid); |
2326 | | #endif |
2327 | 0 | p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, false); |
2328 | 0 | if(!p_tcaphash_begincall){ |
2329 | 0 | try_src: |
2330 | | /* can this actually happen? */ |
2331 | | #ifdef DEBUG_TCAPSRT |
2332 | | dbg(12,"BNotFound trying stid,src"); |
2333 | | #endif |
2334 | | /* Do we have a continue from the same source? (stid,src) */ |
2335 | 0 | use_dst = true; |
2336 | 0 | tcaphash_begin_key.tid = p_tcapsrt_info->src_tid; |
2337 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2338 | 0 | { |
2339 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2340 | 0 | tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data); |
2341 | 0 | } else { |
2342 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2343 | 0 | tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src)); |
2344 | 0 | } |
2345 | 0 | tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key); |
2346 | | #ifdef DEBUG_TCAPSRT |
2347 | | dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey); |
2348 | | dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->src)); |
2349 | | dbg(51,"Tid %lx \n",tcaphash_begin_key.tid); |
2350 | | #endif |
2351 | 0 | p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,false); |
2352 | 0 | } |
2353 | 0 | if(p_tcaphash_begincall && |
2354 | 0 | !p_tcaphash_begincall->context->contcall ) { |
2355 | | #ifdef DEBUG_TCAPSRT |
2356 | | dbg(12,"BFound \n"); |
2357 | | #endif |
2358 | 0 | p_tcaphash_context=p_tcaphash_begincall->context; |
2359 | 0 | p_tcaphash_context->responded=true; |
2360 | |
|
2361 | | #ifdef DEBUG_TCAPSRT |
2362 | | dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey); |
2363 | | dbg(11,"Frame reqlink #%u \n", pinfo->num); |
2364 | | #endif |
2365 | 0 | create_tcaphash_cont(&tcaphash_cont_key, |
2366 | 0 | p_tcaphash_begincall->context); |
2367 | | |
2368 | | /* Create END for (stid,src) or (dtid,dst) */ |
2369 | 0 | tcaphash_end_key.tid = use_dst ? p_tcapsrt_info->dst_tid : p_tcapsrt_info->src_tid; |
2370 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2371 | 0 | { |
2372 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2373 | 0 | tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)(use_dst ? pinfo->dst.data : pinfo->src.data)); |
2374 | 0 | tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)(use_dst ? pinfo->src.data : pinfo->dst.data)); |
2375 | 0 | } else { |
2376 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2377 | 0 | tcaphash_end_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, use_dst ? &pinfo->dst : &pinfo->src)); |
2378 | 0 | tcaphash_end_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, use_dst ? &pinfo->src : &pinfo->dst)); |
2379 | 0 | } |
2380 | 0 | tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key); |
2381 | |
|
2382 | | #ifdef DEBUG_TCAPSRT |
2383 | | dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey); |
2384 | | dbg(51,"addr %s ", address_to_str(pinfo->pool, use_dst ? &pinfo->dst : &pinfo->src)); |
2385 | | dbg(51,"Tid %lx ",tcaphash_end_key.tid); |
2386 | | dbg(11,"Frame reqlink #%u ", pinfo->num); |
2387 | | #endif |
2388 | 0 | create_tcaphash_end(&tcaphash_end_key, |
2389 | 0 | p_tcaphash_begincall->context); |
2390 | |
|
2391 | 0 | } else { /* Begin not found */ |
2392 | | #ifdef DEBUG_TCAPSRT |
2393 | | dbg(12,"BnotFound "); |
2394 | | #endif |
2395 | 0 | if (!use_dst) { |
2396 | | /* make another try with src tid / address */ |
2397 | 0 | goto try_src; |
2398 | 0 | } |
2399 | 0 | } /* begin found */ |
2400 | 0 | } /* cont found */ |
2401 | | /* display tcap session, if available */ |
2402 | 0 | if (gtcap_DisplaySRT && tree && |
2403 | 0 | p_tcaphash_context && |
2404 | 0 | p_tcaphash_context->session_id) { |
2405 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2406 | 0 | proto_item_set_generated(stat_item); |
2407 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2408 | 0 | proto_item_set_generated(pi); |
2409 | 0 | } |
2410 | |
|
2411 | 0 | return p_tcaphash_context; |
2412 | 0 | } |
2413 | | |
2414 | | /* |
2415 | | * Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT |
2416 | | * If nothing is found, |
2417 | | * - either it is a session in opening state, |
2418 | | * - or the session is closed/aborted by the remote, ( so we switch the src and dst tid ) |
2419 | | * so try to find a tcap session registered with a TC_BEGIN "key", |
2420 | | * matching the destination Id of the TC_END |
2421 | | * Then associate the TC_CONT "key" to the TCAP context |
2422 | | * and display the available info for the TCAP context |
2423 | | */ |
2424 | | |
2425 | | static struct tcaphash_context_t * |
2426 | | tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2427 | | struct tcapsrt_info_t *p_tcapsrt_info) |
2428 | 0 | { |
2429 | 0 | struct tcaphash_context_t *p_tcaphash_context=NULL; |
2430 | |
|
2431 | 0 | struct tcaphash_end_info_key_t tcaphash_end_key; |
2432 | 0 | struct tcaphash_endcall_t *p_tcaphash_endcall=NULL; |
2433 | |
|
2434 | 0 | struct tcaphash_begin_info_key_t tcaphash_begin_key; |
2435 | 0 | struct tcaphash_begincall_t *p_tcaphash_begincall=NULL; |
2436 | 0 | proto_item *pi; |
2437 | 0 | nstime_t delta; |
2438 | 0 | proto_item *stat_item=NULL; |
2439 | 0 | proto_tree *stat_tree=NULL; |
2440 | |
|
2441 | | #ifdef DEBUG_TCAPSRT |
2442 | | 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); |
2443 | | dbg(10,"\n Hend #%u ", pinfo->num); |
2444 | | #endif |
2445 | | /* look only for matching request, if matching conversation is available. */ |
2446 | 0 | tcaphash_end_key.tid = p_tcapsrt_info->dst_tid; |
2447 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2448 | 0 | { |
2449 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2450 | 0 | tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data); |
2451 | 0 | tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data); |
2452 | 0 | } else { |
2453 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2454 | 0 | tcaphash_end_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src)); |
2455 | 0 | tcaphash_end_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst)); |
2456 | 0 | } |
2457 | 0 | tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key); |
2458 | |
|
2459 | | #ifdef DEBUG_TCAPSRT |
2460 | | dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey); |
2461 | | dbg(11,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst)); |
2462 | | dbg(51,"Tid %lx ",tcaphash_end_key.tid); |
2463 | | #endif |
2464 | 0 | p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,true); |
2465 | |
|
2466 | 0 | if(!p_tcaphash_endcall) { |
2467 | | #ifdef DEBUG_TCAPSRT |
2468 | | dbg(12,"EnotFound "); |
2469 | | #endif |
2470 | 0 | tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid; |
2471 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2472 | 0 | { |
2473 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2474 | 0 | tcaphash_begin_key.pc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data); |
2475 | 0 | } else { |
2476 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2477 | 0 | tcaphash_begin_key.pc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst)); |
2478 | 0 | } |
2479 | 0 | tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key); |
2480 | |
|
2481 | | #ifdef DEBUG_TCAPSRT |
2482 | | dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey); |
2483 | | dbg(51,"addr %s ", address_to_str(pinfo->pool, &pinfo->dst)); |
2484 | | dbg(51,"Tid %lx ",tcaphash_begin_key.tid); |
2485 | | #endif |
2486 | 0 | p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,false); |
2487 | 0 | if(!p_tcaphash_begincall) { |
2488 | | #ifdef DEBUG_TCAPSRT |
2489 | | dbg(12,"BnotFound "); |
2490 | | #endif |
2491 | 0 | } |
2492 | 0 | } |
2493 | 0 | if (p_tcaphash_endcall) { |
2494 | | /* Use the TC_BEGIN Destination reference */ |
2495 | 0 | p_tcaphash_context=p_tcaphash_endcall->context; |
2496 | 0 | } else if (p_tcaphash_begincall) { |
2497 | | /* Use the TC_BEGIN Source reference */ |
2498 | 0 | p_tcaphash_context=p_tcaphash_begincall->context; |
2499 | 0 | } |
2500 | |
|
2501 | 0 | if (p_tcaphash_context) { |
2502 | |
|
2503 | | #ifdef DEBUG_TCAPSRT |
2504 | | dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame); |
2505 | | #endif |
2506 | 0 | if (gtcap_DisplaySRT && tree) { |
2507 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2508 | 0 | proto_item_set_generated(stat_item); |
2509 | |
|
2510 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2511 | 0 | proto_item_set_generated(pi); |
2512 | 0 | } |
2513 | |
|
2514 | | #ifdef DEBUG_TCAPSRT |
2515 | | dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame); |
2516 | | #endif |
2517 | | /* Indicate the frame to which this is a reply. */ |
2518 | 0 | if (gtcap_DisplaySRT && stat_tree) { |
2519 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0, |
2520 | 0 | p_tcaphash_context->first_frame, |
2521 | 0 | "Begin of session in frame %u", |
2522 | 0 | p_tcaphash_context->first_frame); |
2523 | 0 | proto_item_set_generated(pi); |
2524 | | /* Calculate Service Response Time */ |
2525 | 0 | nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time); |
2526 | | |
2527 | | /* display Service Response Time and make it filterable */ |
2528 | 0 | pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta); |
2529 | 0 | proto_item_set_generated(pi); |
2530 | 0 | } |
2531 | | /* Close the context and remove it (if needed) */ |
2532 | 0 | tcapsrt_close(p_tcaphash_context,pinfo); |
2533 | |
|
2534 | 0 | } else {/* context present */ |
2535 | | #ifdef DEBUG_TCAPSRT |
2536 | | dbg(12,"Context notFound "); |
2537 | | #endif |
2538 | 0 | } |
2539 | 0 | return p_tcaphash_context; |
2540 | 0 | } |
2541 | | |
2542 | | /* |
2543 | | * ANSI PART |
2544 | | * Create the record identifiying the TCAP transaction |
2545 | | * When the identifier for the transaction is reused, check |
2546 | | * the following criteria before to append a new record: |
2547 | | * - a timeout corresponding to a message retransmission is detected, |
2548 | | * - a message hast been lost |
2549 | | * - or the previous transaction has been be closed |
2550 | | */ |
2551 | | static struct tcaphash_context_t * |
2552 | | tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2553 | | struct tcapsrt_info_t *p_tcapsrt_info) |
2554 | 0 | { |
2555 | 0 | struct tcaphash_context_t *p_tcaphash_context=NULL; |
2556 | 0 | struct tcaphash_context_key_t tcaphash_context_key; |
2557 | 0 | struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall; |
2558 | 0 | struct tcaphash_ansi_info_key_t tcaphash_ansi_key; |
2559 | 0 | proto_item *pi; |
2560 | 0 | nstime_t delta; |
2561 | 0 | bool isResponse=false; |
2562 | 0 | proto_tree * stat_tree=NULL; |
2563 | 0 | proto_item * stat_item=NULL; |
2564 | | |
2565 | | /* prepare the key data */ |
2566 | 0 | tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid; |
2567 | 0 | if (pinfo->src.type == ss7pc_address_type && pinfo->dst.type == ss7pc_address_type) |
2568 | 0 | { |
2569 | | /* We have MTP3 PCs (so we can safely do this cast) */ |
2570 | 0 | tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data); |
2571 | 0 | tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data); |
2572 | 0 | } else { |
2573 | | /* Don't have MTP3 PCs (have SCCP GT ?) */ |
2574 | 0 | tcaphash_ansi_key.opc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->src)); |
2575 | 0 | tcaphash_ansi_key.dpc_hash = g_str_hash(address_to_str(pinfo->pool, &pinfo->dst)); |
2576 | 0 | } |
2577 | 0 | tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key); |
2578 | | |
2579 | | /* look up the request */ |
2580 | | #ifdef DEBUG_TCAPSRT |
2581 | | dbg(10,"\n Hansi #%u ", pinfo->num); |
2582 | | dbg(11,"key %lx ",tcaphash_ansi_key.hashKey); |
2583 | | dbg(51,"PC %s %s ",address_to_str(pinfo->pool, &pinfo->src), address_to_str(pinfo->pool, &pinfo->dst)); |
2584 | | dbg(51,"Tid %lx ",tcaphash_ansi_key.tid); |
2585 | | #endif |
2586 | 0 | p_tcaphash_ansicall = (struct tcaphash_ansicall_t *) |
2587 | 0 | wmem_map_lookup(tcaphash_ansi, &tcaphash_ansi_key); |
2588 | |
|
2589 | 0 | if (p_tcaphash_ansicall) { |
2590 | | /* Walk through list of transaction with identical keys */ |
2591 | 0 | do { |
2592 | | /* Check if the request with this reqSeqNum has been seen */ |
2593 | 0 | if (pinfo->num == p_tcaphash_ansicall->context->first_frame) { |
2594 | | /* We have seen this request before -> do nothing */ |
2595 | | #ifdef DEBUG_TCAPSRT |
2596 | | dbg(22,"Request already seen "); |
2597 | | #endif |
2598 | 0 | isResponse=false; |
2599 | 0 | p_tcaphash_context=p_tcaphash_ansicall->context; |
2600 | 0 | break; |
2601 | 0 | } |
2602 | | |
2603 | | /* Check if the response with this reqSeqNum has been seen */ |
2604 | 0 | if (pinfo->num == p_tcaphash_ansicall->context->last_frame) { |
2605 | | /* We have seen this response before -> do nothing */ |
2606 | | #ifdef DEBUG_TCAPSRT |
2607 | | dbg(22,"Response already seen "); |
2608 | | #endif |
2609 | 0 | isResponse=true; |
2610 | 0 | p_tcaphash_context=p_tcaphash_ansicall->context; |
2611 | 0 | break; |
2612 | 0 | } |
2613 | | |
2614 | | /* Check for the first Request without Response |
2615 | | received before this frame */ |
2616 | 0 | if ( pinfo->num > p_tcaphash_ansicall->context->first_frame && |
2617 | 0 | p_tcaphash_ansicall->context->last_frame==0 ) { |
2618 | | /* Take it, and update the context */ |
2619 | |
|
2620 | | #ifdef DEBUG_TCAPSRT |
2621 | | dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey); |
2622 | | #endif |
2623 | 0 | p_tcaphash_ansicall->context->last_frame = pinfo->num; |
2624 | 0 | p_tcaphash_ansicall->context->responded = true; |
2625 | 0 | p_tcaphash_ansicall->context->closed = true; |
2626 | 0 | p_tcaphash_context=p_tcaphash_ansicall->context; |
2627 | 0 | isResponse=true; |
2628 | |
|
2629 | 0 | if (gtcap_DisplaySRT && tree) { |
2630 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2631 | 0 | proto_item_set_generated(stat_item); |
2632 | |
|
2633 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2634 | 0 | proto_item_set_generated(pi); |
2635 | |
|
2636 | | #ifdef DEBUG_TCAPSRT |
2637 | | dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame); |
2638 | | #endif |
2639 | | /* Indicate the frame to which this is a reply. */ |
2640 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0, |
2641 | 0 | p_tcaphash_context->first_frame, |
2642 | 0 | "Begin of session in frame %u", |
2643 | 0 | p_tcaphash_context->first_frame); |
2644 | 0 | proto_item_set_generated(pi); |
2645 | | /* Calculate Service Response Time */ |
2646 | 0 | nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time); |
2647 | | |
2648 | | /* display Service Response Time and make it filterable */ |
2649 | 0 | pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta); |
2650 | 0 | proto_item_set_generated(pi); |
2651 | 0 | } |
2652 | 0 | break; |
2653 | 0 | } /* Lastframe=0, so take it */ |
2654 | | |
2655 | | |
2656 | | /* If the last record for Tcap transaction with identifier has been reached */ |
2657 | 0 | if (!p_tcaphash_ansicall->next_ansicall) { |
2658 | | /* check if we have to create a new record or not */ |
2659 | | /* if last request has been responded (response number in known) |
2660 | | and this request appears after last response (has bigger frame number) |
2661 | | and last request occurred after the timeout for repetition, |
2662 | | or |
2663 | | if last request hasn't been responded (so number unknown) |
2664 | | and this request appears after last request (has bigger frame number) |
2665 | | and this request occurred after the timeout for message lost */ |
2666 | 0 | if ( ( p_tcaphash_ansicall->context->last_frame != 0 |
2667 | 0 | && pinfo->num > p_tcaphash_ansicall->context->first_frame |
2668 | 0 | && (unsigned) pinfo->abs_ts.secs > (unsigned)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout) |
2669 | 0 | ) || |
2670 | 0 | ( p_tcaphash_ansicall->context->last_frame == 0 |
2671 | 0 | && pinfo->num > p_tcaphash_ansicall->context->first_frame |
2672 | 0 | && (unsigned)pinfo->abs_ts.secs > (unsigned)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout) |
2673 | 0 | ) |
2674 | 0 | ) |
2675 | 0 | { |
2676 | | /* we decide that we have a new request */ |
2677 | | /* Append new record to the list */ |
2678 | | #ifdef DEBUG_TCAPSRT |
2679 | | dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey); |
2680 | | dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_ansicall->context->last_frame ); |
2681 | | #endif |
2682 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2683 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2684 | 0 | p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall, |
2685 | 0 | p_tcaphash_context, |
2686 | 0 | pinfo); |
2687 | |
|
2688 | | #ifdef DEBUG_TCAPSRT |
2689 | | dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey); |
2690 | | #endif |
2691 | 0 | update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo); |
2692 | 0 | p_tcaphash_ansicall=p_new_tcaphash_ansicall; |
2693 | 0 | } else { |
2694 | | |
2695 | | /* If the Tid is reused for a closed Transaction */ |
2696 | 0 | if ( p_tcaphash_ansicall->context->closed) { |
2697 | | #ifdef DEBUG_TCAPSRT |
2698 | | dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey); |
2699 | | dbg(12,"Frame %u rsp %u ",pinfo->num,p_tcaphash_ansicall->context->last_frame ); |
2700 | | #endif |
2701 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2702 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2703 | 0 | p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall, |
2704 | 0 | p_tcaphash_context, |
2705 | 0 | pinfo); |
2706 | |
|
2707 | | #ifdef DEBUG_TCAPSRT |
2708 | | dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey); |
2709 | | #endif |
2710 | 0 | update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo); |
2711 | 0 | p_tcaphash_ansicall=p_new_tcaphash_ansicall; |
2712 | |
|
2713 | 0 | } else { |
2714 | | /* the Tid is reused for an opened Transaction */ |
2715 | | /* so, this is the reply to the request of our context */ |
2716 | 0 | p_tcaphash_context=p_tcaphash_ansicall->context; |
2717 | | #ifdef DEBUG_TCAPSRT |
2718 | | dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame); |
2719 | | #endif |
2720 | |
|
2721 | 0 | if (gtcap_DisplaySRT && tree) { |
2722 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2723 | 0 | proto_item_set_generated(stat_item); |
2724 | |
|
2725 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2726 | 0 | proto_item_set_generated(pi); |
2727 | |
|
2728 | | #ifdef DEBUG_TCAPSRT |
2729 | | dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame); |
2730 | | #endif |
2731 | | /* Indicate the frame to which this is a reply. */ |
2732 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0, |
2733 | 0 | p_tcaphash_context->first_frame, |
2734 | 0 | "Begin of session in frame %u", |
2735 | 0 | p_tcaphash_context->first_frame); |
2736 | 0 | proto_item_set_generated(pi); |
2737 | | /* Calculate Service Response Time */ |
2738 | 0 | nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time); |
2739 | | |
2740 | | /* display Service Response Time and make it filterable */ |
2741 | 0 | pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta); |
2742 | 0 | proto_item_set_generated(pi); |
2743 | 0 | } |
2744 | 0 | p_tcaphash_context=p_tcaphash_ansicall->context; |
2745 | 0 | } /* test with Timeout */ |
2746 | 0 | } /* closed */ |
2747 | 0 | break; |
2748 | 0 | } /* Next call is NULL */ |
2749 | 0 | p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall; |
2750 | 0 | } while (p_tcaphash_ansicall != NULL ); |
2751 | | /* |
2752 | | * New TCAP context |
2753 | | */ |
2754 | 0 | } else { /* p_tcaphash_ansicall has not been found */ |
2755 | | #ifdef DEBUG_TCAPSRT |
2756 | | dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey); |
2757 | | #endif |
2758 | |
|
2759 | 0 | tcaphash_context_key.session_id = tcapsrt_global_SessionId++; |
2760 | 0 | p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo); |
2761 | 0 | p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context); |
2762 | |
|
2763 | | #ifdef DEBUG_TCAPSRT |
2764 | | dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey); |
2765 | | dbg(11,"Frame reqlink #%u ", pinfo->num); |
2766 | | #endif |
2767 | 0 | update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo); |
2768 | 0 | } |
2769 | | |
2770 | | /* display tcap session, if available */ |
2771 | 0 | if ( gtcap_DisplaySRT && tree && |
2772 | 0 | p_tcaphash_context && |
2773 | 0 | p_tcaphash_context->session_id) { |
2774 | 0 | stat_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tcap_stat, &stat_item, "Stat"); |
2775 | 0 | proto_item_set_generated(stat_item); |
2776 | 0 | pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id); |
2777 | 0 | proto_item_set_generated(pi); |
2778 | 0 | } |
2779 | | |
2780 | | |
2781 | | /* add link to response frame, if available */ |
2782 | 0 | if( gtcap_DisplaySRT && stat_tree && |
2783 | 0 | p_tcaphash_ansicall->context->last_frame != 0){ |
2784 | 0 | if (!isResponse) { /* Request */ |
2785 | | #ifdef DEBUG_TCAPSRT |
2786 | | dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame); |
2787 | | #endif |
2788 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0, |
2789 | 0 | p_tcaphash_ansicall->context->last_frame, |
2790 | 0 | "End of session in frame %u", |
2791 | 0 | p_tcaphash_ansicall->context->last_frame); |
2792 | 0 | proto_item_set_generated(pi); |
2793 | 0 | } else { /* Response */ |
2794 | | #ifdef DEBUG_TCAPSRT |
2795 | | dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame); |
2796 | | #endif |
2797 | | /* Indicate the frame to which this is a reply. */ |
2798 | 0 | if (gtcap_DisplaySRT) { |
2799 | 0 | pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0, |
2800 | 0 | p_tcaphash_context->first_frame, |
2801 | 0 | "Begin of session in frame %u", |
2802 | 0 | p_tcaphash_context->first_frame); |
2803 | 0 | proto_item_set_generated(pi); |
2804 | | /* Calculate Service Response Time */ |
2805 | 0 | nstime_delta(&delta, &pinfo->abs_ts, &p_tcaphash_context->begin_time); |
2806 | | |
2807 | | /* display Service Response Time and make it filterable */ |
2808 | 0 | pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta); |
2809 | 0 | proto_item_set_generated(pi); |
2810 | 0 | } |
2811 | 0 | } /* Request or Response */ |
2812 | 0 | } |
2813 | 0 | return p_tcaphash_context; |
2814 | 0 | } |
2815 | | |
2816 | | /* |
2817 | | * Service Response Time analyze |
2818 | | * Called just after dissector call |
2819 | | * Associate a TCAP context to a tcap session and display session related infomations |
2820 | | * like the first frame, the last, the session duration, |
2821 | | * and a uniq session identifier for the filtering |
2822 | | * |
2823 | | * For ETSI tcap, the TCAP context can be reached through three keys |
2824 | | * - a key (BEGIN) identifying the session according to the tcap source identifier |
2825 | | * - a key (CONT) identifying the established session (src_id and dst_id) |
2826 | | * - a key (END) identifying the session according to the tcap destination identifier |
2827 | | * |
2828 | | * For ANSI tcap, the TCAP context is reached through a uniq key |
2829 | | * - a key (ANSI) identifying the session according to the tcap identifier |
2830 | | */ |
2831 | | struct tcaphash_context_t * |
2832 | | tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2833 | | struct tcapsrt_info_t *p_tcapsrt_info) |
2834 | 24 | { |
2835 | 24 | struct tcaphash_context_t *tcap_context=NULL; |
2836 | | |
2837 | | /* if this packet isn't loaded because of a read filter, don't output anything */ |
2838 | 24 | if(pinfo == NULL || pinfo->num == 0) { |
2839 | 0 | return NULL; |
2840 | 0 | } |
2841 | | |
2842 | 24 | switch (p_tcapsrt_info->ope) { |
2843 | | |
2844 | 0 | case TC_BEGIN: |
2845 | | #ifdef DEBUG_TCAPSRT |
2846 | | dbg(1,"\nTC_BEGIN "); |
2847 | | #endif |
2848 | 0 | tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info); |
2849 | 0 | break; |
2850 | | |
2851 | 0 | case TC_CONT: |
2852 | | #ifdef DEBUG_TCAPSRT |
2853 | | dbg(1,"\nTC_CONT "); |
2854 | | #endif |
2855 | 0 | tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info); |
2856 | 0 | break; |
2857 | | |
2858 | 0 | case TC_ABORT: |
2859 | | #ifdef DEBUG_TCAPSRT |
2860 | | dbg(1,"\nTC_ABORT "); |
2861 | | #endif |
2862 | 0 | tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info); |
2863 | 0 | break; |
2864 | | |
2865 | 0 | case TC_END: |
2866 | | #ifdef DEBUG_TCAPSRT |
2867 | | dbg(1,"\nTC_END "); |
2868 | | #endif |
2869 | 0 | tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info); |
2870 | 0 | break; |
2871 | | |
2872 | 0 | case TC_ANSI_ALL: |
2873 | 0 | case TC_ANSI_ABORT: |
2874 | | #ifdef DEBUG_TCAPSRT |
2875 | | dbg(1,"\nTC_ANSI "); |
2876 | | #endif |
2877 | 0 | tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info); |
2878 | 0 | break; |
2879 | | |
2880 | 24 | default: |
2881 | | #ifdef DEBUG_TCAPSRT |
2882 | | dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope); |
2883 | | #endif |
2884 | 24 | break; |
2885 | 24 | } /* switch tcapop */ |
2886 | | #ifdef DEBUG_TCAPSRT |
2887 | | if (tcap_context) |
2888 | | dbg(1,"session %d ", tcap_context->session_id); |
2889 | | #endif |
2890 | 24 | return tcap_context; |
2891 | 24 | } |
2892 | | |
2893 | | /* |
2894 | | * Initialize the Message Info used by the main dissector |
2895 | | * Data are linked to a TCAP transaction |
2896 | | */ |
2897 | | struct tcapsrt_info_t * |
2898 | | tcapsrt_razinfo(void) |
2899 | 27 | { |
2900 | 27 | struct tcapsrt_info_t *p_tcapsrt_info ; |
2901 | | |
2902 | | /* Global buffer for packet extraction */ |
2903 | 27 | tcapsrt_global_current++; |
2904 | 27 | if(tcapsrt_global_current==MAX_TCAP_INSTANCE){ |
2905 | 2 | tcapsrt_global_current=0; |
2906 | 2 | } |
2907 | | |
2908 | 27 | p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current]; |
2909 | 27 | memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t)); |
2910 | | |
2911 | 27 | return p_tcapsrt_info; |
2912 | 27 | } |
2913 | | |
2914 | | void |
2915 | | tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context, |
2916 | | packet_info *pinfo) |
2917 | 0 | { |
2918 | | #ifdef DEBUG_TCAPSRT |
2919 | | dbg(60,"Force close "); |
2920 | | #endif |
2921 | 0 | if (p_tcaphash_context) { |
2922 | 0 | p_tcaphash_context->responded=true; |
2923 | 0 | p_tcaphash_context->last_frame = pinfo->num; |
2924 | 0 | p_tcaphash_context->end_time = pinfo->abs_ts; |
2925 | 0 | p_tcaphash_context->closed=true; |
2926 | | |
2927 | | /* If the endkey is present */ |
2928 | 0 | if (p_tcaphash_context->endcall |
2929 | 0 | && !gtcap_PersistentSRT) { |
2930 | 0 | if (p_tcaphash_context->endcall->next_endcall) { |
2931 | 0 | if (p_tcaphash_context->endcall->previous_endcall ) { |
2932 | | #ifdef DEBUG_TCAPSRT |
2933 | | dbg(20,"deplace Ehash "); |
2934 | | #endif |
2935 | 0 | p_tcaphash_context->endcall->previous_endcall->next_endcall |
2936 | 0 | = p_tcaphash_context->endcall->next_endcall; |
2937 | 0 | p_tcaphash_context->endcall->next_endcall->previous_endcall |
2938 | 0 | = p_tcaphash_context->endcall->previous_endcall; |
2939 | 0 | wmem_map_remove(tcaphash_end, p_tcaphash_context->endcall->endkey); |
2940 | 0 | } else { |
2941 | | /* cannot remove the father */ |
2942 | | #ifdef DEBUG_TCAPSRT |
2943 | | dbg(20,"father Ehash "); |
2944 | | #endif |
2945 | 0 | } /* no previous link, so father */ |
2946 | 0 | } else if (!gtcap_PersistentSRT) { |
2947 | | #ifdef DEBUG_TCAPSRT |
2948 | | dbg(20,"remove Ehash "); |
2949 | | #endif |
2950 | 0 | wmem_map_remove(tcaphash_end, p_tcaphash_context->endcall->endkey); |
2951 | |
|
2952 | 0 | } /* endcall without chained string */ |
2953 | 0 | } /* no endcall */ |
2954 | | |
2955 | | |
2956 | | /* If the contkey is present */ |
2957 | 0 | if (p_tcaphash_context->contcall |
2958 | 0 | && !gtcap_PersistentSRT) { |
2959 | 0 | if (p_tcaphash_context->contcall->next_contcall) { |
2960 | 0 | if (p_tcaphash_context->contcall->previous_contcall ) { |
2961 | | #ifdef DEBUG_TCAPSRT |
2962 | | dbg(20,"deplace Chash "); |
2963 | | #endif |
2964 | 0 | p_tcaphash_context->contcall->previous_contcall->next_contcall |
2965 | 0 | = p_tcaphash_context->contcall->next_contcall; |
2966 | 0 | p_tcaphash_context->contcall->next_contcall->previous_contcall |
2967 | 0 | = p_tcaphash_context->contcall->previous_contcall; |
2968 | 0 | wmem_map_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey); |
2969 | 0 | } else { |
2970 | | /* cannot remove the father */ |
2971 | | #ifdef DEBUG_TCAPSRT |
2972 | | dbg(20,"father Chash "); |
2973 | | #endif |
2974 | 0 | } /* no previous link, so father */ |
2975 | 0 | } else if (!gtcap_PersistentSRT) { |
2976 | | #ifdef DEBUG_TCAPSRT |
2977 | | dbg(20,"remove Chash "); |
2978 | | #endif |
2979 | 0 | wmem_map_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey); |
2980 | 0 | } /* contcall without chained string */ |
2981 | 0 | } /* no contcall */ |
2982 | | |
2983 | | |
2984 | | /* If the beginkey is present */ |
2985 | 0 | if (p_tcaphash_context->begincall |
2986 | 0 | && !gtcap_PersistentSRT) { |
2987 | 0 | if (p_tcaphash_context->begincall->next_begincall) { |
2988 | 0 | if (p_tcaphash_context->begincall->previous_begincall ) { |
2989 | | #ifdef DEBUG_TCAPSRT |
2990 | | dbg(20,"deplace Bhash "); |
2991 | | #endif |
2992 | 0 | p_tcaphash_context->begincall->previous_begincall->next_begincall |
2993 | 0 | = p_tcaphash_context->begincall->next_begincall; |
2994 | 0 | p_tcaphash_context->begincall->next_begincall->previous_begincall |
2995 | 0 | = p_tcaphash_context->begincall->previous_begincall; |
2996 | 0 | wmem_map_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey); |
2997 | 0 | } else { |
2998 | | /* cannot remove the father */ |
2999 | | #ifdef DEBUG_TCAPSRT |
3000 | | dbg(20,"father Bhash "); |
3001 | | #endif |
3002 | 0 | } |
3003 | 0 | } else if (!gtcap_PersistentSRT) { |
3004 | | #ifdef DEBUG_TCAPSRT |
3005 | | dbg(20,"remove Bhash "); |
3006 | | #endif |
3007 | 0 | wmem_map_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey); |
3008 | 0 | } /* begincall without chained string */ |
3009 | 0 | } /* no begincall */ |
3010 | | |
3011 | | /* If the ansikey is present */ |
3012 | 0 | if (p_tcaphash_context->ansicall |
3013 | 0 | && !gtcap_PersistentSRT) { |
3014 | 0 | if (p_tcaphash_context->ansicall->next_ansicall) { |
3015 | 0 | if (p_tcaphash_context->ansicall->previous_ansicall ) { |
3016 | | #ifdef DEBUG_TCAPSRT |
3017 | | dbg(20,"deplace Ahash "); |
3018 | | #endif |
3019 | 0 | p_tcaphash_context->ansicall->previous_ansicall->next_ansicall |
3020 | 0 | = p_tcaphash_context->ansicall->next_ansicall; |
3021 | 0 | p_tcaphash_context->ansicall->next_ansicall->previous_ansicall |
3022 | 0 | = p_tcaphash_context->ansicall->previous_ansicall; |
3023 | 0 | wmem_map_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey); |
3024 | 0 | } else { |
3025 | | /* cannot remove the father */ |
3026 | | #ifdef DEBUG_TCAPSRT |
3027 | | dbg(20,"father Ahash "); |
3028 | | #endif |
3029 | 0 | } |
3030 | 0 | } else if (!gtcap_PersistentSRT) { |
3031 | | #ifdef DEBUG_TCAPSRT |
3032 | | dbg(20,"remove Ahash "); |
3033 | | #endif |
3034 | 0 | wmem_map_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey); |
3035 | 0 | } /* ansicall without chained string */ |
3036 | 0 | } /* no ansicall */ |
3037 | |
|
3038 | 0 | if (!gtcap_PersistentSRT) { |
3039 | | #ifdef DEBUG_TCAPSRT |
3040 | | dbg(20,"remove context "); |
3041 | | #endif |
3042 | 0 | wmem_map_remove(tcaphash_context, p_tcaphash_context->key); |
3043 | 0 | } |
3044 | 0 | } else { /* no context */ |
3045 | | #ifdef DEBUG_TCAPSRT |
3046 | | dbg(20,"No context to remove "); |
3047 | | #endif |
3048 | 0 | } |
3049 | 0 | } |
3050 | | |
3051 | | const value_string tcap_component_type_str[] = { |
3052 | | { TCAP_COMP_INVOKE, "Invoke" }, |
3053 | | { TCAP_COMP_RRL, "Return Result(L)" }, |
3054 | | { TCAP_COMP_RE, "Return Error" }, |
3055 | | { TCAP_COMP_REJECT, "Reject" }, |
3056 | | { TCAP_COMP_RRN, "Return Result(NL)" }, |
3057 | | { 0, NULL } |
3058 | | }; |
3059 | | |
3060 | | static int |
3061 | | dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_) |
3062 | 29 | { |
3063 | 29 | proto_item *item=NULL; |
3064 | 29 | proto_tree *tree=NULL; |
3065 | | |
3066 | 29 | struct tcaphash_context_t * p_tcap_context; |
3067 | 29 | dissector_handle_t subdissector_handle; |
3068 | 29 | asn1_ctx_t asn1_ctx; |
3069 | 29 | int8_t ber_class; |
3070 | 29 | bool pc; |
3071 | 29 | int tag; |
3072 | 29 | struct tcap_private_t *p_tcap_private; |
3073 | | |
3074 | | /* Check if ANSI TCAP and call the ANSI TCAP dissector if that's the case |
3075 | | * PackageType ::= CHOICE { unidirectional [PRIVATE 1] IMPLICIT UniTransactionPDU, |
3076 | | * queryWithPerm [PRIVATE 2] IMPLICIT TransactionPDU, |
3077 | | * queryWithoutPerm [PRIVATE 3] IMPLICIT TransactionPDU, |
3078 | | * response [PRIVATE 4] IMPLICIT TransactionPDU, |
3079 | | * conversationWithPerm [PRIVATE 5] IMPLICIT TransactionPDU, |
3080 | | * conversationWithoutPerm [PRIVATE 6] IMPLICIT TransactionPDU, |
3081 | | * abort [PRIVATE 22] IMPLICIT Abort |
3082 | | * } |
3083 | | * |
3084 | | * |
3085 | | */ |
3086 | 29 | get_ber_identifier(tvb, 0, &ber_class, &pc, &tag); |
3087 | | |
3088 | 29 | if(ber_class == BER_CLASS_PRI){ |
3089 | 2 | switch (tag){ |
3090 | | |
3091 | 0 | case 1: |
3092 | 0 | case 2: |
3093 | 0 | case 3: |
3094 | 0 | case 4: |
3095 | 0 | case 5: |
3096 | 0 | case 6: |
3097 | 0 | case 22: |
3098 | 0 | return call_dissector(ansi_tcap_handle, tvb, pinfo, parent_tree); |
3099 | | |
3100 | 2 | default: |
3101 | 2 | return tvb_captured_length(tvb); |
3102 | 2 | } |
3103 | 2 | } |
3104 | | |
3105 | | /* ITU TCAP */ |
3106 | 27 | asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo); |
3107 | | |
3108 | 27 | tcap_top_tree = parent_tree; |
3109 | 27 | tcap_stat_tree = NULL; |
3110 | | |
3111 | 27 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCAP"); |
3112 | | |
3113 | | /* create display subtree for the protocol */ |
3114 | 27 | if(parent_tree){ |
3115 | 27 | item = proto_tree_add_item(parent_tree, proto_tcap, tvb, 0, -1, ENC_NA); |
3116 | 27 | tree = proto_item_add_subtree(item, ett_tcap); |
3117 | 27 | tcap_stat_tree=tree; |
3118 | 27 | } |
3119 | 27 | cur_oid = NULL; |
3120 | 27 | tcapext_oid = NULL; |
3121 | | |
3122 | 27 | p_tcap_private = wmem_new0(pinfo->pool, struct tcap_private_t); |
3123 | 27 | asn1_ctx.value_ptr = p_tcap_private; |
3124 | 27 | gp_tcapsrt_info=tcapsrt_razinfo(); |
3125 | 27 | tcap_subdissector_used=false; |
3126 | 27 | gp_tcap_context=NULL; |
3127 | 27 | dissect_tcap_TCMessage(false, tvb, 0, &asn1_ctx, tree, -1); |
3128 | | |
3129 | 27 | if (!tcap_subdissector_used ) { |
3130 | 24 | p_tcap_context=tcapsrt_call_matching(tvb, pinfo, tcap_stat_tree, gp_tcapsrt_info); |
3131 | 24 | p_tcap_private->context=p_tcap_context; |
3132 | | |
3133 | | /* If the current message is TCAP only, |
3134 | | * save the Application Context Name for the next messages |
3135 | | */ |
3136 | 24 | if ( p_tcap_context && cur_oid && !p_tcap_context->oid_present ) { |
3137 | | /* Save the application context and the sub dissector */ |
3138 | 0 | (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid)); |
3139 | 0 | p_tcap_context->oid_present=true; |
3140 | 0 | if ( (subdissector_handle = dissector_get_string_handle(ber_oid_dissector_table, cur_oid)) ) { |
3141 | 0 | p_tcap_context->subdissector_handle=subdissector_handle; |
3142 | 0 | p_tcap_context->subdissector_present=true; |
3143 | 0 | } |
3144 | 0 | } |
3145 | 24 | if (p_tcap_context && p_tcap_context->callback) { |
3146 | | /* Callback function for the upper layer */ |
3147 | 0 | (p_tcap_context->callback)(tvb, pinfo, tcap_stat_tree, p_tcap_context); |
3148 | 0 | } |
3149 | 24 | } |
3150 | 27 | return tvb_captured_length(tvb); |
3151 | 29 | } |
3152 | | |
3153 | | void |
3154 | | proto_reg_handoff_tcap(void) |
3155 | 14 | { |
3156 | | |
3157 | 14 | data_handle = find_dissector("data"); |
3158 | 14 | ansi_tcap_handle = find_dissector_add_dependency("ansi_tcap", proto_tcap); |
3159 | 14 | ber_oid_dissector_table = find_dissector_table("ber.oid"); |
3160 | | |
3161 | 14 | ss7pc_address_type = address_type_get_by_name("AT_SS7PC"); |
3162 | | |
3163 | 14 | register_ber_oid_dissector("0.0.17.773.1.1.1", dissect_DialoguePDU_PDU, proto_tcap, "id-as-dialogue"); |
3164 | 14 | register_ber_oid_dissector("0.0.17.773.1.2.1", dissect_UniDialoguePDU_PDU, proto_tcap, "id-as-uniDialogue"); |
3165 | | |
3166 | 14 | } |
3167 | | |
3168 | | static void init_tcap(void); |
3169 | | static void cleanup_tcap(void); |
3170 | | |
3171 | | void |
3172 | | proto_register_tcap(void) |
3173 | 14 | { |
3174 | | |
3175 | | /* Setup list of header fields See Section 1.6.1 for details*/ |
3176 | 14 | static hf_register_info hf[] = { |
3177 | 14 | { &hf_tcap_tag, |
3178 | 14 | { "Tag", |
3179 | 14 | "tcap.msgtype", |
3180 | 14 | FT_UINT8, BASE_HEX, NULL, 0, |
3181 | 14 | NULL, HFILL } |
3182 | 14 | }, |
3183 | 14 | { &hf_tcap_length, |
3184 | 14 | { "Length", |
3185 | 14 | "tcap.len", |
3186 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
3187 | 14 | NULL, HFILL } |
3188 | 14 | }, |
3189 | 14 | { &hf_tcap_data, |
3190 | 14 | { "Data", |
3191 | 14 | "tcap.data", |
3192 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3193 | 14 | NULL, HFILL } |
3194 | 14 | }, |
3195 | 14 | { &hf_tcap_tid, |
3196 | 14 | { "Transaction Id", |
3197 | 14 | "tcap.tid", |
3198 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3199 | 14 | NULL, HFILL } |
3200 | 14 | }, |
3201 | 14 | { &hf_tcap_constructor_eoc, |
3202 | 14 | { "CONSTRUCTOR EOC", |
3203 | 14 | "tcap.constructor_eoc", |
3204 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
3205 | 14 | NULL, HFILL } |
3206 | 14 | }, |
3207 | | /* Tcap Service Response Time */ |
3208 | 14 | { &hf_tcapsrt_SessionId, |
3209 | 14 | { "Session Id", |
3210 | 14 | "tcap.srt.session_id", |
3211 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
3212 | 14 | NULL, HFILL } |
3213 | 14 | }, |
3214 | 14 | { &hf_tcapsrt_BeginSession, |
3215 | 14 | { "Begin Session", |
3216 | 14 | "tcap.srt.begin", |
3217 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
3218 | 14 | "SRT Begin of Session", HFILL } |
3219 | 14 | }, |
3220 | 14 | { &hf_tcapsrt_EndSession, |
3221 | 14 | { "End Session", |
3222 | 14 | "tcap.srt.end", |
3223 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
3224 | 14 | "SRT End of Session", HFILL } |
3225 | 14 | }, |
3226 | 14 | { &hf_tcapsrt_SessionTime, |
3227 | 14 | { "Session duration", |
3228 | 14 | "tcap.srt.sessiontime", |
3229 | 14 | FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, |
3230 | 14 | "Duration of the TCAP session", HFILL } |
3231 | 14 | }, |
3232 | 14 | { &hf_tcapsrt_Duplicate, |
3233 | 14 | { "Session Duplicate", |
3234 | 14 | "tcap.srt.duplicate", |
3235 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
3236 | 14 | "SRT Duplicated with Session", HFILL } |
3237 | 14 | }, |
3238 | 14 | { &hf_tcap_UniDialoguePDU_PDU, |
3239 | 14 | { "UniDialoguePDU", "tcap.UniDialoguePDU", |
3240 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_UniDialoguePDU_vals), 0, |
3241 | 14 | NULL, HFILL }}, |
3242 | 14 | { &hf_tcap_DialoguePDU_PDU, |
3243 | 14 | { "DialoguePDU", "tcap.DialoguePDU", |
3244 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_DialoguePDU_vals), 0, |
3245 | 14 | NULL, HFILL }}, |
3246 | 14 | { &hf_tcap_oid, |
3247 | 14 | { "oid", "tcap.oid", |
3248 | 14 | FT_OID, BASE_NONE, NULL, 0, |
3249 | 14 | "OBJECT_IDENTIFIER", HFILL }}, |
3250 | 14 | { &hf_tcap_dialog, |
3251 | 14 | { "dialog", "tcap.dialog", |
3252 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3253 | 14 | "Dialog1", HFILL }}, |
3254 | 14 | { &hf_tcap_unidirectional, |
3255 | 14 | { "unidirectional", "tcap.unidirectional_element", |
3256 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3257 | 14 | NULL, HFILL }}, |
3258 | 14 | { &hf_tcap_begin, |
3259 | 14 | { "begin", "tcap.begin_element", |
3260 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3261 | 14 | NULL, HFILL }}, |
3262 | 14 | { &hf_tcap_end, |
3263 | 14 | { "end", "tcap.end_element", |
3264 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3265 | 14 | NULL, HFILL }}, |
3266 | 14 | { &hf_tcap_continue, |
3267 | 14 | { "continue", "tcap.continue_element", |
3268 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3269 | 14 | NULL, HFILL }}, |
3270 | 14 | { &hf_tcap_abort, |
3271 | 14 | { "abort", "tcap.abort_element", |
3272 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3273 | 14 | NULL, HFILL }}, |
3274 | 14 | { &hf_tcap_dialoguePortion, |
3275 | 14 | { "dialoguePortion", "tcap.dialoguePortion", |
3276 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3277 | 14 | NULL, HFILL }}, |
3278 | 14 | { &hf_tcap_components, |
3279 | 14 | { "components", "tcap.components", |
3280 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
3281 | 14 | "ComponentPortion", HFILL }}, |
3282 | 14 | { &hf_tcap_otid, |
3283 | 14 | { "otid", "tcap.otid", |
3284 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3285 | 14 | "OrigTransactionID", HFILL }}, |
3286 | 14 | { &hf_tcap_dtid, |
3287 | 14 | { "dtid", "tcap.dtid", |
3288 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3289 | 14 | "DestTransactionID", HFILL }}, |
3290 | 14 | { &hf_tcap_reason, |
3291 | 14 | { "reason", "tcap.reason", |
3292 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_Reason_vals), 0, |
3293 | 14 | NULL, HFILL }}, |
3294 | 14 | { &hf_tcap_p_abortCause, |
3295 | 14 | { "p-abortCause", "tcap.p_abortCause", |
3296 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_P_AbortCause_U_vals), 0, |
3297 | 14 | NULL, HFILL }}, |
3298 | 14 | { &hf_tcap_u_abortCause, |
3299 | 14 | { "u-abortCause", "tcap.u_abortCause", |
3300 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3301 | 14 | "DialoguePortion", HFILL }}, |
3302 | 14 | { &hf_tcap__untag_item, |
3303 | 14 | { "Component", "tcap.Component", |
3304 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_Component_vals), 0, |
3305 | 14 | NULL, HFILL }}, |
3306 | 14 | { &hf_tcap_invoke, |
3307 | 14 | { "invoke", "tcap.invoke_element", |
3308 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3309 | 14 | NULL, HFILL }}, |
3310 | 14 | { &hf_tcap_returnResultLast, |
3311 | 14 | { "returnResultLast", "tcap.returnResultLast_element", |
3312 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3313 | 14 | "ReturnResult", HFILL }}, |
3314 | 14 | { &hf_tcap_returnError, |
3315 | 14 | { "returnError", "tcap.returnError_element", |
3316 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3317 | 14 | NULL, HFILL }}, |
3318 | 14 | { &hf_tcap_reject, |
3319 | 14 | { "reject", "tcap.reject_element", |
3320 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3321 | 14 | NULL, HFILL }}, |
3322 | 14 | { &hf_tcap_returnResultNotLast, |
3323 | 14 | { "returnResultNotLast", "tcap.returnResultNotLast_element", |
3324 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3325 | 14 | "ReturnResult", HFILL }}, |
3326 | 14 | { &hf_tcap_invokeID, |
3327 | 14 | { "invokeID", "tcap.invokeID", |
3328 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3329 | 14 | "InvokeIdType", HFILL }}, |
3330 | 14 | { &hf_tcap_linkedID, |
3331 | 14 | { "linkedID", "tcap.linkedID", |
3332 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3333 | 14 | "InvokeIdType", HFILL }}, |
3334 | 14 | { &hf_tcap_opCode, |
3335 | 14 | { "opCode", "tcap.opCode", |
3336 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_OPERATION_vals), 0, |
3337 | 14 | "OPERATION", HFILL }}, |
3338 | 14 | { &hf_tcap_parameter, |
3339 | 14 | { "parameter", "tcap.parameter_element", |
3340 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3341 | 14 | NULL, HFILL }}, |
3342 | 14 | { &hf_tcap_resultretres, |
3343 | 14 | { "resultretres", "tcap.resultretres_element", |
3344 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3345 | 14 | NULL, HFILL }}, |
3346 | 14 | { &hf_tcap_errorCode, |
3347 | 14 | { "errorCode", "tcap.errorCode", |
3348 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_ErrorCode_vals), 0, |
3349 | 14 | NULL, HFILL }}, |
3350 | 14 | { &hf_tcap_invokeIDRej, |
3351 | 14 | { "invokeIDRej", "tcap.invokeIDRej", |
3352 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_T_invokeIDRej_vals), 0, |
3353 | 14 | NULL, HFILL }}, |
3354 | 14 | { &hf_tcap_derivable, |
3355 | 14 | { "derivable", "tcap.derivable", |
3356 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3357 | 14 | "InvokeIdType", HFILL }}, |
3358 | 14 | { &hf_tcap_not_derivable, |
3359 | 14 | { "not-derivable", "tcap.not_derivable_element", |
3360 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3361 | 14 | NULL, HFILL }}, |
3362 | 14 | { &hf_tcap_problem, |
3363 | 14 | { "problem", "tcap.problem", |
3364 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_T_problem_vals), 0, |
3365 | 14 | NULL, HFILL }}, |
3366 | 14 | { &hf_tcap_generalProblem, |
3367 | 14 | { "generalProblem", "tcap.generalProblem", |
3368 | 14 | FT_INT32, BASE_DEC, VALS(tcap_GeneralProblem_vals), 0, |
3369 | 14 | NULL, HFILL }}, |
3370 | 14 | { &hf_tcap_invokeProblem, |
3371 | 14 | { "invokeProblem", "tcap.invokeProblem", |
3372 | 14 | FT_INT32, BASE_DEC, VALS(tcap_InvokeProblem_vals), 0, |
3373 | 14 | NULL, HFILL }}, |
3374 | 14 | { &hf_tcap_returnResultProblem, |
3375 | 14 | { "returnResultProblem", "tcap.returnResultProblem", |
3376 | 14 | FT_INT32, BASE_DEC, VALS(tcap_ReturnResultProblem_vals), 0, |
3377 | 14 | NULL, HFILL }}, |
3378 | 14 | { &hf_tcap_returnErrorProblem, |
3379 | 14 | { "returnErrorProblem", "tcap.returnErrorProblem", |
3380 | 14 | FT_INT32, BASE_DEC, VALS(tcap_ReturnErrorProblem_vals), 0, |
3381 | 14 | NULL, HFILL }}, |
3382 | 14 | { &hf_tcap_localValue, |
3383 | 14 | { "localValue", "tcap.localValue", |
3384 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3385 | 14 | "INTEGER", HFILL }}, |
3386 | 14 | { &hf_tcap_globalValue, |
3387 | 14 | { "globalValue", "tcap.globalValue", |
3388 | 14 | FT_OID, BASE_NONE, NULL, 0, |
3389 | 14 | "OBJECT_IDENTIFIER", HFILL }}, |
3390 | 14 | { &hf_tcap_nationaler, |
3391 | 14 | { "nationaler", "tcap.nationaler", |
3392 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3393 | 14 | "INTEGER_M32768_32767", HFILL }}, |
3394 | 14 | { &hf_tcap_privateer, |
3395 | 14 | { "privateer", "tcap.privateer", |
3396 | 14 | FT_INT32, BASE_DEC, NULL, 0, |
3397 | 14 | "INTEGER", HFILL }}, |
3398 | 14 | { &hf_tcap_unidialoguePDU, |
3399 | 14 | { "unidialoguePDU", "tcap.unidialoguePDU_element", |
3400 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3401 | 14 | "AUDT_apdu", HFILL }}, |
3402 | 14 | { &hf_tcap_audt_protocol_version, |
3403 | 14 | { "protocol-version", "tcap.audt_protocol_version", |
3404 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3405 | 14 | "AUDT_protocol_version", HFILL }}, |
3406 | 14 | { &hf_tcap_audt_application_context_name, |
3407 | 14 | { "application-context-name", "tcap.audt_application_context_name", |
3408 | 14 | FT_OID, BASE_NONE, NULL, 0, |
3409 | 14 | "AUDT_application_context_name", HFILL }}, |
3410 | 14 | { &hf_tcap_audt_user_information, |
3411 | 14 | { "user-information", "tcap.audt_user_information", |
3412 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
3413 | 14 | "AUDT_user_information", HFILL }}, |
3414 | 14 | { &hf_tcap_audt_user_information_item, |
3415 | 14 | { "user-information item", "tcap.audt_user_information_item_element", |
3416 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3417 | 14 | "EXTERNAL", HFILL }}, |
3418 | 14 | { &hf_tcap_dialogueRequest, |
3419 | 14 | { "dialogueRequest", "tcap.dialogueRequest_element", |
3420 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3421 | 14 | "AARQ_apdu", HFILL }}, |
3422 | 14 | { &hf_tcap_dialogueResponse, |
3423 | 14 | { "dialogueResponse", "tcap.dialogueResponse_element", |
3424 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3425 | 14 | "AARE_apdu", HFILL }}, |
3426 | 14 | { &hf_tcap_dialogueAbort, |
3427 | 14 | { "dialogueAbort", "tcap.dialogueAbort_element", |
3428 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3429 | 14 | "ABRT_apdu", HFILL }}, |
3430 | 14 | { &hf_tcap_aarq_protocol_version, |
3431 | 14 | { "protocol-version", "tcap.aarq_protocol_version", |
3432 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3433 | 14 | "AARQ_protocol_version", HFILL }}, |
3434 | 14 | { &hf_tcap_aarq_application_context_name, |
3435 | 14 | { "application-context-name", "tcap.aarq_application_context_name", |
3436 | 14 | FT_OID, BASE_NONE, NULL, 0, |
3437 | 14 | "AARQ_application_context_name", HFILL }}, |
3438 | 14 | { &hf_tcap_aarq_user_information, |
3439 | 14 | { "user-information", "tcap.aarq_user_information", |
3440 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
3441 | 14 | "AARQ_user_information", HFILL }}, |
3442 | 14 | { &hf_tcap_aarq_user_information_item, |
3443 | 14 | { "user-information item", "tcap.aarq_user_information_item_element", |
3444 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3445 | 14 | "EXTERNAL", HFILL }}, |
3446 | 14 | { &hf_tcap_aare_protocol_version, |
3447 | 14 | { "protocol-version", "tcap.aare_protocol_version", |
3448 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
3449 | 14 | "AARE_protocol_version", HFILL }}, |
3450 | 14 | { &hf_tcap_aare_application_context_name, |
3451 | 14 | { "application-context-name", "tcap.aare_application_context_name", |
3452 | 14 | FT_OID, BASE_NONE, NULL, 0, |
3453 | 14 | "AARE_application_context_name", HFILL }}, |
3454 | 14 | { &hf_tcap_result, |
3455 | 14 | { "result", "tcap.result", |
3456 | 14 | FT_INT32, BASE_DEC, VALS(tcap_Associate_result_vals), 0, |
3457 | 14 | "Associate_result", HFILL }}, |
3458 | 14 | { &hf_tcap_result_source_diagnostic, |
3459 | 14 | { "result-source-diagnostic", "tcap.result_source_diagnostic", |
3460 | 14 | FT_UINT32, BASE_DEC, VALS(tcap_Associate_source_diagnostic_vals), 0, |
3461 | 14 | "Associate_source_diagnostic", HFILL }}, |
3462 | 14 | { &hf_tcap_aare_user_information, |
3463 | 14 | { "user-information", "tcap.aare_user_information", |
3464 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
3465 | 14 | "AARE_user_information", HFILL }}, |
3466 | 14 | { &hf_tcap_aare_user_information_item, |
3467 | 14 | { "user-information item", "tcap.aare_user_information_item_element", |
3468 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3469 | 14 | "EXTERNAL", HFILL }}, |
3470 | 14 | { &hf_tcap_abort_source, |
3471 | 14 | { "abort-source", "tcap.abort_source", |
3472 | 14 | FT_INT32, BASE_DEC, VALS(tcap_ABRT_source_vals), 0, |
3473 | 14 | "ABRT_source", HFILL }}, |
3474 | 14 | { &hf_tcap_abrt_user_information, |
3475 | 14 | { "user-information", "tcap.abrt_user_information", |
3476 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
3477 | 14 | "ABRT_user_information", HFILL }}, |
3478 | 14 | { &hf_tcap_abrt_user_information_item, |
3479 | 14 | { "user-information item", "tcap.abrt_user_information_item_element", |
3480 | 14 | FT_NONE, BASE_NONE, NULL, 0, |
3481 | 14 | "EXTERNAL", HFILL }}, |
3482 | 14 | { &hf_tcap_dialogue_service_user, |
3483 | 14 | { "dialogue-service-user", "tcap.dialogue_service_user", |
3484 | 14 | FT_INT32, BASE_DEC, VALS(tcap_T_dialogue_service_user_vals), 0, |
3485 | 14 | NULL, HFILL }}, |
3486 | 14 | { &hf_tcap_dialogue_service_provider, |
3487 | 14 | { "dialogue-service-provider", "tcap.dialogue_service_provider", |
3488 | 14 | FT_INT32, BASE_DEC, VALS(tcap_T_dialogue_service_provider_vals), 0, |
3489 | 14 | NULL, HFILL }}, |
3490 | 14 | { &hf_tcap_AUDT_protocol_version_version1, |
3491 | 14 | { "version1", "tcap.AUDT.protocol.version.version1", |
3492 | 14 | FT_BOOLEAN, 8, NULL, 0x80, |
3493 | 14 | NULL, HFILL }}, |
3494 | 14 | { &hf_tcap_AARQ_protocol_version_version1, |
3495 | 14 | { "version1", "tcap.AARQ.protocol.version.version1", |
3496 | 14 | FT_BOOLEAN, 8, NULL, 0x80, |
3497 | 14 | NULL, HFILL }}, |
3498 | 14 | { &hf_tcap_AARE_protocol_version_version1, |
3499 | 14 | { "version1", "tcap.AARE.protocol.version.version1", |
3500 | 14 | FT_BOOLEAN, 8, NULL, 0x80, |
3501 | 14 | NULL, HFILL }}, |
3502 | 14 | }; |
3503 | | |
3504 | | /* Setup protocol subtree array */ |
3505 | 14 | static int *ett[] = { |
3506 | 14 | &ett_tcap, |
3507 | 14 | &ett_param, |
3508 | 14 | &ett_otid, |
3509 | 14 | &ett_dtid, |
3510 | 14 | &ett_tcap_stat, |
3511 | 14 | &ett_tcap_ExternalPDU_U, |
3512 | 14 | &ett_tcap_TCMessage, |
3513 | 14 | &ett_tcap_Unidirectional, |
3514 | 14 | &ett_tcap_Begin, |
3515 | 14 | &ett_tcap_End, |
3516 | 14 | &ett_tcap_Continue, |
3517 | 14 | &ett_tcap_Abort, |
3518 | 14 | &ett_tcap_Reason, |
3519 | 14 | &ett_tcap_SEQUENCE_SIZE_1_MAX_OF_Component, |
3520 | 14 | &ett_tcap_Component, |
3521 | 14 | &ett_tcap_Invoke, |
3522 | 14 | &ett_tcap_ReturnResult, |
3523 | 14 | &ett_tcap_T_resultretres, |
3524 | 14 | &ett_tcap_ReturnError, |
3525 | 14 | &ett_tcap_Reject, |
3526 | 14 | &ett_tcap_T_invokeIDRej, |
3527 | 14 | &ett_tcap_T_problem, |
3528 | 14 | &ett_tcap_OPERATION, |
3529 | 14 | &ett_tcap_ErrorCode, |
3530 | 14 | &ett_tcap_UniDialoguePDU, |
3531 | 14 | &ett_tcap_AUDT_apdu_U, |
3532 | 14 | &ett_tcap_AUDT_protocol_version, |
3533 | 14 | &ett_tcap_AUDT_user_information, |
3534 | 14 | &ett_tcap_DialoguePDU, |
3535 | 14 | &ett_tcap_AARQ_apdu_U, |
3536 | 14 | &ett_tcap_AARQ_protocol_version, |
3537 | 14 | &ett_tcap_AARQ_user_information, |
3538 | 14 | &ett_tcap_AARE_apdu_U, |
3539 | 14 | &ett_tcap_AARE_protocol_version, |
3540 | 14 | &ett_tcap_AARE_user_information, |
3541 | 14 | &ett_tcap_ABRT_apdu_U, |
3542 | 14 | &ett_tcap_ABRT_user_information, |
3543 | 14 | &ett_tcap_Associate_source_diagnostic, |
3544 | 14 | }; |
3545 | | |
3546 | | /*static enum_val_t tcap_options[] = { |
3547 | | { "itu", "ITU", ITU_TCAP_STANDARD }, |
3548 | | { "ansi", "ANSI", ANSI_TCAP_STANDARD }, |
3549 | | { NULL, NULL, 0 } |
3550 | | };*/ |
3551 | | |
3552 | 14 | module_t *tcap_module; |
3553 | | |
3554 | | /* Register the protocol name and description */ |
3555 | 14 | proto_tcap = proto_register_protocol(PNAME, PSNAME, PFNAME); |
3556 | | |
3557 | | /* Required function calls to register the header fields and subtrees used */ |
3558 | 14 | proto_register_field_array(proto_tcap, hf, array_length(hf)); |
3559 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
3560 | | |
3561 | 14 | ansi_sub_dissectors = register_dissector_table("ansi_tcap.ssn", "ANSI SSN", proto_tcap, FT_UINT8, BASE_DEC); |
3562 | 14 | itu_sub_dissectors = register_dissector_table("itu_tcap.ssn", "ITU SSN", proto_tcap, FT_UINT8, BASE_DEC); |
3563 | | |
3564 | 14 | tcap_module = prefs_register_protocol(proto_tcap, NULL); |
3565 | | |
3566 | | #if 0 |
3567 | | prefs_register_enum_preference(tcap_module, "standard", "ITU TCAP standard", |
3568 | | "The SS7 standard used in ITU TCAP packets", |
3569 | | &tcap_standard, tcap_options, false); |
3570 | | #else |
3571 | 14 | prefs_register_obsolete_preference(tcap_module, "standard"); |
3572 | 14 | #endif |
3573 | | |
3574 | | #if 0 |
3575 | | prefs_register_bool_preference(tcap_module, "lock_info_col", "Lock Info column", |
3576 | | "Always show TCAP in Info column", |
3577 | | &lock_info_col); |
3578 | | #else |
3579 | 14 | prefs_register_obsolete_preference(tcap_module, "lock_info_col"); |
3580 | 14 | #endif |
3581 | | |
3582 | | /* Set default SSNs */ |
3583 | 14 | range_convert_str(wmem_epan_scope(), &global_ssn_range, "", MAX_SSN); |
3584 | | |
3585 | 14 | prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs", |
3586 | 14 | "SCCP (and SUA) SSNs to decode as TCAP", |
3587 | 14 | &global_ssn_range, MAX_SSN); |
3588 | | |
3589 | 14 | prefs_register_obsolete_preference(tcap_module, "srt"); |
3590 | | |
3591 | 14 | prefs_register_bool_preference(tcap_module, "persistentsrt", |
3592 | 14 | "Persistent stats for SRT", |
3593 | 14 | "Statistics for Response Time", |
3594 | 14 | >cap_PersistentSRT); |
3595 | | |
3596 | 14 | prefs_register_uint_preference(tcap_module, "repetitiontimeout", |
3597 | 14 | "Repetition timeout", |
3598 | 14 | "Maximal delay for message repetition", |
3599 | 14 | 10, >cap_RepetitionTimeout); |
3600 | | |
3601 | 14 | prefs_register_uint_preference(tcap_module, "losttimeout", |
3602 | 14 | "Lost timeout", |
3603 | 14 | "Maximal delay for message lost", |
3604 | 14 | 10, >cap_LostTimeout); |
3605 | | |
3606 | | /* 'globally' register dissector */ |
3607 | 14 | tcap_handle = register_dissector("tcap", dissect_tcap, proto_tcap); |
3608 | | |
3609 | | /* hash-tables for SRT */ |
3610 | 14 | tcaphash_context = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_context_calchash, tcaphash_context_equal); |
3611 | 14 | tcaphash_begin = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_begin_calchash, tcaphash_begin_equal); |
3612 | 14 | tcaphash_cont = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_cont_calchash, tcaphash_cont_equal); |
3613 | 14 | tcaphash_end = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_end_calchash, tcaphash_end_equal); |
3614 | 14 | tcaphash_ansi = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), tcaphash_ansi_calchash, tcaphash_ansi_equal); |
3615 | | |
3616 | 14 | register_init_routine(&init_tcap); |
3617 | 14 | register_cleanup_routine(&cleanup_tcap); |
3618 | 14 | } |
3619 | | |
3620 | | |
3621 | | static void range_delete_callback(uint32_t ssn, void *ptr _U_) |
3622 | 0 | { |
3623 | 0 | if ( ssn && !get_ansi_tcap_subdissector(ssn) && !get_itu_tcap_subdissector(ssn) ) { |
3624 | 0 | dissector_delete_uint("sccp.ssn", ssn, tcap_handle); |
3625 | 0 | } |
3626 | 0 | } |
3627 | | |
3628 | | static void range_add_callback(uint32_t ssn, void *ptr _U_) |
3629 | 0 | { |
3630 | 0 | if (ssn && !get_ansi_tcap_subdissector(ssn) && !get_itu_tcap_subdissector(ssn) ) { |
3631 | 0 | dissector_add_uint("sccp.ssn", ssn, tcap_handle); |
3632 | 0 | } |
3633 | 0 | } |
3634 | | |
3635 | | |
3636 | | static void init_tcap(void) |
3637 | 14 | { |
3638 | 14 | ssn_range = range_copy(wmem_epan_scope(), global_ssn_range); |
3639 | 14 | range_foreach(ssn_range, range_add_callback, NULL); |
3640 | | |
3641 | | /* Reset the session counter */ |
3642 | 14 | tcapsrt_global_SessionId=1; |
3643 | | |
3644 | | /* Display of SRT is enabled |
3645 | | * 1) For wireshark only if Persistent Stat is enabled |
3646 | | * 2) For tshark, if the CLI SRT tap is registered |
3647 | | */ |
3648 | 14 | gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_StatSRT; |
3649 | 14 | } |
3650 | | |
3651 | | static void cleanup_tcap(void) |
3652 | 0 | { |
3653 | 0 | range_foreach(ssn_range, range_delete_callback, NULL); |
3654 | 0 | wmem_free(wmem_epan_scope(), ssn_range); |
3655 | 0 | } |
3656 | | |
3657 | | static int |
3658 | | // NOLINTNEXTLINE(misc-no-recursion) |
3659 | | dissect_tcap_param(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset) |
3660 | 0 | { |
3661 | 0 | int tag_offset, saved_offset, len_offset; |
3662 | 0 | tvbuff_t *next_tvb; |
3663 | 0 | proto_tree *subtree; |
3664 | 0 | int8_t ber_class; |
3665 | 0 | bool pc; |
3666 | 0 | int32_t tag; |
3667 | 0 | uint32_t len; |
3668 | 0 | uint32_t tag_length; |
3669 | 0 | uint32_t len_length; |
3670 | 0 | bool ind_field; |
3671 | |
|
3672 | 0 | while (tvb_reported_length_remaining(tvb, offset) > 0) |
3673 | 0 | { |
3674 | 0 | saved_offset = offset; |
3675 | |
|
3676 | 0 | offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag); |
3677 | 0 | tag_offset = offset; |
3678 | 0 | offset = get_ber_length(tvb, offset, &len, &ind_field); |
3679 | 0 | len_offset = offset; |
3680 | |
|
3681 | 0 | tag_length = tag_offset - saved_offset; |
3682 | 0 | len_length = len_offset - tag_offset; |
3683 | |
|
3684 | 0 | if (pc) |
3685 | 0 | { |
3686 | 0 | subtree = proto_tree_add_subtree(tree, tvb, saved_offset, |
3687 | 0 | len + (len_offset - saved_offset), ett_param, NULL, |
3688 | 0 | "CONSTRUCTOR"); |
3689 | 0 | proto_tree_add_uint_format(subtree, hf_tcap_tag, tvb, |
3690 | 0 | saved_offset, tag_length, tag, |
3691 | 0 | "CONSTRUCTOR Tag"); |
3692 | 0 | proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset, |
3693 | 0 | tag_length, ber_class); |
3694 | |
|
3695 | 0 | proto_tree_add_uint(subtree, hf_tcap_length, tvb, tag_offset, |
3696 | 0 | len_length, len); |
3697 | |
|
3698 | 0 | if (len - (ind_field ? 2 : 0)) /*should always be positive unless we get an empty constructor pointless? */ |
3699 | 0 | { |
3700 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, len - (ind_field ? 2 : 0)); |
3701 | 0 | increment_dissection_depth(actx->pinfo); |
3702 | 0 | dissect_tcap_param(actx, subtree,next_tvb,0); |
3703 | 0 | decrement_dissection_depth(actx->pinfo); |
3704 | 0 | } |
3705 | |
|
3706 | 0 | if (ind_field) |
3707 | 0 | proto_tree_add_item(subtree, hf_tcap_constructor_eoc, tvb, offset+len-2, 2, ENC_BIG_ENDIAN); |
3708 | |
|
3709 | 0 | offset += len; |
3710 | 0 | } |
3711 | 0 | else |
3712 | 0 | { |
3713 | 0 | subtree = proto_tree_add_subtree_format(tree, tvb, saved_offset, |
3714 | 0 | len + (len_offset - saved_offset), ett_param, NULL, |
3715 | 0 | "Parameter (0x%.2x)", tag); |
3716 | |
|
3717 | 0 | proto_tree_add_uint(subtree, hf_tcap_tag, tvb, saved_offset, |
3718 | 0 | tag_length, tag); |
3719 | |
|
3720 | 0 | proto_tree_add_uint(subtree, hf_tcap_length, tvb, |
3721 | 0 | saved_offset+tag_length, len_length, len); |
3722 | |
|
3723 | 0 | if (len) /* check for NULLS */ |
3724 | 0 | { |
3725 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, len); |
3726 | 0 | dissect_ber_octet_string(true, actx, tree, next_tvb, 0, |
3727 | 0 | hf_tcap_data, NULL); |
3728 | 0 | } |
3729 | |
|
3730 | 0 | offset += len; |
3731 | 0 | } |
3732 | 0 | } |
3733 | 0 | return offset; |
3734 | 0 | } |
3735 | | |
3736 | | /* |
3737 | | * Call ITU Subdissector to decode the Tcap Component |
3738 | | */ |
3739 | | static bool |
3740 | | 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_) |
3741 | 0 | { |
3742 | 0 | dissector_handle_t subdissector_handle=NULL; |
3743 | 0 | bool is_subdissector=false; |
3744 | 0 | struct tcaphash_context_t * p_tcap_context=NULL; |
3745 | 0 | struct tcap_private_t *p_tcap_private = (struct tcap_private_t*)actx->value_ptr; |
3746 | | |
3747 | | /* |
3748 | | * ok lets look at the oid and ssn and try and find a dissector, otherwise lets decode it. |
3749 | | */ |
3750 | | |
3751 | | /* |
3752 | | * Handle The TCAP Service Response Time |
3753 | | */ |
3754 | 0 | if (!tcap_subdissector_used) { |
3755 | 0 | p_tcap_context=tcapsrt_call_matching(tvb, actx->pinfo, tcap_stat_tree, gp_tcapsrt_info); |
3756 | 0 | tcap_subdissector_used=false; |
3757 | 0 | gp_tcap_context=p_tcap_context; |
3758 | 0 | p_tcap_private->context=p_tcap_context; |
3759 | 0 | } else { |
3760 | | /* Take the last TCAP context */ |
3761 | 0 | p_tcap_context = gp_tcap_context; |
3762 | 0 | p_tcap_private->context=p_tcap_context; |
3763 | 0 | } |
3764 | 0 | if (p_tcap_context) { |
3765 | 0 | if (cur_oid) { |
3766 | 0 | if (p_tcap_context->oid_present) { |
3767 | | /* We have already an Application Context, check if we have |
3768 | | to fallback to a lower version */ |
3769 | 0 | if (strncmp(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid)) != 0) { |
3770 | | /* ACN, changed, Fallback to lower version |
3771 | | * and update the subdissector (purely formal) |
3772 | | */ |
3773 | 0 | (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid)); |
3774 | 0 | if ((subdissector_handle = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) { |
3775 | 0 | p_tcap_context->subdissector_handle = subdissector_handle; |
3776 | 0 | p_tcap_context->subdissector_present = true; |
3777 | 0 | } |
3778 | 0 | } |
3779 | 0 | } else { |
3780 | | /* We do not have the OID in the TCAP context, so store it */ |
3781 | 0 | (void) g_strlcpy(p_tcap_context->oid, cur_oid, sizeof(p_tcap_context->oid)); |
3782 | 0 | p_tcap_context->oid_present = true; |
3783 | | /* Try to find a subdissector according to OID */ |
3784 | 0 | if ((subdissector_handle |
3785 | 0 | = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) { |
3786 | 0 | p_tcap_context->subdissector_handle = subdissector_handle; |
3787 | 0 | p_tcap_context->subdissector_present = true; |
3788 | 0 | } else { |
3789 | | /* Not found, so try to find a subdissector according to SSN */ |
3790 | 0 | if ((subdissector_handle = get_itu_tcap_subdissector(actx->pinfo->match_uint))) { |
3791 | | /* Found according to SSN */ |
3792 | 0 | p_tcap_context->subdissector_handle = subdissector_handle; |
3793 | 0 | p_tcap_context->subdissector_present = true; |
3794 | 0 | } |
3795 | 0 | } |
3796 | 0 | } /* context OID */ |
3797 | 0 | } else { |
3798 | | /* Copy the OID from the TCAP context to the current oid */ |
3799 | 0 | if (p_tcap_context->oid_present) { |
3800 | 0 | p_tcap_private->oid = (void*)p_tcap_context->oid; |
3801 | 0 | p_tcap_private->acv = true; |
3802 | 0 | } |
3803 | 0 | } /* no OID */ |
3804 | 0 | } /* no TCAP context */ |
3805 | | |
3806 | |
|
3807 | 0 | if (p_tcap_context |
3808 | 0 | && p_tcap_context->subdissector_present) { |
3809 | | /* Take the subdissector from the context */ |
3810 | 0 | subdissector_handle = p_tcap_context->subdissector_handle; |
3811 | 0 | is_subdissector = true; |
3812 | 0 | } |
3813 | | |
3814 | | /* Have SccpUsersTable protocol taking precedence over sccp.ssn table */ |
3815 | 0 | if (!is_subdissector && requested_subdissector_handle) { |
3816 | 0 | is_subdissector = true; |
3817 | 0 | subdissector_handle = requested_subdissector_handle; |
3818 | 0 | } |
3819 | |
|
3820 | 0 | if (!is_subdissector) { |
3821 | | /* |
3822 | | * If we do not currently know the subdissector, we have to find it |
3823 | | * - first, according to the OID |
3824 | | * - then according to the SSN |
3825 | | * - and at least, take the default Data handler |
3826 | | */ |
3827 | 0 | if (ber_oid_dissector_table && cur_oid) { |
3828 | | /* Search if we can find the sub protocol according to the A.C.N */ |
3829 | 0 | if ((subdissector_handle |
3830 | 0 | = dissector_get_string_handle(ber_oid_dissector_table, cur_oid))) { |
3831 | | /* found */ |
3832 | 0 | is_subdissector = true; |
3833 | 0 | } else { |
3834 | | /* Search if we can found the sub protocol according to the SSN table */ |
3835 | 0 | if ((subdissector_handle |
3836 | 0 | = get_itu_tcap_subdissector(actx->pinfo->match_uint))) { |
3837 | | /* Found according to SSN */ |
3838 | 0 | is_subdissector = true; |
3839 | 0 | } else { |
3840 | | /* Nothing found, take the Data handler */ |
3841 | 0 | subdissector_handle = data_handle; |
3842 | 0 | is_subdissector = true; |
3843 | 0 | } /* SSN */ |
3844 | 0 | } /* ACN */ |
3845 | 0 | } else { |
3846 | | /* There is no A.C.N for this transaction, so search in the SSN table */ |
3847 | 0 | if ((subdissector_handle = get_itu_tcap_subdissector(actx->pinfo->match_uint))) { |
3848 | | /* Found according to SSN */ |
3849 | 0 | is_subdissector = true; |
3850 | 0 | } else { |
3851 | 0 | subdissector_handle = data_handle; |
3852 | 0 | is_subdissector = true; |
3853 | 0 | } |
3854 | 0 | } /* OID */ |
3855 | 0 | } else { |
3856 | | /* We have it already */ |
3857 | 0 | } |
3858 | | |
3859 | | /* Call the sub dissector if present, and not already called */ |
3860 | 0 | if (is_subdissector) { |
3861 | 0 | bool is_active = call_dissector_only(subdissector_handle, tvb, actx->pinfo, tree, actx->value_ptr); |
3862 | 0 | col_set_fence(actx->pinfo->cinfo, COL_INFO); |
3863 | 0 | if(!is_active){ |
3864 | 0 | return false; |
3865 | 0 | } |
3866 | 0 | } |
3867 | 0 | return true; |
3868 | 0 | } |
3869 | | |
3870 | | void |
3871 | | call_tcap_dissector(dissector_handle_t handle, tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) |
3872 | 0 | { |
3873 | 0 | requested_subdissector_handle = handle; |
3874 | |
|
3875 | 0 | TRY { |
3876 | 0 | dissect_tcap(tvb, pinfo, tree, NULL); |
3877 | 0 | } CATCH_ALL { |
3878 | 0 | requested_subdissector_handle = NULL; |
3879 | 0 | RETHROW; |
3880 | 0 | } ENDTRY; |
3881 | |
|
3882 | 0 | requested_subdissector_handle = NULL; |
3883 | 0 | } |
3884 | | |
3885 | | /* |
3886 | | * Editor modelines |
3887 | | * |
3888 | | * Local Variables: |
3889 | | * c-basic-offset: 2 |
3890 | | * tab-width: 8 |
3891 | | * indent-tabs-mode: nil |
3892 | | * End: |
3893 | | * |
3894 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
3895 | | * :indentSize=2:tabSize=8:noTabs=true: |
3896 | | */ |