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