Coverage Report

Created: 2026-09-28 06:52

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