From Yuriy Sidelnikov: handle the case where a presentation selector
[obnox/wireshark/wip.git] / packet-tcap.c
1 /* packet-tcap.c
2  * Routines for TCAP dissection
3  *
4  * Copyright 2000, Samuel Qu <samuel.qu [AT] utstar.com>,
5  *
6  * Michael Lum <mlum [AT] telostech.com>,
7  * Modified for ANSI TCAP support and many changes for
8  * EOC matching.  (2003)
9  *
10  * (append your name here for newer version)
11  *
12  * $Id: packet-tcap.c,v 1.8 2004/03/05 10:05:03 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 1998 Gerald Combs
17  *
18  * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
19  * is a dissector file; if you just copied this from README.developer,
20  * don't bother with the "Copied from" - you don't even need to put
21  * in a "Copied from" if you copied an existing dissector, especially
22  * if the bulk of the code in the new dissector is your code)
23  *
24  * This program is free software; you can redistribute it and/or
25  * modify it under the terms of the GNU General Public License
26  * as published by the Free Software Foundation; either version 2
27  * of the License, or (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with this program; if not, write to the Free Software
36  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37  */
38
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <gmodule.h>
47
48 #ifdef HAVE_SYS_TYPES_H
49 # include <sys/types.h>
50 #endif
51
52 #ifdef HAVE_NETINET_IN_H
53 # include <netinet/in.h>
54 #endif
55
56 #include <glib.h>
57
58 #ifdef NEED_SNPRINTF_H
59 # include "snprintf.h"
60 #endif
61
62 #include <epan/packet.h>
63 #include "prefs.h"
64 #include "packet-tcap.h"
65 #include "asn1.h"
66
67 Tcap_Standard_Type tcap_standard = ITU_TCAP_STANDARD;
68
69 /* saved pinfo */
70 static packet_info *g_pinfo = NULL;
71 static proto_tree *g_tcap_tree = NULL;
72 static gboolean g_tcap_ends_def_len = FALSE;
73
74 /* Initialize the protocol and registered fields */
75 static int proto_tcap = -1;
76 static int hf_tcap_message_type = -1;
77 static int hf_ansi_tcap_message_type = -1;
78 static int hf_tcap_tag = -1;
79 static int hf_tcap_length = -1;
80 static int hf_tcap_bytes = -1;
81 static int hf_tcap_app_con_name = -1;
82 static int hf_tcap_id = -1;
83 static int hf_tcap_tid = -1;
84 static int hf_tcap_ssn = -1; /* faked */
85 static int hf_tcap_dlg_type = -1;
86 static int hf_tcap_int = -1;
87
88 /* Initialize the subtree pointers */
89 static gint ett_tcap = -1;
90 /* Samuel */
91 static gint ett_otid = -1;
92 static gint ett_dtid = -1;
93 static gint ett_dlg_portion = -1;
94 static gint ett_dlg_req = -1;
95 static gint ett_dlg_rsp = -1;
96 static gint ett_dlg_abort = -1;
97 static gint ett_comps_portion = -1;
98 static gint ett_reason = -1;
99 static gint ett_component = -1;
100 static gint ett_problem = -1;
101 static gint ett_error = -1;
102 static gint ett_params = -1;
103 static gint ett_param = -1;
104
105 static dissector_handle_t data_handle;
106 static dissector_table_t tcap_itu_ssn_dissector_table; /* map use ssn in sccp */
107 static dissector_table_t tcap_ansi_ssn_dissector_table; /* map use ssn in sccp */
108 static gboolean lock_info_col = TRUE;
109
110 #define TC_SEQ_TAG 0x30
111 #define TC_SET_TAG 0x31
112
113 #define TC_EOC_LEN      2 /* 0x00 0x00 */
114
115 /* TCAP transaction message type definition - Samuel */
116 #define ST_MSG_TYP_UNI 0x61 /*0b01100001*/
117 #define ST_MSG_TYP_BGN 0x62 /*0b01100010*/
118 #define ST_MSG_TYP_CNT 0x65 /*0b01100101*/
119 #define ST_MSG_TYP_END 0x64 /*0b01100100*/
120 #define ST_MSG_TYP_PABT 0x67 /*0b01100111*/
121 static const value_string msg_type_strings[] = {
122         { ST_MSG_TYP_UNI, "TC-UNI" },
123         { ST_MSG_TYP_BGN, "TC-BEGIN" },
124         { ST_MSG_TYP_CNT, "TC-CONTINUE" },
125         { ST_MSG_TYP_END, "TC-END" },
126         { ST_MSG_TYP_PABT, "TC-PABORT" },
127         { 0, NULL },
128 };
129
130 /* ANSI TCAP transaction message type definition */
131 #define ANSI_ST_MSG_TYP_UNI 0xe1
132 #define ANSI_ST_MSG_TYP_QWP 0xe2
133 #define ANSI_ST_MSG_TYP_QWOP 0xe3
134 #define ANSI_ST_MSG_TYP_RSP 0xe4
135 #define ANSI_ST_MSG_TYP_CWP 0xe5
136 #define ANSI_ST_MSG_TYP_CWOP 0xe6
137 #define ANSI_ST_MSG_TYP_ABT 0xf6
138 static const value_string ansi_msg_type_strings[] = {
139         { ANSI_ST_MSG_TYP_UNI, "TC-UNI" },
140         { ANSI_ST_MSG_TYP_QWP, "TC-QUERY W PERM" },
141         { ANSI_ST_MSG_TYP_QWOP, "TC-QUERY WO PERM" },
142         { ANSI_ST_MSG_TYP_RSP, "TC-RESPONSE" },
143         { ANSI_ST_MSG_TYP_CWP, "TC-CONV W PERM" },
144         { ANSI_ST_MSG_TYP_CWOP, "TC-CONV WO PERM" },
145         { ANSI_ST_MSG_TYP_ABT, "TC-ABORT" },
146         { 0, NULL },
147 };
148
149 #define ST_ANSI_CMP_TAG 0xe8
150 #define ST_ANSI_TID_TAG 0xc7
151
152 /* TCAP TID tag value - Samuel */
153 #define ST_TID_SOURCE 0
154 #define ST_TID_DEST 1
155 #define ST_ITU_ORG_TID_TAG 0x48 /*0b01001000*/
156 #define ST_ITU_DST_TID_TAG 0x49 /*0b01001001*/
157 #define ST_ITU_PABT_TAG 0x4a /*0b01001010*/
158 #define ST_ITU_DLG_TAG 0x6b
159 #define ST_ITU_CMP_TAG 0x6c
160
161 static const value_string tid_strings[] = {
162         { ST_ITU_ORG_TID_TAG, "Source Transaction ID" },
163         { ST_ITU_DST_TID_TAG, "Destination Transaction ID" },
164         { 0, NULL },
165 };
166
167 /* TCAP dialog type */
168 #define TC_DLG_REQ 0x60
169 #define TC_DLG_RSP 0x61
170 #define TC_DLG_ABRT 0x64
171
172 static const value_string dlg_type_strings[] = {
173         { TC_DLG_REQ , "Dialogue Request" },
174         { TC_DLG_RSP , "Dialogue Response" },
175         { TC_DLG_ABRT, "Dialogue Abort" },
176         { 0, NULL },
177 };
178
179 /* TCAP component type */
180 #define TC_INVOKE 0xa1
181 #define TC_RRL 0xa2
182 #define TC_RE 0xa3
183 #define TC_REJECT 0xa4
184 #define TC_RRN 0xa7
185
186 /* ANSI TCAP component type */
187 #define ANSI_TC_INVOKE_L 0xe9
188 #define ANSI_TC_RRL 0xea
189 #define ANSI_TC_RE 0xeb
190 #define ANSI_TC_REJECT 0xec
191 #define ANSI_TC_INVOKE_N 0xed
192 #define ANSI_TC_RRN 0xee
193
194 #define TC_DS_OK 1
195 #define TC_DS_FAIL 0
196
197
198 static int
199 find_eoc(ASN1_SCK *asn1)
200 {
201     guint       saved_offset;
202     guint       tag;
203     guint       len;
204     gboolean    def_len;
205
206     saved_offset = asn1->offset;
207
208     while (!asn1_eoc(asn1, -1))
209     {
210         asn1_id_decode1(asn1, &tag);
211         asn1_length_decode(asn1, &def_len, &len);
212
213         if (def_len)
214         {
215             asn1->offset += len;
216         }
217         else
218         {
219             asn1->offset += find_eoc(asn1);
220             asn1_eoc_decode(asn1, -1);
221         }
222     }
223
224     len = asn1->offset - saved_offset;
225     asn1->offset = saved_offset;
226
227     return(len);
228 }
229
230 /* dissect length */
231 static int
232 dissect_tcap_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
233 {
234     guint saved_offset;
235     int ret;
236
237     saved_offset = asn1->offset;
238     *len = 0;
239     *def_len = FALSE;
240     ret = asn1_length_decode(asn1, def_len, len);
241
242     if (*def_len)
243     {
244         proto_tree_add_uint(tree, hf_tcap_length, asn1->tvb, saved_offset, asn1->offset - saved_offset, *len);
245     }
246     else
247     {
248         proto_tree_add_text(tree, asn1->tvb,
249             saved_offset, asn1->offset - saved_offset, "Length: Indefinite");
250     }
251
252     return TC_DS_OK;
253 }
254
255 static int
256 dissect_tcap_eoc(ASN1_SCK *asn1, proto_tree *tree)
257 {
258     guint saved_offset, ret;
259
260     saved_offset = asn1->offset;
261
262     if (tvb_length_remaining(asn1->tvb, saved_offset) <= 0)
263     {
264         return TC_DS_FAIL;
265     }
266
267     if (!asn1_eoc(asn1, -1))
268     {
269         return TC_DS_FAIL;
270     }
271
272     ret = asn1_eoc_decode(asn1, -1);
273
274     proto_tree_add_text(tree, asn1->tvb,
275         saved_offset, asn1->offset - saved_offset, "End of Contents");
276
277     return TC_DS_OK;
278 }
279
280 static int
281 dissect_tcap_tag(ASN1_SCK *asn1, proto_tree *tree, guint *tag, gchar * str)
282 {
283     guint saved_offset, real_tag;
284
285     saved_offset = asn1->offset;
286     asn1_id_decode1(asn1, &real_tag);
287     if ((*tag != (guint) -1) && (real_tag != *tag))
288     {
289         asn1->offset = saved_offset;
290         return TC_DS_FAIL;
291     }
292     proto_tree_add_uint_format(tree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset,
293             real_tag, str);
294     return TC_DS_OK;
295 }
296
297 static int
298 dissect_tcap_octet(ASN1_SCK *asn1, proto_tree *tree, gchar * str)
299 {
300     guint saved_offset;
301     guchar my_oct;
302
303     saved_offset = asn1->offset;
304     asn1_octet_decode(asn1, &my_oct);
305     proto_tree_add_uint_format(tree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset,
306                                             my_oct, "%s %d", str, my_oct);
307     return TC_DS_OK;
308 }
309
310 static int
311 dissect_tcap_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar * str)
312 {
313     guint saved_offset;
314     gint32 invokeId;
315
316     saved_offset = asn1->offset;
317     asn1_int32_value_decode(asn1, len, &invokeId);
318     proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
319                                             invokeId, "%s %d", str, invokeId);
320     return TC_DS_OK;
321 }
322
323 static gboolean
324 check_tcap_tag(ASN1_SCK *asn1, guint tag)
325 {
326     guint saved_offset, real_tag;
327
328     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
329     {
330         return (FALSE);
331     }
332
333     saved_offset = asn1->offset;
334     asn1_id_decode1(asn1, &real_tag);
335     asn1->offset = saved_offset;
336     return (tag == real_tag);
337 }
338
339 /* dissect tid */
340 static int
341 dissect_tcap_tid(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti, int type)
342 {
343     guint saved_offset, org_offset = 0;
344     guint len;
345     guint tag;
346     int ret;
347     proto_item *tid_item;
348     proto_tree *subtree;
349     guchar *poctets;
350     guint32 val;
351     gboolean def_len;
352
353     org_offset = asn1->offset;
354     if ( ST_TID_SOURCE == type)
355     {
356         tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Source Transaction ID");
357         subtree = proto_item_add_subtree(tid_item, ett_otid);
358     }
359     else
360     {
361         tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Destination Transaction ID");
362         subtree = proto_item_add_subtree(tid_item, ett_dtid);
363     }
364
365     saved_offset = asn1->offset;
366     ret = asn1_id_decode1(asn1, &tag);
367     proto_tree_add_uint(subtree, hf_tcap_tid, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
368
369     /* error handling */
370     switch(type)
371     {
372     case ST_TID_SOURCE:
373         if (ST_ITU_ORG_TID_TAG != tag)
374         {
375             asn1->offset = saved_offset;
376             return TC_DS_FAIL;
377         }
378         break;
379     case ST_TID_DEST:
380         if (ST_ITU_DST_TID_TAG != tag)
381         {
382             asn1->offset = saved_offset;
383             return TC_DS_FAIL;
384         }
385         break;
386     default:
387         break;
388     }
389
390
391     dissect_tcap_len(asn1, subtree, &def_len, &len);
392
393     saved_offset = asn1->offset;
394     ret = asn1_string_value_decode(asn1, len, &poctets);
395     val = 0;
396     memcpy(&val, poctets, len);
397
398     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
399     g_free(poctets);
400
401     proto_item_set_len(tid_item, asn1->offset - org_offset);
402
403     if (type == ST_TID_DEST)
404     {
405         if (check_col(g_pinfo->cinfo, COL_INFO))
406             col_append_fstr(g_pinfo->cinfo, COL_INFO, "dtid(%x) ", val);
407     }
408     else
409     {
410         if (check_col(g_pinfo->cinfo, COL_INFO))
411             col_append_fstr(g_pinfo->cinfo, COL_INFO, "stid(%x) ", val);
412     }
413
414     return TC_DS_OK;
415 }
416
417 /* Samuel */
418 /* dissect operation portion */
419 static int
420 dissect_tcap_invokeId(ASN1_SCK *asn1, proto_tree *tree)
421 {
422     guint len;
423     guint tag;
424     gboolean def_len;
425
426 #define INVOKE_ID_TAG 0x2
427     if (check_tcap_tag(asn1, INVOKE_ID_TAG))
428     {
429         tag = -1;
430         dissect_tcap_tag(asn1, tree, &tag, "Invoke ID Tag");
431         dissect_tcap_len(asn1, tree, &def_len, &len);
432         dissect_tcap_integer(asn1, tree, len, "Invoke ID:");
433     }
434
435     return TC_DS_OK;
436 }
437
438 static int
439 dissect_tcap_lnkId(ASN1_SCK *asn1, proto_tree *tree)
440 {
441     guint len;
442     guint tag;
443     gboolean def_len;
444
445 #define LINK_ID_TAG 0x80
446     if (check_tcap_tag(asn1, LINK_ID_TAG))
447     {
448         tag = -1;
449         dissect_tcap_tag(asn1, tree, &tag, "Linked ID Tag");
450         dissect_tcap_len(asn1, tree, &def_len, &len);
451         dissect_tcap_integer(asn1, tree, len, "Linked ID:");
452     }
453
454     return TC_DS_OK;
455 }
456
457 static void
458 dissect_tcap_opr_code(ASN1_SCK *asn1, proto_tree *tree)
459 {
460     guint len;
461     guint tag;
462     gboolean got_it = FALSE;
463     gboolean def_len;
464
465 #define TCAP_LOC_OPR_CODE_TAG 0x02
466     if (check_tcap_tag(asn1, TCAP_LOC_OPR_CODE_TAG))
467     {
468         tag = -1;
469         dissect_tcap_tag(asn1, tree, &tag, "Local Operation Code Tag");
470         got_it = TRUE;
471     }
472 #define TCAP_GLB_OPR_CODE_TAG 0x06
473     else if (check_tcap_tag(asn1, TCAP_GLB_OPR_CODE_TAG))
474     {
475         tag = -1;
476         dissect_tcap_tag(asn1, tree, &tag, "Global Operation Code Tag");
477         got_it = TRUE;
478     }
479
480     if (got_it)
481     {
482         dissect_tcap_len(asn1, tree, &def_len, &len);
483
484         proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code");
485
486         asn1->offset += len;
487     }
488 }
489
490 static int
491 dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
492 {
493     guint orig_offset, saved_offset, len_offset;
494     guint tag, len;
495     gboolean def_len;
496     proto_item *item;
497     proto_tree *subtree;
498
499     orig_offset = asn1->offset;
500
501 #define TC_INVALID_TAG 0
502     while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
503         (!check_tcap_tag(asn1, 0)))
504     {
505         if ((exp_len != 0) &&
506             ((asn1->offset - orig_offset) >= exp_len))
507         {
508             break;
509         }
510
511         saved_offset = asn1->offset;
512         asn1_id_decode1(asn1, &tag);
513         len_offset = asn1->offset;
514         asn1_length_decode(asn1, &def_len, &len);
515
516         if (tag == TC_SEQ_TAG)
517         {
518             item =
519                 proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Sequence");
520
521             subtree = proto_item_add_subtree(item, ett_params);
522
523             proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
524                 saved_offset, len_offset - saved_offset, tag, "Sequence Tag");
525
526             if (def_len)
527             {
528                 proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
529                     len_offset, asn1->offset - len_offset, len);
530             }
531             else
532             {
533                 proto_tree_add_text(subtree, asn1->tvb,
534                     len_offset, asn1->offset - len_offset, "Length: Indefinite");
535
536                 len = find_eoc(asn1);
537             }
538
539             proto_item_set_len(item,
540                 (asn1->offset - saved_offset) + len +
541                 (def_len ? 0 : TC_EOC_LEN));
542
543             dissect_tcap_param(asn1, subtree, len);
544
545             if (!def_len)
546             {
547                 dissect_tcap_eoc(asn1, subtree);
548             }
549             continue;
550         }
551
552         if (!def_len)
553         {
554             proto_tree_add_uint_format(tree, hf_tcap_tag, asn1->tvb,
555                 saved_offset, len_offset - saved_offset, tag, "Parameter Tag");
556
557             proto_tree_add_text(tree, asn1->tvb,
558                 len_offset, asn1->offset - len_offset, "Length: Indefinite");
559
560             len = find_eoc(asn1);
561
562             dissect_tcap_param(asn1, tree, len);
563
564             dissect_tcap_eoc(asn1, tree);
565             continue;
566         }
567
568         item =
569             proto_tree_add_text(tree, asn1->tvb,
570                 saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
571
572         subtree = proto_item_add_subtree(item, ett_param);
573
574         proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
575             saved_offset, len_offset - saved_offset, tag, "Parameter Tag");
576
577         proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
578             len_offset, asn1->offset - len_offset, len);
579
580         proto_tree_add_text(subtree, asn1->tvb,
581             asn1->offset, len, "Parameter Data");
582
583         asn1->offset += len;
584     }
585
586     return TC_DS_OK;
587 }
588
589 static proto_tree *
590 dissect_tcap_component(ASN1_SCK *asn1, proto_tree *tree, guint *len_p)
591 {
592     guint saved_offset;
593     guint tag;
594     proto_item *item;
595     proto_tree *subtree;
596     gboolean def_len;
597
598
599     saved_offset = asn1->offset;
600     asn1_id_decode1(asn1, &tag);
601
602     item =
603         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component ID");
604
605     subtree = proto_item_add_subtree(item, ett_component);
606
607     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
608         saved_offset, asn1->offset - saved_offset, tag,
609         "Component ID Identifier");
610
611     dissect_tcap_len(asn1, subtree, &def_len, len_p);
612
613     proto_item_set_len(item, (asn1->offset - saved_offset) + *len_p);
614
615     return(subtree);
616 }
617
618 static void
619 dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree)
620 {
621     guint orig_offset, saved_offset, len_offset;
622     guint len;
623     guint tag;
624     proto_tree *subtree;
625     proto_item *item = NULL;
626     gchar *str = NULL;
627     gchar *type_str = NULL;
628     gint32 spec;
629     gboolean def_len;
630
631
632     orig_offset = asn1->offset;
633     saved_offset = asn1->offset;
634     asn1_id_decode1(asn1, &tag);
635
636     len_offset = asn1->offset;
637     asn1_length_decode(asn1, &def_len, &len);
638
639     item =
640         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
641
642     subtree = proto_item_add_subtree(item, ett_problem);
643
644     if (!def_len)
645     {
646         len = find_eoc(asn1);
647     }
648
649     proto_item_set_len(item, (asn1->offset - saved_offset) + len +
650         (def_len ? 0 : TC_EOC_LEN));
651
652     if (len != 1)
653     {
654         proto_tree_add_text(subtree, asn1->tvb,
655             asn1->offset, len, "Unknown encoding of Problem Code");
656
657         asn1->offset += len;
658
659         if (!def_len)
660         {
661             asn1_eoc_decode(asn1, -1);
662         }
663
664         return;
665     }
666
667     saved_offset = asn1->offset;
668     asn1_int32_value_decode(asn1, 1, &spec);
669
670     switch (tag)
671     {
672     case 0x80:
673         type_str = "General Problem";
674         switch (spec)
675         {
676         case 0: str = "Unrecognized Component"; break;
677         case 1: str = "Mistyped Component"; break;
678         case 2: str = "Badly Structured Component"; break;
679         default:
680             str = "Undefined";
681             break;
682         }
683         break;
684
685     case 0x81:
686         type_str = "Invoke";
687         switch (spec)
688         {
689         case 0: str = "Duplicate Invoke ID"; break;
690         case 1: str = "Unrecognized Operation"; break;
691         case 2: str = "Mistyped Parameter"; break;
692         case 3: str = "Resource Limitation"; break;
693         case 4: str = "Initiating Release"; break;
694         case 5: str = "Unrecognized Linked ID"; break;
695         case 6: str = "Linked Response Unexpected"; break;
696         case 7: str = "Unexpected Linked Operation"; break;
697         default:
698             str = "Undefined";
699             break;
700         }
701         break;
702
703     case 0x82:
704         type_str = "Return Result";
705         switch (spec)
706         {
707         case 0: str = "Unrecognized Invoke ID"; break;
708         case 1: str = "Return Result Unexpected"; break;
709         case 2: str = "Mistyped Parameter"; break;
710         default:
711             str = "Undefined";
712             break;
713         }
714         break;
715
716     case 0x83:
717         type_str = "Return Error";
718         switch (spec)
719         {
720         case 0: str = "Unrecognized Invoke ID"; break;
721         case 1: str = "Return Error Unexpected"; break;
722         case 2: str = "Unrecognized Error"; break;
723         case 3: str = "Unexpected Error"; break;
724         case 4: str = "Mistyped Parameter"; break;
725         default:
726             str = "Undefined";
727             break;
728         }
729         break;
730
731     default:
732         type_str = "Undefined";
733         break;
734     }
735
736     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
737         orig_offset, len_offset - orig_offset, tag, type_str);
738
739     if (def_len)
740     {
741         proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
742             len_offset, saved_offset - len_offset, len);
743     }
744     else
745     {
746         proto_tree_add_text(subtree, asn1->tvb,
747             len_offset, saved_offset - len_offset, "Length: Indefinite");
748     }
749
750     proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1,
751         "Problem Specifier %s", str);
752 }
753
754
755 static void
756 dissect_ansi_opr_code(ASN1_SCK *asn1, proto_tree *tree)
757 {
758     guint len;
759     guint tag;
760     gboolean got_it = FALSE;
761     gboolean def_len;
762
763 #define TCAP_NAT_OPR_CODE_TAG 0xd0
764     if (check_tcap_tag(asn1, TCAP_NAT_OPR_CODE_TAG))
765     {
766         tag = -1;
767         dissect_tcap_tag(asn1, tree, &tag, "National TCAP Operation Code Identifier");
768         got_it = TRUE;
769     }
770 #define TCAP_PRIV_OPR_CODE_TAG 0xd1
771     else if (check_tcap_tag(asn1, TCAP_PRIV_OPR_CODE_TAG))
772     {
773         tag = -1;
774         dissect_tcap_tag(asn1, tree, &tag, "Private TCAP Operation Code Identifier");
775         got_it = TRUE;
776     }
777
778     if (got_it)
779     {
780         dissect_tcap_len(asn1, tree, &def_len, &len);
781
782         proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code");
783
784         asn1->offset += len;
785     }
786 }
787
788 static void
789 dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree)
790 {
791     guint saved_offset = 0;
792     guint len;
793     guint tag;
794     proto_tree *subtree;
795     proto_item *item = NULL;
796     gchar *str = NULL;
797     gchar *type_str = NULL;
798     gint32 type, spec;
799     gboolean def_len;
800
801
802 #define TCAP_PROB_CODE_TAG 0xd5
803     if (check_tcap_tag(asn1, TCAP_PROB_CODE_TAG))
804     {
805         str = "Problem Code Identifier";
806     }
807     else
808     {
809         /* XXX */
810         return;
811     }
812
813     saved_offset = asn1->offset;
814     asn1_id_decode1(asn1, &tag);
815
816     item =
817         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
818
819     subtree = proto_item_add_subtree(item, ett_problem);
820
821     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
822         saved_offset, asn1->offset - saved_offset, tag, str);
823
824     dissect_tcap_len(asn1, subtree, &def_len, &len);
825     proto_item_set_len(item, (asn1->offset - saved_offset) + len);
826
827     if (len != 2)
828     {
829         proto_tree_add_text(subtree, asn1->tvb,
830             asn1->offset, len, "Unknown encoding of Problem Code");
831
832         asn1->offset += len;
833         return;
834     }
835
836     saved_offset = asn1->offset;
837     asn1_int32_value_decode(asn1, 1, &type);
838     asn1_int32_value_decode(asn1, 1, &spec);
839
840     switch (type)
841     {
842     case 0: type_str = "Not used"; break;
843
844     case 1:
845         type_str = "General";
846         switch (spec)
847         {
848         case 1: str = "Unrecognized Component Type"; break;
849         case 2: str = "Incorrect Component Portion"; break;
850         case 3: str = "Badly Structured Component Portion"; break;
851         default:
852             str = "Undefined";
853             break;
854         }
855         break;
856
857     case 2:
858         type_str = "Invoke";
859         switch (spec)
860         {
861         case 1: str = "Duplicate Invoke ID"; break;
862         case 2: str = "Unrecognized Operation Code"; break;
863         case 3: str = "Incorrect Parameter"; break;
864         case 4: str = "Unrecognized Correlation ID"; break;
865         default:
866             str = "Undefined";
867             break;
868         }
869         break;
870
871     case 3:
872         type_str = "Return Result";
873         switch (spec)
874         {
875         case 1: str = "Unrecognized Correlation ID"; break;
876         case 2: str = "Unexpected Return Result"; break;
877         case 3: str = "Incorrect Parameter"; break;
878         default:
879             str = "Undefined";
880             break;
881         }
882         break;
883
884     case 4:
885         type_str = "Return Error";
886         switch (spec)
887         {
888         case 1: str = "Unrecognized Correlation ID"; break;
889         case 2: str = "Unexpected Return Error"; break;
890         case 3: str = "Unrecognized Error"; break;
891         case 4: str = "Unexpected Error"; break;
892         case 5: str = "Incorrect Parameter"; break;
893         default:
894             str = "Undefined";
895             break;
896         }
897         break;
898
899     case 5:
900         type_str = "Transaction Portion";
901         switch (spec)
902         {
903         case 1: str = "Unrecognized Package Type"; break;
904         case 2: str = "Incorrect Transaction Portion"; break;
905         case 3: str = "Badly Structured Transaction Portion"; break;
906         case 4: str = "Unrecognized Transaction ID"; break;
907         case 5: str = "Permission to Release"; break;
908         case 6: str = "Resource Unavailable"; break;
909         default:
910             str = "Undefined";
911             break;
912         }
913         break;
914
915     default:
916         type_str = "Undefined";
917         break;
918     }
919
920     if (spec == 255) { str = "Reserved"; }
921     else if (spec == 0) { str = "Not used"; }
922
923     proto_tree_add_text(subtree, asn1->tvb,
924         saved_offset, 1, "Problem Type %s", type_str);
925
926     proto_tree_add_text(subtree, asn1->tvb,
927         saved_offset + 1, 1, "Problem Specifier %s", str);
928 }
929
930
931 static void
932 dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree)
933 {
934     guint saved_offset = 0;
935     guint len;
936     guint tag;
937     proto_tree *subtree;
938     proto_item *item = NULL;
939     gchar *str = NULL;
940     gboolean def_len;
941
942
943 #define TCAP_NAT_ERR_CODE_TAG 0xd3
944     if (check_tcap_tag(asn1, TCAP_NAT_ERR_CODE_TAG))
945     {
946         str = "National TCAP Error Code Identifier";
947     }
948 #define TCAP_PRIV_ERR_CODE_TAG 0xd4
949     else if (check_tcap_tag(asn1, TCAP_PRIV_ERR_CODE_TAG))
950     {
951         str = "Private TCAP Error Code Identifier";
952     }
953     else
954     {
955         /* XXX */
956         return;
957     }
958
959     saved_offset = asn1->offset;
960     asn1_id_decode1(asn1, &tag);
961
962     item =
963         proto_tree_add_text(tree, asn1->tvb,
964             saved_offset, -1, "TCAP Error Code");
965
966     subtree = proto_item_add_subtree(item, ett_error);
967
968     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
969         saved_offset, asn1->offset - saved_offset, tag, str);
970
971     dissect_tcap_len(asn1, subtree, &def_len, &len);
972     proto_item_set_len(item, (asn1->offset - saved_offset) + len);
973
974     proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Error Code");
975
976     asn1->offset += len;
977 }
978
979
980 static void
981 dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree)
982 {
983     guint len;
984     guint tag;
985     gboolean got_it = FALSE;
986     gboolean def_len;
987
988 #define TCAP_PARAM_SET_TAG 0xf2
989     if (check_tcap_tag(asn1, TCAP_PARAM_SET_TAG))
990     {
991         tag = -1;
992         dissect_tcap_tag(asn1, tree, &tag, "Parameter Set Identifier");
993         got_it = TRUE;
994     }
995 #define TCAP_PARAM_SEQ_TAG 0x30
996     else if (check_tcap_tag(asn1, TCAP_PARAM_SEQ_TAG))
997     {
998         tag = -1;
999         dissect_tcap_tag(asn1, tree, &tag, "Parameter Sequence Identifier");
1000         got_it = TRUE;
1001     }
1002
1003     if (got_it)
1004     {
1005         dissect_tcap_len(asn1, tree, &def_len, &len);
1006
1007         proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data");
1008
1009         asn1->offset += len;
1010     }
1011 }
1012
1013 static void
1014 dissect_ansi_tcap_reject(ASN1_SCK *asn1, proto_tree *tree)
1015 {
1016     guint len;
1017     proto_tree *subtree;
1018
1019 #define COMPONENT_ID_TAG 0xcf
1020     if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
1021     {
1022         subtree = dissect_tcap_component(asn1, tree, &len);
1023
1024         switch (len)
1025         {
1026         case 1:
1027             dissect_tcap_octet(asn1, subtree, "Correlation ID:");
1028             break;
1029         }
1030     }
1031
1032     dissect_ansi_problem(asn1, tree);
1033
1034     dissect_ansi_param(asn1, tree);
1035 }
1036
1037 static void
1038 dissect_ansi_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
1039 {
1040     guint len;
1041     proto_tree *subtree;
1042
1043 #define COMPONENT_ID_TAG 0xcf
1044     if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
1045     {
1046         subtree = dissect_tcap_component(asn1, tree, &len);
1047
1048         switch (len)
1049         {
1050         case 1:
1051             dissect_tcap_octet(asn1, tree, "Correlation ID:");
1052             break;
1053         }
1054     }
1055
1056     dissect_ansi_error(asn1, tree);
1057
1058     dissect_ansi_param(asn1, tree);
1059 }
1060
1061 static void
1062 dissect_ansi_tcap_rr(ASN1_SCK *asn1, proto_tree *tree)
1063 {
1064     guint len;
1065     proto_tree *subtree;
1066
1067 #define COMPONENT_ID_TAG 0xcf
1068     if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
1069     {
1070         subtree = dissect_tcap_component(asn1, tree, &len);
1071
1072         switch (len)
1073         {
1074         case 1:
1075             dissect_tcap_octet(asn1, tree, "Correlation ID:");
1076             break;
1077         }
1078     }
1079
1080     dissect_ansi_param(asn1, tree);
1081 }
1082
1083 static void
1084 dissect_ansi_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
1085 {
1086     guint len;
1087     proto_tree *subtree;
1088
1089 #define COMPONENT_ID_TAG 0xcf
1090     if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
1091     {
1092         subtree = dissect_tcap_component(asn1, tree, &len);
1093
1094         switch (len)
1095         {
1096         case 1:
1097             dissect_tcap_octet(asn1, tree, "Invoke ID:");
1098             break;
1099
1100         case 2:
1101             dissect_tcap_octet(asn1, tree, "Invoke ID:");
1102             dissect_tcap_octet(asn1, tree, "Correlation ID:");
1103             break;
1104         }
1105     }
1106
1107     dissect_ansi_opr_code(asn1, tree);
1108
1109     dissect_ansi_param(asn1, tree);
1110 }
1111
1112 static void
1113 dissect_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
1114 {
1115     proto_tree *subtree;
1116     guint orig_offset, saved_offset;
1117     guint len;
1118     guint tag;
1119     int ret;
1120     proto_item *item;
1121     gboolean def_len;
1122
1123     orig_offset = asn1->offset;
1124     saved_offset = asn1->offset;
1125     ret = asn1_id_decode1(asn1, &tag);
1126
1127     item =
1128         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
1129
1130     subtree = proto_item_add_subtree(item, ett_component);
1131
1132     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
1133         saved_offset, asn1->offset - saved_offset, tag, "Invoke Type Tag");
1134
1135     dissect_tcap_len(asn1, subtree, &def_len, &len);
1136
1137     saved_offset = asn1->offset;
1138
1139     dissect_tcap_invokeId(asn1, subtree);
1140
1141     dissect_tcap_lnkId(asn1, subtree);
1142
1143     dissect_tcap_opr_code(asn1, subtree);
1144
1145     if (def_len)
1146     {
1147         len -= asn1->offset - saved_offset;
1148     }
1149     else
1150     {
1151         len = find_eoc(asn1);
1152     }
1153
1154     dissect_tcap_param(asn1, subtree, len);
1155
1156     if (!def_len)
1157     {
1158         dissect_tcap_eoc(asn1, subtree);
1159     }
1160
1161     proto_item_set_len(item, asn1->offset - orig_offset);
1162 }
1163
1164 static void
1165 dissect_tcap_rr(ASN1_SCK *asn1, proto_tree *tree, gchar *str)
1166 {
1167     guint tag, len, comp_len;
1168     guint orig_offset, saved_offset, len_offset;
1169     proto_item *seq_item, *item;
1170     proto_tree *seq_subtree, *subtree;
1171     gboolean def_len;
1172     gboolean comp_def_len;
1173
1174     tag = -1;
1175     orig_offset = asn1->offset;
1176     saved_offset = asn1->offset;
1177     asn1_id_decode1(asn1, &tag);
1178
1179     item =
1180         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
1181
1182     subtree = proto_item_add_subtree(item, ett_component);
1183
1184     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
1185         saved_offset, asn1->offset - saved_offset, tag, str);
1186
1187     dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len);
1188
1189     saved_offset = asn1->offset;
1190
1191     dissect_tcap_invokeId(asn1, subtree);
1192
1193     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
1194     {
1195         proto_item_set_len(item, asn1->offset - orig_offset);
1196
1197         return;
1198     }
1199
1200     saved_offset = asn1->offset;
1201
1202     tag = -1;
1203     asn1_id_decode1(asn1, &tag);
1204
1205     if (tag == TC_SEQ_TAG)
1206     {
1207         len_offset = asn1->offset;
1208         asn1_length_decode(asn1, &def_len, &len);
1209
1210         seq_item =
1211             proto_tree_add_text(subtree, asn1->tvb, saved_offset, -1, "Sequence");
1212
1213         seq_subtree = proto_item_add_subtree(seq_item, ett_params);
1214
1215         proto_tree_add_uint_format(seq_subtree, hf_tcap_tag, asn1->tvb,
1216             saved_offset, len_offset - saved_offset, tag, "Sequence Tag");
1217
1218         if (def_len)
1219         {
1220             proto_tree_add_uint(seq_subtree, hf_tcap_length, asn1->tvb,
1221                 len_offset, asn1->offset - len_offset, len);
1222         }
1223         else
1224         {
1225             proto_tree_add_text(seq_subtree, asn1->tvb,
1226                 len_offset, asn1->offset - len_offset, "Length: Indefinite");
1227
1228             len = find_eoc(asn1);
1229         }
1230
1231         proto_item_set_len(seq_item,
1232             (asn1->offset - saved_offset) + len +
1233             (def_len ? 0 : TC_EOC_LEN));
1234
1235         saved_offset = asn1->offset;
1236
1237         dissect_tcap_opr_code(asn1, seq_subtree);
1238
1239         len -= asn1->offset - saved_offset;
1240
1241         dissect_tcap_param(asn1, seq_subtree, len);
1242
1243         if (!def_len)
1244         {
1245             dissect_tcap_eoc(asn1, seq_subtree);
1246         }
1247     }
1248
1249     if (!comp_def_len)
1250     {
1251         dissect_tcap_eoc(asn1, subtree);
1252     }
1253
1254     proto_item_set_len(item, asn1->offset - orig_offset);
1255 }
1256
1257 static int
1258 dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
1259 {
1260     guint tag, len, comp_len;
1261     guint orig_offset, saved_offset;
1262     proto_item *item;
1263     proto_tree *subtree;
1264     gboolean comp_def_len, def_len;
1265
1266     tag = -1;
1267     orig_offset = asn1->offset;
1268     saved_offset = asn1->offset;
1269     asn1_id_decode1(asn1, &tag);
1270
1271     item =
1272         proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
1273
1274     subtree = proto_item_add_subtree(item, ett_component);
1275
1276     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
1277         saved_offset, asn1->offset - saved_offset,
1278         tag, "Return Error Type Tag");
1279
1280     dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len);
1281
1282     if (!comp_def_len)
1283     {
1284         comp_len = find_eoc(asn1);
1285     }
1286
1287     saved_offset = asn1->offset;
1288
1289     dissect_tcap_invokeId(asn1, subtree);
1290
1291 #define TC_LOCAL_ERR_CODE_TAG 0x2
1292 #define TC_GBL_ERR_CODE_TAG 0x6
1293     if (check_tcap_tag(asn1, TC_LOCAL_ERR_CODE_TAG))
1294     {
1295         tag = -1;
1296         dissect_tcap_tag(asn1, subtree, &tag, "Local Error Code Tag");
1297     }
1298     else if (check_tcap_tag(asn1, TC_GBL_ERR_CODE_TAG))
1299     {
1300         tag = -1;
1301         dissect_tcap_tag(asn1, subtree, &tag, "Global Error Code Tag");
1302     }
1303     else
1304     {
1305         proto_tree_add_text(subtree, asn1->tvb, asn1->offset, comp_len,
1306             "Unknown Error Code");
1307
1308         asn1->offset += comp_len;
1309
1310         if (!comp_def_len)
1311         {
1312             dissect_tcap_eoc(asn1, subtree);
1313         }
1314
1315         proto_item_set_len(item, asn1->offset - orig_offset);
1316
1317         return(TC_DS_OK);
1318     }
1319
1320     dissect_tcap_len(asn1, subtree, &def_len, &len);
1321     dissect_tcap_integer(asn1, subtree, len, "Error Code:");
1322
1323     dissect_tcap_param(asn1, subtree, comp_len - (asn1->offset - saved_offset));
1324
1325     if (!comp_def_len)
1326     {
1327         dissect_tcap_eoc(asn1, subtree);
1328     }
1329
1330     proto_item_set_len(item, asn1->offset - orig_offset);
1331
1332     return(TC_DS_OK);
1333 }
1334
1335 static void
1336 dissect_tcap_reject(ASN1_SCK *asn1, proto_tree *tree)
1337 {
1338     guint tag, comp_len;
1339     guint saved_offset;
1340     proto_item *item;
1341     proto_tree *subtree;
1342     gboolean def_len;
1343
1344     tag = -1;
1345
1346     saved_offset = asn1->offset;
1347     asn1_id_decode1(asn1, &tag);
1348
1349     item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
1350
1351     subtree = proto_item_add_subtree(item, ett_component);
1352
1353     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
1354         saved_offset, asn1->offset - saved_offset,
1355         tag, "Reject Type Tag");
1356
1357     dissect_tcap_len(asn1, subtree, &def_len, &comp_len);
1358
1359     dissect_tcap_invokeId(asn1, subtree);
1360
1361     dissect_tcap_problem(asn1, subtree);
1362
1363     if (!def_len)
1364     {
1365         dissect_tcap_eoc(asn1, subtree);
1366     }
1367
1368     proto_item_set_len(item, asn1->offset - saved_offset);
1369 }
1370
1371 static void
1372 dissect_ansi_tcap_next_tvb(ASN1_SCK *asn1, guint len, proto_tree *tree)
1373 {
1374     tvbuff_t *next_tvb;
1375     guint saved_offset;
1376     int ret;
1377     gboolean flag = TRUE;
1378     guint tag;
1379     proto_item *item, *tag_item;
1380     proto_tree *subtree, *tag_subtree;
1381     gboolean def_len;
1382
1383
1384     if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO);
1385
1386     next_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len);
1387
1388     /* process components data */
1389     if (!dissector_try_port(tcap_ansi_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree))
1390     {
1391         /* dissect cmp */
1392
1393         saved_offset = asn1->offset;
1394         ret = asn1_id_decode1(asn1, &tag);
1395
1396         /*
1397          * verify tag type is known
1398          */
1399         switch (tag)
1400         {
1401         case ANSI_TC_INVOKE_L :
1402         case ANSI_TC_RRL :
1403         case ANSI_TC_RE :
1404         case ANSI_TC_REJECT :
1405         case ANSI_TC_INVOKE_N :
1406         case ANSI_TC_RRN :
1407             flag = TRUE;
1408             break;
1409
1410         default:
1411             flag = FALSE;
1412             break;
1413         }
1414
1415         if (flag != FALSE)
1416         {
1417             item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Components");
1418             subtree = proto_item_add_subtree(item, ett_component);
1419
1420             switch (tag)
1421             {
1422             case ANSI_TC_INVOKE_L :
1423                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1424                             asn1->offset - saved_offset, tag, "Invoke(Last)");
1425                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1426                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1427
1428                 dissect_ansi_tcap_invoke(asn1, tag_subtree);
1429                 break;
1430             case ANSI_TC_RRL :
1431                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1432                             asn1->offset - saved_offset, tag, "Return Result(Last)");
1433                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1434                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1435
1436                 dissect_ansi_tcap_rr(asn1, tag_subtree);
1437                 break;
1438             case ANSI_TC_RE :
1439                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1440                             asn1->offset - saved_offset, tag, "Return Error");
1441                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1442                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1443
1444                 dissect_ansi_tcap_re(asn1, tag_subtree);
1445                 break;
1446             case ANSI_TC_REJECT :
1447                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1448                             asn1->offset - saved_offset, tag, "Reject");
1449                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1450                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1451
1452                 dissect_ansi_tcap_reject(asn1, tag_subtree);
1453                 break;
1454             case ANSI_TC_INVOKE_N :
1455                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1456                             asn1->offset - saved_offset, tag, "Invoke(Not Last)");
1457                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1458                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1459
1460                 dissect_ansi_tcap_invoke(asn1, tag_subtree);
1461                 break;
1462             case ANSI_TC_RRN :
1463                 tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1464                             asn1->offset - saved_offset, tag, "Return Result(Not Last)");
1465                 dissect_tcap_len(asn1, subtree, &def_len, &len);
1466                 tag_subtree = proto_item_add_subtree(tag_item, ett_component);
1467
1468                 dissect_ansi_tcap_rr(asn1, tag_subtree);
1469                 break;
1470             }
1471
1472             proto_item_set_len(item, asn1->offset - saved_offset);
1473         }
1474     }
1475
1476     if (!flag)
1477     {
1478         /* No sub-dissection occured, treat it as raw data */
1479         call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree);
1480     }
1481 }
1482
1483 static int
1484 dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
1485 {
1486     proto_tree  *subtree;
1487     proto_item  *comps_item;
1488     guint       saved_offset, comps_start;
1489     guint       len, comp_len;
1490     gint        keep_len;
1491     gboolean    comps_def_len, def_len;
1492     guint       tag;
1493     int         ret;
1494     tvbuff_t    *next_tvb;
1495
1496     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
1497     {
1498         return TC_DS_FAIL;
1499     }
1500
1501     comps_start = asn1->offset;
1502     saved_offset = asn1->offset;
1503     ret = asn1_id_decode1(asn1, &tag);
1504
1505     if (ST_ITU_CMP_TAG != tag)
1506     {
1507         asn1->offset = saved_offset;
1508         return TC_DS_FAIL;
1509     }
1510
1511     comps_item =
1512         proto_tree_add_text(tcap_tree, asn1->tvb,
1513             saved_offset, -1, "Components Portion");
1514
1515     subtree = proto_item_add_subtree(comps_item, ett_comps_portion);
1516
1517     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
1518         asn1->offset - saved_offset, tag, "Component Portion Tag");
1519
1520     dissect_tcap_len(asn1, subtree, &comps_def_len, &len);
1521
1522     if (comps_def_len)
1523     {
1524         proto_item_set_len(comps_item, (asn1->offset - comps_start) + len);
1525     }
1526
1527     if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO);
1528
1529     /* call next dissector for EACH component */
1530
1531     keep_len =
1532         (comps_def_len ? 0 : TC_EOC_LEN) +
1533         (g_tcap_ends_def_len ? 0 : TC_EOC_LEN);
1534
1535     while (tvb_length_remaining(asn1->tvb, asn1->offset) > keep_len)
1536     {
1537         /* peek at tag and length */
1538         saved_offset = asn1->offset;
1539         ret = asn1_id_decode1(asn1, &tag);
1540
1541         comp_len = 0;
1542         def_len = FALSE;
1543         ret = asn1_length_decode(asn1, &def_len, &comp_len);
1544
1545         if (def_len)
1546         {
1547             comp_len += (asn1->offset - saved_offset);
1548         }
1549         else
1550         {
1551             comp_len = (asn1->offset - saved_offset) + find_eoc(asn1) + TC_EOC_LEN;
1552         }
1553
1554         next_tvb = tvb_new_subset(asn1->tvb, saved_offset, comp_len, comp_len);
1555         asn1->offset = saved_offset;
1556
1557         /* process component data */
1558         if (dissector_try_port(tcap_itu_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree))
1559         {
1560             proto_tree_add_text(subtree, asn1->tvb, asn1->offset, comp_len, "Component");
1561
1562             asn1->offset += comp_len;
1563         }
1564         else
1565         {
1566             switch (tag)
1567             {
1568             case TC_INVOKE :
1569                 dissect_tcap_invoke(asn1, subtree);
1570                 break;
1571             case TC_RRL :
1572                 dissect_tcap_rr(asn1, subtree, "Return Result(Last) Type Tag");
1573                 break;
1574             case TC_RE :
1575                 dissect_tcap_re(asn1, subtree);
1576                 break;
1577             case TC_REJECT :
1578                 dissect_tcap_reject(asn1, subtree);
1579                 break;
1580             case TC_RRN :
1581                 /* same definition as RRL */
1582                 dissect_tcap_rr(asn1, subtree, "Return Result(Not Last) Type Tag");
1583                 break;
1584             default:
1585                 /* treat it as raw data */
1586                 call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree);
1587                 break;
1588             }
1589         }
1590     }
1591
1592     if (!comps_def_len)
1593     {
1594         dissect_tcap_eoc(asn1, subtree);
1595
1596         proto_item_set_len(comps_item, asn1->offset - comps_start);
1597     }
1598
1599     return TC_DS_OK;
1600 }
1601
1602 /* dissect dialog portion */
1603 static int
1604 dissect_tcap_dlg_protocol_version(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
1605 {
1606     guint saved_offset = 0;
1607     guint len;
1608     guint tag;
1609     int ret;
1610     gboolean def_len;
1611
1612 #define TC_DLG_PROTO_VER_TAG 0x80
1613     if (check_tcap_tag(asn1, TC_DLG_PROTO_VER_TAG))
1614     {
1615         saved_offset = asn1->offset;
1616         ret = asn1_id_decode1(asn1, &tag);
1617         proto_tree_add_uint_format(tcap_tree, hf_tcap_tag, asn1->tvb,
1618             saved_offset, asn1->offset - saved_offset, tag,
1619             "Protocol Version Tag: 0x%x", tag);
1620
1621         dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
1622         saved_offset = asn1->offset;
1623         ti =
1624             proto_tree_add_bytes(tcap_tree, hf_tcap_bytes, asn1->tvb, saved_offset, len,
1625                 (guchar*)(tvb_get_ptr(asn1->tvb, saved_offset, len)));
1626         asn1->offset += len;
1627     }
1628
1629     return TC_DS_OK;
1630 }
1631
1632 static int
1633 dissect_tcap_dlg_application_context_name(ASN1_SCK *asn1, proto_tree *tcap_tree)
1634 {
1635     guint saved_offset = 0;
1636     guint name_len, len, len2;
1637     guint tag;
1638     subid_t *oid;
1639     int ret;
1640     gboolean def_len;
1641
1642     saved_offset = asn1->offset;
1643     ret = asn1_id_decode1(asn1, &tag);
1644     proto_tree_add_uint_format(tcap_tree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
1645                             "Application Context Name Tag: 0x%x", tag);
1646
1647     dissect_tcap_len(asn1, tcap_tree, &def_len, &name_len);
1648
1649     saved_offset = asn1->offset;
1650     ret = asn1_oid_decode (asn1, &oid, &len, &len2);
1651     proto_tree_add_bytes(tcap_tree, hf_tcap_app_con_name, asn1->tvb, saved_offset, len2, tvb_get_ptr(asn1->tvb, saved_offset, len2));
1652     if (ret == ASN1_ERR_NOERROR) g_free(oid);
1653
1654     if (!def_len)
1655     {
1656         /* for Application Context Name Tag */
1657         dissect_tcap_eoc(asn1, tcap_tree);
1658     }
1659
1660     return TC_DS_OK;
1661 }
1662
1663 static int
1664 dissect_tcap_dlg_result(ASN1_SCK *asn1, proto_tree *tree)
1665 {
1666     guint tag, rtag_len, itag_len;
1667     guint saved_offset = 0;
1668     gint32 value;
1669     gchar *str;
1670     gboolean def_len;
1671     gboolean rtag_def_len;
1672
1673     tag = -1;
1674     dissect_tcap_tag(asn1, tree, &tag, "Result Tag");
1675
1676     dissect_tcap_len(asn1, tree, &rtag_def_len, &rtag_len);
1677
1678     tag = -1;
1679     dissect_tcap_tag(asn1, tree, &tag, "Integer Tag");
1680
1681     dissect_tcap_len(asn1, tree, &def_len, &itag_len);
1682
1683     saved_offset = asn1->offset;
1684     asn1_int32_value_decode(asn1, itag_len, &value);
1685
1686     switch (value)
1687     {
1688     case 0x00: str = "Accepted"; break;
1689     case 0x01: str = "Reject-permanent"; break;
1690     default: str = "Unknown value"; break;
1691     }
1692
1693     proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
1694         value, "%s %d", str, value);
1695
1696     if (!rtag_def_len)
1697     {
1698         /* for Result Tag */
1699         dissect_tcap_eoc(asn1, tree);
1700     }
1701
1702     return TC_DS_OK;
1703 }
1704
1705 static int
1706 dissect_tcap_dlg_result_src_diag(ASN1_SCK *asn1, proto_tree *tree)
1707 {
1708     guint saved_offset = 0;
1709     guint len, tag;
1710     gint32 value;
1711     gboolean user;
1712     gchar *str;
1713     gboolean def_len;
1714     gboolean serv_def_len;
1715     gboolean diag_def_len;
1716
1717     tag = -1;
1718     dissect_tcap_tag(asn1, tree, &tag, "Result Source Diagnostic Tag");
1719
1720     dissect_tcap_len(asn1, tree, &diag_def_len, &len);
1721
1722 #define TC_DIAG_SERV_USER_TAG 0xa1
1723 #define TC_DIAG_SERV_PROV_TAG 0xa2
1724     if (check_tcap_tag(asn1, TC_DIAG_SERV_USER_TAG))
1725     {
1726         tag = -1;
1727         dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service User Tag");
1728         user = TRUE;
1729     }
1730     else if (check_tcap_tag(asn1, TC_DIAG_SERV_PROV_TAG))
1731     {
1732         tag = -1;
1733         dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service Provider Tag");
1734         user = FALSE;
1735     }
1736     else
1737     {
1738         proto_tree_add_text(tree, asn1->tvb, asn1->offset, len,
1739             "Unknown Result Source Diagnostic");
1740
1741         asn1->offset += len;
1742         return(TC_DS_OK);
1743     }
1744
1745     dissect_tcap_len(asn1, tree, &serv_def_len, &len);
1746
1747     tag = -1;
1748     dissect_tcap_tag(asn1, tree, &tag, "Integer Tag");
1749
1750     dissect_tcap_len(asn1, tree, &def_len, &len);
1751
1752     saved_offset = asn1->offset;
1753     asn1_int32_value_decode(asn1, len, &value);
1754
1755     if (user)
1756     {
1757         switch (value)
1758         {
1759         case 0x00: str = "Null"; break;
1760         case 0x01: str = "No reason given"; break;
1761         case 0x02: str = "Application Context Name not supplied"; break;
1762         default: str = "Unknown value"; break;
1763         }
1764     }
1765     else
1766     {
1767         switch (value)
1768         {
1769         case 0x00: str = "Null"; break;
1770         case 0x01: str = "No reason given"; break;
1771         case 0x02: str = "No common dialogue portion"; break;
1772         default: str = "Unknown value"; break;
1773         }
1774     }
1775
1776     proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
1777         value, "%s %d", str, value);
1778
1779     if (!serv_def_len)
1780     {
1781         /* for Dialogue Service User/Provider Tag */
1782         dissect_tcap_eoc(asn1, tree);
1783     }
1784
1785     if (!diag_def_len)
1786     {
1787         /* for Result Source Diagnostic Tag */
1788         dissect_tcap_eoc(asn1, tree);
1789     }
1790
1791     return TC_DS_OK;
1792 }
1793
1794 static int
1795 dissect_tcap_dlg_user_info(ASN1_SCK *asn1, proto_tree *tree)
1796 {
1797     guint tag, len;
1798     guint saved_offset = 0;
1799     gboolean def_len;
1800     gboolean user_info_def_len;
1801
1802 #define TC_USR_INFO_TAG 0xbe
1803     if (check_tcap_tag(asn1, TC_USR_INFO_TAG))
1804     {
1805         tag = -1;
1806         dissect_tcap_tag(asn1, tree, &tag, "User Info Tag");
1807         dissect_tcap_len(asn1, tree, &user_info_def_len, &len);
1808
1809 #define TC_EXT_TAG 0x28
1810         if (check_tcap_tag(asn1, TC_EXT_TAG))
1811         {
1812             saved_offset = asn1->offset;
1813             asn1_id_decode1(asn1, &tag);
1814             proto_tree_add_uint_format(tree, hf_tcap_length, asn1->tvb, saved_offset, asn1->offset - saved_offset,
1815                 tag, "External Tag: 0x%x", tag);
1816
1817             dissect_tcap_len(asn1, tree, &def_len, &len);
1818         }
1819
1820         proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data");
1821         asn1->offset += len;
1822
1823         if (!user_info_def_len)
1824         {
1825             /* for User Information Tag */
1826             dissect_tcap_eoc(asn1, tree);
1827         }
1828     }
1829
1830     return TC_DS_OK;
1831 }
1832
1833 static int
1834 dissect_tcap_dlg_req(ASN1_SCK *asn1, proto_tree *tcap_tree)
1835 {
1836     proto_tree *subtree;
1837     guint saved_offset = 0;
1838     guint len;
1839     guint tag;
1840     int ret;
1841     proto_item *req_item;
1842     guint req_start = asn1->offset;
1843     gboolean def_len;
1844
1845     /* dissect dialog portion */
1846     saved_offset = asn1->offset;
1847     ret = asn1_id_decode1(asn1, &tag);
1848     req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Request");
1849     subtree = proto_item_add_subtree(req_item, ett_dlg_req);
1850     proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
1851
1852     dissect_tcap_len(asn1, subtree, &def_len, &len);
1853
1854     dissect_tcap_dlg_protocol_version(asn1, subtree, NULL);
1855
1856     dissect_tcap_dlg_application_context_name(asn1, subtree);
1857
1858     dissect_tcap_dlg_user_info(asn1, subtree);
1859
1860     /* decode end of sequence */
1861
1862     if (!def_len)
1863     {
1864         /* for Dialogue Request Tag */
1865         dissect_tcap_eoc(asn1, subtree);
1866     }
1867
1868     proto_item_set_len(req_item, asn1->offset - req_start);
1869
1870     return TC_DS_OK;
1871 }
1872
1873 static int
1874 dissect_tcap_dlg_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree)
1875 {
1876     proto_tree *subtree;
1877     guint saved_offset = 0;
1878     guint len;
1879     guint tag;
1880     int ret;
1881     proto_item *req_item;
1882     guint req_start = asn1->offset;
1883     gboolean def_len;
1884
1885     /* dissect dialog portion */
1886     saved_offset = asn1->offset;
1887     ret = asn1_id_decode1(asn1, &tag);
1888     req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Response");
1889     subtree = proto_item_add_subtree(req_item, ett_dlg_rsp);
1890     proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
1891
1892     dissect_tcap_len(asn1, subtree, &def_len, &len);
1893
1894     dissect_tcap_dlg_protocol_version(asn1, subtree, NULL);
1895
1896     dissect_tcap_dlg_application_context_name(asn1, subtree);
1897
1898     /* result */
1899     dissect_tcap_dlg_result(asn1, subtree);
1900
1901     /* result source diag */
1902     dissect_tcap_dlg_result_src_diag(asn1, subtree);
1903
1904     dissect_tcap_dlg_user_info(asn1, subtree);
1905
1906     if (!def_len)
1907     {
1908         /* for Dialogue Response Tag */
1909         dissect_tcap_eoc(asn1, subtree);
1910     }
1911
1912     proto_item_set_len(req_item, asn1->offset - req_start);
1913
1914     return TC_DS_OK;
1915 }
1916
1917 static int
1918 dissect_tcap_dlg_abrt(ASN1_SCK *asn1, proto_tree *tree)
1919 {
1920     proto_tree *subtree;
1921     guint saved_offset = 0;
1922     guint len;
1923     guint tag;
1924     int ret;
1925     proto_item *req_item;
1926     gint32 value;
1927     gchar *str;
1928     gboolean def_len, abort_def_len;
1929
1930     /* dissect dialog pabort portion */
1931     saved_offset = asn1->offset;
1932     ret = asn1_id_decode1(asn1, &tag);
1933     req_item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Dialogue Abort");
1934     subtree = proto_item_add_subtree(req_item, ett_dlg_abort );
1935     proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
1936
1937     dissect_tcap_len(asn1, subtree, &abort_def_len, &len);
1938
1939     tag = -1;
1940     dissect_tcap_tag(asn1, subtree, &tag, "Abort Source Tag");
1941     dissect_tcap_len(asn1, subtree, &def_len, &len);
1942
1943     saved_offset = asn1->offset;
1944     asn1_int32_value_decode(asn1, len, &value);
1945
1946     switch (value)
1947     {
1948     case 0x00: str = "Dialogue Service User"; break;
1949     case 0x01: str = "Dialogue Service Provider"; break;
1950     default: str = "Unknown value"; break;
1951     }
1952
1953     proto_tree_add_int_format(subtree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
1954         value, "Abort Source: %s %d", str, value);
1955
1956     dissect_tcap_dlg_user_info(asn1, subtree);
1957
1958     if (!abort_def_len)
1959     {
1960         /* for Dialogue Abort Tag */
1961         dissect_tcap_eoc(asn1, subtree);
1962     }
1963
1964     return TC_DS_OK;
1965 }
1966
1967 static int
1968 dissect_tcap_dialog_portion(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
1969 {
1970     proto_tree *subtree;
1971     guint saved_offset = 0;
1972     guint len;
1973     guint tag;
1974     int ret;
1975     proto_item *dlg_item;
1976     guint dlg_start = asn1->offset;
1977     gboolean def_len, ext_tag_def_len, portion_def_len;
1978
1979     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
1980     {
1981         return TC_DS_FAIL;
1982     }
1983
1984     /* dissect dialog portion */
1985     saved_offset = asn1->offset;
1986     ret = asn1_id_decode1(asn1, &tag);
1987
1988     /* error handling */
1989     if (ST_ITU_DLG_TAG != tag)
1990     {
1991         asn1->offset = saved_offset;
1992         return TC_DS_FAIL;
1993     }
1994
1995     dlg_item =
1996         proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Portion");
1997
1998     subtree = proto_item_add_subtree(dlg_item, ett_dlg_portion);
1999
2000     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
2001         saved_offset, asn1->offset - saved_offset, tag, "Dialogue Portion Tag");
2002
2003     dissect_tcap_len(asn1, subtree, &portion_def_len, &len);
2004
2005     if (portion_def_len)
2006     {
2007         proto_item_set_len(dlg_item, len);
2008     }
2009
2010     ext_tag_def_len = FALSE;
2011     saved_offset = asn1->offset;
2012     ret = asn1_id_decode1(asn1, &tag);
2013 #define TC_EXT_TAG 0x28
2014     if (TC_EXT_TAG != tag)
2015     {
2016         asn1->offset = saved_offset;
2017     }
2018     else
2019     {
2020         proto_tree_add_uint_format(subtree, hf_tcap_length, asn1->tvb,
2021             saved_offset, asn1->offset - saved_offset, tag,
2022             "External Tag: 0x%x", tag);
2023
2024         dissect_tcap_len(asn1, subtree, &ext_tag_def_len, &len);
2025     }
2026
2027     saved_offset = asn1->offset;
2028     ret = asn1_id_decode1(asn1, &tag);
2029 #define TC_OID_TAG 0x06
2030     if (TC_OID_TAG != tag)
2031     {
2032         asn1->offset = saved_offset;
2033     }
2034     else
2035     {
2036         proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
2037             saved_offset, asn1->offset - saved_offset, tag,
2038             "Object Identifier Tag");
2039
2040         dissect_tcap_len(asn1, subtree, &def_len, &len);
2041
2042         saved_offset = asn1->offset;
2043         ti =
2044             proto_tree_add_bytes(subtree, hf_tcap_bytes, asn1->tvb, saved_offset, len,
2045                 (guchar*)(tvb_get_ptr(asn1->tvb, saved_offset, len)));
2046
2047         asn1->offset += len;
2048     }
2049
2050     saved_offset = asn1->offset;
2051     ret = asn1_id_decode1(asn1, &tag);
2052
2053     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
2054         saved_offset, asn1->offset - saved_offset, tag,
2055         "Single-ASN.1-type Tag");
2056
2057     dissect_tcap_len(asn1, subtree, &def_len, &len);
2058
2059     proto_item_set_len(dlg_item, asn1->offset - dlg_start);
2060
2061     /* dialogue PDU */
2062     saved_offset = asn1->offset;
2063     ret = asn1_id_decode1(asn1, &tag);
2064     asn1->offset = saved_offset;
2065
2066     switch(tag)
2067     {
2068     case TC_DLG_REQ:
2069         dissect_tcap_dlg_req(asn1, subtree);
2070         break;
2071     case TC_DLG_RSP:
2072         dissect_tcap_dlg_rsp(asn1, subtree);
2073         break;
2074     case TC_DLG_ABRT:
2075         dissect_tcap_dlg_abrt(asn1, subtree);
2076         break;
2077     default:
2078         break;
2079     }
2080
2081     /* decode end of sequence */
2082
2083     if (!def_len)
2084     {
2085         dissect_tcap_eoc(asn1, subtree);
2086     }
2087
2088     if (!ext_tag_def_len)
2089     {
2090         dissect_tcap_eoc(asn1, subtree);
2091     }
2092
2093     if (!portion_def_len)
2094     {
2095         dissect_tcap_eoc(asn1, subtree);
2096     }
2097
2098     proto_item_set_len(dlg_item, asn1->offset - dlg_start);
2099
2100     return TC_DS_OK;
2101 }
2102
2103 /* dissect reason */
2104 static int
2105 dissect_tcap_abort_reason(ASN1_SCK *asn1, proto_tree *tcap_tree)
2106 {
2107     guint saved_offset = 0;
2108     guint tag, len;
2109     proto_tree *subtree;
2110     proto_item *item;
2111     gint32 value;
2112     gchar *str = NULL;
2113     gboolean def_len;
2114
2115 #define TC_PABRT_REASON_TAG 0x4a
2116     tag = TC_PABRT_REASON_TAG;
2117     if (check_tcap_tag(asn1, tag))
2118     {
2119         saved_offset = asn1->offset;
2120         item =
2121             proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "PAbort Cause");
2122
2123         subtree = proto_item_add_subtree(item, ett_reason);
2124
2125         tag = -1;
2126         dissect_tcap_tag(asn1, subtree, &tag, "PAbort Cause Tag");
2127         dissect_tcap_len(asn1, subtree, &def_len, &len);
2128
2129         proto_item_set_len(item, (asn1->offset - saved_offset) + len);
2130
2131         saved_offset = asn1->offset;
2132         asn1_int32_value_decode(asn1, len, &value);
2133
2134         switch (value)
2135         {
2136         case 0x00: str = "Unrecognized Message Type"; break;
2137         case 0x01: str = "Unrecognized Transaction ID"; break;
2138         case 0x02: str = "Badly Formatted Transaction Portion"; break;
2139         case 0x03: str = "Incorrect Transaction Portion"; break;
2140         case 0x04: str = "Resource Limitation"; break;
2141         default:
2142             str = "Undefined";
2143             break;
2144         }
2145
2146         proto_tree_add_text(subtree, asn1->tvb,
2147             saved_offset, asn1->offset - saved_offset, "Cause Value %s (%d)",
2148             str, value);
2149     }
2150
2151     return TC_DS_OK;
2152 }
2153
2154 /* dissect each type of message */
2155
2156 static void
2157 dissect_tcap_unidirectional(ASN1_SCK *asn1, proto_tree *tcap_tree)
2158 {
2159
2160     dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
2161
2162     dissect_tcap_components(asn1, tcap_tree);
2163 }
2164
2165 static void
2166 dissect_tcap_begin(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2167 {
2168
2169     dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_SOURCE);
2170
2171     dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
2172
2173     dissect_tcap_components(asn1, tcap_tree);
2174 }
2175
2176 static void
2177 dissect_tcap_continue(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2178 {
2179
2180     dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_SOURCE);
2181
2182     dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_DEST);
2183
2184     dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
2185
2186     dissect_tcap_components(asn1, tcap_tree);
2187
2188 }
2189
2190 static void
2191 dissect_tcap_end(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2192 {
2193
2194     dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_DEST);
2195
2196     dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
2197
2198     dissect_tcap_components(asn1, tcap_tree);
2199 }
2200
2201 static void
2202 dissect_tcap_abort(ASN1_SCK *asn1, proto_tree *tree, proto_item *ti)
2203 {
2204
2205     dissect_tcap_tid(asn1, tree, ti, ST_TID_DEST);
2206
2207     dissect_tcap_abort_reason(asn1, tree);
2208
2209     dissect_tcap_dialog_portion(asn1, tree, NULL);
2210 }
2211
2212 /* Samuel */
2213 static void
2214 dissect_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree)
2215 {
2216     ASN1_SCK asn1;
2217     guint msg_type_tag;
2218     proto_item *ti;
2219     guint offset = 0;
2220     guint saved_offset = 0;
2221     guint len;
2222     gchar *str = NULL;
2223
2224     asn1_open(&asn1, tvb, offset);
2225
2226     asn1_id_decode1(&asn1, &msg_type_tag);
2227
2228     str = match_strval(msg_type_tag, msg_type_strings);
2229
2230     if (str == NULL)
2231     {
2232         proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring");
2233         return;
2234     }
2235
2236     if (check_col(pinfo->cinfo, COL_INFO))
2237     {
2238         col_set_str(pinfo->cinfo, COL_INFO, str);
2239         col_append_str(pinfo->cinfo, COL_INFO, " ");
2240     }
2241
2242     proto_tree_add_uint_hidden(tcap_tree, hf_tcap_ssn, asn1.tvb, offset,
2243         0, pinfo->match_port); /* len -1 is unacceptable */
2244
2245     ti = proto_tree_add_uint(tcap_tree, hf_tcap_message_type, asn1.tvb, offset, asn1.offset - saved_offset,
2246             msg_type_tag);
2247
2248     dissect_tcap_len(&asn1, tcap_tree, &g_tcap_ends_def_len, &len);
2249
2250     switch(msg_type_tag)
2251     {
2252     case ST_MSG_TYP_UNI:
2253         dissect_tcap_unidirectional(&asn1, tcap_tree);
2254         break;
2255     case ST_MSG_TYP_BGN:
2256         dissect_tcap_begin(&asn1, tcap_tree, ti);
2257         break;
2258     case ST_MSG_TYP_CNT:
2259         dissect_tcap_continue(&asn1, tcap_tree, ti);
2260         break;
2261     case ST_MSG_TYP_END:
2262         dissect_tcap_end(&asn1, tcap_tree, ti);
2263         break;
2264     case ST_MSG_TYP_PABT:
2265         dissect_tcap_abort(&asn1, tcap_tree, ti);
2266         break;
2267     default:
2268         proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1,
2269             "Message type not handled, ignoring");
2270         break;
2271     }
2272
2273     if (!g_tcap_ends_def_len)
2274     {
2275         dissect_tcap_eoc(&asn1, tcap_tree);
2276     }
2277
2278     asn1_close(&asn1, &saved_offset);
2279 }
2280
2281 static int
2282 dissect_ansi_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
2283 {
2284     proto_tree *subtree;
2285     guint saved_offset = 0;
2286     guint len;
2287     guint tag;
2288     int ret;
2289     proto_item *cmp_item;
2290     guint cmp_start = asn1->offset;
2291     gboolean def_len;
2292
2293     saved_offset = asn1->offset;
2294     ret = asn1_id_decode1(asn1, &tag);
2295
2296     if (ST_ANSI_CMP_TAG != tag)
2297     {
2298         asn1->offset = saved_offset;
2299         return TC_DS_FAIL;
2300     }
2301
2302     cmp_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Components Portion");
2303
2304     subtree = proto_item_add_subtree(cmp_item, ett_comps_portion);
2305
2306     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
2307         "Component Sequence Identifier");
2308
2309     dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
2310
2311     /* call next dissector */
2312
2313     dissect_ansi_tcap_next_tvb(asn1, len, subtree);
2314
2315     proto_item_set_len(cmp_item, asn1->offset - cmp_start);
2316
2317     return TC_DS_OK;
2318 }
2319
2320 static int
2321 dissect_ansi_tcap_unidirectional(ASN1_SCK *asn1, proto_tree *tcap_tree)
2322 {
2323     guint saved_offset = 0;
2324     guint len;
2325     guint tag;
2326     int ret;
2327     proto_item *trans_item;
2328     guint trans_start = asn1->offset;
2329     gboolean def_len;
2330
2331     saved_offset = asn1->offset;
2332     ret = asn1_id_decode1(asn1, &tag);
2333
2334     if (ST_ANSI_TID_TAG != tag)
2335     {
2336         asn1->offset = saved_offset;
2337         return TC_DS_FAIL;
2338     }
2339
2340     trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
2341
2342     dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
2343
2344     if (len != 0)
2345     {
2346         return TC_DS_FAIL;
2347     }
2348
2349     proto_item_set_len(trans_item, asn1->offset - trans_start);
2350
2351     dissect_ansi_tcap_components(asn1, tcap_tree);
2352
2353     return TC_DS_OK;
2354 }
2355
2356 static int
2357 dissect_ansi_tcap_qwp_qwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2358 {
2359     proto_tree *subtree;
2360     guint saved_offset = 0;
2361     guint len;
2362     guint tag;
2363     int ret;
2364     proto_item *trans_item;
2365     guint trans_start = asn1->offset;
2366     guchar *poctets;
2367     guint32 val;
2368     gboolean def_len;
2369
2370     saved_offset = asn1->offset;
2371     ret = asn1_id_decode1(asn1, &tag);
2372
2373     if (ST_ANSI_TID_TAG != tag)
2374     {
2375         asn1->offset = saved_offset;
2376         return TC_DS_FAIL;
2377     }
2378
2379     trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
2380     subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
2381
2382     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
2383         "Originating Transaction ID Identifier");
2384
2385     dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
2386
2387     if (len != 4)
2388     {
2389         return TC_DS_FAIL;
2390     }
2391
2392     saved_offset = asn1->offset;
2393     ret = asn1_string_value_decode(asn1, len, &poctets);
2394     val = 0;
2395     memcpy(&val, poctets, len);
2396     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
2397     g_free(poctets);
2398
2399     if (check_col(g_pinfo->cinfo, COL_INFO))
2400         col_append_fstr(g_pinfo->cinfo, COL_INFO, "otid(%x) ", val);
2401
2402     proto_item_set_len(trans_item, asn1->offset - trans_start);
2403
2404     dissect_ansi_tcap_components(asn1, tcap_tree);
2405
2406     return TC_DS_OK;
2407 }
2408
2409 static int
2410 dissect_ansi_tcap_abort(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2411 {
2412     proto_tree *subtree;
2413     guint saved_offset = 0;
2414     guint len;
2415     guint tag;
2416     int ret;
2417     proto_item *trans_item;
2418     guint trans_start = asn1->offset;
2419     guchar *poctets;
2420     guint32 val;
2421     gint32 value;
2422     gboolean def_len;
2423     gchar *str;
2424
2425     saved_offset = asn1->offset;
2426     ret = asn1_id_decode1(asn1, &tag);
2427
2428     if (ST_ANSI_TID_TAG != tag)
2429     {
2430         asn1->offset = saved_offset;
2431         return TC_DS_FAIL;
2432     }
2433
2434     trans_item =
2435         proto_tree_add_text(tcap_tree, asn1->tvb,
2436         saved_offset, -1, "Transaction Portion");
2437
2438     subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
2439
2440     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
2441         saved_offset, asn1->offset - saved_offset, tag,
2442         "Responding Transaction ID Identifier");
2443
2444     dissect_tcap_len(asn1, subtree, &def_len, &len);
2445
2446     if (len != 4)
2447     {
2448         return TC_DS_FAIL;
2449     }
2450
2451     saved_offset = asn1->offset;
2452     ret = asn1_string_value_decode(asn1, len, &poctets);
2453
2454     val = 0;
2455     memcpy(&val, poctets, len);
2456     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
2457     g_free(poctets);
2458
2459     if (check_col(g_pinfo->cinfo, COL_INFO))
2460         col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
2461
2462     proto_item_set_len(trans_item, asn1->offset - trans_start);
2463
2464     if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
2465     {
2466         proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1,
2467             "!!! Missing Component Portion !!!");
2468
2469         return TC_DS_FAIL;
2470     }
2471
2472     saved_offset = asn1->offset;
2473     ret = asn1_id_decode1(asn1, &tag);
2474
2475 #define ANSI_TC_PABRT_CAUSE_TAG 0xd7
2476     if (tag == ANSI_TC_PABRT_CAUSE_TAG)
2477     {
2478         trans_item =
2479             proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "P-Abort Portion");
2480
2481         subtree = proto_item_add_subtree(trans_item, ett_dlg_abort);
2482
2483         dissect_tcap_len(asn1, subtree, &def_len, &len);
2484
2485         proto_item_set_len(trans_item, (asn1->offset - saved_offset) + len);
2486
2487         saved_offset = asn1->offset;
2488         asn1_int32_value_decode(asn1, len, &value);
2489
2490         switch (value)
2491         {
2492         case 1: str = "Unrecognized Package Type"; break;
2493         case 2: str = "Incorrect Transaction Portion"; break;
2494         case 3: str = "Badly Structured Transaction Portion"; break;
2495         case 4: str = "Unrecognized Transaction ID"; break;
2496         case 5: str = "Permission to Release"; break;
2497         case 6: str = "Resource Unavailable"; break;
2498         default:
2499             str = "Undefined";
2500             break;
2501         }
2502
2503         proto_tree_add_text(subtree, asn1->tvb,
2504             saved_offset, asn1->offset - saved_offset, "P-Abort Cause Value %s (%d)",
2505             str, value);
2506     }
2507 #define ANSI_TC_UABRT_INFO_TAG 0xd8
2508     else if (tag == ANSI_TC_UABRT_INFO_TAG)
2509     {
2510         trans_item =
2511             proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "U-Abort Portion");
2512
2513         subtree = proto_item_add_subtree(trans_item, ett_dlg_abort);
2514
2515         dissect_tcap_len(asn1, subtree, &def_len, &len);
2516         if (len > 0)
2517         {
2518             dissect_tcap_integer(asn1, subtree, len, "User Abort Information:");
2519         }
2520     }
2521
2522     return TC_DS_OK;
2523 }
2524
2525 static int
2526 dissect_ansi_tcap_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2527 {
2528     proto_tree *subtree;
2529     guint saved_offset = 0;
2530     guint len;
2531     guint tag;
2532     int ret;
2533     proto_item *trans_item;
2534     guint trans_start = asn1->offset;
2535     guchar *poctets;
2536     guint32 val;
2537     gboolean def_len;
2538
2539     saved_offset = asn1->offset;
2540     ret = asn1_id_decode1(asn1, &tag);
2541
2542     if (ST_ANSI_TID_TAG != tag)
2543     {
2544         asn1->offset = saved_offset;
2545         return TC_DS_FAIL;
2546     }
2547
2548     trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
2549     subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
2550
2551     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
2552         "Responding Transaction ID Identifier");
2553
2554     dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
2555
2556     if (len != 4)
2557     {
2558         return TC_DS_FAIL;
2559     }
2560
2561     saved_offset = asn1->offset;
2562     ret = asn1_string_value_decode(asn1, len, &poctets);
2563     val = 0;
2564     memcpy(&val, poctets, len);
2565     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
2566     g_free(poctets);
2567
2568     if (check_col(g_pinfo->cinfo, COL_INFO))
2569         col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
2570
2571     proto_item_set_len(trans_item, asn1->offset - trans_start);
2572
2573     dissect_ansi_tcap_components(asn1, tcap_tree);
2574
2575     return TC_DS_OK;
2576 }
2577
2578 static int
2579 dissect_ansi_tcap_cwp_cwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
2580 {
2581     proto_tree *subtree;
2582     guint saved_offset = 0;
2583     guint len;
2584     guint tag;
2585     int ret;
2586     proto_item *trans_item;
2587     guint trans_start = asn1->offset;
2588     guchar *poctets;
2589     guint32 val;
2590     gboolean def_len;
2591
2592     saved_offset = asn1->offset;
2593     ret = asn1_id_decode1(asn1, &tag);
2594
2595     if (ST_ANSI_TID_TAG != tag)
2596     {
2597         asn1->offset = saved_offset;
2598         return TC_DS_FAIL;
2599     }
2600
2601     trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
2602     subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
2603
2604     proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
2605         "Transaction ID Identifier");
2606
2607     dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
2608
2609     if (len != 8)
2610     {
2611         return TC_DS_FAIL;
2612     }
2613
2614     saved_offset = asn1->offset;
2615     ret = asn1_string_value_decode(asn1, 4, &poctets);
2616     val = 0;
2617     memcpy(&val, poctets, 4);
2618     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
2619     g_free(poctets);
2620
2621     if (check_col(g_pinfo->cinfo, COL_INFO))
2622         col_append_fstr(g_pinfo->cinfo, COL_INFO, "otid(%x) ", val);
2623
2624     saved_offset = asn1->offset;
2625     ret = asn1_string_value_decode(asn1, 4, &poctets);
2626     val = 0;
2627     memcpy(&val, poctets, 4);
2628     ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
2629     g_free(poctets);
2630
2631     if (check_col(g_pinfo->cinfo, COL_INFO))
2632         col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
2633
2634     proto_item_set_len(trans_item, asn1->offset - trans_start);
2635
2636     dissect_ansi_tcap_components(asn1, tcap_tree);
2637
2638     return TC_DS_OK;
2639 }
2640
2641 static void
2642 dissect_ansi_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree)
2643 {
2644     ASN1_SCK asn1;
2645     guint msg_type_tag;
2646     proto_item *ti;
2647     guint offset = 0;
2648     guint saved_offset = 0;
2649     guint len;
2650     gchar *str = NULL;
2651     gboolean def_len;
2652
2653     asn1_open(&asn1, tvb, offset);
2654
2655     asn1_id_decode1(&asn1, &msg_type_tag);
2656
2657     str = match_strval(msg_type_tag, ansi_msg_type_strings);
2658
2659     if (str == NULL)
2660     {
2661         proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring");
2662         return;
2663     }
2664
2665     if (check_col(pinfo->cinfo, COL_INFO))
2666     {
2667         col_set_str(pinfo->cinfo, COL_INFO, str);
2668         col_append_str(pinfo->cinfo, COL_INFO, " ");
2669     }
2670
2671     proto_tree_add_uint_hidden(tcap_tree, hf_tcap_ssn, asn1.tvb, offset,
2672         0, pinfo->match_port); /* len -1 is unacceptable */
2673
2674     ti = proto_tree_add_uint(tcap_tree, hf_ansi_tcap_message_type, asn1.tvb, offset, asn1.offset - saved_offset,
2675             msg_type_tag);
2676
2677     dissect_tcap_len(&asn1, tcap_tree, &def_len, &len);
2678
2679     switch(msg_type_tag)
2680     {
2681     case ANSI_ST_MSG_TYP_UNI:
2682         dissect_ansi_tcap_unidirectional(&asn1, tcap_tree);
2683         break;
2684     case ANSI_ST_MSG_TYP_QWP:
2685         dissect_ansi_tcap_qwp_qwop(&asn1, tcap_tree, ti);
2686         break;
2687     case ANSI_ST_MSG_TYP_QWOP:
2688         dissect_ansi_tcap_qwp_qwop(&asn1, tcap_tree, ti);
2689         break;
2690     case ANSI_ST_MSG_TYP_RSP:
2691         dissect_ansi_tcap_rsp(&asn1, tcap_tree, ti);
2692         break;
2693     case ANSI_ST_MSG_TYP_CWP:
2694         dissect_ansi_tcap_cwp_cwop(&asn1, tcap_tree, ti);
2695         break;
2696     case ANSI_ST_MSG_TYP_CWOP:
2697         dissect_ansi_tcap_cwp_cwop(&asn1, tcap_tree, ti);
2698         break;
2699     case ANSI_ST_MSG_TYP_ABT:
2700         dissect_ansi_tcap_abort(&asn1, tcap_tree, ti);
2701         break;
2702     default:
2703         proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1,
2704             "Message type not handled, ignoring");
2705         break;
2706     }
2707
2708     asn1_close(&asn1, &saved_offset);
2709 }
2710
2711 /* Code to actually dissect the packets */
2712 static void
2713 dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2714 {
2715     proto_item *ti;
2716     proto_tree *tcap_tree;
2717
2718     g_pinfo = pinfo;
2719
2720     if (check_col(pinfo->cinfo, COL_PROTOCOL))
2721         col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCAP");
2722
2723     /* In the interest of speed, if "tree" is NULL, don't do any
2724      * work not necessary to generate protocol tree items.
2725      */
2726     if (tree)
2727     {
2728         ti = proto_tree_add_item(tree, proto_tcap, tvb, 0, -1, FALSE);
2729         tcap_tree = proto_item_add_subtree(ti, ett_tcap);
2730         g_tcap_tree = tree;
2731
2732         if (tcap_standard == ITU_TCAP_STANDARD)
2733         {
2734             dissect_tcap_message(tvb, pinfo, tcap_tree);
2735         }
2736         else
2737         {
2738             dissect_ansi_tcap_message(tvb, pinfo, tcap_tree);
2739         }
2740     }
2741 }
2742
2743
2744 /* Register the protocol with Ethereal */
2745
2746 /* this format is require because a script is used to build the C function
2747    that calls all the protocol registration.
2748 */
2749 void
2750 proto_register_tcap(void)
2751 {
2752
2753 /* Setup list of header fields  See Section 1.6.1 for details*/
2754     static hf_register_info hf[] = {
2755         /*{ &hf_tcap_FIELDABBREV,
2756                 { "FIELDNAME",           "PROTOABBREV.FIELDABBREV",
2757                 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
2758                 "FIELDDESCR" }
2759         },*/
2760         { &hf_tcap_tag,
2761                 { "Tag",           "tcap.msgtype",
2762                 FT_UINT8, BASE_HEX, NULL, 0,
2763                 "", HFILL }
2764         },
2765         { &hf_tcap_length,
2766                 { "Length", "tcap.len",
2767                 FT_UINT8, BASE_HEX, NULL, 0,
2768                 "", HFILL }
2769         },
2770         { &hf_tcap_id,
2771                 { "Value", "tcap.id",
2772                 FT_UINT8, BASE_HEX, NULL, 0,
2773                 "", HFILL }
2774         },
2775         { &hf_tcap_message_type,
2776                 { "Message Type", "tcap.msgtype",
2777                 FT_UINT8, BASE_HEX, VALS(msg_type_strings), 0,
2778                 "", HFILL }
2779         },
2780         { &hf_ansi_tcap_message_type,
2781                 { "Message Type", "tcap.msgtype",
2782                 FT_UINT8, BASE_HEX, VALS(ansi_msg_type_strings), 0,
2783                 "", HFILL }
2784         },
2785         { &hf_tcap_tid,
2786                 { "Transaction Id", "tcap.tid",
2787                 FT_UINT32, BASE_DEC, VALS(tid_strings), 0,
2788                 "", HFILL }
2789         },
2790         { &hf_tcap_ssn,
2791                 { "Called or Calling SubSystem Number", "tcap.ssn",
2792                 FT_UINT8, BASE_DEC, 0x0, 0x0,
2793                 "", HFILL }
2794         },
2795         { &hf_tcap_dlg_type,
2796                 { "Dialogue Type", "tcap.dlgtype",
2797                 FT_UINT8, BASE_HEX, VALS(dlg_type_strings), 0,
2798                 "", HFILL }
2799         },
2800         { &hf_tcap_app_con_name,
2801                 { "Application Context Name", "tcap.dlg.appconname",
2802                 FT_BYTES, BASE_HEX, 0, 0,
2803                 "", HFILL }
2804         },
2805         { &hf_tcap_bytes,
2806                 { "Binary Data", "tcap.data",
2807                 FT_BYTES, BASE_HEX, 0, 0,
2808                 "", HFILL }
2809         },
2810         { &hf_tcap_int,
2811                 { "Integer Data", "tcap.data",
2812                 FT_INT32, BASE_DEC, 0, 0,
2813                 "", HFILL }
2814         },
2815     };
2816
2817 /* Setup protocol subtree array */
2818     static gint *ett[] = {
2819         &ett_tcap,
2820         &ett_otid,
2821         &ett_dtid,
2822         &ett_dlg_portion,
2823         &ett_comps_portion,
2824         &ett_reason,
2825         &ett_dlg_req,
2826         &ett_dlg_rsp,
2827         &ett_dlg_abort,
2828         &ett_component,
2829         &ett_error,
2830         &ett_problem,
2831         &ett_params,
2832         &ett_param,
2833     };
2834
2835     static enum_val_t tcap_options[] = {
2836         { "ITU",  ITU_TCAP_STANDARD },
2837         { "ANSI", ANSI_TCAP_STANDARD },
2838         { NULL, 0 }
2839     };
2840
2841     module_t *tcap_module;
2842
2843 /* Register the protocol name and description */
2844     proto_tcap = proto_register_protocol("Transaction Capabilities Application Part",
2845         "TCAP", "tcap");
2846
2847 /* Required function calls to register the header fields and subtrees used */
2848     proto_register_field_array(proto_tcap, hf, array_length(hf));
2849     proto_register_subtree_array(ett, array_length(ett));
2850
2851     tcap_module = prefs_register_protocol(proto_tcap, NULL);
2852
2853     prefs_register_enum_preference(tcap_module, "standard", "TCAP standard",
2854         "The SS7 standard used in TCAP packets",
2855         (gint *)&tcap_standard, tcap_options, FALSE);
2856
2857     prefs_register_bool_preference(tcap_module, "lock_info_col", "Lock Info column",
2858         "Always show TCAP in Info column",
2859         &lock_info_col);
2860
2861     /* we will fake a ssn subfield which has the same value obtained from sccp */
2862     tcap_itu_ssn_dissector_table = register_dissector_table("tcap.itu_ssn", "ITU TCAP SSN", FT_UINT8, BASE_DEC);
2863     tcap_ansi_ssn_dissector_table = register_dissector_table("tcap.ansi_ssn", "ANSI TCAP SSN", FT_UINT8, BASE_DEC);
2864 }
2865
2866
2867 /* If this dissector uses sub-dissector registration add a registration routine.
2868    This format is required because a script is used to find these routines and
2869    create the code that calls these routines.
2870 */
2871 void
2872 proto_reg_handoff_tcap(void)
2873 {
2874     dissector_handle_t tcap_handle;
2875
2876     tcap_handle = create_dissector_handle(dissect_tcap,
2877         proto_tcap);
2878
2879     dissector_add("sccp.ssn", 5, tcap_handle); /* MAP*/
2880     dissector_add("sccp.ssn", 6, tcap_handle); /* HLR*/
2881     dissector_add("sccp.ssn", 7, tcap_handle); /* VLR */
2882     dissector_add("sccp.ssn", 8, tcap_handle); /* MSC */
2883     dissector_add("sccp.ssn", 9, tcap_handle); /* EIR */
2884     dissector_add("sccp.ssn", 10, tcap_handle); /* EIR */
2885     dissector_add("sccp.ssn", 11, tcap_handle); /* SMS/MC */
2886     dissector_add("sccp.ssn", 12, tcap_handle); /* IS41 OTAF */
2887
2888     dissector_add("sua.ssn", 5, tcap_handle); /* MAP*/
2889     dissector_add("sua.ssn", 6, tcap_handle); /* HLR*/
2890     dissector_add("sua.ssn", 7, tcap_handle); /* VLR */
2891     dissector_add("sua.ssn", 8, tcap_handle); /* MSC */
2892     dissector_add("sua.ssn", 9, tcap_handle); /* EIR */
2893     dissector_add("sua.ssn", 10, tcap_handle); /* EIR */
2894     dissector_add("sua.ssn", 11, tcap_handle); /* SMS/MC */
2895     dissector_add("sua.ssn", 12, tcap_handle); /* IS41 OTAF */
2896
2897     data_handle = find_dissector("data");
2898 }