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