diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | Makefile.common | 3 | ||||
-rw-r--r-- | epan/Makefile.common | 3 | ||||
-rw-r--r-- | packet-ansi_801.c | 956 | ||||
-rw-r--r-- | packet-ansi_a.c | 17 | ||||
-rw-r--r-- | packet-ansi_map.c | 15 | ||||
-rw-r--r-- | packet-gsm_map.c | 147 | ||||
-rw-r--r-- | packet-gsm_sms.c | 19 | ||||
-rw-r--r-- | packet-gsm_sms.h | 29 | ||||
-rw-r--r-- | packet-gsm_ss.c | 1273 | ||||
-rw-r--r-- | packet-gsm_ss.h | 3 |
11 files changed, 2289 insertions, 177 deletions
@@ -1832,6 +1832,7 @@ Michael Lum <mlum [AT] telostech.com> { ALCAP (Q.2630.1) support IS-637-A (SMS) support IS-683-A (OTA) support + IS-801 (PLD) support BSSAP (GSM 08.06)/BSAP (IOS 4.0.1) support IOS 4.0.1 support GSM BSSMAP (GSM 08.08) support diff --git a/Makefile.common b/Makefile.common index 6990acb472..ed070f6d29 100644 --- a/Makefile.common +++ b/Makefile.common @@ -3,7 +3,7 @@ # a) common to both files and # b) portable between both files # -# $Id: Makefile.common,v 1.36 2004/03/26 02:10:46 guy Exp $ +# $Id: Makefile.common,v 1.37 2004/03/27 11:32:26 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -97,6 +97,7 @@ DISSECTOR_INCLUDES = \ packet-gnutella.h \ packet-gsm_a.h \ packet-gsm_map.h \ + packet-gsm_sms.h \ packet-gsm_ss.h \ packet-gssapi.h \ packet-gtp.h \ diff --git a/epan/Makefile.common b/epan/Makefile.common index f551c842ac..8d0bf091c9 100644 --- a/epan/Makefile.common +++ b/epan/Makefile.common @@ -3,7 +3,7 @@ # a) common to both files and # b) portable between both files # -# $Id: Makefile.common,v 1.13 2004/03/23 19:51:06 guy Exp $ +# $Id: Makefile.common,v 1.14 2004/03/27 11:32:30 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -57,6 +57,7 @@ DISSECTOR_SRC = \ ../packet-ans.c \ ../packet-ansi_637.c \ ../packet-ansi_683.c \ + ../packet-ansi_801.c \ ../packet-ansi_a.c \ ../packet-ansi_map.c \ ../packet-aodv.c \ diff --git a/packet-ansi_801.c b/packet-ansi_801.c new file mode 100644 index 0000000000..371f312ee6 --- /dev/null +++ b/packet-ansi_801.c @@ -0,0 +1,956 @@ +/* packet-ansi_801.c + * Routines for ANSI IS-801 (Location Services (PLD)) dissection + * + * Location Services (Position Determination Service) + * 3GPP2 C.S0022-0 v1.0 IS-801 + * + * Location Services (Position Determination Service) + * 3GPP2 C.S0022-0-1 v1.0 IS-801 Addendum + * + * Copyright 2004, Michael Lum <mlum [AT] telostech.com> + * In association with Telos Technology Inc. + * + * $Id: packet-ansi_801.c,v 1.1 2004/03/27 11:32:27 guy Exp $ + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <gmodule.h> + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif + +#include <string.h> + +#include "epan/packet.h" + + +static char *ansi_proto_name = "ANSI IS-801 (Location Services (PLD))"; +static char *ansi_proto_name_short = "IS-801"; + +#define ANSI_801_FORWARD 0 +#define ANSI_801_REVERSE 1 + + +/* Initialize the subtree pointers */ +static gint ett_ansi_801 = -1; + +/* Initialize the protocol and registered fields */ +static int proto_ansi_801 = -1; +static int hf_ansi_801_for_req_type = -1; +static int hf_ansi_801_for_rsp_type = -1; +static int hf_ansi_801_rev_req_type = -1; +static int hf_ansi_801_rev_rsp_type = -1; +static int hf_ansi_801_for_sess_tag = -1; +static int hf_ansi_801_rev_sess_tag = -1; +static int hf_ansi_801_sess_tag = -1; + +static char bigbuf[1024]; +static dissector_handle_t data_handle; +static packet_info *g_pinfo; +static proto_tree *g_tree; + + +/* 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); +} + + +/* PARAM FUNCTIONS */ + +#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \ + if ((edc_len) > (edc_max_len)) \ + { \ + proto_tree_add_text(tree, tvb, \ + offset, (edc_len) - (edc_max_len), "Extraneous Data"); \ + } + +#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \ + if ((sdc_len) < (sdc_min_len)) \ + { \ + proto_tree_add_text(tree, tvb, \ + offset, (sdc_len), "Short Data (?)"); \ + return; \ + } + +#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \ + if ((edc_len) != (edc_eq_len)) \ + { \ + proto_tree_add_text(tree, tvb, \ + offset, (edc_len), "Unexpected Data Length"); \ + return; \ + } + + +static void +for_req_pseudo_meas(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) +{ + guint32 value; + guint32 saved_offset; + + SHORT_DATA_CHECK(len, 3); + + saved_offset = offset; + + value = tvb_get_ntoh24(tvb, offset); + + other_decode_bitfield_value(bigbuf, value >> 16, 0xe0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Preferred response quality, %u", + bigbuf, + (value & 0xe00000) >> 21); + + other_decode_bitfield_value(bigbuf, value >> 16, 0x1f, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number of fixes (MSB), %u", + bigbuf, + (value & 0x1fe000) >> 13); + + other_decode_bitfield_value(bigbuf, value >> 8, 0xe0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number of fixes (LSB)", + bigbuf); + + other_decode_bitfield_value(bigbuf, value >> 8, 0x1f, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Time between fixes (MSB), %u", + bigbuf, + (value & 0x001fe0) >> 5); + + other_decode_bitfield_value(bigbuf, value, 0xe0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Time between fixes (LSB)", + bigbuf); + + other_decode_bitfield_value(bigbuf, value, 0x10, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Offset %srequested", + bigbuf, + (value & 0x10) ? "" : "not "); + + other_decode_bitfield_value(bigbuf, value, 0x0f, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Reserved", + bigbuf); + + offset += 3; + + EXTRANEOUS_DATA_CHECK(len, offset - saved_offset); +} + +static const value_string for_req_type_strings[] = { + { 0, "Reserved" }, + { 2, "Request MS Information" }, + { 3, "Request Autonomous Measurement Weighting Factors" }, + { 4, "Request Pseudorange Measurement" }, + { 5, "Request Pilot Phase Measurement" }, + { 1, "Request Location Response" }, + { 6, "Request Time Offset Measurement" }, + { 7, "Request Cancellation" }, + { 0, NULL }, +}; +#define NUM_FOR_REQ_TYPE (sizeof(for_req_type_strings)/sizeof(value_string)) +static gint ett_for_req_type[NUM_FOR_REQ_TYPE]; +static void (*for_req_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = { + NULL, /* Reserved */ + NULL, /* Request MS Information */ + NULL, /* Request Autonomous Measurement Weighting Factors */ + for_req_pseudo_meas, /* Request Pseudorange Measurement */ + NULL, /* Request Pilot Phase Measurement */ + NULL, /* Request Location Response */ + NULL, /* Request Time Offset Measurement */ + NULL, /* Request Cancellation */ + NULL, /* NONE */ +}; + +static const value_string for_rsp_type_strings[] = { + { 0, "Reject" }, + { 2, "Provide BS Capabilities" }, + { 4, "Provide GPS Acquisition Assistance" }, + { 6, "Provide GPS Location Assistance Spherical Coordinates" }, + { 7, "Provide GPS Location Assistance Cartesian Coordinates" }, + { 5, "Provide GPS Sensitivity Assistance" }, + { 3, "Provide Base Station Almanac" }, + { 8, "Provide GPS Almanac" }, + { 9, "Provide GPS Ephemeris" }, + { 10, "Provide GPS Navigation Message Bits" }, + { 1, "Provide Location Response" }, + { 11, "Provide GPS Almanac Correction" }, + { 12, "Provide GPS Satellite Health Information" }, + { 0, NULL }, +}; +#define NUM_FOR_RSP_TYPE (sizeof(for_rsp_type_strings)/sizeof(value_string)) +static gint ett_for_rsp_type[NUM_FOR_RSP_TYPE]; +static void (*for_rsp_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = { + NULL, /* Reject */ + NULL, /* Provide BS Capabilities */ + NULL, /* Provide GPS Acquisition Assistance */ + NULL, /* Provide GPS Location Assistance Spherical Coordinates */ + NULL, /* Provide GPS Location Assistance Cartesian Coordinates */ + NULL, /* Provide GPS Sensitivity Assistance */ + NULL, /* Provide Base Station Almanac */ + NULL, /* Provide GPS Almanac */ + NULL, /* Provide GPS Ephemeris */ + NULL, /* Provide GPS Navigation Message Bits */ + NULL, /* Provide Location Response */ + NULL, /* Provide GPS Almanac Correction */ + NULL, /* Provide GPS Satellite Health Information */ + NULL, /* NONE */ +}; + +static const value_string rev_req_type_strings[] = { + { 0, "Reserved" }, + { 2, "Request BS Capabilities" }, + { 4, "Request GPS Acquisition Assistance" }, + { 6, "Request GPS Location Assistance" }, + { 7, "Reserved" }, + { 5, "Request GPS Sensitivity Assistance" }, + { 3, "Request Base Station Almanac" }, + { 8, "Request GPS Almanac" }, + { 9, "Request GPS Ephemeris" }, + { 10, "Request GPS Navigation Message Bits" }, + { 1, "Request Location Response" }, + { 11, "Request GPS Almanac Correction" }, + { 12, "Request GPS Satellite Health Information" }, + { 0, NULL }, +}; +#define NUM_REV_REQ_TYPE (sizeof(rev_req_type_strings)/sizeof(value_string)) +static gint ett_rev_req_type[NUM_REV_REQ_TYPE]; +static void (*rev_req_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = { + NULL, /* Reserved */ + NULL, /* Request BS Capabilities */ + NULL, /* Request GPS Acquisition Assistance */ + NULL, /* Request GPS Location Assistance */ + NULL, /* Reserved */ + NULL, /* Request GPS Sensitivity Assistance */ + NULL, /* Request Base Station Almanac */ + NULL, /* Request GPS Almanac */ + NULL, /* Request GPS Ephemeris */ + NULL, /* Request GPS Navigation Message Bits */ + NULL, /* Request Location Response */ + NULL, /* Request GPS Almanac Correction */ + NULL, /* Request GPS Satellite Health Information */ + NULL, /* NONE */ +}; + +static const value_string rev_rsp_type_strings[] = { + { 0, "Reject" }, + { 2, "Provide MS Information" }, + { 3, "Provide Autonomous Measurement Weighting Factors" }, + { 4, "Provide Pseudorange Measurement" }, + { 5, "Provide Pilot Phase Measurement" }, + { 1, "Provide Location Response" }, + { 6, "Provide Time Offset Measurement" }, + { 7, "Provide Cancellation Acknowledgement" }, + { 0, NULL }, +}; +#define NUM_REV_RSP_TYPE (sizeof(rev_rsp_type_strings)/sizeof(value_string)) +static gint ett_rev_rsp_type[NUM_REV_RSP_TYPE]; +static void (*rev_rsp_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = { + NULL, /* Reject */ + NULL, /* Provide MS Information */ + NULL, /* Provide Autonomous Measurement Weighting Factors */ + NULL, /* Provide Pseudorange Measurement */ + NULL, /* Provide Pilot Phase Measurement */ + NULL, /* Provide Location Response */ + NULL, /* Provide Time Offset Measurement */ + NULL, /* Provide Cancellation Acknowledgement */ + NULL, /* NONE */ +}; + +static void +for_request(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p) +{ + guint32 offset; + guint8 oct; + gchar *str = NULL; + gint idx; + proto_tree *subtree; + proto_item *item; + + offset = *offset_p; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0xf0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Reserved", + bigbuf); + + str = my_match_strval(oct & 0x0f, for_req_type_strings, &idx); + + if (str == NULL) + { + return; + } + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + item = + proto_tree_add_uint_format(tree, hf_ansi_801_for_req_type, tvb, offset, + 1, oct & 0x0f, + "%s : Request Type, %s (%u)", + bigbuf, + str, + oct & 0x0f); + + subtree = proto_item_add_subtree(item, ett_for_req_type[idx]); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + proto_tree_add_text(subtree, tvb, offset, 1, + "Length: %u", + oct); + + offset++; + + if (for_req_type_fcn[idx] != NULL) + { + (*for_req_type_fcn[idx])(tvb, subtree, oct, offset); + } + else + { + proto_tree_add_text(subtree, tvb, offset, oct, + "Data"); + } + + *offset_p = offset + oct; +} + +static void +for_response(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p) +{ + guint32 offset; + guint8 oct; + gchar *str = NULL; + gint idx; + proto_tree *subtree; + proto_item *item; + + offset = *offset_p; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0xe0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Reserved", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x10, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Unsolicited response indicator", + bigbuf); + + str = my_match_strval(oct & 0x0f, for_rsp_type_strings, &idx); + + if (str == NULL) + { + return; + } + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + item = + proto_tree_add_uint_format(tree, hf_ansi_801_for_rsp_type, tvb, offset, + 1, oct & 0x0f, + "%s : Response Type, %s (%u)", + bigbuf, + str, + oct & 0x0f); + + subtree = proto_item_add_subtree(item, ett_for_rsp_type[idx]); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + proto_tree_add_text(subtree, tvb, offset, 1, + "Length: %u", + oct); + + offset++; + + if (for_rsp_type_fcn[idx] != NULL) + { + (*for_rsp_type_fcn[idx])(tvb, subtree, oct, offset); + } + else + { + proto_tree_add_text(subtree, tvb, offset, oct, + "Data"); + } + + *offset_p = offset + oct; +} + +static void +rev_request(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p) +{ + guint32 offset; + guint8 oct; + gchar *str = NULL; + gint idx; + proto_tree *subtree; + proto_item *item; + + offset = *offset_p; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0xf0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Reserved", + bigbuf); + + str = my_match_strval(oct & 0x0f, rev_req_type_strings, &idx); + + if (str == NULL) + { + return; + } + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + item = + proto_tree_add_uint_format(tree, hf_ansi_801_rev_req_type, tvb, offset, + 1, oct & 0x0f, + "%s : Request Type, %s (%u)", + bigbuf, + str, + oct & 0x0f); + + subtree = proto_item_add_subtree(item, ett_rev_req_type[idx]); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + proto_tree_add_text(subtree, tvb, offset, 1, + "Length: %u", + oct); + + offset++; + + if (rev_req_type_fcn[idx] != NULL) + { + (*rev_req_type_fcn[idx])(tvb, subtree, oct, offset); + } + else + { + proto_tree_add_text(subtree, tvb, offset, oct, + "Data"); + } + + *offset_p = offset + oct; +} + +static void +rev_response(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p) +{ + guint32 offset; + guint8 oct; + gchar *str = NULL; + gint idx; + proto_tree *subtree; + proto_item *item; + + offset = *offset_p; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0xe0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Reserved", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x10, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Unsolicited response indicator", + bigbuf); + + str = my_match_strval(oct & 0x0f, rev_rsp_type_strings, &idx); + + if (str == NULL) + { + return; + } + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + item = + proto_tree_add_uint_format(tree, hf_ansi_801_rev_rsp_type, tvb, offset, + 1, oct & 0x0f, + "%s : Response Type, %s (%u)", + bigbuf, + str, + oct & 0x0f); + + subtree = proto_item_add_subtree(item, ett_rev_rsp_type[idx]); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + proto_tree_add_text(subtree, tvb, offset, 1, + "Length: %u", + oct); + + offset++; + + if (rev_rsp_type_fcn[idx] != NULL) + { + (*rev_rsp_type_fcn[idx])(tvb, subtree, oct, offset); + } + else + { + proto_tree_add_text(subtree, tvb, offset, oct, + "Data"); + } + + *offset_p = offset + oct; +} + +static void +dissect_ansi_801_for_message(tvbuff_t *tvb, proto_tree *tree) +{ + guint32 offset; + guint8 oct, num_req, num_rsp; + guint rem_len; + gchar *str = NULL; + + offset = 0; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0x80, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session Start", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x40, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session End", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x20, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session Source", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x1f, 8); + proto_tree_add_uint_format(tree, hf_ansi_801_for_sess_tag, tvb, offset, + 1, oct & 0x1f, + "%s : Session Tag (%u)", + bigbuf, + oct & 0x1f); + + proto_tree_add_uint_hidden(tree, hf_ansi_801_sess_tag, tvb, offset, + 1, oct & 0x1f); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + switch (oct) + { + case 0x00: str = "Position Determination Data Message"; break; + case 0xff: str = "Reserved"; break; + default: + if (oct < 0xc0) + { + str = "Reserved for future standardization"; + } + else + { + str = + "Available for manufacturer-specific Position Determination " + "Data Message definition as specified in TSB-58"; + } + break; + } + + other_decode_bitfield_value(bigbuf, oct, 0xff, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : PD Message Type, %s (%u)", + bigbuf, + str, + oct); + + offset++; + + if (oct == 0x00) + { + oct = tvb_get_guint8(tvb, offset); + + num_req = (oct & 0xf0) >> 4; + num_rsp = oct & 0x0f; + + other_decode_bitfield_value(bigbuf, oct, 0xf0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number Requests (%u)", + bigbuf, + num_req); + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number Responses (%u)", + bigbuf, + num_rsp); + + offset++; + rem_len = tvb_length_remaining(tvb, offset); + + while ((num_req > 0) && + (rem_len >= 2)) + { + for_request(tvb, tree, &offset); + + rem_len = tvb_length_remaining(tvb, offset); + num_req--; + } + + if (num_req != 0) + { + proto_tree_add_text(tree, tvb, + offset, -1, "Short Data (?)"); + return; + } + + while ((num_rsp > 0) && + (rem_len >= 2)) + { + for_response(tvb, tree, &offset); + + rem_len = tvb_length_remaining(tvb, offset); + num_rsp--; + } + + if (num_rsp != 0) + { + proto_tree_add_text(tree, tvb, + offset, -1, "Short Data (?)"); + return; + } + + if (rem_len > 0) + { + proto_tree_add_text(tree, tvb, offset, rem_len, + "Extraneous Data"); + } + } + else + { + proto_tree_add_text(tree, tvb, offset, -1, + "Reserved/Proprietary/Future Data"); + } +} + +static void +dissect_ansi_801_rev_message(tvbuff_t *tvb, proto_tree *tree) +{ + guint32 offset; + guint8 oct, num_req, num_rsp; + guint rem_len; + gchar *str = NULL; + + offset = 0; + oct = tvb_get_guint8(tvb, offset); + + other_decode_bitfield_value(bigbuf, oct, 0x80, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session Start", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x40, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session End", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x20, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Session Source", + bigbuf); + + other_decode_bitfield_value(bigbuf, oct, 0x1f, 8); + proto_tree_add_uint_format(tree, hf_ansi_801_rev_sess_tag, tvb, offset, + 1, oct & 0x1f, + "%s : Session Tag (%u)", + bigbuf, + oct & 0x1f); + + proto_tree_add_uint_hidden(tree, hf_ansi_801_sess_tag, tvb, offset, + 1, oct & 0x1f); + + offset++; + oct = tvb_get_guint8(tvb, offset); + + switch (oct) + { + case 0x00: str = "Position Determination Data Message"; break; + case 0xff: str = "Reserved"; break; + default: + if (oct < 0xc0) + { + str = "Reserved for future standardization"; + } + else + { + str = + "Available for manufacturer-specific Position Determination " + "Data Message definition as specified in TSB-58"; + } + break; + } + + other_decode_bitfield_value(bigbuf, oct, 0xff, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : PD Message Type, %s (%u)", + bigbuf, + str, + oct); + + offset++; + + if (oct == 0x00) + { + oct = tvb_get_guint8(tvb, offset); + + num_req = (oct & 0xf0) >> 4; + num_rsp = oct & 0x0f; + + other_decode_bitfield_value(bigbuf, oct, 0xf0, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number Requests (%u)", + bigbuf, + num_req); + + other_decode_bitfield_value(bigbuf, oct, 0x0f, 8); + proto_tree_add_text(tree, tvb, offset, 1, + "%s : Number Responses (%u)", + bigbuf, + num_rsp); + + offset++; + rem_len = tvb_length_remaining(tvb, offset); + + while ((num_req > 0) && + (rem_len >= 2)) + { + rev_request(tvb, tree, &offset); + + rem_len = tvb_length_remaining(tvb, offset); + num_req--; + } + + if (num_req != 0) + { + proto_tree_add_text(tree, tvb, + offset, -1, "Short Data (?)"); + return; + } + + while ((num_rsp > 0) && + (rem_len >= 2)) + { + rev_response(tvb, tree, &offset); + + rem_len = tvb_length_remaining(tvb, offset); + num_rsp--; + } + + if (num_rsp != 0) + { + proto_tree_add_text(tree, tvb, + offset, -1, "Short Data (?)"); + return; + } + + if (rem_len > 0) + { + proto_tree_add_text(tree, tvb, offset, rem_len, + "Extraneous Data"); + } + } + else + { + proto_tree_add_text(tree, tvb, offset, -1, + "Reserved/Proprietary/Future Data"); + } +} + +static void +dissect_ansi_801(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ansi_801_item; + proto_tree *ansi_801_tree = NULL; + + g_pinfo = pinfo; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + { + col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short); + } + + /* In the interest of speed, if "tree" is NULL, don't do any work not + * necessary to generate protocol tree items. + */ + if (tree) + { + g_tree = tree; + + /* + * create the ansi_801 protocol tree + */ + ansi_801_item = + proto_tree_add_protocol_format(tree, proto_ansi_801, tvb, 0, -1, + "%s %s Link", + ansi_proto_name, + (pinfo->match_port == ANSI_801_FORWARD) ? "Forward" : "Reverse"); + + ansi_801_tree = + proto_item_add_subtree(ansi_801_item, ett_ansi_801); + + if (pinfo->match_port == ANSI_801_FORWARD) + { + dissect_ansi_801_for_message(tvb, ansi_801_tree); + } + else + { + dissect_ansi_801_rev_message(tvb, ansi_801_tree); + } + } +} + + +/* Register the protocol with Ethereal */ +void +proto_register_ansi_801(void) +{ + guint i; + gint last_offset; + + /* Setup list of header fields */ + static hf_register_info hf[] = + { + { &hf_ansi_801_for_req_type, + { "Forward Request Type", "ansi_801.for_req_type", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_for_rsp_type, + { "Forward Response Type", "ansi_801.for_rsp_type", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_rev_req_type, + { "Reverse Request Type", "ansi_801.rev_req_type", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_rev_rsp_type, + { "Reverse Response Type", "ansi_801.rev_rsp_type", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_for_sess_tag, + { "Forward Session Tag", "ansi_801.for_sess_tag", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_rev_sess_tag, + { "Reverse Session Tag", "ansi_801.rev_sess_tag", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + { &hf_ansi_801_sess_tag, + { "Session Tag", "ansi_801.sess_tag", + FT_UINT8, BASE_DEC, NULL, 0, + "", HFILL } + }, + }; + + /* Setup protocol subtree array */ +#define NUM_INDIVIDUAL_PARAMS 1 + gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_FOR_REQ_TYPE+NUM_FOR_RSP_TYPE+NUM_REV_REQ_TYPE+NUM_REV_RSP_TYPE]; + + ett[0] = &ett_ansi_801; + + last_offset = NUM_INDIVIDUAL_PARAMS; + + for (i=0; i < NUM_FOR_REQ_TYPE; i++, last_offset++) + { + ett[last_offset] = &ett_for_req_type[i]; + } + + for (i=0; i < NUM_FOR_RSP_TYPE; i++, last_offset++) + { + ett[last_offset] = &ett_for_rsp_type[i]; + } + + for (i=0; i < NUM_REV_REQ_TYPE; i++, last_offset++) + { + ett[last_offset] = &ett_rev_req_type[i]; + } + + for (i=0; i < NUM_REV_RSP_TYPE; i++, last_offset++) + { + ett[last_offset] = &ett_rev_rsp_type[i]; + } + + /* Register the protocol name and description */ + proto_ansi_801 = + proto_register_protocol(ansi_proto_name, "ANSI IS-801 (Location Services (PLD))", "ansi_801"); + + /* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_ansi_801, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + + +void +proto_reg_handoff_ansi_801(void) +{ + dissector_handle_t ansi_801_handle; + + ansi_801_handle = create_dissector_handle(dissect_ansi_801, proto_ansi_801); + + dissector_add("ansi_map.pld", ANSI_801_FORWARD, ansi_801_handle); + dissector_add("ansi_map.pld", ANSI_801_REVERSE, ansi_801_handle); + dissector_add("ansi_a.pld", ANSI_801_FORWARD, ansi_801_handle); + dissector_add("ansi_a.pld", ANSI_801_REVERSE, ansi_801_handle); + + data_handle = find_dissector("data"); +} diff --git a/packet-ansi_a.c b/packet-ansi_a.c index d87f9723bf..58100ea79a 100644 --- a/packet-ansi_a.c +++ b/packet-ansi_a.c @@ -10,7 +10,7 @@ * 2000 Access Network Interfaces * 3GPP2 A.S0001-1 TIA/EIA-2001 * - * $Id: packet-ansi_a.c,v 1.15 2003/12/21 04:31:56 jmayer Exp $ + * $Id: packet-ansi_a.c,v 1.16 2004/03/27 11:32:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -374,6 +374,7 @@ static dissector_handle_t bsmap_handle; static dissector_handle_t dtap_handle; static dissector_table_t is637_dissector_table; /* IS-637-A Transport Layer (SMS) */ static dissector_table_t is683_dissector_table; /* IS-683-A (OTA) */ +static dissector_table_t is801_dissector_table; /* IS-801 (PLD) */ static packet_info *g_pinfo; static proto_tree *g_tree; @@ -4172,7 +4173,15 @@ elem_adds_user_part(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, (g_pinfo->p2p_dir == P2P_DIR_RECV), adds_tvb, g_pinfo, g_tree); break; - case ADDS_APP_PLD: str = "PLD"; break; + case ADDS_APP_PLD: + str = "PLD"; + + adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1); + + dissector_try_port(is801_dissector_table, + (g_pinfo->p2p_dir == P2P_DIR_RECV), adds_tvb, g_pinfo, g_tree); + break; + default: str = "Unknown"; break; @@ -8400,6 +8409,10 @@ proto_register_ansi_a(void) register_dissector_table("ansi_a.ota", "IS-683-A (OTA)", FT_UINT8, BASE_DEC); + is801_dissector_table = + register_dissector_table("ansi_a.pld", "IS-801 (PLD)", + FT_UINT8, BASE_DEC); + proto_register_subtree_array(ett, ett_len / sizeof(gint *)); ansi_a_tap = register_tap("ansi_a"); diff --git a/packet-ansi_map.c b/packet-ansi_map.c index d560127440..8d149d9d2b 100644 --- a/packet-ansi_map.c +++ b/packet-ansi_map.c @@ -79,7 +79,7 @@ * UIM * 3GPP2 N.S0003 * - * $Id: packet-ansi_map.c,v 1.13 2003/12/12 19:55:26 guy Exp $ + * $Id: packet-ansi_map.c,v 1.14 2004/03/27 11:32:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -670,10 +670,12 @@ static gchar ansi_map_add_string[1024]; static dissector_handle_t data_handle; static dissector_table_t is637_tele_id_dissector_table; /* IS-637 Teleservice ID */ static dissector_table_t is683_dissector_table; /* IS-683-A (OTA) */ +static dissector_table_t is801_dissector_table; /* IS-801 (PLD) */ static packet_info *g_pinfo; static proto_tree *g_tree; static gint32 ansi_map_sms_tele_id = -1; static gboolean is683_ota; +static gboolean is801_pld; static gboolean ansi_map_is_invoke; @@ -863,7 +865,7 @@ param_srvc_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) case 1: str = "CDMA OTASP Service"; is683_ota = TRUE; break; case 2: str = "TDMA OTASP Service"; break; case 3: str = "CDMA OTAPA Service"; is683_ota = TRUE; break; - case 4: str = "CDMA Position Determination Service"; break; + case 4: str = "CDMA Position Determination Service"; is801_pld = TRUE; break; case 5: str = "AMPS Position Determination Service"; break; default: if ((value >= 6) && (value <= 223)) { str = "Reserved, treat as Undefined Service"; } @@ -11748,6 +11750,10 @@ param_sms_bd(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) { dissector_try_port(is683_dissector_table, ansi_map_is_invoke ? 0 : 1, next_tvb, g_pinfo, g_tree); } + else if (is801_pld) + { + dissector_try_port(is801_dissector_table, ansi_map_is_invoke ? 0 : 1, next_tvb, g_pinfo, g_tree); + } proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, @@ -13083,6 +13089,7 @@ dissect_ansi_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) ansi_map_is_invoke = FALSE; is683_ota = FALSE; + is801_pld = FALSE; dissect_ansi_map_message(&asn1, pinfo, ansi_map_tree); asn1_close(&asn1, &offset); @@ -13189,6 +13196,10 @@ proto_register_ansi_map(void) register_dissector_table("ansi_map.ota", "IS-683-A (OTA)", FT_UINT8, BASE_DEC); + is801_dissector_table = + register_dissector_table("ansi_map.pld", "IS-801 (PLD)", + FT_UINT8, BASE_DEC); + /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_ansi_map, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); diff --git a/packet-gsm_map.c b/packet-gsm_map.c index 1a0b1a6276..c2166caa19 100644 --- a/packet-gsm_map.c +++ b/packet-gsm_map.c @@ -7,7 +7,7 @@ * Changed to run on new version of TCAP, many changes for * EOC matching, and parameter separation. (2003) * - * $Id: packet-gsm_map.c,v 1.9 2004/03/19 07:54:57 guy Exp $ + * $Id: packet-gsm_map.c,v 1.10 2004/03/27 11:32:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -407,23 +407,6 @@ my_match_strval(guint32 val, const value_string *vs, gint *idx) return(NULL); } -static gboolean -check_map_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); -} - #define GSM_MAP_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \ { \ guint _len_offset; \ @@ -469,7 +452,7 @@ dissect_map_params(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && - (!check_map_tag(asn1, 0))) + (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) @@ -642,84 +625,6 @@ param_alertReason(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) saved_offset, len, str); } -static void -param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) -{ - guint saved_offset; - gint32 value; - guchar *poctets; - gchar *str = NULL; - char bigbuf[1024]; - - saved_offset = asn1->offset; - asn1_int32_value_decode(asn1, 1, &value); - - other_decode_bitfield_value(bigbuf, value, 0x80, 8); - proto_tree_add_text(tree, asn1->tvb, - saved_offset, 1, - "%s : %sxtension", - bigbuf, (value & 0x80) ? "No E" : "E"); - - switch ((value & 0x70) >> 4) - { - case 0x00: str = "unknown"; break; - case 0x01: str = "International Number"; break; - case 0x02: str = "National Significant Number"; break; - case 0x03: str = "Network Specific Number"; break; - case 0x04: str = "Subscriber Number"; break; - case 0x05: str = "Reserved"; break; - case 0x06: str = "Abbreviated Number"; break; - case 0x07: str = "Reserved for extension"; break; - } - - other_decode_bitfield_value(bigbuf, value, 0x70, 8); - proto_tree_add_text(tree, asn1->tvb, - saved_offset, asn1->offset - saved_offset, - "%s : %s", - bigbuf, str); - - switch (value & 0x0f) - { - case 0x00: str = "unknown"; break; - case 0x01: str = "ISDN/Telephony Numbering (Rec ITU-T E.164)"; break; - case 0x02: str = "spare"; break; - case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break; - case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break; - case 0x05: str = "spare"; break; - case 0x06: str = "Land Mobile Numbering (ITU-T Rec. E.212)"; break; - case 0x07: str = "spare"; break; - case 0x08: str = "National Numbering"; break; - case 0x09: str = "Private Numbering"; break; - case 0x0f: str = "Reserved for extension"; break; - default: - str = "Reserved"; - break; - } - - other_decode_bitfield_value(bigbuf, value, 0x0f, 8); - proto_tree_add_text(tree, asn1->tvb, - saved_offset, asn1->offset - saved_offset, - "%s : %s", - bigbuf, str); - - saved_offset = asn1->offset; - asn1_string_value_decode(asn1, len - 1, &poctets); - - my_dgt_tbcd_unpack(bigbuf, poctets, len - 1, &Dgt_msid); - g_free(poctets); - - if (hf_field == -1) - { - proto_tree_add_text(tree, asn1->tvb, - saved_offset, len - 1, "BCD Digits %s", bigbuf); - } - else - { - proto_tree_add_string_format(tree, hf_field, asn1->tvb, - saved_offset, len - 1, bigbuf, "BCD Digits %s", bigbuf); - } -} - typedef enum { @@ -913,7 +818,7 @@ param_TripletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && - (!check_map_tag(asn1, 0))) + (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) @@ -961,7 +866,7 @@ param_QuintupletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) orig_offset = asn1->offset; while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && - (!check_map_tag(asn1, 0))) + (!tcap_check_tag(asn1, 0))) { if ((exp_len != 0) && ((asn1->offset - orig_offset) >= exp_len)) @@ -1526,7 +1431,7 @@ op_send_rti_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) start_offset = asn1->offset; - if (check_map_tag(asn1, 0x89)) + if (tcap_check_tag(asn1, 0x89)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1581,7 +1486,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number"); - if (check_map_tag(asn1, 0x82)) + if (tcap_check_tag(asn1, 0x82)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1589,7 +1494,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN"); } - if (check_map_tag(asn1, 0x84)) + if (tcap_check_tag(asn1, 0x84)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1597,7 +1502,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI"); } - if (check_map_tag(asn1, 0x85)) + if (tcap_check_tag(asn1, 0x85)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1605,7 +1510,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "GSM Bearer Capability"); } - if (check_map_tag(asn1, 0xa6)) + if (tcap_check_tag(asn1, 0xa6)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1613,7 +1518,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Network Signal Info"); } - if (check_map_tag(asn1, 0x87)) + if (tcap_check_tag(asn1, 0x87)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1621,7 +1526,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Suppression Of Announcement"); } - if (check_map_tag(asn1, 0x88)) + if (tcap_check_tag(asn1, 0x88)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1629,7 +1534,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_GMSC_ADDR, "GMSC Address"); } - if (check_map_tag(asn1, 0x89)) + if (tcap_check_tag(asn1, 0x89)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1637,7 +1542,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Call Reference Number"); } - if (check_map_tag(asn1, 0x8a)) + if (tcap_check_tag(asn1, 0x8a)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1645,7 +1550,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Interrogation"); } - if (check_map_tag(asn1, 0x8b)) + if (tcap_check_tag(asn1, 0x8b)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1653,7 +1558,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Extension Container"); } - if (check_map_tag(asn1, 0x8c)) + if (tcap_check_tag(asn1, 0x8c)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1661,7 +1566,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Alerting Pattern"); } - if (check_map_tag(asn1, 0x8d)) + if (tcap_check_tag(asn1, 0x8d)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1669,7 +1574,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "CCBS Call"); } - if (check_map_tag(asn1, 0x8f)) + if (tcap_check_tag(asn1, 0x8f)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1677,7 +1582,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Supported Camel Phases In GMSC"); } - if (check_map_tag(asn1, 0x8e)) + if (tcap_check_tag(asn1, 0x8e)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1685,7 +1590,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Additional Signal Info"); } - if (check_map_tag(asn1, 0x90)) + if (tcap_check_tag(asn1, 0x90)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1693,7 +1598,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Not Supported In GMSC"); } - if (check_map_tag(asn1, 0x91)) + if (tcap_check_tag(asn1, 0x91)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -1701,7 +1606,7 @@ op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Pre-paging Supported"); } - if (check_map_tag(asn1, 0x92)) + if (tcap_check_tag(asn1, 0x92)) { saved_offset = asn1->offset; asn1_id_decode1(asn1, &tag); @@ -2406,7 +2311,7 @@ dissect_map_invokeId(ASN1_SCK *asn1, proto_tree *tree) proto_tree *subtree; gboolean def_len; - if (check_map_tag(asn1, TCAP_INVOKE_ID_TAG)) + if (tcap_check_tag(asn1, TCAP_INVOKE_ID_TAG)) { saved_offset = asn1->offset; item = @@ -2574,7 +2479,7 @@ dissect_map_lnkId(ASN1_SCK *asn1, proto_tree *tree) proto_tree *subtree; gboolean def_len; - if (check_map_tag(asn1, TCAP_LINKED_ID_TAG)) + if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG)) { saved_offset = asn1->offset; @@ -2621,7 +2526,7 @@ dissect_map_opr_code(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint } tap_p = &tap_rec[tap_current]; - if (check_map_tag(asn1, MAP_OPR_CODE_TAG)) + if (tcap_check_tag(asn1, MAP_OPR_CODE_TAG)) { opr_offset = asn1->offset; @@ -2879,12 +2784,12 @@ dissect_map_re(ASN1_SCK *asn1, proto_tree *tree) #define MAP_LOCAL_ERR_CODE_TAG 0x2 #define MAP_GBL_ERR_CODE_TAG 0x6 - if (check_map_tag(asn1, MAP_LOCAL_ERR_CODE_TAG)) + if (tcap_check_tag(asn1, MAP_LOCAL_ERR_CODE_TAG)) { tag = -1; dissect_map_tag(asn1, subtree, &tag, "Local Error Code Tag", &null_item); } - else if (check_map_tag(asn1, MAP_GBL_ERR_CODE_TAG)) + else if (tcap_check_tag(asn1, MAP_GBL_ERR_CODE_TAG)) { tag = -1; dissect_map_tag(asn1, subtree, &tag, "Global Error Code Tag", &null_item); diff --git a/packet-gsm_sms.c b/packet-gsm_sms.c index c28e932401..7fc55ebdaa 100644 --- a/packet-gsm_sms.c +++ b/packet-gsm_sms.c @@ -11,7 +11,7 @@ * Technical realization of Short Message Service (SMS) * (3GPP TS 23.040 version 5.4.0 Release 5) * - * $Id: packet-gsm_sms.c,v 1.10 2004/03/05 10:06:19 guy Exp $ + * $Id: packet-gsm_sms.c,v 1.11 2004/03/27 11:32:29 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -53,6 +53,8 @@ #include "epan/packet.h" #include "prefs.h" +#include "packet-gsm_sms.h" + /* PROTOTYPES/FORWARDS */ @@ -1392,8 +1394,8 @@ dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct) */ #define GN_BYTE_MASK ((1 << bits) - 1) -static int -char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length, +int +gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length, const guint8 *input, unsigned char *output) { unsigned char *out_num = output; /* Current pointer to the output buffer */ @@ -1488,7 +1490,8 @@ char_def_alphabet_ext_decode(unsigned char value) } } -unsigned char char_def_alphabet_decode(unsigned char value) +static unsigned char +char_def_alphabet_decode(unsigned char value) { if (value < GN_CHAR_ALPHABET_SIZE) { @@ -1500,8 +1503,8 @@ unsigned char char_def_alphabet_decode(unsigned char value) } } -static void -char_ascii_decode(unsigned char* dest, const unsigned char* src, int len) +void +gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len) { int i, j; @@ -1828,10 +1831,10 @@ dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gb if (seven_bit) { out_len = - char_7bit_unpack(fill_bits, length, sizeof(bigbuf), + gsm_sms_char_7bit_unpack(fill_bits, length, sizeof(bigbuf), tvb_get_ptr(tvb, offset, length), bigbuf); bigbuf[out_len] = '\0'; - char_ascii_decode(bigbuf, bigbuf, out_len); + gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len); bigbuf[udl] = '\0'; proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf); diff --git a/packet-gsm_sms.h b/packet-gsm_sms.h new file mode 100644 index 0000000000..8a311a2c4a --- /dev/null +++ b/packet-gsm_sms.h @@ -0,0 +1,29 @@ +/* packet-gsm_sms.h + * + * $Id: packet-gsm_sms.h,v 1.1 2004/03/27 11:32:29 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 int gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length, + const guint8 *input, unsigned char *output); +extern void gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len); diff --git a/packet-gsm_ss.c b/packet-gsm_ss.c index 59e544ecec..5ee7eb7c71 100644 --- a/packet-gsm_ss.c +++ b/packet-gsm_ss.c @@ -19,7 +19,7 @@ * Michael Lum <mlum [AT] telostech.com>, * Created (2004). * - * $Id: packet-gsm_ss.c,v 1.1 2004/03/19 07:54:57 guy Exp $ + * $Id: packet-gsm_ss.c,v 1.2 2004/03/27 11:32:29 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -59,32 +59,33 @@ #include "asn1.h" #include "packet-tcap.h" +#include "packet-gsm_sms.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" }, + { 10, "Register SS" }, + { 11, "Erase SS" }, + { 12, "Activate SS" }, + { 13, "Deactivate SS" }, + { 14, "Interrogate SS" }, + { 16, "Notify SS" }, + { 17, "Register Password" }, + { 18, "Get Password" }, + { 19, "Process Unstructured SS Data" }, + { 38, "Forward Check SS Indication" }, + { 59, "Process Unstructured SS Request" }, + { 60, "Unstructured SS Request" }, + { 61, "Unstructured SS Notify" }, + { 77, "Erase CC Entry" }, + { 119, "Access Register CC Entry" }, + { 120, "Forward CUG Info" }, + { 121, "Split MPTY" }, + { 122, "Retrieve MPTY" }, + { 123, "Hold MPTY" }, + { 124, "Build MPTY" }, + { 125, "Forward Charge Advice" }, + { 126, "Explicit CT" }, { 0, NULL } }; @@ -96,9 +97,87 @@ static int hf_null = -1; gint gsm_ss_ett_sequence = -1; gint gsm_ss_ett_param = -1; +static gboolean gsm_ss_seven_bit = FALSE; +static gboolean gsm_ss_eight_bit = FALSE; +static gboolean gsm_ss_ucs2 = FALSE; +static gboolean gsm_ss_compressed = FALSE; + + +typedef struct dgt_set_t +{ + unsigned char out[15]; +} +dgt_set_t; + +#ifdef MLUM +static dgt_set_t Dgt_tbcd = { + { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e */ + '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#' + } +}; +#endif + +static dgt_set_t Dgt_msid = { + { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e */ + '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?' + } +}; + + +/* FORWARD DECLARATIONS */ + +static void op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len); + /* GENERIC HELPER FUNCTIONS */ +/* + * Unpack BCD input pattern into output ASCII pattern + * + * Input Pattern is supplied using the same format as the digits + * + * Returns: length of unpacked pattern + */ +static int +my_dgt_tbcd_unpack( + char *out, /* ASCII pattern out */ + guchar *in, /* packed pattern in */ + int num_octs, /* Number of octets to unpack */ + dgt_set_t *dgt /* Digit definitions */ + ) +{ + int cnt = 0; + unsigned char i; + + while (num_octs) + { + /* + * unpack first value in byte + */ + i = *in++; + *out++ = dgt->out[i & 0x0f]; + cnt++; + + /* + * unpack second value in byte + */ + i >>= 4; + + if (i == 0x0f) /* odd number bytes - hit filler */ + break; + + *out++ = dgt->out[i]; + cnt++; + num_octs--; + } + + *out = '\0'; + + return(cnt); +} + static gchar * my_match_strval(guint32 val, const value_string *vs, gint *idx) { @@ -120,6 +199,84 @@ my_match_strval(guint32 val, const value_string *vs, gint *idx) /* PARAMETER dissection */ +void +param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) +{ + guint saved_offset; + gint32 value; + guchar *poctets; + gchar *str = NULL; + char bigbuf[1024]; + + saved_offset = asn1->offset; + asn1_int32_value_decode(asn1, 1, &value); + + other_decode_bitfield_value(bigbuf, value, 0x80, 8); + proto_tree_add_text(tree, asn1->tvb, + saved_offset, 1, + "%s : %sxtension", + bigbuf, (value & 0x80) ? "No E" : "E"); + + switch ((value & 0x70) >> 4) + { + case 0x00: str = "unknown"; break; + case 0x01: str = "International Number"; break; + case 0x02: str = "National Significant Number"; break; + case 0x03: str = "Network Specific Number"; break; + case 0x04: str = "Subscriber Number"; break; + case 0x05: str = "Reserved"; break; + case 0x06: str = "Abbreviated Number"; break; + case 0x07: str = "Reserved for extension"; break; + } + + other_decode_bitfield_value(bigbuf, value, 0x70, 8); + proto_tree_add_text(tree, asn1->tvb, + saved_offset, asn1->offset - saved_offset, + "%s : %s", + bigbuf, str); + + switch (value & 0x0f) + { + case 0x00: str = "unknown"; break; + case 0x01: str = "ISDN/Telephony Numbering (Rec ITU-T E.164)"; break; + case 0x02: str = "spare"; break; + case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break; + case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break; + case 0x05: str = "spare"; break; + case 0x06: str = "Land Mobile Numbering (ITU-T Rec. E.212)"; break; + case 0x07: str = "spare"; break; + case 0x08: str = "National Numbering"; break; + case 0x09: str = "Private Numbering"; break; + case 0x0f: str = "Reserved for extension"; break; + default: + str = "Reserved"; + break; + } + + other_decode_bitfield_value(bigbuf, value, 0x0f, 8); + proto_tree_add_text(tree, asn1->tvb, + saved_offset, asn1->offset - saved_offset, + "%s : %s", + bigbuf, str); + + saved_offset = asn1->offset; + asn1_string_value_decode(asn1, len - 1, &poctets); + + my_dgt_tbcd_unpack(bigbuf, poctets, len - 1, &Dgt_msid); + g_free(poctets); + + if (hf_field == -1) + { + proto_tree_add_text(tree, asn1->tvb, + saved_offset, len - 1, "BCD Digits %s", bigbuf); + } + else + { + proto_tree_add_string_format(tree, hf_field, asn1->tvb, + saved_offset, len - 1, bigbuf, "BCD Digits %s", bigbuf); + } +} + static void param_ssCode(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) { @@ -423,11 +580,443 @@ param_ssStatus(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) (value & 0x01) ? "" : "Not "); } +static void +param_bearerservice(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 = "allBearerServices"; break; + case 0x10: str = "allDataCDA-Services"; break; + case 0x11: str = "dataCDA-300bps"; break; + case 0x12: str = "dataCDA-1200bps"; break; + case 0x13: str = "dataCDA-1200-75bps"; break; + case 0x14: str = "dataCDA-2400bps"; break; + case 0x15: str = "dataCDA-4800bps"; break; + case 0x16: str = "dataCDA-9600bps"; break; + case 0x17: str = "general-dataCDA"; break; + case 0x18: str = "allDataCDS-Services"; break; + case 0x1a: str = "dataCDS-1200bps"; break; + case 0x1c: str = "dataCDS-2400bps"; break; + case 0x1d: str = "dataCDS-4800bps"; break; + case 0x1e: str = "dataCDS-9600bps"; break; + case 0x1f: str = "general-dataCDS"; break; + + case 0x20: str = "allPadAccessCA-Services"; break; + case 0x21: str = "padAccessCA-300bps"; break; + case 0x22: str = "padAccessCA-1200bps"; break; + case 0x23: str = "padAccessCA-1200-75bps"; break; + case 0x24: str = "padAccessCA-2400bps"; break; + case 0x25: str = "padAccessCA-4800bps"; break; + case 0x26: str = "padAccessCA-9600bps"; break; + case 0x27: str = "general-padAccessCA"; break; + case 0x28: str = "allDataPDS-Services"; break; + case 0x2c: str = "dataPDS-2400bps"; break; + case 0x2d: str = "dataPDS-4800bps"; break; + case 0x2e: str = "dataPDS-9600bps"; break; + case 0x2f: str = "general-dataPDS"; break; + + case 0x30: str = "allAlternateSpeech-DataCDA"; break; + case 0x38: str = "allAlternateSpeech-DataCDS"; break; + case 0x40: str = "allSpeechFollowedByDataCDA"; break; + case 0x48: str = "allSpeechFollowedByDataCDS"; break; + + case 0x50: str = "allDataCircuitAsynchronous"; break; + case 0x60: str = "allAsynchronousServices"; break; + case 0x58: str = "allDataCircuitSynchronous"; break; + case 0x68: str = "allSynchronousServices"; break; + + case 0xd0: str = "allPLMN-specificBS"; break; + case 0xd1: str = "plmn-specificBS-1"; break; + case 0xd2: str = "plmn-specificBS-2"; break; + case 0xd3: str = "plmn-specificBS-3"; break; + case 0xd4: str = "plmn-specificBS-4"; break; + case 0xd5: str = "plmn-specificBS-5"; break; + case 0xd6: str = "plmn-specificBS-6"; break; + case 0xd7: str = "plmn-specificBS-7"; break; + case 0xd8: str = "plmn-specificBS-8"; break; + case 0xd9: str = "plmn-specificBS-9"; break; + case 0xda: str = "plmn-specificBS-A"; break; + case 0xdb: str = "plmn-specificBS-B"; break; + case 0xdc: str = "plmn-specificBS-C"; break; + case 0xdd: str = "plmn-specificBS-D"; break; + case 0xde: str = "plmn-specificBS-E"; break; + case 0xdf: str = "plmn-specificBS-F"; break; + + default: + str = "Undefined"; + break; + } + + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str); +} + +static void +param_teleservice(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 = "allTeleservices"; break; + case 0x10: str = "allSpeechTransmissionServices"; break; + case 0x11: str = "telephony"; break; + case 0x12: str = "emergencyCalls"; break; + case 0x20: str = "allShortMessageServices"; break; + case 0x21: str = "shortMessageMT-PP"; break; + case 0x22: str = "shortMessageMO-PP"; break; + case 0x60: str = "allFacsimileTransmissionServices"; break; + case 0x61: str = "facsimileGroup3AndAlterSpeech"; break; + case 0x62: str = "automaticFacsimileGroup3"; break; + case 0x63: str = "facsimileGroup4"; break; + + case 0x70: str = "allDataTeleservices"; break; + case 0x80: str = "allTeleservices-ExeptSMS"; break; + + case 0x90: str = "allVoiceGroupCallServices"; break; + case 0x91: str = "voiceGroupCall"; break; + case 0x92: str = "voiceBroadcastCall"; break; + + case 0xd0: str = "allPLMN-specificTS"; break; + case 0xd1: str = "plmn-specificTS-1"; break; + case 0xd2: str = "plmn-specificTS-2"; break; + case 0xd3: str = "plmn-specificTS-3"; break; + case 0xd4: str = "plmn-specificTS-4"; break; + case 0xd5: str = "plmn-specificTS-5"; break; + case 0xd6: str = "plmn-specificTS-6"; break; + case 0xd7: str = "plmn-specificTS-7"; break; + case 0xd8: str = "plmn-specificTS-8"; break; + case 0xd9: str = "plmn-specificTS-9"; break; + case 0xda: str = "plmn-specificTS-A"; break; + case 0xdb: str = "plmn-specificTS-B"; break; + case 0xdc: str = "plmn-specificTS-C"; break; + case 0xdd: str = "plmn-specificTS-D"; break; + case 0xde: str = "plmn-specificTS-E"; break; + case 0xdf: str = "plmn-specificTS-F"; break; + + default: + str = "Undefined"; + break; + } + + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str); +} + +/* + * GSM 03.38 + * Same as Cell Broadcast + */ +static void +param_ussdDCS(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) +{ + guint saved_offset; + gint32 value; + gchar *str = NULL; + char bigbuf[1024]; + proto_tree *subtree; + proto_item *item; + + hf_field = hf_field; + + gsm_ss_seven_bit = FALSE; + gsm_ss_eight_bit = FALSE; + gsm_ss_ucs2 = FALSE; + gsm_ss_compressed = FALSE; + + saved_offset = asn1->offset; + asn1_int32_value_decode(asn1, len, &value); + + item = + proto_tree_add_text(tree, asn1->tvb, + saved_offset, len, + "Data Coding Scheme (%d)", + value); + + subtree = proto_item_add_subtree(item, gsm_ss_ett_param); + + if ((value & 0xf0) == 0x00) + { + /* 0000.... Language using the default alphabet */ + + switch (value & 0x0f) + { + case 0x00: str = "German"; break; + case 0x01: str = "English"; break; + case 0x02: str = "Italian"; break; + case 0x03: str = "French"; break; + case 0x04: str = "Spanish"; break; + case 0x05: str = "Dutch"; break; + case 0x06: str = "Swedish"; break; + case 0x07: str = "Danish"; break; + case 0x08: str = "Portuguese"; break; + case 0x09: str = "Finnish"; break; + case 0x0a: str = "Norwegian"; break; + case 0x0b: str = "Greek"; break; + case 0x0c: str = "Turkish"; break; + case 0x0d: str = "Hungarian"; break; + case 0x0e: str = "Polish"; break; + case 0x0f: str = "Language unspecified"; break; + } + + other_decode_bitfield_value(bigbuf, value, 0x0f, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : %s language using default alphabet", + bigbuf, + str); + + gsm_ss_seven_bit = TRUE; + } + else if ((value & 0xf0) == 0x10) + { + switch (value & 0x0f) + { + case 0x00: str = "Default alphabet; message preceded by language indication"; break; + case 0x01: str = "UCS2; message preceded by language indication"; break; + default: + str = "Reserved for European languages"; + break; + } + + other_decode_bitfield_value(bigbuf, value, 0xff, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : %s", + bigbuf, + str); + } + else if ((value & 0xf0) == 0x20) + { + switch (value & 0x0f) + { + case 0x00: str = "Czech"; break; + default: + str = "Reserved for European languages using the default alphabet"; + break; + } + + other_decode_bitfield_value(bigbuf, value, 0xff, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : %s", + bigbuf, + str); + } + else if ((value & 0xf0) == 0x30) + { + other_decode_bitfield_value(bigbuf, value, 0xff, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Reserved for European Languages using the default alphabet", + bigbuf); + } + else if ((value & 0xc0) == 0x40) + { + other_decode_bitfield_value(bigbuf, value, 0xc0, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : General Data Coding indication", + bigbuf); + + gsm_ss_compressed = (value & 0x20) >> 5; + + other_decode_bitfield_value(bigbuf, value, 0x20, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Text is %scompressed", + bigbuf, + gsm_ss_compressed ? "" : "not "); + + other_decode_bitfield_value(bigbuf, value, 0x10, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : %s", + bigbuf, + (value & 0x10) ? "Message class is defined below" : + "Reserved, no message class"); + + switch ((value & 0x0c) >> 2) + { + case 0x00: str = "GSM 7 bit default alphabet"; + gsm_ss_seven_bit = TRUE; + break; + case 0x01: str = "8 bit data"; break; + case 0x02: str = "UCS2 (16 bit)"; + gsm_ss_ucs2 = TRUE; + break; + case 0x03: str = "Reserved"; break; + } + + other_decode_bitfield_value(bigbuf, value, 0x0c, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Character set: %s", + bigbuf, + str); + + switch (value & 0x03) + { + case 0x00: str = "Class 0"; break; + case 0x01: str = "Class 1 Default meaning: ME-specific"; break; + case 0x02: str = "Class 2 (U)SIM specific message"; break; + case 0x03: str = "Class 3 Default meaning: TE-specific"; break; + } + + other_decode_bitfield_value(bigbuf, value, 0x03, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Message Class: %s%s", + bigbuf, + str, + (value & 0x10) ? "" : " (reserved)"); + } + else if ((value & 0xf0) == 0xf0) + { + other_decode_bitfield_value(bigbuf, value, 0xf0, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Data Coding / Message Handling", + bigbuf); + + other_decode_bitfield_value(bigbuf, value, 0x08, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Reserved", + bigbuf); + + gsm_ss_seven_bit = !(gsm_ss_eight_bit = (value & 0x04) ? TRUE : FALSE); + + other_decode_bitfield_value(bigbuf, value, 0x04, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Message coding: %s", + bigbuf, + gsm_ss_eight_bit ? "8 bit data" : "Default alphabet"); + + switch (value & 0x03) + { + case 0x00: str = "No message class"; break; + case 0x01: str = "Class 1 user defined"; break; + case 0x02: str = "Class 2 user defined"; break; + case 0x03: str = "Class 3 Default meaning: TE-specific"; break; + } + + other_decode_bitfield_value(bigbuf, value, 0x03, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Message Class: %s", + bigbuf, + str); + } + else + { + other_decode_bitfield_value(bigbuf, value, 0xff, 8); + proto_tree_add_text(subtree, asn1->tvb, + saved_offset, 1, + "%s : Reserved coding groups", + bigbuf); + } +} + +static void +param_ussdString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) +{ + guint saved_offset; + char bigbuf[1024]; + guint8 fill_bits; + guint32 out_len; + char *ustr; + + hf_field = hf_field; + + saved_offset = asn1->offset; + + if (gsm_ss_compressed) + { + proto_tree_add_text(tree, asn1->tvb, + saved_offset, len, + "Compressed data"); + } + else + { + if (gsm_ss_seven_bit) + { + fill_bits = 0; + + out_len = + gsm_sms_char_7bit_unpack(fill_bits, len, sizeof(bigbuf), + tvb_get_ptr(asn1->tvb, saved_offset, len), bigbuf); + bigbuf[out_len] = '\0'; + gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len); + + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", bigbuf); + } + else if (gsm_ss_eight_bit) + { + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", + tvb_format_text(asn1->tvb, saved_offset, len)); + } + else if (gsm_ss_ucs2) + { + ustr = tvb_fake_unicode(asn1->tvb, saved_offset, len, FALSE); + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", ustr); + g_free(ustr); + } + else + { + /* don't know what form it is */ + + proto_tree_add_text(tree, asn1->tvb, + saved_offset, len, + "Parameter Data"); + } + } + + asn1->offset += len; +} + +static void +param_ia5String(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) +{ + guint saved_offset; + + hf_field = hf_field; + + saved_offset = asn1->offset; + + proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", + tvb_format_text(asn1->tvb, saved_offset, len)); + + asn1->offset += len; +} + typedef enum { GSM_SS_P_SS_CODE, /* SS-Code */ GSM_SS_P_SS_STATUS, /* SS-Status */ + GSM_SS_P_BEARERSERVICE, /* Bearer Service */ + GSM_SS_P_TELESERVICE, /* Tele Service */ + GSM_SS_P_FORWARD_TO_NUM, /* Forward to Number */ + GSM_SS_P_LONG_FORWARD_TO_NUM, /* Long Forward to Number */ + GSM_SS_P_USSD_DCS, /* USSD Data Coding Scheme */ + GSM_SS_P_USSD_STRING, /* USSD String */ + GSM_SS_P_IA5_STRING, /* IA5 String */ GSM_SS_P_NONE /* NONE */ } param_idx_t; @@ -437,12 +1026,26 @@ 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 */ + param_bearerservice, /* Bearer Service */ + param_teleservice, /* Tele Service */ + param_AddressString, /* Forward to Number */ + param_AddressString, /* Long Forward to Number */ + param_ussdDCS, /* USSD Data Coding Scheme */ + param_ussdString, /* USSD String */ + param_ia5String, /* IA5 String */ NULL /* NONE */ }; static int *param_1_hf[] = { HF_NULL, /* SS-Code */ HF_NULL, /* SS-Status */ + HF_NULL, /* Bearer Service */ + HF_NULL, /* Tele Service */ + HF_NULL, /* Forward to Number */ + HF_NULL, /* Long Forward to Number */ + HF_NULL, /* USSD Data Coding Scheme */ + HF_NULL, /* USSD String */ + HF_NULL, /* IA5 String */ NULL /* NONE */ }; @@ -479,7 +1082,6 @@ static int *param_1_hf[] = { (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \ } - #define GSM_SS_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \ { \ gint _ett_param_idx; \ @@ -533,6 +1135,332 @@ static int *param_1_hf[] = { static void +param_forwardingFeature(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + guint tag, len; + gboolean def_len; + proto_tree *subtree; + + exp_len = exp_len; + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature", + gsm_ss_ett_sequence, + &def_len, &len, subtree); + + if (tcap_check_tag(asn1, 0x82)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice"); + } + + if (tcap_check_tag(asn1, 0x83)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice"); + } + + if (tcap_check_tag(asn1, 0x84)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status"); + } + + if (tcap_check_tag(asn1, 0x85)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number"); + } + + if (tcap_check_tag(asn1, 0x88)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress"); + } + + if (tcap_check_tag(asn1, 0x86)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarding Options"); + } + + if (tcap_check_tag(asn1, 0x87)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time"); + } + + if (tcap_check_tag(asn1, 0x89)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_LONG_FORWARD_TO_NUM, "Long Forward to Number"); + } + + 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 +param_forwardingFeatureList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset, start_offset; + guint tag, len; + gboolean def_len; + proto_tree *subtree; + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature List", + gsm_ss_ett_sequence, + &def_len, &len, subtree); + + start_offset = asn1->offset; + + while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) && + (!tcap_check_tag(asn1, 0))) + { + if ((exp_len != 0) && + ((asn1->offset - saved_offset) >= exp_len)) + { + break; + } + + param_forwardingFeature(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 +param_ssInfo(ASN1_SCK *asn1, proto_tree *tree) +{ + guint saved_offset, start_offset; + guint tag, len; + gboolean def_len = FALSE; + proto_tree *subtree; + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + switch (tag) + { + case 0xa0: /* forwardingInfo */ + GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Info", + gsm_ss_ett_sequence, + &def_len, &len, subtree); + + start_offset = asn1->offset; + + if (tcap_check_tag(asn1, 0x04)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code"); + } + + param_forwardingFeatureList(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"); + } + break; + + case 0xa1: /* callBarringInfo */ + GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Info", + gsm_ss_ett_sequence, + &def_len, &len, subtree); + + start_offset = asn1->offset; + + /* XXX */ + 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"); + } + break; + + case 0xa3: /* ss-Data */ + GSM_SS_START_SUBTREE(tree, saved_offset, tag, "ss-Data", + gsm_ss_ett_sequence, + &def_len, &len, subtree); + + start_offset = asn1->offset; + + /* XXX */ + 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"); + } + break; + + default: + /* XXX */ + break; + } +} + +static void +param_ssForBS(ASN1_SCK *asn1, proto_tree *tree) +{ + guint saved_offset, start_offset; + guint tag, len, rem_len; + gboolean def_len = FALSE; + proto_tree *subtree; + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + 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"); + + if (tcap_check_tag(asn1, 0x82)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice"); + } + + if (tcap_check_tag(asn1, 0x83)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice"); + } + + if (tcap_check_tag(asn1, 0x84)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Long FTN supported"); + } + + rem_len = len - (asn1->offset - start_offset); + + if (rem_len > 0) + { + op_generic_ss(asn1, subtree, rem_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"); + } +} + +static void +param_ussdArg(ASN1_SCK *asn1, proto_tree *tree) +{ + guint saved_offset, start_offset; + guint tag, len, rem_len; + gboolean def_len = FALSE; + proto_tree *subtree; + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + 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_USSD_DCS, "USSD Data Coding Scheme"); + + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_STRING, "USSD String"); + + rem_len = len - (asn1->offset - start_offset); + + if (rem_len > 0) + { + op_generic_ss(asn1, subtree, rem_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"); + } +} + + +/* MESSAGES */ + +static void op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint orig_offset, saved_offset, len_offset; @@ -622,10 +1550,10 @@ op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) } static void -op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +op_register_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset, start_offset; - guint tag, len; + guint tag, len, rem_len; gboolean def_len = FALSE; proto_tree *subtree; @@ -655,7 +1583,60 @@ op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) 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 (tcap_check_tag(asn1, 0x82)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice"); + } + + if (tcap_check_tag(asn1, 0x83)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice"); + } + + if (tcap_check_tag(asn1, 0x84)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number"); + } + + if (tcap_check_tag(asn1, 0x86)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress"); + } + + if (tcap_check_tag(asn1, 0x85)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time"); + } + + if (tcap_check_tag(asn1, 0x87)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Default Priority"); + } + + rem_len = len - (asn1->offset - start_offset); + + if (rem_len > 0) + { + op_generic_ss(asn1, subtree, rem_len); + } if (!def_len) { @@ -668,6 +1649,118 @@ op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) } static void +op_register_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssInfo(asn1, tree); +} + +static void +op_erase_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssForBS(asn1, tree); +} + +static void +op_erase_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssInfo(asn1, tree); +} + +static void +op_activate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssForBS(asn1, tree); +} + +static void +op_activate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssInfo(asn1, tree); +} + +static void +op_deactivate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssForBS(asn1, tree); +} + +static void +op_deactivate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssInfo(asn1, tree); +} + +static void +op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ssForBS(asn1, tree); +} + +static void op_interrogate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) { guint saved_offset; @@ -700,27 +1793,125 @@ op_interrogate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) default: /* do nothing - unexpected tag */ - break; + return; } op_generic_ss(asn1, tree, 0); } +static void +op_proc_uss_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + guint tag, rem_len; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + if (tcap_check_tag(asn1, 0x16)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData"); + } + + rem_len = exp_len - (asn1->offset - saved_offset); + + if (rem_len > 0) + { + op_generic_ss(asn1, tree, rem_len); + } +} + +static void +op_proc_uss_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + guint tag, rem_len; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + if (tcap_check_tag(asn1, 0x16)) + { + saved_offset = asn1->offset; + asn1_id_decode1(asn1, &tag); + + GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData"); + } + + rem_len = exp_len - (asn1->offset - saved_offset); + + if (rem_len > 0) + { + op_generic_ss(asn1, tree, rem_len); + } +} + +static void +op_proc_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ussdArg(asn1, tree); +} + +static void +op_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ussdArg(asn1, tree); +} + +static void +op_uss_notify(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) +{ + guint saved_offset; + + exp_len = exp_len; + + if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return; + + saved_offset = asn1->offset; + + param_ussdArg(asn1, tree); +} + #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_register_ss, /* RegisterSS */ + op_erase_ss, /* EraseSS */ + op_activate_ss, /* ActivateSS */ + op_deactivate_ss, /* DeactivateSS */ op_interrogate_ss, /* InterrogateSS */ NULL, /* NotifySS */ NULL, /* RegisterPassword */ NULL, /* GetPassword */ - NULL, /* ProcessUnstructuredSS-Data */ + op_proc_uss_data, /* ProcessUnstructuredSS-Data */ NULL, /* ForwardCheckSS-Indication */ - NULL, /* ProcessUnstructuredSS-Request */ - NULL, /* UnstructuredSS-Request */ - NULL, /* UnstructuredSS-Notify */ + op_proc_uss_req, /* ProcessUnstructuredSS-Request */ + op_uss_req, /* UnstructuredSS-Request */ + op_uss_notify, /* UnstructuredSS-Notify */ NULL, /* EraseCC-Entry */ NULL, /* AccessRegisterCCEntry */ NULL, /* ForwardCUG-Info */ @@ -735,15 +1926,15 @@ static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = { }; static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = { - NULL, /* RegisterSS */ - NULL, /* EraseSS */ - NULL, /* ActivateSS */ - NULL, /* DeactivateSS */ + op_register_ss_rr, /* RegisterSS */ + op_erase_ss_rr, /* EraseSS */ + op_activate_ss_rr, /* ActivateSS */ + op_deactivate_ss_rr, /* DeactivateSS */ op_interrogate_ss_rr, /* InterrogateSS */ NULL, /* NotifySS */ NULL, /* RegisterPassword */ NULL, /* GetPassword */ - NULL, /* ProcessUnstructuredSS-Data */ + op_proc_uss_data_rr, /* ProcessUnstructuredSS-Data */ NULL, /* ForwardCheckSS-Indication */ NULL, /* ProcessUnstructuredSS-Request */ NULL, /* UnstructuredSS-Request */ diff --git a/packet-gsm_ss.h b/packet-gsm_ss.h index dab70e8eea..017b7a6e84 100644 --- a/packet-gsm_ss.h +++ b/packet-gsm_ss.h @@ -1,6 +1,6 @@ /* packet-gsm_ss.h * - * $Id: packet-gsm_ss.h,v 1.1 2004/03/19 07:54:57 guy Exp $ + * $Id: packet-gsm_ss.h,v 1.2 2004/03/27 11:32:29 guy Exp $ * * Copyright 2004, Michael Lum <mlum [AT] telostech.com>, * In association with Telos Technology Inc. @@ -29,4 +29,5 @@ extern gint gsm_ss_ett_param; extern const value_string gsm_ss_opr_code_strings[]; +extern void param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field); extern void gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len, guint opr_code, guint comp_type_tag); |