Treat TVBs as opaque: use the accessor functions instead of accessing the fields
[obnox/wireshark/wip.git] / epan / dissectors / packet-ansi_637.c
index 2c0825db6d657c2efb9feb84c33d112e2514fa9b..a51fee76639a2192e0e49cd93b972711d85dc514 100644 (file)
 # include "config.h"
 #endif
 
-#include <stdio.h>
-/* #include <stdlib.h> */
-#include <gmodule.h>
-
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 # include <netinet/in.h>
 #endif
 
-#include <string.h>
-
-#include "epan/packet.h"
-#include "epan/emem.h"
+#include <epan/packet.h>
+#include <epan/emem.h>
+#include <epan/strutil.h>
 
 
 static const char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
@@ -99,6 +94,26 @@ static const value_string ansi_tele_msg_type_strings[] = {
     { 4,       "Delivery Acknowledgement (mobile-terminated only)" },
     { 5,       "User Acknowledgement (either direction)" },
     { 0, NULL },
+    };
+
+static const value_string ansi_tele_msg_status_strings[] = {
+    {0x00,"Message accepted"},
+    {0x01,"Message deposited to Internet"},
+    {0x02,"Message delivered"},
+    {0x03,"Message cancelled"},
+    {0x84,"Network congestion"},
+    {0x85,"Network error"},
+    {0x9f,"Unknown error"},
+    {0xc4,"Network congestion"},
+    {0xc5,"Network error"},
+    {0xc6,"Cancel failed"},
+    {0xc7,"Blocked destination"},
+    {0xc8,"Text too long"},
+    {0xc9,"Duplicate message"},
+    {0xca,"Invalid destination"},
+    {0xcd,"Message expired"},
+    {0xdf,"Unknown error"},
+    { 0, NULL }
 };
 
 static const value_string ansi_tele_id_strings[] = {
@@ -111,6 +126,7 @@ static const value_string ansi_tele_id_strings[] = {
     { 4101,    "CDMA Wireless Enhanced Messaging Teleservice (WEMT)" },
     { 65535,   "(Reserved) Being used for Broadcast" },
     { 0, NULL },
+
 };
 
 static const value_string ansi_tele_param_strings[] = {
@@ -131,6 +147,7 @@ static const value_string ansi_tele_param_strings[] = {
     { 0x0e,    "Call-Back Number" },
     { 0x0f,    "Message Display Mode" },
     { 0x10,    "Multiple Encoding User Data" },
+    { 0x14,    "Message Status" },
     { 0, NULL },
 };
 
@@ -173,6 +190,7 @@ static int hf_ansi_637_trans_length = -1;
 static int hf_ansi_637_trans_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_status = -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;
@@ -185,14 +203,111 @@ static gint ett_params = -1;
 
 static guint32 ansi_637_trans_tele_id;
 static char ansi_637_bigbuf[1024];
+static char gsm_637_bigbuf[1024];
+static char ia5_637_bigbuf[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 */
+#define GN_CHAR_ALPHABET_SIZE 128
+
+#define GN_CHAR_ESCAPE 0x1b
+
+static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
+
+    /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
+    /* Fixed to use unicode */
+    /* Characters in hex position 10, [12 to 1a] and 24 are not present on
+       latin1 charset, so we cannot reproduce on the screen, however they are
+       greek symbol not present even on my Nokia */
+
+    '@',  0xa3, '$' , 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
+    0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
+   0x394, '_', 0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,
+   0x3a3,0x398,0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
+    ' ',  '!',  '\"', '#',  0xa4,  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
+    0xa1, 'A',  'B',  'C',  'D',  'E',  'F',  'G',
+    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
+    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
+    'X',  'Y',  'Z',  0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
+    0xbf, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+    'x',  'y',  'z',  0xe4, 0xf6, 0xf1, 0xfc, 0xe0
+};
+
+
+
+static gboolean
+char_is_escape(unsigned char value)
+{
+    return (value == GN_CHAR_ESCAPE);
+}
+
+static gunichar
+char_def_alphabet_ext_decode(unsigned char value)
+{
+    switch (value)
+    {
+    case 0x0a: return 0x0c; /* form feed */
+    case 0x14: return '^';
+    case 0x28: return '{';
+    case 0x29: return '}';
+    case 0x2f: return '\\';
+    case 0x3c: return '[';
+    case 0x3d: return '~';
+    case 0x3e: return ']';
+    case 0x40: return '|';
+    case 0x65: return 0x20ac; /* euro */
+    default: return '?'; /* invalid character */
+    }
+}
+
+static gunichar
+char_def_alphabet_decode(unsigned char value)
+{
+    if (value < GN_CHAR_ALPHABET_SIZE)
+    {
+       return gsm_default_alphabet[value];
+    }
+    else
+    {
+       return '?';
+    }
+}
 
 static void
+gsm_sms_char_7bit_ascii_decode(unsigned char * dest, const unsigned char* src, int len)
+{
+    int i, j;
+    gunichar buf;
+
+
+    for (i = 0, j = 0; j < len;  j++)
+    {
+       if (char_is_escape(src[j])) {
+           buf = char_def_alphabet_ext_decode(src[++j]);
+           i += g_unichar_to_utf8(buf,&(dest[i]));
+       }
+       else {
+           buf = char_def_alphabet_decode(src[j]);
+           i += g_unichar_to_utf8(buf,&(dest[i]));
+       }
+    }
+    dest[i]=0;
+    return;
+}
+
+
+
+
+
+static int
 decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oct, guint8 *last_bit, gchar *buf)
 {
     guint8     oct, oct2, bit;
@@ -202,7 +317,7 @@ decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oc
 
     if (num_fields == 0)
     {
-       return;
+        return 0;
     }
 
     /* saved_offset = *offset; */
@@ -275,6 +390,7 @@ decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oc
     buf[i] = '\0';
     *last_bit = bit;
     *last_oct = (bit == 1) ? oct : oct2;
+    return i;
 }
 
 /* PARAM FUNCTIONS */
@@ -321,6 +437,107 @@ tele_param_msg_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
        tvb, offset, 3, octs);
 }
 
+/* Adamek Jan - IS637C Message status decoding procedure */
+static void
+tele_param_msg_status(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+    /* Declare some variables */
+
+    guint8     oct;
+    guint8     error_class;
+    guint8     msg_status_code;
+    const gchar *str = NULL;
+
+    /* Chceck if the exact length */
+    EXACT_DATA_CHECK(len, 1);
+
+    /* get the status octet? */
+
+    oct = tvb_get_guint8(tvb, offset);
+
+
+    /* error class filter */
+    proto_tree_add_item(tree, hf_ansi_637_tele_msg_status,tvb, offset, 1, FALSE);
+
+    /*error class filter end */
+
+
+/*error class */
+
+    error_class = ((oct & 0xc0) >> 6);
+    switch (error_class)
+    {
+    case 0x00: str = "No Error";break;
+    case 0x01: str = "Reserved";break;
+    case 0x02: str = "Temporary Condition";break;
+    case 0x03: str = "Permanent Condition";break;
+    default: str = "Reserved";break;
+    }
+    other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+    proto_tree_add_text(tree, tvb, offset, 1,
+                        "%s :  Erorr Class: %s",
+                        ansi_637_bigbuf,
+                        str);
+
+
+
+    msg_status_code = (oct & 0x3f);
+
+    if (error_class == 0x00){
+       switch (msg_status_code)
+       {
+       case 0x00: str = "Message accepted";break;
+        case 0x01: str = "Message deposited to internet";break;
+        case 0x02: str = "Message delivered";break;
+        case 0x03: str = "Message cancelled";break;
+        default: str = "Reserved";break;
+        }
+       other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+       proto_tree_add_text(tree, tvb, offset, 1,
+                            "%s :  Message status code: %s",
+                            ansi_637_bigbuf,
+                            str);
+    }
+
+/*error message status */
+    if (error_class == 0x02){
+        switch (msg_status_code)
+        {
+        case 0x04: str = "Network congestion";break;
+        case 0x05: str = "Network error";break;
+        case 0x1f: str = "Unknown error";break;
+        default: str = "Reserved";break;
+        }
+        other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+        proto_tree_add_text(tree, tvb, offset, 1,
+                            "%s :  Message status code: %s",
+                            ansi_637_bigbuf,
+                            str);
+    }
+
+    if (error_class == 0x03){
+        switch (msg_status_code)
+        {
+        case 0x04: str = "Network congestion";break;
+        case 0x05: str = "Network error";break;
+        case 0x06: str = "Cancel failed";break;
+        case 0x07: str = "Blocked destination";break;
+        case 0x08: str = "Text too long";break;
+        case 0x09: str = "Duplicate message";break;
+        case 0x0a: str = "Invalid destination";break;
+        case 0x0d: str = "Message expired";break;
+        case 0x1f: str = "Unknown error";break;
+        default: str = "Reserved";break;
+        }
+        other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+        proto_tree_add_text(tree, tvb, offset, 1,
+                            "%s :  Message status code: %s",
+                            ansi_637_bigbuf,
+                            str);
+    }
+}
+
+
 static void
 tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
 {
@@ -332,9 +549,14 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     guint8     bit;
     guint32    required_octs;
     guint32    saved_offset;
-    guint32    i;
+    guint32    i , out_len;
     const gchar        *str = NULL;
 
+    /*add more translation UCS  , IA5 , latin ,  latin \ hebrew ,gsm 7BIT*/
+    gchar *utf8_text = NULL;
+    GIConv cd;
+    GError *l_conv_error = NULL;
+
     SHORT_DATA_CHECK(len, 2);
 
     /*
@@ -471,11 +693,116 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
                "%s :  Reserved",
                ansi_637_bigbuf);
        }
+    }
+    else if (encoding == 0x03)/* IA5 */
+    {
+        i = (num_fields * 7) - 3;
+        required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+        if (required_octs + used > len)
+        {
+            proto_tree_add_text(tree, tvb, offset, 1,
+                                "Missing %d octet(s) for number of fields",
+                                (required_octs + used) - len);
+
+            return;
+        }
+
+        bit = 3;
+        saved_offset = offset;
+        out_len = decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
+        IA5_7BIT_decode(ia5_637_bigbuf, ansi_637_bigbuf, out_len);
+
+        proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+                            "Encoded user data: %s",
+                            ia5_637_bigbuf);
+    }
+    /*TODO UCS else if (encoding == 0x04)
+      {
+      }*/
+    else if (encoding == 0x07)/* Latin/Hebrew */
+    {
+        saved_offset = offset - 1;
+        for (i=0; i < num_fields; i++)
+        {
+            oct = tvb_get_guint8(tvb, saved_offset);
+            oct2 = tvb_get_guint8(tvb, saved_offset + 1);;
+            ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+            saved_offset++;
+        }
+
+        if ((cd = g_iconv_open("UTF-8","iso-8859-8")) != (GIConv)-1)
+        {
+            utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error);
+            if(!l_conv_error)
+            {
+                proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
+            }
+            else
+            {
+                proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-8 contact Wireshark developers");
+            }
+            if(utf8_text)
+                g_free(utf8_text);
+            g_iconv_close(cd);
+        }
+    }
+    else if (encoding == 0x08) /* Latin */
+    {
+        saved_offset = offset - 1;
+        for (i=0; i < num_fields; i++)
+        {
+            oct = tvb_get_guint8(tvb, saved_offset);
+            oct2 = tvb_get_guint8(tvb, saved_offset + 1);;
+            ansi_637_bigbuf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+            saved_offset++;
+        }
+
+        if ((cd = g_iconv_open("UTF-8","iso-8859-1")) != (GIConv)-1)
+        {
+            utf8_text = g_convert_with_iconv(ansi_637_bigbuf , num_fields , cd , NULL , NULL , &l_conv_error);
+            if(!l_conv_error)
+            {
+                proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
+            }
+            else
+            {
+                proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-1 contact Wireshark developers");
+            }
+            if(utf8_text)
+                g_free(utf8_text);
+            g_iconv_close(cd);
+        }
+    }
+    else if (encoding == 0x09) /* GSM 7-bit default alphabet */
+    {
+        i = (num_fields * 7) - 3;
+        required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+        if (required_octs + used > len)
+        {
+            proto_tree_add_text(tree, tvb, offset, 1,
+                                "Missing %d octet(s) for number of fields",
+                                (required_octs + used) - len);
+
+            return;
+        }
+
+        bit = 3;
+        saved_offset = offset;
+        out_len = decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
+        gsm_sms_char_7bit_ascii_decode(gsm_637_bigbuf, ansi_637_bigbuf, out_len);
+
+        proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+                            "Encoded user data: %s",
+                            gsm_637_bigbuf);
+
+
     }
     else
     {
-       proto_tree_add_text(tree, tvb, offset, len - used,
-           "Encoded user data");
+        proto_tree_add_text(tree, tvb, offset, len - used,
+                            "Encoded user data");
     }
 }
 
@@ -561,7 +888,7 @@ tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 off
     if (str == NULL)
     {
        proto_tree_add_text(tree, tvb, offset, 1,
-           str2);
+           "%s", str2);
     }
     else
     {
@@ -572,11 +899,11 @@ tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 off
 }
 
 static const value_string tele_param_pri_ind_strings[] = {
-       { 0,    "Normal" },
-       { 1,    "Interactive" },
-       { 2,    "Urgent" },
-       { 3,    "Emergency" },
-       { 0, NULL }
+    { 0,       "Normal" },
+    { 1,       "Interactive" },
+    { 2,       "Urgent" },
+    { 3,       "Emergency" },
+    { 0, NULL }
 };
 
 static void
@@ -729,7 +1056,7 @@ tele_param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     }
 
     proto_tree_add_text(tree, tvb, offset, 1,
-       str);
+       "%s", str);
 }
 
 static void
@@ -920,7 +1247,7 @@ static void (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint
     tele_param_cb_num,         /* Call-Back Number */
     tele_param_disp_mode,      /* Message Display Mode */
     NULL,                      /* Multiple Encoding User Data */
-    NULL,                      /* NONE */
+    tele_param_msg_status      /* Message status */
 };
 
 static void
@@ -1012,12 +1339,10 @@ trans_param_srvc_cat(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset,
 
     value = tvb_get_ntohs(tvb, offset);
 
-    str = match_strval(value, ansi_srvc_cat_strings);
-
-    if (NULL == str) str = "Reserved";
+    str = val_to_str_const(value, ansi_srvc_cat_strings, "Reserved");
 
     proto_tree_add_text(tree, tvb, offset, 2,
-       str);
+       "%s", str);
 
     g_snprintf(add_string, string_len, " - %s (%d)", str, value);
 }
@@ -1388,11 +1713,10 @@ trans_param_subaddress(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offse
 }
 
 static void
-trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
+trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len _U_, guint32 offset, gchar *add_string, int string_len)
 {
     guint8     oct;
 
-    len = len;
     oct = tvb_get_guint8(tvb, offset);
 
     other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
@@ -1494,7 +1818,7 @@ trans_param_cause_codes(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offs
     }
 
     proto_tree_add_text(tree, tvb, offset, 1,
-       str);
+       "%s", str);
 }
 
 static void
@@ -1510,7 +1834,7 @@ trans_param_bearer_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offs
      */
     tele_tvb = tvb_new_subset(tvb, offset, len, len);
 
-    dissector_try_port(tele_dissector_table, ansi_637_trans_tele_id,
+    dissector_try_uint(tele_dissector_table, ansi_637_trans_tele_id,
        tele_tvb, g_pinfo, g_tree);
 }
 
@@ -1537,7 +1861,7 @@ static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
 static gboolean
 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;
+    void (*param_fcn)(tvbuff_t *, proto_tree *, guint, guint32) = NULL;
     guint8     oct;
     guint8     len;
     guint32    curr_offset;
@@ -1561,7 +1885,7 @@ dissect_ansi_637_tele_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
     param_fcn = ansi_637_tele_param_fcn[idx];
 
     item =
-       proto_tree_add_text(tree, tvb, curr_offset, -1, str);
+       proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str);
 
     subtree = proto_item_add_subtree(item, ett_param_idx);
 
@@ -1627,17 +1951,14 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     const gchar        *str = NULL;
     guint32    value;
 
-    if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    {
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
-    }
+    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)
     {
-       value = pinfo->match_port;
+       value = pinfo->match_uint;
 
        /*
         * create the ansi_637 protocol tree
@@ -1697,7 +2018,7 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                {
                    /*
                     * supposed to be "Reserved for carrier specific teleservices"
-                    * but we are using it to key SMS Broadcast dissection were
+                    * but we are using it to key SMS Broadcast dissection where
                     * there is no teleservice ID
                     */
                    str = "(Reserved) Being used for Broadcast";
@@ -1715,7 +2036,7 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                "%s - %s (%d)",
                ansi_proto_name_tele,
                str,
-               pinfo->match_port);
+               pinfo->match_uint);
 
        ansi_637_tree =
            proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
@@ -1727,7 +2048,7 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *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, int string_len) = NULL;
+    void (*param_fcn)(tvbuff_t *, proto_tree *, guint, guint32, gchar *, int) = NULL;
     guint8     oct;
     guint8     len;
     guint32    curr_offset;
@@ -1750,7 +2071,7 @@ dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
     param_fcn = ansi_637_trans_param_fcn[idx];
 
     item =
-       proto_tree_add_text(tree, tvb, curr_offset, -1, str);
+       proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str);
 
     subtree = proto_item_add_subtree(item, ett_param_idx);
 
@@ -1797,6 +2118,7 @@ dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
     return(TRUE);
 }
 
+
 static void
 dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -1808,10 +2130,7 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     guint8     oct;
     guint8     len;
 
-    if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    {
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
-    }
+    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.
@@ -1882,7 +2201,14 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
     }
 }
-
+/* Dissect SMS embedded in SIP */
+static void
+dissect_ansi_637_trans_app(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    col_set_str(pinfo->cinfo, COL_PROTOCOL,"/");
+    col_set_fence(pinfo->cinfo, COL_INFO);
+    dissect_ansi_637_trans(tvb, pinfo, tree);
+}
 /* Register the protocol with Wireshark */
 void
 proto_register_ansi_637(void)
@@ -1896,50 +2222,55 @@ proto_register_ansi_637(void)
          { "Message Type",
            "ansi_637_trans.msg_type",
            FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000,
-           "", HFILL }},
+           NULL, 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 }},
+           NULL, HFILL }},
        { &hf_ansi_637_trans_length,
            { "Length", "ansi_637_trans.len",
            FT_UINT8, BASE_DEC, NULL, 0,
-           "", HFILL }},
+           NULL, HFILL }},
        { &hf_ansi_637_trans_bin_addr,
            { "Binary Address", "ansi_637_trans.bin_addr",
-           FT_BYTES, BASE_HEX, 0, 0,
-           "", HFILL }},
+           FT_BYTES, BASE_NONE, 0, 0,
+           NULL, HFILL }},
        };
-       static hf_register_info hf_tele[] =
-       {
+    static hf_register_info hf_tele[] =
+    {
        { &hf_ansi_637_tele_msg_type,
          { "Message Type",
            "ansi_637_tele.msg_type",
            FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
-           "", HFILL }},
+           NULL, HFILL }},
        { &hf_ansi_637_tele_msg_id,
          { "Message ID",
            "ansi_637_tele.msg_id",
            FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
-           "", HFILL }},
+           NULL, HFILL }},
+       { &hf_ansi_637_tele_msg_status,
+         { "Message Status",
+           "ansi_637_tele.msg_status",
+           FT_UINT8, BASE_DEC, VALS(ansi_tele_msg_status_strings), 0,
+           NULL, HFILL }},
        { &hf_ansi_637_tele_msg_rsvd,
          { "Reserved",
            "ansi_637_tele.msg_rsvd",
            FT_UINT24, BASE_DEC, NULL, 0x00000f,
-           "", HFILL }},
+           NULL, HFILL }},
        { &hf_ansi_637_tele_length,
            { "Length", "ansi_637_tele.len",
            FT_UINT8, BASE_DEC, NULL, 0,
-           "", HFILL }},
+           NULL, HFILL }},
        { &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 }},
+           NULL, HFILL }},
     };
 
     /* Setup protocol subtree array */
 #define        NUM_INDIVIDUAL_PARAMS   3
-    static gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
+    gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
 
     memset((void *) ett, 0, sizeof(ett));
 
@@ -1972,8 +2303,8 @@ proto_register_ansi_637(void)
     proto_ansi_637_trans =
        proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
 
-       register_dissector("ansi_637_tele", dissect_ansi_637_tele, proto_ansi_637_tele);
-       register_dissector("ansi_637_trans", dissect_ansi_637_trans, proto_ansi_637_trans);
+    register_dissector("ansi_637_tele", dissect_ansi_637_tele, proto_ansi_637_tele);
+    register_dissector("ansi_637_trans", dissect_ansi_637_trans, proto_ansi_637_trans);
 
     /* Required function calls to register the header fields and subtrees used */
     proto_register_field_array(proto_ansi_637_tele, hf_tele, array_length(hf_tele));
@@ -1991,11 +2322,15 @@ proto_reg_handoff_ansi_637(void)
 {
     dissector_handle_t ansi_637_tele_handle;
     dissector_handle_t ansi_637_trans_handle;
+    dissector_handle_t ansi_637_trans_app_handle;
     guint              i;
 
     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);
+    ansi_637_trans_app_handle = create_dissector_handle(dissect_ansi_637_trans_app, proto_ansi_637_trans);
 
+    /* Dissect messages embedded in SIP */
+    dissector_add_string("media_type","application/vnd.3gpp2.sms", ansi_637_trans_app_handle);
     /*
      * register for all known teleservices
      * '-1' is to stop before trailing '0' entry
@@ -2007,18 +2342,18 @@ proto_reg_handoff_ansi_637(void)
        /*
         * ANSI MAP dissector will push out teleservice ids
         */
-       dissector_add("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
+       dissector_add_uint("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
 
        /*
         * we will push out teleservice ids after Transport layer decode
         */
-       dissector_add("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
+       dissector_add_uint("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);
+    dissector_add_uint("ansi_a.sms", 0, ansi_637_trans_handle);
 
     /* data_handle = find_dissector("data"); */
 }