From Michael Lum:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 27 Mar 2004 11:32:30 +0000 (11:32 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 27 Mar 2004 11:32:30 +0000 (11:32 +0000)
ANSI IS-801 support;

dissect more GSM supplementary services messages and fields.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@10503 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.common
epan/Makefile.common
packet-ansi_801.c [new file with mode: 0644]
packet-ansi_a.c
packet-ansi_map.c
packet-gsm_map.c
packet-gsm_sms.c
packet-gsm_sms.h [new file with mode: 0644]
packet-gsm_ss.c
packet-gsm_ss.h

diff --git a/AUTHORS b/AUTHORS
index d6c3e2a550d0234a327f09b3d01af33a98f93425..837f72d1f7bd48a86f692255e41e598c217a4695 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -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
index 6990acb472aaffd64da11a31f005f8a9a837e98b..ed070f6d2977b87c8ebc0ceac58a4de8dded3d09 100644 (file)
@@ -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    \
index f551c842ac398bed6c272f9f1054ee20c1ddbdbe..8d0bf091c9c421b43f266300994a2846c1747f81 100644 (file)
@@ -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 (file)
index 0000000..371f312
--- /dev/null
@@ -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");
+}
index d87f9723bf6f237106b113de6ee0e857047c13ce..58100ea79a39c6af79a70daf8f4d1c94999da6ae 100644 (file)
@@ -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");
index d560127440504c0698c7301d03c96a642b311de5..8d149d9d2b5823b383e2d0a6908445698554c3c5 100644 (file)
@@ -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));
index 1a0b1a6276e90d06083a73a55333362570b856c6..c2166caa1998268d1cb4f560b03c861781ab6272 100644 (file)
@@ -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);
index c28e932401ed2d39d1a78c304f8ecd6a79af27c0..7fc55ebdaa8c6ae4fc5960bbfd97ba451d770c07 100644 (file)
@@ -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 (file)
index 0000000..8a311a2
--- /dev/null
@@ -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);
index 59e544ecec6a1c3c0b20cfffa465944248d98d56..5ee7eb7c71f9c18a31be0f10e89694e158036485 100644 (file)
@@ -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>
 #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,24 +1135,350 @@ static int *param_1_hf[] = {
 
 
 static void
-op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+param_forwardingFeature(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;
+    guint              saved_offset;
+    guint              tag, len;
+    gboolean           def_len;
+    proto_tree         *subtree;
 
-    orig_offset = asn1->offset;
+    exp_len = exp_len;
 
-    while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
-       (!tcap_check_tag(asn1, 0)))
+    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))
     {
-       if ((exp_len != 0) &&
-           ((asn1->offset - orig_offset) >= exp_len))
-       {
-           break;
-       }
+       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;
+    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);
@@ -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)
     {
@@ -667,6 +1648,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)
 {
@@ -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 */
index dab70e8eeabaf4a5026a26cc1187de750174f72e..017b7a6e844d78a01caf4a7ef39622a940ffd523 100644 (file)
@@ -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);