Treat TVBs as opaque: use the accessor functions instead of accessing the fields
[obnox/wireshark/wip.git] / epan / dissectors / packet-ansi_637.c
index 76d8c96e1234aa376b75fe517acb65b65aacf84c..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/strutil.h>
 
 
 static const char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
@@ -247,27 +242,6 @@ static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
 };
 
 
-static gunichar IA5_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
-
-    /*ITU-T recommendation T.50 specifies International Reference Alphabet 5 (IA5) */
-
-    '?', '?', '?', '?', '?', '?', '?', '?',
-    '?', '?', '?', '?', '?', '?', '?', '?',
-    '?', '?', '?', '?', '?', '?', '?', '?',
-    '?', '?', '?', '?', '?', '?', '?', '?',
-    ' ', '!', '\"','#', '$', '%', '&', '\'',
-    '(', ')', '*', '+', ',', '-', '.', '/',
-    '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', ':', ';', '<', '=', '>', '?',
-    '@', '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',  '[',  '\\',  ']',  '^',  '_',
-    '`', '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',  '{',  '|',  '}',  '~',  '?'
-};
 
 static gboolean
 char_is_escape(unsigned char value)
@@ -294,7 +268,7 @@ char_def_alphabet_ext_decode(unsigned char value)
     }
 }
 
-static gunichar 
+static gunichar
 char_def_alphabet_decode(unsigned char value)
 {
     if (value < GN_CHAR_ALPHABET_SIZE)
@@ -331,34 +305,6 @@ gsm_sms_char_7bit_ascii_decode(unsigned char * dest, const unsigned char* src, i
 
 
 
-static gunichar 
-char_def_ia5_alphabet_decode(unsigned char value)
-{
-    if (value < GN_CHAR_ALPHABET_SIZE)
-    {
-               return IA5_default_alphabet[value];
-    }
-    else
-    {
-               return '?';
-    }
-}
-
-static void
-IA5_7BIT_decode(unsigned char * dest, const unsigned char* src, int len)
-{
-    int i, j;
-    gunichar buf;
-
-
-    for (i = 0, j = 0; j < len;  j++)
-    {
-           buf = char_def_ia5_alphabet_decode(src[j]);
-           i += g_unichar_to_utf8(buf,&(dest[i]));
-    }
-    dest[i]=0;
-    return;
-}
 
 
 static int
@@ -371,7 +317,7 @@ decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oc
 
     if (num_fields == 0)
     {
-               return 0;
+        return 0;
     }
 
     /* saved_offset = *offset; */
@@ -444,7 +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;
+    return i;
 }
 
 /* PARAM FUNCTIONS */
@@ -502,13 +448,13 @@ tele_param_msg_status(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset
     guint8     msg_status_code;
     const gchar *str = NULL;
 
-    /* Chceck if the exact length */  
+    /* 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);
@@ -532,9 +478,9 @@ tele_param_msg_status(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset
                         "%s :  Erorr Class: %s",
                         ansi_637_bigbuf,
                         str);
-       
 
-        
+
+
     msg_status_code = (oct & 0x3f);
 
     if (error_class == 0x00){
@@ -566,9 +512,9 @@ tele_param_msg_status(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset
         proto_tree_add_text(tree, tvb, offset, 1,
                             "%s :  Message status code: %s",
                             ansi_637_bigbuf,
-                            str);   
+                            str);
     }
-  
+
     if (error_class == 0x03){
         switch (msg_status_code)
         {
@@ -606,8 +552,7 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
     guint32    i , out_len;
     const gchar        *str = NULL;
 
-    /*add more translation UCS  , IA5 , latin ,  latin \ hebrew ,gsm 7BIT*/ 
-    proto_item *ucs2_item;
+    /*add more translation UCS  , IA5 , latin ,  latin \ hebrew ,gsm 7BIT*/
     gchar *utf8_text = NULL;
     GIConv cd;
     GError *l_conv_error = NULL;
@@ -749,32 +694,32 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
                ansi_637_bigbuf);
        }
     }
-       else if (encoding == 0x03)/* IA5 */
-       {
-            i = (num_fields * 7) - 3;
-            required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+    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);
+        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;
-            }
+            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);
+        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)
-       {
-       }*/
+        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;
@@ -782,20 +727,20 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
         {
             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);                   
+            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->real_data +  offset, num_fields , cd , NULL , NULL , &l_conv_error);
+            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)
             {
-                ucs2_item = proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
+                proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
             }
             else
             {
-                ucs2_item = proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-8 contact Wireshark developers");
+                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);
@@ -818,12 +763,12 @@ tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
             utf8_text = g_convert_with_iconv(ansi_637_bigbuf , num_fields , cd , NULL , NULL , &l_conv_error);
             if(!l_conv_error)
             {
-                ucs2_item = proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
+                proto_tree_add_text(tree, tvb, offset, num_fields, "Encoded user data: %s", utf8_text);
             }
             else
             {
-                ucs2_item = proto_tree_add_text(tree, tvb, offset, num_fields, "%s", "Failed on iso-8859-1 contact Wireshark developers");
-            }                  
+                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);
@@ -1394,9 +1339,7 @@ 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,
        "%s", str);
@@ -1770,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);
@@ -1892,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);
 }
 
@@ -2009,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
@@ -2079,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";
@@ -2097,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);
@@ -2179,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)
 {
@@ -2190,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.
@@ -2264,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)
@@ -2326,7 +2270,7 @@ proto_register_ansi_637(void)
 
     /* 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));
 
@@ -2359,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));
@@ -2378,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
@@ -2394,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"); */
 }