From Michael Lum:

GSM A facility element decoding;

	make TCAP dissector export routines for use by various GSM
	dissectors;

	make GSM MAP dissector use exported TCAP routines/defines;

	GSM Supplementary Services support.

svn path=/trunk/; revision=10409
This commit is contained in:
Guy Harris 2004-03-19 07:54:58 +00:00
parent e39c338b07
commit 11340a8122
9 changed files with 1582 additions and 645 deletions

View File

@ -1836,6 +1836,7 @@ Michael Lum <mlum [AT] telostech.com> {
GSM SMS (3GPP TS 24.011) support
GSM SS (3GPP TS 24.080) support
GSM SMS TPDU (3GPP TS 23.040) support
GSM Supplementary Services support
GSM MAP fixes and parameter separation
Taps for ANSI A-interface statistics
Support for SS7 point codes as address types

View File

@ -3,7 +3,7 @@
# a) common to both files and
# b) portable between both files
#
# $Id: Makefile.common,v 1.29 2004/03/18 08:25:09 guy Exp $
# $Id: Makefile.common,v 1.30 2004/03/19 07:54:57 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -94,6 +94,7 @@ DISSECTOR_INCLUDES = \
packet-gnutella.h \
packet-gsm_a.h \
packet-gsm_map.h \
packet-gsm_ss.h \
packet-gssapi.h \
packet-gtp.h \
packet-h225.h \

View File

@ -3,7 +3,7 @@
# a) common to both files and
# b) portable between both files
#
# $Id: Makefile.common,v 1.8 2004/03/18 08:25:09 guy Exp $
# $Id: Makefile.common,v 1.9 2004/03/19 07:54:58 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -198,6 +198,7 @@ DISSECTOR_SRC = \
../packet-gsm_map.c \
../packet-gsm_sms.c \
../packet-gsm_sms_ud.c \
../packet-gsm_ss.c \
../packet-gssapi.c \
../packet-gtp.c \
../packet-gvrp.c \

View File

@ -38,7 +38,7 @@
* Formats and coding
* (3GPP TS 24.080 version 4.3.0 Release 4)
*
* $Id: packet-gsm_a.c,v 1.11 2004/02/20 10:50:13 guy Exp $
* $Id: packet-gsm_a.c,v 1.12 2004/03/19 07:54:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -71,8 +71,11 @@
#include "epan/packet.h"
#include "prefs.h"
#include "tap.h"
#include "asn1.h"
#include "packet-tcap.h"
#include "packet-bssap.h"
#include "packet-gsm_ss.h"
#include "packet-gsm_a.h"
/* PROTOTYPES/FORWARDS */
@ -684,6 +687,8 @@ static int hf_gsm_a_cell_lac = -1;
static int hf_gsm_a_dlci_cc = -1;
static int hf_gsm_a_dlci_spare = -1;
static int hf_gsm_a_dlci_sapi = -1;
static int hf_gsm_a_bssmap_cause = -1;
static int hf_gsm_a_dtap_cause = -1;
/* Initialize the subtree pointers */
static gint ett_bssmap_msg = -1;
@ -711,6 +716,14 @@ static gint ett_bc_oct_6f = -1;
static gint ett_bc_oct_6g = -1;
static gint ett_bc_oct_7 = -1;
static gint ett_tc_component = -1;
static gint ett_tc_invoke_id = -1;
static gint ett_tc_linked_id = -1;
static gint ett_tc_opr_code = -1;
static gint ett_tc_err_code = -1;
static gint ett_tc_prob_code = -1;
static gint ett_tc_sequence = -1;
static char a_bigbuf[1024];
static gchar a_add_string[1024];
@ -1214,8 +1227,8 @@ be_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_
}
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
proto_tree_add_uint_format(tree, hf_gsm_a_bssmap_cause,
tvb, curr_offset, 1, oct & 0x7f,
"%s : Cause: (%u) %s",
a_bigbuf,
oct & 0x7f,
@ -5907,8 +5920,8 @@ de_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_
}
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
proto_tree_add_uint_format(tree, hf_gsm_a_dtap_cause,
tvb, curr_offset, 1, cause,
"%s : Cause: (%u) %s",
a_bigbuf,
cause,
@ -5931,6 +5944,332 @@ de_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_
return(curr_offset - offset);
}
#define GSM_A_TC_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
{ \
guint _len_offset; \
proto_item *_item; \
\
_len_offset = asn1->offset; \
asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
\
_item = \
proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
\
_Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
\
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
\
if (*_Gdef_len_p) \
{ \
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
} \
else \
{ \
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
\
*_Glen_p = tcap_find_eoc(asn1); \
} \
\
proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
(*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
}
/*
* [6] 3.6
*/
static guint8
de_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
{
ASN1_SCK asn1_real, *asn1;
proto_item *item;
proto_tree *subtree, *temp_subtree, *seq_subtree;
guint saved_offset, comp_saved_offset, comp_len_offset, comp_data_offset;
guint comp_len, temp_len;
gboolean def_len[3];
guint comp_tag, tag;
gchar *str;
gint32 int_val;
add_string = add_string;
asn1 = &asn1_real;
asn1_open(asn1, tvb, offset);
/* call next dissector for EACH component */
while ((len - (asn1->offset - offset)) > 0)
{
comp_saved_offset = asn1->offset;
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &comp_tag);
comp_len_offset = asn1->offset;
comp_len = 0;
def_len[0] = FALSE;
asn1_length_decode(asn1, &def_len[0], &comp_len);
comp_data_offset = asn1->offset;
if (def_len[0])
{
temp_len = comp_len + (asn1->offset - saved_offset);
}
else
{
comp_len = tcap_find_eoc(asn1);
temp_len = comp_len + (asn1->offset - saved_offset) + TCAP_EOC_LEN;
}
item =
proto_tree_add_text(tree, asn1->tvb, comp_saved_offset, temp_len, "Component");
subtree = proto_item_add_subtree(item, ett_tc_component);
str = match_strval((guint32) comp_tag, tcap_component_type_str);
if (str == NULL)
{
proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset, temp_len,
"Unknown component type tag, ignoring component");
asn1->offset = comp_saved_offset + temp_len;
continue;
}
proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset,
comp_len_offset - comp_saved_offset,
"%s Type Tag: 0x%02x", str, comp_tag);
if (def_len[0])
{
proto_tree_add_text(subtree, asn1->tvb,
comp_len_offset, asn1->offset - comp_len_offset, "Length: %d", comp_len);
}
else
{
proto_tree_add_text(subtree, asn1->tvb,
comp_len_offset, asn1->offset - comp_len_offset, "Length: Indefinite");
}
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Invoke ID",
ett_tc_invoke_id, &def_len[1], &temp_len, temp_subtree);
if (temp_len > 0)
{
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, temp_len, &int_val);
proto_tree_add_text(temp_subtree, asn1->tvb,
saved_offset, temp_len, "Invoke ID: %d", int_val);
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
switch (comp_tag)
{
case TCAP_COMP_INVOKE:
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
if (tag == TCAP_LINKED_ID_TAG)
{
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Linked ID",
ett_tc_linked_id, &def_len[1], &temp_len, temp_subtree);
if (temp_len > 0)
{
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, temp_len, &int_val);
proto_tree_add_text(temp_subtree, asn1->tvb,
saved_offset, temp_len, "Linked ID: %d", int_val);
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
}
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Operation Code",
ett_tc_opr_code, &def_len[1], &temp_len, temp_subtree);
if (temp_len > 0)
{
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, temp_len, &int_val);
str = match_strval(int_val, gsm_ss_opr_code_strings);
proto_tree_add_text(temp_subtree, asn1->tvb,
saved_offset, temp_len, "Operation Code: %s (%d)",
(str == NULL) ? "Unknown Operation Code" : str,
int_val);
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
{
gsm_ss_dissect(asn1, subtree,
comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
}
break;
case TCAP_COMP_RRL:
if ((len - (asn1->offset - offset)) > 0)
{
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Sequence",
ett_tc_sequence, &def_len[1], &temp_len, seq_subtree);
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_A_TC_START_SUBTREE(seq_subtree, saved_offset, tag, "Operation Code",
ett_tc_opr_code, &def_len[2], &temp_len, temp_subtree);
if (temp_len > 0)
{
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, temp_len, &int_val);
str = match_strval(int_val, gsm_ss_opr_code_strings);
proto_tree_add_text(temp_subtree, asn1->tvb,
saved_offset, temp_len, "Operation Code: %s (%d)",
(str == NULL) ? "Unknown Operation Code" : str,
int_val);
}
if (!def_len[2])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
{
gsm_ss_dissect(asn1, seq_subtree,
comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
}
break;
case TCAP_COMP_RE:
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Error Code",
ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
if (temp_len > 0)
{
proto_tree_add_text(temp_subtree, asn1->tvb,
asn1->offset, temp_len, "Error Code");
asn1->offset += temp_len;
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
{
/*
* XXX need conversations to determine 'opr_code'
*/
gsm_ss_dissect(asn1, subtree,
comp_len - (asn1->offset - comp_data_offset), 0, comp_tag);
}
break;
case TCAP_COMP_REJECT:
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Problem Code",
ett_tc_prob_code, &def_len[1], &temp_len, temp_subtree);
if (temp_len > 0)
{
proto_tree_add_text(temp_subtree, asn1->tvb,
asn1->offset, temp_len, "Problem Code");
asn1->offset += temp_len;
}
if (!def_len[1])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
break;
}
if (!def_len[0])
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
}
return(len);
}
/*
* [3] 10.5.4.17
*/
@ -5939,7 +6278,6 @@ de_keypad_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, g
{
guint8 oct;
guint32 curr_offset;
gchar *str;
len = len;
curr_offset = offset;
@ -5952,16 +6290,6 @@ de_keypad_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, g
"%s : Spare",
a_bigbuf);
switch ((oct & 0x60) >> 5)
{
case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
case 1: str = "Reserved for other international standards"; break;
case 2: str = "National standard"; break;
default:
str = "Standard defined for the GSM PLMNS";
break;
}
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
@ -5978,6 +6306,113 @@ de_keypad_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, g
return(curr_offset - offset);
}
/*
* [3] 10.5.4.21
*/
static guint8
de_prog_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
{
guint8 oct;
guint32 curr_offset;
gchar *str;
len = len;
curr_offset = offset;
oct = tvb_get_guint8(tvb, curr_offset);
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Extension: %s",
a_bigbuf,
(oct & 0x80) ? "extended" : "not extended");
switch ((oct & 0x60) >> 5)
{
case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
case 1: str = "Reserved for other international standards"; break;
case 2: str = "National standard"; break;
default:
str = "Standard defined for the GSM PLMNS";
break;
}
other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Coding standard: %s",
a_bigbuf,
str);
other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Spare",
a_bigbuf);
switch (oct & 0x0f)
{
case 0: str = "User"; break;
case 1: str = "Private network serving the local user"; break;
case 2: str = "Public network serving the local user"; break;
case 4: str = "Public network serving the remote user"; break;
case 5: str = "Private network serving the remote user"; break;
case 10: str = "Network beyond interworking point"; break;
default:
str = "Reserved";
break;
}
other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Location: %s",
a_bigbuf,
str);
curr_offset++;
oct = tvb_get_guint8(tvb, curr_offset);
other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Extension: %s",
a_bigbuf,
(oct & 0x80) ? "extended" : "not extended");
switch (oct & 0x7f)
{
case 1: str = "Call is not end-to-end PLMN/ISDN, further call progress information may be available in-band"; break;
case 2: str = "Destination address in non-PLMN/ISDN"; break;
case 3: str = "Origination address in non-PLMN/ISDN"; break;
case 4: str = "Call has returned to the PLMN/ISDN"; break;
case 8: str = "In-band information or appropriate pattern now available"; break;
case 32: str = "Call is end-to-end PLMN/ISDN"; break;
case 64: str = "Queueing"; break;
default:
str = "Unspecific";
break;
}
other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
proto_tree_add_text(tree,
tvb, curr_offset, 1,
"%s : Progress Description: %s (%d)",
a_bigbuf,
str,
oct & 0x7f);
sprintf(add_string, " - %d", oct & 0x7f);
curr_offset++;
EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
return(curr_offset - offset);
}
/*
* [3] 10.5.4.22
*/
@ -6409,13 +6844,13 @@ static guint8 (*dtap_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset
NULL /* handled inline */, /* Congestion Level */
NULL, /* Connected Number */
NULL, /* Connected Subaddress */
NULL, /* Facility */
de_facility, /* Facility */
NULL, /* High Layer Compatibility */
de_keypad_facility, /* Keypad Facility */
NULL, /* Low Layer Compatibility */
NULL, /* More Data */
NULL, /* Notification Indicator */
NULL, /* Progress Indicator */
de_prog_ind, /* Progress Indicator */
NULL, /* Recall type $(CCBS)$ */
NULL, /* Redirecting Party BCD Number */
NULL, /* Redirecting Party Subaddress */
@ -10723,19 +11158,32 @@ proto_register_gsm_a(void)
{ &hf_gsm_a_dlci_cc,
{ "Control Channel", "bssap.dlci.cc",
FT_UINT8, BASE_HEX, VALS(bssap_cc_values), 0xc0,
"", HFILL}},
"", HFILL}
},
{ &hf_gsm_a_dlci_spare,
{ "Spare", "bssap.dlci.spare",
FT_UINT8, BASE_HEX, NULL, 0x38,
"", HFILL}},
"", HFILL}
},
{ &hf_gsm_a_dlci_sapi,
{ "SAPI", "bssap.dlci.sapi",
FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), 0x07,
"", HFILL}},
"", HFILL}
},
{ &hf_gsm_a_bssmap_cause,
{ "BSSMAP Cause", "gsm_a_bssmap.cause",
FT_UINT8, BASE_HEX, 0, 0x0,
"", HFILL }
},
{ &hf_gsm_a_dtap_cause,
{ "DTAP Cause", "gsm_a_dtap.cause",
FT_UINT8, BASE_HEX, 0, 0x0,
"", HFILL }
},
};
/* Setup protocol subtree array */
#define NUM_INDIVIDUAL_ELEMS 24
#define NUM_INDIVIDUAL_ELEMS 33
static gint *ett[NUM_INDIVIDUAL_ELEMS + NUM_GSM_BSSMAP_MSG +
NUM_GSM_DTAP_MSG_MM + NUM_GSM_DTAP_MSG_RR + NUM_GSM_DTAP_MSG_CC +
NUM_GSM_DTAP_MSG_GMM + NUM_GSM_DTAP_MSG_SMS +
@ -10769,6 +11217,16 @@ proto_register_gsm_a(void)
ett[22] = &ett_bc_oct_6g;
ett[23] = &ett_bc_oct_7;
ett[24] = &ett_tc_component;
ett[25] = &ett_tc_invoke_id;
ett[26] = &ett_tc_linked_id;
ett[27] = &ett_tc_opr_code;
ett[28] = &ett_tc_err_code;
ett[29] = &ett_tc_prob_code;
ett[30] = &ett_tc_sequence;
ett[31] = &gsm_ss_ett_sequence;
ett[32] = &gsm_ss_ett_param;
last_offset = NUM_INDIVIDUAL_ELEMS;
for (i=0; i < NUM_GSM_BSSMAP_MSG; i++, last_offset++)

File diff suppressed because it is too large Load Diff

810
packet-gsm_ss.c Normal file
View File

@ -0,0 +1,810 @@
/* packet-gsm_ss.c
* Routines for GSM Supplementary Services dissection
*
* NOTE:
* Routines are shared by GSM MAP/GSM A dissectors.
* This file provides SHARED routines and is NOT a
* standalone dissector.
*
* Copyright 2004, Michael Lum <mlum [AT] telostech.com>
* In association with Telos Technology Inc.
*
* Title 3GPP Other
*
* Reference [1]
* Mobile radio Layer 3 supplementary service specification;
* Formats and coding
* (3GPP TS 24.080 version 4.3.0 Release 4)
*
* Michael Lum <mlum [AT] telostech.com>,
* Created (2004).
*
* $Id: packet-gsm_ss.c,v 1.1 2004/03/19 07:54:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-gsm_map.c (where "WHATEVER_FILE_YOU_USED"
* is a dissector file; if you just copied this from README.developer,
* don't bother with the "Copied from" - you don't even need to put
* in a "Copied from" if you copied an existing dissector, especially
* if the bulk of the code in the new dissector is your code)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "epan/packet.h"
#include "tap.h"
#include "asn1.h"
#include "packet-tcap.h"
#include "packet-gsm_ss.h"
const value_string gsm_ss_opr_code_strings[] = {
{ 10, "RegisterSS" },
{ 11, "EraseSS" },
{ 12, "ActivateSS" },
{ 13, "DeactivateSS" },
{ 14, "InterrogateSS" },
{ 16, "NotifySS" },
{ 17, "RegisterPassword" },
{ 18, "GetPassword" },
{ 19, "ProcessUnstructuredSS-Data" },
{ 38, "ForwardCheckSS-Indication" },
{ 59, "ProcessUnstructuredSS-Request" },
{ 60, "UnstructuredSS-Request" },
{ 61, "UnstructuredSS-Notify" },
{ 77, "EraseCC-Entry" },
{ 119, "AccessRegisterCCEntry" },
{ 120, "ForwardCUG-Info" },
{ 121, "SplitMPTY" },
{ 122, "RetrieveMPTY" },
{ 123, "HoldMPTY" },
{ 124, "BuildMPTY" },
{ 125, "ForwardChargeAdvice" },
{ 126, "ExplicitCT" },
{ 0, NULL }
};
/* never initialize in field array */
static int hf_null = -1;
#define HF_NULL &hf_null
gint gsm_ss_ett_sequence = -1;
gint gsm_ss_ett_param = -1;
/* GENERIC HELPER FUNCTIONS */
static gchar *
my_match_strval(guint32 val, const value_string *vs, gint *idx)
{
gint i = 0;
while (vs[i].strptr) {
if (vs[i].value == val)
{
*idx = i;
return(vs[i].strptr);
}
i++;
}
*idx = -1;
return(NULL);
}
/* PARAMETER dissection */
static void
param_ssCode(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
{
guint saved_offset;
gint32 value;
gchar *str = NULL;
hf_field = hf_field;
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, len, &value);
switch (value)
{
case 0x00:
str = "allSS - all SS";
break;
case 0x10:
str = "allLineIdentificationSS - all line identification SS";
break;
case 0x11:
str = "clip - calling line identification presentation";
break;
case 0x12:
str = "clir - calling line identification restriction";
break;
case 0x13:
str = "colp - connected line identification presentation";
break;
case 0x14:
str = "colr - connected line identification restriction";
break;
case 0x15:
str = "mci - malicious call identification";
break;
case 0x18:
str = "allNameIdentificationSS - all name indentification SS";
break;
case 0x19:
str = "cnap - calling name presentation";
break;
case 0x20:
str = "allForwardingSS - all forwarding SS";
break;
case 0x21:
str = "cfu - call forwarding unconditional";
break;
case 0x28:
str = "allCondForwardingSS - all conditional forwarding SS";
break;
case 0x29:
str = "cfb - call forwarding busy";
break;
case 0x2a:
str = "cfnry - call forwarding on no reply";
break;
case 0x2b:
str = "cfnrc - call forwarding on mobile subscriber not reachable";
break;
case 0x24:
str = "cd - call deflection";
break;
case 0x30:
str = "allCallOfferingSS - all call offering SS includes also all forwarding SS";
break;
case 0x31:
str = "ect - explicit call transfer";
break;
case 0x32:
str = "mah - mobile access hunting";
break;
case 0x40:
str = "allCallCompletionSS - all Call completion SS";
break;
case 0x41:
str = "cw - call waiting";
break;
case 0x42:
str = "hold - call hold";
break;
case 0x43:
str = "ccbs-A - completion of call to busy subscribers, originating side";
break;
case 0x44:
str = "ccbs-B - completion of call to busy subscribers, destination side";
break;
case 0x45:
str = "mc - multicall";
break;
case 0x50:
str = "allMultiPartySS - all multiparty SS";
break;
case 0x51:
str = "multiPTY - multiparty";
break;
case 0x60:
str = "allCommunityOfInterestSS - all community of interest SS";
break;
case 0x61:
str = "cug - closed user group";
break;
case 0x70:
str = "allChargingSS - all charging SS";
break;
case 0x71:
str = "aoci - advice of charge information";
break;
case 0x72:
str = "aocc - advice of charge charging";
break;
case 0x80:
str = "allAdditionalInfoTransferSS - all additional information transfer SS";
break;
case 0x81:
str = "uus1 - UUS1 user-to-user signalling";
break;
case 0x82:
str = "uus2 - UUS2 user-to-user signalling";
break;
case 0x83:
str = "uus3 - UUS3 user-to-user signalling";
break;
case 0x90:
str = "allBarringSS - all barring SS";
break;
case 0x91:
str = "barringOfOutgoingCalls";
break;
case 0x92:
str = "baoc - barring of all outgoing calls";
break;
case 0x93:
str = "boic - barring of outgoing international calls";
break;
case 0x94:
str = "boicExHC - barring of outgoing international calls except those directed to the home PLMN";
break;
case 0x99:
str = "barringOfIncomingCalls";
break;
case 0x9a:
str = "baic - barring of all incoming calls";
break;
case 0x9b:
str = "bicRoam - barring of incoming calls when roaming outside home PLMN Country";
break;
case 0xf0:
str = "allPLMN-specificSS";
break;
case 0xa0:
str = "allCallPrioritySS - all call priority SS";
break;
case 0xa1:
str = "emlpp - enhanced Multilevel Precedence Pre-emption (EMLPP) service";
break;
case 0xb0:
str = "allLCSPrivacyException - all LCS Privacy Exception Classes";
break;
case 0xb1:
str = "universal - allow location by any LCS client";
break;
case 0xb2:
str = "callrelated - allow location by any value added LCS client to which a call is established from the target MS";
break;
case 0xb3:
str = "callunrelated - allow location by designated external value added LCS clients";
break;
case 0xb4:
str = "plmnoperator - allow location by designated PLMN operator LCS clients";
break;
case 0xc0:
str = "allMOLR-SS - all Mobile Originating Location Request Classes";
break;
case 0xc1:
str = "basicSelfLocation - allow an MS to request its own location";
break;
case 0xc2:
str = "autonomousSelfLocation - allow an MS to perform self location without interaction with the PLMN for a predetermined period of time";
break;
case 0xc3:
str = "transferToThirdParty - allow an MS to request transfer of its location to another LCS client";
break;
default:
/*
* XXX
*/
str = "reserved for future use";
break;
}
proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
}
/*
* See GSM 03.11
*/
static void
param_ssStatus(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
{
guint saved_offset;
gint32 value;
char bigbuf[1024];
hf_field = hf_field;
saved_offset = asn1->offset;
asn1_int32_value_decode(asn1, len, &value);
other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, 1,
"%s : Unused",
bigbuf);
/*
* Q bit is valid only if A bit is "Active"
*/
other_decode_bitfield_value(bigbuf, value, 0x08, 8);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, 1,
"%s : Q bit: %s",
bigbuf,
(value & 0x01) ?
((value & 0x08) ? "Quiescent" : "Operative") : "N/A");
other_decode_bitfield_value(bigbuf, value, 0x04, 8);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, 1,
"%s : P bit: %sProvisioned",
bigbuf,
(value & 0x04) ? "" : "Not ");
other_decode_bitfield_value(bigbuf, value, 0x02, 8);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, 1,
"%s : R bit: %sRegistered",
bigbuf,
(value & 0x02) ? "" : "Not ");
other_decode_bitfield_value(bigbuf, value, 0x01, 8);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, 1,
"%s : A bit: %sActive",
bigbuf,
(value & 0x01) ? "" : "Not ");
}
typedef enum
{
GSM_SS_P_SS_CODE, /* SS-Code */
GSM_SS_P_SS_STATUS, /* SS-Status */
GSM_SS_P_NONE /* NONE */
}
param_idx_t;
#define NUM_PARAM_1 (GSM_SS_P_NONE+1)
static gint ett_param_1[NUM_PARAM_1];
static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = {
param_ssCode, /* SS-Code */
param_ssStatus, /* SS-Status */
NULL /* NONE */
};
static int *param_1_hf[] = {
HF_NULL, /* SS-Code */
HF_NULL, /* SS-Status */
NULL /* NONE */
};
#define GSM_SS_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
{ \
guint _len_offset; \
proto_item *_item; \
\
_len_offset = asn1->offset; \
asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
\
_item = \
proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
\
_Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
\
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
\
if (*_Gdef_len_p) \
{ \
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
} \
else \
{ \
proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
_len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
\
*_Glen_p = tcap_find_eoc(asn1); \
} \
\
proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
(*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
}
#define GSM_SS_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \
{ \
gint _ett_param_idx; \
guint _len; \
void (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \
int *_param_hf = NULL; \
proto_tree *_subtree; \
gboolean _def_len; \
\
if (Ga1 == GSM_SS_P_NONE) \
{ \
_ett_param_idx = gsm_ss_ett_param; \
_param_fcn = NULL; \
_param_hf = HF_NULL; \
} \
else \
{ \
_ett_param_idx = ett_param_1[Ga1]; \
_param_fcn = param_1_fcn[Ga1]; \
_param_hf = param_1_hf[Ga1]; \
} \
\
GSM_SS_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \
\
if (_len > 0) \
{ \
if (Ga1 == GSM_SS_P_NONE || _param_fcn == NULL) \
{ \
proto_tree_add_text(_subtree, asn1->tvb, \
asn1->offset, _len, "Parameter Data"); \
\
asn1->offset += _len; \
} \
else \
{ \
(*_param_fcn)(asn1, _subtree, _len, *_param_hf); \
} \
} \
\
if (!_def_len) \
{ \
guint _saved_offset; \
\
_saved_offset = asn1->offset; \
asn1_eoc_decode(asn1, -1); \
\
proto_tree_add_text(Gtree, asn1->tvb, \
_saved_offset, asn1->offset - _saved_offset, "End of Contents"); \
} \
}
static void
op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
{
guint orig_offset, saved_offset, len_offset;
guint tag, len;
gboolean def_len = FALSE;
proto_item *item;
proto_tree *subtree;
orig_offset = asn1->offset;
while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
(!tcap_check_tag(asn1, 0)))
{
if ((exp_len != 0) &&
((asn1->offset - orig_offset) >= exp_len))
{
break;
}
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
if (TCAP_CONSTRUCTOR(tag))
{
GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
gsm_ss_ett_sequence,
&def_len, &len, subtree);
op_generic_ss(asn1, subtree, len);
if (!def_len)
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
continue;
}
len_offset = asn1->offset;
asn1_length_decode(asn1, &def_len, &len);
if (!def_len)
{
proto_tree_add_text(tree, asn1->tvb,
saved_offset, len_offset - saved_offset,
"Tag: 0x%02x", tag);
proto_tree_add_text(tree, asn1->tvb,
len_offset, asn1->offset - len_offset, "Length: Indefinite");
len = tcap_find_eoc(asn1);
op_generic_ss(asn1, tree, len);
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(tree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
continue;
}
item =
proto_tree_add_text(tree, asn1->tvb,
saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
subtree = proto_item_add_subtree(item, gsm_ss_ett_param);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, len_offset - saved_offset,
"Tag: 0x%02x", tag);
proto_tree_add_text(subtree, asn1->tvb,
len_offset, asn1->offset - len_offset, "Length: %d", len);
if (len > 0)
{
proto_tree_add_text(subtree, asn1->tvb,
asn1->offset, len, "Parameter Data");
asn1->offset += len;
}
}
}
static void
op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
{
guint saved_offset, start_offset;
guint tag, len;
gboolean def_len = FALSE;
proto_tree *subtree;
exp_len = exp_len;
if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
if (TCAP_CONSTRUCTOR(tag) == FALSE)
{
/*
* Hmmm, unexpected
*/
return;
}
GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
gsm_ss_ett_sequence,
&def_len, &len, subtree);
start_offset = asn1->offset;
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
op_generic_ss(asn1, subtree, len - (asn1->offset - start_offset));
if (!def_len)
{
saved_offset = asn1->offset;
asn1_eoc_decode(asn1, -1);
proto_tree_add_text(subtree, asn1->tvb,
saved_offset, asn1->offset - saved_offset, "End of Contents");
}
}
static void
op_interrogate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
{
guint saved_offset;
guint tag;
exp_len = exp_len;
if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
switch (tag)
{
case 0x80: /* SS-Status */
GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
return;
case 0x82: /* BasicServiceGroupList */
/* FALLTHRU */
case 0x83: /* ForwardingFeatureList */
/* FALLTHRU */
case 0x84: /* GenericServiceInfo */
/*
* XXX
* needs implementing, let "generic" parameter dissector handle it for now
*/
break;
default:
/* do nothing - unexpected tag */
break;
}
op_generic_ss(asn1, tree, 0);
}
#define GSM_SS_NUM_OP (sizeof(gsm_ss_opr_code_strings)/sizeof(value_string))
static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
NULL, /* RegisterSS */
NULL, /* EraseSS */
NULL, /* ActivateSS */
NULL, /* DeactivateSS */
op_interrogate_ss, /* InterrogateSS */
NULL, /* NotifySS */
NULL, /* RegisterPassword */
NULL, /* GetPassword */
NULL, /* ProcessUnstructuredSS-Data */
NULL, /* ForwardCheckSS-Indication */
NULL, /* ProcessUnstructuredSS-Request */
NULL, /* UnstructuredSS-Request */
NULL, /* UnstructuredSS-Notify */
NULL, /* EraseCC-Entry */
NULL, /* AccessRegisterCCEntry */
NULL, /* ForwardCUG-Info */
NULL, /* SplitMPTY */
NULL, /* RetrieveMPTY */
NULL, /* HoldMPTY */
NULL, /* BuildMPTY */
NULL, /* ForwardChargeAdvice */
NULL, /* ExplicitCT */
NULL /* NONE */
};
static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
NULL, /* RegisterSS */
NULL, /* EraseSS */
NULL, /* ActivateSS */
NULL, /* DeactivateSS */
op_interrogate_ss_rr, /* InterrogateSS */
NULL, /* NotifySS */
NULL, /* RegisterPassword */
NULL, /* GetPassword */
NULL, /* ProcessUnstructuredSS-Data */
NULL, /* ForwardCheckSS-Indication */
NULL, /* ProcessUnstructuredSS-Request */
NULL, /* UnstructuredSS-Request */
NULL, /* UnstructuredSS-Notify */
NULL, /* EraseCC-Entry */
NULL, /* AccessRegisterCCEntry */
NULL, /* ForwardCUG-Info */
NULL, /* SplitMPTY */
NULL, /* RetrieveMPTY */
NULL, /* HoldMPTY */
NULL, /* BuildMPTY */
NULL, /* ForwardChargeAdvice */
NULL, /* ExplicitCT */
NULL /* NONE */
};
void
gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len,
guint opr_code, guint comp_type_tag)
{
void (*dissect_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint exp_len);
gchar *str;
gint op_idx;
dissect_fcn = NULL;
str = my_match_strval(opr_code, gsm_ss_opr_code_strings, &op_idx);
if (str != NULL)
{
switch (comp_type_tag)
{
case TCAP_COMP_INVOKE:
dissect_fcn = op_fcn[op_idx];
break;
case TCAP_COMP_RRL:
dissect_fcn = op_fcn_rr[op_idx];
break;
case TCAP_COMP_RE:
/* XXX */
break;
default:
/*
* no parameters should be present in the component types
* ignore
*/
return;
}
}
if (dissect_fcn == NULL)
{
op_generic_ss(asn1, tree, exp_len);
}
else
{
(*dissect_fcn)(asn1, tree, exp_len);
}
}

32
packet-gsm_ss.h Normal file
View File

@ -0,0 +1,32 @@
/* packet-gsm_ss.h
*
* $Id: packet-gsm_ss.h,v 1.1 2004/03/19 07:54:57 guy Exp $
*
* Copyright 2004, Michael Lum <mlum [AT] telostech.com>,
* In association with Telos Technology Inc.
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
extern gint gsm_ss_ett_sequence;
extern gint gsm_ss_ett_param;
extern const value_string gsm_ss_opr_code_strings[];
extern void gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len, guint opr_code, guint comp_type_tag);

View File

@ -9,7 +9,7 @@
*
* (append your name here for newer version)
*
* $Id: packet-tcap.c,v 1.8 2004/03/05 10:05:03 guy Exp $
* $Id: packet-tcap.c,v 1.9 2004/03/19 07:54:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -61,8 +61,8 @@
#include <epan/packet.h>
#include "prefs.h"
#include "packet-tcap.h"
#include "asn1.h"
#include "packet-tcap.h"
Tcap_Standard_Type tcap_standard = ITU_TCAP_STANDARD;
@ -107,11 +107,6 @@ static dissector_table_t tcap_itu_ssn_dissector_table; /* map use ssn in sccp */
static dissector_table_t tcap_ansi_ssn_dissector_table; /* map use ssn in sccp */
static gboolean lock_info_col = TRUE;
#define TC_SEQ_TAG 0x30
#define TC_SET_TAG 0x31
#define TC_EOC_LEN 2 /* 0x00 0x00 */
/* TCAP transaction message type definition - Samuel */
#define ST_MSG_TYP_UNI 0x61 /*0b01100001*/
#define ST_MSG_TYP_BGN 0x62 /*0b01100010*/
@ -176,27 +171,20 @@ static const value_string dlg_type_strings[] = {
{ 0, NULL },
};
/* TCAP component type */
#define TC_INVOKE 0xa1
#define TC_RRL 0xa2
#define TC_RE 0xa3
#define TC_REJECT 0xa4
#define TC_RRN 0xa7
/* ANSI TCAP component type */
#define ANSI_TC_INVOKE_L 0xe9
#define ANSI_TC_RRL 0xea
#define ANSI_TC_RE 0xeb
#define ANSI_TC_REJECT 0xec
#define ANSI_TC_INVOKE_N 0xed
#define ANSI_TC_RRN 0xee
const value_string tcap_component_type_str[] = {
{ TCAP_COMP_INVOKE, "Invoke" },
{ TCAP_COMP_RRL, "Return Result(L)" },
{ TCAP_COMP_RE, "Return Error" },
{ TCAP_COMP_REJECT, "Reject" },
{ TCAP_COMP_RRN, "Return Result(NL)" },
{ 0, NULL } };
#define TC_DS_OK 1
#define TC_DS_FAIL 0
static int
find_eoc(ASN1_SCK *asn1)
int
tcap_find_eoc(ASN1_SCK *asn1)
{
guint saved_offset;
guint tag;
@ -216,7 +204,7 @@ find_eoc(ASN1_SCK *asn1)
}
else
{
asn1->offset += find_eoc(asn1);
asn1->offset += tcap_find_eoc(asn1);
asn1_eoc_decode(asn1, -1);
}
}
@ -227,7 +215,23 @@ find_eoc(ASN1_SCK *asn1)
return(len);
}
/* dissect length */
gboolean
tcap_check_tag(ASN1_SCK *asn1, guint tag)
{
guint saved_offset, real_tag;
if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
{
return (FALSE);
}
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &real_tag);
asn1->offset = saved_offset;
return (tag == real_tag);
}
static int
dissect_tcap_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
{
@ -320,22 +324,6 @@ dissect_tcap_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar * str)
return TC_DS_OK;
}
static gboolean
check_tcap_tag(ASN1_SCK *asn1, guint tag)
{
guint saved_offset, real_tag;
if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
{
return (FALSE);
}
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &real_tag);
asn1->offset = saved_offset;
return (tag == real_tag);
}
/* dissect tid */
static int
dissect_tcap_tid(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti, int type)
@ -424,7 +412,7 @@ dissect_tcap_invokeId(ASN1_SCK *asn1, proto_tree *tree)
gboolean def_len;
#define INVOKE_ID_TAG 0x2
if (check_tcap_tag(asn1, INVOKE_ID_TAG))
if (tcap_check_tag(asn1, INVOKE_ID_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Invoke ID Tag");
@ -442,8 +430,7 @@ dissect_tcap_lnkId(ASN1_SCK *asn1, proto_tree *tree)
guint tag;
gboolean def_len;
#define LINK_ID_TAG 0x80
if (check_tcap_tag(asn1, LINK_ID_TAG))
if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Linked ID Tag");
@ -463,14 +450,14 @@ dissect_tcap_opr_code(ASN1_SCK *asn1, proto_tree *tree)
gboolean def_len;
#define TCAP_LOC_OPR_CODE_TAG 0x02
if (check_tcap_tag(asn1, TCAP_LOC_OPR_CODE_TAG))
if (tcap_check_tag(asn1, TCAP_LOC_OPR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Local Operation Code Tag");
got_it = TRUE;
}
#define TCAP_GLB_OPR_CODE_TAG 0x06
else if (check_tcap_tag(asn1, TCAP_GLB_OPR_CODE_TAG))
else if (tcap_check_tag(asn1, TCAP_GLB_OPR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Global Operation Code Tag");
@ -500,7 +487,7 @@ dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
#define TC_INVALID_TAG 0
while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
(!check_tcap_tag(asn1, 0)))
(!tcap_check_tag(asn1, 0)))
{
if ((exp_len != 0) &&
((asn1->offset - orig_offset) >= exp_len))
@ -513,7 +500,7 @@ dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
len_offset = asn1->offset;
asn1_length_decode(asn1, &def_len, &len);
if (tag == TC_SEQ_TAG)
if (TCAP_CONSTRUCTOR(tag))
{
item =
proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Sequence");
@ -533,12 +520,12 @@ dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
proto_tree_add_text(subtree, asn1->tvb,
len_offset, asn1->offset - len_offset, "Length: Indefinite");
len = find_eoc(asn1);
len = tcap_find_eoc(asn1);
}
proto_item_set_len(item,
(asn1->offset - saved_offset) + len +
(def_len ? 0 : TC_EOC_LEN));
(def_len ? 0 : TCAP_EOC_LEN));
dissect_tcap_param(asn1, subtree, len);
@ -557,7 +544,7 @@ dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
proto_tree_add_text(tree, asn1->tvb,
len_offset, asn1->offset - len_offset, "Length: Indefinite");
len = find_eoc(asn1);
len = tcap_find_eoc(asn1);
dissect_tcap_param(asn1, tree, len);
@ -643,11 +630,11 @@ dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree)
if (!def_len)
{
len = find_eoc(asn1);
len = tcap_find_eoc(asn1);
}
proto_item_set_len(item, (asn1->offset - saved_offset) + len +
(def_len ? 0 : TC_EOC_LEN));
(def_len ? 0 : TCAP_EOC_LEN));
if (len != 1)
{
@ -761,14 +748,14 @@ dissect_ansi_opr_code(ASN1_SCK *asn1, proto_tree *tree)
gboolean def_len;
#define TCAP_NAT_OPR_CODE_TAG 0xd0
if (check_tcap_tag(asn1, TCAP_NAT_OPR_CODE_TAG))
if (tcap_check_tag(asn1, TCAP_NAT_OPR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "National TCAP Operation Code Identifier");
got_it = TRUE;
}
#define TCAP_PRIV_OPR_CODE_TAG 0xd1
else if (check_tcap_tag(asn1, TCAP_PRIV_OPR_CODE_TAG))
else if (tcap_check_tag(asn1, TCAP_PRIV_OPR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Private TCAP Operation Code Identifier");
@ -800,7 +787,7 @@ dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree)
#define TCAP_PROB_CODE_TAG 0xd5
if (check_tcap_tag(asn1, TCAP_PROB_CODE_TAG))
if (tcap_check_tag(asn1, TCAP_PROB_CODE_TAG))
{
str = "Problem Code Identifier";
}
@ -941,12 +928,12 @@ dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree)
#define TCAP_NAT_ERR_CODE_TAG 0xd3
if (check_tcap_tag(asn1, TCAP_NAT_ERR_CODE_TAG))
if (tcap_check_tag(asn1, TCAP_NAT_ERR_CODE_TAG))
{
str = "National TCAP Error Code Identifier";
}
#define TCAP_PRIV_ERR_CODE_TAG 0xd4
else if (check_tcap_tag(asn1, TCAP_PRIV_ERR_CODE_TAG))
else if (tcap_check_tag(asn1, TCAP_PRIV_ERR_CODE_TAG))
{
str = "Private TCAP Error Code Identifier";
}
@ -986,14 +973,14 @@ dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree)
gboolean def_len;
#define TCAP_PARAM_SET_TAG 0xf2
if (check_tcap_tag(asn1, TCAP_PARAM_SET_TAG))
if (tcap_check_tag(asn1, TCAP_PARAM_SET_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Parameter Set Identifier");
got_it = TRUE;
}
#define TCAP_PARAM_SEQ_TAG 0x30
else if (check_tcap_tag(asn1, TCAP_PARAM_SEQ_TAG))
else if (tcap_check_tag(asn1, TCAP_PARAM_SEQ_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Parameter Sequence Identifier");
@ -1017,7 +1004,7 @@ dissect_ansi_tcap_reject(ASN1_SCK *asn1, proto_tree *tree)
proto_tree *subtree;
#define COMPONENT_ID_TAG 0xcf
if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
{
subtree = dissect_tcap_component(asn1, tree, &len);
@ -1041,7 +1028,7 @@ dissect_ansi_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
proto_tree *subtree;
#define COMPONENT_ID_TAG 0xcf
if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
{
subtree = dissect_tcap_component(asn1, tree, &len);
@ -1065,7 +1052,7 @@ dissect_ansi_tcap_rr(ASN1_SCK *asn1, proto_tree *tree)
proto_tree *subtree;
#define COMPONENT_ID_TAG 0xcf
if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
{
subtree = dissect_tcap_component(asn1, tree, &len);
@ -1087,7 +1074,7 @@ dissect_ansi_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
proto_tree *subtree;
#define COMPONENT_ID_TAG 0xcf
if (check_tcap_tag(asn1, COMPONENT_ID_TAG))
if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
{
subtree = dissect_tcap_component(asn1, tree, &len);
@ -1148,7 +1135,7 @@ dissect_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
}
else
{
len = find_eoc(asn1);
len = tcap_find_eoc(asn1);
}
dissect_tcap_param(asn1, subtree, len);
@ -1202,7 +1189,7 @@ dissect_tcap_rr(ASN1_SCK *asn1, proto_tree *tree, gchar *str)
tag = -1;
asn1_id_decode1(asn1, &tag);
if (tag == TC_SEQ_TAG)
if (TCAP_CONSTRUCTOR(tag))
{
len_offset = asn1->offset;
asn1_length_decode(asn1, &def_len, &len);
@ -1225,12 +1212,12 @@ dissect_tcap_rr(ASN1_SCK *asn1, proto_tree *tree, gchar *str)
proto_tree_add_text(seq_subtree, asn1->tvb,
len_offset, asn1->offset - len_offset, "Length: Indefinite");
len = find_eoc(asn1);
len = tcap_find_eoc(asn1);
}
proto_item_set_len(seq_item,
(asn1->offset - saved_offset) + len +
(def_len ? 0 : TC_EOC_LEN));
(def_len ? 0 : TCAP_EOC_LEN));
saved_offset = asn1->offset;
@ -1281,7 +1268,7 @@ dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
if (!comp_def_len)
{
comp_len = find_eoc(asn1);
comp_len = tcap_find_eoc(asn1);
}
saved_offset = asn1->offset;
@ -1290,12 +1277,12 @@ dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
#define TC_LOCAL_ERR_CODE_TAG 0x2
#define TC_GBL_ERR_CODE_TAG 0x6
if (check_tcap_tag(asn1, TC_LOCAL_ERR_CODE_TAG))
if (tcap_check_tag(asn1, TC_LOCAL_ERR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, subtree, &tag, "Local Error Code Tag");
}
else if (check_tcap_tag(asn1, TC_GBL_ERR_CODE_TAG))
else if (tcap_check_tag(asn1, TC_GBL_ERR_CODE_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, subtree, &tag, "Global Error Code Tag");
@ -1529,8 +1516,8 @@ dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
/* call next dissector for EACH component */
keep_len =
(comps_def_len ? 0 : TC_EOC_LEN) +
(g_tcap_ends_def_len ? 0 : TC_EOC_LEN);
(comps_def_len ? 0 : TCAP_EOC_LEN) +
(g_tcap_ends_def_len ? 0 : TCAP_EOC_LEN);
while (tvb_length_remaining(asn1->tvb, asn1->offset) > keep_len)
{
@ -1548,7 +1535,7 @@ dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
}
else
{
comp_len = (asn1->offset - saved_offset) + find_eoc(asn1) + TC_EOC_LEN;
comp_len = (asn1->offset - saved_offset) + tcap_find_eoc(asn1) + TCAP_EOC_LEN;
}
next_tvb = tvb_new_subset(asn1->tvb, saved_offset, comp_len, comp_len);
@ -1565,19 +1552,19 @@ dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
{
switch (tag)
{
case TC_INVOKE :
case TCAP_COMP_INVOKE :
dissect_tcap_invoke(asn1, subtree);
break;
case TC_RRL :
case TCAP_COMP_RRL :
dissect_tcap_rr(asn1, subtree, "Return Result(Last) Type Tag");
break;
case TC_RE :
case TCAP_COMP_RE :
dissect_tcap_re(asn1, subtree);
break;
case TC_REJECT :
case TCAP_COMP_REJECT :
dissect_tcap_reject(asn1, subtree);
break;
case TC_RRN :
case TCAP_COMP_RRN :
/* same definition as RRL */
dissect_tcap_rr(asn1, subtree, "Return Result(Not Last) Type Tag");
break;
@ -1610,7 +1597,7 @@ dissect_tcap_dlg_protocol_version(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_i
gboolean def_len;
#define TC_DLG_PROTO_VER_TAG 0x80
if (check_tcap_tag(asn1, TC_DLG_PROTO_VER_TAG))
if (tcap_check_tag(asn1, TC_DLG_PROTO_VER_TAG))
{
saved_offset = asn1->offset;
ret = asn1_id_decode1(asn1, &tag);
@ -1721,13 +1708,13 @@ dissect_tcap_dlg_result_src_diag(ASN1_SCK *asn1, proto_tree *tree)
#define TC_DIAG_SERV_USER_TAG 0xa1
#define TC_DIAG_SERV_PROV_TAG 0xa2
if (check_tcap_tag(asn1, TC_DIAG_SERV_USER_TAG))
if (tcap_check_tag(asn1, TC_DIAG_SERV_USER_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service User Tag");
user = TRUE;
}
else if (check_tcap_tag(asn1, TC_DIAG_SERV_PROV_TAG))
else if (tcap_check_tag(asn1, TC_DIAG_SERV_PROV_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service Provider Tag");
@ -1800,14 +1787,14 @@ dissect_tcap_dlg_user_info(ASN1_SCK *asn1, proto_tree *tree)
gboolean user_info_def_len;
#define TC_USR_INFO_TAG 0xbe
if (check_tcap_tag(asn1, TC_USR_INFO_TAG))
if (tcap_check_tag(asn1, TC_USR_INFO_TAG))
{
tag = -1;
dissect_tcap_tag(asn1, tree, &tag, "User Info Tag");
dissect_tcap_len(asn1, tree, &user_info_def_len, &len);
#define TC_EXT_TAG 0x28
if (check_tcap_tag(asn1, TC_EXT_TAG))
if (tcap_check_tag(asn1, TC_EXT_TAG))
{
saved_offset = asn1->offset;
asn1_id_decode1(asn1, &tag);
@ -2114,7 +2101,7 @@ dissect_tcap_abort_reason(ASN1_SCK *asn1, proto_tree *tcap_tree)
#define TC_PABRT_REASON_TAG 0x4a
tag = TC_PABRT_REASON_TAG;
if (check_tcap_tag(asn1, tag))
if (tcap_check_tag(asn1, tag))
{
saved_offset = asn1->offset;
item =

View File

@ -1,6 +1,6 @@
/* packet-tcap.h
*
* $Id: packet-tcap.h,v 1.2 2003/12/21 04:31:57 jmayer Exp $
* $Id: packet-tcap.h,v 1.3 2004/03/19 07:54:58 guy Exp $
*
* Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
* In association with Telos Technology Inc.
@ -27,8 +27,38 @@
*/
typedef enum {
ITU_TCAP_STANDARD = 1,
ANSI_TCAP_STANDARD = 2
ITU_TCAP_STANDARD = 1,
ANSI_TCAP_STANDARD = 2
} Tcap_Standard_Type;
extern Tcap_Standard_Type tcap_standard;
extern const value_string tcap_component_type_str[];
/* TCAP component type */
#define TCAP_COMP_INVOKE 0xa1
#define TCAP_COMP_RRL 0xa2
#define TCAP_COMP_RE 0xa3
#define TCAP_COMP_REJECT 0xa4
#define TCAP_COMP_RRN 0xa7
/* ANSI TCAP component type */
#define ANSI_TC_INVOKE_L 0xe9
#define ANSI_TC_RRL 0xea
#define ANSI_TC_RE 0xeb
#define ANSI_TC_REJECT 0xec
#define ANSI_TC_INVOKE_N 0xed
#define ANSI_TC_RRN 0xee
#define TCAP_SEQ_TAG 0x30
#define TCAP_SET_TAG 0x31
#define TCAP_INVOKE_ID_TAG 0x02
#define TCAP_LINKED_ID_TAG 0x80
#define TCAP_EOC_LEN 2 /* 0x00 0x00 */
#define TCAP_CONSTRUCTOR(TCtag) (TCtag & 0x20)
extern int tcap_find_eoc(ASN1_SCK *asn1);
extern gboolean tcap_check_tag(ASN1_SCK *asn1, guint tag);