diff options
author | Pascal Quantin <pascal.quantin@gmail.com> | 2014-01-09 21:58:09 +0000 |
---|---|---|
committer | Pascal Quantin <pascal.quantin@gmail.com> | 2014-01-09 21:58:09 +0000 |
commit | 70dc6197ec35d99cca2af594fd75c09f12b15bcd (patch) | |
tree | d28fa90922aa7d943920f89cff252f89db236ff0 /epan/dissectors/packet-ansi_637.c | |
parent | f42fa7abf12b4f6a374901ec117081005e2ec0cd (diff) |
From Michael Lum via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9472 :
ANSI IS-637 SMS enhancements for CMAS (TIA-1149) and header dissection
svn path=/trunk/; revision=54684
Diffstat (limited to 'epan/dissectors/packet-ansi_637.c')
-rw-r--r-- | epan/dissectors/packet-ansi_637.c | 3097 |
1 files changed, 2026 insertions, 1071 deletions
diff --git a/epan/dissectors/packet-ansi_637.c b/epan/dissectors/packet-ansi_637.c index a4ed247c61..8edfaf3698 100644 --- a/epan/dissectors/packet-ansi_637.c +++ b/epan/dissectors/packet-ansi_637.c @@ -1,13 +1,21 @@ /* packet-ansi_637.c - * Routines for ANSI IS-637-A (SMS) dissection + * Routines for ANSI IS-637-A/D (SMS) dissection * * Copyright 2003, Michael Lum <mlum [AT] telostech.com> * In association with Telos Technology Inc. + * Copyright 2013, Michael Lum <michael.lum [AT] starsolutions.com> + * In association with Star Solutions, Inc. (Updated for some of IS-637-D and CMAS) * * Title 3GPP2 Other * * Short Message Service * 3GPP2 C.S0015-0 TIA/EIA-637-A + * 3GPP2 C.S0015-C v1.0 TIA/EIA-637-D + * 3GPP2 C.R1001-H v1.0 TSB-58-I (or J?) + * + * For CMAS See: + * TIA-1149.1 or + * (520-10030206__Editor_TIA-1149-0-1_CMASoverCDMA_Publication.pdf) * * $Id$ * @@ -34,54 +42,31 @@ #include <epan/packet.h> #include <epan/wmem/wmem.h> +#include <epan/expert.h> #include <epan/strutil.h> #include <epan/to_str.h> +#include <epan/tfs.h> #include "packet-gsm_sms.h" +#include "packet-ansi_a.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_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); +/* + * Masks the number of bits given by len starting at the given offset + * MBoffset should be from 0 to 7 and MBlen 1 to 8 + * MASK_B(0, 1) = 0x80 + * MASK_B(0, 8) = 0xff + * MASK_B(4, 3) = 0x0e + * MASK_B(7, 1) = 0x01 + */ +#define MASK_B(MBoffset, MBlen) \ + ((0xff >> (MBoffset)) & (0xff << (8 - ((MBoffset) + (MBlen))))) static const value_string ansi_tele_msg_type_strings[] = { { 1, "Deliver (mobile-terminated only)" }, @@ -89,26 +74,35 @@ static const value_string ansi_tele_msg_type_strings[] = { { 3, "Cancellation (mobile-originated only)" }, { 4, "Delivery Acknowledgement (mobile-terminated only)" }, { 5, "User Acknowledgement (either direction)" }, - { 0, NULL }, - }; + { 6, "Read Acknowledgement (either direction)" }, + { 7, "Deliver Report (mobile-originated only)" }, + { 8, "Submit Report (mobile-terminated only)" }, + { 0, NULL } +}; + +static const value_string ansi_tele_msg_header_ind_strings[] = { + { 0, "The User Data field contains only the short message" }, + { 1, "The User Data field contains a Header in addition to the short message" }, + { 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"}, + { 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); @@ -121,10 +115,9 @@ static const value_string ansi_tele_id_strings[] = { { 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 }, - + { 0, NULL } }; +#define INTERNAL_BROADCAST_TELE_ID 65535 static const value_string ansi_tele_param_strings[] = { { 0x00, "Message Identifier" }, @@ -144,8 +137,14 @@ 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 }, + { 0x11, "Message Deposit Index" }, + { 0x12, "Service Category Program Data" }, + { 0x13, "Service Category Program Results" }, + { 0x14, "Message status" }, + { 0x15, "TP-Failure cause" }, + { 0x16, "Enhanced VMN" }, + { 0x17, "Enhanced VMN Ack" }, + { 0, NULL } }; static value_string_ext ansi_tele_param_strings_ext = VALUE_STRING_EXT_INIT(ansi_tele_param_strings); @@ -155,7 +154,7 @@ static const value_string ansi_trans_msg_type_strings[] = { { 0, "Point-to-Point" }, { 1, "Broadcast" }, { 2, "Acknowledge" }, - { 0, NULL }, + { 0, NULL } }; static const value_string ansi_trans_param_strings[] = { @@ -168,7 +167,39 @@ static const value_string ansi_trans_param_strings[] = { { 0x06, "Bearer Reply Option" }, { 0x07, "Cause Codes" }, { 0x08, "Bearer Data" }, - { 0, NULL }, + { 0, NULL } +}; + +static const value_string ansi_tele_month_strings[] = { + { 0, "January" }, + { 1, "February" }, + { 2, "March" }, + { 3, "April" }, + { 4, "May" }, + { 5, "June" }, + { 6, "July" }, + { 7, "August" }, + { 8, "September" }, + { 9, "October" }, + { 10, "November" }, + { 11, "December" }, + { 0, NULL } +}; + +static const value_string ansi_trans_subaddr_odd_even_ind_strings[] = { + { 0x00, "Even" }, + { 0x01, "Odd" }, + { 0, NULL } +}; + +static const true_false_string tfs_digit_mode_8bit_4bit = { + "8-bit ASCII", + "4-bit DTMF" +}; + +static const true_false_string tfs_number_mode_data_ansi_t1 = { + "Data Network Address", + "ANSI T1.607" }; /* @@ -183,24 +214,123 @@ static const unsigned char air_digits[] = { /* 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_param_id = -1; static int hf_ansi_637_trans_length = -1; static int hf_ansi_637_trans_bin_addr = -1; +static int hf_ansi_637_trans_tele_id = -1; +static int hf_ansi_637_trans_srvc_cat = -1; +static int hf_ansi_637_trans_addr_param_digit_mode = -1; +static int hf_ansi_637_trans_addr_param_number_mode = -1; +static int hf_ansi_637_trans_addr_param_ton = -1; +static int hf_ansi_637_trans_addr_param_plan = -1; +static int hf_ansi_637_trans_addr_param_num_fields = -1; +static int hf_ansi_637_trans_addr_param_number = -1; +static int hf_ansi_637_trans_subaddr_type = -1; +static int hf_ansi_637_trans_subaddr_odd_even_ind = -1; +static int hf_ansi_637_trans_subaddr_num_fields = -1; +static int hf_ansi_637_trans_bearer_reply_seq_num = -1; +static int hf_ansi_637_trans_cause_codes_seq_num = -1; +static int hf_ansi_637_trans_cause_codes_error_class = -1; +static int hf_ansi_637_trans_cause_codes_code = -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_length = -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_header_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; +static int hf_ansi_637_tele_user_data_encoding = -1; +static int hf_ansi_637_tele_user_data_message_type = -1; +static int hf_ansi_637_tele_user_data_num_fields = -1; +static int hf_ansi_637_tele_response_code = -1; +static int hf_ansi_637_tele_message_center_ts_year = -1; +static int hf_ansi_637_tele_message_center_ts_month = -1; +static int hf_ansi_637_tele_message_center_ts_day = -1; +static int hf_ansi_637_tele_message_center_ts_hours = -1; +static int hf_ansi_637_tele_message_center_ts_minutes = -1; +static int hf_ansi_637_tele_message_center_ts_seconds = -1; +static int hf_ansi_637_tele_validity_period_ts_year = -1; +static int hf_ansi_637_tele_validity_period_ts_month = -1; +static int hf_ansi_637_tele_validity_period_ts_day = -1; +static int hf_ansi_637_tele_validity_period_ts_hours = -1; +static int hf_ansi_637_tele_validity_period_ts_minutes = -1; +static int hf_ansi_637_tele_validity_period_ts_seconds = -1; +static int hf_ansi_637_tele_validity_period_relative_validity = -1; +static int hf_ansi_637_tele_deferred_del_ts_year = -1; +static int hf_ansi_637_tele_deferred_del_ts_month = -1; +static int hf_ansi_637_tele_deferred_del_ts_day = -1; +static int hf_ansi_637_tele_deferred_del_ts_hours = -1; +static int hf_ansi_637_tele_deferred_del_ts_minutes = -1; +static int hf_ansi_637_tele_deferred_del_ts_seconds = -1; +static int hf_ansi_637_tele_deferred_del_relative = -1; +static int hf_ansi_637_tele_priority_indicator = -1; +static int hf_ansi_637_tele_privacy_indicator = -1; +static int hf_ansi_637_tele_reply_option_user_ack_req = -1; +static int hf_ansi_637_tele_reply_option_dak_req = -1; +static int hf_ansi_637_tele_reply_option_read_ack_req = -1; +static int hf_ansi_637_tele_reply_option_report_req = -1; +static int hf_ansi_637_tele_num_messages = -1; +static int hf_ansi_637_tele_alert_msg_delivery_priority = -1; +static int hf_ansi_637_tele_language = -1; +static int hf_ansi_637_tele_cb_num_digit_mode = -1; +static int hf_ansi_637_tele_cb_num_ton = -1; +static int hf_ansi_637_tele_cb_num_plan = -1; +static int hf_ansi_637_tele_cb_num_num_fields = -1; +static int hf_ansi_637_tele_cb_num_number = -1; +static int hf_ansi_637_tele_msg_display_mode = -1; +static int hf_ansi_637_tele_msg_deposit_idx = -1; +static int hf_ansi_637_tele_srvc_cat_prog_results_srvc_cat = -1; +static int hf_ansi_637_tele_srvc_cat_prog_results_result = -1; +static int hf_ansi_637_tele_msg_status_error_class = -1; +static int hf_ansi_637_tele_msg_status_code = -1; +static int hf_ansi_637_tele_tp_failure_cause_value = -1; +static int hf_ansi_637_reserved_bits_8_generic = -1; +static int hf_ansi_637_reserved_bits_8_03 = -1; +static int hf_ansi_637_reserved_bits_8_07 = -1; +static int hf_ansi_637_reserved_bits_8_0f = -1; +static int hf_ansi_637_reserved_bits_8_3f = -1; +static int hf_ansi_637_reserved_bits_8_7f = -1; +static int hf_ansi_637_tele_cmas_encoding = -1; +static int hf_ansi_637_tele_cmas_num_fields = -1; +static int hf_ansi_637_tele_cmas_protocol_version = -1; +static int hf_ansi_637_tele_cmas_record_type = -1; +static int hf_ansi_637_tele_cmas_record_len = -1; +static int hf_ansi_637_tele_cmas_char_set = -1; +static int hf_ansi_637_tele_cmas_category = -1; +static int hf_ansi_637_tele_cmas_response_type = -1; +static int hf_ansi_637_tele_cmas_severity = -1; +static int hf_ansi_637_tele_cmas_urgency = -1; +static int hf_ansi_637_tele_cmas_certainty = -1; +static int hf_ansi_637_tele_cmas_identifier = -1; +static int hf_ansi_637_tele_cmas_alert_handling = -1; +static int hf_ansi_637_tele_cmas_expires_year = -1; +static int hf_ansi_637_tele_cmas_expires_month = -1; +static int hf_ansi_637_tele_cmas_expires_day = -1; +static int hf_ansi_637_tele_cmas_expires_hours = -1; +static int hf_ansi_637_tele_cmas_expires_minutes = -1; +static int hf_ansi_637_tele_cmas_expires_seconds = -1; +static int hf_ansi_637_tele_cmas_language = -1; /* Initialize the subtree pointers */ static gint ett_ansi_637_tele = -1; static gint ett_ansi_637_trans = -1; +static gint ett_ansi_637_header_ind = -1; static gint ett_params = -1; +static expert_field ei_ansi_637_extraneous_data = EI_INIT; +static expert_field ei_ansi_637_short_data = EI_INIT; +static expert_field ei_ansi_637_unexpected_length = EI_INIT; +static expert_field ei_ansi_637_unknown_encoding = EI_INIT; +static expert_field ei_ansi_637_failed_conversion = EI_INIT; +static expert_field ei_ansi_637_unknown_cmas_record_type = EI_INIT; +static expert_field ei_ansi_637_unknown_trans_parameter = EI_INIT; +static expert_field ei_ansi_637_no_trans_parameter_dissector = EI_INIT; +static expert_field ei_ansi_637_unknown_tele_parameter = EI_INIT; +static expert_field ei_ansi_637_no_tele_parameter_dissector = EI_INIT; + static dissector_handle_t ansi_637_tele_handle; static dissector_handle_t ansi_637_trans_handle; @@ -212,20 +342,22 @@ static proto_tree *g_tree; /* FUNCTIONS */ +/* + * last_bit must be from 1 to 8 + * '1' means there is one bit remaining in 'last_oct' (i.e. 0x01) + * '3' means there are 3 bits remaining in 'last_oct' (i.e. 0x07) + */ 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; - + guint8 oct, oct2, bit; + guint32 i; if (num_fields == 0) { return 0; } - /* saved_offset = *offset; */ oct = oct2 = *last_oct; bit = *last_bit; @@ -295,6 +427,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; } @@ -303,573 +436,875 @@ decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oc #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"); \ + proto_tree_add_expert(tree, pinfo, &ei_ansi_637_extraneous_data, \ + tvb, offset, (edc_len) - (edc_max_len)); \ } #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \ if ((sdc_len) < (sdc_min_len)) \ { \ - proto_tree_add_text(tree, tvb, offset, \ - (sdc_len), "Short Data (?)"); \ + proto_tree_add_expert(tree, pinfo, &ei_ansi_637_short_data, \ + tvb, offset, (sdc_len)); \ 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"); \ + proto_tree_add_expert(tree, pinfo, &ei_ansi_637_unexpected_length, \ + tvb, offset, (edc_len)); \ return; \ } +/* + * text decoding helper + * + * there are 'unused_bits' bits remaining in the octet at 'offset' + */ static void -tele_param_msg_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data) +text_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 encoding, guint8 num_fields, guint16 num_bits, guint8 unused_bits, guint8 fill_bits) { - EXACT_DATA_CHECK(len, 3); + guint8 oct; + guint8 bit; + guint32 required_octs; + guint32 out_len; + const gchar *str = NULL; + tvbuff_t *tvb_out = NULL; - proto_tree_add_item(tree, hf_ansi_637_tele_msg_type, tvb, offset, 3, ENC_BIG_ENDIAN); + GIConv cd; + GError *l_conv_error = NULL; + gchar *ustr = NULL; - proto_tree_add_item(tree, hf_ansi_637_tele_msg_id, tvb, offset, 3, ENC_BIG_ENDIAN); + /* + * has to be big enough to hold all of the 'shifted' bits + */ + required_octs = (num_bits + fill_bits + 7) / 8; - 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; - } + /* + * shift the bits to octet alignment in 'buf' + */ + tvb_out = + tvb_new_octet_aligned(tvb, (offset * 8) + (8 - unused_bits), (required_octs * 8)); + add_new_data_source(pinfo, tvb_out, "Characters"); - proto_tree_add_item(tree, hf_ansi_637_tele_msg_rsvd, tvb, offset, 3, ENC_BIG_ENDIAN); + switch (encoding) + { + default: + proto_tree_add_expert(tree, pinfo, &ei_ansi_637_unknown_encoding, tvb, offset, required_octs); + return; + + case 0x02: /* 7-bit ASCII */ + + offset = 0; + oct = tvb_get_guint8(tvb_out, offset); + offset += 1; + bit = 8; + + (void) decode_7_bits(tvb_out, &offset, num_fields, &oct, &bit, ansi_637_bigbuf); + + proto_tree_add_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, 0, + offset, ansi_637_bigbuf); + break; + + case 0x03: /* IA5 */ + + offset = 0; + oct = tvb_get_guint8(tvb_out, offset); + offset += 1; + bit = 8; + + 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_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, 0, + offset, ia5_637_bigbuf); + break; + + case 0x09: /* GSM 7-bit default alphabet */ + + offset = 0; + bit = fill_bits; + + proto_tree_add_ts_23_038_7bits_item(tree, hf_ansi_637_tele_user_data_text, tvb_out, (offset << 3) + bit, num_fields); + break; + + case 0x04: /* UNICODE */ + + proto_tree_add_item(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, num_fields*2, ENC_UCS_2|ENC_BIG_ENDIAN); + break; + + case 0x10: /* KSC5601 (Korean) */ + + if (str == NULL) str = "EUC-KR"; + + /* FALLTHROUGH */ + + case 0x07: /* Latin/Hebrew */ + + if (str == NULL) str = "iso-8859-8"; + + /* FALLTHROUGH */ + + case 0x08: /* Latin */ + + if (str == NULL) str = "iso-8859-1"; + + offset = 0; + + if ((cd = g_iconv_open("UTF-8", str)) != (GIConv) -1) + { + ustr = 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_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, + required_octs, ustr); + } + else + { + proto_tree_add_expert_format(tree, pinfo, &ei_ansi_637_failed_conversion, tvb_out, offset, required_octs, + "Failed iconv conversion on %s - (report to wireshark.org)", + str); + } + if (ustr) + { + g_free(ustr); + } + g_iconv_close(cd); + } + break; + } } -/* 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_) +tele_param_timestamp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, int hf_year, int hf_month, int hf_day, int hf_hours, int hf_minutes, int hf_seconds) { - /* Declare some variables */ - guint8 oct; - guint8 error_class; - guint8 msg_status_code; + guint8 oct; + guint16 temp; const gchar *str = NULL; - /* Chceck if the exact length */ - EXACT_DATA_CHECK(len, 1); + EXACT_DATA_CHECK(len, 6); + + oct = tvb_get_guint8(tvb, offset); + + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f); + temp += ((temp < 96) ? 2000 : 1900); + + proto_tree_add_uint_format_value(tree, hf_year, tvb, offset, 1, + oct, + "%u (%02x)", + temp, oct); - /* get the status octet? */ + offset += 1; oct = tvb_get_guint8(tvb, offset); + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f) - 1; - /* error class filter */ - proto_tree_add_item(tree, hf_ansi_637_tele_msg_status,tvb, offset, 1, ENC_BIG_ENDIAN); + str = val_to_str_const(temp, ansi_tele_month_strings, "Invalid"); + proto_tree_add_uint_format_value(tree, hf_month, tvb, offset, 1, + oct, + "%s (%02x)", + str, oct); - /*error class filter end */ + offset += 1; + oct = tvb_get_guint8(tvb, offset); -/*error class */ + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f); - 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); + proto_tree_add_uint_format_value(tree, hf_day, tvb, offset, 1, + oct, + "%u", + temp); + offset += 1; + oct = tvb_get_guint8(tvb, offset); - msg_status_code = (oct & 0x3f); + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f); - 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); - } + proto_tree_add_uint_format_value(tree, hf_hours, tvb, offset, 1, + oct, + "%u", + temp); -/*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); - } + offset += 1; - 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); + oct = tvb_get_guint8(tvb, offset); + + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f); + + proto_tree_add_uint_format_value(tree, hf_minutes, tvb, offset, 1, oct, + "%u", + temp); + + offset += 1; + + oct = tvb_get_guint8(tvb, offset); + + temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f); + + proto_tree_add_uint_format_value(tree, hf_seconds, tvb, offset, 1, + oct, + "%u", + temp); +} + +static void +tele_param_msg_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p) +{ + 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_header_ind, tvb, offset, 3, ENC_BIG_ENDIAN); + if ((tvb_get_guint8(tvb, offset + 2) & 0x08) == 0x08) + { + *has_private_data_p = TRUE; } + + proto_tree_add_item(tree, hf_ansi_637_tele_msg_rsvd, tvb, offset, 3, ENC_BIG_ENDIAN); } +/* + * for record types 0, 1, 2 and 3 for unknowns + */ +#define NUM_CMAS_PARAM 4 +static gint ett_tia_1149_cmas_param[NUM_CMAS_PARAM]; + +/* + * Special dissection for CMAS Message as defined in TIA-1149 + */ +static const value_string cmas_category_strings[] = { + { 0x00, "Geo (Geophysical including landslide)" }, + { 0x01, "Met (Meteorological including flood)" }, + { 0x02, "Safety (General emergency and public safety)" }, + { 0x03, "Security (Law enforcement, military, homeland and local/private security)" }, + { 0x04, "Rescue (Rescue and recovery)" }, + { 0x05, "Fire (Fire suppression and rescue)" }, + { 0x06, "Health (Medical and public health)" }, + { 0x07, "Env (Pollution and other environmental)" }, + { 0x08, "Transport (Public and private transportation)" }, + { 0x09, "Infra (Utility, telecommunication, other nontransport infrastructure)" }, + { 0x0a, "CBRNE (Chemical, Biological, Radiological, Nuclear or High-Yield Explosive threat or attack)" }, + { 0x0b, "Other (Other events)" }, + { 0, NULL } +}; + +static const value_string cmas_response_type_strings[] = { + { 0x00, "Shelter (Take shelter in place)" }, + { 0x01, "Evacuate (Relocate)" }, + { 0x02, "Prepare (Make preparations)" }, + { 0x03, "Execute (Execute a pre-planned activity)" }, + { 0x04, "Monitor (Attend to information sources)" }, + { 0x05, "Avoid (Avoid hazard)" }, + { 0x06, "Assess (Evaluate the information in this message. This value SHOULD NOT be used in public warning applications.)" }, + { 0x07, "None (No action recommended)" }, + { 0, NULL } +}; + +static const value_string cmas_severity_strings[] = { + { 0x00, "Extreme (Extraordinary threat to life or property)" }, + { 0x01, "Severe (Significant threat to life or property)" }, + { 0, NULL } +}; + +static const value_string cmas_urgency_strings[] = { + { 0x00, "Immediate (Responsive action should be taken immediately)" }, + { 0x01, "Expected (Responsive action should be taken soon - within the next hour)" }, + { 0, NULL } +}; + +static const value_string cmas_certainty_strings[] = { + { 0x00, "Observed (Determined to have occurred or to be ongoing)" }, + { 0x01, "Likely (Likely. Probability > ~50%)" }, + { 0, NULL } +}; static void -tele_param_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data) +tele_param_user_data_cmas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - 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; + proto_tree *subtree; + proto_item *item; + guint8 bit_mask_8; + guint8 oct, oct2; + guint8 encoding; + guint8 num_fields; + guint8 reserved_bits; + guint8 unused_bits; + guint8 record_type; + guint8 record_len; + guint8 subtree_idx; + guint16 num_bits; + guint32 value; + guint32 temp_offset; + guint32 required_octs; tvbuff_t *tvb_out = NULL; - gsm_sms_udh_fields_t udh_fields; - - gchar *utf8_text = NULL; - GIConv cd; - GError *l_conv_error = NULL; + const gchar *str = NULL; SHORT_DATA_CHECK(len, 2); - memset(&udh_fields, 0, sizeof(udh_fields)); + value = tvb_get_ntohs(tvb, offset); /* - * message encoding + * must be encoded as 'Octet, unspecified' */ - oct = tvb_get_guint8(tvb, offset); - oct2 = 0; - msg_type = 0; - used = 0; - - encoding = ((oct & 0xf8) >> 3); - switch (encoding) + if ((value & 0xf800) != 0) { - 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; + proto_tree_add_expert(tree, pinfo, &ei_ansi_637_unknown_encoding, tvb, offset, len); + return; } - 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); + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_cmas_encoding, tvb, offset, 2, + value, + "%s (%u)", + val_to_str_const((value & 0xf800) >> 11, ansi_tsb58_encoding_vals, "Error"), + (value & 0xf800) >> 11); - 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); + proto_tree_add_item(tree, hf_ansi_637_tele_cmas_num_fields, tvb, offset, 2, ENC_BIG_ENDIAN); - oct = oct2; - offset += 1; - used += 1; - } + num_fields = (value & 0x07f8) >> 3; - offset += 1; - used += 1; + offset += 2; - /* - * number of fields - */ - oct2 = tvb_get_guint8(tvb, offset); - num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); + /* NOTE: there are now 3 bits remaining in 'value' */ - 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); + unused_bits = 3; - 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); + required_octs = num_fields; - 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); + tvb_out = + tvb_new_octet_aligned(tvb, ((offset - 1) * 8) + (8 - unused_bits), (required_octs * 8)); + add_new_data_source(pinfo, tvb_out, "CMAS Message"); - offset += 1; - used += 1; - oct = oct2; + temp_offset = offset; + offset = 0; - /* NOTE: there are now 3 bits remaining in 'oct' */ + proto_tree_add_item(tree, hf_ansi_637_tele_cmas_protocol_version, tvb_out, offset, 1, ENC_BIG_ENDIAN); - if (len <= used) return; + offset += 1; - /* - * decode rest if 7-bit ASCII - */ - if (encoding == 0x02) + while ((required_octs - offset) > 2) { - /* - * 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); + record_type = tvb_get_guint8(tvb_out, offset); + subtree_idx = record_type; - if (required_octs + used > len) + switch (record_type) { - proto_tree_add_text(tree, tvb, offset, 1, - "Missing %d octet(s) for number of fields", - (required_octs + used) - len); - - return; + default: str = "Reserved"; subtree_idx = 3; break; + case 0x00: str = "Type 0 Elements (Alert Text)"; break; + case 0x01: str = "Type 1 Elements"; break; + case 0x02: str = "Type 2 Elements"; break; } - 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, &udh_fields); - } + record_len = tvb_get_guint8(tvb_out, offset + 1); + + item = + proto_tree_add_text(tree, tvb_out, offset, record_len + 2, + "%s", + str); + + subtree = proto_item_add_subtree(item, ett_tia_1149_cmas_param[subtree_idx]); + + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_record_type, tvb_out, offset, 1, + record_type, + "%s", + str); - 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_uint_format_value(subtree, hf_ansi_637_tele_cmas_record_len, tvb_out, offset, 1, + record_len, + "%u", + record_len); - proto_tree_add_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, saved_offset, - offset - saved_offset, ansi_637_bigbuf); + offset += 1; - switch (bit) + switch (record_type) { - 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; - } + default: + proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_unknown_cmas_record_type, tvb_out, offset, record_len); - 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); + offset += record_len; + break; + + case 0x00: + encoding = (tvb_get_guint8(tvb_out, offset) & 0xf8) >> 3; + + str = val_to_str_const(encoding, ansi_tsb58_encoding_vals, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_char_set, tvb_out, offset, 1, + encoding, + "%s (%u)", + str, encoding); + + num_bits = (record_len * 8) - 5; + + switch (encoding) + { + case 0x04: /* UNICODE */ + /* 16-bit encodings */ + num_fields = num_bits / 16; + reserved_bits = 3; + break; + + case 0x00: /* Octet, unspecified */ + case 0x10: /* KSC5601 (Korean) */ + case 0x07: /* Latin/Hebrew */ + case 0x08: /* Latin */ + /* 8-bit encodings */ + num_fields = num_bits / 8; + reserved_bits = 3; + break; + + default: + /* 7-bit encodings */ + num_fields = num_bits / 7; + + if ((num_bits % 7) == 0) + { + oct2 = tvb_get_guint8(tvb_out, offset + record_len - 1); + if ((oct2 & 0x7f) == 0) + { + /* + * the entire last 7 bits are reserved + */ + num_fields--; + } + } + + reserved_bits = num_bits - (num_fields * 7); + break; + } + + temp_offset = offset; + text_decoder(tvb_out, pinfo, subtree, temp_offset, encoding, num_fields, + num_bits, 3 /* (5 bits used from 'temp_offset' octet for encoding */, 0); + + offset += (record_len - 1); + + if (reserved_bits > 0) + { + oct = tvb_get_guint8(tvb_out, offset); + + bit_mask_8 = MASK_B(8 - reserved_bits, reserved_bits); + + other_decode_bitfield_value(ansi_637_bigbuf, oct, bit_mask_8, 8); + proto_tree_add_uint_format(subtree, hf_ansi_637_reserved_bits_8_generic, tvb_out, offset, 1, + oct & bit_mask_8, + "%s = Reserved bit(s)", + ansi_637_bigbuf); + } + + offset += 1; + break; + + case 0x01: + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_const(oct, cmas_category_strings, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_category, tvb_out, offset, 1, + oct, + "%s (%u)", + str, oct); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_const(oct, cmas_response_type_strings, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_response_type, tvb_out, offset, 1, + oct, + "%s (%u)", + str, oct); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_const((oct & 0xf0) >> 4, cmas_severity_strings, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_severity, tvb_out, offset, 1, + oct, + "%s (%u)", + str, (oct & 0xf0) >> 4); + + str = val_to_str_const(oct & 0x0f, cmas_urgency_strings, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_urgency, tvb_out, offset, 1, + oct, + "%s (%u)", + str, oct & 0x0f); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_const((oct & 0xf0) >> 4, cmas_certainty_strings, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_certainty, tvb_out, offset, 1, + oct, + "%s (%u)", + str, (oct & 0xf0) >> 4); + + proto_tree_add_item(subtree, hf_ansi_637_reserved_bits_8_0f, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + break; + + case 0x02: + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_identifier, tvb_out, offset, 2, ENC_BIG_ENDIAN); + + offset += 2; + + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_alert_handling, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + /* + * TIA-1149 does not say whether this should be encoded in the same way as IS-637 + * I.e. year = oct + ((oct < 96) ? 2000 : 1900); + */ + value = oct + ((oct < 96) ? 2000 : 1900); + + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_expires_year, tvb_out, offset, 1, + oct, + "%u (%02x)", + value, oct); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_const(oct - 1, ansi_tele_month_strings, "Invalid"); + + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_expires_month, tvb_out, offset, 1, + oct, + "%s (%02x)", + str, oct); + + offset += 1; + + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_expires_day, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_expires_hours, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_expires_minutes, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + proto_tree_add_item(subtree, hf_ansi_637_tele_cmas_expires_seconds, tvb_out, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + oct = tvb_get_guint8(tvb_out, offset); + + str = val_to_str_ext_const(oct, &ansi_tsb58_language_ind_vals_ext, "Reserved"); + proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_language, tvb_out, offset, 1, + oct, + "%s (%u)", + str, oct); + + offset += 1; + break; } } - 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); + EXTRANEOUS_DATA_CHECK(required_octs, offset); - return; - } + offset += temp_offset; /* move 'offset' back to the correct spot in 'tvb' */ - 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, &udh_fields); - } - 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_item(tree, hf_ansi_637_reserved_bits_8_07, tvb, offset, 1, ENC_BIG_ENDIAN); +} - proto_tree_add_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, - saved_offset, offset - saved_offset, ia5_637_bigbuf); +static void +tele_param_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p) +{ + guint8 oct; + guint8 bit_mask_8; + guint8 encoding; + guint8 encoding_bit_len; + guint8 num_fields; + guint8 unused_bits; + guint8 fill_bits; + guint16 reserved_bits; + guint32 value; + guint32 orig_offset; + guint32 saved_offset; + guint32 required_octs; + const gchar *str = NULL; + tvbuff_t *tvb_out = NULL; + enum character_set cset; - } - else if (encoding == 0x04)/* UCS-2 (not UTF-16?) */ + SHORT_DATA_CHECK(len, 2); + + orig_offset = offset; + reserved_bits = len * 8; + + value = tvb_get_ntohs(tvb, offset); + + encoding_bit_len = 7; + cset = ASCII_7BITS; + + encoding = (guint8) ((value & 0xf800) >> 11); + switch (encoding) { - 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, &udh_fields); - } + case 0x00: + str = "Octet, unspecified"; + encoding_bit_len = 8; + cset = OTHER; + break; - proto_tree_add_item(tree, hf_ansi_637_tele_user_data_text, - tvb_out, offset, num_fields*2, ENC_UCS_2|ENC_BIG_ENDIAN); + case 0x01: + str = "Extended Protocol Message"; + break; + + case 0x02: + str = "7-bit ASCII"; + break; + + case 0x03: + str = "IA5"; + break; + + case 0x04: + str = "UNICODE"; + encoding_bit_len = 16; + cset = OTHER; + break; + + case 0x05: + str = "Shift-JIS"; + break; + + case 0x06: + str = "Korean"; + cset = OTHER; + break; + + case 0x07: + str = "Latin/Hebrew"; + encoding_bit_len = 8; + cset = OTHER; + break; + + case 0x08: + str = "Latin"; + encoding_bit_len = 8; + cset = OTHER; + break; + + case 0x09: + str = "GSM 7-bit default alphabet"; + cset = GSM_7BITS; + break; + + case 0x10: + str = "KSC5601 (Korean)"; + encoding_bit_len = 8; + cset = OTHER; + break; + + default: + str = "Reserved"; + break; } - else if (encoding == 0x07)/* Latin/Hebrew */ + + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_user_data_encoding, tvb, offset, 2, + value, + "%s (%u)", + str, + encoding); + + reserved_bits -= 5; + + if (encoding == 0x01) { - 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, &udh_fields); - } + proto_tree_add_item(tree, hf_ansi_637_tele_user_data_message_type, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(tree, hf_ansi_637_tele_user_data_text, - tvb_out, offset, num_fields, ENC_ISO_8859_8|ENC_NA); + offset += 1; + value = tvb_get_ntohs(tvb, offset); + + reserved_bits -= 8; } - else if (encoding == 0x08) /* ISO 8859-1 (a/k/a ISO Latin 1) */ + + proto_tree_add_item(tree, hf_ansi_637_tele_user_data_num_fields, tvb, offset, 2, ENC_BIG_ENDIAN); + + offset += 1; + + num_fields = (value & 0x07f8) >> 3; + + reserved_bits -= 8 + (num_fields * encoding_bit_len); + + /* NOTE: there are now 3 bits remaining in 'value' */ + + unused_bits = 3; + fill_bits = 0; + + /* + * ALL of this is for header support ! + */ + if (*has_private_data_p == TRUE) { - saved_offset = offset - 1; - buf = (gchar*)wmem_alloc(pinfo->pool, num_fields); - for (i=0; i < num_fields; i++) + gsm_sms_udh_fields_t udh_fields; + gint32 num_udh_bits; + + memset(&udh_fields, 0, sizeof(udh_fields)); + + value = tvb_get_ntohs(tvb, offset); + + /* + * 'length' split across two octets +1 for the length octet itself + * (dis_field_udh() will start at the length offset) + */ + required_octs = ((value & 0x07f8) >> 3) + 1; + + /* + * need fill bits + */ + if (encoding_bit_len == 7) { - 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; + /* + * not the same formula as dis_field_udh() because we are including + * the length octet in the calculation but the result is the same + */ + fill_bits = 7 - ((required_octs * 8) % 7); } - tvb_out = tvb_new_child_real_data(tvb, buf, num_fields, num_fields); - add_new_data_source(pinfo, tvb_out, "Characters"); + + num_udh_bits = (required_octs * 8) + fill_bits; + + tvb_out = + tvb_new_octet_aligned(tvb, (offset * 8) + (8 - unused_bits), num_udh_bits); + add_new_data_source(pinfo, tvb_out, "Header"); + + saved_offset = offset + required_octs; + offset = 0; - required_octs = len - used; - if (*has_private_data == TRUE) { - dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, OTHER, &bit, &udh_fields); - } + fill_bits = 0; + dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, cset, &fill_bits, &udh_fields); - proto_tree_add_item(tree, hf_ansi_637_tele_user_data_text, - tvb_out, offset, num_fields, ENC_ISO_8859_1|ENC_NA); - } - else if (encoding == 0x09) /* GSM 7-bit default alphabet */ - { - i = (num_fields * 7) - 3; - required_octs = (i / 8) + ((i % 8) ? 1 : 0); + offset = saved_offset; - if (required_octs + used > len) + if (encoding_bit_len == 7) { - proto_tree_add_text(tree, tvb, offset, 1, - "Missing %d octet(s) for number of fields", - (required_octs + used) - len); + switch (cset) + { + case GSM_7BITS: + case OTHER: + break; + + case ASCII_7BITS: + if (fill_bits > unused_bits) + { + /* this branch was NOT tested */ - return; + offset += 1; + unused_bits = 8 - (fill_bits - unused_bits); + } + else if (fill_bits > 0) + { + /* this branch was tested */ + unused_bits = unused_bits - fill_bits; + } + + if (unused_bits == 0) + { + /* this branch was NOT tested */ + + offset += 1; + unused_bits = 8; + } + break; + } } - 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++) + if (udh_fields.frags > 0) { - 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; + col_append_fstr(pinfo->cinfo, COL_INFO, " (Short Message fragment %u of %u)", udh_fields.frag, udh_fields.frags); } - 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, &udh_fields); - } - - proto_tree_add_ts_23_038_7bits_item(tree, hf_ansi_637_tele_user_data_text, tvb_out, (offset<<3)+bit, num_fields); } - else if (encoding == 0x10)/* KSC5601 (Korean) */ + + text_decoder(tvb, pinfo, tree, offset, encoding, num_fields, + num_fields * encoding_bit_len, unused_bits, fill_bits); + + if (reserved_bits > 0) { - 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, &udh_fields); - } + /* + * unlike for CMAS, the bits that can be reserved will always be + * at the end of an octet so we don't have to worry about them + * spanning two octets + */ - if ((cd = g_iconv_open("UTF-8","EUC-KR")) != (GIConv)-1) + switch (cset) { - 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_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); + case GSM_7BITS: + bit_mask_8 = MASK_B(0, reserved_bits); /* MSBs */ + break; + + default: + bit_mask_8 = MASK_B(8 - reserved_bits, reserved_bits); /* LSBs */ + break; } - } - else - { - proto_tree_add_text(tree, tvb, offset, len - used, - "Encoded user data"); + + oct = tvb_get_guint8(tvb, orig_offset + len - 1); + + other_decode_bitfield_value(ansi_637_bigbuf, oct, bit_mask_8, 8); + proto_tree_add_uint_format(tree, hf_ansi_637_reserved_bits_8_generic, tvb, orig_offset + len - 1, 1, + oct & bit_mask_8, + "%s = Reserved bit(s)", + ansi_637_bigbuf); } } 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_) +tele_param_rsp_code(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _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); + proto_tree_add_item(tree, hf_ansi_637_tele_response_code, tvb, offset, 1, ENC_BIG_ENDIAN); } static void -tele_param_timestamp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) +tele_param_message_center_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _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); + tele_param_timestamp(tvb, pinfo, tree, len, offset, + hf_ansi_637_tele_message_center_ts_year, + hf_ansi_637_tele_message_center_ts_month, + hf_ansi_637_tele_message_center_ts_day, + hf_ansi_637_tele_message_center_ts_hours, + hf_ansi_637_tele_message_center_ts_minutes, + hf_ansi_637_tele_message_center_ts_seconds); +} - offset += 3; +static void +tele_param_validity_period_abs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + 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, - "Hour %d%d, Minutes %d%d, Seconds %d%d", - (oct & 0xf0) >> 4, - oct & 0x0f, - (oct2 & 0xf0) >> 4, - oct2 & 0x0f, - (oct3 & 0xf0) >> 4, - oct3 & 0x0f); + tele_param_timestamp(tvb, pinfo, tree, len, offset, + hf_ansi_637_tele_validity_period_ts_year, + hf_ansi_637_tele_validity_period_ts_month, + hf_ansi_637_tele_validity_period_ts_day, + hf_ansi_637_tele_validity_period_ts_hours, + hf_ansi_637_tele_validity_period_ts_minutes, + hf_ansi_637_tele_validity_period_ts_seconds); } 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_) +tele_param_timestamp_rel(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len _U_, guint32 offset, int hf) { - guint8 oct; - guint32 value = 0; - const gchar *str = NULL; - const gchar *str2 = NULL; - - EXACT_DATA_CHECK(len, 1); + guint8 oct; + guint32 value = 0; + const gchar *str = NULL; + const gchar *str2 = NULL; oct = tvb_get_guint8(tvb, offset); @@ -887,262 +1322,207 @@ tele_param_rel_timestamp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree else { str = "Reserved"; break; } } - if (str == NULL) + if (str != NULL) { - proto_tree_add_text(tree, tvb, offset, 1, - "%s", str2); + proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1, + oct, + "%s", + str); } else { - proto_tree_add_text(tree, tvb, offset, 1, - "%d %s", + proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1, + oct, + "%u %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_) +tele_param_validity_period_rel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _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"); + tele_param_timestamp_rel(tvb, pinfo, tree, len, offset, hf_ansi_637_tele_validity_period_relative_validity); +} - other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); - proto_tree_add_text(tree, tvb, offset, 1, - "%s : %s", - ansi_637_bigbuf, - str); +static void +tele_param_deferred_del_abs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 6); - other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); - proto_tree_add_text(tree, tvb, offset, 1, - "%s : Reserved", - ansi_637_bigbuf); + tele_param_timestamp(tvb, pinfo, tree, len, offset, + hf_ansi_637_tele_deferred_del_ts_year, + hf_ansi_637_tele_deferred_del_ts_month, + hf_ansi_637_tele_deferred_del_ts_day, + hf_ansi_637_tele_deferred_del_ts_hours, + hf_ansi_637_tele_deferred_del_ts_minutes, + hf_ansi_637_tele_deferred_del_ts_seconds); } 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_) +tele_param_deferred_del_rel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _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); + tele_param_timestamp_rel(tvb, pinfo, tree, len, offset, hf_ansi_637_tele_deferred_del_relative); } +static const value_string tele_param_priority_ind_strings[] = { + { 0, "Normal" }, + { 1, "Interactive" }, + { 2, "Urgent" }, + { 3, "Emergency" }, + { 0, NULL } +}; + 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_) +tele_param_pri_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - guint8 oct; - EXACT_DATA_CHECK(len, 1); - oct = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_ansi_637_tele_priority_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_3f, tvb, offset, 1, ENC_BIG_ENDIAN); +} - 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"); +static const value_string tele_param_privacy_ind_strings[] = { + { 0, "Not restricted (privacy level 0)" }, + { 1, "Restricted (privacy level 1)" }, + { 2, "Confidential (privacy level 2)" }, + { 3, "Secret (privacy level 3)" }, + { 0, NULL } +}; - 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"); +static void +tele_param_priv_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 1); - other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8); - proto_tree_add_text(tree, tvb, offset, 1, - "%s : Reserved", - ansi_637_bigbuf); + proto_tree_add_item(tree, hf_ansi_637_tele_privacy_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_3f, tvb, offset, 1, ENC_BIG_ENDIAN); } 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_) +tele_param_reply_opt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _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); + proto_tree_add_item(tree, hf_ansi_637_tele_reply_option_user_ack_req, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_tele_reply_option_dak_req, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_tele_reply_option_read_ack_req, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_tele_reply_option_report_req, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_0f, tvb, offset, 1, ENC_BIG_ENDIAN); } static void -tele_param_alert(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean* has_private_data _U_) +tele_param_num_messages(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - guint8 oct; - const gchar *str = NULL; + guint8 oct; 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; - } + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_num_messages, tvb, offset, 1, + ((oct & 0xf0) >> 4) * 10 + (oct & 0x0f), + "%u%u", + (oct & 0xf0) >> 4, oct & 0x0f); +} - other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8); - proto_tree_add_text(tree, tvb, offset, 1, - "%s : %s", - ansi_637_bigbuf, - str); +static const value_string tele_param_alert_priority_strings[] = { + { 0, "Use Mobile default alert" }, + { 1, "Use Low-priority alert" }, + { 2, "Use Medium-priority alert" }, + { 3, "Use High-priority alert" }, + { 0, NULL } +}; - 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_alert(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 1); + + proto_tree_add_item(tree, hf_ansi_637_tele_alert_msg_delivery_priority, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_3f, tvb, offset, 1, ENC_BIG_ENDIAN); } 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_) +tele_param_lang_ind(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - guint8 oct; + 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); + str = val_to_str_ext_const(oct, &ansi_tsb58_language_ind_vals_ext, "Reserved"); + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_language, tvb, offset, 1, + oct, + "%s (%u)", + str, oct); } 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_) +tele_param_cb_num(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - guint8 oct, oct2, num_fields, odd; - guint32 saved_offset; - guint32 required_octs; - guint32 i; + guint8 oct, oct2, num_fields, odd; + guint8 *poctets; + guint32 saved_offset; + guint32 required_octs; + guint32 i; SHORT_DATA_CHECK(len, 2); - oct = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_digit_mode, tvb, offset, 1, ENC_BIG_ENDIAN); - 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"); + oct = tvb_get_guint8(tvb, offset); 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); + proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_ton, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_plan, tvb, offset, 1, ENC_BIG_ENDIAN); 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); + proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_num_fields, tvb, offset, 1, ENC_BIG_ENDIAN); - if (num_fields == 0) return; + num_fields = tvb_get_guint8(tvb, offset); - 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); + if (num_fields == 0) return; - return; - } + SHORT_DATA_CHECK(len - 2, num_fields); 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'; + poctets = tvb_get_string(wmem_packet_scope(), tvb, offset, num_fields); - proto_tree_add_text(tree, tvb, offset, num_fields, + proto_tree_add_string_format(tree, hf_ansi_637_tele_cb_num_number, tvb, offset, num_fields, + (gchar *) poctets, "Number: %s", - ansi_637_bigbuf); + (gchar *) format_text(poctets, num_fields)); } else { offset += 1; - num_fields = (oct & 0x7f) << 1; + oct2 = tvb_get_guint8(tvb, offset); - num_fields |= ((oct2 & 0x80) >> 7); + num_fields = ((oct & 0x7f) << 1) | ((oct2 & 0x80) >> 7); + /* + * not combined into a 16-bit field because hf_ansi_637_tele_cb_num_num_fields is used above + * and uses a different bitmask + */ 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)", + proto_tree_add_uint_format(tree, hf_ansi_637_tele_cb_num_num_fields, tvb, offset, 1, + num_fields, + "%s = Number of fields (MSB): %u", 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)", + "%s = Number of fields (LSB)", ansi_637_bigbuf); oct = oct2; @@ -1153,14 +1533,7 @@ tele_param_cb_num(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint 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; - } + SHORT_DATA_CHECK(len - 2, required_octs); odd = num_fields & 0x01; memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf)); @@ -1170,8 +1543,7 @@ tele_param_cb_num(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint i = 0; while (i < num_fields) { - ansi_637_bigbuf[i] = - air_digits[(oct & 0x78) >> 3]; + ansi_637_bigbuf[i] = air_digits[(oct & 0x78) >> 3]; i += 1; if (i >= num_fields) break; @@ -1179,83 +1551,215 @@ tele_param_cb_num(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint oct2 = tvb_get_guint8(tvb, offset); offset += 1; - ansi_637_bigbuf[i] = - air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)]; + 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, + proto_tree_add_string_format(tree, hf_ansi_637_tele_cb_num_number, tvb, saved_offset, offset - saved_offset, + ansi_637_bigbuf, "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); + proto_tree_add_item(tree, + odd ? hf_ansi_637_reserved_bits_8_07 : hf_ansi_637_reserved_bits_8_7f, + tvb, offset - 1, 1, ENC_BIG_ENDIAN); + } +} + +static const value_string tele_param_msg_display_mode_strings[] = { + { 0, "Immediate Display: The mobile station is to display the received message as soon as possible." }, + { 1, "Mobile default setting: The mobile station is to display the received message based on a pre-defined mode in the mobile station." }, + { 2, "User Invoke: The mobile station is to display the received message based on the mode selected by the user." }, + { 3, "Reserved" }, + { 0, NULL } +}; + +static void +tele_param_disp_mode(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 1); + + proto_tree_add_item(tree, hf_ansi_637_tele_msg_display_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_3f, tvb, offset, 1, ENC_BIG_ENDIAN); +} + +static void +tele_param_msg_deposit_idx(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 2); + + proto_tree_add_item(tree, hf_ansi_637_tele_msg_deposit_idx, tvb, offset, 2, ENC_BIG_ENDIAN); +} + +static const value_string tele_param_srvc_cat_prog_results_result_strings[] = { + { 0x00, "Programming successful" }, + { 0x01, "Service Category memory limit exceeded" }, + { 0x02, "Service Category limit exceeded" }, + { 0x03, "Category already programmed" }, + { 0x04, "Category not previously programmed" }, + { 0x05, "Invalid MAX_MESSAGES" }, + { 0x06, "Invalid ALERT_OPTION" }, + { 0x07, "Invalid Service Category name" }, + { 0x08, "Unspecified programming failure" }, + { 0x09, "Reserved" }, + { 0x0a, "Reserved" }, + { 0x0b, "Reserved" }, + { 0x0c, "Reserved" }, + { 0x0d, "Reserved" }, + { 0x0e, "Reserved" }, + { 0x0f, "Reserved" }, + { 0, NULL } +}; + +static void +tele_param_srvc_cat_prog_results(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + guint32 curr_offset; + guint32 value; + const gchar *str = NULL; + + curr_offset = offset; + + while ((len - (curr_offset - offset)) >= 3) + { + value = tvb_get_ntohs(tvb, curr_offset); + + str = val_to_str_const(value, ansi_tsb58_srvc_cat_vals, "Reserved"); + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_srvc_cat_prog_results_srvc_cat, tvb, curr_offset, 2, + value, + "%s (%u)", + str, value); + + curr_offset += 2; + + proto_tree_add_item(tree, hf_ansi_637_tele_srvc_cat_prog_results_result, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_0f, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + + curr_offset += 1; } + + EXTRANEOUS_DATA_CHECK(len, curr_offset - offset); } +/* Adamek Jan - IS637C Message status decoding procedure */ +static const value_string tele_param_msg_status_error_class_strings[] = { + { 0x00, "No Error" }, + { 0x01, "Reserved" }, + { 0x02, "Temporary Condition" }, + { 0x03, "Permanent Condition" }, + { 0, NULL } +}; + 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_) +tele_param_msg_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) { - guint8 oct; + guint8 oct; + guint8 msg_status_code; const gchar *str = NULL; EXACT_DATA_CHECK(len, 1); + proto_tree_add_item(tree, hf_ansi_637_tele_msg_status, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_tele_msg_status_error_class, tvb, offset, 1, ENC_BIG_ENDIAN); + oct = tvb_get_guint8(tvb, offset); + msg_status_code = (oct & 0x3f); + 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; + case 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; + } + break; + + case 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; + } + break; + + case 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; + } + break; + + default: + 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); + proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_msg_status_code, tvb, offset, 1, + oct, + "%s (%u)", + str, msg_status_code); +} - 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_tp_failure_cause(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_) +{ + EXACT_DATA_CHECK(len, 1); + + proto_tree_add_item(tree, hf_ansi_637_tele_tp_failure_cause_value, tvb, offset, 1, ENC_BIG_ENDIAN); } #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 (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p) = { + tele_param_msg_id, /* Message Identifier */ + tele_param_user_data, /* User Data */ + tele_param_rsp_code, /* User Response Code */ + tele_param_message_center_timestamp,/* Message Center Time Stamp */ + tele_param_validity_period_abs, /* Validity Period - Absolute */ + tele_param_validity_period_rel, /* Validity Period - Relative */ + tele_param_deferred_del_abs, /* Deferred Delivery Time - Absolute */ + tele_param_deferred_del_rel, /* 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_deposit_idx, /* Message Deposit Index */ + NULL, /* Service Category Program Data */ + tele_param_srvc_cat_prog_results, /* Service Category Program Results */ + tele_param_msg_status, /* Message status */ + tele_param_tp_failure_cause, /* TP-Failure cause */ + NULL, /* Enhanced VMN */ + NULL /* Enhanced VMN Ack */ }; 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; + guint32 value; const gchar *str = NULL; EXACT_DATA_CHECK(len, 2); @@ -1323,41 +1827,56 @@ trans_param_tele_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui } } - proto_tree_add_text(tree, tvb, offset, 2, - "%s (%d)", - str, - value); + /* + * NOT format_value because I don't need the text from the hf_ + */ + proto_tree_add_uint_format(tree, hf_ansi_637_trans_tele_id, tvb, offset, 2, + value, + "%s (%u)", + str, value); - g_snprintf(add_string, string_len, " - %s (%d)", str, value); + g_snprintf(add_string, string_len, " - %s (%u)", 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; + 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"); + str = val_to_str_const(value, ansi_tsb58_srvc_cat_vals, "Reserved"); + proto_tree_add_uint_format_value(tree, hf_ansi_637_trans_srvc_cat, tvb, offset, 2, + value, + "%s (%u)", + str, value); - proto_tree_add_text(tree, tvb, offset, 2, - "%s", str); + g_snprintf(add_string, string_len, " - %s (%u)", str, value); - g_snprintf(add_string, string_len, " - %s (%d)", str, value); + if ((value >= ANSI_TSB58_SRVC_CAT_CMAS_MIN) && (value <= ANSI_TSB58_SRVC_CAT_CMAS_MAX)) + { + col_append_fstr(pinfo->cinfo, COL_INFO, " - CMAS (%s)", str); + } } +static const value_string trans_param_addr_data_net_ton_strings[] = { + { 0x00, "Unknown" }, + { 0x01, "Internet Protocol (RFC 791)" }, + { 0x02, "Internet Email Address (RFC 822)" }, + { 0, NULL } +}; + 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; + guint8 oct, oct2, num_fields, odd; + gboolean email_addr; + guint32 saved_offset; + guint32 required_octs; + guint32 i; SHORT_DATA_CHECK(len, 2); @@ -1365,69 +1884,51 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui 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"); + proto_tree_add_item(tree, hf_ansi_637_trans_addr_param_digit_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_trans_addr_param_number_mode, tvb, offset, 1, ENC_BIG_ENDIAN); 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; - } + email_addr = (((oct & 0x38) >> 3) == 0x02) ? TRUE : FALSE; - 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); + /* + * do not change to ...add_item() with VALS in hf defintion because this parameter is + * used below in the 'else' with a different string array + */ + proto_tree_add_uint_format_value(tree, hf_ansi_637_trans_addr_param_ton, tvb, offset, 1, + oct, + "%s (%u)", + val_to_str_const((oct & 0x38) >> 3, trans_param_addr_data_net_ton_strings, "Reserved"), (oct & 0x38) >> 3); offset += 1; - num_fields = (oct & 0x07) << 5; + oct2 = tvb_get_guint8(tvb, offset); - num_fields |= ((oct2 & 0xf8) >> 3); + num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3); + /* + * not combined into a 16-bit field because hf_ansi_637_trans_addr_param_num_fields is used below + * and uses a different bitmask + */ 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); + proto_tree_add_uint_format(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, offset - 1, 1, + num_fields, + "%s = Number of fields (MSB): %u", + 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)", + "%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; - } + SHORT_DATA_CHECK(len - 2, num_fields); 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", + "%s = Most significant bits of first field", ansi_637_bigbuf); offset += 1; @@ -1437,49 +1938,52 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui while (i < num_fields) { ansi_637_bigbuf[i] = (oct & 0x07) << 5; - ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf8) >> 3; + 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, + proto_tree_add_string_format(tree, hf_ansi_637_trans_addr_param_number, tvb, offset, num_fields - 1, + ansi_637_bigbuf, "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); + (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", + "%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); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_07, tvb, offset, 1, ENC_BIG_ENDIAN); } 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); + /* + * do not change to ...add_item() with VALS in hf definition because this parameter + * is used above in the 'if' with a different string array + */ + proto_tree_add_uint_format_value(tree, hf_ansi_637_trans_addr_param_ton, tvb, offset, 1, + oct, + "%s (%u)", + val_to_str_const((oct & 0x38) >> 3, ansi_a_ms_info_rec_num_type_vals, "Reserved"), (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)", + proto_tree_add_uint_format(tree, hf_ansi_637_trans_addr_param_plan, tvb, offset, 1, + ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7), + "%s = Numbering Plan (MSB): %s (%u)", ansi_637_bigbuf, + val_to_str_const(((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7), ansi_a_ms_info_rec_num_plan_vals, "Reserved"), ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)); offset += 1; @@ -1487,39 +1991,33 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8); proto_tree_add_text(tree, tvb, offset, 1, - "%s : Numbering plan (LSB)", + "%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); + num_fields = ((oct & 0x7f) << 1) | ((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)", + proto_tree_add_uint_format(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, offset - 1, 1, + num_fields, + "%s = Number of fields (MSB): %u", 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)", + "%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; - } + SHORT_DATA_CHECK(len - 3, num_fields); 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", + "%s = Most significant bits of first field", ansi_637_bigbuf); offset += 1; @@ -1529,12 +2027,13 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui while (i < num_fields) { ansi_637_bigbuf[i] = (oct & 0x7f) << 1; - ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0x80) >> 7; + 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, + proto_tree_add_string_format(tree, hf_ansi_637_trans_addr_param_number, tvb, offset, num_fields - 1, + ansi_637_bigbuf, "Number: %s", ansi_637_bigbuf); @@ -1542,31 +2041,29 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui 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", + "%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); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_7f, tvb, offset, 1, ENC_BIG_ENDIAN); } } else { offset += 1; - num_fields = (oct & 0x3f) << 2; + oct2 = tvb_get_guint8(tvb, offset); - num_fields |= ((oct2 & 0xc0) >> 6); + num_fields = ((oct & 0x3f) << 2) | ((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)", + proto_tree_add_uint_format(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, offset - 1, 1, + num_fields, + "%s = Number of fields (MSB): %u", 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)", + "%s = Number of fields (LSB)", ansi_637_bigbuf); oct = oct2; @@ -1577,14 +2074,7 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui 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; - } + SHORT_DATA_CHECK(len - 2, required_octs); odd = num_fields & 0x01; memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf)); @@ -1611,168 +2101,116 @@ trans_param_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gui i += 1; } - proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset, + proto_tree_add_string_format(tree, hf_ansi_637_trans_addr_param_number, tvb, saved_offset, offset - saved_offset, + ansi_637_bigbuf, "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); + proto_tree_add_item(tree, + odd ? hf_ansi_637_reserved_bits_8_03 : hf_ansi_637_reserved_bits_8_3f, + tvb, offset - 1, 1, ENC_BIG_ENDIAN); } } +static const value_string trans_param_subaddr_type_strings[] = { + { 0x0, "NSAP (CCITT Recommendation X.213 or ISO 8348 AD2)" }, + { 0x1, "User-specified" }, + { 0, NULL } +}; + 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; + guint8 oct, num_fields; + guint32 value; + guint32 i; 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); + value = tvb_get_ntohs(tvb, offset); - other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8); - proto_tree_add_text(tree, tvb, offset, 1, - "%s : Odd", - ansi_637_bigbuf); + proto_tree_add_uint_format_value(tree, hf_ansi_637_trans_subaddr_type, tvb, offset, 2, + value, + "%s (%u)", + val_to_str_const((value & 0xe000) >> 13, trans_param_subaddr_type_strings, "Reserved"), (value & 0xe000) >> 13); - offset += 1; - num_fields = (oct & 0x0f) << 4; - oct2 = tvb_get_guint8(tvb, offset); - num_fields |= ((oct2 & 0xf0) >> 4); + proto_tree_add_item(tree, hf_ansi_637_trans_subaddr_odd_even_ind, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_trans_subaddr_num_fields, tvb, offset, 2, ENC_BIG_ENDIAN); - 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); + num_fields = (value & 0x0ff0) >> 4; 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); + SHORT_DATA_CHECK(len - 2, num_fields); - 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", + other_decode_bitfield_value(ansi_637_bigbuf, value, 0x000f, 16); + proto_tree_add_text(tree, tvb, offset, 2, + "%s = Most significant bits of first field", ansi_637_bigbuf); - offset += 1; - oct = oct2; + offset += 2; + oct = value & 0x000f; 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; + 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); + (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", + "%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); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_0f, tvb, offset, 1, ENC_BIG_ENDIAN); } 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); + proto_tree_add_item(tree, hf_ansi_637_trans_bearer_reply_seq_num, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_03, tvb, offset, 1, ENC_BIG_ENDIAN); - 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); + g_snprintf(add_string, string_len, " - Reply Sequence Number (%u)", + (tvb_get_guint8(tvb, offset) & 0xfc) >> 2); } +static const value_string trans_param_cause_codes_error_class_strings[] = { + { 0x00, "No Error" }, + { 0x01, "Reserved" }, + { 0x02, "Temporary Condition" }, + { 0x03, "Permanent Condition" }, + { 0, NULL } +}; + 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; - } + guint8 oct; + const gchar *str; - g_snprintf(add_string, string_len, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2); + proto_tree_add_item(tree, hf_ansi_637_trans_cause_codes_seq_num, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ansi_637_trans_cause_codes_error_class, tvb, offset, 1, ENC_BIG_ENDIAN); - 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); + oct = tvb_get_guint8(tvb, offset); - offset += 1; + g_snprintf(add_string, string_len, " - Reply Sequence Number (%u)", (oct & 0xfc) >> 2); if (!(oct & 0x03)) return; if (len == 1) return; + offset += 1; + oct = tvb_get_guint8(tvb, offset); switch (oct) @@ -1819,40 +2257,38 @@ trans_param_cause_codes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, break; } - proto_tree_add_text(tree, tvb, offset, 1, - "%s", str); + proto_tree_add_uint_format_value(tree, hf_ansi_637_trans_cause_codes_code, tvb, offset, 1, + oct, + "%s (%u)", + str, oct); } 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_) +trans_param_bearer_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, 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"); + tvbuff_t *tele_tvb; /* * 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); + 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 */ + 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)) @@ -1861,9 +2297,9 @@ 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) +dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset, gboolean *has_private_data_p) { - void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gboolean*) = NULL; + void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gboolean *) = NULL; guint8 oct; guint8 len; guint32 curr_offset; @@ -1887,12 +2323,13 @@ dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, param_fcn = ansi_637_tele_param_fcn[idx]; item = - proto_tree_add_text(tree, tvb, curr_offset, -1, "%s", str); + 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); + proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id, tvb, curr_offset, 1, oct); curr_offset += 1; @@ -1900,8 +2337,7 @@ dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, 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); + proto_tree_add_uint(subtree, hf_ansi_637_tele_length, tvb, curr_offset, 1, len); curr_offset += 1; @@ -1909,12 +2345,25 @@ dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, { if (param_fcn == NULL) { - proto_tree_add_text(subtree, tvb, curr_offset, - len, "Parameter Data"); + proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_no_tele_parameter_dissector, tvb, curr_offset, len); } else { - (*param_fcn)(tvb, pinfo, subtree, len, curr_offset, has_private_data); + /* + * internal working (aka hack) for CMAS + * + * the 'User Data' subparameter is encoded in a special way for CMAS + * (as per TIA-1149) + * + * if (Broadcast SMS && 'User Data') then call CMAS dissector + */ + if ((ansi_637_trans_tele_id == INTERNAL_BROADCAST_TELE_ID) && + (oct == 0x01)) + { + param_fcn = tele_param_user_data_cmas; + } + + (*param_fcn)(tvb, pinfo, subtree, len, curr_offset, has_private_data_p); } curr_offset += len; @@ -1926,20 +2375,19 @@ dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, } static void -dissect_ansi_637_tele_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ansi_637_tree, gboolean* has_private_data) +dissect_ansi_637_tele_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ansi_637_tree, gboolean *has_private_data_p) { - guint8 len; - guint32 curr_offset; + 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)) + if (!dissect_ansi_637_tele_param(tvb, pinfo, ansi_637_tree, &curr_offset, has_private_data_p)) { - proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset, - "Unknown Parameter Data"); + proto_tree_add_expert(ansi_637_tree, pinfo, &ei_ansi_637_unknown_tele_parameter, tvb, curr_offset, len - curr_offset); break; } } @@ -1950,9 +2398,9 @@ 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; + const gchar *str = NULL; + guint32 value; + gboolean has_private_data = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short); @@ -2015,19 +2463,10 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { str = "Reserved for assignment by this Standard for TDMA MS-based SMEs"; } - else if ((value >= 49152) && (value < 65535)) + 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"; @@ -2036,15 +2475,27 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } } - 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); + if (value == INTERNAL_BROADCAST_TELE_ID) + { + /* + * supposed to be "Reserved for carrier specific teleservices" + * but we are using it to key SMS Broadcast dissection where + * there is no teleservice ID + */ + ansi_637_item = + proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1, + "%s", + ansi_proto_name_tele); + } + else + { + ansi_637_item = + proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1, + "%s - %s (%u)", + ansi_proto_name_tele, str, pinfo->match_uint); + } - ansi_637_tree = - proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele); + 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); } @@ -2053,14 +2504,14 @@ dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 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; + 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; + const gchar *str; curr_offset = *offset; @@ -2075,13 +2526,11 @@ dissect_ansi_637_trans_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree 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); + 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); + proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id, tvb, curr_offset, 1, oct); curr_offset += 1; @@ -2089,8 +2538,7 @@ dissect_ansi_637_trans_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree 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); + proto_tree_add_uint(subtree, hf_ansi_637_trans_length, tvb, curr_offset, 1, len); curr_offset += 1; @@ -2098,14 +2546,13 @@ dissect_ansi_637_trans_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree { if (param_fcn == NULL) { - proto_tree_add_text(subtree, tvb, curr_offset, - len, "Parameter Data"); + proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_no_trans_parameter_dissector, tvb, curr_offset, len); } else { - gchar *ansi_637_add_string; + gchar *ansi_637_add_string; - ansi_637_add_string = (gchar *)wmem_alloc(wmem_packet_scope(), 1024); + 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); @@ -2129,11 +2576,11 @@ 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; + guint32 curr_offset; + gint idx; + const gchar *str = NULL; + guint8 oct; + guint8 len; col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short); @@ -2160,23 +2607,19 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { 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); + "%s - Unrecognized Transport Layer Message Type (%u)", + ansi_proto_name_trans, oct); - ansi_637_tree = - proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans); + 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_proto_name_trans, str); - ansi_637_tree = - proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]); + ansi_637_tree = proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]); if (oct == ANSI_TRANS_MSG_TYPE_BROADCAST) { @@ -2186,7 +2629,9 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) * * using a reserved value to key dissector port */ - ansi_637_trans_tele_id = 65535; + ansi_637_trans_tele_id = INTERNAL_BROADCAST_TELE_ID; + + col_append_str(pinfo->cinfo, COL_INFO, "(BROADCAST)"); } } @@ -2198,100 +2643,592 @@ dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { 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"); + proto_tree_add_expert(ansi_637_tree, pinfo, &ei_ansi_637_unknown_trans_parameter, tvb, curr_offset, len - curr_offset); 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_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; + 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 + static hf_register_info hf_trans[] = { { &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 }}, + NULL, HFILL } + }, { &hf_ansi_637_trans_length, { "Length", "ansi_637_trans.len", FT_UINT8, BASE_DEC, NULL, 0, - NULL, HFILL }}, + 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[] = - { + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_tele_id, + { "Teleservice ID", "ansi_637_trans.tele_id", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_srvc_cat, + { "Service Category", "ansi_637_trans.srvc_cat", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_digit_mode, + { "Digit Mode", "ansi_637_trans.addr_param.digit_mode", + FT_BOOLEAN, 8, TFS(&tfs_digit_mode_8bit_4bit), 0x80, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_number_mode, + { "Number Mode", "ansi_637_trans.addr_param.number_mode", + FT_BOOLEAN, 8, TFS(&tfs_number_mode_data_ansi_t1), 0x40, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_ton, + { "Type of Number", "ansi_637_trans.addr_param.ton", + FT_UINT8, BASE_DEC, NULL, 0x38, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_plan, + { "Numbering Plan", "ansi_637_trans.addr_param.plan", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_num_fields, + { "Number of fields", "ansi_637_trans.addr_param.num_fields", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_addr_param_number, + { "Number", "ansi_637_trans.addr_param.number", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_subaddr_type, + { "Type", "ansi_637_trans.subaddr.type", + FT_UINT16, BASE_DEC, NULL, 0xe000, + NULL, HFILL } + }, + { &hf_ansi_637_trans_subaddr_odd_even_ind, + { "Odd/Even Indicator", "ansi_637_trans.subaddr.odd_even_ind", + FT_UINT16, BASE_DEC, VALS(ansi_trans_subaddr_odd_even_ind_strings), 0x1000, + NULL, HFILL } + }, + { &hf_ansi_637_trans_subaddr_num_fields, + { "Number of fields", "ansi_637_trans.subaddr.num_fields", + FT_UINT16, BASE_DEC, NULL, 0x0ff0, + NULL, HFILL } + }, + { &hf_ansi_637_trans_bearer_reply_seq_num, + { "Reply Sequence Number", "ansi_637_trans.bearer_reply.seq_num", + FT_UINT8, BASE_DEC, NULL, 0xfc, + NULL, HFILL } + }, + { &hf_ansi_637_trans_cause_codes_seq_num, + { "Reply Sequence Number", "ansi_637_trans.cause_codes.seq_num", + FT_UINT8, BASE_DEC, NULL, 0xfc, + NULL, HFILL } + }, + { &hf_ansi_637_trans_cause_codes_error_class, + { "Error Class", "ansi_637_trans.cause_codes.error_class", + FT_UINT8, BASE_DEC, VALS(trans_param_cause_codes_error_class_strings), 0x03, + NULL, HFILL } + }, + { &hf_ansi_637_trans_cause_codes_code, + { "Cause Code", "ansi_637_trans.cause_codes.code", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + } + }; + + static hf_register_info hf_tele[] = { { &hf_ansi_637_tele_msg_type, - { "Message Type", + { "Message Type", "ansi_637_tele.msg_type", FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000, - NULL, HFILL }}, + NULL, HFILL } + }, { &hf_ansi_637_tele_msg_id, - { "Message ID", + { "Message ID", "ansi_637_tele.msg_id", FT_UINT24, BASE_DEC, NULL, 0x0ffff0, - NULL, HFILL }}, + NULL, HFILL } + }, + { &hf_ansi_637_tele_length, + { "Length", "ansi_637_tele.len", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, { &hf_ansi_637_tele_msg_status, - { "Message 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 }}, + NULL, HFILL } + }, + { &hf_ansi_637_tele_msg_header_ind, + { "Header Indicator", + "ansi_637_tele.msg_header_ind", + FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_header_ind_strings), 0x000008, + NULL, HFILL } + }, { &hf_ansi_637_tele_msg_rsvd, - { "Reserved", + { "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 }}, + 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 }}, + NULL, HFILL } + }, { &hf_ansi_637_tele_user_data_text, { "Encoded user data", "ansi_637_tele.user_data.text", FT_STRING, STR_UNICODE, NULL, 0, - NULL, HFILL }}, + NULL, HFILL } + }, + { &hf_ansi_637_tele_user_data_encoding, + { "Encoding", "ansi_637_tele.user_data.encoding", + FT_UINT16, BASE_DEC, NULL, 0xf800, + NULL, HFILL } + }, + { &hf_ansi_637_tele_user_data_message_type, + { "Message Type (see TIA/EIA/IS-91)", "ansi_637_tele.user_data.message_type", + FT_UINT16, BASE_DEC, NULL, 0x07f8, + NULL, HFILL } + }, + { &hf_ansi_637_tele_user_data_num_fields, + { "Number of fields", "ansi_637_tele.user_data.num_fields", + FT_UINT16, BASE_DEC, NULL, 0x07f8, + NULL, HFILL } + }, + { &hf_ansi_637_tele_response_code, + { "Response Code", "ansi_637_tele.response_code", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_year, + { "Timestamp (Year)", "ansi_637_tele.message_center_ts.year", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_month, + { "Timestamp (Month)", "ansi_637_tele.message_center_ts.month", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_day, + { "Timestamp (Day)", "ansi_637_tele.message_center_ts.day", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_hours, + { "Timestamp (Hours)", "ansi_637_tele.message_center_ts.hours", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_minutes, + { "Timestamp (Minutes)", "ansi_637_tele.message_center_ts.minutes", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_message_center_ts_seconds, + { "Timestamp (Seconds)", "ansi_637_tele.message_center_ts.seconds", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_year, + { "Timestamp (Year)", "ansi_637_tele.validity_period_ts.year", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_month, + { "Timestamp (Month)", "ansi_637_tele.validity_period_ts.month", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_day, + { "Timestamp (Day)", "ansi_637_tele.validity_period_ts.day", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_hours, + { "Timestamp (Hours)", "ansi_637_tele.validity_period_ts.hours", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_minutes, + { "Timestamp (Minutes)", "ansi_637_tele.validity_period_ts.minutes", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_ts_seconds, + { "Timestamp (Seconds)", "ansi_637_tele.validity_period_ts.seconds", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_validity_period_relative_validity, + { "Validity", "ansi_637_tele.validity_period_relative.validity", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_year, + { "Timestamp (Year)", "ansi_637_tele.deferred_del_ts.year", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_month, + { "Timestamp (Month)", "ansi_637_tele.deferred_del_ts.month", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_day, + { "Timestamp (Day)", "ansi_637_tele.deferred_del_ts.day", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_hours, + { "Timestamp (Hours)", "ansi_637_tele.deferred_del_ts.hours", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_minutes, + { "Timestamp (Minutes)", "ansi_637_tele.deferred_del_ts.minutes", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_ts_seconds, + { "Timestamp (Seconds)", "ansi_637_tele.deferred_del_ts.seconds", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_deferred_del_relative, + { "Delivery Time", "ansi_637_tele.deferred_del.relative", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_priority_indicator, + { "Priority", "ansi_637_tele.priority_indicator", + FT_UINT8, BASE_DEC, VALS(tele_param_priority_ind_strings), 0xc0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_privacy_indicator, + { "Privacy", "ansi_637_tele.privacy_indicator", + FT_UINT8, BASE_DEC, VALS(tele_param_privacy_ind_strings), 0xc0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_reply_option_user_ack_req, + { "User Acknowledgement Requested", "ansi_637_tele.reply_option.user_ack_req", + FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, + NULL, HFILL } + }, + { &hf_ansi_637_tele_reply_option_dak_req, + { "Delivery Acknowledgement Requested", "ansi_637_tele.reply_option.dak_req", + FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40, + NULL, HFILL } + }, + { &hf_ansi_637_tele_reply_option_read_ack_req, + { "Read Acknowledgement Requested", "ansi_637_tele.reply_option.read_ack_req", + FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, + NULL, HFILL } + }, + { &hf_ansi_637_tele_reply_option_report_req, + { "Delivery/Submit Report Requested", "ansi_637_tele.reply_option.report_req", + FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10, + NULL, HFILL } + }, + { &hf_ansi_637_tele_num_messages, + { "Number of voice mail messages", "ansi_637_tele.num_messages.count", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_alert_msg_delivery_priority, + { "Privacy", "ansi_637_tele.alert_msg_delivery.priority", + FT_UINT8, BASE_DEC, VALS(tele_param_alert_priority_strings), 0xc0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_language, + { "Language", "ansi_637_tele.language", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cb_num_digit_mode, + { "Digit Mode", "ansi_637_tele.cb_num.digit_mode", + FT_BOOLEAN, 8, TFS(&tfs_digit_mode_8bit_4bit), 0x80, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cb_num_ton, + { "Type of Number", "ansi_637_tele.cb_num.ton", + FT_UINT8, BASE_DEC, VALS(ansi_a_ms_info_rec_num_type_vals), 0x70, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cb_num_plan, + { "Numbering Plan", "ansi_637_tele.cb_num.plan", + FT_UINT8, BASE_DEC, VALS(ansi_a_ms_info_rec_num_plan_vals), 0x0f, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cb_num_num_fields, + { "Number of fields", "ansi_637_tele.cb_num.num_fields", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cb_num_number, + { "Call-Back Number", "ansi_637_tele.cb_num.number", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_msg_display_mode, + { "Message Display Mode", "ansi_637_tele.msg_display_mode", + FT_UINT8, BASE_DEC, VALS(tele_param_msg_display_mode_strings), 0xc0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_msg_deposit_idx, + { "Message Deposit Index", "ansi_637_tele.msg_deposit_idx", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_srvc_cat_prog_results_srvc_cat, + { "Service Category", "ansi_637_tele.srvc_cat_prog_results.srvc_cat", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_srvc_cat_prog_results_result, + { "Programming Result", "ansi_637_tele.srvc_cat_prog_results.result", + FT_UINT8, BASE_DEC, VALS(tele_param_srvc_cat_prog_results_result_strings), 0xf0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_msg_status_error_class, + { "Error Class", "ansi_637_tele.msg_status.error_class", + FT_UINT8, BASE_DEC, VALS(tele_param_msg_status_error_class_strings), 0xc0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_msg_status_code, + { "Message Status Code", "ansi_637_tele.msg_status.code", + FT_UINT8, BASE_DEC, NULL, 0x3f, + NULL, HFILL } + }, + { &hf_ansi_637_tele_tp_failure_cause_value, + { "GSM SMS TP-Failure Cause", "ansi_637_tele.tp_failure_cause.value", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_generic, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_03, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0x03, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_07, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0x07, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_0f, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0x0f, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_3f, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0x3f, + NULL, HFILL } + }, + { &hf_ansi_637_reserved_bits_8_7f, + { "Reserved bit(s)", "ansi_637_tele.reserved", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_encoding, + { "Encoding", "ansi_637_tele.cmas.encoding", + FT_UINT16, BASE_DEC, NULL, 0xf800, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_num_fields, + { "Number of fields", "ansi_637_tele.cmas.num_fields", + FT_UINT16, BASE_DEC, NULL, 0x07f8, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_protocol_version, + { "CMAE_protocol_version", "ansi_637_tele.cmas.protocol_version", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_record_type, + { "E_RECORD_TYPE", "ansi_637_tele.cmas.record_type", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_record_len, + { "E_RECORD_LENGTH", "ansi_637_tele.cmas.record_len", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_char_set, + { "CMAE_char_set", "ansi_637_tele.cmas.char_set", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_category, + { "CMAE_category", "ansi_637_tele.cmas.category", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_response_type, + { "CMAE_response_type", "ansi_637_tele.cmas.response_type", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_severity, + { "CMAE_severity", "ansi_637_tele.cmas.severity", + FT_UINT8, BASE_DEC, NULL, 0xf0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_urgency, + { "CMAE_urgency", "ansi_637_tele.cmas.urgency", + FT_UINT8, BASE_DEC, NULL, 0x0f, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_certainty, + { "CMAE_certainty", "ansi_637_tele.cmas.certainty", + FT_UINT8, BASE_DEC, NULL, 0xf0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_identifier, + { "CMAE_identifier", "ansi_637_tele.cmas.identifier", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_alert_handling, + { "CMAE_alert_handling", "ansi_637_tele.cmas.alert_handling", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_year, + { "CMAE_expires (Year)", "ansi_637_tele.cmas.expires.year", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_month, + { "CMAE_expires (Month)", "ansi_637_tele.cmas.expires.month", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_day, + { "CMAE_expires (Day)", "ansi_637_tele.cmas.expires.day", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_hours, + { "CMAE_expires (Hours)", "ansi_637_tele.cmas.expires.hours", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_minutes, + { "CMAE_expires (Minutes)", "ansi_637_tele.cmas.expires.minutes", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_expires_seconds, + { "CMAE_expires (Seconds)", "ansi_637_tele.cmas.expires.seconds", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_ansi_637_tele_cmas_language, + { "CMAE_language", "ansi_637_tele.cmas.language", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL } + } + }; + + static ei_register_info ei[] = { + { &ei_ansi_637_extraneous_data, + { "ansi_637.extraneous_data", PI_PROTOCOL, PI_NOTE, + "Extraneous Data - try checking decoder variant preference or dissector bug/later version spec (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_short_data, + { "ansi_637.short_data", PI_PROTOCOL, PI_NOTE, + "Short Data (?) - try checking decoder variant preference or dissector bug/later version spec (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_unexpected_length, + { "ansi_637.unexpected_length", PI_PROTOCOL, PI_WARN, + "Unexpected Data Length - try checking decoder variant preference or dissector bug/later version spec (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_unknown_encoding, + { "ansi_637.unknown_format", PI_PROTOCOL, PI_NOTE, + "Encoding Unknown/Unsupported - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_failed_conversion, + { "ansi_637.failed_conversion", PI_PROTOCOL, PI_WARN, + "Failed iconv conversion - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_unknown_cmas_record_type, + { "ansi_637.unknown_cmas_record_type", PI_PROTOCOL, PI_WARN, + "Unknown CMAS record type - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_unknown_trans_parameter, + { "ansi_637.unknown_trans_parameter", PI_PROTOCOL, PI_WARN, + "Unknown transport layer parameter - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_no_trans_parameter_dissector, + { "ansi_637.no_trans_parameter_dissector", PI_PROTOCOL, PI_WARN, + "No transport layer parameter dissector - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_unknown_tele_parameter, + { "ansi_637.unknown_tele_parameter", PI_PROTOCOL, PI_WARN, + "Unknown teleservice layer parameter - (report to wireshark.org)", + EXPFILL } + }, + { &ei_ansi_637_no_tele_parameter_dissector, + { "ansi_637.no_tele_parameter_dissector", PI_PROTOCOL, PI_WARN, + "No teleservice layer parameter dissector - (report to wireshark.org)", + EXPFILL } + } }; + expert_module_t *expert_ansi_637; + /* Setup protocol subtree array */ -#define NUM_INDIVIDUAL_PARAMS 3 - gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM]; +#define NUM_INDIVIDUAL_PARAMS 4 + gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM+NUM_CMAS_PARAM]; memset((void *) ett, 0, sizeof(ett)); ett[0] = &ett_ansi_637_tele; ett[1] = &ett_ansi_637_trans; - ett[2] = &ett_params; + ett[2] = &ett_ansi_637_header_ind; + ett[3] = &ett_params; for (i=0; i < NUM_TELE_PARAM; i++) { @@ -2311,6 +3248,12 @@ proto_register_ansi_637(void) ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i]; } + for (i=0; i < NUM_CMAS_PARAM; i++) + { + ett_tia_1149_cmas_param[i] = -1; + ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM+i] = &ett_tia_1149_cmas_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"); @@ -2326,6 +3269,10 @@ proto_register_ansi_637(void) proto_register_field_array(proto_ansi_637_trans, hf_trans, array_length(hf_trans)); proto_register_subtree_array(ett, array_length(ett)); + expert_ansi_637 = + expert_register_protocol(proto_ansi_637_trans); + expert_register_field_array(expert_ansi_637, ei, array_length(ei)); + tele_dissector_table = register_dissector_table("ansi_637.tele_id", "ANSI IS-637-A Teleservice ID", FT_UINT8, BASE_DEC); @@ -2341,7 +3288,8 @@ proto_reg_handoff_ansi_637(void) 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); + 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 @@ -2362,6 +3310,13 @@ proto_reg_handoff_ansi_637(void) } /* + * internal implementation add this pseudo teleservice ID for handling broadcast SMS + * (which don't have teleservice IDs) + */ + dissector_add_uint("ansi_map.tele_id", INTERNAL_BROADCAST_TELE_ID, ansi_637_tele_handle); + dissector_add_uint("ansi_637.tele_id", INTERNAL_BROADCAST_TELE_ID, ansi_637_tele_handle); + + /* * ANSI A-interface will push out transport layer data */ dissector_add_uint("ansi_a.sms", 0, ansi_637_trans_handle); |