wireshark/epan/dissectors/packet-ansi_637.c
John Thacker e6d81e8731 ANSI IS-637 A: Use tvb_new_octet_aligned for addresses
Use tvb_new_octet_aligned when adding addresses (strings or bytes)
that are not byte aligned. That is not only clearer code, but also
prevents attempting to add unvalidated strings.

Since we're aligning the fields properly, get rid of the extra
fields for the MSB of the first field and LSB of the last field.

Fix #18664
2022-11-23 07:01:19 -05:00

3388 lines
117 KiB
C

/* packet-ansi_637.c
* 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)
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/strutil.h>
#include <epan/to_str.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_trans = "ANSI IS-637-A (SMS) Transport Layer";
static const char *ansi_proto_name_short = "IS-637-A";
/*
* 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)" },
{ 2, "Submit (mobile-originated only)" },
{ 3, "Cancellation (mobile-originated only)" },
{ 4, "Delivery Acknowledgement (mobile-terminated only)" },
{ 5, "User Acknowledgement (either direction)" },
{ 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" },
{ 0, NULL }
};
static value_string_ext ansi_tele_msg_status_strings_ext = VALUE_STRING_EXT_INIT(ansi_tele_msg_status_strings);
static const value_string ansi_tele_id_strings[] = {
{ 1, "Reserved for maintenance" },
{ 4096, "AMPS Extended Protocol Enhanced Services" },
{ 4097, "CDMA Cellular Paging Teleservice" },
{ 4098, "CDMA Cellular Messaging Teleservice" },
{ 4099, "CDMA Voice Mail Notification" },
{ 4100, "CDMA Wireless Application Protocol (WAP)" },
{ 4101, "CDMA Wireless Enhanced Messaging Teleservice (WEMT)" },
{ 0, NULL }
};
#define INTERNAL_BROADCAST_TELE_ID 65535
static const value_string ansi_tele_param_strings[] = {
{ 0x00, "Message Identifier" },
{ 0x01, "User Data" },
{ 0x02, "User Response Code" },
{ 0x03, "Message Center Time Stamp" },
{ 0x04, "Validity Period - Absolute" },
{ 0x05, "Validity Period - Relative" },
{ 0x06, "Deferred Delivery Time - Absolute" },
{ 0x07, "Deferred Delivery Time - Relative" },
{ 0x08, "Priority Indicator" },
{ 0x09, "Privacy Indicator" },
{ 0x0a, "Reply Option" },
{ 0x0b, "Number of Messages" },
{ 0x0c, "Alert on Message Delivery" },
{ 0x0d, "Language Indicator" },
{ 0x0e, "Call-Back Number" },
{ 0x0f, "Message Display Mode" },
{ 0x10, "Multiple Encoding User Data" },
{ 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);
#define ANSI_TRANS_MSG_TYPE_BROADCAST 1
static const value_string ansi_trans_msg_type_strings[] = {
{ 0, "Point-to-Point" },
{ 1, "Broadcast" },
{ 2, "Acknowledge" },
{ 0, NULL }
};
static const value_string ansi_trans_param_strings[] = {
{ 0x00, "Teleservice Identifier" },
{ 0x01, "Service Category" },
{ 0x02, "Originating Address" },
{ 0x03, "Originating Subaddress" },
{ 0x04, "Destination Address" },
{ 0x05, "Destination Subaddress" },
{ 0x06, "Bearer Reply Option" },
{ 0x07, "Cause Codes" },
{ 0x08, "Bearer Data" },
{ 0, NULL }
};
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"
};
/*
* from Table 2.7.1.3.2.4-4. Representation of DTMF Digits
* 3GPP2 C.S0005-C (IS-2000 aka cdma2000)
*/
static const unsigned char air_digits[] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
'?','1','2','3','4','5','6','7','8','9','0','*','#','?','?','?'
};
/* Initialize the protocol and registered fields */
static int proto_ansi_637_tele = -1;
static int proto_ansi_637_trans = -1;
static int hf_ansi_637_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_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_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_num_fields07f8 = -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_reserved_bits_16_generic = -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;
static int hf_ansi_637_tele_cmas_text = -1;
static int hf_ansi_637_tele_mult_enc_user_data_encoding = -1;
static int hf_ansi_637_tele_mult_enc_user_data_num_fields = -1;
static int hf_ansi_637_tele_mult_enc_user_data_text = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_encoding = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_operation_code = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_category = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_language = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_max_messages = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_alert_option = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_num_fields = -1;
static int hf_ansi_637_tele_srvc_cat_prog_data_text = -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;
static guint32 ansi_637_trans_tele_id;
static char ansi_637_bigbuf[1024];
static dissector_table_t tele_dissector_table;
static proto_tree *g_tree;
/* PARAM FUNCTIONS */
#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
if ((edc_len) > (edc_max_len)) \
{ \
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_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_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
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, int hf_index)
{
guint8 bit;
guint32 required_octs;
tvbuff_t *tvb_out = NULL;
const guchar *ustr = NULL;
/*
* has to be big enough to hold all of the 'shifted' bits
*/
required_octs = (num_bits + fill_bits + 7) / 8;
/*
* 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");
switch (encoding)
{
default:
proto_tree_add_expert(tree, pinfo, &ei_ansi_637_unknown_encoding, tvb, offset, required_octs);
return;
case 0x00: /* Octet, unspecified */
proto_tree_add_string(tree, hf_index, tvb_out, 0, required_octs,
tvb_bytes_to_str(pinfo->pool, tvb_out, 0, required_octs));
break;
case 0x02: /* 7-bit ASCII */
offset = 0;
bit = 0;
proto_tree_add_ascii_7bits_item(tree, hf_index, tvb_out, (offset << 3) + bit, num_fields);
break;
case 0x03: /* IA5 */
offset = 0;
bit = 0;
ustr = tvb_get_ascii_7bits_string(pinfo->pool, tvb_out, (offset << 3) + bit, num_fields);
IA5_7BIT_decode(ansi_637_bigbuf, ustr, num_fields);
proto_tree_add_string(tree, hf_index, tvb_out, 0,
required_octs, ansi_637_bigbuf);
break;
case 0x04: /* UNICODE */
offset = 0;
proto_tree_add_item(tree, hf_index, tvb_out, offset, num_fields*2, ENC_UCS_2|ENC_BIG_ENDIAN);
break;
case 0x07: /* Latin/Hebrew */
offset = 0;
proto_tree_add_item(tree, hf_index, tvb_out, offset, num_fields, ENC_ISO_8859_8|ENC_NA);
break;
case 0x08: /* Latin */
offset = 0;
proto_tree_add_item(tree, hf_index, tvb_out, offset, num_fields, ENC_ISO_8859_1|ENC_NA);
break;
case 0x09: /* GSM 7-bit default alphabet */
offset = 0;
bit = fill_bits;
proto_tree_add_ts_23_038_7bits_packed_item(tree, hf_index, tvb_out, (offset << 3) + bit, num_fields);
break;
case 0x10: /* KSC5601 (Korean) */
offset = 0;
proto_tree_add_item_ret_string(tree, hf_index, tvb_out, offset, required_octs, ENC_EUC_KR|ENC_NA, pinfo->pool, &ustr);
if (ustr == NULL)
proto_tree_add_expert_format(tree, pinfo, &ei_ansi_637_failed_conversion, tvb_out, offset, required_octs,
"Failed iconv conversion on EUC-KR - (report to wireshark.org)");
break;
}
}
static void
tele_param_timestamp(tvbuff_t *tvb, packet_info *pinfo , 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)
{
guint8 oct;
guint16 temp;
const gchar *str = NULL;
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);
offset += 1;
oct = tvb_get_guint8(tvb, offset);
temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f) - 1;
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);
offset += 1;
oct = tvb_get_guint8(tvb, offset);
temp = (((oct & 0xf0) >> 4) * 10) + (oct & 0x0f);
proto_tree_add_uint_format_value(tree, hf_day, 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_hours, 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_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_cmas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
proto_tree *subtree;
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;
const gchar *str = NULL;
SHORT_DATA_CHECK(len, 2);
value = tvb_get_ntohs(tvb, offset);
/*
* must be encoded as 'Octet, unspecified'
*/
if ((value & 0xf800) != 0)
{
proto_tree_add_expert(tree, pinfo, &ei_ansi_637_unknown_encoding, tvb, offset, len);
return;
}
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);
proto_tree_add_item(tree, hf_ansi_637_tele_cmas_num_fields, tvb, offset, 2, ENC_BIG_ENDIAN);
num_fields = (value & 0x07f8) >> 3;
offset += 2;
/* NOTE: there are now 3 bits remaining in 'value' */
unused_bits = 3;
required_octs = num_fields;
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");
temp_offset = offset;
offset = 0;
proto_tree_add_item(tree, hf_ansi_637_tele_cmas_protocol_version, tvb_out, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
while ((required_octs - offset) > 2)
{
record_type = tvb_get_guint8(tvb_out, offset);
subtree_idx = record_type;
switch (record_type)
{
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;
}
record_len = tvb_get_guint8(tvb_out, offset + 1);
subtree =
proto_tree_add_subtree(tree, tvb_out, offset, record_len + 2,
ett_tia_1149_cmas_param[subtree_idx], NULL, str);
proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_record_type, tvb_out, offset, 1,
record_type,
"%s",
str);
offset += 1;
proto_tree_add_uint_format_value(subtree, hf_ansi_637_tele_cmas_record_len, tvb_out, offset, 1,
record_len,
"%u",
record_len);
offset += 1;
switch (record_type)
{
default:
proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_unknown_cmas_record_type, tvb_out, offset, record_len);
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;
if (num_fields) {
text_decoder(tvb_out, pinfo, subtree, temp_offset, encoding, num_fields, num_bits,
3 /* (5 bits used from 'temp_offset' octet for encoding */, 0, hf_ansi_637_tele_cmas_text);
}
offset += (record_len - 1);
if (reserved_bits > 0)
proto_tree_add_bits_item(subtree, hf_ansi_637_reserved_bits_8_generic, tvb_out, (offset*8)+(8-reserved_bits), reserved_bits, ENC_NA);
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;
}
}
EXTRANEOUS_DATA_CHECK(required_octs, offset);
offset += temp_offset; /* move 'offset' back to the correct spot in 'tvb' */
proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_07, tvb, offset, 1, ENC_BIG_ENDIAN);
}
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 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;
tvbuff_t *tvb_out;
enum character_set cset;
SHORT_DATA_CHECK(len, 2);
orig_offset = offset;
reserved_bits = len * 8;
value = tvb_get_ntohs(tvb, offset);
encoding = (guint8) ((value & 0xf800) >> 11);
str = val_to_str_const(encoding, ansi_tsb58_encoding_vals, "Reserved");
switch (encoding)
{
case 0x00:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x10:
encoding_bit_len = 8;
cset = OTHER;
break;
case 0x01:
case 0x02:
case 0x03:
default:
encoding_bit_len = 7;
cset = ASCII_7BITS;
break;
case 0x04:
encoding_bit_len = 16;
cset = UCS2;
break;
case 0x09:
encoding_bit_len = 7;
cset = GSM_7BITS;
break;
}
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)
{
proto_tree_add_item(tree, hf_ansi_637_tele_user_data_message_type, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 1;
value = tvb_get_ntohs(tvb, offset);
reserved_bits -= 8;
}
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)
{
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)
{
/*
* 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);
}
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;
fill_bits = 0;
if (encoding_bit_len == 16) {
/* the NUM_FIELD value represents the number of characters in Unicode encoding.
Let's translate it into bytes */
num_fields <<= 1;
}
dis_field_udh(tvb_out, pinfo, tree, &offset, &required_octs, &num_fields, cset, &fill_bits, &udh_fields);
offset = saved_offset;
if (encoding_bit_len == 7)
{
switch (cset)
{
case ASCII_7BITS:
if (fill_bits > unused_bits)
{
/* this branch was NOT tested */
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;
default:
break;
}
} else if (encoding_bit_len == 16) {
/* compute the number of Unicode characters now that UDH is taken into account */
num_fields >>= 1;
}
if (udh_fields.frags > 0)
{
col_append_fstr(pinfo->cinfo, COL_INFO, " (Short Message fragment %u of %u)", udh_fields.frag, udh_fields.frags);
}
}
if (num_fields) {
text_decoder(tvb, pinfo, tree, offset, encoding, num_fields,
num_fields * encoding_bit_len, unused_bits, fill_bits, hf_ansi_637_tele_user_data_text);
}
if (reserved_bits > 0)
{
/*
* 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
*/
switch (cset)
{
case GSM_7BITS:
{
crumb_spec_t crumbs[3];
guint8 i = 0;
guint bits_offset;
if (reserved_bits > 3) {
bits_offset = ((orig_offset + len - 2)*8)+5;
crumbs[i].crumb_bit_offset = 0;
crumbs[i++].crumb_bit_length = reserved_bits - 3;
crumbs[i].crumb_bit_offset = 8;
} else {
bits_offset = ((orig_offset + len - 1)*8)+5;
crumbs[i].crumb_bit_offset = 0;
}
crumbs[i++].crumb_bit_length = 3;
crumbs[i].crumb_bit_offset = 0;
crumbs[i].crumb_bit_length = 0;
proto_tree_add_split_bits_item_ret_val(tree, hf_ansi_637_reserved_bits_16_generic, tvb, bits_offset, crumbs, NULL);
}
break;
default:
proto_tree_add_bits_item(tree, hf_ansi_637_reserved_bits_8_generic, tvb, ((orig_offset + len - 1)*8)+(8-reserved_bits), reserved_bits, ENC_NA); /* LSBs */
break;
}
}
}
static void
tele_param_rsp_code(tvbuff_t *tvb, packet_info *pinfo, 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_response_code, tvb, offset, 1, ENC_BIG_ENDIAN);
}
static void
tele_param_message_center_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
EXACT_DATA_CHECK(len, 6);
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);
}
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);
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_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;
oct = tvb_get_guint8(tvb, offset);
switch (oct)
{
case 245: str = "Indefinite"; break;
case 246: str = "Immediate"; break;
case 247: str = "Valid until mobile becomes inactive/Deliver when mobile next becomes active"; break;
case 248: str = "Valid until registration area changes, discard if not registered" ; break;
default:
if (oct <= 143) { value = (oct + 1) * 5; str2 = "Minutes"; break; }
else if ((oct >= 144) && (oct <= 167)) { value = (oct - 143) * 30; str2 = "Minutes + 12 Hours"; break; }
else if ((oct >= 168) && (oct <= 196)) { value = oct - 166; str2 = "Days"; break; }
else if ((oct >= 197) && (oct <= 244)) { value = oct - 192; str2 = "Weeks"; break; }
else { str = "Reserved"; break; }
}
if (str != NULL)
{
proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1,
oct,
"%s",
str);
}
else
{
proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1,
oct,
"%u %s",
value, str2);
}
}
static void
tele_param_validity_period_rel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
EXACT_DATA_CHECK(len, 1);
tele_param_timestamp_rel(tvb, pinfo, tree, len, offset, hf_ansi_637_tele_validity_period_relative_validity);
}
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);
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_deferred_del_rel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
EXACT_DATA_CHECK(len, 1);
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_pri_ind(tvbuff_t *tvb, packet_info *pinfo, 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_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);
}
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 }
};
static void
tele_param_priv_ind(tvbuff_t *tvb, packet_info *pinfo, 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_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_reply_opt(tvbuff_t *tvb, packet_info *pinfo, 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_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_num_messages(tvbuff_t *tvb, packet_info *pinfo, 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_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);
}
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 }
};
static void
tele_param_alert(tvbuff_t *tvb, packet_info *pinfo, 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, 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_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, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
guint8 oct, oct2, num_fields, odd;
guint8 *poctets;
guint32 saved_offset;
guint32 required_octs;
guint32 i;
SHORT_DATA_CHECK(len, 2);
proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_digit_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
oct = tvb_get_guint8(tvb, offset);
if (oct & 0x80)
{
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;
proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_num_fields, tvb, offset, 1, ENC_BIG_ENDIAN);
num_fields = tvb_get_guint8(tvb, offset);
if (num_fields == 0) return;
SHORT_DATA_CHECK(len - 2, num_fields);
offset += 1;
poctets = tvb_get_string_enc(pinfo->pool, tvb, offset, num_fields, ENC_ASCII|ENC_NA);
proto_tree_add_string_format(tree, hf_ansi_637_tele_cb_num_number, tvb, offset, num_fields,
(gchar *) poctets,
"Number: %s",
(gchar *) format_text(pinfo->pool, poctets, num_fields));
}
else
{
offset += 1;
oct2 = tvb_get_guint8(tvb, offset);
num_fields = ((oct & 0x7f) << 1) | ((oct2 & 0x80) >> 7);
proto_tree_add_item(tree, hf_ansi_637_tele_cb_num_num_fields07f8, tvb, offset, 2, ENC_BIG_ENDIAN);
oct = oct2;
odd = FALSE;
if (num_fields > 0)
{
i = (num_fields - 1) * 4;
required_octs = (i / 8) + ((i % 8) ? 1 : 0);
SHORT_DATA_CHECK(len - 2, required_octs);
odd = num_fields & 0x01;
memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
saved_offset = offset;
offset += 1;
i = 0;
while (i < num_fields)
{
ansi_637_bigbuf[i] = air_digits[(oct & 0x78) >> 3];
i += 1;
if (i >= num_fields) break;
oct2 = tvb_get_guint8(tvb, offset);
offset += 1;
ansi_637_bigbuf[i] = air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)];
oct = oct2;
i += 1;
}
proto_tree_add_string_format(tree, hf_ansi_637_tele_cb_num_number, tvb, saved_offset, offset - saved_offset,
ansi_637_bigbuf,
"Number: %s",
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, 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_mult_enc_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
guint64 encoding;
guint8 encoding_bit_len;
guint64 num_fields;
guint8 unused_bits;
guint8 fill_bits;
guint16 reserved_bits;
guint32 orig_offset;
enum character_set cset = OTHER;
SHORT_DATA_CHECK(len, 2);
orig_offset = offset;
offset <<= 3;
reserved_bits = len * 8;
while (reserved_bits > 7) {
proto_tree_add_bits_ret_val(tree, hf_ansi_637_tele_mult_enc_user_data_encoding,
tvb, offset, 5, &encoding, ENC_BIG_ENDIAN);
switch (encoding) {
case 0x00:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x10:
encoding_bit_len = 8;
cset = OTHER;
break;
case 0x01:
case 0x02:
case 0x03:
default:
encoding_bit_len = 7;
cset = ASCII_7BITS;
break;
case 0x04:
encoding_bit_len = 16;
cset = UCS2;
break;
case 0x09:
encoding_bit_len = 7;
cset = GSM_7BITS;
break;
}
offset += 5;
reserved_bits -= 5;
proto_tree_add_bits_ret_val(tree, hf_ansi_637_tele_mult_enc_user_data_num_fields,
tvb, offset, 8, &num_fields, ENC_BIG_ENDIAN);
offset += 8;
reserved_bits -= 8;
unused_bits = (offset & 0x07) ? 8 - (offset & 0x07) : 0;
fill_bits = 0;
if (num_fields) {
text_decoder(tvb, pinfo, tree, offset>>3, (guint8)encoding, (guint8)num_fields, (guint8)num_fields * encoding_bit_len,
unused_bits, fill_bits, hf_ansi_637_tele_mult_enc_user_data_text);
offset += (guint8)num_fields * encoding_bit_len;
reserved_bits -= (guint8)num_fields * encoding_bit_len;
}
}
if (reserved_bits > 0)
{
/*
* 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
*/
switch (cset)
{
case GSM_7BITS:
{
crumb_spec_t crumbs[3];
guint8 i = 0;
guint bits_offset;
if (reserved_bits > 3) {
bits_offset = ((orig_offset + len - 2)*8)+5;
crumbs[i].crumb_bit_offset = 0;
crumbs[i++].crumb_bit_length = reserved_bits - 3;
crumbs[i].crumb_bit_offset = 8;
} else {
bits_offset = ((orig_offset + len - 1)*8)+5;
crumbs[i].crumb_bit_offset = 0;
}
crumbs[i++].crumb_bit_length = 3;
crumbs[i].crumb_bit_offset = 0;
crumbs[i].crumb_bit_length = 0;
proto_tree_add_split_bits_item_ret_val(tree, hf_ansi_637_reserved_bits_16_generic, tvb, bits_offset, crumbs, NULL);
}
break;
default:
proto_tree_add_bits_item(tree, hf_ansi_637_reserved_bits_8_generic, tvb, ((orig_offset + len - 1)*8)+(8-reserved_bits), reserved_bits, ENC_NA); /* LSBs */
break;
}
}
}
static void
tele_param_msg_deposit_idx(tvbuff_t *tvb, packet_info *pinfo, 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_data_op_code_vals[] = {
{ 0x00, "Delete the Service Category" },
{ 0x01, "Add the Service Category" },
{ 0x02, "Clear all Service Categories" },
{ 0x00, NULL}
};
static const value_string tele_param_srvc_cat_prog_data_alert_option_vals[] = {
{ 0x00, "No alert" },
{ 0x01, "Mobile Station default alert" },
{ 0x02, "Vibrate alert once" },
{ 0x03, "Vibrate alert - repeat" },
{ 0x04, "Visual alert once" },
{ 0x05, "Visual alert - repeat" },
{ 0x06, "Low-priority alert once" },
{ 0x07, "Low-priority alert - repeat" },
{ 0x08, "Medium-priority alert once" },
{ 0x09, "Medium-priority alert - repeat" },
{ 0x0a, "High-priority alert once" },
{ 0x0b, "High-priority alert - repeat" },
{ 0x00, NULL}
};
static void
tele_param_srvc_cat_prog_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
guint64 encoding;
guint8 encoding_bit_len;
guint64 num_fields;
guint8 unused_bits;
guint8 fill_bits;
guint16 reserved_bits;
guint32 orig_offset;
enum character_set cset = OTHER;
SHORT_DATA_CHECK(len, 2);
orig_offset = offset;
offset <<= 3;
reserved_bits = len * 8;
proto_tree_add_bits_ret_val(tree, hf_ansi_637_tele_srvc_cat_prog_data_encoding,
tvb, offset, 5, &encoding, ENC_BIG_ENDIAN);
switch (encoding) {
case 0x00:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x10:
encoding_bit_len = 8;
cset = OTHER;
break;
case 0x01:
case 0x02:
case 0x03:
default:
encoding_bit_len = 7;
cset = ASCII_7BITS;
break;
case 0x04:
encoding_bit_len = 16;
cset = OTHER;
break;
case 0x09:
encoding_bit_len = 7;
cset = GSM_7BITS;
break;
}
offset += 5;
reserved_bits -= 5;
while (reserved_bits > 7) {
proto_tree_add_bits_item(tree, hf_ansi_637_tele_srvc_cat_prog_data_operation_code,
tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
reserved_bits -= 4;
proto_tree_add_bits_item(tree, hf_ansi_637_tele_srvc_cat_prog_data_category,
tvb, offset, 16, ENC_BIG_ENDIAN);
offset += 16;
reserved_bits -= 16;
proto_tree_add_bits_item(tree, hf_ansi_637_tele_srvc_cat_prog_data_language,
tvb, offset, 8, ENC_BIG_ENDIAN);
offset += 8;
reserved_bits -= 8;
proto_tree_add_bits_item(tree, hf_ansi_637_tele_srvc_cat_prog_data_max_messages,
tvb, offset, 8, ENC_BIG_ENDIAN);
offset += 8;
reserved_bits -= 8;
proto_tree_add_bits_item(tree, hf_ansi_637_tele_srvc_cat_prog_data_alert_option,
tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
reserved_bits -= 4;
proto_tree_add_bits_ret_val(tree, hf_ansi_637_tele_srvc_cat_prog_data_num_fields,
tvb, offset, 8, &num_fields, ENC_BIG_ENDIAN);
offset += 8;
reserved_bits -= 8;
unused_bits = (offset & 0x07) ? 8 - (offset & 0x07) : 0;
fill_bits = 0;
if (num_fields) {
text_decoder(tvb, pinfo, tree, offset>>3, (guint8)encoding, (guint8)num_fields, (guint8)num_fields * encoding_bit_len,
unused_bits, fill_bits, hf_ansi_637_tele_srvc_cat_prog_data_text);
offset += (guint8)num_fields * encoding_bit_len;
reserved_bits -= (guint8)num_fields * encoding_bit_len;
}
}
if (reserved_bits > 0)
{
/*
* 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
*/
switch (cset)
{
case GSM_7BITS:
{
crumb_spec_t crumbs[3];
guint8 i = 0;
guint bits_offset;
if (reserved_bits > 3) {
bits_offset = ((orig_offset + len - 2)*8)+5;
crumbs[i].crumb_bit_offset = 0;
crumbs[i++].crumb_bit_length = reserved_bits - 3;
crumbs[i].crumb_bit_offset = 8;
} else {
bits_offset = ((orig_offset + len - 1)*8)+5;
crumbs[i].crumb_bit_offset = 0;
}
crumbs[i++].crumb_bit_length = 3;
crumbs[i].crumb_bit_offset = 0;
crumbs[i].crumb_bit_length = 0;
proto_tree_add_split_bits_item_ret_val(tree, hf_ansi_637_reserved_bits_16_generic, tvb, bits_offset, crumbs, NULL);
}
break;
default:
proto_tree_add_bits_item(tree, hf_ansi_637_reserved_bits_8_generic, tvb, ((orig_offset + len - 1)*8)+(8-reserved_bits), reserved_bits, ENC_NA); /* LSBs */
break;
}
}
}
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, 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_msg_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gboolean *has_private_data_p _U_)
{
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 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;
}
proto_tree_add_uint_format_value(tree, hf_ansi_637_tele_msg_status_code, tvb, offset, 1,
oct,
"%s (%u)",
str, msg_status_code);
}
static void
tele_param_tp_failure_cause(tvbuff_t *tvb, packet_info *pinfo, 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_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 */
tele_param_mult_enc_user_data, /* Multiple Encoding User Data */
tele_param_msg_deposit_idx, /* Message Deposit Index */
tele_param_srvc_cat_prog_data, /* 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, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
{
guint32 value;
const gchar *str = NULL;
EXACT_DATA_CHECK(len, 2);
value = tvb_get_ntohs(tvb, offset);
ansi_637_trans_tele_id = value;
str = try_val_to_str(value, ansi_tele_id_strings);
if (NULL == str)
{
switch (value)
{
case 1:
str = "Reserved for maintenance";
break;
case 4102:
str = "CDMA Service Category Programming Teleservice (SCPT)";
break;
case 4103:
str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)";
break;
case 32513:
str = "TDMA Cellular Messaging Teleservice";
break;
case 32514:
str = "TDMA Cellular Paging Teleservice (CPT-136)";
break;
case 32515:
str = "TDMA Over-the-Air Activation Teleservice (OATS)";
break;
case 32520:
str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)";
break;
case 32584:
str = "TDMA Segmented System Assisted Mobile Positioning Service";
break;
default:
if ((value >= 2) && (value <= 4095))
{
str = "Reserved for assignment by TIA-41";
}
else if ((value >= 4104) && (value <= 4113))
{
str = "Reserved for GSM1x Teleservice (CDMA)";
}
else if ((value >= 4114) && (value <= 32512))
{
str = "Reserved for assignment by TIA-41";
}
else if ((value >= 32521) && (value <= 32575))
{
str = "Reserved for assignment by this Standard for TDMA MS-based SMEs";
}
else if ((value >= 49152) && (value <= 65535))
{
str = "Reserved for carrier specific teleservices";
}
else
{
str = "Unrecognized Teleservice ID";
}
break;
}
}
/*
* 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);
snprintf(add_string, string_len, " - %s (%u)", str, value);
}
static void
trans_param_srvc_cat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len)
{
guint32 value;
const gchar *str;
EXACT_DATA_CHECK(len, 2);
value = tvb_get_ntohs(tvb, offset);
str = val_to_str_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);
snprintf(add_string, string_len, " - %s (%u)", 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, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
{
guint8 oct, oct2, odd;
gboolean email_addr;
guint32 i, saved_offset, required_octs;
guint64 num_fields;
tvbuff_t *tvb_out;
SHORT_DATA_CHECK(len, 2);
oct = tvb_get_guint8(tvb, offset);
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)
{
email_addr = (((oct & 0x38) >> 3) == 0x02) ? TRUE : FALSE;
/*
* 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);
proto_tree_add_bits_ret_val(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, (offset*8)+5, 8, &num_fields, ENC_BIG_ENDIAN);
if (num_fields == 0) return;
offset += 1;
SHORT_DATA_CHECK(len - 2, num_fields);
tvb_out = tvb_new_octet_aligned(tvb, offset*8 + 5, (gint)num_fields*8);
add_new_data_source(pinfo, tvb_out, "Address");
if (email_addr)
{
proto_tree_add_item(tree, hf_ansi_637_trans_addr_param_number, tvb_out, 0, (gint)num_fields,
ENC_ASCII);
}
else
{
proto_tree_add_item(tree, hf_ansi_637_trans_bin_addr, tvb_out, 0, (gint)num_fields, ENC_NA);
}
offset += ((guint32)num_fields);
proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_07, tvb, offset, 1, ENC_BIG_ENDIAN);
}
else
{
/*
* 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);
proto_tree_add_item(tree, hf_ansi_637_trans_addr_param_plan, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_bits_ret_val(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, (offset*8)+1, 8, &num_fields, ENC_BIG_ENDIAN);
offset += 1;
if (num_fields == 0) return;
SHORT_DATA_CHECK(len - 3, num_fields);
tvb_out = tvb_new_octet_aligned(tvb, offset*8 + 1, (gint)num_fields*8);
add_new_data_source(pinfo, tvb_out, "Address");
proto_tree_add_item(tree, hf_ansi_637_trans_addr_param_number, tvb_out, 0, (gint)num_fields,
ENC_ASCII);
offset += ((guint32)num_fields);
proto_tree_add_item(tree, hf_ansi_637_reserved_bits_8_7f, tvb, offset, 1, ENC_BIG_ENDIAN);
}
}
else
{
proto_tree_add_bits_ret_val(tree, hf_ansi_637_trans_addr_param_num_fields, tvb, (offset*8)+2, 8, &num_fields, ENC_BIG_ENDIAN);
offset += 1;
oct = tvb_get_guint8(tvb, offset);
odd = FALSE;
if (num_fields > 0)
{
i = ((guint32)num_fields - 1) * 4;
required_octs = (i / 8) + ((i % 8) ? 1 : 0);
SHORT_DATA_CHECK(len - 2, required_octs);
odd = num_fields & 0x01;
memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
saved_offset = offset;
offset += 1;
i = 0;
while (i < num_fields)
{
ansi_637_bigbuf[i] =
air_digits[(oct & 0x3c) >> 2];
i += 1;
if (i >= num_fields) break;
oct2 = tvb_get_guint8(tvb, offset);
offset += 1;
ansi_637_bigbuf[i] =
air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)];
oct = oct2;
i += 1;
}
proto_tree_add_string_format(tree, hf_ansi_637_trans_addr_param_number, tvb, saved_offset, offset - saved_offset,
ansi_637_bigbuf,
"Number: %s",
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, proto_tree *tree, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
{
guint8 num_fields;
guint32 value;
tvbuff_t *tvb_out;
SHORT_DATA_CHECK(len, 2);
value = tvb_get_ntohs(tvb, offset);
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);
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);
num_fields = (value & 0x0ff0) >> 4;
if (num_fields == 0) return;
SHORT_DATA_CHECK(len - 2, num_fields);
offset += 1;
tvb_out = tvb_new_octet_aligned(tvb, offset*8 + 4, num_fields*8);
add_new_data_source(pinfo, tvb_out, "Subaddress");
proto_tree_add_item(tree, hf_ansi_637_trans_bin_addr, tvb_out, 0, num_fields, ENC_NA);
offset += num_fields;
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)
{
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);
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;
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);
oct = tvb_get_guint8(tvb, offset);
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)
{
case 0: str = "Address vacant"; break;
case 1: str = "Address translation failure"; break;
case 2: str = "Network resource shortage"; break;
case 3: str = "Network failure"; break;
case 4: str = "Invalid Teleservice ID"; break;
case 5: str = "Other network problem"; break;
case 6: str = "Unsupported network interface"; break;
case 32: str = "No page response"; break;
case 33: str = "Destination busy"; break;
case 34: str = "No acknowledgement"; break;
case 35: str = "Destination resource shortage"; break;
case 36: str = "SMS delivery postponed"; break;
case 37: str = "Destination out of service"; break;
case 38: str = "Destination no longer at this address"; break;
case 39: str = "Other terminal problem"; break;
case 64: str = "Radio interface resource shortage"; break;
case 65: str = "Radio interface incompatibility"; break;
case 66: str = "Other radio interface problem"; break;
case 67: str = "Unsupported Base Station Capability"; break;
case 96: str = "Encoding problem"; break;
case 97: str = "Service origination denied"; break;
case 98: str = "Service termination denied"; break;
case 99: str = "Supplementary service not supported"; break;
case 100: str = "Service not supported"; break;
case 101: str = "Reserved"; break;
case 102: str = "Missing expected parameter"; break;
case 103: str = "Missing mandatory parameter"; break;
case 104: str = "Unrecognized parameter value"; break;
case 105: str = "Unexpected parameter value"; break;
case 106: str = "User Data size error"; break;
case 107: str = "Other general problems"; break;
case 108: str = "Session not active"; break;
default:
if ((oct >= 7) && (oct <= 31)) { str = "Reserved, treat as Other network problem"; }
else if ((oct >= 40) && (oct <= 47)) { str = "Reserved, treat as Other terminal problem"; }
else if ((oct >= 48) && (oct <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
else if ((oct >= 68) && (oct <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
else if ((oct >= 109) && (oct <= 223)) { str = "Reserved, treat as Other general problems"; }
else { str = "Reserved for protocol extension, treat as Other general problems"; }
break;
}
proto_tree_add_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 _U_, guint len, guint32 offset, gchar *add_string _U_, int string_len _U_)
{
tvbuff_t *tele_tvb;
/*
* dissect the embedded teleservice data
*/
tele_tvb = tvb_new_subset_length(tvb, offset, len);
dissector_try_uint(tele_dissector_table, ansi_637_trans_tele_id, tele_tvb, pinfo, g_tree);
}
#define NUM_TRANS_PARAM (sizeof(ansi_trans_param_strings)/sizeof(value_string))
static gint ett_ansi_637_trans_param[NUM_TRANS_PARAM];
static void (*ansi_637_trans_param_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint len, guint32 offset, gchar *add_string, int string_len) = {
trans_param_tele_id, /* Teleservice Identifier */
trans_param_srvc_cat, /* Service Category */
trans_param_address, /* Originating Address */
trans_param_subaddress, /* Originating Subaddress */
trans_param_address, /* Destination Address */
trans_param_subaddress, /* Destination Subaddress */
trans_param_bearer_reply_opt, /* Bearer Reply Option */
trans_param_cause_codes, /* Cause Codes */
trans_param_bearer_data, /* Bearer Data */
NULL, /* NONE */
};
#define NUM_TRANS_MSG_TYPE (sizeof(ansi_trans_msg_type_strings)/sizeof(value_string))
static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
/* GENERIC IS-637 DISSECTOR FUNCTIONS */
static gboolean
dissect_ansi_637_tele_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset, gboolean *has_private_data_p)
{
void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gboolean *) = NULL;
guint8 oct;
guint8 len;
guint32 curr_offset;
gint ett_param_idx, idx;
proto_tree *subtree;
proto_item *item;
const gchar *str = NULL;
curr_offset = *offset;
oct = tvb_get_guint8(tvb, curr_offset);
str = try_val_to_str_idx_ext((guint32) oct, &ansi_tele_param_strings_ext, &idx);
if (NULL == str)
{
return(FALSE);
}
ett_param_idx = ett_ansi_637_tele_param[idx];
param_fcn = ansi_637_tele_param_fcn[idx];
subtree =
proto_tree_add_subtree(tree, tvb, curr_offset, -1,
ett_param_idx, &item, str);
proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id, tvb, curr_offset, 1, oct);
curr_offset += 1;
len = tvb_get_guint8(tvb, curr_offset);
proto_item_set_len(item, (curr_offset - *offset) + len + 1);
proto_tree_add_uint(subtree, hf_ansi_637_tele_length, tvb, curr_offset, 1, len);
curr_offset += 1;
if (len > 0)
{
if (param_fcn == NULL)
{
proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_no_tele_parameter_dissector, tvb, curr_offset, len);
}
else
{
/*
* 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;
}
*offset = curr_offset;
return(TRUE);
}
static void
dissect_ansi_637_tele_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ansi_637_tree, gboolean *has_private_data_p)
{
guint8 len;
guint32 curr_offset;
curr_offset = 0;
len = tvb_reported_length(tvb);
while ((len - curr_offset) > 0)
{
if (!dissect_ansi_637_tele_param(tvb, pinfo, ansi_637_tree, &curr_offset, has_private_data_p))
{
proto_tree_add_expert(ansi_637_tree, pinfo, &ei_ansi_637_unknown_tele_parameter, tvb, curr_offset, len - curr_offset);
break;
}
}
}
static int
dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ansi_637_item;
proto_tree *ansi_637_tree = NULL;
const gchar *str = NULL;
guint32 value;
gboolean has_private_data = FALSE;
col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
/* In the interest of speed, if "tree" is NULL, don't do any work not
* necessary to generate protocol tree items.
*/
if (tree)
{
g_tree = tree;
value = pinfo->match_uint;
/*
* create the ansi_637 protocol tree
*/
str = try_val_to_str(value, ansi_tele_id_strings);
if (NULL == str)
{
switch (value)
{
case 1:
str = "Reserved for maintenance";
break;
case 4102:
str = "CDMA Service Category Programming Teleservice (SCPT)";
break;
case 4103:
str = "CDMA Card Application Toolkit Protocol Teleservice (CATPT)";
break;
case 32513:
str = "TDMA Cellular Messaging Teleservice";
break;
case 32514:
str = "TDMA Cellular Paging Teleservice (CPT-136)";
break;
case 32515:
str = "TDMA Over-the-Air Activation Teleservice (OATS)";
break;
case 32520:
str = "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)";
break;
case 32584:
str = "TDMA Segmented System Assisted Mobile Positioning Service";
break;
default:
if ((value >= 2) && (value <= 4095))
{
str = "Reserved for assignment by TIA-41";
}
else if ((value >= 4104) && (value <= 4113))
{
str = "Reserved for GSM1x Teleservice (CDMA)";
}
else if ((value >= 4114) && (value <= 32512))
{
str = "Reserved for assignment by TIA-41";
}
else if ((value >= 32521) && (value <= 32575))
{
str = "Reserved for assignment by this Standard for TDMA MS-based SMEs";
}
else if ((value >= 49152) && (value <= 65535))
{
str = "Reserved for carrier specific teleservices";
}
else
{
str = "Unrecognized Teleservice ID";
}
break;
}
}
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);
dissect_ansi_637_tele_message(tvb, pinfo, ansi_637_tree, &has_private_data);
}
return tvb_captured_length(tvb);
}
static gboolean
dissect_ansi_637_trans_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *offset)
{
void (*param_fcn)(tvbuff_t *, packet_info *, proto_tree *, guint, guint32, gchar *, int) = NULL;
guint8 oct;
guint8 len;
guint32 curr_offset;
gint ett_param_idx, idx;
proto_tree *subtree;
proto_item *item;
const gchar *str;
curr_offset = *offset;
oct = tvb_get_guint8(tvb, curr_offset);
str = try_val_to_str_idx((guint32) oct, ansi_trans_param_strings, &idx);
if (NULL == str)
{
return(FALSE);
}
ett_param_idx = ett_ansi_637_trans_param[idx];
param_fcn = ansi_637_trans_param_fcn[idx];
subtree = proto_tree_add_subtree(tree, tvb, curr_offset, -1, ett_param_idx, &item, str);
proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id, tvb, curr_offset, 1, oct);
curr_offset += 1;
len = tvb_get_guint8(tvb, curr_offset);
proto_item_set_len(item, (curr_offset - *offset) + len + 1);
proto_tree_add_uint(subtree, hf_ansi_637_trans_length, tvb, curr_offset, 1, len);
curr_offset += 1;
if (len > 0)
{
if (param_fcn == NULL)
{
proto_tree_add_expert(subtree, pinfo, &ei_ansi_637_no_trans_parameter_dissector, tvb, curr_offset, len);
}
else
{
gchar *ansi_637_add_string;
ansi_637_add_string = (gchar *) wmem_alloc(pinfo->pool, 1024);
ansi_637_add_string[0] = '\0';
(*param_fcn)(tvb, pinfo, subtree, len, curr_offset, ansi_637_add_string, 1024);
if (ansi_637_add_string[0] != '\0')
{
proto_item_append_text(item, "%s", ansi_637_add_string);
}
}
curr_offset += len;
}
*offset = curr_offset;
return(TRUE);
}
static int
dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ansi_637_item;
proto_tree *ansi_637_tree = NULL;
guint32 curr_offset;
gint idx;
const gchar *str = NULL;
guint8 oct;
guint8 len;
col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
/* In the interest of speed, if "tree" is NULL, don't do any work not
* necessary to generate protocol tree items.
*/
if (tree)
{
g_tree = tree;
/*
* reset the teleservice ID for each dissection
*/
ansi_637_trans_tele_id = 0;
/*
* create the ansi_637 protocol tree
*/
oct = tvb_get_guint8(tvb, 0);
str = try_val_to_str_idx(oct, ansi_trans_msg_type_strings, &idx);
if (NULL == str)
{
ansi_637_item =
proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
"%s - Unrecognized Transport Layer Message Type (%u)",
ansi_proto_name_trans, oct);
ansi_637_tree = proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans);
}
else
{
ansi_637_item =
proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
"%s - %s",
ansi_proto_name_trans, str);
ansi_637_tree = proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]);
if (oct == ANSI_TRANS_MSG_TYPE_BROADCAST)
{
/*
* there is no teleservice ID for Broadcast but we want the
* bearer data to be dissected
*
* using a reserved value to key dissector port
*/
ansi_637_trans_tele_id = INTERNAL_BROADCAST_TELE_ID;
col_append_str(pinfo->cinfo, COL_INFO, "(BROADCAST)");
}
}
curr_offset = 1;
len = tvb_reported_length(tvb);
while ((len - curr_offset) > 0)
{
if (!dissect_ansi_637_trans_param(tvb, pinfo, ansi_637_tree, &curr_offset))
{
proto_tree_add_expert(ansi_637_tree, pinfo, &ei_ansi_637_unknown_trans_parameter, tvb, curr_offset, len - curr_offset);
break;
}
}
}
return tvb_captured_length(tvb);
}
/* Dissect SMS embedded in SIP */
static int
dissect_ansi_637_trans_app(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "/");
col_set_fence(pinfo->cinfo, COL_INFO);
return dissect_ansi_637_trans(tvb, pinfo, tree, data);
}
/* Register the protocol with Wireshark */
void
proto_register_ansi_637(void)
{
guint i;
/* Setup list of header fields */
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 }
},
{ &hf_ansi_637_trans_length,
{ "Length", "ansi_637_trans.len",
FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_trans_bin_addr,
{ "Binary Address", "ansi_637_trans.bin_addr",
FT_BYTES, BASE_NONE, 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_UINT16, BASE_DEC, VALS(ansi_a_ms_info_rec_num_plan_vals), 0x0780,
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, 0x0,
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",
"ansi_637_tele.msg_type",
FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
NULL, HFILL }
},
{ &hf_ansi_637_tele_msg_id,
{ "Message ID",
"ansi_637_tele.msg_id",
FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_length,
{ "Length", "ansi_637_tele.len",
FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_msg_status,
{ "Message Status",
"ansi_637_tele.msg_status",
FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ansi_tele_msg_status_strings_ext, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_msg_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",
"ansi_637_tele.msg_rsvd",
FT_UINT24, BASE_DEC, NULL, 0x000007,
NULL, HFILL }
},
{ &hf_ansi_637_tele_subparam_id,
{ "Teleservice Subparam ID", "ansi_637_tele.subparam_id",
FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ansi_tele_param_strings_ext, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_user_data_text,
{ "Encoded user data", "ansi_637_tele.user_data.text",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &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_num_fields07f8,
{ "Number of fields", "ansi_637_tele.cb_num.num_fields",
FT_UINT16, BASE_DEC, NULL, 0x07F8,
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_reserved_bits_16_generic,
{ "Reserved bit(s)", "ansi_637_tele.reserved",
FT_UINT16, BASE_DEC, NULL, 0,
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 }
},
{ &hf_ansi_637_tele_cmas_text,
{ "CMAE_alert_text", "ansi_637_tele.cmas.text",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_mult_enc_user_data_encoding,
{ "Encoding", "ansi_637_tele.mult_enc_user_data.encoding",
FT_UINT8, BASE_DEC, VALS(ansi_tsb58_encoding_vals), 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_mult_enc_user_data_num_fields,
{ "Number of fields", "ansi_637_tele.mult_enc_user_data.num_fields",
FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_mult_enc_user_data_text,
{ "Encoded user data", "ansi_637_tele.mult_enc_user_data.text",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_encoding,
{ "Encoding", "ansi_637_tele.srvc_cat_prog_data.encoding",
FT_UINT8, BASE_DEC, VALS(ansi_tsb58_encoding_vals), 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_operation_code,
{ "Operation code", "ansi_637_tele.srvc_cat_prog_data.operation_code",
FT_UINT8, BASE_DEC, VALS(tele_param_srvc_cat_prog_data_op_code_vals), 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_category,
{ "Operation code", "ansi_637_tele.srvc_cat_prog_data.category",
FT_UINT16, BASE_DEC|BASE_EXT_STRING, &ansi_tsb58_srvc_cat_vals_ext, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_language,
{ "Operation code", "ansi_637_tele.srvc_cat_prog_data.language",
FT_UINT8, BASE_DEC|BASE_EXT_STRING, &ansi_tsb58_language_ind_vals_ext, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_max_messages,
{ "Maximum number of messages", "ansi_637_tele.srvc_cat_prog_data.max_messages",
FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_alert_option,
{ "Alert option", "ansi_637_tele.srvc_cat_prog_data.alert_option",
FT_UINT8, BASE_DEC, VALS(tele_param_srvc_cat_prog_data_alert_option_vals), 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_num_fields,
{ "Number of fields", "ansi_637_tele.srvc_cat_prog_data.num_fields",
FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_ansi_637_tele_srvc_cat_prog_data_text,
{ "Encoded program data", "ansi_637_tele.srvc_cat_prog_data.text",
FT_STRING, BASE_NONE, 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 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_ansi_637_header_ind;
ett[3] = &ett_params;
for (i=0; i < NUM_TELE_PARAM; i++)
{
ett_ansi_637_tele_param[i] = -1;
ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_637_tele_param[i];
}
for (i=0; i < NUM_TRANS_MSG_TYPE; i++)
{
ett_ansi_637_trans_msg[i] = -1;
ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+i] = &ett_ansi_637_trans_msg[i];
}
for (i=0; i < NUM_TRANS_PARAM; i++)
{
ett_ansi_637_trans_param[i] = -1;
ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i];
}
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");
proto_ansi_637_trans =
proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
ansi_637_tele_handle = register_dissector("ansi_637_tele", dissect_ansi_637_tele, proto_ansi_637_tele);
ansi_637_trans_handle = register_dissector("ansi_637_trans", dissect_ansi_637_trans, proto_ansi_637_trans);
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_ansi_637_tele, hf_tele, array_length(hf_tele));
proto_register_field_array(proto_ansi_637_trans, hf_trans, array_length(hf_trans));
proto_register_subtree_array(ett, array_length(ett));
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", proto_ansi_637_tele, FT_UINT8, BASE_DEC);
}
void
proto_reg_handoff_ansi_637(void)
{
dissector_handle_t ansi_637_trans_app_handle;
guint i;
ansi_637_trans_app_handle = create_dissector_handle(dissect_ansi_637_trans_app, proto_ansi_637_trans);
/* Dissect messages embedded in SIP */
dissector_add_string("media_type", "application/vnd.3gpp2.sms", ansi_637_trans_app_handle);
/*
* register for all known teleservices
* '-1' is to stop before trailing '0' entry
*
* to add teleservices, modify 'ansi_tele_id_strings'
*/
for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++)
{
/*
* ANSI MAP dissector will push out teleservice ids
*/
dissector_add_uint("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
/*
* we will push out teleservice ids after Transport layer decode
*/
dissector_add_uint("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
}
/*
* 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);
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/