diff options
author | Guy Harris <guy@alum.mit.edu> | 2004-02-20 10:43:12 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2004-02-20 10:43:12 +0000 |
commit | 8b29cc684bc8942a181a2902fb48c22ae0ce0c67 (patch) | |
tree | 258cde616f2c74ac18e1856e7d5fa30cd6ae3fb1 /packet-tcap.c | |
parent | cea8bc380172974409bc95746605b727c19849bf (diff) |
From Michael Lum:
Corrected many miscellaneous problems with nested indefinite
length parameters.
Now supports multiple Components.
svn path=/trunk/; revision=10125
Diffstat (limited to 'packet-tcap.c')
-rw-r--r-- | packet-tcap.c | 613 |
1 files changed, 356 insertions, 257 deletions
diff --git a/packet-tcap.c b/packet-tcap.c index b596da80c3..fe073b30f1 100644 --- a/packet-tcap.c +++ b/packet-tcap.c @@ -9,7 +9,7 @@ * * (append your name here for newer version) * - * $Id: packet-tcap.c,v 1.6 2004/01/23 01:51:38 jmayer Exp $ + * $Id: packet-tcap.c,v 1.7 2004/02/20 10:43:12 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -75,7 +75,6 @@ static gboolean g_tcap_ends_def_len = FALSE; static int proto_tcap = -1; static int hf_tcap_message_type = -1; static int hf_ansi_tcap_message_type = -1; -static int hf_tcap_none = -1; static int hf_tcap_tag = -1; static int hf_tcap_length = -1; static int hf_tcap_bytes = -1; @@ -95,7 +94,7 @@ static gint ett_dlg_portion = -1; static gint ett_dlg_req = -1; static gint ett_dlg_rsp = -1; static gint ett_dlg_abort = -1; -static gint ett_cmp_portion = -1; +static gint ett_comps_portion = -1; static gint ett_reason = -1; static gint ett_component = -1; static gint ett_problem = -1; @@ -196,6 +195,38 @@ static const value_string dlg_type_strings[] = { #define TC_DS_FAIL 0 +static int +find_eoc(ASN1_SCK *asn1) +{ + guint saved_offset; + guint tag; + guint len; + gboolean def_len; + + saved_offset = asn1->offset; + + while (!asn1_eoc(asn1, -1)) + { + asn1_id_decode1(asn1, &tag); + asn1_length_decode(asn1, &def_len, &len); + + if (def_len) + { + asn1->offset += len; + } + else + { + asn1->offset += find_eoc(asn1); + asn1_eoc_decode(asn1, -1); + } + } + + len = asn1->offset - saved_offset; + asn1->offset = saved_offset; + + return(len); +} + /* dissect length */ static int dissect_tcap_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len) @@ -214,7 +245,7 @@ dissect_tcap_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len } else { - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(tree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Length: Indefinite"); } @@ -240,7 +271,7 @@ dissect_tcap_eoc(ASN1_SCK *asn1, proto_tree *tree) ret = asn1_eoc_decode(asn1, -1); - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(tree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "End of Contents"); return TC_DS_OK; @@ -322,12 +353,12 @@ dissect_tcap_tid(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti, int type org_offset = asn1->offset; if ( ST_TID_SOURCE == type) { - tid_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, asn1->offset, -1, "Source Transaction ID"); + tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Source Transaction ID"); subtree = proto_item_add_subtree(tid_item, ett_otid); } else { - tid_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, asn1->offset, -1, "Destination Transaction ID"); + tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Destination Transaction ID"); subtree = proto_item_add_subtree(tid_item, ett_dtid); } @@ -450,29 +481,33 @@ dissect_tcap_opr_code(ASN1_SCK *asn1, proto_tree *tree) { dissect_tcap_len(asn1, tree, &def_len, &len); - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, asn1->offset, len, "Operation Code"); + proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code"); asn1->offset += len; } } static int -dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree) +dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { - guint off_tree[100], saved_offset, len_offset; - int num_seq; + guint orig_offset, saved_offset, len_offset; guint tag, len; gboolean def_len; - proto_item *item_tree[100], *item; - proto_tree *seq_tree[100], *use_tree, *subtree; + proto_item *item; + proto_tree *subtree; - num_seq = 0; - use_tree = tree; + orig_offset = asn1->offset; #define TC_INVALID_TAG 0 while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && (!check_tcap_tag(asn1, 0))) { + if ((exp_len != 0) && + ((asn1->offset - orig_offset) >= exp_len)) + { + break; + } + saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); len_offset = asn1->offset; @@ -481,88 +516,71 @@ dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree) if (tag == TC_SEQ_TAG) { item = - proto_tree_add_none_format(use_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Sequence"); + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Sequence"); subtree = proto_item_add_subtree(item, ett_params); proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, len_offset - saved_offset, tag, "Sequence Tag"); - if (!def_len) + if (def_len) { - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, - len_offset, asn1->offset - len_offset, "Length: Indefinite"); - - seq_tree[num_seq] = subtree; - item_tree[num_seq] = item; - off_tree[num_seq] = saved_offset; - num_seq++; + proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb, + len_offset, asn1->offset - len_offset, len); } else { - proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb, - len_offset, asn1->offset - len_offset, len); + proto_tree_add_text(subtree, asn1->tvb, + len_offset, asn1->offset - len_offset, "Length: Indefinite"); - proto_item_set_len(item, (asn1->offset - saved_offset) + len); + len = find_eoc(asn1); } - use_tree = subtree; - continue; - } + proto_item_set_len(item, + (asn1->offset - saved_offset) + len + + (def_len ? 0 : TC_EOC_LEN)); - if (!def_len) - { - proto_tree_add_uint_format(use_tree, hf_tcap_tag, asn1->tvb, - saved_offset, len_offset - saved_offset, tag, "Parameter Tag"); - proto_tree_add_none_format(use_tree, hf_tcap_none, asn1->tvb, - len_offset, asn1->offset - len_offset, "Length: Indefinite"); + dissect_tcap_param(asn1, subtree, len); - seq_tree[num_seq] = use_tree; - item_tree[num_seq] = NULL; - num_seq++; + if (!def_len) + { + dissect_tcap_eoc(asn1, subtree); + } continue; } - else - { - item = - proto_tree_add_none_format(use_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Parameter"); - subtree = proto_item_add_subtree(item, ett_param); - - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + if (!def_len) + { + proto_tree_add_uint_format(tree, hf_tcap_tag, asn1->tvb, saved_offset, len_offset - saved_offset, tag, "Parameter Tag"); - proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb, - len_offset, asn1->offset - len_offset, len); + proto_tree_add_text(tree, asn1->tvb, + len_offset, asn1->offset - len_offset, "Length: Indefinite"); - proto_item_set_len(item, (asn1->offset - saved_offset) + len); + len = find_eoc(asn1); - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, - asn1->offset, len, "Parameter Data"); + dissect_tcap_param(asn1, tree, len); - asn1->offset += len; + dissect_tcap_eoc(asn1, tree); + continue; } - if (tvb_length_remaining(asn1->tvb, asn1->offset) <=0) break; + item = + proto_tree_add_text(tree, asn1->tvb, + saved_offset, (asn1->offset - saved_offset) + len, "Parameter"); - while ((num_seq > 0) && - asn1_eoc(asn1, -1)) - { - saved_offset = asn1->offset; - asn1_eoc_decode(asn1, -1); + subtree = proto_item_add_subtree(item, ett_param); - proto_tree_add_none_format(seq_tree[num_seq-1], hf_tcap_none, asn1->tvb, - saved_offset, asn1->offset - saved_offset, "End of Contents"); + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + saved_offset, len_offset - saved_offset, tag, "Parameter Tag"); - if (item_tree[num_seq-1] != NULL) - { - proto_item_set_len(item_tree[num_seq-1], asn1->offset - off_tree[num_seq-1]); - } + proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb, + len_offset, asn1->offset - len_offset, len); - num_seq--; - } + proto_tree_add_text(subtree, asn1->tvb, + asn1->offset, len, "Parameter Data"); + + asn1->offset += len; } return TC_DS_OK; @@ -582,8 +600,7 @@ dissect_tcap_component(ASN1_SCK *asn1, proto_tree *tree, guint *len_p) asn1_id_decode1(asn1, &tag); item = - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Component ID"); + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component ID"); subtree = proto_item_add_subtree(item, ett_component); @@ -601,8 +618,8 @@ dissect_tcap_component(ASN1_SCK *asn1, proto_tree *tree, guint *len_p) static void dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree) { - guint orig_offset, saved_offset = 0; - guint len, tag_len; + guint orig_offset, saved_offset, len_offset; + guint len; guint tag; proto_tree *subtree; proto_item *item = NULL; @@ -615,23 +632,35 @@ dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree) orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); - tag_len = asn1->offset - saved_offset; + + len_offset = asn1->offset; + asn1_length_decode(asn1, &def_len, &len); item = - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Problem Code"); + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code"); subtree = proto_item_add_subtree(item, ett_problem); - dissect_tcap_len(asn1, subtree, &def_len, &len); - proto_item_set_len(item, (asn1->offset - saved_offset) + len); + if (!def_len) + { + len = find_eoc(asn1); + } + + proto_item_set_len(item, (asn1->offset - saved_offset) + len + + (def_len ? 0 : TC_EOC_LEN)); if (len != 1) { - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Unknown encoding of Problem Code"); asn1->offset += len; + + if (!def_len) + { + asn1_eoc_decode(asn1, -1); + } + return; } @@ -705,10 +734,21 @@ dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree) } proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, - orig_offset, tag_len, tag, type_str); + orig_offset, len_offset - orig_offset, tag, type_str); - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, - saved_offset, 1, "Problem Specifier %s", str); + if (def_len) + { + proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb, + len_offset, saved_offset - len_offset, len); + } + else + { + proto_tree_add_text(subtree, asn1->tvb, + len_offset, saved_offset - len_offset, "Length: Indefinite"); + } + + proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1, + "Problem Specifier %s", str); } @@ -739,7 +779,7 @@ dissect_ansi_opr_code(ASN1_SCK *asn1, proto_tree *tree) { dissect_tcap_len(asn1, tree, &def_len, &len); - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, asn1->offset, len, "Operation Code"); + proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code"); asn1->offset += len; } @@ -774,8 +814,7 @@ dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree) asn1_id_decode1(asn1, &tag); item = - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Problem Code"); + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code"); subtree = proto_item_add_subtree(item, ett_problem); @@ -787,7 +826,7 @@ dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree) if (len != 2) { - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Unknown encoding of Problem Code"); asn1->offset += len; @@ -881,10 +920,10 @@ dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree) if (spec == 255) { str = "Reserved"; } else if (spec == 0) { str = "Not used"; } - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1, "Problem Type %s", type_str); - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(subtree, asn1->tvb, saved_offset + 1, 1, "Problem Specifier %s", str); } @@ -921,7 +960,7 @@ dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree) asn1_id_decode1(asn1, &tag); item = - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "TCAP Error Code"); subtree = proto_item_add_subtree(item, ett_error); @@ -932,8 +971,7 @@ dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree) dissect_tcap_len(asn1, subtree, &def_len, &len); proto_item_set_len(item, (asn1->offset - saved_offset) + len); - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, - asn1->offset, len, "Error Code"); + proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Error Code"); asn1->offset += len; } @@ -966,7 +1004,7 @@ dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree) { dissect_tcap_len(asn1, tree, &def_len, &len); - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, asn1->offset, len, "Parameter Data"); + proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data"); asn1->offset += len; } @@ -1075,27 +1113,28 @@ static void dissect_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree) { proto_tree *subtree; - guint saved_offset = 0; + guint orig_offset, saved_offset; guint len; guint tag; int ret; proto_item *item; - guint start = asn1->offset; gboolean def_len; + orig_offset = asn1->offset; saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); - item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components"); + + item = + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); + subtree = proto_item_add_subtree(item, ett_component); - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, - tag, "Invoke Type Tag"); + + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + saved_offset, asn1->offset - saved_offset, tag, "Invoke Type Tag"); dissect_tcap_len(asn1, subtree, &def_len, &len); - if (def_len) - { - proto_item_set_len(item, (asn1->offset - start) + len); - } + saved_offset = asn1->offset; dissect_tcap_invokeId(asn1, subtree); @@ -1103,84 +1142,150 @@ dissect_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree) dissect_tcap_opr_code(asn1, subtree); - dissect_tcap_param(asn1, subtree); + if (def_len) + { + len -= asn1->offset - saved_offset; + } + else + { + len = find_eoc(asn1); + } + + dissect_tcap_param(asn1, subtree, len); if (!def_len) { dissect_tcap_eoc(asn1, subtree); } + + proto_item_set_len(item, asn1->offset - orig_offset); } static void dissect_tcap_rr(ASN1_SCK *asn1, proto_tree *tree, gchar *str) { guint tag, len, comp_len; - guint saved_offset; - proto_item *item; - proto_tree *subtree; + guint orig_offset, saved_offset, len_offset; + proto_item *seq_item, *item; + proto_tree *seq_subtree, *subtree; gboolean def_len; gboolean comp_def_len; tag = -1; + orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); - item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components"); + + item = + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); + subtree = proto_item_add_subtree(item, ett_component); - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, - tag, str); + + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + saved_offset, asn1->offset - saved_offset, tag, str); dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len); - if (comp_def_len) - { - proto_item_set_len(item, (asn1->offset - saved_offset) + comp_len); - } + saved_offset = asn1->offset; dissect_tcap_invokeId(asn1, subtree); - tag = TC_SEQ_TAG; - if (check_tcap_tag(asn1, TC_SEQ_TAG)) + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) { - tag = -1; - dissect_tcap_tag(asn1, subtree, &tag, "Sequence Tag"); - dissect_tcap_len(asn1, subtree, &def_len, &len); + proto_item_set_len(item, asn1->offset - orig_offset); + + return; } - dissect_tcap_opr_code(asn1, subtree); + saved_offset = asn1->offset; + + tag = -1; + asn1_id_decode1(asn1, &tag); + + if (tag == TC_SEQ_TAG) + { + len_offset = asn1->offset; + asn1_length_decode(asn1, &def_len, &len); - dissect_tcap_param(asn1, subtree); + seq_item = + proto_tree_add_text(subtree, asn1->tvb, saved_offset, -1, "Sequence"); + + seq_subtree = proto_item_add_subtree(seq_item, ett_params); + + proto_tree_add_uint_format(seq_subtree, hf_tcap_tag, asn1->tvb, + saved_offset, len_offset - saved_offset, tag, "Sequence Tag"); + + if (def_len) + { + proto_tree_add_uint(seq_subtree, hf_tcap_length, asn1->tvb, + len_offset, asn1->offset - len_offset, len); + } + else + { + proto_tree_add_text(seq_subtree, asn1->tvb, + len_offset, asn1->offset - len_offset, "Length: Indefinite"); + + len = find_eoc(asn1); + } + + proto_item_set_len(seq_item, + (asn1->offset - saved_offset) + len + + (def_len ? 0 : TC_EOC_LEN)); + + saved_offset = asn1->offset; + + dissect_tcap_opr_code(asn1, seq_subtree); + + len -= asn1->offset - saved_offset; + + dissect_tcap_param(asn1, seq_subtree, len); + + if (!def_len) + { + dissect_tcap_eoc(asn1, seq_subtree); + } + } if (!comp_def_len) { dissect_tcap_eoc(asn1, subtree); } + + proto_item_set_len(item, asn1->offset - orig_offset); } static int dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree) { guint tag, len, comp_len; - guint saved_offset; + guint orig_offset, saved_offset; proto_item *item; proto_tree *subtree; - gboolean def_len; + gboolean comp_def_len, def_len; tag = -1; + orig_offset = asn1->offset; saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); - item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components"); + + item = + proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); + subtree = proto_item_add_subtree(item, ett_component); - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, - tag, "Return Error Type Tag"); - dissect_tcap_len(asn1, subtree, &def_len, &comp_len); + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + saved_offset, asn1->offset - saved_offset, + tag, "Return Error Type Tag"); - if (def_len) + dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len); + + if (!comp_def_len) { - proto_item_set_len(item, (asn1->offset - saved_offset) + comp_len); + comp_len = find_eoc(asn1); } saved_offset = asn1->offset; + dissect_tcap_invokeId(asn1, subtree); #define TC_LOCAL_ERR_CODE_TAG 0x2 @@ -1197,23 +1302,33 @@ dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree) } else { - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, asn1->offset, comp_len, + proto_tree_add_text(subtree, asn1->tvb, asn1->offset, comp_len, "Unknown Error Code"); - asn1->offset += (comp_len - (asn1->offset - saved_offset)); + asn1->offset += comp_len; + + if (!comp_def_len) + { + dissect_tcap_eoc(asn1, subtree); + } + + proto_item_set_len(item, asn1->offset - orig_offset); + return(TC_DS_OK); } dissect_tcap_len(asn1, subtree, &def_len, &len); dissect_tcap_integer(asn1, subtree, len, "Error Code:"); - dissect_tcap_param(asn1, subtree); + dissect_tcap_param(asn1, subtree, comp_len - (asn1->offset - saved_offset)); - if (!def_len) + if (!comp_def_len) { dissect_tcap_eoc(asn1, subtree); } + proto_item_set_len(item, asn1->offset - orig_offset); + return(TC_DS_OK); } @@ -1231,28 +1346,26 @@ dissect_tcap_reject(ASN1_SCK *asn1, proto_tree *tree) saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); - item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components"); + item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component"); subtree = proto_item_add_subtree(item, ett_component); - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, - tag, "Reject Type Tag"); + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, + saved_offset, asn1->offset - saved_offset, + tag, "Reject Type Tag"); dissect_tcap_len(asn1, subtree, &def_len, &comp_len); - if (def_len) - { - proto_item_set_len(item, (asn1->offset - saved_offset) + comp_len); - } - dissect_tcap_invokeId(asn1, subtree); - dissect_tcap_problem(asn1, tree); + dissect_tcap_problem(asn1, subtree); if (!def_len) { dissect_tcap_eoc(asn1, subtree); } + + proto_item_set_len(item, asn1->offset - saved_offset); } static void @@ -1301,7 +1414,7 @@ dissect_ansi_tcap_next_tvb(ASN1_SCK *asn1, guint len, proto_tree *tree) if (flag != FALSE) { - item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components"); + item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Components"); subtree = proto_item_add_subtree(item, ett_component); switch (tag) @@ -1367,72 +1480,25 @@ dissect_ansi_tcap_next_tvb(ASN1_SCK *asn1, guint len, proto_tree *tree) } } -static void -dissect_tcap_next_tvb(ASN1_SCK *asn1, guint len, proto_tree *tree) -{ - tvbuff_t *next_tvb; - guint saved_offset; - int ret; - guint tag; - - if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO); - - next_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len); - - /* process components data */ - if (dissector_try_port(tcap_itu_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree)) - { - asn1->offset += len; - } - else - { - saved_offset = asn1->offset; - ret = asn1_id_decode1(asn1, &tag); - asn1->offset = saved_offset; - - switch (tag) - { - case TC_INVOKE : - dissect_tcap_invoke(asn1, tree); - break; - case TC_RRL : - dissect_tcap_rr(asn1, tree, "Return Result(Last) Type Tag"); - break; - case TC_RE : - dissect_tcap_re(asn1, tree); - break; - case TC_REJECT : - dissect_tcap_reject(asn1, tree); - break; - case TC_RRN : - /* same definition as RRL */ - dissect_tcap_rr(asn1, tree, "Return Result(Not Last) Type Tag"); - break; - default: - /* treat it as raw data */ - call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree); - break; - } - } -} - static int dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree) { - proto_tree *subtree; - guint saved_offset = 0; - guint len, next_tvb_len; - guint tag; - int ret; - proto_item *cmp_item; - guint cmp_start = asn1->offset; - gboolean def_len; + proto_tree *subtree; + proto_item *comps_item; + guint saved_offset, comps_start; + guint len, comp_len; + gint keep_len; + gboolean comps_def_len, def_len; + guint tag; + int ret; + tvbuff_t *next_tvb; if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) { return TC_DS_FAIL; } + comps_start = asn1->offset; saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); @@ -1442,49 +1508,91 @@ dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree) return TC_DS_FAIL; } - cmp_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components Portion"); - subtree = proto_item_add_subtree(cmp_item, ett_cmp_portion); + comps_item = + proto_tree_add_text(tcap_tree, asn1->tvb, + saved_offset, -1, "Components Portion"); - proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag, - "Component Portion Tag"); + subtree = proto_item_add_subtree(comps_item, ett_comps_portion); - dissect_tcap_len(asn1, subtree, &def_len, &len); + proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, + asn1->offset - saved_offset, tag, "Component Portion Tag"); - if (def_len) + dissect_tcap_len(asn1, subtree, &comps_def_len, &len); + + if (comps_def_len) { - proto_item_set_len(cmp_item, (asn1->offset - cmp_start) + len); + proto_item_set_len(comps_item, (asn1->offset - comps_start) + len); } - /* call next dissector */ + if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO); - if (!def_len) - { - /* - * take remaining length minus the EOC for the indefinite - * component length - */ - next_tvb_len = - tvb_length_remaining(asn1->tvb, asn1->offset) - TC_EOC_LEN; - } - else + /* call next dissector for EACH component */ + + keep_len = + (comps_def_len ? 0 : TC_EOC_LEN) + + (g_tcap_ends_def_len ? 0 : TC_EOC_LEN); + + while (tvb_length_remaining(asn1->tvb, asn1->offset) > keep_len) { - next_tvb_len = len; - } + /* peek at tag and length */ + saved_offset = asn1->offset; + ret = asn1_id_decode1(asn1, &tag); - /* - * take length minus the EOC for the indefinite - * transaction message length - */ - next_tvb_len -= g_tcap_ends_def_len ? 0 : TC_EOC_LEN; + comp_len = 0; + def_len = FALSE; + ret = asn1_length_decode(asn1, &def_len, &comp_len); - dissect_tcap_next_tvb(asn1, next_tvb_len, subtree); + if (def_len) + { + comp_len += (asn1->offset - saved_offset); + } + else + { + comp_len = (asn1->offset - saved_offset) + find_eoc(asn1) + TC_EOC_LEN; + } - if (!def_len) + next_tvb = tvb_new_subset(asn1->tvb, saved_offset, comp_len, comp_len); + asn1->offset = saved_offset; + + /* process component data */ + if (dissector_try_port(tcap_itu_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree)) + { + asn1->offset += comp_len; + } + else + { + switch (tag) + { + case TC_INVOKE : + dissect_tcap_invoke(asn1, subtree); + break; + case TC_RRL : + dissect_tcap_rr(asn1, subtree, "Return Result(Last) Type Tag"); + break; + case TC_RE : + dissect_tcap_re(asn1, subtree); + break; + case TC_REJECT : + dissect_tcap_reject(asn1, subtree); + break; + case TC_RRN : + /* same definition as RRL */ + dissect_tcap_rr(asn1, subtree, "Return Result(Not Last) Type Tag"); + break; + default: + /* treat it as raw data */ + call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree); + break; + } + } + } + + if (!comps_def_len) { dissect_tcap_eoc(asn1, subtree); - } - proto_item_set_len(cmp_item, asn1->offset - cmp_start); + proto_item_set_len(comps_item, asn1->offset - comps_start); + } return TC_DS_OK; } @@ -1625,7 +1733,7 @@ dissect_tcap_dlg_result_src_diag(ASN1_SCK *asn1, proto_tree *tree) } else { - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, asn1->offset, len, + proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Unknown Result Source Diagnostic"); asn1->offset += len; @@ -1707,7 +1815,7 @@ dissect_tcap_dlg_user_info(ASN1_SCK *asn1, proto_tree *tree) dissect_tcap_len(asn1, tree, &def_len, &len); } - proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, asn1->offset, len, "Parameter Data"); + proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data"); asn1->offset += len; if (!user_info_def_len) @@ -1735,7 +1843,7 @@ dissect_tcap_dlg_req(ASN1_SCK *asn1, proto_tree *tcap_tree) /* dissect dialog portion */ saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); - req_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Dialogue Request"); + req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Request"); subtree = proto_item_add_subtree(req_item, ett_dlg_req); proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag); @@ -1775,7 +1883,7 @@ dissect_tcap_dlg_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree) /* dissect dialog portion */ saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); - req_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Dialogue Response"); + req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Response"); subtree = proto_item_add_subtree(req_item, ett_dlg_rsp); proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag); @@ -1820,7 +1928,7 @@ dissect_tcap_dlg_abrt(ASN1_SCK *asn1, proto_tree *tree) /* dissect dialog pabort portion */ saved_offset = asn1->offset; ret = asn1_id_decode1(asn1, &tag); - req_item = proto_tree_add_none_format(tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Dialogue Abort"); + req_item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Dialogue Abort"); subtree = proto_item_add_subtree(req_item, ett_dlg_abort ); proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag); @@ -1883,8 +1991,7 @@ dissect_tcap_dialog_portion(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *t } dlg_item = - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "Dialogue Portion"); + proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Portion"); subtree = proto_item_add_subtree(dlg_item, ett_dlg_portion); @@ -2009,8 +2116,7 @@ dissect_tcap_abort_reason(ASN1_SCK *asn1, proto_tree *tcap_tree) { saved_offset = asn1->offset; item = - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "PAbort Cause"); + proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "PAbort Cause"); subtree = proto_item_add_subtree(item, ett_reason); @@ -2035,7 +2141,7 @@ dissect_tcap_abort_reason(ASN1_SCK *asn1, proto_tree *tcap_tree) break; } - proto_tree_add_none_format(subtree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset, "Cause Value %s (%d)", str, value); } @@ -2121,7 +2227,7 @@ dissect_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree) if (str == NULL) { - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1.tvb, offset, -1, "Unknown message type, ignoring"); + proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring"); return; } @@ -2157,7 +2263,7 @@ dissect_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree) dissect_tcap_abort(&asn1, tcap_tree, ti); break; default: - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1.tvb, offset, -1, + proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Message type not handled, ignoring"); break; } @@ -2191,9 +2297,9 @@ dissect_ansi_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree) return TC_DS_FAIL; } - cmp_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Components Portion"); + cmp_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Components Portion"); - subtree = proto_item_add_subtree(cmp_item, ett_cmp_portion); + subtree = proto_item_add_subtree(cmp_item, ett_comps_portion); proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag, "Component Sequence Identifier"); @@ -2229,7 +2335,7 @@ dissect_ansi_tcap_unidirectional(ASN1_SCK *asn1, proto_tree *tcap_tree) return TC_DS_FAIL; } - trans_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Transaction Portion"); + trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion"); dissect_tcap_len(asn1, tcap_tree, &def_len, &len); @@ -2268,7 +2374,7 @@ dissect_ansi_tcap_qwp_qwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti return TC_DS_FAIL; } - trans_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Transaction Portion"); + trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_portion); proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag, @@ -2324,7 +2430,7 @@ dissect_ansi_tcap_abort(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti) } trans_item = - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, + proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_portion); @@ -2368,8 +2474,7 @@ dissect_ansi_tcap_abort(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti) if (tag == ANSI_TC_PABRT_CAUSE_TAG) { trans_item = - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "P-Abort Portion"); + proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "P-Abort Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_abort); @@ -2401,8 +2506,7 @@ dissect_ansi_tcap_abort(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti) else if (tag == ANSI_TC_UABRT_INFO_TAG) { trans_item = - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, - saved_offset, -1, "U-Abort Portion"); + proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "U-Abort Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_abort); @@ -2439,7 +2543,7 @@ dissect_ansi_tcap_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti) return TC_DS_FAIL; } - trans_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Transaction Portion"); + trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_portion); proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag, @@ -2492,7 +2596,7 @@ dissect_ansi_tcap_cwp_cwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti return TC_DS_FAIL; } - trans_item = proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1->tvb, saved_offset, -1, "Transaction Portion"); + trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion"); subtree = proto_item_add_subtree(trans_item, ett_dlg_portion); proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag, @@ -2552,7 +2656,7 @@ dissect_ansi_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tr if (str == NULL) { - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1.tvb, offset, -1, "Unknown message type, ignoring"); + proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring"); return; } @@ -2594,7 +2698,7 @@ dissect_ansi_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tr dissect_ansi_tcap_abort(&asn1, tcap_tree, ti); break; default: - proto_tree_add_none_format(tcap_tree, hf_tcap_none, asn1.tvb, offset, -1, + proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Message type not handled, ignoring"); break; } @@ -2676,11 +2780,6 @@ proto_register_tcap(void) FT_UINT8, BASE_HEX, VALS(ansi_msg_type_strings), 0, "", HFILL } }, - { &hf_tcap_none, - { "Sub tree", "tcap.none", - FT_NONE, 0, 0, 0, - "", HFILL } - }, { &hf_tcap_tid, { "Transaction Id", "tcap.tid", FT_UINT32, BASE_DEC, VALS(tid_strings), 0, @@ -2719,7 +2818,7 @@ proto_register_tcap(void) &ett_otid, &ett_dtid, &ett_dlg_portion, - &ett_cmp_portion, + &ett_comps_portion, &ett_reason, &ett_dlg_req, &ett_dlg_rsp, |