From Michael Lum:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 22 Oct 2003 20:59:02 +0000 (20:59 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 22 Oct 2003 20:59:02 +0000 (20:59 +0000)
BSSAP (GSM 08.06)/BSAP (IOS 4.0.1) support
IOS 4.0.1 support
Add Transport Layer support to ANSI IS-637-A dissector

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

AUTHORS
Makefile.am
Makefile.nmake
packet-ansi_637.c
packet-ansi_a.c [new file with mode: 0644]
packet-bssap.c [new file with mode: 0644]
packet-bssap.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index b30ca988282cd3d13c35ce8a3359c5f81c9c2178..cf041ff56ab2bb5f7d2dc070769bab1680be7fd4 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1797,6 +1797,8 @@ Michael Lum <mlum [AT] telostech.com> {
        ALCAP (Q.2630.1) support
        IS-637-A (SMS) support
        IS-683-A (OTA) support
+       BSSAP (GSM 08.06)/BSAP (IOS 4.0.1) support
+       IOS 4.0.1 support
 }
 
 Shiang-Ming Huang <smhuang [AT] pcs.csie.nctu.edu.tw> {
index fe0c8018ed5b44eb2cdb818ea460369808a59136..04e14b893937b637d3941fc9f5680e902191a486 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.642 2003/10/22 02:07:39 sahlberg Exp $
+# $Id: Makefile.am,v 1.643 2003/10/22 20:59:01 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@ethereal.com>
@@ -92,6 +92,7 @@ DISSECTOR_SRC = \
        packet-ajp13.c          \
        packet-alcap.c \
        packet-ans.c   \
+       packet-ansi_a.c   \
        packet-ansi_637.c   \
        packet-ansi_683.c   \
        packet-ansi_map.c   \
@@ -113,6 +114,7 @@ DISSECTOR_SRC = \
        packet-bootparams.c \
        packet-bpdu.c  \
        packet-brdwlk.c \
+       packet-bssap.c \
        packet-bssgp.c \
        packet-bvlc.c \
        packet-cdp.c   \
@@ -581,6 +583,7 @@ noinst_HEADERS = \
        packet-atm.h   \
        packet-bgp.h   \
        packet-bootparams.h \
+       packet-bssap.h \
        packet-chdlc.h \
        packet-clearcase.h  \
        packet-clip.h  \
index dfa19b3b31db415b8d9ff651caba370525c58d62..6940c269dd6307bfd2e4450e44d1fe9c9b4eb885 100644 (file)
@@ -1,7 +1,7 @@
 ## Makefile for building ethereal.exe with Microsoft C and nmake
 ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
 #
-# $Id: Makefile.nmake,v 1.349 2003/10/22 02:07:39 sahlberg Exp $
+# $Id: Makefile.nmake,v 1.350 2003/10/22 20:59:01 guy Exp $
 
 include config.nmake
 include <win32.mak>
@@ -32,6 +32,7 @@ DISSECTOR_SRC = \
        packet-ajp13.c          \
        packet-alcap.c \
        packet-ans.c   \
+       packet-ansi_a.c   \
        packet-ansi_637.c   \
        packet-ansi_683.c   \
        packet-ansi_map.c   \
@@ -53,6 +54,7 @@ DISSECTOR_SRC = \
        packet-bootparams.c \
        packet-bpdu.c  \
        packet-brdwlk.c \
+       packet-bssap.c \
        packet-bssgp.c \
        packet-bvlc.c \
        packet-cdp.c   \
index 5edf2b9ef150e07c8c9063bf80f4c183fed368f1..88fbc3cddcfaaed6c41a77fee2fc58f94a2941d0 100644 (file)
@@ -9,7 +9,7 @@
  *   Short Message Service
  *                     3GPP2 C.S0015-0         TIA/EIA-637-A
  *
- * $Id: packet-ansi_637.c,v 1.1 2003/10/06 19:25:20 guy Exp $
+ * $Id: packet-ansi_637.c,v 1.2 2003/10/22 20:59:01 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "epan/packet.h"
 
 
-static char *ansi_proto_name = "ANSI IS-637-A (SMS)";
+static char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
+static char *ansi_proto_name_trans = "ANSI IS-637-A (SMS) Transport Layer";
 static char *ansi_proto_name_short = "IS-637-A";
 
-static const value_string ansi_msg_type_strings[] = {
+static const value_string ansi_srvc_cat_strings[] = {
+    { 0x0000,  "Unknown or unspecified" },
+    { 0x0001,  "Emergency Broadcasts" },
+    { 0x0002,  "Administrative" },
+    { 0x0003,  "Maintenance" },
+    { 0x0004,  "General News - Local" },
+    { 0x0005,  "General News - Regional" },
+    { 0x0006,  "General News - National" },
+    { 0x0007,  "General News - International" },
+    { 0x0008,  "Business/Financial News - Local" },
+    { 0x0009,  "Business/Financial News - Regional" },
+    { 0x000A,  "Business/Financial News - National" },
+    { 0x000B,  "Business/Financial News - International" },
+    { 0x000C,  "Sports News - Local" },
+    { 0x000D,  "Sports News - Regional" },
+    { 0x000E,  "Sports News - National" },
+    { 0x000F,  "Sports News - International" },
+    { 0x0010,  "Entertainment News - Local" },
+    { 0x0011,  "Entertainment News - Regional" },
+    { 0x0012,  "Entertainment News - National" },
+    { 0x0013,  "Entertainment News - International" },
+    { 0x0014,  "Local Weather" },
+    { 0x0015,  "Area Traffic Reports" },
+    { 0x0016,  "Local Airport Flight Schedules" },
+    { 0x0017,  "Restaurants" },
+    { 0x0018,  "Lodgings" },
+    { 0x0019,  "Retail Directory" },
+    { 0x001A,  "Advertisements" },
+    { 0x001B,  "Stock Quotes" },
+    { 0x001C,  "Employment Opportunities" },
+    { 0x001D,  "Medical/Health/Hospitals" },
+    { 0x001E,  "Technology News" },
+    { 0x001F,  "Multi-category" },
+    { 0, NULL },
+};
+
+static const value_string ansi_tele_msg_type_strings[] = {
     { 1,       "Deliver (mobile-terminated only)" },
     { 2,       "Submit (mobile-originated only)" },
     { 3,       "Cancellation (mobile-originated only)" },
@@ -63,7 +100,7 @@ static const value_string ansi_msg_type_strings[] = {
     { 0, NULL },
 };
 
-static const value_string ansi_tele_strings[] = {
+static const value_string ansi_tele_id_strings[] = {
     { 1,       "Reserved for maintenance" },
     { 4096,    "AMPS Extended Protocol Enhanced Services" },
     { 4097,    "CDMA Cellular Paging Teleservice" },
@@ -75,7 +112,7 @@ static const value_string ansi_tele_strings[] = {
     { 0, NULL },
 };
 
-static const value_string ansi_param_strings[] = {
+static const value_string ansi_tele_param_strings[] = {
     { 0x00,    "Message Identifier" },
     { 0x01,    "User Data" },
     { 0x02,    "User Response Code" },
@@ -96,21 +133,60 @@ static const value_string ansi_param_strings[] = {
     { 0, NULL },
 };
 
+static const value_string ansi_trans_msg_type_strings[] = {
+    { 0,       "Point-to-Point" },
+    { 1,       "Broadcast" },
+    { 2,       "Acknowledge" },
+    { 0, NULL },
+};
+
+static const value_string ansi_trans_param_strings[] = {
+    { 0x00,    "Teleservice Identifier" },
+    { 0x01,    "Service Category" },
+    { 0x02,    "Originating Address" },
+    { 0x03,    "Originating Subaddress" },
+    { 0x04,    "Destination Address" },
+    { 0x05,    "Destination Subaddress" },
+    { 0x06,    "Bearer Reply Option" },
+    { 0x07,    "Cause Codes" },
+    { 0x08,    "Bearer Data" },
+    { 0, NULL },
+};
+
+/*
+ * from Table 2.7.1.3.2.4-4. Representation of DTMF Digits
+ * 3GPP2 C.S0005-C (IS-2000 aka cdma2000)
+ */
+static unsigned char air_digits[] = {
+  /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
+     '?','1','2','3','4','5','6','7','8','9','0','*','#','?','?'
+};
+
 /* Initialize the protocol and registered fields */
-static int proto_ansi_637 = -1;
+static int proto_ansi_637_tele = -1;
+static int proto_ansi_637_trans = -1;
 static int hf_ansi_637_none = -1;
-static int hf_ansi_637_msg_type = -1;
-static int hf_ansi_637_msg_id = -1;
-static int hf_ansi_637_msg_junk = -1;
 static int hf_ansi_637_length = -1;
-static int hf_ansi_637_subparam_id = -1;
+static int hf_ansi_637_bin_addr = -1;
+static int hf_ansi_637_tele_msg_type = -1;
+static int hf_ansi_637_tele_msg_id = -1;
+static int hf_ansi_637_tele_msg_rsvd = -1;
+static int hf_ansi_637_tele_subparam_id = -1;
+static int hf_ansi_637_trans_msg_type = -1;
+static int hf_ansi_637_trans_param_id = -1;
 
 /* Initialize the subtree pointers */
-static gint ett_ansi_637 = -1;
+static gint ett_ansi_637_tele = -1;
+static gint ett_ansi_637_trans = -1;
 static gint ett_params = -1;
 
-static char bigbuf[1024];
+static guint32 ansi_637_trans_tele_id;
+static char ansi_637_bigbuf[1024];
+static gchar ansi_637_add_string[1024];
 static dissector_handle_t data_handle;
+static dissector_table_t tele_dissector_table;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
 
 /* FUNCTIONS */
 
@@ -272,28 +348,28 @@ my_match_strval(guint32 val, const value_string *vs, gint *idx)
 #define        EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
     if ((edc_len) > (edc_max_len)) \
     { \
-       proto_tree_add_none_format(tree, hf_ansi_637_none, tvb, \
-           offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+       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_none_format(tree, hf_ansi_637_none, tvb, \
-           offset, (sdc_len), "Short Data (?)"); \
+       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_none_format(tree, hf_ansi_637_none, tvb, \
-           offset, (edc_len), "Unexpected Data Length"); \
+       proto_tree_add_text(tree, tvb, offset, \
+           (edc_len), "Unexpected Data Length"); \
        return; \
     }
 
 static void
-param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct, oct2;
     guint8     encoding;
@@ -335,27 +411,24 @@ param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     default: str = "Reserved"; break;
     }
 
-    my_decode_bitfield_value(bigbuf, oct, 0xf8, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s :  Encoding, %s",
-       bigbuf,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Encoding: %s",
+       ansi_637_bigbuf,
        str);
 
     if (encoding == 0x01)
     {
-       my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s :  Message type, see TIA/EIA/IS-91 (%d)",
-           bigbuf,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Message type: see TIA/EIA/IS-91 (%d)",
+           ansi_637_bigbuf,
            msg_type);
 
-       my_decode_bitfield_value(bigbuf, oct2, 0xf8, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset+1, 1,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+       proto_tree_add_text(tree, tvb, offset+1, 1,
            "%s :  Message type",
-           bigbuf);
+           ansi_637_bigbuf);
 
        oct = oct2;
        offset++;
@@ -371,24 +444,21 @@ param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     oct2 = tvb_get_guint8(tvb, offset);
     num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset-1, 1,
-       "%s :  Number of fields (%d)",
-       bigbuf,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, offset-1, 1,
+       "%s :  Number of fields (MSB): %d",
+       ansi_637_bigbuf,
        num_fields);
 
-    my_decode_bitfield_value(bigbuf, oct2, 0xf8, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s :  Number of fields",
-       bigbuf);
+    my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Number of fields (LSB)",
+       ansi_637_bigbuf);
 
-    my_decode_bitfield_value(bigbuf, oct2, 0x07, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Most significant bits of first field",
-       bigbuf);
+       ansi_637_bigbuf);
 
     offset++;
     used++;
@@ -414,8 +484,7 @@ param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
        if (required_octs + used > len)
        {
-           proto_tree_add_none_format(tree, hf_ansi_637_none,
-               tvb, offset, 1,
+           proto_tree_add_text(tree, tvb, offset, 1,
                "Missing %d octet(s) for number of fields",
                (required_octs + used) - len);
 
@@ -425,12 +494,11 @@ param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
        bit = 3;
        saved_offset = offset;
 
-       decode_7_bits(tvb, &offset, num_fields, &oct, &bit, bigbuf);
+       decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
 
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, saved_offset, offset - saved_offset,
-           "Encoded user data, %s",
-           bigbuf);
+       proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+           "Encoded user data: %s",
+           ansi_637_bigbuf);
 
        switch (bit)
        {
@@ -445,23 +513,21 @@ param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
        if (bit != 8)
        {
-           my_decode_bitfield_value(bigbuf, oct, oct2, 8);
-           proto_tree_add_none_format(tree, hf_ansi_637_none,
-               tvb, offset - 1, 1,
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, oct2, 8);
+           proto_tree_add_text(tree, tvb, offset - 1, 1,
                "%s :  Reserved",
-               bigbuf);
+               ansi_637_bigbuf);
        }
     }
     else
     {
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, len - used,
+       proto_tree_add_text(tree, tvb, offset, len - used,
            "Encoded user data");
     }
 }
 
 static void
-param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
 
@@ -472,14 +538,13 @@ param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
      */
     oct = tvb_get_guint8(tvb, offset);
 
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "Response code (%d)",
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "Response code: %d",
        oct);
 }
 
 static void
-param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct, oct2, oct3;
 
@@ -489,8 +554,7 @@ param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     oct2 = tvb_get_guint8(tvb, offset+1);
     oct3 = tvb_get_guint8(tvb, offset+2);
 
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 3,
+    proto_tree_add_text(tree, tvb, offset, 3,
        "Year %d%d, Month %d%d, Day %d%d",
        (oct & 0xf0) >> 4,
        oct & 0x0f,
@@ -505,8 +569,7 @@ param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     oct2 = tvb_get_guint8(tvb, offset+1);
     oct3 = tvb_get_guint8(tvb, offset+2);
 
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 3,
+    proto_tree_add_text(tree, tvb, offset, 3,
        "Hour %d%d, Minutes %d%d, Seconds %d%d",
        (oct & 0xf0) >> 4,
        oct & 0x0f,
@@ -517,7 +580,7 @@ param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 }
 
 static void
-param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     guint32    value = 0;
@@ -544,22 +607,19 @@ param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
     if (str == NULL)
     {
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s",
+       proto_tree_add_text(tree, tvb, offset, 1,
            str2);
     }
     else
     {
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
+       proto_tree_add_text(tree, tvb, offset, 1,
            "%d %s",
            value, str2);
     }
 }
 
 static void
-param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     gchar      *str = NULL;
@@ -576,22 +636,20 @@ param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     case 0x11: str = "Emergency"; break;
     }
 
-    my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  %s",
-       bigbuf,
+       ansi_637_bigbuf,
        str);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Reserved",
-       bigbuf);
+       ansi_637_bigbuf);
 }
 
 static void
-param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     gchar      *str = NULL;
@@ -608,22 +666,20 @@ param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     case 3: str = "Secret (privacy level 3)"; break;
     }
 
-    my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  %s",
-       bigbuf,
+       ansi_637_bigbuf,
        str);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Reserved",
-       bigbuf);
+       ansi_637_bigbuf);
 }
 
 static void
-param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
 
@@ -631,29 +687,26 @@ param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
     oct = tvb_get_guint8(tvb, offset);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s :  %s",
-       bigbuf,
-       (oct & 0x80) ? "User (manual) acknowledgment is requested" : "No user (manual) acknowledgement is requested");
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  %s (manual) acknowledgment is requested",
+       ansi_637_bigbuf,
+       (oct & 0x80) ? "User" : "No user");
 
-    my_decode_bitfield_value(bigbuf, oct, 0x40, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s :  %s",
-       bigbuf,
-       (oct & 0x40) ? "Delivery acknowledgment requested" : "No delivery acknowledgment requested");
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  %s acknowledgment requested",
+       ansi_637_bigbuf,
+       (oct & 0x40) ? "Delivery" : "No delivery");
 
-    my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Reserved",
-       bigbuf);
+       ansi_637_bigbuf);
 }
 
 static void
-param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
 
@@ -661,15 +714,14 @@ param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
     oct = tvb_get_guint8(tvb, offset);
 
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "Number of voice mail messages, %d%d",
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "Number of voice mail messages: %d%d",
        (oct & 0xf0) >> 4,
        oct & 0x0f);
 }
 
 static void
-param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     gchar      *str = NULL;
@@ -686,22 +738,20 @@ param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     case 3: str = "Use High-priority alert"; break;
     }
 
-    my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  %s",
-       bigbuf,
+       ansi_637_bigbuf,
        str);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Reserved",
-       bigbuf);
+       ansi_637_bigbuf);
 }
 
 static void
-param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     gchar      *str = NULL;
@@ -723,14 +773,12 @@ param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     default: str = "Reserved"; break;
     }
 
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s",
+    proto_tree_add_text(tree, tvb, offset, 1,
        str);
 }
 
 static void
-param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct, oct2, num_fields, odd;
     guint32    saved_offset;
@@ -741,45 +789,40 @@ param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
     oct = tvb_get_guint8(tvb, offset);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
-       "%s :  Digit mode, %s",
-       bigbuf,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Digit mode: %s",
+       ansi_637_bigbuf,
        (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
 
     if (oct & 0x80)
     {
-       my_decode_bitfield_value(bigbuf, oct, 0x70, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s :  Type of number (%d)",
-           bigbuf,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x70, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Type of number: (%d)",
+           ansi_637_bigbuf,
            (oct & 0x70) >> 4);
 
-       my_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s :  Numbering plan (%d)",
-           bigbuf,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Numbering plan: (%d)",
+           ansi_637_bigbuf,
            oct & 0x0f);
 
        offset++;
        num_fields = tvb_get_guint8(tvb, offset);
 
-       my_decode_bitfield_value(bigbuf, oct, 0xff, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s :  Number of fields (%d)",
-           bigbuf,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xff, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Number of fields: (%d)",
+           ansi_637_bigbuf,
            num_fields);
 
        if (num_fields == 0) return;
 
        if (num_fields > (len - 2))
        {
-           proto_tree_add_none_format(tree, hf_ansi_637_none,
-               tvb, offset, 1,
+           proto_tree_add_text(tree, tvb, offset, 1,
                "Missing %d octet(s) for number of fields",
                (num_fields + 2) - len);
 
@@ -791,15 +834,14 @@ param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
        i = 0;
        while (i < num_fields)
        {
-           bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f;
+           ansi_637_bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f;
            i++;
        }
-       bigbuf[i] = '\0';
+       ansi_637_bigbuf[i] = '\0';
 
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, num_fields,
-           "Number, %s",
-           bigbuf);
+       proto_tree_add_text(tree, tvb, offset, num_fields,
+           "Number: %s",
+           ansi_637_bigbuf);
     }
     else
     {
@@ -808,19 +850,18 @@ param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
        oct2 = tvb_get_guint8(tvb, offset);
        num_fields |= ((oct2 & 0x80) >> 7);
 
-       my_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset-1, 1,
-           "%s :  Number of fields (%d)",
-           bigbuf,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+       proto_tree_add_text(tree, tvb, offset-1, 1,
+           "%s :  Number of fields (MBS): (%d)",
+           ansi_637_bigbuf,
            num_fields);
 
-       my_decode_bitfield_value(bigbuf, oct2, 0x80, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
-           "%s :  Number of fields",
-           bigbuf);
+       my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Number of fields (LSB)",
+           ansi_637_bigbuf);
 
+       oct = oct2;
        odd = FALSE;
 
        if (num_fields > 0)
@@ -830,8 +871,7 @@ param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 
            if (required_octs + 2 > len)
            {
-               proto_tree_add_none_format(tree, hf_ansi_637_none,
-                   tvb, offset, 1,
+               proto_tree_add_text(tree, tvb, offset, 1,
                    "Missing %d octet(s) for number of fields",
                    (required_octs + 2) - len);
 
@@ -839,50 +879,44 @@ param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
            }
 
            odd = num_fields & 0x01;
-           memset((void *) bigbuf, 0, sizeof(bigbuf));
+           memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
            saved_offset = offset;
            offset++;
 
            i = 0;
            while (i < num_fields)
            {
-               bigbuf[i] =
-                   ((oct & 0x78) >> 3) |
-                   0x30;
+               ansi_637_bigbuf[i] =
+                   air_digits[(oct & 0x78) >> 3];
+
+               i++;
+               if (i >= num_fields) break;
 
-               if (!odd)
-               {
-                   oct2 = tvb_get_guint8(tvb, offset);
-                   offset++;
+               oct2 = tvb_get_guint8(tvb, offset);
+               offset++;
 
-                   i++;
-                   bigbuf[i] =
-                       ((oct & 0x07) << 1) |
-                       ((oct2 & 0x80) >> 7) |
-                       0x30;
+               ansi_637_bigbuf[i] =
+                   air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)];
 
-                   oct = oct2;
-               }
+               oct = oct2;
 
                i++;
            }
 
-           proto_tree_add_none_format(tree, hf_ansi_637_none,
-               tvb, saved_offset, offset - saved_offset,
-               "Number, %s",
-               bigbuf);
+           proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+               "Number: %s",
+               ansi_637_bigbuf);
        }
 
-       my_decode_bitfield_value(bigbuf, oct, odd ? 0x07: 0x7f, 8);
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, offset, 1,
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x07: 0x7f, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
            "%s :  Reserved",
-           bigbuf);
+           ansi_637_bigbuf);
     }
 }
 
 static void
-param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+tele_param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
     guint8     oct;
     gchar      *str = NULL;
@@ -899,47 +933,604 @@ param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     case 0x11: str = "Reserved"; break;
     }
 
-    my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  %s",
-       bigbuf,
+       ansi_637_bigbuf,
        str);
 
-    my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
-    proto_tree_add_none_format(tree, hf_ansi_637_none,
-       tvb, offset, 1,
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
        "%s :  Reserved",
-       bigbuf);
+       ansi_637_bigbuf);
+}
+
+#define        NUM_TELE_PARAM (sizeof(ansi_tele_param_strings)/sizeof(value_string))
+static gint ett_ansi_637_tele_param[NUM_TELE_PARAM];
+static void (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+    NULL,                      /* Message Identifier */
+    tele_param_user_data,      /* User Data */
+    tele_param_rsp_code,       /* User Response Code */
+    tele_param_timestamp,      /* Message Center Time Stamp */
+    tele_param_timestamp,      /* Validity Period  Absolute */
+    tele_param_rel_timestamp,  /* Validity Period  Relative */
+    tele_param_timestamp,      /* Deferred Delivery Time - Absolute */
+    tele_param_rel_timestamp,  /* Deferred Delivery Time - Relative */
+    tele_param_pri_ind,                /* Priority Indicator */
+    tele_param_priv_ind,       /* Privacy Indicator */
+    tele_param_reply_opt,      /* Reply Option */
+    tele_param_num_messages,   /* Number of Messages */
+    tele_param_alert,          /* Alert on Message Delivery */
+    tele_param_lang_ind,       /* Language Indicator */
+    tele_param_cb_num,         /* Call-Back Number */
+    tele_param_disp_mode,      /* Message Display Mode */
+    NULL,                      /* Multiple Encoding User Data */
+    NULL,                      /* NONE */
+};
+
+static void
+trans_param_tele_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint32    value;
+    gchar      *str = NULL;
+
+    EXACT_DATA_CHECK(len, 2);
+
+    value = tvb_get_ntohs(tvb, offset);
+
+    ansi_637_trans_tele_id = value;
+
+    str = match_strval(value, ansi_tele_id_strings);
+
+    if (NULL == str) str = "Unrecognized Teleservice ID";
+
+    proto_tree_add_text(tree, tvb, offset, 2,
+       "%s (%d)",
+       str,
+       value);
+
+    sprintf(add_string, " - %s (%d)", str, value);
+}
+
+static void
+trans_param_srvc_cat(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint32    value;
+    gchar      *str = NULL;
+
+    EXACT_DATA_CHECK(len, 2);
+
+    value = tvb_get_ntohs(tvb, offset);
+
+    str = match_strval(value, ansi_srvc_cat_strings);
+
+    if (NULL == str) str = "Reserved";
+
+    proto_tree_add_text(tree, tvb, offset, 2,
+       str);
+
+    sprintf(add_string, " - %s (%d)", str, value);
+}
+
+static void
+trans_param_address(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint8     oct, oct2, num_fields, odd;
+    gboolean   email_addr;
+    guint32    saved_offset;
+    guint32    required_octs;
+    guint32    i;
+    gchar      *str;
+
+    SHORT_DATA_CHECK(len, 2);
+
+    add_string = add_string;
+    email_addr = FALSE;
+
+    oct = tvb_get_guint8(tvb, offset);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Digit mode: %s",
+       ansi_637_bigbuf,
+       (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Number mode: %s",
+       ansi_637_bigbuf,
+       (oct & 0x40) ? "Data Network Address" : "ANSI T1.607");
+
+    if (oct & 0x80)
+    {
+       if (oct & 0x40)
+       {
+           switch ((oct & 0x38) >> 3)
+           {
+           case 0: str = "Unknown"; break;
+           case 1: str = "Internet Protocol (RFC 791)"; break;
+           case 2: str = "Internet Email Address (RFC 822)"; email_addr = TRUE; break;
+           default:
+               str = "Reserved";
+               break;
+           }
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Type of number: %s (%d)",
+               ansi_637_bigbuf,
+               str,
+               (oct & 0x38) >> 3);
+
+           offset++;
+           num_fields = (oct & 0x07) << 5;
+           oct2 = tvb_get_guint8(tvb, offset);
+           num_fields |= ((oct2 & 0xf8) >> 3);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+           proto_tree_add_text(tree, tvb, offset-1, 1,
+               "%s :  Number of fields (MSB): (%d)",
+               ansi_637_bigbuf,
+               num_fields);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Number of fields (LSB)",
+               ansi_637_bigbuf);
+
+           if (num_fields == 0) return;
+
+           if (num_fields > (len - 2))
+           {
+               proto_tree_add_text(tree, tvb, offset, 1,
+                   "Missing %d octet(s) for number of fields",
+                   (num_fields + 2) - len);
+
+               return;
+           }
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Most significant bits of first field",
+               ansi_637_bigbuf);
+
+           offset++;
+           oct = oct2;
+
+           i = 0;
+           while (i < num_fields)
+           {
+               ansi_637_bigbuf[i] = (oct & 0x07) << 5;
+               ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf8) >> 3;
+               i++;
+           }
+           ansi_637_bigbuf[i] = '\0';
+
+           if (email_addr)
+           {
+               proto_tree_add_text(tree, tvb, offset, num_fields - 1,
+                   "Number: %s",
+                   ansi_637_bigbuf);
+           }
+           else
+           {
+               proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
+                   ansi_637_bigbuf);
+           }
+
+           offset += (num_fields - 1);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Least significant bits of last field",
+               ansi_637_bigbuf);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Reserved",
+               ansi_637_bigbuf);
+       }
+       else
+       {
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Type of number: (%d)",
+               ansi_637_bigbuf,
+               (oct & 0x38) >> 3);
+
+           oct2 = tvb_get_guint8(tvb, offset + 1);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Numbering plan (MSB): (%d)",
+               ansi_637_bigbuf,
+               ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7));
+
+           offset++;
+           oct = oct2;
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Numbering plan (LSB)",
+               ansi_637_bigbuf);
+
+           offset++;
+           num_fields = (oct & 0x7f) << 1;
+           oct2 = tvb_get_guint8(tvb, offset);
+           num_fields |= ((oct2 & 0x80) >> 7);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+           proto_tree_add_text(tree, tvb, offset-1, 1,
+               "%s :  Number of fields (MSB): (%d)",
+               ansi_637_bigbuf,
+               num_fields);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Number of fields (LSB)",
+               ansi_637_bigbuf);
+
+           if (num_fields == 0) return;
+
+           if (num_fields > (len - 3))
+           {
+               proto_tree_add_text(tree, tvb, offset, 1,
+                   "Missing %d octet(s) for number of fields",
+                   (num_fields + 3) - len);
+
+               return;
+           }
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x7f, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Most significant bits of first field",
+               ansi_637_bigbuf);
+
+           offset++;
+           oct = oct2;
+
+           i = 0;
+           while (i < num_fields)
+           {
+               ansi_637_bigbuf[i] = (oct & 0x7f) << 1;
+               ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0x80) >> 7;
+               i++;
+           }
+           ansi_637_bigbuf[i] = '\0';
+
+           proto_tree_add_text(tree, tvb, offset, num_fields - 1,
+               "Number: %s",
+               ansi_637_bigbuf);
+
+           offset += (num_fields - 1);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Least significant bit of last field",
+               ansi_637_bigbuf);
+
+           my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+           proto_tree_add_text(tree, tvb, offset, 1,
+               "%s :  Reserved",
+               ansi_637_bigbuf);
+       }
+    }
+    else
+    {
+       offset++;
+       num_fields = (oct & 0x3f) << 2;
+       oct2 = tvb_get_guint8(tvb, offset);
+       num_fields |= ((oct2 & 0xc0) >> 6);
+
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+       proto_tree_add_text(tree, tvb, offset-1, 1,
+           "%s :  Number of fields (MSB): (%d)",
+           ansi_637_bigbuf,
+           num_fields);
+
+       my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xc0, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Number of fields (LSB)",
+           ansi_637_bigbuf);
+
+       oct = oct2;
+       odd = FALSE;
+
+       if (num_fields > 0)
+       {
+           i = (num_fields - 1) * 4;
+           required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+           if (required_octs + 2 > len)
+           {
+               proto_tree_add_text(tree, tvb, offset, 1,
+                   "Missing %d octet(s) for number of fields",
+                   (required_octs + 2) - len);
+
+               return;
+           }
+
+           odd = num_fields & 0x01;
+           memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
+           saved_offset = offset;
+           offset++;
+
+           i = 0;
+           while (i < num_fields)
+           {
+               ansi_637_bigbuf[i] =
+                   air_digits[(oct & 0x3c) >> 2];
+
+               i++;
+               if (i >= num_fields) break;
+
+               oct2 = tvb_get_guint8(tvb, offset);
+               offset++;
+
+               ansi_637_bigbuf[i] =
+                   air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)];
+
+               oct = oct2;
+
+               i++;
+           }
+
+           proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+               "Number: %s",
+               ansi_637_bigbuf);
+       }
+
+       my_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x03: 0x3f, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "%s :  Reserved",
+           ansi_637_bigbuf);
+    }
 }
 
-#define        NUM_PARAM (sizeof(ansi_param_strings)/sizeof(value_string))
-static gint ett_ansi_param[NUM_PARAM];
-static void (*ansi_637_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
-    NULL,      /* Message Identifier */
-    param_user_data,   /* User Data */
-    param_rsp_code,    /* User Response Code */
-    param_timestamp,   /* Message Center Time Stamp */
-    param_timestamp,   /* Validity Period  Absolute */
-    param_rel_timestamp,       /* Validity Period  Relative */
-    param_timestamp,   /* Deferred Delivery Time - Absolute */
-    param_rel_timestamp,       /* Deferred Delivery Time - Relative */
-    param_pri_ind,     /* Priority Indicator */
-    param_priv_ind,    /* Privacy Indicator */
-    param_reply_opt,   /* Reply Option */
-    param_num_messages,        /* Number of Messages */
-    param_alert,       /* Alert on Message Delivery */
-    param_lang_ind,    /* Language Indicator */
-    param_cb_num,      /* Call-Back Number */
-    param_disp_mode,   /* Message Display Mode */
-    NULL,      /* Multiple Encoding User Data */
+static void
+trans_param_subaddress(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint8     oct, oct2, num_fields;
+    guint32    i;
+    gchar      *str;
+
+    SHORT_DATA_CHECK(len, 2);
+
+    add_string = add_string;
+
+    oct = tvb_get_guint8(tvb, offset);
+
+    switch ((oct & 0xe0) >> 5)
+    {
+    case 0: str = "NSAP (CCITT Recommendation X.213 or ISO 8348 AD2)"; break;
+    case 1: str = "User-specified"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Type: %s",
+       ansi_637_bigbuf,
+       str);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Odd",
+       ansi_637_bigbuf);
+
+    offset++;
+    num_fields = (oct & 0x0f) << 4;
+    oct2 = tvb_get_guint8(tvb, offset);
+    num_fields |= ((oct2 & 0xf0) >> 4);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, offset-1, 1,
+       "%s :  Number of fields (MSB): (%d)",
+       ansi_637_bigbuf,
+       num_fields);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Number of fields (LSB)",
+       ansi_637_bigbuf);
+
+    if (num_fields == 0) return;
+
+    if (num_fields > (len - 2))
+    {
+       proto_tree_add_text(tree, tvb, offset, 1,
+           "Missing %d octet(s) for number of fields",
+           (num_fields + 2) - len);
+
+       return;
+    }
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Most significant bits of first field",
+       ansi_637_bigbuf);
+
+    offset++;
+    oct = oct2;
+
+    i = 0;
+    while (i < num_fields)
+    {
+       ansi_637_bigbuf[i] = (oct & 0x0f) << 4;
+       ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf0) >> 4;
+       i++;
+    }
+    ansi_637_bigbuf[i] = '\0';
+
+    proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
+       ansi_637_bigbuf);
+
+    offset += (num_fields - 1);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Least significant bits of last field",
+       ansi_637_bigbuf);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Reserved",
+       ansi_637_bigbuf);
+}
+
+static void
+trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint8     oct;
+
+    len = len;
+    oct = tvb_get_guint8(tvb, offset);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Reply Sequence Number: %d",
+       ansi_637_bigbuf,
+       (oct & 0xfc) >> 2);
+
+    sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Reserved",
+       ansi_637_bigbuf);
+}
+
+static void
+trans_param_cause_codes(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    guint8     oct;
+    gchar      *str = NULL;
+
+    oct = tvb_get_guint8(tvb, offset);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Reply Sequence Number: %d",
+       ansi_637_bigbuf,
+       (oct & 0xfc) >> 2);
+
+    switch (oct & 0x03)
+    {
+    case 0x00: str = "No error"; break;
+    case 0x02: str = "Temporary Condition"; break;
+    case 0x03: str = "Permanent Condition"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
+
+    my_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+       "%s :  Error Class: %s",
+       ansi_637_bigbuf,
+       str);
+
+    offset++;
+
+    if (!(oct & 0x03)) return;
+
+    if (len == 1) return;
+
+    oct = tvb_get_guint8(tvb, offset);
+
+    switch (oct)
+    {
+    case 0: str = "Address vacant"; break;
+    case 1: str = "Address translation failure"; break;
+    case 2: str = "Network resource shortage"; break;
+    case 3: str = "Network failure"; break;
+    case 4: str = "Invalid Teleservice ID"; break;
+    case 5: str = "Other network problem"; break;
+    case 6: str = "Unsupported network interface"; break;
+    case 32: str = "No page response"; break;
+    case 33: str = "Destination busy"; break;
+    case 34: str = "No acknowledgement"; break;
+    case 35: str = "Destination resource shortage"; break;
+    case 36: str = "SMS delivery postponed"; break;
+    case 37: str = "Destination out of service"; break;
+    case 38: str = "Destination no longer at this address"; break;
+    case 39: str = "Other terminal problem"; break;
+    case 64: str = "Radio interface resource shortage"; break;
+    case 65: str = "Radio interface incompatibility"; break;
+    case 66: str = "Other radio interface problem"; break;
+    case 67: str = "Unsupported Base Station Capability"; break;
+    case 96: str = "Encoding problem"; break;
+    case 97: str = "Service origination denied"; break;
+    case 98: str = "Service termination denied"; break;
+    case 99: str = "Supplementary service not supported"; break;
+    case 100: str = "Service not supported"; break;
+    case 101: str = "Reserved"; break;
+    case 102: str = "Missing expected parameter"; break;
+    case 103: str = "Missing mandatory parameter"; break;
+    case 104: str = "Unrecognized parameter value"; break;
+    case 105: str = "Unexpected parameter value"; break;
+    case 106: str = "User Data size error"; break;
+    case 107: str = "Other general problems"; break;
+    case 108: str = "Session not active"; break;
+    default:
+       if ((oct >= 7) && (oct <= 31)) { str = "Reserved, treat as Other network problem"; }
+       else if ((oct >= 40) && (oct <= 47)) { str = "Reserved, treat as Other terminal problem"; }
+       else if ((oct >= 48) && (oct <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
+       else if ((oct >= 68) && (oct <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
+       else if ((oct >= 109) && (oct <= 223)) { str = "Reserved, treat as Other general problems"; }
+       else { str = "Reserved for protocol extension, treat as Other general problems"; }
+       break;
+    }
+
+    proto_tree_add_text(tree, tvb, offset, 1,
+       str);
+}
+
+static void
+trans_param_bearer_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+    tvbuff_t   *tele_tvb;
+
+    add_string = add_string;
+
+    proto_tree_add_text(tree, tvb, offset, len,
+       "Bearer Data");
+
+    /*
+     * dissect the embedded teleservice data
+     */
+    tele_tvb = tvb_new_subset(tvb, offset, len, len);
+
+    dissector_try_port(tele_dissector_table, ansi_637_trans_tele_id,
+       tele_tvb, g_pinfo, g_tree);
+}
+
+#define        NUM_TRANS_PARAM (sizeof(ansi_trans_param_strings)/sizeof(value_string))
+static gint ett_ansi_637_trans_param[NUM_TRANS_PARAM];
+static void (*ansi_637_trans_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = {
+    trans_param_tele_id,       /* Teleservice Identifier */
+    trans_param_srvc_cat,      /* Service Category */
+    trans_param_address,       /* Originating Address */
+    trans_param_subaddress,    /* Originating Subaddress */
+    trans_param_address,       /* Destination Address */
+    trans_param_subaddress,    /* Destination Subaddress */
+    trans_param_bearer_reply_opt,      /* Bearer Reply Option */
+    trans_param_cause_codes,   /* Cause Codes */
+    trans_param_bearer_data,   /* Bearer Data */
     NULL,      /* NONE */
 };
 
+#define        NUM_TRANS_MSG_TYPE (sizeof(ansi_trans_msg_type_strings)/sizeof(value_string))
+static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
+
 /* GENERIC IS-637 DISSECTOR FUNCTIONS */
 
 static gboolean
-dissect_ansi_637_param(tvbuff_t *tvb, proto_tree *tree, guint32        *offset)
+dissect_ansi_637_tele_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
 {
     void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = NULL;
     guint8     oct;
@@ -954,23 +1545,22 @@ dissect_ansi_637_param(tvbuff_t *tvb, proto_tree *tree, guint32  *offset)
     curr_offset = *offset;
 
     oct = tvb_get_guint8(tvb, curr_offset);
-    str = my_match_strval((guint32) oct, ansi_param_strings, &idx);
+    str = my_match_strval((guint32) oct, ansi_tele_param_strings, &idx);
 
     if (NULL == str)
     {
        return(FALSE);
     }
 
-    ett_param_idx = ett_ansi_param[idx];
-    param_fcn = ansi_637_param_fcn[idx];
+    ett_param_idx = ett_ansi_637_tele_param[idx];
+    param_fcn = ansi_637_tele_param_fcn[idx];
 
     item =
-       proto_tree_add_none_format(tree, hf_ansi_637_none,
-           tvb, curr_offset, -1, str);
+       proto_tree_add_text(tree, tvb, curr_offset, -1, str);
 
     subtree = proto_item_add_subtree(item, ett_param_idx);
 
-    proto_tree_add_uint(subtree, hf_ansi_637_subparam_id,
+    proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
        tvb, curr_offset, 1, oct);
 
     curr_offset++;
@@ -988,8 +1578,8 @@ dissect_ansi_637_param(tvbuff_t *tvb, proto_tree *tree, guint32    *offset)
     {
        if (param_fcn == NULL)
        {
-           proto_tree_add_none_format(subtree, hf_ansi_637_none,
-               tvb, curr_offset, len, "Parameter Data");
+           proto_tree_add_text(subtree, tvb, curr_offset,
+               len, "Parameter Data");
        }
        else
        {
@@ -1005,7 +1595,7 @@ dissect_ansi_637_param(tvbuff_t *tvb, proto_tree *tree, guint32   *offset)
 }
 
 static void
-dissect_ansi_637_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
+dissect_ansi_637_tele_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
 {
     guint8     oct;
     guint8     len;
@@ -1034,7 +1624,7 @@ dissect_ansi_637_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
     msg_type = (octs >> 20) & 0x0f;
     msg_id = (octs >> 4) & 0xffff;
 
-    str = match_strval(msg_type, ansi_msg_type_strings);
+    str = match_strval(msg_type, ansi_tele_msg_type_strings);
 
     /*
      * do not append to COL_INFO
@@ -1046,19 +1636,19 @@ dissect_ansi_637_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
 
     subtree = proto_item_add_subtree(item, ett_params);
 
-    proto_tree_add_uint(subtree, hf_ansi_637_subparam_id,
+    proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
        tvb, 0, 1, oct);
 
     proto_tree_add_uint(subtree, hf_ansi_637_length,
        tvb, 1, 1, len);
 
-    proto_tree_add_uint(subtree, hf_ansi_637_msg_type,
+    proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_type,
        tvb, 2, 3, octs);
 
-    proto_tree_add_uint(subtree, hf_ansi_637_msg_id,
+    proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_id,
        tvb, 2, 3, octs);
 
-    proto_tree_add_uint(subtree, hf_ansi_637_msg_junk,
+    proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_rsvd,
        tvb, 2, 3, octs);
 
     proto_item_set_len(item, 2 + len);
@@ -1068,10 +1658,9 @@ dissect_ansi_637_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
 
     while ((len - curr_offset) > 0)
     {
-       if (!dissect_ansi_637_param(tvb, ansi_637_tree, &curr_offset))
+       if (!dissect_ansi_637_tele_param(tvb, ansi_637_tree, &curr_offset))
        {
-           proto_tree_add_none_format(ansi_637_tree, hf_ansi_637_none,
-               tvb, curr_offset, len - curr_offset,
+           proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
                "Unknown Parameter Data");
            break;
        }
@@ -1079,13 +1668,13 @@ dissect_ansi_637_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
 }
 
 static void
-dissect_ansi_637(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
     proto_item *ansi_637_item;
     proto_tree *ansi_637_tree = NULL;
     gchar      *str = NULL;
 
-    if (!proto_is_protocol_enabled(proto_ansi_637))
+    if (!proto_is_protocol_enabled(proto_ansi_637_tele))
     {
        call_dissector(data_handle,tvb, pinfo, tree);
        return;
@@ -1104,24 +1693,169 @@ dissect_ansi_637(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        /*
         * create the ansi_637 protocol tree
         */
-       str = match_strval(pinfo->match_port, ansi_tele_strings);
+       str = match_strval(pinfo->match_port, ansi_tele_id_strings);
 
        if (NULL == str) str = "Unrecognized Teleservice ID";
 
        ansi_637_item =
-           proto_tree_add_protocol_format(tree, proto_ansi_637, tvb, 0, -1,
-               "%s %s (%d)",
-               ansi_proto_name,
+           proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1,
+               "%s %s (%d)",
+               ansi_proto_name_tele,
                str,
                pinfo->match_port);
 
        ansi_637_tree =
-           proto_item_add_subtree(ansi_637_item, ett_ansi_637);
+           proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
 
-       dissect_ansi_637_message(tvb, ansi_637_tree);
+       dissect_ansi_637_tele_message(tvb, ansi_637_tree);
     }
 }
 
+static gboolean
+dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
+{
+    void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = NULL;
+    guint8     oct;
+    guint8     len;
+    guint32    curr_offset;
+    gint       ett_param_idx, idx;
+    proto_tree *subtree;
+    proto_item *item;
+    gchar      *str = NULL;
+
+    curr_offset = *offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+    str = my_match_strval((guint32) oct, ansi_trans_param_strings, &idx);
+
+    if (NULL == str)
+    {
+       return(FALSE);
+    }
+
+    ett_param_idx = ett_ansi_637_trans_param[idx];
+    param_fcn = ansi_637_trans_param_fcn[idx];
+
+    item =
+       proto_tree_add_text(tree, tvb, curr_offset, -1, str);
+
+    subtree = proto_item_add_subtree(item, ett_param_idx);
+
+    proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id,
+       tvb, curr_offset, 1, oct);
+
+    curr_offset++;
+
+    len = tvb_get_guint8(tvb, curr_offset);
+
+    proto_item_set_len(item, (curr_offset - *offset) + len + 1);
+
+    proto_tree_add_uint(subtree, hf_ansi_637_length,
+       tvb, curr_offset, 1, len);
+
+    curr_offset++;
+
+    if (len > 0)
+    {
+       if (param_fcn == NULL)
+       {
+           proto_tree_add_text(subtree, tvb, curr_offset,
+               len, "Parameter Data");
+       }
+       else
+       {
+           ansi_637_add_string[0] = '\0';
+           (*param_fcn)(tvb, subtree, len, curr_offset, ansi_637_add_string);
+
+           if (ansi_637_add_string[0] != '\0')
+           {
+               proto_item_append_text(item, ansi_637_add_string);
+           }
+       }
+
+       curr_offset += len;
+    }
+
+    *offset = curr_offset;
+
+    return(TRUE);
+}
+
+static void
+dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_item *ansi_637_item;
+    proto_tree *ansi_637_tree = NULL;
+    guint32    curr_offset;
+    gint       idx;
+    gchar      *str = NULL;
+    guint8     oct;
+    guint8     len;
+
+    if (!proto_is_protocol_enabled(proto_ansi_637_trans))
+    {
+       call_dissector(data_handle,tvb, pinfo, tree);
+       return;
+    }
+
+    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_pinfo = pinfo;
+       g_tree = tree;
+
+       /*
+        * create the ansi_637 protocol tree
+        */
+       oct = tvb_get_guint8(tvb, 0);
+
+       str = my_match_strval(oct, ansi_trans_msg_type_strings, &idx);
+
+       if (NULL == str)
+       {
+           ansi_637_item =
+               proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
+                   "%s - Unrecognized Transport Layer Message Type (%d)",
+                   ansi_proto_name_trans,
+                   oct);
+
+           ansi_637_tree =
+               proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans);
+       }
+       else
+       {
+           ansi_637_item =
+               proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
+                   "%s - %s",
+                   ansi_proto_name_trans,
+                   str);
+
+           ansi_637_tree =
+               proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]);
+       }
+
+       curr_offset = 1;
+
+       len = tvb_length(tvb);
+
+       while ((len - curr_offset) > 0)
+       {
+           if (!dissect_ansi_637_trans_param(tvb, ansi_637_tree, &curr_offset))
+           {
+               proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
+                   "Unknown Parameter Data");
+               break;
+           }
+       }
+    }
+}
 
 /* Register the protocol with Ethereal */
 void
@@ -1132,19 +1866,24 @@ proto_register_ansi_637(void)
     /* Setup list of header fields */
     static hf_register_info hf[] =
     {
-       { &hf_ansi_637_msg_type,
+       { &hf_ansi_637_trans_msg_type,
+         { "Message Type",
+           "ansi_637.trans_msg_type",
+           FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000,
+           "", HFILL }},
+       { &hf_ansi_637_tele_msg_type,
          { "Message Type",
-           "ansi_637.msg_type",
-           FT_UINT24, BASE_DEC, VALS(ansi_msg_type_strings), 0xf00000,
+           "ansi_637.tele_msg_type",
+           FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
            "", HFILL }},
-       { &hf_ansi_637_msg_id,
+       { &hf_ansi_637_tele_msg_id,
          { "Message ID",
-           "ansi_637.msg_id",
+           "ansi_637.tele_msg_id",
            FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
            "", HFILL }},
-       { &hf_ansi_637_msg_junk,
+       { &hf_ansi_637_tele_msg_rsvd,
          { "Reserved",
-           "ansi_637.msg_junk",
+           "ansi_637.tele_msg_rsvd",
            FT_UINT24, BASE_DEC, NULL, 0x00000f,
            "", HFILL }},
        { &hf_ansi_637_length,
@@ -1157,67 +1896,101 @@ proto_register_ansi_637(void)
            FT_NONE, 0, 0, 0,
            "", HFILL }
        },
-       { &hf_ansi_637_subparam_id,
-           { "Subparam ID",    "ansi_637.subparam_id",
-           FT_UINT8, BASE_DEC, VALS(ansi_param_strings), 0,
+       { &hf_ansi_637_tele_subparam_id,
+           { "Teleservice Subparam ID",        "ansi_637.tele_subparam_id",
+           FT_UINT8, BASE_DEC, VALS(ansi_tele_param_strings), 0,
+           "", HFILL }
+       },
+       { &hf_ansi_637_trans_param_id,
+           { "Transport Param ID",     "ansi_637.trans_param_id",
+           FT_UINT8, BASE_DEC, VALS(ansi_trans_param_strings), 0,
+           "", HFILL }
+       },
+       { &hf_ansi_637_bin_addr,
+           { "Binary Address", "ansi_637.bin_addr",
+           FT_BYTES, BASE_HEX, 0, 0,
            "", HFILL }
        },
     };
 
     /* Setup protocol subtree array */
-#define        NUM_INDIVIDUAL_PARAMS   2
-    static gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_PARAM];
+#define        NUM_INDIVIDUAL_PARAMS   3
+    static gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
 
     memset((void *) ett, 0, sizeof(ett));
 
-    ett[0] = &ett_ansi_637;
-    ett[1] = &ett_params;
+    ett[0] = &ett_ansi_637_tele;
+    ett[1] = &ett_ansi_637_trans;
+    ett[2] = &ett_params;
+
+    for (i=0; i < NUM_TELE_PARAM; i++)
+    {
+       ett_ansi_637_tele_param[i] = -1;
+       ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_637_tele_param[i];
+    }
+
+    for (i=0; i < NUM_TRANS_MSG_TYPE; i++)
+    {
+       ett_ansi_637_trans_msg[i] = -1;
+       ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+i] = &ett_ansi_637_trans_msg[i];
+    }
 
-    for (i=0; i < NUM_PARAM; i++)
+    for (i=0; i < NUM_TRANS_PARAM; i++)
     {
-       ett_ansi_param[i] = -1;
-       ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_param[i];
+       ett_ansi_637_trans_param[i] = -1;
+       ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i];
     }
 
     /* Register the protocol name and description */
-    proto_ansi_637 =
-       proto_register_protocol(ansi_proto_name, "ANSI IS-637-A", "ansi_637");
+    proto_ansi_637_tele =
+       proto_register_protocol(ansi_proto_name_tele, "ANSI IS-637-A Teleservice", "ansi_637_tele");
+
+    proto_ansi_637_trans =
+       proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
 
     /* Required function calls to register the header fields and subtrees used */
-    proto_register_field_array(proto_ansi_637, hf, array_length(hf));
+    proto_register_field_array(proto_ansi_637_tele, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
+
+    tele_dissector_table =
+       register_dissector_table("ansi_637.tele_id",
+           "ANSI IS-637-A Teleservice ID", FT_UINT8, BASE_DEC);
 }
 
 
 void
 proto_reg_handoff_ansi_637(void)
 {
-    dissector_handle_t ansi_637_handle;
+    dissector_handle_t ansi_637_tele_handle;
+    dissector_handle_t ansi_637_trans_handle;
     guint              i;
 
-    ansi_637_handle = create_dissector_handle(dissect_ansi_637, proto_ansi_637);
+    ansi_637_tele_handle = create_dissector_handle(dissect_ansi_637_tele, proto_ansi_637_tele);
+    ansi_637_trans_handle = create_dissector_handle(dissect_ansi_637_trans, proto_ansi_637_trans);
 
     /*
      * register for all known teleservices
      * '-1' is to stop before trailing '0' entry
      *
-     * to add teleservices, modify 'ansi_tele_strings'
+     * to add teleservices, modify 'ansi_tele_id_strings'
      */
-    for (i=0; i < ((sizeof(ansi_tele_strings)/sizeof(value_string))-1); i++)
+    for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++)
     {
        /*
         * ANSI MAP dissector will push out teleservice ids
         */
-       dissector_add("ansi_map.tele_id", ansi_tele_strings[i].value, ansi_637_handle);
+       dissector_add("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
 
        /*
-        * ANSI A-interface dissector will push out teleservice ids after
-        * transport layer dissection
-        *
-        * This is for IOS or IS-634 variants.
+        * we will push out teleservice ids after Transport layer decode
         */
-       /* dissector_add("ansi_a.tele_id", ansi_tele_strings[i].value, ansi_637_handle); */
+       dissector_add("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
     }
 
+    /*
+     * ANSI A-interface will push out transport layer data
+     */
+    dissector_add("ansi_a.sms", 0, ansi_637_trans_handle);
+
     data_handle = find_dissector("data");
 }
diff --git a/packet-ansi_a.c b/packet-ansi_a.c
new file mode 100644 (file)
index 0000000..0909cb5
--- /dev/null
@@ -0,0 +1,8423 @@
+/* packet-ansi_a.c
+ * Routines for ANSI A Interface (IS-634/IOS) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Title               3GPP2                   Other
+ *
+ *   Inter-operability Specification (IOS) for CDMA
+ *   2000 Access Network Interfaces
+ *                     3GPP2 A.S0001-1         TIA/EIA-2001
+ *
+ * $Id: packet-ansi_a.c,v 1.1 2003/10/22 20:59:01 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"
+#include "prefs.h"
+
+#include "packet-bssap.h"
+
+/* PROTOTYPES/FORWARDS */
+
+void proto_reg_handoff_ansi_a(void);
+
+#define ANSI_A_MAX(x,y)        (((x) < (y)) ? (y) : (x))
+
+#define ANSI_A_MIN(x,y)        (((x) < (y)) ? (x) : (y))
+
+/*
+ * taken from packet-bssap.h
+ * I wasn't sure if I wanted to #include from ../bssap !
+#define PDU_TYPE_BSMAP 0x00
+#define PDU_TYPE_DTAP  0x01
+ */
+
+static const value_string ansi_bsmap_strings[] = {
+    { 0x69,    "Additional Service Notification" },
+    { 0x65,    "ADDS Page" },
+    { 0x66,    "ADDS Page Ack" },
+    { 0x67,    "ADDS Transfer" },
+    { 0x68,    "ADDS Transfer Ack" },
+    { 0x02,    "Assignment Complete" },
+    { 0x03,    "Assignment Failure" },
+    { 0x01,    "Assignment Request" },
+    { 0x45,    "Authentication Request" },
+    { 0x46,    "Authentication Response" },
+    { 0x48,    "Base Station Challenge" },
+    { 0x49,    "Base Station Challenge Response" },
+    { 0x40,    "Block" },
+    { 0x41,    "Block Acknowledge" },
+    { 0x09,    "BS Service Request" },
+    { 0x0A,    "BS Service Response" },
+    { 0x20,    "Clear Command" },
+    { 0x21,    "Clear Complete" },
+    { 0x22,    "Clear Request" },
+    { 0x57,    "Complete Layer 3 Information" },
+    { 0x60,    "Feature Notification" },
+    { 0x61,    "Feature Notification Ack" },
+    { 0x13,    "Handoff Command" },
+    { 0x15,    "Handoff Commenced" },
+    { 0x14,    "Handoff Complete" },
+    { 0x16,    "Handoff Failure" },
+    { 0x17,    "Handoff Performed" },
+    { 0x10,    "Handoff Request" },
+    { 0x12,    "Handoff Request Acknowledge" },
+    { 0x11,    "Handoff Required" },
+    { 0x1A,    "Handoff Required Reject" },
+    { 0x6C,    "PACA Command" },
+    { 0x6D,    "PACA Command Ack" },
+    { 0x6E,    "PACA Update" },
+    { 0x6F,    "PACA Update Ack" },
+    { 0x52,    "Paging Request" },
+    { 0x53,    "Privacy Mode Command" },
+    { 0x55,    "Privacy Mode Complete" },
+    { 0x23,    "Radio Measurements for Position Request" },
+    { 0x25,    "Radio Measurements for Position Response" },
+    { 0x56,    "Rejection" },
+    { 0x05,    "Registration Request" },
+    { 0x30,    "Reset" },
+    { 0x31,    "Reset Acknowledge" },
+    { 0x34,    "Reset Circuit" },
+    { 0x35,    "Reset Circuit Acknowledge" },
+    { 0x47,    "SSD Update Request" },
+    { 0x4A,    "SSD Update Response" },
+    { 0x6A,    "Status Request" },
+    { 0x6B,    "Status Response" },
+    { 0x39,    "Transcoder Control Acknowledge" },
+    { 0x38,    "Transcoder Control Request" },
+    { 0x42,    "Unblock" },
+    { 0x43,    "Unblock Acknowledge" },
+    { 0x0B,    "User Zone Reject" },
+    { 0x04,    "User Zone Update" },
+    { 0, NULL },
+};
+
+static const value_string ansi_dtap_strings[] = {
+    { 0x62,    "Additional Service Request" },
+    { 0x53,    "ADDS Deliver" },
+    { 0x54,    "ADDS Deliver Ack" },
+    { 0x26,    "Alert With Information" },
+    { 0x45,    "Authentication Request" },
+    { 0x46,    "Authentication Response" },
+    { 0x48,    "Base Station Challenge" },
+    { 0x49,    "Base Station Challenge Response" },
+    { 0x24,    "CM Service Request" },
+    { 0x25,    "CM Service Request Continuation" },
+    { 0x07,    "Connect" },
+    { 0x10,    "Flash with Information" },
+    { 0x50,    "Flash with Information Ack" },
+    { 0x02,    "Location Updating Accept" },
+    { 0x04,    "Location Updating Reject" },
+    { 0x08,    "Location Updating Request" },
+    { 0x27,    "Paging Response" },
+    { 0x2B,    "Parameter Update Confirm" },
+    { 0x2C,    "Parameter Update Request" },
+    { 0x56,    "Rejection" },
+    { 0x03,    "Progress" },
+    { 0x70,    "Service Redirection" },
+    { 0x2E,    "Service Release" },
+    { 0x2F,    "Service Release Complete" },
+    { 0x47,    "SSD Update Request" },
+    { 0x4A,    "SSD Update Response" },
+    { 0x6A,    "Status Request" },
+    { 0x6B,    "Status Response" },
+    { 0x0B,    "User Zone Reject" },
+    { 0x0C,    "User Zone Update" },
+    { 0x0D,    "User Zone Update Request" },
+    { 0, NULL },
+};
+
+static const value_string ansi_elem_1_strings[] = {
+    { 0x20,    "Access Network Identifiers" },
+    { 0x3D,    "ADDS User Part" },
+    { 0x25,    "AMPS Hard Handoff Parameters" },
+    { 0x30,    "Anchor PDSN Address" },
+    { 0x7C,    "Anchor P-P Address" },
+    { 0x41,    "Authentication Challenge Parameter" },
+    { 0x28,    "Authentication Confirmation Parameter (RANDC)" },
+    { 0x59,    "Authentication Data" },
+    { 0x4A,    "Authentication Event" },
+    { 0x40,    "Authentication Parameter COUNT" },
+    { 0x42,    "Authentication Response Parameter" },
+    { 0x37,    "Band Class" },
+    { 0x5B,    "Called Party ASCII Number" },
+    { 0x5E,    "Called Party BCD Number" },
+    { 0x4B,    "Calling Party ASCII Number" },
+    { 0x04,    "Cause" },
+    { 0x08,    "Cause Layer 3" },
+    { 0x0C,    "CDMA Serving One Way Delay" },
+    { 0x05,    "Cell Identifier" },
+    { 0x1A,    "Cell Identifier List" },
+    { 0x23,    "Channel Number" },
+    { 0x0B,    "Channel Type" },
+    { 0x19,    "Circuit Group" },
+    { 0x01,    "Circuit Identity Code" },
+    { 0x24,    "Circuit Identity Code Extension" },
+    { 0x12,    "Classmark Information Type 2" },
+    { 0x29,    "Downlink Radio Environment" },
+    { 0x2B,    "Downlink Radio Environment List" },
+    { 0x0A,    "Encryption Information" },
+    { 0x10,    "Extended Handoff Direction Parameters" },
+    { 0x2C,    "Geographic Location" },
+    { 0x5A,    "Special Service Call Indicator" },
+    { 0x26,    "Handoff Power Level" },
+    { 0x16,    "Hard Handoff Parameters" },
+    { 0x2E,    "Information Element Requested" },
+    { 0x09,    "IS-2000 Channel Identity" },
+    { 0x27,    "IS-2000 Channel Identity 3X" },
+    { 0x11,    "IS-2000 Mobile Capabilities" },
+    { 0x0F,    "IS-2000 Non-Negotiable Service Configuration Record" },
+    { 0x0E,    "IS-2000 Service Configuration Record" },
+    { 0x62,    "IS-95/IS-2000 Cause Value" },
+    { 0x67,    "IS-2000 Redirection Record" },
+    { 0x22,    "IS-95 Channel Identity" },
+    { 0x64,    "IS-95 MS Measured Channel Identity" },
+    { 0x17,    "Layer 3 Information" },
+    { 0x13,    "Location Area Information" },
+    { 0x38,    "Message Waiting Indication" },
+    { 0x0D,    "Mobile Identity" },
+    { 0x15,    "MS Information Records" },
+    { 0xA0,    "Origination Continuation Indicator" },
+    { 0x5F,    "PACA Order" },
+    { 0x60,    "PACA Reorigination Indicator" },
+    { 0x4E,    "PACA Timestamp" },
+    { 0x70,    "Packet Session Parameters" },
+    { 0x14,    "PDSN IP Address" },
+    { 0xA2,    "Power Down Indicator" },
+    { 0x06,    "Priority" },
+    { 0x3B,    "Protocol Revision" },
+    { 0x18,    "Protocol Type" },
+    { 0x2D,    "PSMM Count" },
+    { 0x07,    "Quality of Service Parameters" },
+    { 0x1D,    "Radio Environment and Resources" },
+    { 0x1F,    "Registration Type" },
+    { 0x44,    "Reject Cause" },
+    { 0x1B,    "Response Request" },
+    { 0x68,    "Return Cause" },
+    { 0x21,    "RF Channel Identity" },
+    { 0x03,    "Service Option" },
+    { 0x1E,    "Service Option Connection Identifier (SOCI)" },
+    { 0x2A,    "Service Option List" },
+    { 0x69,    "Service Redirection Info" },
+    { 0x71,    "Session Reference Identifier (SR_ID)" },
+    { 0x32,    "SID" },
+    { 0x34,    "Signal" },
+    { 0x35,    "Slot Cycle Index" },
+    { 0x31,    "Software Version" },
+    { 0x39,    "Source RNC to Target RNC Transparent Container" },
+    { 0x14,    "Source PDSN Address" },
+    { 0x33,    "Tag" },
+    { 0x3A,    "Target RNC to Source RNC Transparent Container" },
+    { 0x36,    "Transcoder Mode" }, /* XXX 0x1C in IOS 4.0.1 */
+    { 0x02,    "User Zone ID" },
+    { 0xA1,    "Voice Privacy Request" },
+    { 0, NULL },
+};
+
+#define        ANSI_MS_INFO_REC_DISPLAY        0x01
+#define        ANSI_MS_INFO_REC_CLD_PN         0x02
+#define        ANSI_MS_INFO_REC_CLG_PN         0x03
+#define        ANSI_MS_INFO_REC_CONN_N         0x04
+#define        ANSI_MS_INFO_REC_SIGNAL         0x05
+#define        ANSI_MS_INFO_REC_MW             0x06
+#define        ANSI_MS_INFO_REC_SC             0x07
+#define        ANSI_MS_INFO_REC_CLD_PSA        0x08
+#define        ANSI_MS_INFO_REC_CLG_PSA        0x09
+#define        ANSI_MS_INFO_REC_CONN_SA        0x0a
+#define        ANSI_MS_INFO_REC_RED_N          0x0b
+#define        ANSI_MS_INFO_REC_RED_SA         0x0c
+#define        ANSI_MS_INFO_REC_MP             0x0d
+#define        ANSI_MS_INFO_REC_PA             0x0e
+#define        ANSI_MS_INFO_REC_LC             0x0f
+#define        ANSI_MS_INFO_REC_EDISPLAY       0x10
+#define        ANSI_MS_INFO_REC_NNSC           0x13
+#define        ANSI_MS_INFO_REC_MC_EDISPLAY    0x14
+#define        ANSI_MS_INFO_REC_CWI            0x15
+#define        ANSI_MS_INFO_REC_ERTI           0xfe
+
+static const value_string ansi_ms_info_rec_str[] = {
+    { ANSI_MS_INFO_REC_DISPLAY,                "Display" },
+    { ANSI_MS_INFO_REC_CLD_PN,         "Called Party Number" },
+    { ANSI_MS_INFO_REC_CLG_PN,         "Calling Party Number" },
+    { ANSI_MS_INFO_REC_CONN_N,         "Connected Number" },
+    { ANSI_MS_INFO_REC_SIGNAL,         "Signal" },
+    { ANSI_MS_INFO_REC_MW,             "Message Waiting" },
+    { ANSI_MS_INFO_REC_SC,             "Service Configuration" },
+    { ANSI_MS_INFO_REC_CLD_PSA,                "Called Party Subaddress" },
+    { ANSI_MS_INFO_REC_CLG_PSA,                "Calling Party Subaddress" },
+    { ANSI_MS_INFO_REC_CONN_SA,                "Connected Subaddress" },
+    { ANSI_MS_INFO_REC_RED_N,          "Redirecting Number" },
+    { ANSI_MS_INFO_REC_RED_SA,         "Redirecting Subaddress" },
+    { ANSI_MS_INFO_REC_MP,             "Meter Pulses" },
+    { ANSI_MS_INFO_REC_PA,             "Parametric Alerting" },
+    { ANSI_MS_INFO_REC_LC,             "Line Control" },
+    { ANSI_MS_INFO_REC_EDISPLAY,       "Extended Display" },
+    { ANSI_MS_INFO_REC_NNSC,           "Non-Negotiable Service Configuration" },
+    { ANSI_MS_INFO_REC_MC_EDISPLAY,    "Multiple Character Extended Display" },
+    { ANSI_MS_INFO_REC_CWI,            "Call Waiting Indicator" },
+    { ANSI_MS_INFO_REC_ERTI,           "Extended Record Type International" },
+    { 0, NULL },
+};
+#define        NUM_MS_INFO_REC (sizeof(ansi_ms_info_rec_str)/sizeof(value_string))
+static gint ett_ansi_ms_info_rec[NUM_MS_INFO_REC];
+
+static gchar *band_class_str[] = {
+    "800 MHz Cellular System",
+    "1.850 to 1.990 GHz Broadband PCS",
+    "872 to 960 MHz TACS Band",
+    "832 to 925 MHz JTACS Band",
+    "1.750 to 1.870 GHz Korean PCS",
+    "450 MHz NMT",
+    "2 GHz IMT-2000 Band",
+    "North American 700 MHz Cellular Band",
+    "1.710 to 1.880 GHz PCS",
+    "880 to 960 MHz Band",
+    "Secondary 800 MHz Band",
+    "400 MHz European PAMR Band",
+    "800 MHz European PAMR Band"
+};
+#define        NUM_BAND_CLASS_STR      (sizeof(band_class_str)/sizeof(gchar *))
+
+static gchar *cell_disc_str[] = {
+    "whole Cell Global Identification (CGI)",
+    "LAC/CI",
+    "Cell Identity (CI)",
+    "None",
+    "Location Area Identification (LAI)",
+    "Location Area Code (LAC)",
+    "ALL",
+    "IS-41 whole Cell Global Identification (ICGI)",
+    "Enhanced whole Cell Global Identification (ECGI)"
+};
+#define        NUM_CELL_DISC_STR       (sizeof(cell_disc_str)/sizeof(gchar *))
+
+/* Initialize the protocol and registered fields */
+static int proto_a_bsmap = -1;
+static int proto_a_dtap = -1;
+
+static int hf_ansi_a_none = -1;
+static int hf_ansi_a_bsmap_msgtype = -1;
+static int hf_ansi_a_dtap_msgtype = -1;
+static int hf_ansi_a_length = -1;
+static int hf_ansi_a_elem_id = -1;
+static int hf_ansi_a_esn = -1;
+static int hf_ansi_a_imsi = -1;
+static int hf_ansi_a_min = -1;
+static int hf_ansi_a_cld_party_bcd_num = -1;
+static int hf_ansi_a_clg_party_bcd_num = -1;
+static int hf_ansi_a_cld_party_ascii_num = -1;
+static int hf_ansi_a_clg_party_ascii_num = -1;
+static int hf_ansi_a_cell_ci = -1;
+static int hf_ansi_a_cell_lac = -1;
+static int hf_ansi_a_cell_mscid = -1;
+static int hf_ansi_a_pdsn_ip_addr = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_bsmap = -1;
+static gint ett_dtap = -1;
+static gint ett_elems = -1;
+static gint ett_elem = -1;
+static gint ett_dtap_oct_1 = -1;
+static gint ett_cm_srvc_type = -1;
+static gint ett_ansi_ms_info_rec_reserved = -1;
+static gint ett_ansi_enc_info = -1;
+
+#define        A_VARIANT_IS634         4
+#define        A_VARIANT_TSB80         5
+#define        A_VARIANT_IS634A        6
+#define        A_VARIANT_IOS2          7
+#define        A_VARIANT_IOS3          8
+#define        A_VARIANT_IOS401        9
+
+/*
+ * IOS 4, probably most common
+ */
+static gint a_global_variant = A_VARIANT_IOS401;
+
+/*
+ * Variables to allow for proper deletion of dissector registration when
+ * the user changes values
+ */
+static gint a_variant = 0;
+
+static char a_bigbuf[1024];
+static gchar a_add_string[1024];
+static dissector_handle_t data_handle;
+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 packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+
+typedef struct dgt_set_t
+{
+    unsigned char out[15];
+}
+dgt_set_t;
+
+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','*','#'
+    }
+};
+
+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','?','?','?','?','?'
+    }
+};
+
+/* 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;
+       i &= 0x0F;
+       *out++ = dgt->out[i];
+       cnt++;
+
+       /*
+        * unpack second value in byte
+        */
+       i = *in++;
+       i >>= 4;
+
+       if (i == 0xff)  /* odd number bytes - hit filler */
+           break;
+
+       *out++ = dgt->out[i];
+       cnt++;
+       num_octs--;
+    }
+
+    *out = '\0';
+
+    return(cnt);
+}
+
+/* Generate, into "buf", a string showing the bits of a bitfield.
+ * Return a pointer to the character after that string.
+ */
+static char *
+my_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
+{
+    int                i;
+    guint32    bit;
+    char       *p;
+
+    i = 0;
+    p = buf;
+    bit = 1 << (width - 1);
+
+    for (;;)
+    {
+       if (mask & bit)
+       {
+           /* This bit is part of the field.  Show its value. */
+           if (val & bit)
+           {
+               *p++ = '1';
+           }
+           else
+           {
+               *p++ = '0';
+           }
+       }
+       else
+       {
+           /* This bit is not part of the field. */
+           *p++ = '.';
+       }
+
+       bit >>= 1;
+       i++;
+
+       if (i >= width) break;
+
+       if (i % 4 == 0) *p++ = ' ';
+    }
+
+    *p = '\0';
+
+    return(p);
+}
+
+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);
+}
+
+/* ELEMENT FUNCTIONS */
+
+#define        EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+    if ((edc_len) > (edc_max_len)) \
+    { \
+       proto_tree_add_text(tree, tvb, \
+           curr_offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+       curr_offset += ((edc_len) - (edc_max_len)); \
+    }
+
+#define        SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+    if ((sdc_len) < (sdc_min_len)) \
+    { \
+       proto_tree_add_text(tree, tvb, \
+           curr_offset, (sdc_len), "Short Data (?)"); \
+       curr_offset += (sdc_len); \
+       return(curr_offset - offset); \
+    }
+
+#define        EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+    if ((edc_len) != (edc_eq_len)) \
+    { \
+       proto_tree_add_text(tree, tvb, \
+           asn1->offset, (edc_len), "Unexpected Data Length"); \
+       asn1->offset += (edc_len); \
+       return; \
+    }
+
+#define        NO_MORE_DATA_CHECK(nmdc_len) \
+    if ((nmdc_len) == (curr_offset - offset)) return(nmdc_len);
+
+
+/*
+ * IOS 6.2.2.6
+ */
+static guint8
+elem_chan_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "Channel Number: %d",
+       value);
+
+    curr_offset += 2;
+
+    sprintf(add_string, " - (%d)", value);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.7
+ */
+static guint8
+elem_chan_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+    gboolean   data;
+
+    curr_offset = offset;
+    data = FALSE;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct)
+    {
+    case 0: str = "No Alert"; break;
+    case 1: str = "Speech"; break;
+    case 2: str = "Data"; data = TRUE; break;
+    case 3: str = "Signaling";
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Speech or Data Indicator: %s",
+       str);
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct)
+    {
+    case 0: str = "Reserved (invalid)"; break;
+    case 1: str = "DCCH"; break;
+    case 2: str = "Reserved for future use (invalid)"; break;
+    case 8: str = "Full rate TCH channel Bm"; break;
+    case 9: str = "Half rate TCH channel Lm"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Channel Rate and Type: %s",
+       str);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (data)
+    {
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Extension",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  %sTransparent service",
+           a_bigbuf,
+           (oct & 0x40) ? "Non-" : "");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+    }
+    else
+    {
+       switch (oct)
+       {
+       case 0: str = "No Resources Required (invalid)"; break;
+       case 1: str = "Reserved"; break;
+       case 2: str = "Reserved"; break;
+       case 3: str = "TIA/EIA-IS-2000 8 kb/s vocoder"; break;
+       case 4: str = "8 kb/s enhanced vocoder (EVRC)"; break;
+       case 5: str = "13 kb/s vocoder"; break;
+       case 6: str = "ADPCM"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "Speech Encoding Algorithm/data rate + Transparency Indicator: %s",
+           str);
+    }
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.8
+ */
+static guint8
+elem_rf_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Color Code");
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  N-AMPS",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ANSI/EIA/TIA-553",
+       a_bigbuf);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Timeslot Number",
+       a_bigbuf);
+
+    curr_offset++;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value >> 8, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, value >> 8, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ARFCN (MSB): %d",
+       a_bigbuf,
+       value & 0x07ff);
+
+    my_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+    proto_tree_add_text(tree, tvb, curr_offset + 1, 1,
+       "%s :  ARFCN (LSB)",
+       a_bigbuf);
+
+    sprintf(add_string, " - (ARFCN: %d)", value & 0x07ff);
+
+    curr_offset += 2;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.9
+ */
+static guint8
+elem_sid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value >> 8, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, value >> 8, 0x7f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  SID (MSB), %d",
+       a_bigbuf,
+       value & 0x7fff);
+
+    my_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+    proto_tree_add_text(tree, tvb, curr_offset + 1, 1,
+       "%s :  SID (LSB)",
+       a_bigbuf);
+
+    sprintf(add_string, " - (SID: %d)", value & 0x7fff);
+
+    curr_offset += 2;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.10
+ */
+static guint8
+elem_is95_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Hard Handoff",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Number of Channels to Add: %d",
+       a_bigbuf,
+       (oct & 0x70) >> 4);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Frame Offset: (%d), %.2f ms",
+       a_bigbuf,
+       oct & 0x0f,
+       (oct & 0x0f) * 1.25);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    SHORT_DATA_CHECK(len - (curr_offset - offset), 4);
+
+    do
+    {
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "Walsh Code Channel Index: %d",
+           oct);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xff, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Pilot PN Code (LSB)",
+           a_bigbuf);
+
+       curr_offset++;
+
+       value = oct;
+       oct = tvb_get_guint8(tvb, curr_offset);
+       value |= ((guint32) (oct & 0x80)) << 1;
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Pilot PN Code (MSB): %d",
+           a_bigbuf,
+           value);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Power Combined",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Frequency Included",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  ARFCN (MSB): %d",
+           a_bigbuf,
+           value);
+
+       curr_offset++;
+
+       my_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  ARFCN (LSB)",
+           a_bigbuf);
+
+       if (add_string[0] == '\0')
+       {
+           sprintf(add_string, " - (ARFCN: %d)", value);
+       }
+
+       curr_offset++;
+    }
+    while ((len - (curr_offset - offset)) >= 4);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.11
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.12
+ */
+static guint8
+elem_enc_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     oct_len;
+    guint32    curr_offset;
+    gchar      *str;
+    guint8     num_recs;
+    proto_tree *subtree;
+    proto_item *item;
+
+    curr_offset = offset;
+
+    num_recs = 0;
+
+    while ((len - (curr_offset - offset)) >= 2)
+    {
+       num_recs++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       switch ((oct & 0x7c) >> 2)
+       {
+       case 0: str = "Not Used - Invalid value"; break;
+       case 1: str = "SME Key: Signaling Message Encryption Key"; break;
+       case 2: str = "Reserved (VPM: Voice Privacy Mask)"; break;
+       case 3: str = "Reserved"; break;
+       case 4: str = "Private Longcode"; break;
+       case 5: str = "Data Key (ORYX)"; break;
+       case 6: str = "Initial RAND"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       item =
+           proto_tree_add_text(tree,
+               tvb, curr_offset, 1,
+               "Encryption Info - %d: (%d) %s",
+               num_recs,
+               (oct & 0x7c) >> 2,
+               str);
+
+       subtree = proto_item_add_subtree(item, ett_ansi_enc_info);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(subtree, tvb, curr_offset, 1,
+           "%s :  Extension",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x7c, 8);
+       proto_tree_add_text(subtree, tvb, curr_offset, 1,
+           "%s :  Encryption Parameter Identifier: (%d) %s",
+           a_bigbuf,
+           (oct & 0x7c) >> 2,
+           str);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+       proto_tree_add_text(subtree, tvb, curr_offset, 1,
+           "%s :  Status: %s",
+           a_bigbuf,
+           (oct & 0x02) ? "active" : "inactive");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+       proto_tree_add_text(subtree, tvb, curr_offset, 1,
+           "%s :  Available: algorithm is %savailable",
+           a_bigbuf,
+           (oct & 0x01) ? "" : "not ");
+
+       curr_offset++;
+
+       oct_len = tvb_get_guint8(tvb, curr_offset);
+
+       proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+           curr_offset, 1, oct_len);
+
+       curr_offset++;
+
+       if (oct_len > 0)
+       {
+           SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+           proto_tree_add_text(subtree, tvb, curr_offset, oct_len,
+               "Encryption Parameter value");
+
+           curr_offset += oct_len;
+       }
+    }
+
+    sprintf(add_string, " - %d record%s",
+       num_recs, plurality(num_recs, "", "s"));
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.13
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.14
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.15
+ */
+static guint8
+elem_cm_info_type_2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     num_bands;
+    guint32    curr_offset;
+    gint       temp_int;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Mobile P_REV: %d",
+       a_bigbuf,
+       (oct & 0xe0) >> 5);
+
+    sprintf(add_string, " - P_REV (%d)", (oct & 0xe0) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  See List of Entries",
+       a_bigbuf);
+
+    switch (oct & 0x07)
+    {
+    case 0: str = "Class 1, vehicle and portable"; break;
+    case 1: str = "Class 2, portable"; break;
+    case 2: str = "Class 3, handheld"; break;
+    case 3: str = "Class 4, handheld"; break;
+    case 4: str = "Class 5, handheld"; break;
+    case 5: str = "Class 6, handheld"; break;
+    case 6: str = "Class 7, handheld"; break;
+    default:
+       str = "Class 8, handheld";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  RF Power Capability: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Reserved");
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  NAR_AN_CAP: N-AMPS %ssupported",
+       a_bigbuf,
+       (oct & 0x80) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  IS-95: %ssupported",
+       a_bigbuf,
+       (oct & 0x40) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Slotted: mobile is %sin slotted mode",
+       a_bigbuf,
+       (oct & 0x20) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  DTX: mobile is %scapable of DTX",
+       a_bigbuf,
+       (oct & 0x04) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Mobile Term: mobile is %scapable of receiving incoming calls",
+       a_bigbuf,
+       (oct & 0x02) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Reserved");
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Mobile Term: mobile is %scapable of receiving incoming calls",
+       a_bigbuf,
+       (oct & 0x02) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  PACA Supported Indicator (PSI): mobile station %s PACA",
+       a_bigbuf,
+       (oct & 0x01) ? "supports" : "does not support");
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "SCM Length: %d",
+       oct);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Station Class Mark: %d",
+       oct);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Count of Band Class Entries: %d",
+       oct);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Band Class Entry Length: %d",
+       oct);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    SHORT_DATA_CHECK(len - (curr_offset - offset), 3);
+
+    num_bands = 0;
+    do
+    {
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       temp_int = oct & 0x1f;
+       if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+       {
+           str = "Reserved";
+       }
+       else
+       {
+           str = band_class_str[temp_int];
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Band Class: %s",
+           a_bigbuf,
+           str);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Band Class %d Air Interfaces Supported: %d",
+           a_bigbuf,
+           num_bands,
+           oct & 0x1f);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "Band Class %d MS Protocol Level: %d",
+           num_bands,
+           oct);
+
+       curr_offset++;
+
+       num_bands++;
+    }
+    while ((len - (curr_offset - offset)) >= 3);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.16
+ */
+static guint8
+elem_mid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     *poctets;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct & 0x07)
+    {
+    case 2:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: Broadcast",
+           a_bigbuf);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       switch ((oct & 0xc0) >> 6)
+       {
+       case 0: str = "Normal"; break;
+       case 1: str = "Interactive"; break;
+       case 2: str = "Urgent"; break;
+       default:
+           str = "Emergency";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Priority: %s",
+           a_bigbuf,
+           str);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Message ID: %d",
+           a_bigbuf,
+           oct & 0x3f);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "Zone ID: %d",
+           oct);
+
+       sprintf(add_string, " - Broadcast (Zone ID: %d)", oct);
+
+       curr_offset++;
+
+       value = tvb_get_ntohs(tvb, curr_offset);
+
+       switch (value)
+       {
+       case 0x0000: str = "Unknown or unspecified"; break;
+       case 0x0001: str = "Emergency Broadcasts"; break;
+       case 0x0002: str = "Administrative"; break;
+       case 0x0003: str = "Maintenance"; break;
+       case 0x0004: str = "General News - Local"; break;
+       case 0x0005: str = "General News - Regional"; break;
+       case 0x0006: str = "General News - National"; break;
+       case 0x0007: str = "General News - International"; break;
+       case 0x0008: str = "Business/Financial News - Local"; break;
+       case 0x0009: str = "Business/Financial News - Regional"; break;
+       case 0x000A: str = "Business/Financial News - National"; break;
+       case 0x000B: str = "Business/Financial News - International"; break;
+       case 0x000C: str = "Sports News - Local"; break;
+       case 0x000D: str = "Sports News - Regional"; break;
+       case 0x000E: str = "Sports News - National"; break;
+       case 0x000F: str = "Sports News - International"; break;
+       case 0x0010: str = "Entertainment News - Local"; break;
+       case 0x0011: str = "Entertainment News - Regional"; break;
+       case 0x0012: str = "Entertainment News - National"; break;
+       case 0x0013: str = "Entertainment News - International"; break;
+       case 0x0014: str = "Local Weather"; break;
+       case 0x0015: str = "Area Traffic Reports"; break;
+       case 0x0016: str = "Local Airport Flight Schedules"; break;
+       case 0x0017: str = "Restaurants"; break;
+       case 0x0018: str = "Lodgings"; break;
+       case 0x0019: str = "Retail Directory"; break;
+       case 0x001A: str = "Advertisements"; break;
+       case 0x001B: str = "Stock Quotes"; break;
+       case 0x001C: str = "Employment Opportunities"; break;
+       case 0x001D: str = "Medical/Health/Hospitals"; break;
+       case 0x001E: str = "Technology News"; break;
+       case 0x001F: str = "Multi-category"; break;
+       default:
+           if ((value >= 0x0020) && (value <= 0x8000)) { str = "Reserved for standard service categories"; }
+           else { str = "Reserved for proprietary service categories"; }
+           break;
+       }
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 2,
+           "Service: (%d) %s",
+           value,
+           str);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       switch (oct)
+       {
+       case 0: str = "Unknown or unspecified"; break;
+       case 1: str = "English"; break;
+       case 2: str = "French"; break;
+       case 3: str = "Spanish"; break;
+       case 4: str = "Japanese"; break;
+       case 5: str = "Korean"; break;
+       case 6: str = "Chinese"; break;
+       case 7: str = "Hebrew"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "Language: (%d) %s",
+           oct,
+           str);
+
+       curr_offset++;
+       break;
+
+    case 0:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Unused",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Odd/Even Indicator: %s",
+           a_bigbuf,
+           (oct & 0x08) ? "ODD" : "EVEN");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: No Identity Code",
+           a_bigbuf);
+
+       strcpy(add_string, " - No Identity Code");
+
+       curr_offset++;
+
+       if (len > 1)
+       {
+           proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+               "Format not supported");
+       }
+
+       curr_offset += len - 1;
+       break;
+
+    case 1:
+       /*
+        * IS-634 value
+        */
+       /* FALLTHRU */
+
+    case 6:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Identity Digit 1: %c",
+           a_bigbuf,
+           Dgt_msid.out[(oct & 0xf0) >> 4]);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Odd/Even Indicator: %s",
+           a_bigbuf,
+           (oct & 0x08) ? "ODD" : "EVEN");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: %s",
+           a_bigbuf,
+           ((oct & 0x07) == 1) ? "MIN" : "IMSI");
+
+       a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
+       curr_offset++;
+
+       poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+       my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
+           &Dgt_msid);
+       g_free(poctets);
+
+       proto_tree_add_string_format(tree,
+           ((oct & 0x07) == 1) ? hf_ansi_a_min : hf_ansi_a_imsi,
+           tvb, curr_offset, len - (curr_offset - offset),
+           a_bigbuf,
+           "BCD Digits: %s",
+           a_bigbuf);
+
+       sprintf(add_string, " - %s (%s)",
+           ((oct & 0x07) == 1) ? "MIN" : "IMSI",
+           a_bigbuf);
+
+       curr_offset += len - (curr_offset - offset);
+       break;
+
+    case 3:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Unused",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Odd/Even Indicator: %s",
+           a_bigbuf,
+           (oct & 0x08) ? "ODD" : "EVEN");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: Interface Directory Number",
+           a_bigbuf);
+
+       strcpy(add_string, " - Interface Directory Number");
+
+       curr_offset++;
+
+       if (len > 1)
+       {
+           proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+               "Format not supported");
+       }
+
+       curr_offset += len - 1;
+       break;
+
+    case 4:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Unused",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Odd/Even Indicator: %s",
+           a_bigbuf,
+           (oct & 0x08) ? "ODD" : "EVEN");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: TMSI",
+           a_bigbuf);
+
+       strcpy(add_string, " - TMSI");
+
+       curr_offset++;
+
+       if (len > 1)
+       {
+           proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+               "Format not supported");
+       }
+
+       curr_offset += len - 1;
+       break;
+
+    case 5:
+       my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Unused",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Odd/Even Indicator: %s",
+           a_bigbuf,
+           (oct & 0x08) ? "ODD" : "EVEN");
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Type of Identity: ESN",
+           a_bigbuf);
+
+       curr_offset++;
+
+       value = tvb_get_ntohl(tvb, curr_offset);
+
+       proto_tree_add_uint(tree, hf_ansi_a_esn,
+           tvb, curr_offset, 4,
+           value);
+
+       sprintf(add_string, " - ESN (0x%04x)", value);
+
+       curr_offset += 4;
+       break;
+
+    default:
+       proto_tree_add_text(tree, tvb, curr_offset, len,
+           "Format Unknown");
+
+       strcpy(add_string, " - Format Unknown");
+
+       curr_offset += len;
+       break;
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.17
+ */
+static guint8
+elem_sci(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Slot Cycle Index: %d",
+       a_bigbuf,
+       oct & 0x07);
+
+    sprintf(add_string, " - (%d)", oct & 0x07);
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.18
+ */
+static guint8
+elem_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3c, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Call Priority Level: %d",
+       a_bigbuf,
+       (oct & 0x3c) >> 2);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Queuing %sallowed",
+       a_bigbuf,
+       (oct & 0x02) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Preemption %sallowed",
+       a_bigbuf,
+       (oct & 0x01) ? "" : "not ");
+
+    sprintf(add_string, " - (%d)", (oct & 0x3c) >> 2);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.19
+ */
+static guint8
+elem_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Extension",
+       a_bigbuf);
+
+    if (oct & 0x80)
+    {
+       /* 2 octet cause */
+
+       if ((oct & 0x0f) == 0x00)
+       {
+           /* national cause */
+           switch ((oct & 0x70) >> 4)
+           {
+           case 0: str = "Normal Event"; break;
+           case 1: str = "Normal Event"; break;
+           case 2: str = "Resource Unavailable"; break;
+           case 3: str = "Service or option not available"; break;
+           case 4: str = "Service or option not implemented"; break;
+           case 5: str = "Invalid message (e.g., parameter out of range)"; break;
+           case 6: str = "Protocol error"; break;
+           default:
+               str = "Interworking";
+               break;
+           }
+
+           my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+           proto_tree_add_text(tree,
+               tvb, curr_offset, 1,
+               "%s :  Cause Class: %s",
+               a_bigbuf,
+               str);
+
+           my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+           proto_tree_add_text(tree,
+               tvb, curr_offset, 1,
+               "%s :  National Cause",
+               a_bigbuf);
+
+           curr_offset++;
+
+           proto_tree_add_text(tree, tvb, curr_offset, 1,
+               "Cause Value");
+
+           curr_offset++;
+
+           strcpy(add_string, " - (National Cause)");
+       }
+       else
+       {
+           value = tvb_get_guint8(tvb, curr_offset + 1);
+
+           my_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+           proto_tree_add_text(tree,
+               tvb, curr_offset, 1,
+               "%s :  Cause (MSB): %d",
+               a_bigbuf,
+               ((oct & 0x7f) << 8) | value);
+
+           curr_offset++;
+
+           my_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
+           proto_tree_add_text(tree, tvb, curr_offset, 1,
+               "%s :  Cause (LSB)",
+               a_bigbuf);
+
+           curr_offset++;
+       }
+    }
+    else
+    {
+       switch (oct)
+       {
+       case 0x00: str = "Radio interface message failure"; break;
+       case 0x01: str = "Radio interface failure"; break;
+       case 0x02: str = "Uplink Quality"; break;
+       case 0x03: str = "Uplink strength"; break;
+       case 0x04: str = "Downlink quality"; break;
+       case 0x05: str = "Downlink strength"; break;
+       case 0x06: str = "Distance"; break;
+       case 0x07: str = "OAM&P intervention"; break;
+       case 0x08: str = "MS busy"; break;
+       case 0x09: str = "Call processing"; break;
+       case 0x0A: str = "Reversion to old channel"; break;
+       case 0x0B: str = "Handoff successful"; break;
+       case 0x0C: str = "No response from MS"; break;
+       case 0x0D: str = "Timer expired"; break;
+       case 0x0E: str = "Better cell (power budget)"; break;
+       case 0x0F: str = "Interference"; break;
+       case 0x10: str = "Packet call going dormant"; break;
+       case 0x11: str = "Service option not available"; break;
+       case 0x12: str = "Invalid Call"; break;
+       case 0x13: str = "Successful operation"; break;
+       case 0x14: str = "Normal call release"; break;
+       case 0x1B: str = "Inter-BS Soft Handoff Drop Target"; break;
+       case 0x1D: str = "Intra-BS Soft Handoff Drop Target"; break;
+       case 0x20: str = "Equipment failure"; break;
+       case 0x21: str = "No radio resource available"; break;
+       case 0x22: str = "Requested terrestrial resource unavailable"; break;
+       case 0x25: str = "BS not equipped"; break;
+       case 0x26: str = "MS not equipped (or incapable)"; break;
+       case 0x29: str = "PACA Call Queued"; break;
+       case 0x2B: str = "Alternate signaling type reject"; break;
+       case 0x2D: str = "PACA Queue Overflow"; break;
+       case 0x2E: str = "PACA Cancel Request Rejected"; break;
+       case 0x30: str = "Requested transcoding/rate adaptation unavailable"; break;
+       case 0x31: str = "Lower priority radio resources not available"; break;
+       case 0x32: str = "PCF resources not available"; break;
+       case 0x33: str = "TFO Control request Failed"; break;
+       case 0x40: str = "Ciphering algorithm not supported"; break;
+       case 0x41: str = "Private Long Code not available or not supported."; break;
+       case 0x42: str = "Requested MUX option or rates not available."; break;
+       case 0x43: str = "Requested Privacy Configuration unavailable"; break;
+       case 0x4F: str = "Terrestrial circuit already allocated.a"; break;
+       case 0x50: str = "Terrestrial circuit already allocated"; break;
+       case 0x5F: str = "Protocol Error between BS and MSC.a"; break;
+       case 0x60: str = "Protocol Error between BS and MSC"; break;
+       case 0x71: str = "ADDS message too long for delivery on the paging channel"; break;
+       case 0x72: str = "MS-to-IWF TCP connection failure"; break;
+       case 0x73: str = "ATH0 (Modem hang up) Command"; break;
+       case 0x74: str = "+FSH/+FHNG (Fax session ended) Command"; break;
+       case 0x75: str = "No carrier"; break;
+       case 0x76: str = "PPP protocol failure"; break;
+       case 0x77: str = "PPP session closed by the MS"; break;
+       case 0x78: str = "Do not notify MS"; break;
+       case 0x79: str = "PDSN resources are not available"; break;
+       case 0x7A: str = "Data ready to send"; break;
+       case 0x7F: str = "Handoff procedure time-out"; break;
+       default:
+           str = "Reserved for future use";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "%s :  Cause: (%d) %s",
+           a_bigbuf,
+           oct & 0x7f,
+           str);
+
+       curr_offset++;
+
+       sprintf(add_string, " - (%d) %s", oct & 0x7f, str);
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.20
+ * Formats everything after the discriminator, shared function.
+ */
+static guint8
+elem_cell_id_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, guint8 disc)
+{
+    guint32    value;
+    guint32    market_id;
+    guint32    switch_num;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    switch (disc)
+    {
+    case 0x02:
+       value = tvb_get_ntohs(tvb, curr_offset);
+
+       proto_tree_add_uint(tree, hf_ansi_a_cell_ci, tvb,
+           curr_offset, 2, value);
+
+       curr_offset += 2;
+
+       sprintf(add_string, " - CI (%d)", value);
+       break;
+
+    case 0x05:
+       value = tvb_get_ntohs(tvb, curr_offset);
+
+       proto_tree_add_uint(tree, hf_ansi_a_cell_lac, tvb,
+           curr_offset, 2, value);
+
+       curr_offset += 2;
+
+       sprintf(add_string, " - LAC (%d)", value);
+       break;
+
+    case 0x07:
+       market_id = tvb_get_ntohs(tvb, curr_offset);
+       switch_num = tvb_get_guint8(tvb, curr_offset + 2);
+
+       value = tvb_get_ntoh24(tvb, curr_offset);
+
+       proto_tree_add_uint_hidden(tree, hf_ansi_a_cell_mscid, tvb,
+           curr_offset, 3, value);
+
+       proto_tree_add_text(tree, tvb, curr_offset, 3,
+           "Market ID %d  Switch Number %d",
+           market_id, switch_num);
+
+       curr_offset += 3;
+
+       value = tvb_get_ntohs(tvb, curr_offset);
+
+       proto_tree_add_uint(tree, hf_ansi_a_cell_ci, tvb,
+           curr_offset, 2, value);
+
+       curr_offset += 2;
+
+       sprintf(add_string, " - Market ID (%d) Switch Number (%d) CI (%d)",
+           market_id,
+           switch_num,
+           value);
+       break;
+
+    default:
+       proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+           "Cell ID - Non IOS format");
+
+       curr_offset += (len - 1);
+       break;
+    }
+
+    return(curr_offset - offset);
+}
+
+static guint8
+elem_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+
+    len = len;
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (oct >= (gint) NUM_CELL_DISC_STR)
+    {
+       str = "Unknown";
+    }
+    else
+    {
+       str = cell_disc_str[oct];
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Cell Identification Discriminator: (%d) %s",
+       oct,
+       str);
+
+    curr_offset++;
+
+    curr_offset +=
+       elem_cell_id_aux(tvb, tree, curr_offset, len - (curr_offset - offset), add_string, oct);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.21
+ */
+static guint8
+elem_cell_id_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     num_cells;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (oct >= (gint) NUM_CELL_DISC_STR)
+    {
+       str = "Unknown";
+    }
+    else
+    {
+       str = cell_disc_str[oct];
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Cell Identification Discriminator: (%d) %s",
+       oct,
+       str);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    num_cells = 0;
+    do
+    {
+       curr_offset +=
+           elem_cell_id_aux(tvb, tree, curr_offset, len - (curr_offset - offset), add_string, oct);
+
+       num_cells++;
+    }
+    while ((len - (curr_offset - offset)) > 0);
+
+    sprintf(add_string, " - %d cell%s",
+       num_cells, plurality(num_cells, "", "s"));
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.22
+ */
+static guint8
+elem_cic(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  PCM Multiplexer: %d",
+       a_bigbuf,
+       (value & 0xffe0) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Timeslot: %d",
+       a_bigbuf,
+       value & 0x001f);
+
+    curr_offset += 2;
+
+    sprintf(add_string, " - (%1$d) (0x%1$04x)", value);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.23
+ */
+static guint8
+elem_cic_ext(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  PCM Multiplexer: %d",
+       a_bigbuf,
+       (value & 0xffe0) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Timeslot: %d",
+       a_bigbuf,
+       value & 0x001f);
+
+    curr_offset += 2;
+
+    sprintf(add_string, " - (%1$d) (0x%1$04x)", value);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x0f)
+    {
+    case 0x00: str = "Full-rate"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Circuit Mode: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.24
+ * UNUSED
+ */
+
+#define        ANSI_A_CELL_ID_LEN(_disc) ((_disc == 7) ? 5 : 2)
+
+/*
+ * IOS 6.2.2.25
+ */
+static guint8
+elem_downlink_re(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     disc;
+    guint8     num_cells;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Number of Cells: %d",
+       oct);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    disc = tvb_get_guint8(tvb, curr_offset);
+
+    if (disc >= (gint) NUM_CELL_DISC_STR)
+    {
+       str = "Unknown";
+    }
+    else
+    {
+       str = cell_disc_str[disc];
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Cell Identification Discriminator: (%d) %s",
+       disc,
+       str);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    SHORT_DATA_CHECK(len - (curr_offset - offset), (guint32) 3 + ANSI_A_CELL_ID_LEN(disc));
+
+    num_cells =0;
+
+    do
+    {
+       curr_offset +=
+           elem_cell_id_aux(tvb, tree, curr_offset,
+               len - (curr_offset - offset), add_string, disc);
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Downlink Signal Strength Raw: %d",
+           a_bigbuf,
+           oct & 0x3f);
+
+       curr_offset++;
+
+       value = tvb_get_ntohs(tvb, curr_offset);
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 2,
+           "CDMA Target One Way Delay: %d",
+           value);
+
+       curr_offset += 2;
+
+       num_cells++;
+    }
+    while ((len - (curr_offset - offset)) >= (guint32) (3 + ANSI_A_CELL_ID_LEN(disc)));
+
+    sprintf(add_string, " - %d cell%s",
+       num_cells, plurality(num_cells, "", "s"));
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.26
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.27
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.28
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.29
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.30
+ */
+static guint8
+elem_pdsn_ip_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    proto_tree_add_item(tree, hf_ansi_a_pdsn_ip_addr, tvb, curr_offset, len, FALSE);
+
+/*
+    proto_tree_add_text(tree, tvb, curr_offset, len,
+       "IPv4 Address");
+*/
+
+    curr_offset += len;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.31
+ */
+static guint8
+elem_ho_pow_lev(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     num_cells;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Number of Cells: %d",
+       oct);
+
+    curr_offset++;
+
+    SHORT_DATA_CHECK(len - (curr_offset - offset), (guint32) 6);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ID Type: %d",
+       a_bigbuf,
+       (oct & 0x60) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Handoff Power Level: %d",
+       a_bigbuf,
+       oct & 0x1f);
+
+    curr_offset++;
+
+    curr_offset +=
+       elem_cell_id_aux(tvb, tree, curr_offset,
+           len - (curr_offset - offset), add_string, 0x7);
+
+    num_cells = 1;
+
+    while ((len - (curr_offset - offset)) >= 3)
+    {
+       num_cells++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Handoff Power Level: %d",
+           a_bigbuf,
+           oct & 0x1f);
+
+       curr_offset++;
+
+       curr_offset +=
+           elem_cell_id_aux(tvb, tree, curr_offset,
+               len - (curr_offset - offset), add_string, 0x2);
+    }
+
+    sprintf(add_string, " - %d cell%s",
+       num_cells, plurality(num_cells, "", "s"));
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.32
+ */
+static guint8
+elem_uz_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 2,
+       "UZID: %d",
+       value);
+
+    curr_offset += 2;
+
+    sprintf(add_string, " - (%d)", value);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.33
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.34
+ */
+static guint8
+elem_is2000_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     num_chan;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  OTD: Mobile will %sbe using OTD",
+       a_bigbuf,
+       (oct & 0x80) ? "" : "not ");
+
+    num_chan = (oct & 0x70) >> 4;
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Channel Count: %d",
+       a_bigbuf,
+       num_chan);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Frame Offset: (%d), %.2f ms",
+       a_bigbuf,
+       oct & 0x0f,
+       (oct & 0x0f) * 1.25);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    SHORT_DATA_CHECK(len - (curr_offset - offset), 6);
+
+    do
+    {
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       switch (oct)
+       {
+       case 0x01: str = "Fundamental Channel (FCH) TIA/EIA/IS-2000"; break;
+       case 0x02: str = "Dedicated Control Channel (DCCH) TIA/EIA/IS-2000"; break;
+       case 0x03: str = "Supplemental Channel (SCH) TIA/EIA/IS-2000"; break;
+       default:
+           if ((oct >= 0x80) && (oct <= 0x9f)) { str = "Reserved for UMTS"; }
+           else { str = "Reserved"; }
+           break;
+       }
+
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "Physical Channel Type: %s",
+           str);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       switch ((oct & 0x60) >> 5)
+       {
+       case 0: str = "Gating rate 1"; break;
+       case 1: str = "Gating rate 1/2"; break;
+       case 2: str = "Gating rate 1/4"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Pilot Gating Rate: %s",
+           a_bigbuf,
+           str);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  QOF Mask",
+           a_bigbuf);
+
+       value = tvb_get_guint8(tvb, curr_offset + 1);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Walsh Code Channel Index (MSB): %d",
+           a_bigbuf,
+           ((guint32) (oct & 0x07) << 8) | value);
+
+       curr_offset++;
+
+       my_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Walsh Code Channel Index (LSB)",
+           a_bigbuf);
+
+       curr_offset++;
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0xff, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Pilot PN Code (LSB)",
+           a_bigbuf);
+
+       curr_offset++;
+
+       value = oct;
+       oct = tvb_get_guint8(tvb, curr_offset);
+       value |= ((guint32) (oct & 0x80)) << 1;
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Pilot PN Code (MSB): %d",
+           a_bigbuf,
+           value);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Frequency Included",
+           a_bigbuf);
+
+       value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  ARFCN (MSB): %d",
+           a_bigbuf,
+           value);
+
+       curr_offset++;
+
+       my_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  ARFCN (LSB)",
+           a_bigbuf);
+
+       curr_offset++;
+    }
+    while ((len - (curr_offset - offset)) >= 6);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.35
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.36
+ */
+static guint8
+elem_is95_ms_meas_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    gint       temp_int;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    temp_int = (oct & 0xf8) >> 3;
+    if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+    {
+       str = "Reserved";
+    }
+    else
+    {
+       str = band_class_str[temp_int];
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Band Class: %s",
+       a_bigbuf,
+       str);
+
+    value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ARFCN (MSB): %d",
+       a_bigbuf,
+       value);
+
+    curr_offset++;
+
+    my_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ARFCN (LSB)",
+       a_bigbuf);
+
+    sprintf(add_string, " - (ARFCN: %d)", value);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.37
+ */
+static guint8
+elem_clg_party_ascii_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    guint8     *poctets;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Extension: %s",
+       a_bigbuf,
+       (oct & 0x80) ? "Not extended" : "Extended");
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "Unknown"; break;
+    case 1: str = "International number"; break;
+    case 2: str = "National number"; break;
+    case 3: str = "Network-specific number"; break;
+    case 4: str = "Dedicated PAD access, short code"; break;
+    case 5: str = "Reserved"; break;
+    case 6: str = "Reserved"; break;
+    default:
+       str = "Reserved for extension";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Type of Number: %s",
+       a_bigbuf,
+       str);
+
+    switch (oct & 0x0f)
+    {
+    case 0x00: str = "Unknown"; break;
+    case 0x01: str = "ISDN/Telephony Numbering (ITU recommendation E.164/E.163)"; break;
+    case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+    case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+    case 0x07: str = "Reserved for extension"; break;
+    case 0x08: str = "National Numbering"; break;
+    case 0x09: str = "Private Numbering"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Number Plan Identification: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    if (!(oct & 0x80))
+    {
+       /* octet 3a */
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Extension",
+           a_bigbuf);
+
+       switch ((oct & 0x60) >> 5)
+       {
+       case 0: str = "Presentation allowed"; break;
+       case 1: str = "Presentation restricted"; break;
+       case 2: str = "Number not available due to interworking"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Presentation Indicator: %s",
+           a_bigbuf,
+           str);
+
+       switch (oct & 0x03)
+       {
+       case 0: str = "User-provided, not screened"; break;
+       case 1: str = "User-provided, verified and passed"; break;
+       case 2: str = "User-provided, verified and failed"; break;
+       default:
+           str = "Network-provided";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Screening Indicator: %s",
+           a_bigbuf,
+           str);
+
+       curr_offset++;
+    }
+
+    poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+    proto_tree_add_string_format(tree, hf_ansi_a_clg_party_ascii_num,
+       tvb, curr_offset, len - (curr_offset - offset),
+       "Digits: %s",
+       poctets);
+
+    curr_offset += len - (curr_offset - offset);
+
+    sprintf(add_string, " - (%s)", poctets);
+    g_free(poctets);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.38
+ */
+static guint8
+elem_l3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    curr_offset;
+    tvbuff_t   *l3_tvb;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    proto_tree_add_text(tree, tvb, curr_offset, len,
+       "Layer 3 Information");
+
+    /*
+     * dissect the embedded DTAP message
+     */
+    l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+    call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
+
+    curr_offset += len;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.39
+ * Protocol Discriminator
+ */
+
+/*
+ * IOS 6.2.2.40
+ * Reserved Octet
+ */
+
+/*
+ * IOS 6.2.2.41
+ * Location Updating Type
+ * UNUSED in SPEC!
+ */
+
+/*
+ * IOS 6.2.2.42
+ * Simple data no decode required
+ */
+
+/*
+ * IOS 6.2.2.43
+ */
+static guint8
+elem_lai(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint16    value;
+    guint32    curr_offset;
+    gchar      mcc[4];
+    gchar      mnc[4];
+
+    len = len;
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    mcc[0] = Dgt_tbcd.out[oct & 0x0f];
+    mcc[1] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+
+    oct = tvb_get_guint8(tvb, curr_offset+1);
+
+    mcc[2] = Dgt_tbcd.out[(oct & 0x0f)];
+    mcc[3] = '\0';
+
+    mnc[2] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+
+    oct = tvb_get_guint8(tvb, curr_offset+2);
+
+    mnc[0] = Dgt_tbcd.out[(oct & 0x0f)];
+    mnc[1] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+    mnc[3] = '\0';
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 3,
+       "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+       mcc,
+       mnc);
+
+    curr_offset += 3;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "Location Area Code (LAC): 0x%04x (%d)",
+       value,
+       value);
+
+    curr_offset += 2;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.44
+ */
+static guint8
+elem_rej_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct)
+    {
+    case 0x01: str = "Reserved"; break;
+    case 0x02: str = "MIN/IMSI unknown in HLR"; break;
+    case 0x03: str = "Illegal MS"; break;
+    case 0x04: str = "TMSI/IMSI/MIN unknown in VLR"; break;
+    case 0x05: str = "Reserved"; break;
+    case 0x0b: str = "Roaming not allowed"; break;
+    case 0x0c: str = "Location area not allowed"; break;
+    case 0x20: str = "Service option not supported"; break;
+    case 0x21: str = "Requested service option not subscribed"; break;
+    case 0x22: str = "Service option temporarily out of order"; break;
+    case 0x26: str = "Call cannot be identified"; break;
+    case 0x51: str = "Network failure"; break;
+    case 0x56: str = "Congestion"; break;
+    case 0x62: str = "Message type non-existent or not implemented"; break;
+    case 0x63: str = "Information element non-existent or not implemented"; break;
+    case 0x64: str = "Invalid information element contents"; break;
+    case 0x65: str = "Message not compatible with the call state"; break;
+    case 0x66: str = "Protocol error, unspecified"; break;
+    case 0x6e: str = "Invalid message, unspecified"; break;
+    case 0x6f: str = "Mandatory information element error"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Reject Cause Value: (%d) %s",
+       oct,
+       str);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%s)", str);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.45
+ */
+static guint8
+elem_auth_chlg_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x0f)
+    {
+    case 1: str = "RAND 32 bits"; break;
+    case 2: str = "RANDU 24 bits"; break;
+    case 4: str = "RANDSSD 56 bits"; break;
+    case 8: str = "RANDBS 32 bits"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Random Number Type: (%d) %s",
+       a_bigbuf,
+       oct & 0x0f,
+       str);
+
+    curr_offset++;
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, len - (curr_offset - offset),
+       "RAND/RANDU/RANDBS/RANDSSD Value");
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset += len - (curr_offset - offset);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.46
+ */
+static guint8
+elem_auth_resp_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x0f)
+    {
+    case 1: str = "AUTHR"; break;
+    case 2: str = "AUTHU"; break;
+    case 4: str = "AUTHBS"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Auth Signature Type: (%d) %s",
+       a_bigbuf,
+       oct & 0x0f,
+       str);
+
+    curr_offset++;
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, len - (curr_offset - offset),
+       "Auth Signature");
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset += len - (curr_offset - offset);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.47
+ */
+static guint8
+elem_auth_param_count(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Count: %d",
+       a_bigbuf,
+       oct & 0x3f);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%d)", oct & 0x3f);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.48
+ */
+static guint8
+elem_mwi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Number of Messages: %d",
+       oct);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%d)", oct);
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.49
+ * Progress
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.50
+ */
+static guint8
+elem_signal(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct)
+    {
+    case 0x00: str = "Dial tone on"; break;
+    case 0x01: str = "Ring back tone on"; break;
+    case 0x02: str = "Intercept tone on"; break;
+    case 0x03: str = "Network congestion (reorder) tone on"; break;
+    case 0x04: str = "Busy tone on"; break;
+    case 0x05: str = "Confirm tone on"; break;
+    case 0x06: str = "Answer tone on"; break;
+    case 0x07: str = "Call waiting tone on"; break;
+    case 0x08: str = "Off-hook warning tone on"; break;
+    case 0x3f: str = "Tones off"; break;
+    case 0x40: str = "Normal Alerting"; break;
+    case 0x41: str = "Inter-group Alerting"; break;
+    case 0x42: str = "Special/Priority Alerting"; break;
+    case 0x43: str = "Reserved (ISDN Alerting pattern 3)"; break;
+    case 0x44: str = "Ping Ring (abbreviated alert)"; break;
+    case 0x45: str = "Reserved (ISDN Alerting pattern 5)"; break;
+    case 0x46: str = "Reserved (ISDN Alerting pattern 6)"; break;
+    case 0x47: str = "Reserved (ISDN Alerting pattern 7)"; break;
+    case 0x63: str = "Abbreviated intercept"; break;
+    case 0x65: str = "Abbreviated reorder"; break;
+    case 0x4f: str = "Alerting off"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Signal Value: (%d) %s",
+       oct,
+       str);
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x03)
+    {
+    case 0: str = "Medium pitch (standard alert)"; break;
+    case 1: str = "High pitch"; break;
+    case 2: str = "Low pitch"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s : Alert Pitch: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.51
+ * CM Service Type
+ */
+
+/*
+ * IOS 6.2.2.52
+ */
+static guint8
+elem_cld_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     *poctets;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Extension",
+       a_bigbuf);
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "Unknown"; break;
+    case 1: str = "International number"; break;
+    case 2: str = "National number"; break;
+    case 3: str = "Network specific number"; break;
+    case 4: str = "Dedicated PAD access, short code"; break;
+    case 7: str = "Reserved for extension"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Type of Number: %s",
+       a_bigbuf,
+       str);
+
+    switch (oct & 0x0f)
+    {
+    case 0x00: str = "Unknown"; break;
+    case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+    case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+    case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+    case 0x07: str = "Reserved for extension"; break;
+    case 0x08: str = "National numbering plan"; break;
+    case 0x09: str = "Private numbering plan"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Numbering Plan Identification: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+    my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+       &Dgt_tbcd);
+    g_free(poctets);
+
+    proto_tree_add_string_format(tree, hf_ansi_a_cld_party_bcd_num,
+       tvb, curr_offset, len - (curr_offset - offset),
+       a_bigbuf,
+       "BCD Digits: %s",
+       a_bigbuf);
+
+    sprintf(add_string, " - (%s)", a_bigbuf);
+
+    curr_offset += len - (curr_offset - offset);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.53
+ * UNUSED in SPEC and no IEI!
+ */
+#ifdef MAYBE_USED_FOR_OLDER_CODECS
+static guint8
+elem_clg_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     *poctets;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Extension: %s",
+       a_bigbuf,
+       (oct & 0x80) ? "Not extended" : "Extended");
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "Unknown"; break;
+    case 1: str = "International number"; break;
+    case 2: str = "National number"; break;
+    case 3: str = "Network specific number"; break;
+    case 4: str = "Dedicated PAD access, short code"; break;
+    case 7: str = "Reserved for extension"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Type of Number: %s",
+       a_bigbuf,
+       str);
+
+    switch (oct & 0x0f)
+    {
+    case 0x00: str = "Unknown"; break;
+    case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+    case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+    case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+    case 0x07: str = "Reserved for extension"; break;
+    case 0x08: str = "National numbering plan"; break;
+    case 0x09: str = "Private numbering plan"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Numbering Plan Identification: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    if (!(oct & 0x80))
+    {
+       /* octet 3a */
+
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Extension",
+           a_bigbuf);
+
+       switch ((oct & 0x60) >> 5)
+       {
+       case 0: str = "Presentation allowed"; break;
+       case 1: str = "Presentation restricted"; break;
+       case 2: str = "Number not available due to interworking"; break;
+       default:
+           str = "Reserved";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Presentation Indicator: %s",
+           a_bigbuf,
+           str);
+
+       switch (oct & 0x03)
+       {
+       case 0: str = "User-provided, not screened"; break;
+       case 1: str = "User-provided, verified and passed"; break;
+       case 2: str = "User-provided, verified and failed"; break;
+       default:
+           str = "Network-provided";
+           break;
+       }
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+
+       my_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+       proto_tree_add_text(tree, tvb, curr_offset, 1,
+           "%s :  Screening Indicator: %s",
+           a_bigbuf,
+           str);
+
+       curr_offset++;
+    }
+
+    poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+    my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+       &Dgt_tbcd);
+    g_free(poctets);
+
+    proto_tree_add_string_format(tree, hf_ansi_a_clg_party_bcd_num,
+       tvb, curr_offset, len - (curr_offset - offset),
+       a_bigbuf,
+       "BCD Digits: %s",
+       a_bigbuf);
+
+    sprintf(add_string, " - (%s)", a_bigbuf);
+
+    curr_offset += len - (curr_offset - offset);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+#endif
+
+/*
+ * IOS 6.2.2.54
+ */
+static guint8
+elem_qos_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Packet Priority: %d",
+       a_bigbuf,
+       oct & 0x0f);
+
+    sprintf(add_string, " - (%d)", oct & 0x0f);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.55
+ */
+static guint8
+elem_cause_l3(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Extension",
+       a_bigbuf);
+
+    switch ((oct & 0x60) >> 5)
+    {
+    case 0: str = "Standard as described in ITU Recommendation Q.931"; break;
+    case 1: str = "Reserved for other international standards"; break;
+    case 2: str = "National standard"; break;
+    default:
+       str = "Reserved for other international standards";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Coding Standard: %s",
+       a_bigbuf,
+       str);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x0f)
+    {
+    case 0: str = "User"; break;
+    case 1: str = "Private network serving the local user"; break;
+    case 2: str = "Public network serving the local user"; break;
+    case 3: str = "Transit network"; break;
+    case 4: str = "Public network serving the remote user"; break;
+    case 5: str = "Private network serving the remote user"; break;
+    case 7: str = "International network"; break;
+    case 10: str = "Network beyond interworking point"; break;
+    default:
+       str = "All other values Reserved"; break;
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Location: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Extension",
+       a_bigbuf);
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "normal event"; break;
+    case 1: str = "normal event"; break;
+    case 2: str = "resource unavailable"; break;
+    case 3: str = "service or option not available"; break;
+    case 4: str = "service or option not implemented"; break;
+    case 5: str = "invalid message (e.g., parameter out of range)"; break;
+    case 6: str = "protocol error (e.g., unknown message)"; break;
+    default:
+       str = "interworking";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Class: (%d) %s",
+       a_bigbuf,
+       (oct & 0x70) >> 4,
+       str);
+
+    switch (oct & 0x7f)
+    {
+    case 0x01: str = "Unassigned (unallocated) number"; break;
+    case 0x03: str = "No route to destination"; break;
+    case 0x06: str = "Channel unacceptable"; break;
+    case 0x0F: str = "Procedure failed"; break;
+    case 0x10: str = "Normal Clearing"; break;
+    case 0x11: str = "User busy"; break;
+    case 0x12: str = "No user responding"; break;
+    case 0x13: str = "User alerting, no answer"; break;
+    case 0x15: str = "Call rejected"; break;
+    case 0x16: str = "Number changed New destination"; break;
+    case 0x1A: str = "Non selected user clearing"; break;
+    case 0x1B: str = "Destination out of order"; break;
+    case 0x1C: str = "Invalid number format (incomplete number)"; break;
+    case 0x1D: str = "Facility rejected"; break;
+    case 0x1F: str = "Normal, unspecified"; break;
+    case 0x22: str = "No circuit/channel available"; break;
+    case 0x26: str = "Network out of order"; break;
+    case 0x29: str = "Temporary failure"; break;
+    case 0x2A: str = "Switching equipment congestion"; break;
+    case 0x2B: str = "Access information discarded information element ids"; break;
+    case 0x2C: str = "requested circuit/channel not available"; break;
+    case 0x2F: str = "Resources unavailable, unspecified"; break;
+    case 0x31: str = "Quality of service unavailable"; break;
+    case 0x32: str = "Requested facility not subscribed"; break;
+    case 0x33: str = "Request MUX option or rates unavailable"; break;
+    case 0x39: str = "Bearer capability not authorized"; break;
+    case 0x3A: str = "Bearer capability not presently available"; break;
+    case 0x3B: str = "SSD Update Rejected"; break;
+    case 0x3F: str = "Service or option not available, unspecified"; break;
+    case 0x41: str = "Bearer service not implemented"; break;
+    case 0x45: str = "Requested facility not implement"; break;
+    case 0x46: str = "Only restricted digital information bearer capability is available"; break;
+    case 0x4F: str = "Service or option not implemented, unspecified"; break;
+    case 0x51: str = "Reserved"; break;
+    case 0x58: str = "Incompatible destination incompatible parameter"; break;
+    case 0x5B: str = "Invalid transit network selection"; break;
+    case 0x5F: str = "Invalid message, unspecified"; break;
+    case 0x60: str = "Mandatory information element error information element identifier(s)"; break;
+    case 0x61: str = "Message type nonexistent or not implemented message type"; break;
+    case 0x62: str = "Message not compatible with control state message type or message type nonexistent or not implemented"; break;
+    case 0x64: str = "Invalid information element contents Information element Identifier(s)"; break;
+    case 0x65: str = "Message not compatible with call state message type"; break;
+    case 0x6F: str = "Protocol error, unspecified"; break;
+    case 0x7F: str = "Interworking, unspecified"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Value: (%d)",
+       a_bigbuf,
+       oct & 0x0f);
+
+    sprintf(add_string, " - (%d) %s", oct & 0x7f, str);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.56
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.57
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.58
+ */
+static guint8
+elem_xmode(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  TFO Mode: %s",
+       a_bigbuf,
+       (oct & 0x01) ? "TFO" : "tandem");
+
+    sprintf(add_string, " - (%s)",
+       (oct & 0x01) ? "TFO" : "tandem");
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.59
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.60
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.61
+ */
+static guint8
+elem_reg_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct)
+    {
+    case 0x00: str = "Timer-based"; break;
+    case 0x01: str = "Power-up"; break;
+    case 0x02: str = "Zone-based"; break;
+    case 0x03: str = "Power-down"; break;
+    case 0x04: str = "Parameter-change"; break;
+    case 0x05: str = "Ordered"; break;
+    case 0x06: str = "Distance-based"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Location Registration Type: %s",
+       str);
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.62
+ */
+static guint8
+elem_tag(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohl(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 4,
+       "Tag Value: %d",
+       value);
+
+    sprintf(add_string, " - (%d)", value);
+
+    curr_offset += 4;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.63
+ */
+static guint8
+elem_hho_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    gint       temp_int;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    temp_int = oct & 0x1f;
+    if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+    {
+       str = "Reserved";
+    }
+    else
+    {
+       str = band_class_str[temp_int];
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Band Class: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%s)", str);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Number of Preamble Frames: %d",
+       a_bigbuf,
+       (oct & 0xe0) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reset L2: %s Layer 2 Acknowledgement",
+       a_bigbuf,
+       (oct & 0x10) ? "Reset" : "Do not reset");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reset FPC: %s counters",
+       a_bigbuf,
+       (oct & 0x10) ? "Reset" : "Do not reset");
+
+    switch ((oct & 0x06) >> 1)
+    {
+    case 0: str = "Encryption disabled"; break;
+    case 1: str = "Encryption enabled"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x06, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Encryption Mode: %s",
+       a_bigbuf,
+       str);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Private LCM: %s Private Long Code Mask",
+       a_bigbuf,
+       (oct & 0x01) ? "Use" : "Do not use");
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Nom_Pwr_Ext",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Nom_Pwr: %d",
+       a_bigbuf,
+       oct & 0x0f);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3e, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  FPC Subchannel Information: %d",
+       a_bigbuf,
+       (oct & 0x3e) >> 1);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  FPC SubChannel Information Included",
+       a_bigbuf);
+
+    curr_offset++;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0e, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Power Control Step: %d",
+       a_bigbuf,
+       (oct & 0x0e) >> 1);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Power Control Step Included",
+       a_bigbuf);
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.64
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.65
+ */
+static guint8
+elem_sw_ver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     major, minor, point;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    major = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "IOS Major Revision Level: %d",
+       major);
+
+    curr_offset++;
+
+    minor = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "IOS Minor Revision Level: %d",
+       minor);
+
+    curr_offset++;
+
+    point = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "IOS Point Revision Level: %d",
+       point);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (IOS %d.%d.%d)", major, minor, point);
+
+    if (len > 3)
+    {
+       proto_tree_add_text(tree, tvb, curr_offset, len - 3,
+           "Manufacturer/Carrier Software Information");
+
+       curr_offset += len - 3;
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+/*
+ * IOS 6.2.2.66
+ */
+static guint8
+elem_so(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint16    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x8000, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Proprietary Indicator",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x7000, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Service Option Revision",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x0fff, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Base Service Option Number",
+       a_bigbuf);
+
+    switch (value)
+    {
+    case 1: str = "Basic Variable Rate Voice Service (8 kbps)"; break;
+    case 2: str = "Mobile Station Loopback (8 kbps)"; break;
+    case 3: str = "Enhanced Variable Rate Voice Service (8 kbps)"; break;
+    case 4: str = "Asynchronous Data Service (9.6 kbps)"; break;
+    case 5: str = "Group 3 Facsimile (9.6 kbps)"; break;
+    case 6: str = "Short Message Services (Rate Set 1)"; break;
+    case 7: str = "Packet Data Service: Internet or ISO Protocol Stack (9.6 kbps)"; break;
+    case 8: str = "Packet Data Service: CDPD Protocol Stack (9.6 kbps)"; break;
+    case 9: str = "Mobile Station Loopback (13 kbps)"; break;
+    case 10: str = "STU-III Transparent Service"; break;
+    case 11: str = "STU-III Non-Transparent Service"; break;
+    case 12: str = "Asynchronous Data Service (14.4 or 9.6 kbps)"; break;
+    case 13: str = "Group 3 Facsimile (14.4 or 9.6 kbps)"; break;
+    case 14: str = "Short Message Services (Rate Set 2)"; break;
+    case 15: str = "Packet Data Service: Internet or ISO Protocol Stack (14.4 kbps)"; break;
+    case 16: str = "Packet Data Service: CDPD Protocol Stack (14.4 kbps)"; break;
+    case 17: str = "High Rate Voice Service (13 kbps)"; break;
+    case 32768: str = "QCELP (13 kbps)"; break;
+    case 32798: /* 0x801e */ str = "Qualcomm Loopback"; break;
+    case 32799: /* 0x801f */ str = "Qualcomm Markov 8 kbps Loopback"; break;
+    case 32800: /* 0x8020 */ str = "Qualcomm Packet Data"; break;
+    case 32801:        /* 0x8021 */ str = "Qualcomm Async Data"; break;
+    case 18: str = "Over-the-Air Parameter Administration (Rate Set 1)"; break;
+    case 19: str = "Over-the-Air Parameter Administration (Rate Set 2)"; break;
+    case 20: str = "Group 3 Analog Facsimile (Rate Set 1)"; break;
+    case 21: str = "Group 3 Analog Facsimile (Rate Set 2)"; break;
+    case 22: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS1 reverse)"; break;
+    case 23: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS2 reverse)"; break;
+    case 24: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS1 reverse)"; break;
+    case 25: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS2 reverse)"; break;
+    case 26: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS1 reverse)"; break;
+    case 27: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS2 reverse)"; break;
+    case 28: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS1 reverse)"; break;
+    case 29: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS2 reverse)"; break;
+    case 30: str = "Supplemental Channel Loopback Test for Rate Set 1"; break;
+    case 31: str = "Supplemental Channel Loopback Test for Rate Set 2"; break;
+    case 32: str = "Test Data Service Option (TDSO)"; break;
+    case 33: str = "cdma2000 High Speed Packet Data Service, Internet or ISO Protocol Stack"; break;
+    case 34: str = "cdma2000 High Speed Packet Data Service, CDPD Protocol Stack"; break;
+    case 35: str = "Location Services, Rate Set 1 (9.6 kbps)"; break;
+    case 36: str = "Location Services, Rate Set 2 (14.4 kbps)"; break;
+    case 37: str = "ISDN Interworking Service (64 kbps)"; break;
+    case 38: str = "GSM Voice"; break;
+    case 39: str = "GSM Circuit Data"; break;
+    case 40: str = "GSM Packet Data"; break;
+    case 41: str = "GSM Short Message Service"; break;
+    case 42: str = "None Reserved for MC-MAP standard service options"; break;
+    case 54: str = "Markov Service Option (MSO)"; break;
+    case 55: str = "Loopback Service Option (LSO)"; break;
+    case 56: str = "Selectable Mode Vocoder"; break;
+    case 57: str = "32 kbps Circuit Video Conferencing"; break;
+    case 58: str = "64 kbps Circuit Video Conferencing"; break;
+    case 59: str = "HRPD Accounting Records Identifier"; break;
+    case 60: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Removal"; break;
+    case 61: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Compression"; break;
+    case 62: str = "- 4099 None Reserved for standard service options"; break;
+    case 4100: str = "Asynchronous Data Service, Revision 1 (9.6 or 14.4 kbps)"; break;
+    case 4101: str = "Group 3 Facsimile, Revision 1 (9.6 or 14.4 kbps)"; break;
+    case 4102: str = "Reserved for standard service option"; break;
+    case 4103: str = "Packet Data Service: Internet or ISO Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+    case 4104: str = "Packet Data Service: CDPD Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+    default:
+       if ((value >= 4105) && (value <= 32767)) { str = "Reserved for standard service options"; }
+       else if ((value >= 32769) && (value <= 32771)) { str = "Proprietary QUALCOMM Incorporated"; }
+       else if ((value >= 32772) && (value <= 32775)) { str = "Proprietary OKI Telecom"; }
+       else if ((value >= 32776) && (value <= 32779)) { str = "Proprietary Lucent Technologies"; }
+       else if ((value >= 32780) && (value <=32783)) { str = "Nokia"; }
+       else if ((value >= 32784) && (value <=32787)) { str = "NORTEL NETWORKS"; }
+       else if ((value >= 32788) && (value <=32791)) { str = "Sony Electronics Inc."; }
+       else if ((value >= 32792) && (value <=32795)) { str = "Motorola"; }
+       else if ((value >= 32796) && (value <=32799)) { str = "QUALCOMM Incorporated"; }
+       else if ((value >= 32800) && (value <=32803)) { str = "QUALCOMM Incorporated"; }
+       else if ((value >= 32804) && (value <=32807)) { str = "QUALCOMM Incorporated"; }
+       else if ((value >= 32808) && (value <=32811)) { str = "QUALCOMM Incorporated"; }
+       else if ((value >= 32812) && (value <=32815)) { str = "Lucent Technologies"; }
+       else if ((value >= 32816) && (value <=32819)) { str = "Denso International"; }
+       else if ((value >= 32820) && (value <=32823)) { str = "Motorola"; }
+       else if ((value >= 32824) && (value <=32827)) { str = "Denso International"; }
+       else if ((value >= 32828) && (value <=32831)) { str = "Denso International"; }
+       else if ((value >= 32832) && (value <=32835)) { str = "Denso International"; }
+       else if ((value >= 32836) && (value <=32839)) { str = "NEC America"; }
+       else if ((value >= 32840) && (value <=32843)) { str = "Samsung Electronics"; }
+       else if ((value >= 32844) && (value <=32847)) { str = "Texas Instruments Incorporated"; }
+       else if ((value >= 32848) && (value <=32851)) { str = "Toshiba Corporation"; }
+       else if ((value >= 32852) && (value <=32855)) { str = "LG Electronics Inc."; }
+       else if ((value >= 32856) && (value <=32859)) { str = "VIA Telecom Inc."; }
+       else { str = "Reserved"; }
+       break;
+    }
+
+    sprintf(add_string, " - (%1$d) (0x%1$04x)", value);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s %s",
+       &add_string[3],
+       str);
+
+    curr_offset += 2;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+#define        ADDS_APP_SMS    0x03
+#define        ADDS_APP_OTA    0x04
+#define        ADDS_APP_PLD    0x05
+
+/*
+ * IOS 6.2.2.67
+ */
+static guint8
+elem_adds_user_part(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     adds_app;
+    guint32    curr_offset;
+    gchar      *str;
+    tvbuff_t   *adds_tvb;
+
+    curr_offset = offset;
+    adds_app = 0;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    adds_app = oct & 0x3f;
+
+    switch (adds_app)
+    {
+    case ADDS_APP_SMS:
+       str = "SMS";
+
+       adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1);
+
+       dissector_try_port(is637_dissector_table,
+           0, adds_tvb, g_pinfo, g_tree);
+       break;
+
+    case ADDS_APP_OTA:
+       str = "OTA";
+
+       adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1);
+
+       dissector_try_port(is683_dissector_table,
+           (g_pinfo->p2p_dir == P2P_DIR_RECV), adds_tvb, g_pinfo, g_tree);
+       break;
+
+    case ADDS_APP_PLD: str = "PLD"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Data Burst Type: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+       "Application Data Message");
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset += (len - 1);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.68
+ */
+static guint8
+elem_is2000_scr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     oct_len;
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct_len = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Bit-Exact Length Octet Count: %d",
+       oct_len);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Bit-Exact Length Fill Bits: %d",
+       a_bigbuf,
+       oct & 0x07);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    if (oct_len > 0)
+    {
+       SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+       proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+           "IS-2000 Service Configuration Record Content");
+
+       curr_offset += oct_len;
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.69
+ */
+static guint8
+elem_is2000_nn_scr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     oct_len;
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct_len = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Bit-Exact Length Octet Count: %d",
+       oct_len);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Bit-Exact Length Fill Bits: %d",
+       a_bigbuf,
+       oct & 0x07);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    if (oct_len > 0)
+    {
+       SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+       proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+           "IS-2000 Non-Negotiable Service Configuration Record Content");
+
+       curr_offset += oct_len;
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.70
+ */
+static guint8
+elem_is2000_mob_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     oct_len;
+    guint32    curr_offset;
+    gchar      *str;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  DCCH Supported: IS-2000 DCCH %ssupported",
+       a_bigbuf,
+       (oct & 0x10) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  FCH Supported: IS-2000 FCH %ssupported",
+       a_bigbuf,
+       (oct & 0x08) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  OTD Supported: Orthogonal Transmit Diversity %ssupported",
+       a_bigbuf,
+       (oct & 0x04) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Enhanced RC CFG Supported: Radio configuration in radio class 2 %ssupported",
+       a_bigbuf,
+       (oct & 0x02) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  QPCH Supported: Quick Paging Channel %ssupported",
+       a_bigbuf,
+       (oct & 0x01) ? "" : "not ");
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct_len = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "FCH Information: Bit-Exact Length Octet Count: %d",
+       oct_len);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "No mobile assisted geo-location capabilities"; break;
+    case 1: str = "IS801 capable (Advanced Forward Link Triangulation only (AFLT))"; break;
+    case 2: str = "IS801 capable (Advanced Forward Link Triangulation and Global Positioning Systems"; break;
+    case 3: str = "Global Positioning Systems Only"; break;
+    default:
+       str = "All Other values reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Geo Location Type: %s",
+       a_bigbuf,
+       str);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Geo Location Included",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  FCH Information: Bit-Exact Length Fill Bits: %d",
+       a_bigbuf,
+       oct & 0x07);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    if (oct_len > 0)
+    {
+       SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+       proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+           "FCH Information Content");
+
+       curr_offset += oct_len;
+
+       NO_MORE_DATA_CHECK(len);
+    }
+
+    oct_len = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "DCCH Information: Bit-Exact Length Octet Count: %d",
+       oct_len);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  DCCH Information: Bit-Exact Length Fill Bits: %d",
+       a_bigbuf,
+       oct & 0x07);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    if (oct_len > 0)
+    {
+       SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+       proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+           "DCCH Information Content");
+
+       curr_offset += oct_len;
+    }
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.71
+ */
+static guint8
+elem_ptype(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    switch (value)
+    {
+    case 0x880b: str = "PPP"; break;
+    case 0x8881: str = "Unstructured Byte Stream"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "(%d) %s",
+       value,
+       str);
+
+    sprintf(add_string, " - (%s)", str);
+
+    curr_offset += 2;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.72
+ */
+static guint8
+elem_ms_info_recs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint8     oct_len;
+    guint8     rec_type;
+    guint8     num_recs;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str;
+    gint       ett_elem_idx, idx, i;
+    proto_tree *subtree;
+    proto_item *item;
+
+    curr_offset = offset;
+
+    num_recs = 0;
+
+    while ((len - (curr_offset - offset)) >= 2)
+    {
+       num_recs++;
+
+       rec_type = tvb_get_guint8(tvb, curr_offset);
+
+       str = my_match_strval((guint32) rec_type, ansi_ms_info_rec_str, &idx);
+
+       if (str == NULL)
+       {
+           str = "Reserved";
+           ett_elem_idx = ett_ansi_ms_info_rec_reserved;
+       }
+       else
+       {
+           ett_elem_idx = ett_ansi_ms_info_rec[idx];
+       }
+
+       item =
+           proto_tree_add_text(tree,
+               tvb, curr_offset, 1,
+               "Information Record Type - %d: (%d) %s",
+               num_recs,
+               rec_type,
+               str);
+
+       subtree = proto_item_add_subtree(item, ett_elem_idx);
+
+       curr_offset++;
+
+       oct_len = tvb_get_guint8(tvb, curr_offset);
+
+       proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+           curr_offset, 1, oct_len);
+
+       curr_offset++;
+
+       if (oct_len > 0)
+       {
+           SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+           switch (rec_type)
+           {
+           case ANSI_MS_INFO_REC_CLD_PN:
+               oct = tvb_get_guint8(tvb, curr_offset);
+
+               switch ((oct & 0xe0) >> 5)
+               {
+               case 0: str = "Unknown"; break;
+               case 1: str = "International number"; break;
+               case 2: str = "National number"; break;
+               case 3: str = "Network-specific number"; break;
+               case 4: str = "Subscriber number"; break;
+               case 5: str = "Reserved"; break;
+               case 6: str = "Abbreviated number"; break;
+               default:
+                   str = "Reserved for extension";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+               proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                   "%s :  Number Type: %s",
+                   a_bigbuf,
+                   str);
+
+               switch ((oct & 0x1e) >> 1)
+               {
+               case 0x00: str = "Unknown"; break;
+               case 0x01: str = "ISDN/Telephony Numbering"; break;
+               case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+               case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+               case 0x09: str = "Private Numbering"; break;
+               case 0x0f: str = "Reserved for extension"; break;
+               default:
+                   str = "Reserved";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, oct, 0x1e, 8);
+               proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                   "%s :  Number Plan: %s",
+                   a_bigbuf,
+                   str);
+
+               if (oct_len > 1)
+               {
+                   my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+                   proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                       "%s :  MSB of first digit",
+                       a_bigbuf);
+
+                   curr_offset++;
+
+                   for (i=0; i < (oct_len - 1); i++)
+                   {
+                       a_bigbuf[i] = (oct & 0x01) << 7;
+
+                       oct = tvb_get_guint8(tvb, curr_offset + i);
+
+                       a_bigbuf[i] |= (oct & 0xfe) >> 1;
+                   }
+                   a_bigbuf[i] = '\0';
+
+                   proto_tree_add_text(subtree, tvb, curr_offset, oct_len - 1,
+                       "Digits: %s",
+                       a_bigbuf);
+
+                   curr_offset += (oct_len - 2);
+               }
+
+               my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+               proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                   "%s :  Reserved",
+                   a_bigbuf);
+
+               curr_offset++;
+               break;
+
+           case ANSI_MS_INFO_REC_CLG_PN:
+               value = tvb_get_ntohs(tvb, curr_offset);
+
+               oct = (value & 0xff00) >> 8;
+
+               switch ((oct & 0xe0) >> 5)
+               {
+               case 0: str = "Unknown"; break;
+               case 1: str = "International number"; break;
+               case 2: str = "National number"; break;
+               case 3: str = "Network-specific number"; break;
+               case 4: str = "Subscriber number"; break;
+               case 5: str = "Reserved"; break;
+               case 6: str = "Abbreviated number"; break;
+               default:
+                   str = "Reserved for extension";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, value, 0xe000, 16);
+               proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                   "%s :  Number Type: %s",
+                   a_bigbuf,
+                   str);
+
+               switch ((oct & 0x1e) >> 1)
+               {
+               case 0x00: str = "Unknown"; break;
+               case 0x01: str = "ISDN/Telephony Numbering"; break;
+               case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+               case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+               case 0x09: str = "Private Numbering"; break;
+               case 0x0f: str = "Reserved for extension"; break;
+               default:
+                   str = "Reserved";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, value, 0x1e00, 16);
+               proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                   "%s :  Number Plan: %s",
+                   a_bigbuf,
+                   str);
+
+               switch ((value & 0x0180) >> 7)
+               {
+               case 0: str = "Presentation allowed"; break;
+               case 1: str = "Presentation restricted"; break;
+               case 2: str = "Number not available"; break;
+               default:
+                   str = "Reserved";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, value, 0x0180, 16);
+               proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                   "%s :  Presentation Indicator (PI): %s",
+                   a_bigbuf,
+                   str);
+
+               switch ((value & 0x0060) >> 5)
+               {
+               case 0: str = "User-provided, not screened"; break;
+               case 1: str = "User-provided, verified and passed"; break;
+               case 2: str = "User-provided, verified and failed"; break;
+               default:
+                   str = "Network-provided";
+                   break;
+               }
+
+               my_decode_bitfield_value(a_bigbuf, value, 0x0060, 16);
+               proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                   "%s :  Screening Indicator (SI): %s",
+                   a_bigbuf,
+                   str);
+
+               if (oct_len > 2)
+               {
+                   oct = (value & 0x00ff);
+
+                   my_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+                   proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                       "%s :  MSB of first digit",
+                       a_bigbuf);
+
+                   curr_offset += 2;
+
+                   for (i=0; i < (oct_len - 2); i++)
+                   {
+                       a_bigbuf[i] = (oct & 0x1f) << 3;
+
+                       oct = tvb_get_guint8(tvb, curr_offset + i);
+
+                       a_bigbuf[i] |= (oct & 0xe0) >> 5;
+                   }
+                   a_bigbuf[i] = '\0';
+
+                   proto_tree_add_text(subtree, tvb, curr_offset, oct_len - 2,
+                       "Digits: %s",
+                       a_bigbuf);
+
+                   curr_offset += (oct_len - 3);
+
+                   my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+                   proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                       "%s :  Reserved",
+                       a_bigbuf);
+
+                   curr_offset++;
+               }
+               else
+               {
+                   my_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+                   proto_tree_add_text(subtree, tvb, curr_offset, 2,
+                       "%s :  Reserved",
+                       a_bigbuf);
+
+                   curr_offset += 2;
+               }
+               break;
+
+           case ANSI_MS_INFO_REC_MW:
+               oct = tvb_get_guint8(tvb, curr_offset);
+
+               proto_tree_add_text(subtree, tvb, curr_offset, 1,
+                   "Number of messages waiting: %d",
+                   oct);
+
+               curr_offset++;
+               break;
+
+           default:
+               proto_tree_add_text(subtree,
+                   tvb, curr_offset, oct_len,
+                   "Record Content");
+
+               curr_offset += oct_len;
+               break;
+           }
+       }
+    }
+
+    sprintf(add_string, " - %d record%s",
+       num_recs, plurality(num_recs, "", "s"));
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.73
+ */
+static guint8
+elem_ext_ho_dir_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Search Window A Size (Srch_Win_A): %d",
+       a_bigbuf,
+       (oct & 0xf0) << 4);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Search Window N Size (Srch_Win_N): %d",
+       a_bigbuf,
+       oct & 0x0f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Search Window R Size (Srch_Win_R): %d",
+       a_bigbuf,
+       (oct & 0xf0) << 4);
+
+    value = tvb_get_guint8(tvb, curr_offset + 1);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Add Pilot Threshold (T_Add) (MSB): %d",
+       a_bigbuf,
+       (oct & 0x0f) << 2 | (value & 0xc0) >> 6);
+
+    curr_offset++;
+
+    oct = value;
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Add Pilot Threshold (T_Add) (LSB)",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Drop Pilot Threshold (T_Drop): %d",
+       a_bigbuf,
+       oct & 0x3f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Compare Threshold (T_Comp): %d",
+       a_bigbuf,
+       (oct & 0xf0) << 4);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Drop Timer Value (T_TDrop): %d",
+       a_bigbuf,
+       oct & 0x0f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Neighbor Max Age (Nghbor_Max_AGE): %d",
+       a_bigbuf,
+       (oct & 0xf0) << 4);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  SOFT_SLOPE: %d",
+       a_bigbuf,
+       oct & 0x3f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  ADD_INTERCEPT: %d",
+       a_bigbuf,
+       oct & 0x3f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  DROP_INTERCEPT: %d",
+       a_bigbuf,
+       oct & 0x3f);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "Target BS P_REV: %d",
+       oct);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.74
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.75
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.76
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.77
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.78
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.79
+ */
+static guint8
+elem_cdma_sowd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+    gchar      *str = NULL;
+
+    curr_offset = offset;
+
+    curr_offset += elem_cell_id(tvb, tree, offset, len, add_string);
+    add_string[0] = '\0';
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "CDMA Serving One Way Delay: %d",
+       value);
+
+    curr_offset += 2;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x03)
+    {
+    case 0: str = "100 nsec"; break;
+    case 1: str = "50 nsec"; break;
+    case 2: str = "1/16 CDMA PN Chip"; break;
+    case 3: str = "Reserved"; break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Resolution: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.80
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.81
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.82
+ */
+static guint8
+elem_re_res(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    len = len;
+    add_string = add_string;
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Include Priority: MSC %s include priority in Assignment Request",
+       a_bigbuf,
+       (oct & 0x40) ? "should" : "does not need to");
+
+    switch ((oct & 0x30) >> 4)
+    {
+    case 0: str = "Not reported"; break;
+    case 1: str = "radio environment is acceptable"; break;
+    case 2: str = "radio environment is marginally acceptable"; break;
+    default:
+       str = "radio environment is poor";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Forward: %s",
+       a_bigbuf,
+       str);
+
+    switch ((oct & 0x0c) >> 2)
+    {
+    case 0: str = "Not reported"; break;
+    case 1: str = "radio environment is acceptable"; break;
+    case 2: str = "radio environment is marginally acceptable"; break;
+    default:
+       str = "radio environment is poor";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reverse: %s",
+       a_bigbuf,
+       str);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Alloc: resources are %sallocated",
+       a_bigbuf,
+       (oct & 0x02) ? "" : "not ");
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Avail: resources are %savailable",
+       a_bigbuf,
+       (oct & 0x01) ? "" : "not ");
+
+    curr_offset++;
+
+    /* no length check possible */
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.83
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.84
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.85
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.86
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.87
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.88
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.89
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.90
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.91
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.92
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.93
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.94
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.95
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.96
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.97
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.98
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.99
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.100
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.101
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.102
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.103
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.104
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.105
+ */
+static guint8
+elem_cld_party_ascii_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    guint8     *poctets;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+    proto_tree_add_text(tree, tvb, curr_offset, 1,
+       "%s :  Extension",
+       a_bigbuf);
+
+    switch ((oct & 0x70) >> 4)
+    {
+    case 0: str = "Unknown"; break;
+    case 1: str = "International number"; break;
+    case 2: str = "National number"; break;
+    case 3: str = "Network specific number"; break;
+    case 4: str = "Dedicated PAD access, short code"; break;
+    case 7: str = "Reserved for extension"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Type of Number: %s",
+       a_bigbuf,
+       str);
+
+    switch (oct & 0x0f)
+    {
+    case 0x00: str = "Unknown"; break;
+    case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+    case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+    case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+    case 0x07: str = "Reserved for extension"; break;
+    case 0x08: str = "National numbering plan"; break;
+    case 0x09: str = "Private numbering plan"; break;
+    default:
+       str = "Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Numbering Plan Identification: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+    proto_tree_add_string_format(tree, hf_ansi_a_cld_party_ascii_num,
+       tvb, curr_offset, len - (curr_offset - offset),
+       "Digits: %s",
+       poctets);
+
+    curr_offset += len - (curr_offset - offset);
+
+    sprintf(add_string, " - (%s)", poctets);
+    g_free(poctets);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.106
+ */
+static guint8
+elem_band_class(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gint       temp_int;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    temp_int = oct & 0x1f;
+    if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+    {
+       str = "Reserved";
+    }
+    else
+    {
+       str = band_class_str[temp_int];
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Band Class: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%s)", str);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.107
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.108
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.109
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.110
+ */
+static guint8
+elem_is2000_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    proto_tree_add_text(tree, tvb, curr_offset, len, "IS-95/IS-2000 Cause Information");
+
+    curr_offset += len;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.111
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.112
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.113
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.114
+ */
+static guint8
+elem_auth_event(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    if (len == 1)
+    {
+       oct = tvb_get_guint8(tvb, curr_offset);
+
+       switch (oct)
+       {
+       case 0x01: str = "Event: Authentication parameters were NOT received from mobile"; break;
+       case 0x02: str = "Event: RANDC mis-match"; break;
+       default:
+           str = "Event";
+           break;
+       }
+
+       proto_tree_add_text(tree, tvb, curr_offset, len,
+           str);
+    }
+    else
+    {
+       proto_tree_add_text(tree, tvb, curr_offset, len, "Event");
+    }
+
+    curr_offset += len;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.115
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.116
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.117
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.118
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.119
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.120
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.121
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.122
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.123
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.124
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.125
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.126
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.127
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.128
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.129
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.130
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.131
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.132
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.133
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.134
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.135
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.136
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.137
+ * Generic decode is good enough
+ */
+
+/*
+ * IOS 6.2.2.138
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.139
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.140
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.141
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.142
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.143
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.144
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.145
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.146
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.147
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.148
+ */
+static guint8
+elem_cct_group(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    value;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  All Circuits",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Inclusive",
+       a_bigbuf);
+
+    curr_offset++;
+
+    NO_MORE_DATA_CHECK(len);
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "Count: %d circuit%s",
+       oct, plurality(oct, "", "s"));
+
+    sprintf(add_string, " - %d circuit%s",
+       oct, plurality(oct, "", "s"));
+
+    curr_offset++;
+
+    value = tvb_get_ntohs(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  PCM Multiplexer: %d",
+       a_bigbuf,
+       (value & 0xffe0) >> 5);
+
+    my_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 2,
+       "%s :  Timeslot: %d",
+       a_bigbuf,
+       value & 0x001f);
+
+    curr_offset += 2;
+
+    NO_MORE_DATA_CHECK(len);
+
+    proto_tree_add_text(tree,
+       tvb, curr_offset, len - (curr_offset - offset),
+       "Circuit Bitmap");
+
+    curr_offset += len - (curr_offset - offset);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.149
+ */
+static guint8
+elem_paca_ts(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint32    curr_offset;
+
+    add_string = add_string;
+    curr_offset = offset;
+
+    proto_tree_add_text(tree, tvb, curr_offset, len, "PACA Queuing Time");
+
+    curr_offset += len;
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.150
+ */
+static guint8
+elem_paca_order(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    gchar      *str;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    switch (oct & 0x07)
+    {
+    case 0: str = "Reserved"; break;
+    case 1: str = "Update Queue Position and notify MS"; break;
+    case 2: str = "Remove MS from the queue and release MS"; break;
+    case 3: str = "Remove MS from the queue"; break;
+    case 4: str = "MS Requested PACA Cancel"; break;
+    case 5: str = "BS Requested PACA Cancel"; break;
+    default:
+       str = "All other values Reserved";
+       break;
+    }
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  PACA Action Required: %s",
+       a_bigbuf,
+       str);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%s)", str);
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.151
+ */
+static guint8
+elem_paca_reoi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+    guint8     oct;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+    proto_tree_add_text(tree,
+       tvb, curr_offset, 1,
+       "%s :  PACA Reorigination Indicator (PRI)",
+       a_bigbuf);
+
+    curr_offset++;
+
+    sprintf(add_string, " - (%sReorigination)", (oct & 0x01) ? "" : "Not ");
+
+    EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+    return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.152
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.153
+ * A3/A7
+ */
+
+typedef enum
+{
+    P_ACC_NET_ID,      /* Access Network Identifiers */
+    P_ADDS_USER_PART,  /* ADDS User Part */
+    P_AMPS_HHO_PARAM,  /* AMPS Hard Handoff Parameters */
+    P_ANCH_PDSN_ADDR,  /* Anchor PDSN Address */
+    P_ANCH_PP_ADDR,    /* Anchor P-P Address */
+    P_AUTH_CHLG_PARAM, /* Authentication Challenge Parameter */
+    P_AUTH_CNF_PARAM,  /* Authentication Confirmation Parameter (RANDC) */
+    P_AUTH_DATA,       /* Authentication Data */
+    P_AUTH_EVENT,      /* Authentication Event */
+    P_AUTH_PARAM_COUNT,        /* Authentication Parameter COUNT */
+    P_AUTH_RESP_PARAM, /* Authentication Response Parameter */
+    P_BAND_CLASS,      /* Band Class */
+    P_CLD_PARTY_ASCII_NUM,     /* Called Party ASCII Number */
+    P_CLD_PARTY_BCD_NUM,       /* Called Party BCD Number */
+    P_CLG_PARTY_ASCII_NUM,     /* Calling Party ASCII Number */
+    P_CAUSE,   /* Cause */
+    P_CAUSE_L3,        /* Cause Layer 3 */
+    P_CDMA_SOWD,       /* CDMA Serving One Way Delay */
+    P_CELL_ID, /* Cell Identifier */
+    P_CELL_ID_LIST,    /* Cell Identifier List */
+    P_CHAN_NUM,        /* Channel Number */
+    P_CHAN_TYPE,       /* Channel Type */
+    P_CCT_GROUP,       /* Circuit Group */
+    P_CIC,     /* Circuit Identity Code */
+    P_CIC_EXT, /* Circuit Identity Code Extension */
+    P_CM_INFO_TYPE_2,  /* Classmark Information Type 2 */
+    P_DOWNLINK_RE,     /* Downlink Radio Environment */
+    P_DOWNLINK_RE_LIST,        /* Downlink Radio Environment List */
+    P_ENC_INFO,        /* Encryption Information */
+    P_EXT_HO_DIR_PARAMS,       /* Extended Handoff Direction Parameters */
+    P_GEO_LOC, /* Geographic Location */
+    P_SSCI,    /* Special Service Call Indicator */
+    P_HO_POW_LEV,      /* Handoff Power Level */
+    P_HHO_PARAMS,      /* Hard Handoff Parameters */
+    P_IE_REQD, /* Information Element Requested */
+    P_IS2000_CHAN_ID,  /* IS-2000 Channel Identity */
+    P_IS2000_CHAN_ID_3X,       /* IS-2000 Channel Identity 3X */
+    P_IS2000_MOB_CAP,  /* IS-2000 Mobile Capabilities */
+    P_IS2000_NN_SCR,   /* IS-2000 Non-Negotiable Service Configuration Record */
+    P_IS2000_SCR,      /* IS-2000 Service Configuration Record */
+    P_IS2000_CAUSE,    /* IS-95/IS-2000 Cause Value */
+    P_IS2000_RED_RECORD,       /* IS-2000 Redirection Record */
+    P_IS95_CHAN_ID,    /* IS-95 Channel Identity */
+    P_IS95_MS_MEAS_CHAN_ID,    /* IS-95 MS Measured Channel Identity */
+    P_L3_INFO, /* Layer 3 Information */
+    P_LAI,     /* Location Area Information */
+    P_MWI,     /* Message Waiting Indication */
+    P_MID,     /* Mobile Identity */
+    P_MS_INFO_RECS,    /* MS Information Records */
+    P_ORIG_CI, /* Origination Continuation Indicator */
+    P_PACA_ORDER,      /* PACA Order */
+    P_PACA_REOI,       /* PACA Reorigination Indicator */
+    P_PACA_TS, /* PACA Timestamp */
+    P_PSP,     /* Packet Session Parameters */
+    P_PDSN_IP_ADDR,    /* PDSN IP Address */
+    P_PDI,     /* Power Down Indicator */
+    P_PRIO,    /* Priority */
+    P_PREV,    /* Protocol Revision */
+    P_PTYPE,   /* Protocol Type */
+    P_PSMM_COUNT,      /* PSMM Count */
+    P_QOS_PARAMS,      /* Quality of Service Parameters */
+    P_RE_RES,  /* Radio Environment and Resources */
+    P_REG_TYPE,        /* Registration Type */
+    P_REJ_CAUSE,       /* Reject Cause */
+    P_RESP_REQ,        /* Response Request */
+    P_RET_CAUSE,       /* Return Cause */
+    P_RF_CHAN_ID,      /* RF Channel Identity */
+    P_SO,      /* Service Option */
+    P_SOCI,    /* Service Option Connection Identifier (SOCI) */
+    P_SO_LIST, /* Service Option List */
+    P_S_RED_INFO,      /* Service Redirection Info */
+    P_SR_ID,   /* Session Reference Identifier (SR_ID) */
+    P_SID,     /* SID */
+    P_SIGNAL,  /* Signal */
+    P_SCI,     /* Slot Cycle Index */
+    P_SW_VER,  /* Software Version */
+    P_SRNC_TRNC_TC,    /* Source RNC to Target RNC Transparent Container */
+    P_S_PDSN_ADDR,     /* Source PDSN Address */
+    P_TAG,     /* Tag */
+    P_TRNC_SRNC_TC,    /* Target RNC to Source RNC Transparent Container */
+    P_XMODE,   /* Transcoder Mode */
+    P_UZ_ID,   /* User Zone ID */
+    P_VP_REQ,  /* Voice Privacy Request */
+    P_NONE,    /* NONE */
+}
+elem_idx_t;
+
+#define        NUM_ELEM_1 (sizeof(ansi_elem_1_strings)/sizeof(value_string))
+static gint ett_ansi_elem_1[NUM_ELEM_1];
+static guint8 (*elem_1_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
+    NULL,      /* Access Network Identifiers */
+    elem_adds_user_part,       /* ADDS User Part */
+    NULL,      /* AMPS Hard Handoff Parameters */
+    NULL,      /* Anchor PDSN Address */
+    NULL,      /* Anchor P-P Address */
+    elem_auth_chlg_param,      /* Authentication Challenge Parameter */
+    NULL /* no decode required */,     /* Authentication Confirmation Parameter (RANDC) */
+    NULL /* no decode required */,     /* Authentication Data */
+    elem_auth_event,   /* Authentication Event */
+    elem_auth_param_count,     /* Authentication Parameter COUNT */
+    elem_auth_resp_param,      /* Authentication Response Parameter */
+    elem_band_class,   /* Band Class */
+    elem_cld_party_ascii_num,  /* Called Party ASCII Number */
+    elem_cld_party_bcd_num,    /* Called Party BCD Number */
+    elem_clg_party_ascii_num,  /* Calling Party ASCII Number */
+    elem_cause,        /* Cause */
+    elem_cause_l3,     /* Cause Layer 3 */
+    elem_cdma_sowd,    /* CDMA Serving One Way Delay */
+    elem_cell_id,      /* Cell Identifier */
+    elem_cell_id_list, /* Cell Identifier List */
+    elem_chan_num,     /* Channel Number */
+    elem_chan_type,    /* Channel Type */
+    elem_cct_group,    /* Circuit Group */
+    elem_cic,  /* Circuit Identity Code */
+    elem_cic_ext,      /* Circuit Identity Code Extension */
+    elem_cm_info_type_2,       /* Classmark Information Type 2 */
+    elem_downlink_re,  /* Downlink Radio Environment */
+    NULL,      /* Downlink Radio Environment List */
+    elem_enc_info,     /* Encryption Information */
+    elem_ext_ho_dir_params,    /* Extended Handoff Direction Parameters */
+    NULL,      /* Geographic Location */
+    NULL,      /* Special Service Call Indicator */
+    elem_ho_pow_lev,   /* Handoff Power Level */
+    elem_hho_params,   /* Hard Handoff Parameters */
+    NULL,      /* Information Element Requested */
+    elem_is2000_chan_id,       /* IS-2000 Channel Identity */
+    NULL,      /* IS-2000 Channel Identity 3X */
+    elem_is2000_mob_cap,       /* IS-2000 Mobile Capabilities */
+    elem_is2000_nn_scr,        /* IS-2000 Non-Negotiable Service Configuration Record */
+    elem_is2000_scr,   /* IS-2000 Service Configuration Record */
+    elem_is2000_cause, /* IS-95/IS-2000 Cause Value */
+    NULL,      /* IS-2000 Redirection Record */
+    elem_is95_chan_id, /* IS-95 Channel Identity */
+    elem_is95_ms_meas_chan_id, /* IS-95 MS Measured Channel Identity */
+    elem_l3_info,      /* Layer 3 Information */
+    elem_lai,  /* Location Area Information */
+    elem_mwi,  /* Message Waiting Indication */
+    elem_mid,  /* Mobile Identity */
+    elem_ms_info_recs, /* MS Information Records */
+    NULL,      /* Origination Continuation Indicator */
+    elem_paca_order,   /* PACA Order */
+    elem_paca_reoi,    /* PACA Reorigination Indicator */
+    elem_paca_ts,      /* PACA Timestamp */
+    NULL,      /* Packet Session Parameters */
+    elem_pdsn_ip_addr, /* PDSN IP Address */
+    NULL /* no associated data */,     /* Power Down Indicator */
+    elem_prio, /* Priority */
+    NULL,      /* Protocol Revision */
+    elem_ptype,        /* Protocol Type */
+    NULL,      /* PSMM Count */
+    elem_qos_params,   /* Quality of Service Parameters */
+    elem_re_res,       /* Radio Environment and Resources */
+    elem_reg_type,     /* Registration Type */
+    elem_rej_cause,    /* Reject Cause */
+    NULL /* no associated data */,     /* Response Request */
+    NULL,      /* Return Cause */
+    elem_rf_chan_id,   /* RF Channel Identity */
+    elem_so,   /* Service Option */
+    NULL,      /* Service Option Connection Identifier (SOCI) */
+    NULL,      /* Service Option List */
+    NULL,      /* Service Redirection Info */
+    NULL,      /* Session Reference Identifier (SR_ID) */
+    elem_sid,  /* SID */
+    elem_signal,       /* Signal */
+    elem_sci,  /* Slot Cycle Index */
+    elem_sw_ver,       /* Software Version */
+    NULL,      /* Source RNC to Target RNC Transparent Container */
+    NULL,      /* Source PDSN Address */
+    elem_tag,  /* Tag */
+    NULL,      /* Target RNC to Source RNC Transparent Container */
+    elem_xmode,        /* Transcoder Mode */
+    elem_uz_id,        /* User Zone ID */
+    NULL /* no associated data */,     /* Voice Privacy Request */
+    NULL,      /* NONE */
+};
+
+/* MESSAGE FUNCTIONS */
+
+/*
+ * Type Length Value (TLV) element dissector
+ */
+static guint8
+elem_tlv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, guint len, gchar *name_add)
+{
+    guint8     oct, parm_len;
+    guint8     consumed;
+    guint32    curr_offset;
+    proto_tree *subtree;
+    proto_item *item;
+
+    len = len;
+    curr_offset = offset;
+    consumed = 0;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (oct == (guint8) ansi_elem_1_strings[idx].value)
+    {
+       parm_len = tvb_get_guint8(tvb, curr_offset + 1);
+
+       item =
+           proto_tree_add_text(tree,
+               tvb, curr_offset, parm_len + 2,
+               "%s%s",
+               ansi_elem_1_strings[idx].strptr,
+               (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+       subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+       proto_tree_add_uint(subtree, hf_ansi_a_elem_id, tvb,
+           curr_offset, 1, oct);
+
+       proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+           curr_offset + 1, 1, parm_len);
+
+       if (parm_len > 0)
+       {
+           if (elem_1_fcn[idx] == NULL)
+           {
+               proto_tree_add_text(subtree,
+                   tvb, curr_offset + 2, parm_len,
+                   "Element Value");
+
+               consumed = parm_len;
+           }
+           else
+           {
+               a_add_string[0] = '\0';
+               consumed =
+                   (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 2,
+                       parm_len, a_add_string);
+
+               if (a_add_string[0] != '\0')
+               {
+                   proto_item_append_text(item, a_add_string);
+                   a_add_string[0] = '\0';
+               }
+           }
+       }
+
+       consumed += 2;
+    }
+
+    return(consumed);
+}
+
+/*
+ * Type Value (TV) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_tv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, gchar *name_add)
+{
+    guint8     oct;
+    guint8     consumed;
+    guint32    curr_offset;
+    proto_tree *subtree;
+    proto_item *item;
+
+    curr_offset = offset;
+    consumed = 0;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (oct == (guint8) ansi_elem_1_strings[idx].value)
+    {
+       item =
+           proto_tree_add_text(tree,
+               tvb, curr_offset, -1,
+               "%s%s",
+               ansi_elem_1_strings[idx].strptr,
+               (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+       subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+       proto_tree_add_uint(subtree, hf_ansi_a_elem_id, tvb, curr_offset, 1, oct);
+
+       if (elem_1_fcn[idx] == NULL)
+       {
+           /* BAD THING, CANNOT DETERMINE LENGTH */
+
+           proto_tree_add_text(subtree,
+               tvb, curr_offset + 1, 1,
+               "No element dissector, rest of dissection may be incorrect");
+
+           consumed = 1;
+       }
+       else
+       {
+           a_add_string[0] = '\0';
+           consumed = (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 1, -1, a_add_string);
+
+           if (a_add_string[0] != '\0')
+           {
+               proto_item_append_text(item, a_add_string);
+               a_add_string[0] = '\0';
+           }
+       }
+
+       consumed++;
+
+       proto_item_set_len(item, consumed);
+    }
+
+    return(consumed);
+}
+
+/*
+ * Type (T) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_t(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, gchar *name_add)
+{
+    guint8     oct;
+    guint32    curr_offset;
+    guint8     consumed;
+
+    curr_offset = offset;
+    consumed = 0;
+
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    if (oct == (guint8) ansi_elem_1_strings[idx].value)
+    {
+       proto_tree_add_uint_format(tree, hf_ansi_a_elem_id, tvb, curr_offset, 1, oct,
+           "%s%s",
+           ansi_elem_1_strings[idx].strptr,
+           (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+       consumed = 1;
+    }
+
+    return(consumed);
+}
+
+/*
+ * Length Value (LV) element dissector
+ */
+static guint8
+elem_lv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, guint len, gchar *name_add)
+{
+    guint8     parm_len;
+    guint8     consumed;
+    guint32    curr_offset;
+    proto_tree *subtree;
+    proto_item *item;
+
+    len = len;
+    curr_offset = offset;
+    consumed = 0;
+
+    parm_len = tvb_get_guint8(tvb, curr_offset);
+
+    item =
+       proto_tree_add_text(tree,
+           tvb, curr_offset, parm_len + 1,
+           "%s%s",
+           ansi_elem_1_strings[idx].strptr,
+           (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+    subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+    proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+       curr_offset, 1, parm_len);
+
+    if (parm_len > 0)
+    {
+       if (elem_1_fcn[idx] == NULL)
+       {
+           proto_tree_add_text(subtree,
+               tvb, curr_offset + 1, parm_len,
+               "Element Value");
+
+           consumed = parm_len;
+       }
+       else
+       {
+           a_add_string[0] = '\0';
+           consumed =
+               (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 1,
+                   parm_len, a_add_string);
+
+           if (a_add_string[0] != '\0')
+           {
+               proto_item_append_text(item, a_add_string);
+               a_add_string[0] = '\0';
+           }
+       }
+    }
+
+    return(consumed + 1);
+}
+
+/*
+ * Value (V) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_v(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+
+    curr_offset = offset;
+    consumed = 0;
+
+    if (elem_1_fcn[idx] == NULL)
+    {
+       /* BAD THING, CANNOT DETERMINE LENGTH */
+
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "No element dissector, rest of dissection may be incorrect");
+
+       consumed = 1;
+    }
+    else
+    {
+       a_add_string[0] = '\0';
+       consumed = (*elem_1_fcn[idx])(tvb, tree, curr_offset, -1, a_add_string);
+       a_add_string[0] = '\0';
+    }
+
+    return(consumed);
+}
+
+
+#define ELEM_MAND_TLV(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_tlv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    else \
+    { \
+       proto_tree_add_text(tree, \
+           tvb, curr_offset, 0, \
+           "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+               ansi_elem_1_strings[elem_idx].value, \
+               ansi_elem_1_strings[elem_idx].strptr, \
+               (elem_name_addition == NULL) || (elem_name_addition[0] == '\0') ? "" : elem_name_addition \
+           ); \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TLV(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_tlv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_TV(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_tv(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    else \
+    { \
+       proto_tree_add_text(tree, \
+           tvb, curr_offset, 0, \
+           "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+               ansi_elem_1_strings[elem_idx].value, \
+               ansi_elem_1_strings[elem_idx].strptr, \
+               (elem_name_addition == NULL) || (elem_name_addition[0] == '\0') ? "" : elem_name_addition \
+           ); \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TV(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_tv(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_T(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_t(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_LV(elem_idx, elem_name_addition) \
+{\
+    if ((consumed = elem_lv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    else \
+    { \
+       /* Mandatory, but nothing we can do */ \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_V(elem_idx) \
+{\
+    if ((consumed = elem_v(tvb, tree, elem_idx, curr_offset)) > 0) \
+    { \
+       curr_offset += consumed; \
+       curr_len -= consumed; \
+    } \
+    else \
+    { \
+       /* Mandatory, but nothing we can do */ \
+    } \
+    if (curr_len <= 0) return; \
+}
+
+
+/*
+ * IOS 6.1.2.1
+ */
+static void
+bsmap_cl3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CELL_ID, "");
+
+    ELEM_MAND_TLV(P_L3_INFO, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.2
+ */
+static void
+dtap_cm_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+    guint8     oct;
+    proto_tree *subtree;
+    proto_item *item;
+    gchar      *str;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    /*
+     * special dissection for CM Service Type
+     */
+    oct = tvb_get_guint8(tvb, curr_offset);
+
+    switch (oct & 0x0f)
+    {
+    case 0x01: str = "Mobile Originating Call"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    item =
+       proto_tree_add_text(tree,
+           tvb, curr_offset, 1,
+           "CM Service Type: %s",
+           str);
+
+    subtree = proto_item_add_subtree(item, ett_cm_srvc_type);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+    proto_tree_add_text(subtree,
+       tvb, curr_offset, 1,
+       "%s :  Element ID",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+    proto_tree_add_text(subtree,
+       tvb, curr_offset, 1,
+       "%s :  Service Type: (%d) %s",
+       a_bigbuf,
+       oct & 0x0f,
+       str);
+
+    curr_offset++;
+    curr_len--;
+
+    ELEM_MAND_LV(P_CM_INFO_TYPE_2, "");
+
+    ELEM_MAND_LV(P_MID, "");
+
+    ELEM_OPT_TLV(P_CLD_PARTY_BCD_NUM, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_CNF_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_PARAM_COUNT, "");
+
+    ELEM_OPT_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_T(P_VP_REQ, "");
+
+    ELEM_OPT_TV(P_RE_RES, "");
+
+    ELEM_OPT_TLV(P_CLD_PARTY_ASCII_NUM, "");
+
+    ELEM_OPT_TV(P_CIC, "");
+
+    ELEM_OPT_TLV(P_AUTH_EVENT, "");
+
+    ELEM_OPT_TLV(P_AUTH_DATA, "");
+
+    ELEM_OPT_TLV(P_PACA_REOI, "");
+
+    ELEM_OPT_TLV(P_UZ_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.3
+ */
+static void
+bsmap_page_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.4
+ */
+static void
+dtap_page_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_CM_INFO_TYPE_2, "");
+
+    ELEM_MAND_LV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_CNF_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_PARAM_COUNT, "");
+
+    ELEM_OPT_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_T(P_VP_REQ, "");
+
+    ELEM_OPT_TV(P_CIC, "");
+
+    ELEM_OPT_TLV(P_AUTH_EVENT, "");
+
+    ELEM_OPT_TV(P_RE_RES, "");
+
+    ELEM_OPT_TLV(P_UZ_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.12
+ */
+static void
+dtap_progress(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TV(P_SIGNAL, "");
+
+    ELEM_OPT_TLV(P_MS_INFO_RECS, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.15
+ */
+static void
+bsmap_ass_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CHAN_TYPE, "");
+
+    ELEM_OPT_TV(P_CIC, "");
+
+    ELEM_OPT_TLV(P_ENC_INFO, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_TV(P_SIGNAL, "");
+
+    ELEM_OPT_TLV(P_CLG_PARTY_ASCII_NUM, "");
+
+    ELEM_OPT_TLV(P_MS_INFO_RECS, "");
+
+    ELEM_OPT_TLV(P_PRIO, "");
+
+    ELEM_OPT_TLV(P_PACA_TS, "");
+
+    ELEM_OPT_TLV(P_QOS_PARAMS, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.16
+ */
+static void
+bsmap_ass_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CHAN_NUM, "");
+
+    ELEM_OPT_TLV(P_ENC_INFO, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.17
+ */
+static void
+bsmap_ass_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.20
+ */
+static void
+bsmap_clr_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CAUSE_L3, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.21
+ */
+static void
+bsmap_clr_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CAUSE_L3, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.22
+ */
+static void
+bsmap_clr_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint8     consumed;
+    guint32    curr_offset;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_T(P_PDI, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.24
+ */
+static void
+dtap_alert_with_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_MS_INFO_RECS, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.28
+ */
+static void
+bsmap_bs_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.29
+ */
+static void
+bsmap_bs_srvc_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.7
+ */
+static void
+dtap_flash_with_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_CLD_PARTY_BCD_NUM, "");
+
+    ELEM_OPT_TV(P_SIGNAL, "");
+
+    ELEM_OPT_TV(P_MWI, "");
+
+    ELEM_OPT_TLV(P_CLG_PARTY_ASCII_NUM, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_MS_INFO_RECS, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.8
+ */
+static void
+dtap_flash_with_info_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.9
+ */
+static void
+bsmap_feat_noti(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TV(P_SIGNAL, "");
+
+    ELEM_OPT_TV(P_MWI, "");
+
+    ELEM_OPT_TLV(P_CLG_PARTY_ASCII_NUM, "");
+
+    ELEM_OPT_TLV(P_MS_INFO_RECS, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.10
+ */
+static void
+bsmap_feat_noti_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.11
+ */
+static void
+bsmap_paca_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_PRIO, "");
+
+    ELEM_OPT_TLV(P_PACA_TS, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.12
+ */
+static void
+bsmap_paca_command_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.13
+ */
+static void
+bsmap_paca_update(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_PACA_ORDER, "");
+
+    ELEM_OPT_TLV(P_PRIO, "");
+
+    ELEM_OPT_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_CNF_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_PARAM_COUNT, "");
+
+    ELEM_OPT_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TLV(P_AUTH_EVENT, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.14
+ */
+static void
+bsmap_paca_update_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_PRIO, "");
+
+    ELEM_OPT_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.1
+ */
+static void
+bsmap_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.2
+ */
+static void
+bsmap_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_AUTH_RESP_PARAM, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.3
+ */
+static void
+bsmap_user_zone_update(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_UZ_ID, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.4
+ */
+static void
+dtap_ssd_update_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_AUTH_CHLG_PARAM, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.5
+ */
+static void
+dtap_bs_challenge(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_AUTH_CHLG_PARAM, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.6
+ */
+static void
+dtap_bs_challenge_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_AUTH_RESP_PARAM, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.7
+ */
+static void
+dtap_ssd_update_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_CAUSE_L3, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.8
+ */
+static void
+dtap_lu_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_MID, "");
+
+    ELEM_OPT_TV(P_LAI, "");
+
+    ELEM_OPT_TLV(P_CM_INFO_TYPE_2, "");
+
+    ELEM_OPT_TV(P_REG_TYPE, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_CNF_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_PARAM_COUNT, "");
+
+    ELEM_OPT_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TLV(P_AUTH_EVENT, "");
+
+    ELEM_OPT_TLV(P_UZ_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.9
+ */
+static void
+dtap_lu_accept(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TV(P_LAI, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.10
+ */
+static void
+dtap_lu_reject(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_V(P_REJ_CAUSE);
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.18
+ */
+static void
+bsmap_priv_mode_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_ENC_INFO, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.19
+ */
+static void
+bsmap_priv_mode_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_ENC_INFO, "");
+
+    ELEM_OPT_T(P_VP_REQ, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.4
+ */
+static void
+bsmap_ho_reqd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_MAND_TLV(P_CELL_ID_LIST, " (Target)");        /* XXX target list */
+
+    ELEM_OPT_TLV(P_CM_INFO_TYPE_2, "");
+
+    ELEM_OPT_T(P_RESP_REQ, "");
+
+    ELEM_OPT_TLV(P_ENC_INFO, "");
+
+    ELEM_OPT_TLV(P_IS95_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_DOWNLINK_RE, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    ELEM_OPT_TLV(P_IS95_MS_MEAS_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_QOS_PARAMS, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    ELEM_OPT_TLV(P_IS2000_SCR, "");
+
+    ELEM_OPT_TLV(P_PDSN_IP_ADDR, "");
+
+    ELEM_OPT_TLV(P_PTYPE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.5
+ */
+static void
+bsmap_ho_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CHAN_TYPE, "");
+
+    ELEM_MAND_TLV(P_ENC_INFO, "");
+
+    ELEM_MAND_TLV(P_CM_INFO_TYPE_2, "");
+
+    ELEM_MAND_TLV(P_CELL_ID_LIST, "(Target)"); /* XXX target list */
+
+    ELEM_OPT_TLV(P_CIC_EXT, "");
+
+    ELEM_OPT_TLV(P_IS95_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_DOWNLINK_RE, "");
+
+    ELEM_OPT_TV(P_SO, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    ELEM_OPT_TLV(P_IS95_MS_MEAS_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_QOS_PARAMS, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    ELEM_OPT_TLV(P_IS2000_SCR, "");
+
+    ELEM_OPT_TLV(P_PDSN_IP_ADDR, "");
+
+    ELEM_OPT_TLV(P_PTYPE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.6
+ */
+static void
+bsmap_ho_req_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_IS95_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TLV(P_EXT_HO_DIR_PARAMS, "");
+
+    ELEM_OPT_TV(P_HHO_PARAMS, "");
+
+    ELEM_OPT_TLV(P_IS2000_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_SCR, "");
+
+    ELEM_OPT_TLV(P_IS2000_NN_SCR, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.7
+ */
+static void
+bsmap_ho_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.8
+ */
+static void
+bsmap_ho_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TV(P_RF_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_IS95_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TLV(P_HO_POW_LEV, "");
+
+    ELEM_OPT_TV(P_SID, "");
+
+    ELEM_OPT_TLV(P_EXT_HO_DIR_PARAMS, "");
+
+    ELEM_OPT_TV(P_HHO_PARAMS, "");
+
+    ELEM_OPT_TLV(P_IS2000_CHAN_ID, "");
+
+    ELEM_OPT_TLV(P_IS2000_SCR, "");
+
+    ELEM_OPT_TLV(P_IS2000_NN_SCR, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.9
+ */
+static void
+bsmap_ho_reqd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.12
+ */
+static void
+bsmap_ho_performed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.2
+ */
+static void
+bsmap_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CCT_GROUP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.3
+ */
+static void
+bsmap_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.4
+ */
+static void
+bsmap_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    ELEM_OPT_TLV(P_CCT_GROUP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.5
+ */
+static void
+bsmap_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.6
+ */
+static void
+bsmap_reset(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_SW_VER, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.7
+ */
+static void
+bsmap_reset_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_SW_VER, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.8
+ */
+static void
+bsmap_reset_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CCT_GROUP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.9
+ */
+static void
+bsmap_reset_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TV(P_CIC, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.10
+ */
+static void
+bsmap_xmode_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_XMODE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.11
+ */
+static void
+bsmap_xmode_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.1
+ */
+static void
+bsmap_adds_page(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_MAND_TLV(P_ADDS_USER_PART, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CELL_ID_LIST, "");
+
+    ELEM_OPT_TV(P_SCI, "");
+
+    ELEM_OPT_TLV(P_IS2000_MOB_CAP, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.2
+ */
+static void
+bsmap_adds_transfer(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_MAND_TLV(P_ADDS_USER_PART, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_AUTH_RESP_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_CNF_PARAM, "");
+
+    ELEM_OPT_TV(P_AUTH_PARAM_COUNT, "");
+
+    ELEM_OPT_TLV(P_AUTH_CHLG_PARAM, "");
+
+    ELEM_OPT_TLV(P_AUTH_EVENT, "");
+
+    ELEM_OPT_TLV(P_CELL_ID, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.3
+ */
+static void
+dtap_adds_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_LV(P_ADDS_USER_PART, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CDMA_SOWD, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.4
+ */
+static void
+bsmap_adds_page_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_MAND_TLV(P_MID, "");
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_CAUSE, "");
+
+    ELEM_OPT_TLV(P_CELL_ID, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.5
+ */
+static void
+dtap_adds_deliver_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TV(P_TAG, "");
+
+    ELEM_OPT_TLV(P_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.8.1
+ */
+static void
+bsmap_rejection(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_MID, "");
+
+    ELEM_OPT_TLV(P_IS2000_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_rejection(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+    guint32    curr_offset;
+    guint32    consumed;
+    guint      curr_len;
+
+    curr_offset = offset;
+    curr_len = len;
+
+    ELEM_OPT_TLV(P_IS2000_CAUSE, "");
+
+    EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+#define        NUM_IOS401_BSMAP_MSG (sizeof(ansi_bsmap_strings)/sizeof(value_string))
+static gint ett_bsmap_msg[NUM_IOS401_BSMAP_MSG];
+static void (*bsmap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+    NULL,      /* Additional Service Notification */
+    bsmap_adds_page,   /* ADDS Page */
+    bsmap_adds_page_ack,       /* ADDS Page Ack */
+    bsmap_adds_transfer,       /* ADDS Transfer */
+    NULL,      /* ADDS Transfer Ack */
+    bsmap_ass_complete,        /* Assignment Complete */
+    bsmap_ass_failure, /* Assignment Failure */
+    bsmap_ass_req,     /* Assignment Request */
+    bsmap_auth_req,    /* Authentication Request */
+    bsmap_auth_resp,   /* Authentication Response */
+    NULL,      /* Base Station Challenge */
+    NULL,      /* Base Station Challenge Response */
+    bsmap_block,       /* Block */
+    bsmap_block_ack,   /* Block Acknowledge */
+    bsmap_bs_srvc_req, /* BS Service Request */
+    bsmap_bs_srvc_resp,        /* BS Service Response */
+    bsmap_clr_command, /* Clear Command */
+    bsmap_clr_complete,        /* Clear Complete */
+    bsmap_clr_req,     /* Clear Request */
+    bsmap_cl3_info,    /* Complete Layer 3 Information */
+    bsmap_feat_noti,   /* Feature Notification */
+    bsmap_feat_noti_ack,       /* Feature Notification Ack */
+    bsmap_ho_command,  /* Handoff Command */
+    NULL /* no associated data */,     /* Handoff Commenced */
+    NULL /* no associated data */,     /* Handoff Complete */
+    bsmap_ho_failure,  /* Handoff Failure */
+    bsmap_ho_performed,        /* Handoff Performed */
+    bsmap_ho_req,      /* Handoff Request */
+    bsmap_ho_req_ack,  /* Handoff Request Acknowledge */
+    bsmap_ho_reqd,     /* Handoff Required */
+    bsmap_ho_reqd_rej, /* Handoff Required Reject */
+    bsmap_paca_command,        /* PACA Command */
+    bsmap_paca_command_ack,    /* PACA Command Ack */
+    bsmap_paca_update, /* PACA Update */
+    bsmap_paca_update_ack,     /* PACA Update Ack */
+    bsmap_page_req,    /* Paging Request */
+    bsmap_priv_mode_command,   /* Privacy Mode Command */
+    bsmap_priv_mode_complete,  /* Privacy Mode Complete */
+    NULL,      /* Radio Measurements for Position Request */
+    NULL,      /* Radio Measurements for Position Response */
+    bsmap_rejection,   /* Rejection */
+    NULL,      /* Registration Request */
+    bsmap_reset,       /* Reset */
+    bsmap_reset_ack,   /* Reset Acknowledge */
+    bsmap_reset_cct,   /* Reset Circuit */
+    bsmap_reset_cct_ack,       /* Reset Circuit Acknowledge */
+    NULL,      /* SSD Update Request */
+    NULL,      /* SSD Update Response */
+    NULL,      /* Status Request */
+    NULL,      /* Status Response */
+    bsmap_xmode_ack,   /* Transcoder Control Acknowledge */
+    bsmap_xmode_req,   /* Transcoder Control Request */
+    bsmap_unblock,     /* Unblock */
+    bsmap_unblock_ack, /* Unblock Acknowledge */
+    NULL,      /* User Zone Reject */
+    bsmap_user_zone_update,    /* User Zone Update */
+    NULL,      /* NONE */
+};
+
+#define        NUM_IOS401_DTAP_MSG (sizeof(ansi_dtap_strings)/sizeof(value_string))
+static gint ett_dtap_msg[NUM_IOS401_DTAP_MSG];
+static void (*dtap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+    NULL,      /* Additional Service Request */
+    dtap_adds_deliver, /* ADDS Deliver */
+    dtap_adds_deliver_ack,     /* ADDS Deliver Ack */
+    dtap_alert_with_info,      /* Alert With Information */
+    dtap_auth_req,     /* Authentication Request */
+    dtap_auth_resp,    /* Authentication Response */
+    dtap_bs_challenge, /* Base Station Challenge */
+    dtap_bs_challenge_resp,    /* Base Station Challenge Response */
+    dtap_cm_srvc_req,  /* CM Service Request */
+    NULL,      /* CM Service Request Continuation */
+    NULL /* no associated data */,     /* Connect */
+    dtap_flash_with_info,      /* Flash with Information */
+    dtap_flash_with_info_ack,  /* Flash with Information Ack */
+    dtap_lu_accept,    /* Location Updating Accept */
+    dtap_lu_reject,    /* Location Updating Reject */
+    dtap_lu_req,       /* Location Updating Request */
+    dtap_page_resp,    /* Paging Response */
+    NULL /* no associated data */,     /* Parameter Update Confirm */
+    NULL /* no associated data */,     /* Parameter Update Request */
+    dtap_rejection,    /* Rejection */
+    dtap_progress,     /* Progress */
+    NULL,      /* Service Redirection */
+    NULL,      /* Service Release */
+    NULL,      /* Service Release Complete */
+    dtap_ssd_update_req,       /* SSD Update Request */
+    dtap_ssd_update_resp,      /* SSD Update Response */
+    NULL,      /* Status Request */
+    NULL,      /* Status Response */
+    NULL,      /* User Zone Reject */
+    NULL,      /* User Zone Update */
+    NULL,      /* User Zone Update Request */
+    NULL,      /* NONE */
+};
+
+/* GENERIC MAP DISSECTOR FUNCTIONS */
+
+static void
+dissect_bsmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    guint8     oct;
+    guint32    offset, saved_offset;
+    guint32    len;
+    gint       idx;
+    proto_item *bsmap_item = NULL;
+    proto_tree *bsmap_tree = NULL;
+    gchar      *str;
+
+
+    if (!proto_is_protocol_enabled(proto_a_bsmap))
+    {
+       call_dissector(data_handle, tvb, pinfo, tree);
+       return;
+    }
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+    {
+       col_append_str(pinfo->cinfo, COL_INFO, "(BSMAP) ");
+    }
+
+    /*
+     * In the interest of speed, if "tree" is NULL, don't do any work
+     * not necessary to generate protocol tree items.
+     */
+    if (!tree)
+    {
+       return;
+    }
+
+    offset = 0;
+    saved_offset = offset;
+
+    g_pinfo = pinfo;
+    g_tree = tree;
+
+    len = tvb_length(tvb);
+
+    /*
+     * add BSMAP message name
+     */
+    oct = tvb_get_guint8(tvb, offset++);
+
+    str = my_match_strval((guint32) oct, ansi_bsmap_strings, &idx);
+
+    /*
+     * create the a protocol tree
+     */
+    if (str == NULL)
+    {
+       bsmap_item =
+           proto_tree_add_protocol_format(tree, proto_a_bsmap, tvb, 0, len,
+               "ANSI A-I/F BSMAP - Unknown BSMAP Message Type (%d)",
+               oct);
+
+       bsmap_tree = proto_item_add_subtree(bsmap_item, ett_bsmap);
+    }
+    else
+    {
+       bsmap_item =
+           proto_tree_add_protocol_format(tree, proto_a_bsmap, tvb, 0, -1,
+               "ANSI A-I/F BSMAP - %s",
+               str);
+
+       bsmap_tree = proto_item_add_subtree(bsmap_item, ett_bsmap_msg[idx]);
+
+       if (check_col(pinfo->cinfo, COL_INFO))
+       {
+           col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+       }
+    }
+
+    /*
+     * add BSMAP message name
+     */
+    proto_tree_add_uint_format(bsmap_tree, hf_ansi_a_bsmap_msgtype,
+       tvb, saved_offset, 1, oct, "Message Type");
+
+    if (str == NULL) return;
+
+    if ((len - offset) <= 0) return;
+
+    /*
+     * decode elements
+     */
+    if (bsmap_msg_fcn[idx] == NULL)
+    {
+       proto_tree_add_text(bsmap_tree,
+           tvb, offset, len - offset,
+           "Message Elements");
+    }
+    else
+    {
+       (*bsmap_msg_fcn[idx])(tvb, bsmap_tree, offset, len - offset);
+    }
+}
+
+static void
+dissect_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    guint8     oct;
+    guint32    offset, saved_offset;
+    guint32    len;
+    guint32    oct_1, oct_2;
+    gint       idx;
+    proto_item *dtap_item = NULL;
+    proto_tree *dtap_tree = NULL;
+    proto_item *oct_1_item = NULL;
+    proto_tree *oct_1_tree = NULL;
+    gchar      *str;
+
+
+    if (!proto_is_protocol_enabled(proto_a_dtap))
+    {
+       call_dissector(data_handle, tvb, pinfo, tree);
+       return;
+    }
+
+    len = tvb_length(tvb);
+
+    if (len < 3)
+    {
+       /*
+        * too short to be DTAP
+        */
+       call_dissector(data_handle, tvb, pinfo, tree);
+       return;
+    }
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+    {
+       col_append_str(pinfo->cinfo, COL_INFO, "(DTAP) ");
+    }
+
+    /*
+     * In the interest of speed, if "tree" is NULL, don't do any work
+     * not necessary to generate protocol tree items.
+     */
+    if (!tree)
+    {
+       return;
+    }
+
+    offset = 0;
+    saved_offset = offset;
+
+    g_pinfo = pinfo;
+    g_tree = tree;
+
+    /*
+     * get protocol discriminator
+     */
+    oct_1 = tvb_get_guint8(tvb, offset++);
+    oct_2 = tvb_get_guint8(tvb, offset++);
+
+    /*
+     * add DTAP message name
+     */
+    saved_offset = offset;
+    oct = tvb_get_guint8(tvb, offset++);
+
+    str = my_match_strval((guint32) oct, ansi_dtap_strings, &idx);
+
+    /*
+     * create the a protocol tree
+     */
+    if (str == NULL)
+    {
+       dtap_item =
+           proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, len,
+               "ANSI A-I/F DTAP - Unknown DTAP Message Type (%d)",
+               oct);
+
+       dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap);
+    }
+    else
+    {
+       dtap_item =
+           proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, -1,
+               "ANSI A-I/F DTAP - %s",
+               str);
+
+       dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap_msg[idx]);
+
+       if (check_col(pinfo->cinfo, COL_INFO))
+       {
+           col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+       }
+    }
+
+    /*
+     * octet 1
+     */
+    switch (oct_1 & 0x0f)
+    {
+    case 3: str = "Call Control, call related SS"; break;
+    case 5: str = "Mobility Management"; break;
+    case 6: str = "Radio Resource Management"; break;
+    case 9: str = "Facility Management"; break;
+    case 11: str = "Other Signaling Procedures"; break;
+    case 15: str = "Reserved for tests"; break;
+    default:
+       str = "Unknown";
+       break;
+    }
+
+    oct_1_item =
+       proto_tree_add_text(dtap_tree,
+           tvb, 0, 1,
+           "Protocol Discriminator: %s",
+           str);
+
+    oct_1_tree = proto_item_add_subtree(oct_1_item, ett_dtap_oct_1);
+
+    my_decode_bitfield_value(a_bigbuf, oct_1, 0xf0, 8);
+    proto_tree_add_text(oct_1_tree,
+       tvb, 0, 1,
+       "%s :  Reserved",
+       a_bigbuf);
+
+    my_decode_bitfield_value(a_bigbuf, oct_1, 0x0f, 8);
+    proto_tree_add_text(oct_1_tree,
+       tvb, 0, 1,
+       "%s :  Protocol Discriminator: %d",
+       a_bigbuf,
+       oct_1 & 0x0f);
+
+    /*
+     * octet 2
+     */
+    switch (a_variant)
+    {
+    case A_VARIANT_IS634:
+       my_decode_bitfield_value(a_bigbuf, oct_2, 0x80, 8);
+       proto_tree_add_text(dtap_tree,
+           tvb, 1, 1,
+           "%s :  Transaction Identifier (TI) Flag: %s",
+           a_bigbuf,
+           ((oct_2 & 0x80) ?  "allocated by receiver" : "allocated by sender"));
+
+       my_decode_bitfield_value(a_bigbuf, oct_2, 0x70, 8);
+       proto_tree_add_text(dtap_tree,
+           tvb, 1, 1,
+           "%s :  Transaction Identifier (TI): %d",
+           a_bigbuf,
+           (oct_2 & 0x70) >> 4);
+
+       my_decode_bitfield_value(a_bigbuf, oct_2, 0x0f, 8);
+       proto_tree_add_text(dtap_tree,
+           tvb, 1, 1,
+           "%s :  Reserved",
+           a_bigbuf);
+       break;
+
+    default:
+       proto_tree_add_text(dtap_tree,
+           tvb, 1, 1,
+           "Reserved Octet");
+       break;
+    }
+
+    /*
+     * add DTAP message name
+     */
+    proto_tree_add_uint_format(dtap_tree, hf_ansi_a_dtap_msgtype,
+       tvb, saved_offset, 1, oct,
+       "Message Type");
+
+    if (str == NULL) return;
+
+    if ((len - offset) <= 0) return;
+
+    /*
+     * decode elements
+     */
+    if (dtap_msg_fcn[idx] == NULL)
+    {
+       proto_tree_add_text(dtap_tree,
+           tvb, offset, len - offset,
+           "Message Elements");
+    }
+    else
+    {
+       (*dtap_msg_fcn[idx])(tvb, dtap_tree, offset, len - offset);
+    }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_a(void)
+{
+    module_t           *ansi_a_module;
+    guint              i;
+
+    /* Setup list of header fields */
+
+    static hf_register_info hf[] =
+    {
+       { &hf_ansi_a_bsmap_msgtype,
+           { "BSMAP Message Type",     "ansi_a.bsmap_msgtype",
+           FT_UINT8, BASE_HEX, VALS(ansi_bsmap_strings), 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_dtap_msgtype,
+           { "DTAP Message Type",      "ansi_a.dtap_msgtype",
+           FT_UINT8, BASE_HEX, VALS(ansi_dtap_strings), 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_elem_id,
+           { "Element ID",     "ansi_a.elem_id",
+           FT_UINT8, BASE_DEC, VALS(ansi_elem_1_strings), 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_length,
+           { "Length",         "ansi_a.len",
+           FT_UINT8, BASE_DEC, NULL, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_none,
+           { "Sub tree",       "ansi_a.none",
+           FT_NONE, 0, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_esn,
+           { "ESN",    "ansi_a.esn",
+           FT_UINT32, BASE_HEX, 0, 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_imsi,
+           { "IMSI",   "ansi_a.imsi",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_min,
+           { "MIN",    "ansi_a.min",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_cld_party_bcd_num,
+           { "Called Party BCD Number",        "ansi_a.cld_party_bcd_num",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_clg_party_bcd_num,
+           { "Calling Party BCD Number",       "ansi_a.clg_party_bcd_num",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_cld_party_ascii_num,
+           { "Called Party ASCII Number",      "ansi_a.cld_party_ascii_num",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_clg_party_ascii_num,
+           { "Calling Party ASCII Number",     "ansi_a.clg_party_ascii_num",
+           FT_STRING, BASE_DEC, 0, 0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_cell_ci,
+           { "Cell CI",        "ansi_a.cell_ci",
+           FT_UINT16, BASE_HEX, 0, 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_cell_lac,
+           { "Cell LAC",       "ansi_a.cell_lac",
+           FT_UINT16, BASE_HEX, 0, 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_cell_mscid,
+           { "Cell MSCID",     "ansi_a.cell_mscid",
+           FT_UINT24, BASE_HEX, 0, 0x0,
+           "", HFILL }
+       },
+       { &hf_ansi_a_pdsn_ip_addr,
+           { "PDSN IP Address", "ansi_a.pdsn_ip_addr",
+           FT_IPv4, BASE_NONE, NULL, 0,
+           "IP Address", HFILL}},
+    };
+
+    static enum_val_t a_variant_options[] = {
+           { "IS-634 rev. 0",  A_VARIANT_IS634 },
+           { "TSB-80",         A_VARIANT_TSB80 },
+           { "IS-634-A",       A_VARIANT_IS634A },
+           { "IOS 2.x",        A_VARIANT_IOS2 },
+           { "IOS 3.x",        A_VARIANT_IOS3 },
+           { "IOS 4.0.1",      A_VARIANT_IOS401 },
+           { NULL,             0 }
+
+    };
+
+    /* Setup protocol subtree array */
+#define        MAX_NUM_DTAP_MSG        ANSI_A_MAX(NUM_IOS401_DTAP_MSG, 0)
+#define        MAX_NUM_BSMAP_MSG       ANSI_A_MAX(NUM_IOS401_BSMAP_MSG, 0)
+#define        NUM_INDIVIDUAL_ELEMS    8
+    static gint *ett[NUM_INDIVIDUAL_ELEMS+MAX_NUM_DTAP_MSG+MAX_NUM_BSMAP_MSG+NUM_ELEM_1+NUM_MS_INFO_REC];
+
+    memset((void *) ett, 0, sizeof(ett));
+
+    ett[0] = &ett_bsmap;
+    ett[1] = &ett_dtap;
+    ett[2] = &ett_elems;
+    ett[3] = &ett_elem;
+    ett[4] = &ett_dtap_oct_1;
+    ett[5] = &ett_cm_srvc_type;
+    ett[6] = &ett_ansi_ms_info_rec_reserved;
+    ett[7] = &ett_ansi_enc_info;
+
+    for (i=0; i < MAX_NUM_DTAP_MSG; i++)
+    {
+       ett_dtap_msg[i] = -1;
+       ett[NUM_INDIVIDUAL_ELEMS+i] = &ett_dtap_msg[i];
+    }
+
+    for (i=0; i < MAX_NUM_BSMAP_MSG; i++)
+    {
+       ett_bsmap_msg[i] = -1;
+       ett[NUM_INDIVIDUAL_ELEMS+MAX_NUM_DTAP_MSG+i] = &ett_bsmap_msg[i];
+    }
+
+    for (i=0; i < NUM_ELEM_1; i++)
+    {
+       ett_ansi_elem_1[i] = -1;
+       ett[NUM_INDIVIDUAL_ELEMS+MAX_NUM_DTAP_MSG+MAX_NUM_BSMAP_MSG+i] = &ett_ansi_elem_1[i];
+    }
+
+    for (i=0; i < NUM_MS_INFO_REC; i++)
+    {
+       ett_ansi_ms_info_rec[i] = -1;
+       ett[NUM_INDIVIDUAL_ELEMS+MAX_NUM_DTAP_MSG+MAX_NUM_BSMAP_MSG+NUM_ELEM_1+i] = &ett_ansi_ms_info_rec[i];
+    }
+
+    /* Register the protocol name and description */
+
+    proto_a_bsmap =
+       proto_register_protocol("ANSI A-I/F BSMAP", "ANSI BSMAP", "ansi_a_bsmap");
+
+    proto_register_field_array(proto_a_bsmap, hf, array_length(hf));
+
+    proto_a_dtap =
+       proto_register_protocol("ANSI A-I/F DTAP", "ANSI DTAP", "ansi_a_dtap");
+
+    is637_dissector_table =
+       register_dissector_table("ansi_a.sms", "IS-637-A (SMS)",
+       FT_UINT8, BASE_DEC);
+
+    is683_dissector_table =
+       register_dissector_table("ansi_a.ota", "IS-683-A (OTA)",
+       FT_UINT8, BASE_DEC);
+
+    proto_register_subtree_array(ett, array_length(ett));
+
+    /*
+     * setup for preferences
+     */
+    ansi_a_module = prefs_register_protocol(proto_a_bsmap, proto_reg_handoff_ansi_a);
+
+    prefs_register_enum_preference(ansi_a_module,
+       "global_variant",
+       "Dissect PDU as",
+       "(if other than the default of IOS 4.0.1)",
+       &a_global_variant,
+       a_variant_options,
+       FALSE);
+}
+
+
+void
+proto_reg_handoff_ansi_a(void)
+{
+    static int                 ansi_a_prefs_initialized = FALSE;
+
+
+    if (!ansi_a_prefs_initialized)
+    {
+       bsmap_handle = create_dissector_handle(dissect_bsmap, proto_a_bsmap);
+       dtap_handle = create_dissector_handle(dissect_dtap, proto_a_dtap);
+
+       ansi_a_prefs_initialized = TRUE;
+    }
+    else
+    {
+       dissector_delete("bsap.pdu_type",  BSSAP_PDU_TYPE_BSMAP, bsmap_handle);
+       dissector_delete("bsap.pdu_type",  BSSAP_PDU_TYPE_DTAP, dtap_handle);
+    }
+
+    if (a_variant != a_global_variant)
+    {
+       a_variant = a_global_variant;
+    }
+
+    dissector_add("bsap.pdu_type",  BSSAP_PDU_TYPE_BSMAP, bsmap_handle);
+    dissector_add("bsap.pdu_type",  BSSAP_PDU_TYPE_DTAP, dtap_handle);
+
+    data_handle = find_dissector("data");
+}
diff --git a/packet-bssap.c b/packet-bssap.c
new file mode 100644 (file)
index 0000000..f2f2ab9
--- /dev/null
@@ -0,0 +1,489 @@
+/* packet-bssap.c
+ * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
+ * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
+ *     IOS 4.0.1 (BSAP)
+ *     GSM 08.06 (BSSAP)
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id: packet-bssap.c,v 1.1 2003/10/22 20:59:02 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"
+#include "prefs.h"
+#include "packet-bssap.h"
+
+#define BSSAP 0
+#define BSAP  1
+
+#define BSSAP_OR_BSAP_DEFAULT BSSAP
+
+#define PDU_TYPE_OFFSET 0
+#define PDU_TYPE_LENGTH 1
+
+/* Same as below but with names typed out */
+static const value_string bssap_pdu_type_values[] = {
+    { BSSAP_PDU_TYPE_BSSMAP,   "BSS Management" },
+    { BSSAP_PDU_TYPE_DTAP,     "Direct Transfer" },
+    { 0,                       NULL } };
+
+static const value_string bsap_pdu_type_values[] = {
+    { BSSAP_PDU_TYPE_BSSMAP,   "BS Management" },
+    { BSSAP_PDU_TYPE_DTAP,     "Direct Transfer" },
+    { 0,                       NULL } };
+
+/* Same as above but in acronym for (for the Info column) */
+static const value_string bssap_pdu_type_acro_values[] = {
+    { BSSAP_PDU_TYPE_BSSMAP,   "BSSMAP" },
+    { BSSAP_PDU_TYPE_DTAP,     "DTAP" },
+    { 0,                       NULL } };
+
+/* Same as above but in acronym for (for the Info column) */
+static const value_string bsap_pdu_type_acro_values[] = {
+    { BSSAP_PDU_TYPE_BSSMAP,   "BSMAP" },
+    { BSSAP_PDU_TYPE_DTAP,     "DTAP" },
+    { 0,                       NULL } };
+
+#define PARAMETER_DLCI         0x00
+#define PARAMETER_LENGTH       0x01
+#define PARAMETER_DATA         0x02
+
+static const value_string bssap_parameter_values[] = {
+    { PARAMETER_DLCI,  "Data Link Connection Identifier" },
+    { PARAMETER_LENGTH,        "Length" },
+    { PARAMETER_DATA,  "Data" },
+    { 0,               NULL } };
+
+#define DLCI_LENGTH            1
+#define LENGTH_LENGTH          1
+#define DATA_LENGTH            1
+
+#define CC_MASK                        0xc0
+#define SAPI_MASK              0x07
+
+static const value_string bssap_cc_values[] = {
+    { 0x00,            "not further specified" },
+    { 0x80,            "FACCH or SDCCH" },
+    { 0xc0,            "SACCH" },
+    { 0,               NULL } };
+
+static const value_string bsap_cc_values[] = {
+    { 0x00,            "default for TIA/EIA/IS-2000" },
+    { 0,               NULL } };
+
+static const value_string bssap_sapi_values[] = {
+    { 0x00,            "RR/MM/CC" },
+    { 0x03,            "SMS" },
+    { 0,               NULL } };
+
+static const value_string bsap_sapi_values[] = {
+    { 0x00,            "Not used" },
+    { 0,               NULL } };
+
+
+/* Initialize the protocol and registered fields */
+static int proto_bssap = -1;
+static int hf_bssap_pdu_type = -1;
+static int hf_bsap_pdu_type = -1;
+static int hf_bssap_dlci_cc = -1;
+static int hf_bsap_dlci_cc = -1;
+static int hf_bssap_dlci_sapi = -1;
+static int hf_bsap_dlci_sapi = -1;
+static int hf_bssap_length = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_bssap = -1;
+static gint ett_bssap_dlci = -1;
+
+static dissector_handle_t data_handle;
+
+static dissector_table_t bssap_dissector_table;
+static dissector_table_t bsap_dissector_table;
+
+/*
+ * Keep track of pdu_type so we can call appropriate sub-dissector
+ */
+static guint8  pdu_type = 0xFF;
+
+static guint   bssap_or_bsap_global = BSSAP_OR_BSAP_DEFAULT;
+
+
+/* FORWARD DECLARATIONS */
+
+void proto_reg_handoff_bssap(void);
+
+static void
+dissect_bssap_unknown_message(tvbuff_t *message_tvb, proto_tree *bssap_tree)
+{
+    guint32    message_length;
+
+    message_length = tvb_length(message_tvb);
+
+    proto_tree_add_text(bssap_tree, message_tvb, 0, message_length,
+       "Unknown message (%u byte%s)",
+       message_length, plurality(message_length, "", "s"));
+}
+
+static void
+dissect_bssap_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
+{
+    proto_tree_add_text(tree, tvb, 0, length,
+       "Unknown parameter 0x%x (%u byte%s)",
+       type, length, plurality(length, "", "s"));
+}
+
+static void
+dissect_bssap_data_param(tvbuff_t *tvb, packet_info *pinfo,
+                       proto_tree *bssap_tree, proto_tree *tree)
+{
+    if ((pdu_type <= 0x01))
+    {
+       if (bssap_or_bsap_global == BSSAP)
+       {
+           /* BSSAP */
+           if (dissector_try_port(bssap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
+       }
+       else
+       {
+           /* BSAP */
+           if (dissector_try_port(bsap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
+       }
+    }
+
+    /* No sub-dissection occured, treat it as raw data */
+    call_dissector(data_handle, tvb, pinfo, bssap_tree);
+}
+
+static void
+dissect_bssap_dlci_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+{
+    proto_item *dlci_item = 0;
+    proto_tree *dlci_tree = 0;
+    guint8     cc, sapi;
+
+    dlci_item =
+       proto_tree_add_text(tree, tvb, 0, length,
+           "Data Link Connection Identifier");
+
+    dlci_tree = proto_item_add_subtree(dlci_item, ett_bssap_dlci);
+
+    cc = tvb_get_guint8(tvb, 0) & CC_MASK;
+    sapi = tvb_get_guint8(tvb, 0) & SAPI_MASK;
+
+    if (bssap_or_bsap_global == BSSAP)
+    {
+       proto_tree_add_uint(dlci_tree, hf_bssap_dlci_cc, tvb, 0, length, cc);
+       proto_tree_add_uint(dlci_tree, hf_bssap_dlci_sapi, tvb, 0, length, sapi);
+    }
+    else
+    {
+       proto_tree_add_uint(dlci_tree, hf_bsap_dlci_cc, tvb, 0, length, cc);
+       proto_tree_add_uint(dlci_tree, hf_bsap_dlci_sapi, tvb, 0, length, sapi);
+    }
+}
+
+static void
+dissect_bssap_length_param(tvbuff_t *tvb, proto_tree *tree, guint8 length)
+{
+    guint8     data_length;
+
+    data_length = tvb_get_guint8(tvb, 0);
+    proto_tree_add_uint(tree, hf_bssap_length, tvb, 0, length, data_length);
+}
+
+/*
+ * Dissect a parameter given its type, offset into tvb, and length.
+ */
+static guint16
+dissect_bssap_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
+                      proto_tree *tree, guint8 parameter_type, guint8 offset,
+                      guint16 parameter_length)
+{
+    tvbuff_t *parameter_tvb;
+
+    parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
+
+    switch (parameter_type)
+    {
+    case PARAMETER_DLCI:
+       dissect_bssap_dlci_param(parameter_tvb, bssap_tree, parameter_length);
+       break;
+
+    case PARAMETER_LENGTH:
+       dissect_bssap_length_param(parameter_tvb, bssap_tree, parameter_length);
+       break;
+
+    case PARAMETER_DATA:
+       dissect_bssap_data_param(parameter_tvb, pinfo, bssap_tree, tree);
+       break;
+
+    default:
+       dissect_bssap_unknown_param(parameter_tvb, bssap_tree, parameter_type,
+           parameter_length);
+       break;
+    }
+
+    return(parameter_length);
+}
+
+static guint16
+dissect_bssap_var_parameter(tvbuff_t *tvb, packet_info *pinfo,
+                               proto_tree *bssap_tree, proto_tree *tree,
+                               guint8 parameter_type, guint8 offset)
+{
+    guint16    parameter_length;
+    guint8     length_length;
+
+    parameter_length = tvb_get_guint8(tvb, offset);
+    length_length = LENGTH_LENGTH;
+
+    offset += length_length;
+
+    dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree, parameter_type,
+       offset, parameter_length);
+
+    return(parameter_length + length_length);
+}
+
+static void
+dissect_bssap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
+                    proto_tree *tree)
+{
+    guint8     offset = 0;
+
+    /*
+     * Extract the PDU type
+     */
+    pdu_type = tvb_get_guint8(tvb, PDU_TYPE_OFFSET);
+    offset = PDU_TYPE_LENGTH;
+
+    if (bssap_tree)
+    {
+       /*
+        * add the message type to the protocol tree
+        */
+       proto_tree_add_uint(bssap_tree,
+           (bssap_or_bsap_global == BSSAP) ? hf_bssap_pdu_type : hf_bsap_pdu_type,
+           tvb, PDU_TYPE_OFFSET, PDU_TYPE_LENGTH, pdu_type);
+    }
+
+    /* Starting a new message dissection */
+
+    switch (pdu_type)
+    {
+    case BSSAP_PDU_TYPE_BSSMAP:
+       offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+                                    PARAMETER_LENGTH, offset,
+                                    LENGTH_LENGTH);
+       offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
+                                   PARAMETER_DATA,
+                                   (offset - LENGTH_LENGTH));
+       break;
+
+    case BSSAP_PDU_TYPE_DTAP:
+       offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+                                    PARAMETER_DLCI,
+                                    offset, DLCI_LENGTH);
+       offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+                                    PARAMETER_LENGTH, offset,
+                                    LENGTH_LENGTH);
+       offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
+                                   PARAMETER_DATA,
+                                   (offset - LENGTH_LENGTH));
+       break;
+
+    default:
+       if (check_col(pinfo->cinfo, COL_INFO))
+       {
+           col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+               val_to_str(pdu_type, ((bssap_or_bsap_global == BSSAP) ?
+                   bssap_pdu_type_acro_values : bsap_pdu_type_acro_values),
+                   "Unknown"));
+
+       }
+
+       dissect_bssap_unknown_message(tvb, bssap_tree);
+       break;
+    }
+}
+
+static void
+dissect_bssap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_item *bssap_item;
+    proto_tree *bssap_tree = NULL;
+
+    /*
+     * Make entry in the Protocol column on summary display
+     */
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
+    {
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, ((bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP"));
+    }
+
+    if (tree)
+    {
+       /*
+        * create the bssap protocol tree
+        */
+       proto_tree_add_item_hidden(tree, proto_bssap, tvb, 0, -1, FALSE);
+       bssap_item = proto_tree_add_text(tree, tvb, 0, -1, (bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP");
+       bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
+    }
+
+    /* dissect the message */
+
+    dissect_bssap_message(tvb, pinfo, bssap_tree, tree);
+}
+
+static gboolean
+dissect_bssap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    /* Is it a BSSAP/BSAP packet?
+     *    If octet_1 == 0x00 and octet_2 == length(tvb) - 2
+     * or if octet_1 == 0x01 and octet_3 == length(tvb) - 3
+     * then we'll assume it is a bssap packet
+     */
+    switch (tvb_get_guint8(tvb, 0))
+    {
+    case 0x00:
+       if (tvb_get_guint8(tvb, 1) != (tvb_length(tvb) - 2)) { return(FALSE); }
+       break;
+
+    case 0x01:
+       if (tvb_get_guint8(tvb, 2) != (tvb_length(tvb) - 3)) { return(FALSE); }
+       break;
+
+    default:
+       return(FALSE);
+    }
+
+    dissect_bssap(tvb, pinfo, tree);
+
+    return(TRUE);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_bssap(void)
+{
+    module_t   *bssap_module;
+
+    /* Setup list of header fields */
+    static hf_register_info hf[] = {
+       { &hf_bssap_pdu_type,
+           { "Message Type", "bssap.pdu_type",
+               FT_UINT8, BASE_HEX, VALS(bssap_pdu_type_values), 0x0,
+               "", HFILL}},
+       { &hf_bsap_pdu_type,
+           { "Message Type", "bsap.pdu_type",
+               FT_UINT8, BASE_HEX, VALS(bsap_pdu_type_values), 0x0,
+               "", HFILL}},
+       { &hf_bssap_dlci_cc,
+           { "Control Channel", "bssap.dlci.cc",
+               FT_UINT8, BASE_HEX, VALS(bssap_cc_values), CC_MASK,
+               "", HFILL}},
+       { &hf_bsap_dlci_cc,
+           { "Control Channel", "bsap.dlci.cc",
+               FT_UINT8, BASE_HEX, VALS(bsap_cc_values), CC_MASK,
+               "", HFILL}},
+       { &hf_bssap_dlci_sapi,
+           { "SAPI", "bssap.dlci.sapi",
+               FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), SAPI_MASK,
+               "", HFILL}},
+       { &hf_bsap_dlci_sapi,
+           { "SAPI", "bsap.dlci.sapi",
+               FT_UINT8, BASE_HEX, VALS(bsap_sapi_values), SAPI_MASK,
+               "", HFILL}},
+       { &hf_bssap_length,
+           { "Length", "bssap.length",
+               FT_UINT8, BASE_DEC, NULL, 0x0,
+               "", HFILL}},
+    };
+
+    /* Setup protocol subtree array */
+    static gint *ett[] = {
+       &ett_bssap,
+       &ett_bssap_dlci,
+    };
+
+    static enum_val_t bssap_or_bsap_options[] = {
+       { "BSSAP",              BSSAP },
+       { "BSAP",               BSAP  },
+       { NULL,                 0 }
+    };
+
+
+    /* Register the protocol name and description */
+    proto_bssap = proto_register_protocol("BSSAP/BSAP", "BSSAP", "bssap");
+
+    /* Required function calls to register the header fields and subtrees used */
+    proto_register_field_array(proto_bssap, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    bssap_module = prefs_register_protocol(proto_bssap, proto_reg_handoff_bssap);
+
+    prefs_register_enum_preference(bssap_module,
+       "bsap_or_bssap",
+       "Identify to sub-dissector as",
+       "For the sake of sub-dissectors registering to accept data from the BSSAP/BSAP dissector, this defines whether it is identified as BSSAP or BSAP.",
+       &bssap_or_bsap_global,
+       bssap_or_bsap_options,
+       FALSE);
+
+    bssap_dissector_table = register_dissector_table("bssap.pdu_type", "BSSAP Message Type", FT_UINT8, BASE_DEC);
+    bsap_dissector_table = register_dissector_table("bsap.pdu_type", "BSAP Message Type", FT_UINT8, BASE_DEC);
+}
+
+void
+proto_reg_handoff_bssap(void)
+{
+    static gboolean bssap_prefs_initialized = FALSE;
+
+
+    if (!bssap_prefs_initialized)
+    {
+       heur_dissector_add("sccp", dissect_bssap_heur, proto_bssap);
+
+       bssap_prefs_initialized = TRUE;
+    }
+
+    data_handle = find_dissector("data");
+}
diff --git a/packet-bssap.h b/packet-bssap.h
new file mode 100644 (file)
index 0000000..229951c
--- /dev/null
@@ -0,0 +1,34 @@
+/* packet-bssap.h
+ * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
+ * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
+ *     IOS 4.0.1 (BSAP)
+ *     GSM 08.06 (BSSAP)
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id: packet-bssap.h,v 1.1 2003/10/22 20:59:02 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.
+ */
+
+#define BSSAP_PDU_TYPE_BSSMAP  0x00
+#define BSSAP_PDU_TYPE_DTAP    0x01
+
+#define BSSAP_PDU_TYPE_BSMAP   BSSAP_PDU_TYPE_BSSMAP