/* packet-ansi_637.c * Routines for ANSI IS-637-A (SMS) dissection * * Copyright 2003, Michael Lum * In association with Telos Technology Inc. * * Title 3GPP2 Other * * Short Message Service * 3GPP2 C.S0015-0 TIA/EIA-637-A * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include "packet-gsm_sms.h" void proto_register_ansi_637(void); void proto_reg_handoff_ansi_637(void); static const char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer"; static const char *ansi_proto_name_trans = "ANSI IS-637-A (SMS) Transport Layer"; static const char *ansi_proto_name_short = "IS-637-A"; 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 value_string_ext ansi_srvc_cat_strings_ext = VALUE_STRING_EXT_INIT(ansi_srvc_cat_strings); static const value_string ansi_tele_msg_type_strings[] = { { 1, "Deliver (mobile-terminated only)" }, { 2, "Submit (mobile-originated only)" }, { 3, "Cancellation (mobile-originated only)" }, { 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 value_string_ext ansi_tele_msg_status_strings_ext = VALUE_STRING_EXT_INIT(ansi_tele_msg_status_strings); static const value_string ansi_tele_id_strings[] = { { 1, "Reserved for maintenance" }, { 4096, "AMPS Extended Protocol Enhanced Services" }, { 4097, "CDMA Cellular Paging Teleservice" }, { 4098, "CDMA Cellular Messaging Teleservice" }, { 4099, "CDMA Voice Mail Notification" }, { 4100, "CDMA Wireless Application Protocol (WAP)" }, { 4101, "CDMA Wireless Enhanced Messaging Teleservice (WEMT)" }, { 65535, "(Reserved) Being used for Broadcast" }, { 0, NULL }, }; static const value_string ansi_tele_param_strings[] = { { 0x00, "Message Identifier" }, { 0x01, "User Data" }, { 0x02, "User Response Code" }, { 0x03, "Message Center Time Stamp" }, { 0x04, "Validity Period - Absolute" }, { 0x05, "Validity Period - Relative" }, { 0x06, "Deferred Delivery Time - Absolute" }, { 0x07, "Deferred Delivery Time - Relative" }, { 0x08, "Priority Indicator" }, { 0x09, "Privacy Indicator" }, { 0x0a, "Reply Option" }, { 0x0b, "Number of Messages" }, { 0x0c, "Alert on Message Delivery" }, { 0x0d, "Language Indicator" }, { 0x0e, "Call-Back Number" }, { 0x0f, "Message Display Mode" }, { 0x10, "Multiple Encoding User Data" }, { 0x14, "Message Status" }, { 0, NULL }, }; static value_string_ext ansi_tele_param_strings_ext = VALUE_STRING_EXT_INIT(ansi_tele_param_strings); #define ANSI_TRANS_MSG_TYPE_BROADCAST 1 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 const 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_tele = -1; static int proto_ansi_637_trans = -1; static int hf_ansi_637_tele_length = -1; 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_ind = -1; static int hf_ansi_637_tele_msg_rsvd = -1; static int hf_ansi_637_tele_subparam_id = -1; static int hf_ansi_637_tele_user_data_text = -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_tele = -1; static gint ett_ansi_637_trans = -1; static gint ett_params = -1; static dissector_handle_t ansi_637_tele_handle; static dissector_handle_t ansi_637_trans_handle; 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_table_t tele_dissector_table; static proto_tree *g_tree; /* FUNCTIONS */ 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; /* guint32 saved_offset; */ guint32 i; if (num_fields == 0) { return 0; } /* saved_offset = *offset; */ oct = oct2 = *last_oct; bit = *last_bit; if (bit == 1) { oct2 = tvb_get_guint8(tvb, *offset); (*offset) += 1; } for (i=0; i < num_fields; i++) { if (bit != 1) { oct = oct2; /* * cannot grab an octet if we are getting * the last field and bit is 7 or 8 * because there may not be another octet */ if (((i + 1) != num_fields) || ((bit != 7) && (bit != 8))) { oct2 = tvb_get_guint8(tvb, *offset); (*offset) += 1; } } switch (bit) { case 1: buf[i] = ((oct & 0x01) << 6) | ((oct2 & 0xfc) >> 2); break; case 2: buf[i] = ((oct & 0x03) << 5) | ((oct2 & 0xf8) >> 3); break; case 3: buf[i] = ((oct & 0x07) << 4) | ((oct2 & 0xf0) >> 4); break; case 4: buf[i] = ((oct & 0x0f) << 3) | ((oct2 & 0xe0) >> 5); break; case 5: buf[i] = ((oct & 0x1f) << 2) | ((oct2 & 0xc0) >> 6); break; case 6: buf[i] = ((oct & 0x3f) << 1) | ((oct2 & 0x80) >> 7); break; case 7: buf[i] = oct & 0x7f; break; case 8: buf[i] = (oct & 0xfe) >> 1; break; } bit = (bit % 8) + 1; } buf[i] = '\0'; *last_bit = bit; *last_oct = (bit == 1) ? oct : oct2; return i; } /* PARAM FUNCTIONS */ #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \ if ((edc_len) > (edc_max_len)) \ { \ proto_tree_add_text(tree, tvb, offset, \ (edc_len) - (edc_max_len), "Extraneous Data"); \ } #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \ if ((sdc_len) < (sdc_min_len)) \ { \ proto_tree_add_text(tree, tvb, offset, \ (sdc_len), "Short Data (?)"); \ return; \ } #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \ if ((edc_len) != (edc_eq_len)) \ { \ proto_tree_add_text(tree, tvb, offset, \ (edc_len), "Unexpected Data Length"); \ return; \ } static void tele_param_msg_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data) { EXACT_DATA_CHECK(len, 3); proto_tree_add_item(tree, hf_ansi_637_tele_msg_type, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_ansi_637_tele_msg_id, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_ansi_637_tele_msg_ind, tvb, offset, 3, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, offset+2) & 0x08) == 0x08) { *has_private_data = TRUE; } proto_tree_add_item(tree, hf_ansi_637_tele_msg_rsvd, tvb, offset, 3, ENC_BIG_ENDIAN); } /* Adamek Jan - IS637C Message status decoding procedure */ static void tele_param_msg_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { /* 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, ENC_BIG_ENDIAN); /*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, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data) { guint8 oct, oct2; guint8 encoding; guint8 msg_type; guint8 num_fields; guint8 used; guint8 bit; guint32 required_octs; guint32 saved_offset; guint32 i , out_len; const gchar *str = NULL; gchar *buf; tvbuff_t *tvb_out = NULL; gchar *utf8_text = NULL; GIConv cd; GError *l_conv_error = NULL; SHORT_DATA_CHECK(len, 2); /* * message encoding */ oct = tvb_get_guint8(tvb, offset); oct2 = 0; msg_type = 0; used = 0; encoding = ((oct & 0xf8) >> 3); switch (encoding) { case 0x00: str = "Octet, unspecified"; break; case 0x01: str = "Extended Protocol Message"; oct2 = tvb_get_guint8(tvb, offset+1); msg_type = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); break; case 0x02: str = "7-bit ASCII"; break; case 0x03: str = "IA5"; break; case 0x04: str = "UCS-2"; break; case 0x05: str = "Shift-JIS"; break; case 0x06: str = "Korean"; break; case 0x07: str = "Latin/Hebrew"; break; case 0x08: str = "ISO 8859-1"; break; case 0x09: str = "GSM 7-bit default alphabet"; break; case 0x10: str = "KSC5601 (Korean)"; break; default: str = "Reserved"; break; } other_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) { other_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); other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8); proto_tree_add_text(tree, tvb, offset+1, 1, "%s : Message type", ansi_637_bigbuf); oct = oct2; offset += 1; used += 1; } offset += 1; used += 1; /* * number of fields */ oct2 = tvb_get_guint8(tvb, offset); num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); other_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); other_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); other_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 += 1; used += 1; oct = oct2; /* NOTE: there are now 3 bits remaining in 'oct' */ if (len <= used) return; /* * decode rest if 7-bit ASCII */ if (encoding == 0x02) { /* * magic numbers: * 3 bits remaining from last octet * 7 bit encoding * 8 bits per octet */ 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; } saved_offset = offset - 1; i = num_fields * 7; required_octs = (i / 8) + ((i % 8) ? 1 : 0); buf = (gchar*)wmem_alloc(pinfo->pool, required_octs); for (i=0; i < required_octs; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; bit = 0; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, ASCII_7BITS, &bit); } saved_offset = offset; bit = bit ? bit : 8; oct = tvb_get_guint8(tvb_out, offset); offset += 1; decode_7_bits(tvb_out, &offset, num_fields, &oct, &bit, ansi_637_bigbuf); proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, saved_offset, offset - saved_offset, ansi_637_bigbuf); switch (bit) { case 1: oct2 = 0x01; break; case 2: oct2 = 0x03; break; case 3: oct2 = 0x07; break; case 4: oct2 = 0x0f; break; case 5: oct2 = 0x1f; break; case 6: oct2 = 0x3f; break; case 7: oct2 = 0x7f; break; } if (bit != 8) { other_decode_bitfield_value(ansi_637_bigbuf, oct, oct2, 8); proto_tree_add_text(tree, tvb, offset - 1, 1, "%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; } saved_offset = offset - 1; i = num_fields * 7; required_octs = (i / 8) + ((i % 8) ? 1 : 0); buf = (gchar*)wmem_alloc(pinfo->pool, required_octs); for (i=0; i < required_octs; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; bit = 0; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, ASCII_7BITS, &bit); } saved_offset = offset; bit = bit ? bit : 8; oct = tvb_get_guint8(tvb_out, offset); offset += 1; out_len = decode_7_bits(tvb_out, &offset, num_fields, &oct, &bit, ansi_637_bigbuf); IA5_7BIT_decode(ia5_637_bigbuf, ansi_637_bigbuf, out_len); proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, saved_offset, offset - saved_offset, ia5_637_bigbuf); } else if (encoding == 0x04)/* UCS-2 (not UTF-16?) */ { saved_offset = offset - 1; required_octs = 2*num_fields; buf = (gchar*)wmem_alloc(pinfo->pool, required_octs); for (i=0; i < required_octs; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, OTHER, &bit); } if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv)-1) { utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, required_octs), required_octs , cd , NULL , NULL , &l_conv_error); if (!l_conv_error) { proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, required_octs, utf8_text); } else { proto_tree_add_text(tree, tvb_out, offset, required_octs, "%s", "Failed on UCS-2BE contact Wireshark developers"); } if (utf8_text) g_free(utf8_text); g_iconv_close(cd); } } else if (encoding == 0x07)/* Latin/Hebrew */ { saved_offset = offset - 1; buf = (gchar*)wmem_alloc(pinfo->pool, num_fields); for (i=0; i < num_fields; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; required_octs = len - used; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, OTHER, &bit); } if ((cd = g_iconv_open("UTF-8","iso-8859-8")) != (GIConv)-1) { utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error); if (!l_conv_error) { proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, num_fields, utf8_text); } else { proto_tree_add_text(tree, tvb_out, 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) /* ISO 8859-1 (a/k/a ISO Latin 1) */ { saved_offset = offset - 1; buf = (gchar*)wmem_alloc(pinfo->pool, num_fields); for (i=0; i < num_fields; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; required_octs = len - used; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, OTHER, &bit); } if ((cd = g_iconv_open("UTF-8","iso-8859-1")) != (GIConv)-1) { utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, num_fields) , num_fields , cd , NULL , NULL , &l_conv_error); if (!l_conv_error) { proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, num_fields, utf8_text); } else { proto_tree_add_text(tree, tvb_out, 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; } saved_offset = offset - 1; i = num_fields * 7; required_octs = (i / 8) + ((i % 8) ? 1 : 0); buf = (gchar*)wmem_alloc(pinfo->pool, required_octs); for (i=0; i < required_octs; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, required_octs, required_octs); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; bit = 0; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, GSM_7BITS, &bit); } out_len = gsm_sms_char_7bit_unpack(bit, required_octs, num_fields, tvb_get_ptr(tvb_out, offset, required_octs), gsm_637_bigbuf); gsm_637_bigbuf[out_len] = '\0'; proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, required_octs, gsm_sms_chars_to_utf8(gsm_637_bigbuf, num_fields)); } else if (encoding == 0x10)/* KSC5601 (Korean) */ { saved_offset = offset - 1; buf = (gchar*)wmem_alloc(pinfo->pool, num_fields); for (i=0; i < num_fields; i++) { oct = tvb_get_guint8(tvb, saved_offset); oct2 = tvb_get_guint8(tvb, saved_offset + 1); buf[i] = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); saved_offset += 1; } tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields); add_new_data_source(pinfo, tvb_out, "Characters"); offset = 0; required_octs = len - used; if (*has_private_data == TRUE) { dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, OTHER, &bit); } if ((cd = g_iconv_open("UTF-8","EUC-KR")) != (GIConv)-1) { utf8_text = g_convert_with_iconv(tvb_get_ptr(tvb_out, offset, num_fields), num_fields , cd , NULL , NULL , &l_conv_error); if (!l_conv_error) { proto_tree_add_unicode_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, num_fields, utf8_text); } else { proto_tree_add_text(tree, tvb_out, offset, num_fields, "%s", "Failed on EUC-KR contact Wireshark developers"); } if (utf8_text) g_free(utf8_text); g_iconv_close(cd); } } else { proto_tree_add_text(tree, tvb, offset, len - used, "Encoded user data"); } } static void tele_param_rsp_code(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; EXACT_DATA_CHECK(len, 1); /* * response code */ oct = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Response code: %d", oct); } static void tele_param_timestamp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct, oct2, oct3; EXACT_DATA_CHECK(len, 6); oct = tvb_get_guint8(tvb, offset); oct2 = tvb_get_guint8(tvb, offset+1); oct3 = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(tree, tvb, offset, 3, "Year %d%d, Month %d%d, Day %d%d", (oct & 0xf0) >> 4, oct & 0x0f, (oct2 & 0xf0) >> 4, oct2 & 0x0f, (oct3 & 0xf0) >> 4, oct3 & 0x0f); offset += 3; oct = tvb_get_guint8(tvb, offset); oct2 = tvb_get_guint8(tvb, offset+1); oct3 = tvb_get_guint8(tvb, offset+2); proto_tree_add_text(tree, tvb, offset, 3, "Hour %d%d, Minutes %d%d, Seconds %d%d", (oct & 0xf0) >> 4, oct & 0x0f, (oct2 & 0xf0) >> 4, oct2 & 0x0f, (oct3 & 0xf0) >> 4, oct3 & 0x0f); } static void tele_param_rel_timestamp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; guint32 value = 0; const gchar *str = NULL; const gchar *str2 = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); switch (oct) { case 245: str = "Indefinite"; break; case 246: str = "Immediate"; break; case 247: str = "Valid until mobile becomes inactive/Deliver when mobile next becomes active"; break; case 248: str = "Valid until registration area changes, discard if not registered" ; break; default: if (oct <= 143) { value = (oct + 1) * 5; str2 = "Minutes"; break; } else if ((oct >= 144) && (oct <= 167)) { value = (oct - 143) * 30; str2 = "Minutes + 12 Hours"; break; } else if ((oct >= 168) && (oct <= 196)) { value = oct - 166; str2 = "Days"; break; } else if ((oct >= 197) && (oct <= 244)) { value = oct - 192; str2 = "Weeks"; break; } else { str = "Reserved"; break; } } if (str == NULL) { proto_tree_add_text(tree, tvb, offset, 1, "%s", str2); } else { proto_tree_add_text(tree, tvb, offset, 1, "%d %s", value, str2); } } static const value_string tele_param_pri_ind_strings[] = { { 0, "Normal" }, { 1, "Interactive" }, { 2, "Urgent" }, { 3, "Emergency" }, { 0, NULL } }; static void tele_param_pri_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); str=val_to_str_const((oct&0xc0)>>6, tele_param_pri_ind_strings, "Unknown"); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : %s", ansi_637_bigbuf, str); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } static void tele_param_priv_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); switch ((oct & 0xc0) >> 6) { case 0: str = "Not restricted (privacy level 0)"; break; case 1: str = "Restricted (privacy level 1)"; break; case 2: str = "Confidential (privacy level 2)"; break; case 3: str = "Secret (privacy level 3)"; break; } other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : %s", ansi_637_bigbuf, str); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } static void tele_param_reply_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); other_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"); other_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"); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } static void tele_param_num_messages(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); proto_tree_add_text(tree, tvb, offset, 1, "Number of voice mail messages: %d%d", (oct & 0xf0) >> 4, oct & 0x0f); } static void tele_param_alert(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); switch ((oct & 0xc0) >> 6) { case 0: str = "Use Mobile default alert"; break; case 1: str = "Use Low-priority alert"; break; case 2: str = "Use Medium-priority alert"; break; case 3: str = "Use High-priority alert"; break; } other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : %s", ansi_637_bigbuf, str); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } static void tele_param_lang_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); switch (oct) { case 0x00: str = "Unknown or unspecified"; break; case 0x01: str = "English"; break; case 0x02: str = "French"; break; case 0x03: str = "Spanish"; break; case 0x04: str = "Japanese"; break; case 0x05: str = "Korean"; break; case 0x06: str = "Chinese"; break; case 0x07: str = "Hebrew"; break; default: str = "Reserved"; break; } proto_tree_add_text(tree, tvb, offset, 1, "%s", str); } static void tele_param_cb_num(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct, oct2, num_fields, odd; guint32 saved_offset; guint32 required_octs; guint32 i; SHORT_DATA_CHECK(len, 2); oct = tvb_get_guint8(tvb, offset); other_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) { other_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); other_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 += 1; num_fields = tvb_get_guint8(tvb, offset); other_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_text(tree, tvb, offset, 1, "Missing %d octet(s) for number of fields", (num_fields + 2) - len); return; } offset += 1; i = 0; while (i < num_fields) { ansi_637_bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f; i += 1; } ansi_637_bigbuf[i] = '\0'; proto_tree_add_text(tree, tvb, offset, num_fields, "Number: %s", ansi_637_bigbuf); } else { offset += 1; num_fields = (oct & 0x7f) << 1; oct2 = tvb_get_guint8(tvb, offset); num_fields |= ((oct2 & 0x80) >> 7); other_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); other_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) { 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 += 1; i = 0; while (i < num_fields) { ansi_637_bigbuf[i] = air_digits[(oct & 0x78) >> 3]; i += 1; if (i >= num_fields) break; oct2 = tvb_get_guint8(tvb, offset); offset += 1; ansi_637_bigbuf[i] = air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)]; oct = oct2; i += 1; } proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset, "Number: %s", ansi_637_bigbuf); } other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x07: 0x7f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } } static void tele_param_disp_mode(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) { guint8 oct; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); oct = tvb_get_guint8(tvb, offset); switch ((oct & 0xc0) >> 6) { case 0: str = "Immediate Display: The mobile station is to display the received message as soon as possible."; break; case 1: str = "Mobile default setting: The mobile station is to display the received message based on a pre-defined mode in the mobile station."; break; case 2: str = "User Invoke: The mobile station is to display the received message based on the mode selected by the user."; break; case 3: str = "Reserved"; break; } other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : %s", ansi_637_bigbuf, str); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", 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, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data) = { tele_param_msg_id, /* 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 */ tele_param_msg_status /* Message status */ }; static void trans_param_tele_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) { guint32 value; const gchar *str = NULL; EXACT_DATA_CHECK(len, 2); value = tvb_get_ntohs(tvb, offset); ansi_637_trans_tele_id = value; str = try_val_to_str(value, ansi_tele_id_strings); if (NULL == str) { switch (value) { case 1: str = "Reserved for maintenance"; break; case 4102: str = "CDMA Service Category Programming Teleservice (SCPT)"; break; case 4103: str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)"; break; case 32513: str = "TDMA Cellular Messaging Teleservice"; break; case 32514: str = "TDMA Cellular Paging Teleservice (CPT-136)"; break; case 32515: str = "TDMA Over-the-Air Activation Teleservice (OATS)"; break; case 32520: str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)"; break; case 32584: str = "TDMA Segmented System Assisted Mobile Positioning Service"; break; default: if ((value >= 2) && (value <= 4095)) { str = "Reserved for assignment by TIA-41"; } else if ((value >= 4104) && (value <= 4113)) { str = "Reserved for GSM1x Teleservice (CDMA)"; } else if ((value >= 4114) && (value <= 32512)) { str = "Reserved for assignment by TIA-41"; } else if ((value >= 32521) && (value <= 32575)) { str = "Reserved for assignment by this Standard for TDMA MS-based SMEs"; } else if ((value >= 49152) && (value <= 65535)) { str = "Reserved for carrier specific teleservices"; } else { str = "Unrecognized Teleservice ID"; } break; } } proto_tree_add_text(tree, tvb, offset, 2, "%s (%d)", str, value); g_snprintf(add_string, string_len, " - %s (%d)", str, value); } static void trans_param_srvc_cat(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) { guint32 value; const gchar *str; EXACT_DATA_CHECK(len, 2); value = tvb_get_ntohs(tvb, offset); str = val_to_str_ext_const(value, &ansi_srvc_cat_strings_ext, "Reserved"); proto_tree_add_text(tree, tvb, offset, 2, "%s", str); g_snprintf(add_string, string_len, " - %s (%d)", str, value); } static void trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_) { guint8 oct, oct2, num_fields, odd; gboolean email_addr; guint32 saved_offset; guint32 required_octs; guint32 i; const gchar *str; SHORT_DATA_CHECK(len, 2); email_addr = FALSE; oct = tvb_get_guint8(tvb, offset); other_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"); other_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; } other_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 += 1; num_fields = (oct & 0x07) << 5; oct2 = tvb_get_guint8(tvb, offset); num_fields |= ((oct2 & 0xf8) >> 3); other_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); other_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; } other_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 += 1; 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 += 1; } 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_trans_bin_addr, tvb, offset, num_fields - 1, (guint8*)ansi_637_bigbuf); } offset += (num_fields - 1); other_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); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } else { other_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); other_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 += 1; oct = oct2; other_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 += 1; num_fields = (oct & 0x7f) << 1; oct2 = tvb_get_guint8(tvb, offset); num_fields |= ((oct2 & 0x80) >> 7); other_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); other_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; } other_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 += 1; 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 += 1; } ansi_637_bigbuf[i] = '\0'; proto_tree_add_text(tree, tvb, offset, num_fields - 1, "Number: %s", ansi_637_bigbuf); offset += (num_fields - 1); other_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); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } } else { offset += 1; num_fields = (oct & 0x3f) << 2; oct2 = tvb_get_guint8(tvb, offset); num_fields |= ((oct2 & 0xc0) >> 6); other_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); other_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 += 1; i = 0; while (i < num_fields) { ansi_637_bigbuf[i] = air_digits[(oct & 0x3c) >> 2]; i += 1; if (i >= num_fields) break; oct2 = tvb_get_guint8(tvb, offset); offset += 1; ansi_637_bigbuf[i] = air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)]; oct = oct2; i += 1; } proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset, "Number: %s", ansi_637_bigbuf); } other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x03: 0x3f, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Reserved", ansi_637_bigbuf); } } static void trans_param_subaddress(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_) { guint8 oct, oct2, num_fields; guint32 i; const gchar *str; SHORT_DATA_CHECK(len, 2); 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; } other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xe0, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Type: %s", ansi_637_bigbuf, str); other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8); proto_tree_add_text(tree, tvb, offset, 1, "%s : Odd", ansi_637_bigbuf); offset += 1; num_fields = (oct & 0x0f) << 4; oct2 = tvb_get_guint8(tvb, offset); num_fields |= ((oct2 & 0xf0) >> 4); other_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); other_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; } other_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 += 1; 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 += 1; } ansi_637_bigbuf[i] = '\0'; proto_tree_add_bytes(tree, hf_ansi_637_trans_bin_addr, tvb, offset, num_fields - 1, (guint8*)ansi_637_bigbuf); offset += (num_fields - 1); other_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); other_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, packet_info *pinfo _U_, proto_tree *tree, guint len _U_, guint32 offset, gchar *add_string, int string_len) { guint8 oct; oct = tvb_get_guint8(tvb, offset); other_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); g_snprintf(add_string, string_len, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2); other_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, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) { guint8 oct; const gchar *str = NULL; oct = tvb_get_guint8(tvb, offset); other_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; } g_snprintf(add_string, string_len, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2); other_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 += 1; 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, "%s", str); } static void trans_param_bearer_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_) { tvbuff_t *tele_tvb; 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_uint(tele_dissector_table, ansi_637_trans_tele_id, tele_tvb, 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, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) = { 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_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset, gboolean* has_private_data) { void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gboolean*) = NULL; guint8 oct; guint8 len; guint32 curr_offset; gint ett_param_idx, idx; proto_tree *subtree; proto_item *item; const gchar *str = NULL; curr_offset = *offset; oct = tvb_get_guint8(tvb, curr_offset); str = try_val_to_str_idx_ext((guint32) oct, &ansi_tele_param_strings_ext, &idx); if (NULL == str) { return(FALSE); } ett_param_idx = ett_ansi_637_tele_param[idx]; param_fcn = ansi_637_tele_param_fcn[idx]; item = proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str); subtree = proto_item_add_subtree(item, ett_param_idx); proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id, tvb, curr_offset, 1, oct); curr_offset += 1; 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_tele_length, tvb, curr_offset, 1, len); curr_offset += 1; if (len > 0) { if (param_fcn == NULL) { proto_tree_add_text(subtree, tvb, curr_offset, len, "Parameter Data"); } else { (*param_fcn)(tvb, pinfo, subtree, len, curr_offset, has_private_data); } curr_offset += len; } *offset = curr_offset; return(TRUE); } static void dissect_ansi_637_tele_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ansi_637_tree, gboolean* has_private_data) { guint8 len; guint32 curr_offset; curr_offset = 0; len = tvb_length(tvb); while ((len - curr_offset) > 0) { if (!dissect_ansi_637_tele_param(tvb, pinfo, ansi_637_tree, &curr_offset, has_private_data)) { proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset, "Unknown Parameter Data"); break; } } } static void dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ansi_637_item; proto_tree *ansi_637_tree = NULL; const gchar *str = NULL; guint32 value; gboolean has_private_data = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short); /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ if (tree) { g_tree = tree; value = pinfo->match_uint; /* * create the ansi_637 protocol tree */ str = try_val_to_str(value, ansi_tele_id_strings); if (NULL == str) { switch (value) { case 1: str = "Reserved for maintenance"; break; case 4102: str = "CDMA Service Category Programming Teleservice (SCPT)"; break; case 4103: str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)"; break; case 32513: str = "TDMA Cellular Messaging Teleservice"; break; case 32514: str = "TDMA Cellular Paging Teleservice (CPT-136)"; break; case 32515: str = "TDMA Over-the-Air Activation Teleservice (OATS)"; break; case 32520: str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)"; break; case 32584: str = "TDMA Segmented System Assisted Mobile Positioning Service"; break; default: if ((value >= 2) && (value <= 4095)) { str = "Reserved for assignment by TIA-41"; } else if ((value >= 4104) && (value <= 4113)) { str = "Reserved for GSM1x Teleservice (CDMA)"; } else if ((value >= 4114) && (value <= 32512)) { str = "Reserved for assignment by TIA-41"; } else if ((value >= 32521) && (value <= 32575)) { str = "Reserved for assignment by this Standard for TDMA MS-based SMEs"; } else if ((value >= 49152) && (value < 65535)) { str = "Reserved for carrier specific teleservices"; } else if (value == 65535) { /* * supposed to be "Reserved for carrier specific teleservices" * but we are using it to key SMS Broadcast dissection where * there is no teleservice ID */ str = "(Reserved) Being used for Broadcast"; } else { str = "Unrecognized Teleservice ID"; } break; } } ansi_637_item = proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1, "%s - %s (%d)", ansi_proto_name_tele, str, pinfo->match_uint); ansi_637_tree = proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele); dissect_ansi_637_tele_message(tvb, pinfo, ansi_637_tree, &has_private_data); } } static gboolean dissect_ansi_637_trans_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset) { void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gchar *, int) = NULL; guint8 oct; guint8 len; guint32 curr_offset; gint ett_param_idx, idx; proto_tree *subtree; proto_item *item; const gchar *str = NULL; curr_offset = *offset; oct = tvb_get_guint8(tvb, curr_offset); str = try_val_to_str_idx((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, "%s", 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 += 1; 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_trans_length, tvb, curr_offset, 1, len); curr_offset += 1; if (len > 0) { if (param_fcn == NULL) { proto_tree_add_text(subtree, tvb, curr_offset, len, "Parameter Data"); } else { gchar *ansi_637_add_string; ansi_637_add_string = (gchar *)wmem_alloc(wmem_packet_scope(), 1024); ansi_637_add_string[0] = '\0'; (*param_fcn)(tvb, pinfo, subtree, len, curr_offset, ansi_637_add_string, 1024); if (ansi_637_add_string[0] != '\0') { proto_item_append_text(item, "%s", 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; const gchar *str = NULL; guint8 oct; guint8 len; col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short); /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ if (tree) { g_tree = tree; /* * reset the teleservice ID for each dissection */ ansi_637_trans_tele_id = 0; /* * create the ansi_637 protocol tree */ oct = tvb_get_guint8(tvb, 0); str = try_val_to_str_idx(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]); if (oct == ANSI_TRANS_MSG_TYPE_BROADCAST) { /* * there is no teleservice ID for Broadcast but we want the * bearer data to be dissected * * using a reserved value to key dissector port */ ansi_637_trans_tele_id = 65535; } } curr_offset = 1; len = tvb_length(tvb); while ((len - curr_offset) > 0) { if (!dissect_ansi_637_trans_param(tvb, pinfo, ansi_637_tree, &curr_offset)) { proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset, "Unknown Parameter Data"); break; } } } } /* 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) { guint i; /* Setup list of header fields */ static hf_register_info hf_trans[] = { #if 0 { &hf_ansi_637_trans_msg_type, { "Message Type", "ansi_637_trans.msg_type", FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000, NULL, HFILL }}, #endif { &hf_ansi_637_trans_param_id, { "Transport Param ID", "ansi_637_trans.param_id", FT_UINT8, BASE_DEC, VALS(ansi_trans_param_strings), 0, NULL, HFILL }}, { &hf_ansi_637_trans_length, { "Length", "ansi_637_trans.len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_ansi_637_trans_bin_addr, { "Binary Address", "ansi_637_trans.bin_addr", FT_BYTES, BASE_NONE, 0, 0, NULL, HFILL }}, }; 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, NULL, HFILL }}, { &hf_ansi_637_tele_msg_id, { "Message ID", "ansi_637_tele.msg_id", FT_UINT24, BASE_DEC, NULL, 0x0ffff0, NULL, HFILL }}, { &hf_ansi_637_tele_msg_status, { "Message Status", "ansi_637_tele.msg_status", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ansi_tele_msg_status_strings_ext, 0, NULL, HFILL }}, { &hf_ansi_637_tele_msg_ind, { "Header Indicator", "ansi_637_tele.msg_ind", FT_UINT24, BASE_DEC, NULL, 0x000008, NULL, HFILL }}, { &hf_ansi_637_tele_msg_rsvd, { "Reserved", "ansi_637_tele.msg_rsvd", FT_UINT24, BASE_DEC, NULL, 0x000007, NULL, HFILL }}, { &hf_ansi_637_tele_length, { "Length", "ansi_637_tele.len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_ansi_637_tele_subparam_id, { "Teleservice Subparam ID", "ansi_637_tele.subparam_id", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ansi_tele_param_strings_ext, 0, NULL, HFILL }}, { &hf_ansi_637_tele_user_data_text, { "Encoded user data", "ansi_637_tele.user_data.text", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, }; /* Setup protocol subtree array */ #define NUM_INDIVIDUAL_PARAMS 3 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_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_TRANS_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_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"); ansi_637_tele_handle = register_dissector("ansi_637_tele", dissect_ansi_637_tele, proto_ansi_637_tele); ansi_637_trans_handle = 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)); proto_register_field_array(proto_ansi_637_trans, hf_trans, array_length(hf_trans)); 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_trans_app_handle; guint i; 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 * * to add teleservices, modify 'ansi_tele_id_strings' */ for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++) { /* * ANSI MAP dissector will push out teleservice ids */ 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_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_uint("ansi_a.sms", 0, ansi_637_trans_handle); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */