diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-sigcomp.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-sigcomp.c')
-rw-r--r-- | epan/dissectors/packet-sigcomp.c | 6932 |
1 files changed, 6932 insertions, 0 deletions
diff --git a/epan/dissectors/packet-sigcomp.c b/epan/dissectors/packet-sigcomp.c new file mode 100644 index 00000000..2ab1467b --- /dev/null +++ b/epan/dissectors/packet-sigcomp.c @@ -0,0 +1,6932 @@ +/* packet-sigcomp.c + * Routines for Signaling Compression (SigComp) dissection. + * Copyright 2004-2005, Anders Broman <anders.broman@ericsson.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + * References: + * https://www.ietf.org/rfc/rfc3320 + * https://www.ietf.org/rfc/rfc3321 + * https://www.ietf.org/rfc/rfc4077 + * Useful links : + * https://tools.ietf.org/html/draft-ietf-rohc-sigcomp-impl-guide-10 + * https://tools.ietf.org/html/draft-ietf-rohc-sigcomp-sip-01 + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/expert.h> +#include <epan/to_str.h> +#include <epan/strutil.h> +#include <epan/exceptions.h> + +#include <wsutil/wsgcrypt.h> +#include <wsutil/crc16.h> +#include <wsutil/pow2.h> + +void proto_register_sigcomp(void); +void proto_reg_handoff_sigcomp(void); + +/* Initialize the protocol and registered fields */ +static int proto_sigcomp = -1; +static int proto_raw_sigcomp = -1; +static int hf_sigcomp_t_bit = -1; +static int hf_sigcomp_len = -1; +static int hf_sigcomp_returned_feedback_item = -1; +static int hf_sigcomp_returned_feedback_item_len = -1; +static int hf_sigcomp_code_len = -1; +static int hf_sigcomp_destination = -1; +static int hf_sigcomp_partial_state = -1; +static int hf_sigcomp_remaining_message_bytes = -1; +static int hf_sigcomp_compression_ratio = -1; +static int hf_sigcomp_udvm_bytecode = -1; +static int hf_sigcomp_udvm_instr = -1; +static int hf_udvm_multitype_bytecode = -1; +static int hf_udvm_reference_bytecode = -1; +static int hf_udvm_literal_bytecode = -1; +/* static int hf_udvm_operand = -1; */ +static int hf_udvm_length = -1; +static int hf_udvm_addr_length = -1; +static int hf_udvm_destination = -1; +static int hf_udvm_addr_destination = -1; +static int hf_udvm_at_address = -1; +static int hf_udvm_address = -1; +static int hf_udvm_literal_num = -1; +static int hf_udvm_value = -1; +static int hf_udvm_addr_value = -1; +static int hf_partial_identifier_start = -1; +static int hf_partial_identifier_length = -1; +static int hf_state_begin = -1; +static int hf_udvm_state_length = -1; +static int hf_udvm_state_length_addr = -1; +static int hf_udvm_state_address = -1; +static int hf_udvm_state_address_addr = -1; +static int hf_udvm_state_instr = -1; +static int hf_udvm_operand_1 = -1; +static int hf_udvm_operand_2 = -1; +static int hf_udvm_operand_2_addr = -1; +static int hf_udvm_j = -1; +static int hf_udvm_addr_j = -1; +static int hf_udvm_output_start = -1; +static int hf_udvm_addr_output_start = -1; +static int hf_udvm_output_length = -1; +static int hf_udvm_output_length_addr = -1; +static int hf_udvm_req_feedback_loc = -1; +static int hf_udvm_min_acc_len = -1; +static int hf_udvm_state_ret_pri = -1; +static int hf_udvm_ret_param_loc = -1; +static int hf_udvm_position = -1; +static int hf_udvm_ref_dest = -1; +static int hf_udvm_bits = -1; +static int hf_udvm_lower_bound = -1; +static int hf_udvm_upper_bound = -1; +static int hf_udvm_uncompressed = -1; +static int hf_udvm_offset = -1; +static int hf_udvm_addr_offset = -1; +static int hf_udvm_start_value = -1; +static int hf_udvm_execution_trace = -1; +static int hf_sigcomp_nack_ver = -1; +static int hf_sigcomp_nack_reason_code = -1; +static int hf_sigcomp_nack_failed_op_code = -1; +static int hf_sigcomp_nack_pc = -1; +static int hf_sigcomp_nack_sha1 = -1; +static int hf_sigcomp_nack_state_id = -1; +static int hf_sigcomp_nack_memory_size = -1; +static int hf_sigcomp_nack_cycles_per_bit = -1; +static int hf_sigcomp_decompress_instruction = -1; +static int hf_sigcomp_loading_result = -1; +static int hf_sigcomp_byte_copy = -1; +/* Generated from convert_proto_tree_add_text.pl */ +static int hf_sigcomp_accessing_state = -1; +static int hf_sigcomp_getting_value = -1; +static int hf_sigcomp_load_bytecode_into_udvm_start = -1; +static int hf_sigcomp_instruction_code = -1; +static int hf_sigcomp_current_instruction = -1; +static int hf_sigcomp_decompression_failure = -1; +static int hf_sigcomp_wireshark_udvm_diagnostic = -1; +static int hf_sigcomp_calculated_sha_1 = -1; +static int hf_sigcomp_copying_value = -1; +static int hf_sigcomp_storing_value = -1; +static int hf_sigcomp_loading_value = -1; +static int hf_sigcomp_set_hu = -1; +static int hf_sigcomp_loading_h = -1; +static int hf_sigcomp_state_value = -1; +static int hf_sigcomp_output_value = -1; +static int hf_sigcomp_num_state_create = -1; +static int hf_sigcomp_sha1_digest = -1; +static int hf_sigcomp_creating_state = -1; +static int hf_sigcomp_sigcomp_message_decompressed = -1; +static int hf_sigcomp_starting_to_remove_escape_digits = -1; +static int hf_sigcomp_escape_digit_found = -1; +static int hf_sigcomp_illegal_escape_code = -1; +static int hf_sigcomp_end_of_sigcomp_message_indication_found = -1; +static int hf_sigcomp_addr_value = -1; +static int hf_sigcomp_copying_bytes_literally = -1; +static int hf_sigcomp_data_for_sigcomp_dissector = -1; +static int hf_sigcomp_remaining_sigcomp_message = -1; +static int hf_sigcomp_sha1buff = -1; +static int hf_sigcomp_udvm_instruction = -1; +static int hf_sigcomp_remaining_bytes = -1; +static int hf_sigcomp_max_udvm_cycles = -1; +static int hf_sigcomp_used_udvm_cycles = -1; +static int hf_sigcomp_udvm_execution_stated = -1; +static int hf_sigcomp_message_length = -1; +static int hf_sigcomp_byte_code_length = -1; + + +/* Initialize the subtree pointers */ +static gint ett_sigcomp = -1; +static gint ett_sigcomp_udvm = -1; +static gint ett_sigcomp_udvm_exe = -1; +static gint ett_raw_text = -1; + +static expert_field ei_sigcomp_nack_failed_op_code = EI_INIT; +static expert_field ei_sigcomp_invalid_instruction = EI_INIT; +static expert_field ei_sigcomp_invalid_shift_value = EI_INIT; +/* Generated from convert_proto_tree_add_text.pl */ +static expert_field ei_sigcomp_tcp_fragment = EI_INIT; +static expert_field ei_sigcomp_decompression_failure = EI_INIT; +static expert_field ei_sigcomp_failed_to_access_state_wireshark_udvm_diagnostic = EI_INIT; +static expert_field ei_sigcomp_all_remaining_parameters_zero = EI_INIT; +static expert_field ei_sigcomp_sigcomp_message_decompression_failure = EI_INIT; +static expert_field ei_sigcomp_execution_of_this_instruction_is_not_implemented = EI_INIT; + +static dissector_handle_t sip_handle; +static dissector_handle_t sigcomp_handle; +static dissector_handle_t sigcomp_tcp_handle; + + +/* set the tcp ports */ +#define SIGCOMP_TCP_PORT_RANGE "5555,6666" /* Not IANA registered */ + +/* Default preference whether to display the bytecode in UDVM operands or not */ +static gboolean display_udvm_bytecode = FALSE; +/* Default preference whether to dissect the UDVM code or not */ +/* WARNING: Setting this to true might result in the entire dissector being + disabled by default or removed completely. */ +static gboolean dissect_udvm_code = FALSE; +static gboolean display_raw_txt = FALSE; +/* Default preference whether to decompress the message or not */ +/* WARNING: Setting this to true might result in the entire dissector being + disabled by default or removed completely. */ +static gboolean decompress = FALSE; +/* Default preference whether to print debug info at execution of UDVM + * 0 = No printout + * 1 = details level 1 + * 2 = details level 2 + * 3 = details level 3 + * 4 = details level 4 + */ +static gint udvm_print_detail_level = 0; + +/* Value strings */ +static const value_string length_encoding_vals[] = { + { 0x00, "No partial state (Message type 2)" }, + { 0x01, "(6 bytes)" }, + { 0x02, "(9 bytes)" }, + { 0x03, "(12 bytes)" }, + { 0, NULL } +}; + + +static const value_string destination_address_encoding_vals[] = { + { 0x00, "Reserved" }, + { 0x01, "128" }, + { 0x02, "192" }, + { 0x03, "256" }, + { 0x04, "320" }, + { 0x05, "384" }, + { 0x06, "448" }, + { 0x07, "512" }, + { 0x08, "576" }, + { 0x09, "640" }, + { 0x0a, "704" }, + { 0x0b, "768" }, + { 0x0c, "832" }, + { 0x0d, "896" }, + { 0x0e, "960" }, + { 0x0F, "1024" }, + { 0, NULL } +}; +static value_string_ext destination_address_encoding_vals_ext = + VALUE_STRING_EXT_INIT(destination_address_encoding_vals); + + /* RFC3320 + * Figure 10: Bytecode for a multitype (%) operand + * Bytecode: Operand value: Range: HEX val + * 00nnnnnn N 0 - 63 0x00 + * 01nnnnnn memory[2 * N] 0 - 65535 0x40 + * 1000011n 2 ^ (N + 6) 64 , 128 0x86 + * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88 + * 111nnnnn N + 65504 65504 - 65535 0xe0 + * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90 + * 101nnnnn nnnnnnnn N 0 - 8191 0xa0 + * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0 + * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80 + * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81 + */ + +static const value_string display_bytecode_vals[] = { + { 0x00, "00nnnnnn, N, 0 - 63" }, + { 0x40, "01nnnnnn, memory[2 * N],0 - 65535" }, + { 0x86, "1000011n, 2 ^ (N + 6), 64 , 128" }, + { 0x88, "10001nnn, 2 ^ (N + 8), 256,..., 32768" }, + { 0xe0, "111nnnnn N + 65504, 65504 - 65535" }, + { 0x90, "1001nnnn nnnnnnnn, N + 61440, 61440 - 65535" }, + { 0xa0, "101nnnnn nnnnnnnn, N, 0 - 8191" }, + { 0xc0, "110nnnnn nnnnnnnn, memory[N], 0 - 65535" }, + { 0x80, "10000000 nnnnnnnn nnnnnnnn, N, 0 - 65535" }, + { 0x81, "10000001 nnnnnnnn nnnnnnnn, memory[N], 0 - 65535" }, + { 0, NULL } +}; +/* RFC3320 + * 0nnnnnnn memory[2 * N] 0 - 65535 + * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 + * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + */ +static const value_string display_ref_bytecode_vals[] = { + { 0x00, "0nnnnnnn memory[2 * N] 0 - 65535" }, + { 0x80, "10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535" }, + { 0xc0, "11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535" }, + { 0, NULL } +}; + /* The simplest operand type is the literal (#), which encodes a + * constant integer from 0 to 65535 inclusive. A literal operand may + * require between 1 and 3 bytes depending on its value. + * Bytecode: Operand value: Range: + * 0nnnnnnn N 0 - 127 + * 10nnnnnn nnnnnnnn N 0 - 16383 + * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535 + * + * Figure 8: Bytecode for a literal (#) operand + * + */ + +static const value_string display_lit_bytecode_vals[] = { + { 0x00, "0nnnnnnn N 0 - 127" }, + { 0x80, "10nnnnnn nnnnnnnn N 0 - 16383" }, + { 0xc0, "11000000 nnnnnnnn nnnnnnnn N 0 - 65535" }, + { 0, NULL } +}; + +#define SIGCOMP_NACK_STATE_NOT_FOUND 1 +#define SIGCOMP_NACK_CYCLES_EXHAUSTED 2 +#define SIGCOMP_NACK_BYTECODES_TOO_LARGE 18 +#define SIGCOMP_NACK_ID_NOT_UNIQUE 21 +#define SIGCOMP_NACK_STATE_TOO_SHORT 23 + +static const value_string sigcomp_nack_reason_code_vals[] = { + { 1, "STATE_NOT_FOUND" }, /*1 State ID (6 - 20 bytes) */ + { 2, "CYCLES_EXHAUSTED" }, /*2 Cycles Per Bit (1 byte) */ + { 3, "USER_REQUESTED" }, + { 4, "SEGFAULT" }, + { 5, "TOO_MANY_STATE_REQUESTS" }, + { 6, "INVALID_STATE_ID_LENGTH" }, + { 7, "INVALID_STATE_PRIORITY" }, + { 8, "OUTPUT_OVERFLOW" }, + { 9, "STACK_UNDERFLOW" }, + { 10, "BAD_INPUT_BITORDER" }, + { 11, "DIV_BY_ZERO" }, + { 12, "SWITCH_VALUE_TOO_HIGH" }, + { 13, "TOO_MANY_BITS_REQUESTED" }, + { 14, "INVALID_OPERAND" }, + { 15, "HUFFMAN_NO_MATCH" }, + { 16, "MESSAGE_TOO_SHORT" }, + { 17, "INVALID_CODE_LOCATION" }, + { 18, "BYTECODES_TOO_LARGE" }, /*18 Memory size (2 bytes) */ + { 19, "INVALID_OPCODE" }, + { 20, "INVALID_STATE_PROBE" }, + { 21, "ID_NOT_UNIQUE" }, /*21 State ID (6 - 20 bytes) */ + { 22, "MULTILOAD_OVERWRITTEN" }, + { 23, "STATE_TOO_SHORT" }, /*23 State ID (6 - 20 bytes) */ + { 24, "INTERNAL_ERROR" }, + { 25, "FRAMING_ERROR" }, + { 0, NULL } +}; +static value_string_ext sigcomp_nack_reason_code_vals_ext = + VALUE_STRING_EXT_INIT(sigcomp_nack_reason_code_vals); + + +static void dissect_udvm_bytecode(tvbuff_t *udvm_tvb, packet_info* pinfo, proto_tree *sigcomp_udvm_tree, guint destination); + +static int dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset,gboolean is_addr,gint *start_offset, + guint16 *value, gboolean *is_memory_address ); + +static int dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset, gint *start_offset, guint16 *value); + +static int dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset, gint *start_offset, guint16 *value); +static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree); + +static int dissect_sigcomp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +static proto_tree *top_tree; + +#define UDVM_MEMORY_SIZE 65536 + +/********************************************************************************************** + * + * SIGCOMP STATE HANDLER + * + **********************************************************************************************/ +#define STATE_BUFFER_SIZE 20 +#define STATE_MIN_ACCESS_LEN 6 + +/* + * Defenitions for: + * The Session Initiation Protocol (SIP) and Session Description Protocol + * (SDP) Static Dictionary for Signaling Compression (SigComp) + * https://www.ietf.org/rfc/rfc3485 + */ +#define SIP_SDP_STATE_LENGTH 0x12e4 + +static const guint8 sip_sdp_state_identifier[STATE_BUFFER_SIZE] = +{ + /* -0000, */ 0xfb, 0xe5, 0x07, 0xdf, 0xe5, 0xe6, 0xaa, 0x5a, 0xf2, 0xab, 0xb9, 0x14, 0xce, 0xaa, 0x05, 0xf9, + /* -0010, */ 0x9c, 0xe6, 0x1b, 0xa5 +}; + +static const guint8 sip_sdp_static_dictionaty_for_sigcomp[0x12e4] = +{ + + /* -0000, */ 0x0d, 0x0a, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, + /* -0010, */ 0x3a, 0x20, 0x0d, 0x0a, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x49, 0x6e, 0x66, 0x6f, 0x3a, 0x20, + /* -0020, */ 0x0d, 0x0a, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x3a, 0x20, 0x0d, 0x0a, 0x43, + /* -0030, */ 0x61, 0x6c, 0x6c, 0x2d, 0x49, 0x6e, 0x66, 0x6f, 0x3a, 0x20, 0x0d, 0x0a, 0x52, 0x65, 0x70, 0x6c, + /* -0040, */ 0x79, 0x2d, 0x54, 0x6f, 0x3a, 0x20, 0x0d, 0x0a, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x3a, + /* -0050, */ 0x20, 0x0d, 0x0a, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x20, 0x3b, 0x68, 0x61, 0x6e, + /* -0060, */ 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x3d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b, 0x70, 0x75, 0x72, 0x70, + /* -0070, */ 0x6f, 0x73, 0x65, 0x3d, 0x3b, 0x63, 0x61, 0x75, 0x73, 0x65, 0x3d, 0x3b, 0x74, 0x65, 0x78, 0x74, + /* -0080, */ 0x3d, 0x63, 0x61, 0x72, 0x64, 0x33, 0x30, 0x30, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, + /* -0090, */ 0x65, 0x20, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x73, 0x73, 0x61, + /* -00A0, */ 0x67, 0x65, 0x2f, 0x73, 0x69, 0x70, 0x66, 0x72, 0x61, 0x67, 0x34, 0x30, 0x37, 0x20, 0x50, 0x72, + /* -00B0, */ 0x6f, 0x78, 0x79, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, + /* -00C0, */ 0x6f, 0x6e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, + /* -00D0, */ 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x34, 0x38, 0x34, 0x20, 0x41, 0x64, + /* -00E0, */ 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + /* -00F0, */ 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x34, 0x39, + /* -0100, */ 0x34, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x41, 0x67, 0x72, 0x65, 0x65, + /* -0110, */ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x65, 0x61, 0x63, + /* -0120, */ 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x34, 0x38, 0x31, 0x20, 0x43, 0x61, 0x6c, 0x6c, 0x2f, + /* -0130, */ 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x6f, 0x65, 0x73, + /* -0140, */ 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x45, 0x78, 0x69, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x3d, 0x35, 0x30, + /* -0150, */ 0x30, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + /* -0160, */ 0x6c, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x6f, 0x62, 0x75, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x72, + /* -0170, */ 0x74, 0x69, 0x6e, 0x67, 0x3d, 0x34, 0x31, 0x36, 0x20, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, + /* -0180, */ 0x72, 0x74, 0x65, 0x64, 0x20, 0x55, 0x52, 0x49, 0x20, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x72, + /* -0190, */ 0x67, 0x65, 0x6e, 0x63, 0x79, 0x34, 0x31, 0x35, 0x20, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, + /* -01A0, */ 0x72, 0x74, 0x65, 0x64, 0x20, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x54, 0x79, 0x70, 0x65, 0x6e, + /* -01B0, */ 0x64, 0x69, 0x6e, 0x67, 0x34, 0x38, 0x38, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x41, 0x63, 0x63, 0x65, + /* -01C0, */ 0x70, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x48, 0x65, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, + /* -01D0, */ 0x64, 0x34, 0x32, 0x33, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x54, 0x6f, + /* -01E0, */ 0x6f, 0x20, 0x42, 0x72, 0x69, 0x65, 0x66, 0x72, 0x6f, 0x6d, 0x2d, 0x74, 0x61, 0x67, 0x51, 0x2e, + /* -01F0, */ 0x38, 0x35, 0x30, 0x35, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x6f, 0x74, + /* -0200, */ 0x20, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x34, 0x30, 0x33, 0x20, 0x46, 0x6f, + /* -0210, */ 0x72, 0x62, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x6f, 0x6e, 0x2d, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, + /* -0220, */ 0x34, 0x32, 0x39, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x52, 0x65, 0x66, 0x65, + /* -0230, */ 0x72, 0x72, 0x6f, 0x72, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x34, 0x32, 0x30, + /* -0240, */ 0x20, 0x42, 0x61, 0x64, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x6f, 0x72, + /* -0250, */ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x0d, 0x0a, 0x61, 0x3d, 0x6b, 0x65, 0x79, 0x2d, 0x6d, + /* -0260, */ 0x67, 0x6d, 0x74, 0x3a, 0x6d, 0x69, 0x6b, 0x65, 0x79, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x53, + /* -0270, */ 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x35, 0x30, 0x34, 0x20, 0x53, + /* -0280, */ 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x2d, 0x6f, 0x75, 0x74, 0x6f, 0x2d, + /* -0290, */ 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + /* -02A0, */ 0x69, 0x6f, 0x6e, 0x2d, 0x49, 0x6e, 0x66, 0x6f, 0x3a, 0x20, 0x44, 0x65, 0x63, 0x20, 0x33, 0x38, + /* -02B0, */ 0x30, 0x20, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x65, + /* -02C0, */ 0x72, 0x76, 0x69, 0x63, 0x65, 0x35, 0x30, 0x33, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + /* -02D0, */ 0x20, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x34, 0x32, 0x31, 0x20, + /* -02E0, */ 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + /* -02F0, */ 0x65, 0x64, 0x34, 0x30, 0x35, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x4e, 0x6f, 0x74, + /* -0300, */ 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x34, 0x38, 0x37, 0x20, 0x52, 0x65, 0x71, 0x75, + /* -0310, */ 0x65, 0x73, 0x74, 0x20, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x61, 0x75, + /* -0320, */ 0x74, 0x68, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x3d, + /* -0330, */ 0x0d, 0x0a, 0x6d, 0x3d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + /* -0340, */ 0x41, 0x75, 0x67, 0x20, 0x35, 0x31, 0x33, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, + /* -0350, */ 0x54, 0x6f, 0x6f, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x36, 0x38, 0x37, 0x20, 0x44, 0x69, 0x61, + /* -0360, */ 0x6c, 0x6f, 0x67, 0x20, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x33, 0x30, + /* -0370, */ 0x32, 0x20, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, + /* -0380, */ 0x69, 0x6c, 0x79, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, + /* -0390, */ 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, + /* -03A0, */ 0x74, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x0d, 0x0a, 0x52, 0x65, 0x74, 0x72, 0x79, 0x2d, + /* -03B0, */ 0x41, 0x66, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x47, 0x4d, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x34, 0x30, + /* -03C0, */ 0x32, 0x20, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + /* -03D0, */ 0x65, 0x64, 0x0d, 0x0a, 0x61, 0x3d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x3a, 0x6c, 0x61, 0x6e, + /* -03E0, */ 0x64, 0x73, 0x63, 0x61, 0x70, 0x65, 0x34, 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, 0x65, + /* -03F0, */ 0x71, 0x75, 0x65, 0x73, 0x74, 0x72, 0x75, 0x65, 0x34, 0x39, 0x31, 0x20, 0x52, 0x65, 0x71, 0x75, + /* -0400, */ 0x65, 0x73, 0x74, 0x20, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x35, 0x30, 0x31, 0x20, 0x4e, + /* -0410, */ 0x6f, 0x74, 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x34, 0x30, + /* -0420, */ 0x36, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x62, 0x6c, 0x65, + /* -0430, */ 0x36, 0x30, 0x36, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x62, + /* -0440, */ 0x6c, 0x65, 0x0d, 0x0a, 0x61, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x62, 0x72, 0x6f, 0x61, 0x64, + /* -0450, */ 0x63, 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x34, 0x39, 0x33, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x63, + /* -0460, */ 0x69, 0x70, 0x68, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x4d, 0x49, 0x4d, 0x45, 0x2d, + /* -0470, */ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x34, 0x38, 0x32, + /* -0480, */ 0x20, 0x4c, 0x6f, 0x6f, 0x70, 0x20, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x0d, 0x0a, + /* -0490, */ 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4a, 0x75, + /* -04A0, */ 0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x6e, 0x65, + /* -04B0, */ 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x3d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x65, + /* -04C0, */ 0x72, 0x74, 0x63, 0x70, 0x2d, 0x66, 0x62, 0x34, 0x38, 0x39, 0x20, 0x42, 0x61, 0x64, 0x20, 0x45, + /* -04D0, */ 0x76, 0x65, 0x6e, 0x74, 0x6c, 0x73, 0x0d, 0x0a, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + /* -04E0, */ 0x74, 0x65, 0x64, 0x3a, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x35, 0x30, 0x32, 0x20, 0x42, 0x61, 0x64, + /* -04F0, */ 0x20, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x68, 0x61, + /* -0500, */ 0x6e, 0x67, 0x65, 0x2d, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x6f, + /* -0510, */ 0x72, 0x69, 0x65, 0x6e, 0x74, 0x3a, 0x73, 0x65, 0x61, 0x73, 0x63, 0x61, 0x70, 0x65, 0x0d, 0x0a, + /* -0520, */ 0x61, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, + /* -0530, */ 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x33, 0x30, 0x35, + /* -0540, */ 0x20, 0x55, 0x73, 0x65, 0x20, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x0d, 0x0a, 0x61, 0x3d, 0x74, 0x79, + /* -0550, */ 0x70, 0x65, 0x3a, 0x72, 0x65, 0x63, 0x76, 0x6f, 0x6e, 0x6c, 0x79, 0x0d, 0x0a, 0x61, 0x3d, 0x74, + /* -0560, */ 0x79, 0x70, 0x65, 0x3a, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x6b, 0x3d, 0x70, + /* -0570, */ 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x3a, 0x0d, 0x0a, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, + /* -0580, */ 0x2d, 0x42, 0x79, 0x3a, 0x20, 0x0d, 0x0a, 0x49, 0x6e, 0x2d, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x2d, + /* -0590, */ 0x54, 0x6f, 0x3a, 0x20, 0x54, 0x52, 0x55, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a, + /* -05A0, */ 0x20, 0x31, 0x38, 0x32, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, + /* -05B0, */ 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + /* -05C0, */ 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x66, 0x72, 0x61, 0x6d, 0x65, + /* -05D0, */ 0x72, 0x61, 0x74, 0x65, 0x3a, 0x0d, 0x0a, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x2d, 0x49, 0x6e, 0x66, + /* -05E0, */ 0x6f, 0x3a, 0x20, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x6d, 0x61, + /* -05F0, */ 0x78, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x3b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x2d, 0x61, 0x66, + /* -0600, */ 0x74, 0x65, 0x72, 0x3d, 0x75, 0x61, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x3d, 0x34, + /* -0610, */ 0x31, 0x30, 0x20, 0x47, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x52, 0x65, 0x66, 0x65, 0x72, 0x2d, 0x54, + /* -0620, */ 0x6f, 0x3a, 0x20, 0x0d, 0x0a, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x0d, + /* -0630, */ 0x0a, 0x6d, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x71, + /* -0640, */ 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x3a, 0x0d, 0x0a, 0x61, 0x3d, 0x73, 0x64, 0x70, 0x6c, 0x61, + /* -0650, */ 0x6e, 0x67, 0x3a, 0x0d, 0x0a, 0x61, 0x3d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3a, 0x0d, + /* -0660, */ 0x0a, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x3a, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, + /* -0670, */ 0x20, 0x69, 0x70, 0x73, 0x65, 0x63, 0x2d, 0x69, 0x6b, 0x65, 0x3b, 0x74, 0x72, 0x61, 0x6e, 0x73, + /* -0680, */ 0x70, 0x6f, 0x72, 0x74, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x6b, 0x65, 0x79, 0x77, 0x64, 0x73, 0x3a, + /* -0690, */ 0x0d, 0x0a, 0x6b, 0x3d, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x3a, 0x3b, 0x72, 0x65, 0x66, 0x72, + /* -06A0, */ 0x65, 0x73, 0x68, 0x65, 0x72, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x3a, + /* -06B0, */ 0x0d, 0x0a, 0x6b, 0x3d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x3a, 0x3b, 0x72, 0x65, 0x63, 0x65, 0x69, + /* -06C0, */ 0x76, 0x65, 0x64, 0x3d, 0x3b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x0d, 0x0a, + /* -06D0, */ 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x67, 0x72, 0x6f, 0x75, + /* -06E0, */ 0x70, 0x3a, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x3a, 0x20, 0x49, 0x4e, 0x46, 0x4f, 0x20, 0x0d, 0x0a, + /* -06F0, */ 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x0d, 0x0a, 0x61, 0x3d, 0x6c, 0x61, 0x6e, 0x67, 0x3a, + /* -0700, */ 0x0d, 0x0a, 0x6d, 0x3d, 0x64, 0x61, 0x74, 0x61, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2d, 0x73, 0x65, + /* -0710, */ 0x74, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x74, 0x6f, 0x6f, 0x6c, 0x3a, 0x54, 0x4c, 0x53, 0x75, 0x6e, + /* -0720, */ 0x2c, 0x20, 0x0d, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x63, 0x61, + /* -0730, */ 0x74, 0x3a, 0x0d, 0x0a, 0x6b, 0x3d, 0x75, 0x72, 0x69, 0x3a, 0x0d, 0x0a, 0x50, 0x72, 0x6f, 0x78, + /* -0740, */ 0x79, 0x2d, 0x3b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x3d, 0x3b, 0x6d, 0x65, 0x74, 0x68, 0x6f, + /* -0750, */ 0x64, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x6d, 0x69, 0x64, 0x3a, 0x3b, 0x6d, 0x61, 0x64, 0x64, 0x72, + /* -0760, */ 0x3d, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x3d, 0x0d, 0x0a, 0x4d, 0x69, 0x6e, 0x2d, 0x3b, 0x61, + /* -0770, */ 0x6c, 0x67, 0x3d, 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, 0x65, 0x64, + /* -0780, */ 0x2c, 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, 0x74, 0x2c, 0x20, 0x3b, 0x74, 0x74, 0x6c, + /* -0790, */ 0x3d, 0x61, 0x75, 0x74, 0x73, 0x3d, 0x0d, 0x0a, 0x72, 0x3d, 0x0d, 0x0a, 0x7a, 0x3d, 0x0d, 0x0a, + /* -07A0, */ 0x65, 0x3d, 0x3b, 0x69, 0x64, 0x3d, 0x0d, 0x0a, 0x69, 0x3d, 0x63, 0x72, 0x63, 0x3d, 0x0d, 0x0a, + /* -07B0, */ 0x75, 0x3d, 0x3b, 0x71, 0x3d, 0x75, 0x61, 0x73, 0x34, 0x31, 0x34, 0x20, 0x52, 0x65, 0x71, 0x75, + /* -07C0, */ 0x65, 0x73, 0x74, 0x2d, 0x55, 0x52, 0x49, 0x20, 0x54, 0x6f, 0x6f, 0x20, 0x4c, 0x6f, 0x6e, 0x67, + /* -07D0, */ 0x69, 0x76, 0x65, 0x75, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x75, 0x64, 0x70, 0x72, 0x65, + /* -07E0, */ 0x66, 0x65, 0x72, 0x36, 0x30, 0x30, 0x20, 0x42, 0x75, 0x73, 0x79, 0x20, 0x45, 0x76, 0x65, 0x72, + /* -07F0, */ 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x34, 0x38, 0x30, 0x20, + /* -0800, */ 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, 0x79, 0x20, 0x55, 0x6e, 0x61, 0x76, + /* -0810, */ 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x61, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x3a, + /* -0820, */ 0x48, 0x2e, 0x33, 0x33, 0x32, 0x30, 0x32, 0x20, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + /* -0830, */ 0x0d, 0x0a, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, + /* -0840, */ 0x73, 0x3a, 0x20, 0x0d, 0x0a, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + /* -0850, */ 0x6e, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x0d, 0x0a, 0x53, + /* -0860, */ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x3a, 0x20, 0x53, 0x65, + /* -0870, */ 0x70, 0x20, 0x0d, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x2d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + /* -0880, */ 0x3a, 0x20, 0x46, 0x65, 0x62, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, + /* -0890, */ 0x76, 0x65, 0x52, 0x54, 0x50, 0x2f, 0x53, 0x41, 0x56, 0x50, 0x20, 0x52, 0x54, 0x50, 0x2f, 0x41, + /* -08A0, */ 0x56, 0x50, 0x46, 0x20, 0x41, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x69, 0x70, 0x73, + /* -08B0, */ 0x3a, 0x0d, 0x0a, 0x61, 0x3d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x74, 0x65, 0x73, 0x74, 0x65, 0x6c, + /* -08C0, */ 0x3a, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x72, 0x65, 0x63, + /* -08D0, */ 0x76, 0x6f, 0x6e, 0x6c, 0x79, 0x0d, 0x0a, 0x61, 0x3d, 0x73, 0x65, 0x6e, 0x64, 0x6f, 0x6e, 0x6c, + /* -08E0, */ 0x79, 0x0d, 0x0a, 0x63, 0x3d, 0x49, 0x4e, 0x20, 0x49, 0x50, 0x34, 0x20, 0x0d, 0x0a, 0x52, 0x65, + /* -08F0, */ 0x61, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x0d, + /* -0900, */ 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x0d, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x3a, 0x20, + /* -0910, */ 0x3b, 0x75, 0x73, 0x65, 0x72, 0x3d, 0x0d, 0x0a, 0x62, 0x3d, 0x41, 0x53, 0x20, 0x43, 0x54, 0x20, + /* -0920, */ 0x0d, 0x0a, 0x57, 0x57, 0x57, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + /* -0930, */ 0x74, 0x65, 0x3a, 0x20, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x73, + /* -0940, */ 0x65, 0x6e, 0x64, 0x72, 0x65, 0x63, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, + /* -0950, */ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + /* -0960, */ 0x6e, 0x2f, 0x73, 0x64, 0x70, 0x61, 0x74, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x70, 0x61, + /* -0970, */ 0x75, 0x74, 0x68, 0x3d, 0x0d, 0x0a, 0x61, 0x3d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x3a, 0x70, + /* -0980, */ 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x74, 0x72, 0x2d, + /* -0990, */ 0x69, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x63, 0x3d, 0x34, 0x38, 0x33, 0x20, 0x54, 0x6f, 0x6f, + /* -09A0, */ 0x20, 0x4d, 0x61, 0x6e, 0x79, 0x20, 0x48, 0x6f, 0x70, 0x73, 0x6c, 0x69, 0x6e, 0x66, 0x6f, 0x70, + /* -09B0, */ 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x3d, 0x36, 0x30, + /* -09C0, */ 0x34, 0x20, 0x44, 0x6f, 0x65, 0x73, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x45, 0x78, 0x69, 0x73, 0x74, + /* -09D0, */ 0x20, 0x41, 0x6e, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x3d, + /* -09E0, */ 0x0d, 0x0a, 0x0d, 0x0a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2d, 0x44, 0x69, 0x73, 0x70, + /* -09F0, */ 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4d, 0x44, 0x35, 0x38, 0x30, 0x20, 0x50, + /* -0A00, */ 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x61, 0x69, 0x6c, + /* -0A10, */ 0x75, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x34, 0x32, 0x32, 0x20, 0x53, 0x65, 0x73, + /* -0A20, */ 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x54, 0x6f, + /* -0A30, */ 0x6f, 0x20, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x31, 0x38, 0x31, 0x20, 0x43, + /* -0A40, */ 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x73, 0x20, 0x42, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x46, 0x6f, 0x72, + /* -0A50, */ 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x66, 0x61, 0x69, 0x6c, + /* -0A60, */ 0x75, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x61, 0x6c, 0x6d, 0x3d, 0x53, 0x55, 0x42, 0x53, + /* -0A70, */ 0x43, 0x52, 0x49, 0x42, 0x45, 0x20, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + /* -0A80, */ 0x6f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x63, 0x2d, 0x6d, 0x61, 0x6e, + /* -0A90, */ 0x64, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x34, 0x31, 0x33, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + /* -0AA0, */ 0x74, 0x20, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x54, 0x6f, 0x6f, 0x20, 0x4c, 0x61, 0x72, + /* -0AB0, */ 0x67, 0x65, 0x32, 0x65, 0x31, 0x38, 0x33, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, + /* -0AC0, */ 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x63, 0x74, 0x70, 0x34, 0x38, 0x36, 0x20, 0x42, + /* -0AD0, */ 0x75, 0x73, 0x79, 0x20, 0x48, 0x65, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + /* -0AE0, */ 0x61, 0x74, 0x65, 0x64, 0x41, 0x4b, 0x41, 0x76, 0x31, 0x2d, 0x4d, 0x44, 0x35, 0x2d, 0x73, 0x65, + /* -0AF0, */ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + /* -0B00, */ 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x36, 0x30, 0x33, 0x20, 0x44, 0x65, 0x63, + /* -0B10, */ 0x6c, 0x69, 0x6e, 0x65, 0x78, 0x74, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x3d, 0x34, 0x38, 0x35, 0x20, + /* -0B20, */ 0x41, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x3d, + /* -0B30, */ 0x61, 0x75, 0x64, 0x69, 0x6f, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, + /* -0B40, */ 0x79, 0x70, 0x65, 0x3a, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x0d, 0x0a, 0x52, 0x65, 0x63, 0x6f, 0x72, + /* -0B50, */ 0x64, 0x2d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x3a, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x34, 0x30, 0x31, + /* -0B60, */ 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x0d, 0x0a, 0x52, + /* -0B70, */ 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x3a, 0x20, 0x0d, 0x0a, 0x74, 0x3d, 0x30, 0x20, 0x30, 0x2e, + /* -0B80, */ 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x0d, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x52, + /* -0B90, */ 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x20, 0x0d, 0x0a, 0x63, 0x3d, 0x49, 0x4e, 0x20, 0x49, + /* -0BA0, */ 0x50, 0x36, 0x20, 0x31, 0x38, 0x30, 0x20, 0x52, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x31, 0x30, + /* -0BB0, */ 0x30, 0x20, 0x54, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x76, 0x3d, 0x30, 0x0d, 0x0a, 0x6f, 0x3d, 0x55, + /* -0BC0, */ 0x50, 0x44, 0x41, 0x54, 0x45, 0x20, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x20, 0x0d, 0x0a, 0x53, + /* -0BD0, */ 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, + /* -0BE0, */ 0x6e, 0x41, 0x4d, 0x52, 0x54, 0x50, 0x2f, 0x41, 0x56, 0x50, 0x20, 0x0d, 0x0a, 0x50, 0x72, 0x69, + /* -0BF0, */ 0x76, 0x61, 0x63, 0x79, 0x3a, 0x20, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + /* -0C00, */ 0x2d, 0x0d, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x3a, 0x20, 0x0d, 0x0a, 0x61, 0x3d, + /* -0C10, */ 0x72, 0x74, 0x70, 0x6d, 0x61, 0x70, 0x3a, 0x0d, 0x0a, 0x6d, 0x3d, 0x76, 0x69, 0x64, 0x65, 0x6f, + /* -0C20, */ 0x20, 0x0d, 0x0a, 0x6d, 0x3d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x0d, 0x0a, 0x73, 0x3d, 0x20, + /* -0C30, */ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x61, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x3a, 0x3b, 0x65, + /* -0C40, */ 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x3d, 0x0d, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x3a, 0x20, + /* -0C50, */ 0x0d, 0x0a, 0x61, 0x3d, 0x66, 0x6d, 0x74, 0x70, 0x3a, 0x0d, 0x0a, 0x61, 0x3d, 0x63, 0x75, 0x72, + /* -0C60, */ 0x72, 0x3a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + /* -0C70, */ 0x3a, 0x20, 0x0d, 0x0a, 0x61, 0x3d, 0x64, 0x65, 0x73, 0x3a, 0x0d, 0x0a, 0x52, 0x41, 0x63, 0x6b, + /* -0C80, */ 0x3a, 0x20, 0x0d, 0x0a, 0x52, 0x53, 0x65, 0x71, 0x3a, 0x20, 0x42, 0x59, 0x45, 0x20, 0x63, 0x6e, + /* -0C90, */ 0x6f, 0x6e, 0x63, 0x65, 0x3d, 0x31, 0x30, 0x30, 0x72, 0x65, 0x6c, 0x75, 0x72, 0x69, 0x3d, 0x71, + /* -0CA0, */ 0x6f, 0x70, 0x3d, 0x54, 0x43, 0x50, 0x55, 0x44, 0x50, 0x71, 0x6f, 0x73, 0x78, 0x6d, 0x6c, 0x3b, + /* -0CB0, */ 0x6c, 0x72, 0x0d, 0x0a, 0x56, 0x69, 0x61, 0x3a, 0x20, 0x53, 0x49, 0x50, 0x2f, 0x32, 0x2e, 0x30, + /* -0CC0, */ 0x2f, 0x54, 0x43, 0x50, 0x20, 0x34, 0x30, 0x38, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + /* -0CD0, */ 0x20, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x70, 0x73, 0x69, 0x70, + /* -0CE0, */ 0x3a, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74, + /* -0CF0, */ 0x68, 0x3a, 0x20, 0x4f, 0x63, 0x74, 0x20, 0x0d, 0x0a, 0x56, 0x69, 0x61, 0x3a, 0x20, 0x53, 0x49, + /* -0D00, */ 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x3b, 0x63, 0x6f, 0x6d, 0x70, 0x3d, + /* -0D10, */ 0x73, 0x69, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, + /* -0D20, */ 0x63, 0x6b, 0x3b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x3d, 0x7a, 0x39, 0x68, 0x47, 0x34, 0x62, + /* -0D30, */ 0x4b, 0x0d, 0x0a, 0x4d, 0x61, 0x78, 0x2d, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x73, 0x3a, + /* -0D40, */ 0x20, 0x41, 0x70, 0x72, 0x20, 0x53, 0x43, 0x54, 0x50, 0x52, 0x41, 0x43, 0x4b, 0x20, 0x49, 0x4e, + /* -0D50, */ 0x56, 0x49, 0x54, 0x45, 0x20, 0x0d, 0x0a, 0x43, 0x61, 0x6c, 0x6c, 0x2d, 0x49, 0x44, 0x3a, 0x20, + /* -0D60, */ 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, + /* -0D70, */ 0x4b, 0x0d, 0x0a, 0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, 0x0d, 0x0a, 0x43, 0x53, 0x65, 0x71, 0x3a, + /* -0D80, */ 0x20, 0x0d, 0x0a, 0x54, 0x6f, 0x3a, 0x20, 0x3b, 0x74, 0x61, 0x67, 0x3d, 0x04, 0x10, 0xdd, 0x10, + /* -0D90, */ 0x11, 0x31, 0x0d, 0x11, 0x0a, 0x07, 0x10, 0xb9, 0x0c, 0x10, 0xfe, 0x12, 0x10, 0xe1, 0x06, 0x11, + /* -0DA0, */ 0x4e, 0x07, 0x11, 0x4e, 0x03, 0x11, 0x4a, 0x04, 0x11, 0x4a, 0x07, 0x10, 0xb2, 0x08, 0x11, 0x79, + /* -0DB0, */ 0x06, 0x11, 0x81, 0x0f, 0x11, 0x22, 0x0b, 0x11, 0x55, 0x06, 0x11, 0x6b, 0x0b, 0x11, 0x60, 0x13, + /* -0DC0, */ 0x10, 0xb2, 0x08, 0x11, 0x71, 0x05, 0x11, 0x87, 0x13, 0x10, 0xf7, 0x09, 0x0e, 0x8d, 0x08, 0x0d, + /* -0DD0, */ 0xae, 0x0c, 0x10, 0xb9, 0x07, 0x10, 0x8e, 0x03, 0x0d, 0x96, 0x03, 0x10, 0x8a, 0x04, 0x10, 0x8a, + /* -0DE0, */ 0x09, 0x0d, 0xd7, 0x0a, 0x0f, 0x12, 0x08, 0x0f, 0x8f, 0x09, 0x0f, 0x8f, 0x08, 0x0d, 0x6c, 0x06, + /* -0DF0, */ 0x0e, 0x66, 0x09, 0x0e, 0x6c, 0x0a, 0x0e, 0x6c, 0x06, 0x0f, 0xc6, 0x07, 0x0f, 0xc6, 0x05, 0x11, + /* -0E00, */ 0x48, 0x06, 0x11, 0x48, 0x06, 0x0f, 0xbf, 0x07, 0x0f, 0xbf, 0x07, 0x0e, 0x55, 0x06, 0x0f, 0x16, + /* -0E10, */ 0x04, 0x0e, 0xf4, 0x03, 0x0e, 0xb1, 0x03, 0x10, 0xa6, 0x09, 0x10, 0x50, 0x03, 0x10, 0xa3, 0x0a, + /* -0E20, */ 0x0d, 0xb4, 0x05, 0x0e, 0x36, 0x06, 0x0e, 0xd6, 0x03, 0x0d, 0xf9, 0x11, 0x0e, 0xf8, 0x04, 0x0c, + /* -0E30, */ 0xd9, 0x08, 0x0e, 0xea, 0x04, 0x09, 0x53, 0x03, 0x0a, 0x4b, 0x04, 0x0e, 0xe4, 0x10, 0x0f, 0x35, + /* -0E40, */ 0x09, 0x0e, 0xe4, 0x08, 0x0d, 0x3f, 0x03, 0x0f, 0xe1, 0x0b, 0x10, 0x01, 0x03, 0x10, 0xac, 0x06, + /* -0E50, */ 0x10, 0x95, 0x0c, 0x0e, 0x76, 0x0b, 0x0f, 0xeb, 0x0a, 0x0f, 0xae, 0x05, 0x10, 0x2b, 0x04, 0x10, + /* -0E60, */ 0x2b, 0x08, 0x10, 0x7a, 0x10, 0x0f, 0x49, 0x07, 0x0f, 0xb8, 0x09, 0x10, 0x3e, 0x0b, 0x10, 0x0c, + /* -0E70, */ 0x07, 0x0f, 0x78, 0x0b, 0x0f, 0x6d, 0x09, 0x10, 0x47, 0x08, 0x10, 0x82, 0x0b, 0x0f, 0xf6, 0x08, + /* -0E80, */ 0x10, 0x62, 0x08, 0x0f, 0x87, 0x08, 0x10, 0x6a, 0x04, 0x0f, 0x78, 0x0d, 0x0f, 0xcd, 0x08, 0x0d, + /* -0E90, */ 0xae, 0x10, 0x0f, 0x5d, 0x0b, 0x0f, 0x98, 0x14, 0x0d, 0x20, 0x1b, 0x0d, 0x20, 0x04, 0x0d, 0xe0, + /* -0EA0, */ 0x14, 0x0e, 0xb4, 0x0b, 0x0f, 0xa3, 0x0b, 0x07, 0x34, 0x0f, 0x0d, 0x56, 0x04, 0x0e, 0xf4, 0x03, + /* -0EB0, */ 0x10, 0xaf, 0x07, 0x0d, 0x34, 0x09, 0x0f, 0x27, 0x04, 0x10, 0x9b, 0x04, 0x10, 0x9f, 0x09, 0x10, + /* -0EC0, */ 0x59, 0x08, 0x10, 0x72, 0x09, 0x10, 0x35, 0x0a, 0x10, 0x21, 0x0a, 0x10, 0x17, 0x08, 0x0f, 0xe3, + /* -0ED0, */ 0x03, 0x10, 0xa9, 0x05, 0x0c, 0xac, 0x04, 0x0c, 0xbd, 0x07, 0x0c, 0xc1, 0x08, 0x0c, 0xc1, 0x09, + /* -0EE0, */ 0x0c, 0xf6, 0x10, 0x0c, 0x72, 0x0c, 0x0c, 0x86, 0x04, 0x0d, 0x64, 0x0c, 0x0c, 0xd5, 0x09, 0x0c, + /* -0EF0, */ 0xff, 0x1b, 0x0b, 0xfc, 0x11, 0x0c, 0x5d, 0x13, 0x0c, 0x30, 0x09, 0x0c, 0xa4, 0x0c, 0x0c, 0x24, + /* -0F00, */ 0x0c, 0x0d, 0x3b, 0x03, 0x0d, 0x1a, 0x03, 0x0d, 0x1d, 0x16, 0x0c, 0x43, 0x09, 0x0c, 0x92, 0x09, + /* -0F10, */ 0x0c, 0x9b, 0x0d, 0x0e, 0xcb, 0x04, 0x0d, 0x16, 0x06, 0x0d, 0x10, 0x05, 0x04, 0xf2, 0x0b, 0x0c, + /* -0F20, */ 0xe1, 0x05, 0x0b, 0xde, 0x0a, 0x0c, 0xec, 0x13, 0x0b, 0xe3, 0x07, 0x0b, 0xd4, 0x08, 0x0d, 0x08, + /* -0F30, */ 0x0c, 0x0c, 0xc9, 0x09, 0x0c, 0x3a, 0x04, 0x0a, 0xe5, 0x0c, 0x0a, 0x23, 0x08, 0x0b, 0x3a, 0x0e, + /* -0F40, */ 0x09, 0xab, 0x0f, 0x0e, 0xfa, 0x09, 0x0f, 0x6f, 0x0c, 0x0a, 0x17, 0x0f, 0x09, 0x76, 0x0c, 0x0a, + /* -0F50, */ 0x5f, 0x17, 0x0d, 0xe2, 0x0f, 0x07, 0xa8, 0x0a, 0x0f, 0x85, 0x0f, 0x08, 0xd6, 0x0e, 0x09, 0xb9, + /* -0F60, */ 0x0b, 0x0a, 0x7a, 0x03, 0x0b, 0xdb, 0x03, 0x08, 0xc1, 0x04, 0x0e, 0xc7, 0x03, 0x08, 0xd3, 0x02, + /* -0F70, */ 0x04, 0x8d, 0x08, 0x0b, 0x4a, 0x05, 0x0b, 0x8c, 0x07, 0x0b, 0x61, 0x06, 0x05, 0x48, 0x04, 0x07, + /* -0F80, */ 0xf4, 0x05, 0x10, 0x30, 0x04, 0x07, 0x1e, 0x08, 0x07, 0x1e, 0x05, 0x0b, 0x91, 0x10, 0x04, 0xca, + /* -0F90, */ 0x09, 0x0a, 0x71, 0x09, 0x0e, 0x87, 0x05, 0x04, 0x98, 0x05, 0x0b, 0x6e, 0x0b, 0x04, 0x9b, 0x0f, + /* -0FA0, */ 0x04, 0x9b, 0x07, 0x04, 0x9b, 0x03, 0x04, 0xa3, 0x07, 0x04, 0xa3, 0x10, 0x07, 0x98, 0x09, 0x07, + /* -0FB0, */ 0x98, 0x05, 0x0b, 0x73, 0x05, 0x0b, 0x78, 0x05, 0x0b, 0x7d, 0x05, 0x07, 0xb9, 0x05, 0x0b, 0x82, + /* -0FC0, */ 0x05, 0x0b, 0x87, 0x05, 0x0b, 0x1d, 0x05, 0x08, 0xe4, 0x05, 0x0c, 0x81, 0x05, 0x0f, 0x44, 0x05, + /* -0FD0, */ 0x11, 0x40, 0x05, 0x08, 0x78, 0x05, 0x08, 0x9d, 0x05, 0x0f, 0x58, 0x05, 0x07, 0x3f, 0x05, 0x0c, + /* -0FE0, */ 0x6d, 0x05, 0x10, 0xf2, 0x05, 0x0c, 0x58, 0x05, 0x06, 0xa9, 0x04, 0x07, 0xb6, 0x09, 0x05, 0x8c, + /* -0FF0, */ 0x06, 0x06, 0x1a, 0x06, 0x0e, 0x81, 0x0a, 0x06, 0x16, 0x0a, 0x0a, 0xc4, 0x07, 0x0b, 0x5a, 0x0a, + /* -1000, */ 0x0a, 0xba, 0x03, 0x0b, 0x1b, 0x04, 0x11, 0x45, 0x06, 0x0c, 0x8c, 0x07, 0x05, 0xad, 0x0a, 0x0e, + /* -1010, */ 0xda, 0x08, 0x0b, 0x42, 0x0d, 0x09, 0xf7, 0x0b, 0x05, 0x1c, 0x09, 0x11, 0x16, 0x08, 0x05, 0xc9, + /* -1020, */ 0x07, 0x0d, 0x86, 0x06, 0x0b, 0xcf, 0x0a, 0x06, 0x4d, 0x04, 0x0b, 0xa2, 0x06, 0x06, 0x8d, 0x08, + /* -1030, */ 0x05, 0xe6, 0x08, 0x0e, 0x11, 0x0b, 0x0a, 0x9b, 0x03, 0x0a, 0x04, 0x03, 0x0b, 0xb5, 0x05, 0x10, + /* -1040, */ 0xd7, 0x04, 0x09, 0x94, 0x05, 0x0a, 0xe2, 0x03, 0x0b, 0xb2, 0x06, 0x0d, 0x67, 0x04, 0x0d, 0x11, + /* -1050, */ 0x08, 0x08, 0xb7, 0x1b, 0x0e, 0x3b, 0x0a, 0x09, 0xa1, 0x14, 0x04, 0x85, 0x15, 0x07, 0x83, 0x15, + /* -1060, */ 0x07, 0x6e, 0x0d, 0x09, 0x3d, 0x17, 0x06, 0xae, 0x0f, 0x07, 0xe6, 0x14, 0x07, 0xbe, 0x0d, 0x06, + /* -1070, */ 0x0a, 0x0d, 0x09, 0x30, 0x16, 0x06, 0xf2, 0x12, 0x08, 0x1e, 0x21, 0x04, 0xaa, 0x13, 0x10, 0xc5, + /* -1080, */ 0x08, 0x0a, 0x0f, 0x1c, 0x0e, 0x96, 0x18, 0x0b, 0xb8, 0x1a, 0x05, 0x95, 0x1a, 0x05, 0x75, 0x11, + /* -1090, */ 0x06, 0x3d, 0x16, 0x06, 0xdc, 0x1e, 0x0e, 0x19, 0x16, 0x05, 0xd1, 0x1d, 0x06, 0x20, 0x23, 0x05, + /* -10A0, */ 0x27, 0x11, 0x08, 0x7d, 0x11, 0x0d, 0x99, 0x16, 0x04, 0xda, 0x0d, 0x0f, 0x1c, 0x16, 0x07, 0x08, + /* -10B0, */ 0x17, 0x05, 0xb4, 0x0d, 0x08, 0xc7, 0x13, 0x07, 0xf8, 0x12, 0x08, 0x57, 0x1f, 0x04, 0xfe, 0x19, + /* -10C0, */ 0x05, 0x4e, 0x13, 0x08, 0x0b, 0x0f, 0x08, 0xe9, 0x17, 0x06, 0xc5, 0x13, 0x06, 0x7b, 0x19, 0x05, + /* -10D0, */ 0xf1, 0x15, 0x07, 0x44, 0x18, 0x0d, 0xfb, 0x0b, 0x0f, 0x09, 0x1b, 0x0d, 0xbe, 0x12, 0x08, 0x30, + /* -10E0, */ 0x15, 0x07, 0x59, 0x04, 0x0b, 0xa6, 0x04, 0x0b, 0xae, 0x04, 0x0b, 0x9e, 0x04, 0x0b, 0x96, 0x04, + /* -10F0, */ 0x0b, 0x9a, 0x0a, 0x0a, 0xb0, 0x0b, 0x0a, 0x90, 0x08, 0x0b, 0x32, 0x0b, 0x09, 0x6b, 0x08, 0x0b, + /* -1100, */ 0x2a, 0x0b, 0x0a, 0x85, 0x09, 0x0b, 0x12, 0x0a, 0x0a, 0xa6, 0x0d, 0x09, 0xea, 0x13, 0x0d, 0x74, + /* -1110, */ 0x14, 0x07, 0xd2, 0x13, 0x09, 0x0b, 0x12, 0x08, 0x42, 0x10, 0x09, 0x5b, 0x12, 0x09, 0x1e, 0x0d, + /* -1120, */ 0x0c, 0xb1, 0x0e, 0x0c, 0x17, 0x11, 0x09, 0x4a, 0x0c, 0x0a, 0x53, 0x0c, 0x0a, 0x47, 0x09, 0x0a, + /* -1130, */ 0xf7, 0x0e, 0x09, 0xc7, 0x0c, 0x0a, 0x3b, 0x07, 0x06, 0x69, 0x08, 0x06, 0x69, 0x06, 0x09, 0xe3, + /* -1140, */ 0x08, 0x0b, 0x52, 0x0a, 0x0a, 0xd8, 0x12, 0x06, 0x57, 0x0d, 0x06, 0x57, 0x07, 0x09, 0xe3, 0x04, + /* -1150, */ 0x0a, 0xe9, 0x10, 0x07, 0x30, 0x09, 0x0b, 0x00, 0x0c, 0x0a, 0x2f, 0x05, 0x0a, 0xe9, 0x05, 0x0a, + /* -1160, */ 0x6b, 0x06, 0x0a, 0x6b, 0x0a, 0x0a, 0xce, 0x09, 0x0a, 0xee, 0x03, 0x0b, 0xdb, 0x07, 0x0f, 0x7e, + /* -1170, */ 0x0a, 0x09, 0x97, 0x0a, 0x06, 0x71, 0x0e, 0x09, 0xd5, 0x17, 0x06, 0x93, 0x07, 0x0e, 0x5c, 0x07, + /* -1180, */ 0x0f, 0xda, 0x0a, 0x0f, 0x35, 0x0d, 0x0d, 0xec, 0x0a, 0x09, 0x97, 0x0a, 0x06, 0x71, 0x08, 0x0b, + /* -1190, */ 0x22, 0x0f, 0x09, 0x85, 0x06, 0x0b, 0x68, 0x0c, 0x0d, 0x4a, 0x09, 0x0b, 0x09, 0x13, 0x08, 0xf8, + /* -11A0, */ 0x15, 0x08, 0xa2, 0x04, 0x0b, 0xaa, 0x0f, 0x05, 0x66, 0x0d, 0x07, 0x23, 0x09, 0x0a, 0x06, 0x0b, + /* -11B0, */ 0x0d, 0x4a, 0x0f, 0x04, 0xee, 0x06, 0x04, 0xf8, 0x04, 0x09, 0x2b, 0x04, 0x08, 0x53, 0x07, 0x08, + /* -11C0, */ 0xc0, 0x03, 0x11, 0x1f, 0x04, 0x11, 0x1e, 0x07, 0x0d, 0x8c, 0x03, 0x07, 0x34, 0x04, 0x10, 0xdb, + /* -11D0, */ 0x03, 0x07, 0x36, 0x03, 0x0d, 0xa9, 0x0d, 0x04, 0x20, 0x0b, 0x04, 0x51, 0x0c, 0x04, 0x3a, 0x04, + /* -11E0, */ 0x0b, 0xb8, 0x04, 0x0c, 0x24, 0x04, 0x05, 0x95, 0x04, 0x04, 0x7c, 0x04, 0x05, 0x75, 0x04, 0x04, + /* -11F0, */ 0x85, 0x04, 0x09, 0x6b, 0x04, 0x06, 0x3d, 0x06, 0x04, 0x7b, 0x04, 0x06, 0xdc, 0x04, 0x07, 0x83, + /* -1200, */ 0x04, 0x0e, 0x19, 0x12, 0x04, 0x00, 0x10, 0x08, 0x8e, 0x10, 0x08, 0x69, 0x0e, 0x04, 0x12, 0x0d, + /* -1210, */ 0x04, 0x2d, 0x03, 0x10, 0xb9, 0x04, 0x05, 0xd1, 0x04, 0x07, 0x6e, 0x04, 0x06, 0x20, 0x07, 0x04, + /* -1220, */ 0x74, 0x04, 0x0b, 0xfc, 0x0a, 0x04, 0x5c, 0x04, 0x05, 0x27, 0x04, 0x09, 0x3d, 0x04, 0x08, 0x7d, + /* -1230, */ 0x04, 0x0f, 0xae, 0x04, 0x0d, 0x99, 0x04, 0x06, 0xae, 0x04, 0x04, 0xda, 0x09, 0x04, 0x09, 0x08, + /* -1240, */ 0x11, 0x22, 0x04, 0x0f, 0x1c, 0x04, 0x07, 0xe6, 0x04, 0x0e, 0xcb, 0x05, 0x08, 0xbd, 0x04, 0x07, + /* -1250, */ 0x08, 0x04, 0x0f, 0xa3, 0x04, 0x06, 0x57, 0x04, 0x05, 0xb4, 0x04, 0x0f, 0x5d, 0x04, 0x08, 0xc7, + /* -1260, */ 0x08, 0x0b, 0xf4, 0x04, 0x07, 0xf8, 0x04, 0x07, 0x30, 0x04, 0x07, 0xbe, 0x04, 0x08, 0x57, 0x05, + /* -1270, */ 0x0d, 0x46, 0x04, 0x04, 0xfe, 0x04, 0x06, 0x0a, 0x04, 0x05, 0x4e, 0x04, 0x0e, 0x3b, 0x04, 0x08, + /* -1280, */ 0x0b, 0x04, 0x09, 0x30, 0x04, 0x08, 0xe9, 0x05, 0x05, 0xee, 0x04, 0x06, 0xc5, 0x04, 0x06, 0xf2, + /* -1290, */ 0x04, 0x06, 0x7b, 0x04, 0x09, 0xa1, 0x04, 0x05, 0xf1, 0x04, 0x08, 0x1e, 0x04, 0x07, 0x44, 0x04, + /* -12A0, */ 0x0b, 0xdd, 0x04, 0x0d, 0xfb, 0x04, 0x04, 0xaa, 0x04, 0x0b, 0xe3, 0x07, 0x0e, 0xee, 0x04, 0x0f, + /* -12B0, */ 0x09, 0x04, 0x0e, 0xb4, 0x04, 0x0d, 0xbe, 0x04, 0x10, 0xc5, 0x04, 0x08, 0x30, 0x05, 0x0f, 0x30, + /* -12C0, */ 0x04, 0x07, 0x59, 0x04, 0x0a, 0x0f, 0x06, 0x0e, 0x61, 0x04, 0x04, 0x81, 0x04, 0x0d, 0xab, 0x04, + /* -12D0, */ 0x0d, 0x93, 0x04, 0x11, 0x6b, 0x04, 0x0e, 0x96, 0x05, 0x04, 0x66, 0x09, 0x04, 0x6b, 0x0b, 0x04, + /* -12E0, */ 0x46, 0x04, 0x0c, 0xe1 + +}; + +/* + * Definitions for: + * The Presence-Specific Static Dictionary for Signaling + * https://www.ietf.org/rfc/rfc5112 + */ +#define PRESENCE_STATE_LENGTH 0x0d93 + +static const guint8 presence_state_identifier[STATE_BUFFER_SIZE] = +{ + /* -0000, */ 0xd9, 0x42, 0x29, 0x7d, 0x0b, 0xb3, 0x8f, 0xc0, 0x1d, 0x67, 0x41, 0xd6, 0xb3, 0xb4, 0x81, 0x57, + /* -0010, */ 0xac, 0x8e, 0x1b, 0xe0 +}; + +static const guint8 presence_static_dictionary_for_sigcomp[PRESENCE_STATE_LENGTH] = +{ + /* -0000, */ 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x65, 0x6e, 0x74, 0x65, + /* -0010, */ 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, + /* -0020, */ 0x69, 0x73, 0x67, 0x75, 0x73, 0x74, 0x65, 0x64, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x69, + /* -0030, */ 0x61, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x68, 0x75, 0x6d, 0x69, + /* -0040, */ 0x6c, 0x69, 0x61, 0x74, 0x65, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x61, 0x75, 0x74, 0x6f, + /* -0050, */ 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x70, 0x69, 0x72, + /* -0060, */ 0x69, 0x74, 0x73, 0x2d, 0x49, 0x4e, 0x44, 0x50, 0x73, 0x65, 0x6e, 0x64, 0x2d, 0x6f, 0x6e, 0x6c, + /* -0070, */ 0x79, 0x70, 0x61, 0x74, 0x68, 0x65, 0x61, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x73, + /* -0080, */ 0x73, 0x6c, 0x65, 0x65, 0x70, 0x79, 0x69, 0x6e, 0x2d, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, + /* -0090, */ 0x6c, 0x6f, 0x6e, 0x65, 0x6c, 0x79, 0x70, 0x6c, 0x61, 0x79, 0x66, 0x75, 0x6c, 0x6f, 0x77, 0x65, + /* -00A0, */ 0x72, 0x74, 0x68, 0x61, 0x6e, 0x6e, 0x6f, 0x79, 0x65, 0x64, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x66, + /* -00B0, */ 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x3d, 0x63, 0x6f, + /* -00C0, */ 0x6e, 0x66, 0x75, 0x73, 0x65, 0x64, 0x76, 0x61, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x63, 0x6c, + /* -00D0, */ 0x75, 0x62, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x63, + /* -00E0, */ 0x72, 0x61, 0x66, 0x74, 0x68, 0x69, 0x72, 0x73, 0x74, 0x79, 0x63, 0x6f, 0x75, 0x72, 0x69, 0x65, + /* -00F0, */ 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x68, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x66, 0x6f, + /* -0100, */ 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x3d, 0x61, 0x72, 0x65, 0x6e, + /* -0110, */ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3d, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, + /* -0120, */ 0x45, 0x52, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6d, 0x70, 0x79, 0x70, 0x72, + /* -0130, */ 0x65, 0x66, 0x69, 0x78, 0x3d, 0x68, 0x61, 0x6c, 0x66, 0x72, 0x65, 0x69, 0x67, 0x68, 0x74, 0x6d, + /* -0140, */ 0x65, 0x61, 0x6e, 0x67, 0x72, 0x79, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x70, + /* -0150, */ 0x72, 0x6f, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x3d, + /* -0160, */ 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x68, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x75, + /* -0170, */ 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x70, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x45, 0x53, + /* -0180, */ 0x53, 0x41, 0x47, 0x45, 0x77, 0x6f, 0x72, 0x72, 0x69, 0x65, 0x64, 0x68, 0x75, 0x6d, 0x62, 0x6c, + /* -0190, */ 0x65, 0x64, 0x61, 0x69, 0x72, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64, + /* -01A0, */ 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x68, 0x75, + /* -01B0, */ 0x6e, 0x67, 0x72, 0x79, 0x63, 0x72, 0x61, 0x6e, 0x6b, 0x79, 0x61, 0x6d, 0x61, 0x7a, 0x65, 0x64, + /* -01C0, */ 0x61, 0x66, 0x72, 0x61, 0x69, 0x64, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x4e, 0x4f, 0x54, 0x49, + /* -01D0, */ 0x46, 0x59, 0x49, 0x4e, 0x56, 0x49, 0x54, 0x45, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x66, 0x72, + /* -01E0, */ 0x69, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + /* -01F0, */ 0x70, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x5f, 0x61, 0x77, 0x65, 0x62, 0x72, 0x61, 0x76, + /* -0200, */ 0x65, 0x71, 0x75, 0x69, 0x65, 0x74, 0x62, 0x6f, 0x72, 0x65, 0x64, 0x50, 0x52, 0x41, 0x43, 0x4b, + /* -0210, */ 0x70, 0x72, 0x6f, 0x75, 0x64, 0x66, 0x69, 0x78, 0x65, 0x64, 0x68, 0x6f, 0x74, 0x65, 0x6c, 0x68, + /* -0220, */ 0x61, 0x70, 0x70, 0x79, 0x63, 0x61, 0x66, 0x65, 0x63, 0x69, 0x64, 0x3d, 0x62, 0x61, 0x6e, 0x6b, + /* -0230, */ 0x6d, 0x69, 0x6e, 0x3d, 0x61, 0x77, 0x61, 0x79, 0x6d, 0x61, 0x78, 0x3d, 0x6d, 0x65, 0x61, 0x6c, + /* -0240, */ 0x62, 0x75, 0x73, 0x79, 0x77, 0x6f, 0x72, 0x6b, 0x75, 0x72, 0x6e, 0x3d, 0x63, 0x6f, 0x6c, 0x64, + /* -0250, */ 0x68, 0x75, 0x72, 0x74, 0x6a, 0x65, 0x61, 0x6c, 0x6f, 0x75, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, + /* -0260, */ 0x73, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, + /* -0270, */ 0x6d, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + /* -0280, */ 0x6f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x66, + /* -0290, */ 0x6f, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, + /* -02A0, */ 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, + /* -02B0, */ 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x3d, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, + /* -02C0, */ 0x74, 0x68, 0x61, 0x6e, 0x78, 0x69, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, + /* -02D0, */ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x62, 0x72, 0x65, 0x61, + /* -02E0, */ 0x6b, 0x66, 0x61, 0x73, 0x74, 0x61, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x67, 0x2d, 0x74, 0x61, 0x6b, + /* -02F0, */ 0x65, 0x72, 0x65, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x3a, 0x63, 0x69, 0x76, + /* -0300, */ 0x69, 0x63, 0x4c, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x71, 0x75, + /* -0310, */ 0x61, 0x6c, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x77, 0x61, 0x74, 0x65, 0x72, 0x63, + /* -0320, */ 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x62, 0x61, 0x73, 0x69, 0x63, + /* -0330, */ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, + /* -0340, */ 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x3d, 0x61, 0x64, 0x64, + /* -0350, */ 0x65, 0x64, 0x75, 0x72, 0x69, 0x3d, 0x77, 0x68, 0x61, 0x74, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, + /* -0360, */ 0x65, 0x6e, 0x74, 0x2d, 0x61, 0x62, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x72, + /* -0370, */ 0x61, 0x73, 0x73, 0x65, 0x64, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x69, + /* -0380, */ 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x76, 0x6f, 0x75, + /* -0390, */ 0x73, 0x65, 0x6c, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64, + /* -03A0, */ 0x66, 0x6c, 0x69, 0x72, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2d, 0x72, + /* -03B0, */ 0x75, 0x6c, 0x65, 0x73, 0x65, 0x72, 0x76, 0x63, 0x61, 0x70, 0x73, 0x70, 0x68, 0x65, 0x72, 0x65, + /* -03C0, */ 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, + /* -03D0, */ 0x3d, 0x62, 0x61, 0x72, 0x72, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x78, 0x74, + /* -03E0, */ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x69, 0x6d, 0x65, + /* -03F0, */ 0x2d, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, + /* -0400, */ 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x77, 0x69, 0x6c, 0x6c, + /* -0410, */ 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x73, 0x73, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x65, + /* -0420, */ 0x73, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x61, 0x63, 0x6b, + /* -0430, */ 0x61, 0x67, 0x65, 0x73, 0x75, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x65, 0x73, 0x74, + /* -0440, */ 0x61, 0x75, 0x72, 0x61, 0x6e, 0x74, 0x72, 0x75, 0x63, 0x6b, 0x70, 0x6c, 0x6d, 0x6f, 0x62, 0x69, + /* -0450, */ 0x6c, 0x69, 0x74, 0x79, 0x6a, 0x6f, 0x69, 0x6e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, + /* -0460, */ 0x61, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x65, 0x72, 0x69, 0x6e, + /* -0470, */ 0x67, 0x69, 0x76, 0x65, 0x75, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x61, 0x6e, + /* -0480, */ 0x67, 0x75, 0x61, 0x67, 0x65, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + /* -0490, */ 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2d, 0x6f, 0x66, + /* -04A0, */ 0x2d, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2d, 0x74, 0x79, 0x70, + /* -04B0, */ 0x65, 0x3d, 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2d, + /* -04C0, */ 0x69, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x75, 0x74, + /* -04D0, */ 0x72, 0x61, 0x6c, 0x49, 0x4e, 0x46, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x69, 0x65, 0x6d, + /* -04E0, */ 0x65, 0x6e, 0x73, 0x2d, 0x52, 0x54, 0x50, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x65, 0x72, 0x76, + /* -04F0, */ 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x6c, 0x65, 0x2d, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, + /* -0500, */ 0x6c, 0x64, 0x3d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, + /* -0510, */ 0x6f, 0x72, 0x74, 0x6f, 0x6f, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, + /* -0520, */ 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3d, 0x3a, 0x67, 0x65, 0x6f, 0x70, 0x72, 0x69, + /* -0530, */ 0x76, 0x31, 0x30, 0x30, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, + /* -0540, */ 0x6f, 0x63, 0x2d, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x75, 0x72, 0x70, 0x72, 0x69, + /* -0550, */ 0x73, 0x65, 0x64, 0x61, 0x72, 0x6b, 0x75, 0x72, 0x6e, 0x3a, 0x6f, 0x6d, 0x61, 0x3a, 0x78, 0x6d, + /* -0560, */ 0x6c, 0x3a, 0x70, 0x72, 0x73, 0x3a, 0x70, 0x69, 0x64, 0x66, 0x3a, 0x6f, 0x6d, 0x61, 0x2d, 0x70, + /* -0570, */ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6f, 0x69, 0x73, 0x79, 0x3a, + /* -0580, */ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x65, + /* -0590, */ 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x73, 0x63, 0x68, 0x6f, 0x6f, + /* -05A0, */ 0x6c, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, + /* -05B0, */ 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6d, 0x65, 0x65, 0x74, + /* -05C0, */ 0x69, 0x6e, 0x67, 0x63, 0x61, 0x6c, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x74, 0x6f, 0x72, + /* -05D0, */ 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x3a, + /* -05E0, */ 0x77, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, + /* -05F0, */ 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x2d, + /* -0600, */ 0x66, 0x6f, 0x72, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x77, 0x61, 0x74, 0x63, 0x68, + /* -0610, */ 0x65, 0x72, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x70, 0x6c, 0x61, 0x63, 0x65, + /* -0620, */ 0x2d, 0x69, 0x73, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x77, 0x61, + /* -0630, */ 0x79, 0x68, 0x6f, 0x6d, 0x65, 0x70, 0x61, 0x67, 0x65, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, + /* -0640, */ 0x77, 0x61, 0x72, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x70, 0x75, 0x74, + /* -0650, */ 0x72, 0x61, 0x76, 0x65, 0x6c, 0x62, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + /* -0660, */ 0x65, 0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x3a, 0x72, 0x6c, 0x6d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x75, + /* -0670, */ 0x65, 0x3d, 0x3a, 0x63, 0x61, 0x70, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x75, 0x69, + /* -0680, */ 0x6c, 0x74, 0x79, 0x69, 0x6e, 0x76, 0x69, 0x6e, 0x63, 0x69, 0x62, 0x6c, 0x65, 0x76, 0x65, 0x6e, + /* -0690, */ 0x74, 0x3d, 0x6d, 0x6f, 0x6f, 0x64, 0x79, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x3d, 0x70, + /* -06A0, */ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x66, 0x72, 0x6f, 0x6d, + /* -06B0, */ 0x3d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x63, 0x61, 0x72, 0x64, 0x70, 0x6f, 0x73, 0x3d, 0x61, 0x75, + /* -06C0, */ 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + /* -06D0, */ 0x6f, 0x74, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + /* -06E0, */ 0x49, 0x44, 0x69, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x69, 0x73, 0x61, 0x70, 0x70, + /* -06F0, */ 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x6e, 0x6f, 0x74, 0x65, 0x2d, 0x77, 0x65, 0x6c, 0x6c, 0x69, + /* -0700, */ 0x62, 0x72, 0x61, 0x72, 0x79, 0x3a, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + /* -0710, */ 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x69, 0x76, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, + /* -0720, */ 0x65, 0x73, 0x73, 0x61, 0x72, 0x63, 0x61, 0x73, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + /* -0730, */ 0x74, 0x65, 0x64, 0x69, 0x6e, 0x64, 0x69, 0x67, 0x6e, 0x61, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x72, + /* -0740, */ 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x68, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x63, 0x6c, 0x61, + /* -0750, */ 0x73, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + /* -0760, */ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x2d, 0x62, 0x79, 0x3a, 0x63, 0x69, 0x70, 0x69, 0x64, + /* -0770, */ 0x66, 0x2d, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3d, 0x61, 0x63, 0x74, 0x6f, + /* -0780, */ 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x65, + /* -0790, */ 0x72, 0x69, 0x6f, 0x75, 0x73, 0x65, 0x6c, 0x3d, 0x3a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x78, + /* -07A0, */ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x3a, 0x72, 0x70, 0x69, 0x64, 0x75, 0x72, 0x6e, 0x3a, 0x69, + /* -07B0, */ 0x65, 0x74, 0x66, 0x3a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x78, 0x6d, 0x6c, 0x2d, 0x70, + /* -07C0, */ 0x61, 0x74, 0x63, 0x68, 0x2d, 0x6f, 0x70, 0x73, 0x65, 0x63, 0x2d, 0x61, 0x67, 0x72, 0x65, 0x65, + /* -07D0, */ 0x61, 0x72, 0x6c, 0x79, 0x2d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2d, 0x70, 0x61, 0x74, + /* -07E0, */ 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x68, 0x65, 0x2d, 0x70, 0x68, + /* -07F0, */ 0x6f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + /* -0800, */ 0x69, 0x6c, 0x69, 0x74, 0x79, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, + /* -0810, */ 0x78, 0x63, 0x69, 0x74, 0x65, 0x64, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + /* -0820, */ 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x70, 0x72, 0x69, 0x6f, + /* -0830, */ 0x72, 0x69, 0x74, 0x79, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, + /* -0840, */ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x72, 0x6f, 0x6f, 0x6d, 0x75, 0x73, 0x74, 0x55, 0x6e, 0x64, 0x65, + /* -0850, */ 0x72, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2d, 0x6e, 0x61, 0x6d, + /* -0860, */ 0x65, 0x3d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + /* -0870, */ 0x6f, 0x6e, 0x73, 0x2d, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x64, 0x70, 0x2d, 0x61, + /* -0880, */ 0x6e, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x72, 0x75, 0x65, 0x3a, 0x70, 0x69, + /* -0890, */ 0x64, 0x66, 0x2d, 0x64, 0x69, 0x66, 0x66, 0x72, 0x75, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x64, + /* -08A0, */ 0x75, 0x70, 0x6c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x63, 0x6f, + /* -08B0, */ 0x6e, 0x74, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x68, 0x6f, 0x70, 0x70, + /* -08C0, */ 0x69, 0x6e, 0x67, 0x2d, 0x61, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x3d, 0x61, 0x70, 0x70, 0x6f, + /* -08D0, */ 0x69, 0x6e, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3d, 0x61, 0x73, 0x73, 0x6f, 0x63, + /* -08E0, */ 0x69, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x69, 0x6e, 0x74, 0x65, + /* -08F0, */ 0x72, 0x65, 0x73, 0x74, 0x65, 0x64, 0x65, 0x76, 0x63, 0x61, 0x70, 0x73, 0x74, 0x61, 0x74, 0x75, + /* -0900, */ 0x73, 0x3d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x77, 0x69, + /* -0910, */ 0x6e, 0x66, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x72, 0x61, + /* -0920, */ 0x6e, 0x73, 0x69, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x6f, 0x73, 0x70, 0x69, 0x74, 0x61, 0x6c, + /* -0930, */ 0x61, 0x6e, 0x67, 0x3d, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x73, 0x69, 0x63, 0x6b, + /* -0940, */ 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x3f, 0x3e, 0x63, + /* -0950, */ 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x05, 0x0d, 0x34, 0x08, 0x0d, 0x06, 0x09, 0x0c, 0xe3, 0x07, 0x0d, + /* -0960, */ 0x48, 0x06, 0x0d, 0x36, 0x13, 0x0b, 0xab, 0x05, 0x09, 0x65, 0x07, 0x0c, 0xd4, 0x08, 0x0d, 0x40, + /* -0970, */ 0x05, 0x0d, 0x23, 0x05, 0x0c, 0x35, 0x07, 0x0c, 0xae, 0x05, 0x0d, 0x2f, 0x06, 0x08, 0xb9, 0x05, + /* -0980, */ 0x07, 0x2b, 0x04, 0x0d, 0x12, 0x06, 0x0d, 0x4f, 0x09, 0x0c, 0x2c, 0x04, 0x0c, 0x89, 0x04, 0x0a, + /* -0990, */ 0xf6, 0x09, 0x0b, 0x57, 0x0b, 0x0b, 0x05, 0x08, 0x0a, 0xda, 0x06, 0x0a, 0xda, 0x06, 0x04, 0x89, + /* -09A0, */ 0x05, 0x0b, 0xa6, 0x04, 0x0b, 0x94, 0x06, 0x05, 0x05, 0x07, 0x0b, 0x3f, 0x0e, 0x0b, 0xba, 0x07, + /* -09B0, */ 0x0b, 0x98, 0x0a, 0x0c, 0x8d, 0x09, 0x0b, 0x6d, 0x09, 0x0c, 0x8e, 0x0e, 0x0c, 0x48, 0x0a, 0x0c, + /* -09C0, */ 0xb2, 0x1d, 0x09, 0x56, 0x0d, 0x0c, 0x38, 0x06, 0x07, 0xba, 0x0b, 0x08, 0xb9, 0x0b, 0x07, 0xec, + /* -09D0, */ 0x06, 0x0d, 0x02, 0x0a, 0x0a, 0x46, 0x04, 0x08, 0xf4, 0x06, 0x0b, 0x6a, 0x04, 0x0a, 0xb6, 0x0c, + /* -09E0, */ 0x0c, 0x55, 0x08, 0x0a, 0x31, 0x04, 0x0a, 0x92, 0x08, 0x0a, 0x1b, 0x05, 0x0a, 0xb1, 0x04, 0x08, + /* -09F0, */ 0xc0, 0x05, 0x0a, 0x27, 0x05, 0x0a, 0xa7, 0x05, 0x0a, 0xac, 0x04, 0x0a, 0xba, 0x04, 0x07, 0xdc, + /* -0A00, */ 0x05, 0x08, 0xad, 0x0a, 0x09, 0x29, 0x0a, 0x08, 0xa7, 0x05, 0x0a, 0x56, 0x05, 0x0b, 0x4d, 0x07, + /* -0A10, */ 0x09, 0x2a, 0x0d, 0x09, 0xa7, 0x0b, 0x07, 0xa9, 0x06, 0x09, 0xc6, 0x0b, 0x0b, 0x5f, 0x0c, 0x09, + /* -0A20, */ 0xdf, 0x0b, 0x09, 0xe0, 0x06, 0x07, 0xcb, 0x0c, 0x0a, 0x0b, 0x09, 0x09, 0x20, 0x08, 0x0a, 0x97, + /* -0A30, */ 0x07, 0x09, 0xe0, 0x07, 0x0c, 0xfb, 0x06, 0x0a, 0x8c, 0x0e, 0x09, 0x7f, 0x0a, 0x09, 0x87, 0x0b, + /* -0A40, */ 0x0c, 0x71, 0x0a, 0x0c, 0x71, 0x06, 0x07, 0x93, 0x05, 0x0a, 0x66, 0x04, 0x08, 0x67, 0x04, 0x09, + /* -0A50, */ 0xba, 0x08, 0x09, 0x20, 0x0a, 0x0b, 0x72, 0x05, 0x0a, 0x72, 0x08, 0x07, 0xb3, 0x0b, 0x0a, 0xc5, + /* -0A60, */ 0x07, 0x09, 0xf2, 0x07, 0x08, 0x89, 0x04, 0x08, 0xad, 0x08, 0x0a, 0xbe, 0x06, 0x0c, 0x9f, 0x0b, + /* -0A70, */ 0x06, 0xd0, 0x0e, 0x08, 0x26, 0x08, 0x0a, 0x9f, 0x07, 0x09, 0xc6, 0x0a, 0x0c, 0x69, 0x07, 0x08, + /* -0A80, */ 0x85, 0x05, 0x0b, 0x7c, 0x07, 0x0a, 0x39, 0x0c, 0x09, 0x34, 0x07, 0x0a, 0x21, 0x09, 0x08, 0x7d, + /* -0A90, */ 0x07, 0x0c, 0xf5, 0x0b, 0x0c, 0xa3, 0x14, 0x06, 0xa6, 0x0d, 0x08, 0xb2, 0x0c, 0x07, 0x2a, 0x0c, + /* -0AA0, */ 0x08, 0xb3, 0x04, 0x07, 0x56, 0x07, 0x09, 0x1a, 0x04, 0x07, 0x52, 0x07, 0x07, 0x40, 0x05, 0x07, + /* -0AB0, */ 0x4d, 0x07, 0x0b, 0x80, 0x06, 0x07, 0x47, 0x16, 0x06, 0x91, 0x08, 0x0c, 0x62, 0x10, 0x09, 0xcf, + /* -0AC0, */ 0x10, 0x07, 0xdd, 0x09, 0x0a, 0xf6, 0x09, 0x06, 0xfc, 0x0c, 0x0b, 0x17, 0x07, 0x07, 0x39, 0x04, + /* -0AD0, */ 0x06, 0xf8, 0x07, 0x09, 0xa1, 0x06, 0x06, 0x8d, 0x05, 0x07, 0x21, 0x04, 0x0a, 0x55, 0x09, 0x0a, + /* -0AE0, */ 0xd2, 0x0c, 0x0a, 0xcf, 0x13, 0x06, 0xc8, 0x0a, 0x08, 0xec, 0x07, 0x0d, 0x06, 0x0b, 0x08, 0x0c, + /* -0AF0, */ 0x14, 0x0b, 0xd5, 0x12, 0x07, 0xbe, 0x0d, 0x07, 0xd1, 0x16, 0x08, 0x01, 0x14, 0x0b, 0xf1, 0x06, + /* -0B00, */ 0x05, 0xb4, 0x07, 0x04, 0x56, 0x09, 0x04, 0x17, 0x0c, 0x0a, 0xea, 0x09, 0x04, 0x1f, 0x0a, 0x07, + /* -0B10, */ 0x7e, 0x0b, 0x07, 0x6a, 0x07, 0x0c, 0x0f, 0x0b, 0x07, 0xa0, 0x0a, 0x0c, 0x96, 0x06, 0x05, 0x28, + /* -0B20, */ 0x06, 0x0a, 0x7d, 0x05, 0x06, 0x1f, 0x07, 0x05, 0x8b, 0x0a, 0x04, 0x3c, 0x06, 0x05, 0xae, 0x04, + /* -0B30, */ 0x06, 0x50, 0x09, 0x0a, 0xe2, 0x06, 0x05, 0xf6, 0x07, 0x07, 0xfd, 0x09, 0x0b, 0x33, 0x0a, 0x0c, + /* -0B40, */ 0xec, 0x0a, 0x0a, 0x83, 0x07, 0x06, 0x54, 0x06, 0x04, 0x90, 0x04, 0x05, 0x3f, 0x05, 0x0a, 0x92, + /* -0B50, */ 0x07, 0x07, 0x8a, 0x07, 0x08, 0xcc, 0x08, 0x09, 0xea, 0x07, 0x04, 0x96, 0x05, 0x06, 0x10, 0x08, + /* -0B60, */ 0x07, 0x98, 0x0a, 0x06, 0xf1, 0x08, 0x04, 0x79, 0x09, 0x0b, 0x22, 0x07, 0x0b, 0x8e, 0x07, 0x0b, + /* -0B70, */ 0x46, 0x04, 0x0d, 0x3c, 0x06, 0x04, 0x80, 0x08, 0x07, 0x12, 0x09, 0x09, 0x4a, 0x07, 0x04, 0xe3, + /* -0B80, */ 0x07, 0x05, 0x84, 0x05, 0x09, 0x7a, 0x05, 0x06, 0x01, 0x09, 0x09, 0x12, 0x04, 0x09, 0x52, 0x0d, + /* -0B90, */ 0x04, 0xaa, 0x0d, 0x08, 0x56, 0x08, 0x04, 0xdc, 0x07, 0x05, 0x92, 0x05, 0x05, 0x0c, 0x0a, 0x04, + /* -0BA0, */ 0x4c, 0x04, 0x06, 0x2c, 0x0b, 0x04, 0xd1, 0x04, 0x06, 0x24, 0x09, 0x0c, 0x40, 0x04, 0x04, 0xce, + /* -0BB0, */ 0x0c, 0x08, 0xc1, 0x11, 0x04, 0x00, 0x05, 0x07, 0x34, 0x0a, 0x06, 0x6a, 0x08, 0x0d, 0x28, 0x05, + /* -0BC0, */ 0x06, 0x1a, 0x0a, 0x04, 0x28, 0x07, 0x0a, 0xfe, 0x06, 0x04, 0xff, 0x08, 0x09, 0x94, 0x07, 0x05, + /* -0BD0, */ 0x76, 0x10, 0x08, 0x98, 0x06, 0x05, 0xf0, 0x06, 0x09, 0x03, 0x10, 0x09, 0x03, 0x09, 0x08, 0x1e, + /* -0BE0, */ 0x0a, 0x08, 0x3c, 0x06, 0x09, 0x9b, 0x0d, 0x0c, 0xbb, 0x07, 0x06, 0xe3, 0x05, 0x09, 0xcc, 0x06, + /* -0BF0, */ 0x0a, 0x15, 0x07, 0x04, 0x73, 0x05, 0x06, 0x73, 0x0d, 0x06, 0x73, 0x05, 0x08, 0x45, 0x08, 0x0a, + /* -0C00, */ 0x29, 0x09, 0x0a, 0x40, 0x05, 0x07, 0x1a, 0x0a, 0x07, 0x1a, 0x09, 0x0b, 0x4f, 0x09, 0x0c, 0xdb, + /* -0C10, */ 0x06, 0x05, 0xea, 0x06, 0x05, 0xde, 0x0a, 0x04, 0x0e, 0x0a, 0x0b, 0x0e, 0x09, 0x06, 0x86, 0x08, + /* -0C20, */ 0x05, 0x60, 0x0b, 0x07, 0x74, 0x09, 0x05, 0x4f, 0x08, 0x04, 0xf0, 0x07, 0x09, 0x90, 0x06, 0x08, + /* -0C30, */ 0x70, 0x0a, 0x0c, 0x21, 0x07, 0x05, 0x6f, 0x0b, 0x0c, 0xcc, 0x04, 0x07, 0x90, 0x07, 0x04, 0xea, + /* -0C40, */ 0x0a, 0x08, 0x33, 0x04, 0x06, 0x34, 0x09, 0x06, 0xdc, 0x04, 0x06, 0x40, 0x07, 0x05, 0x2e, 0x04, + /* -0C50, */ 0x06, 0x48, 0x06, 0x07, 0x87, 0x07, 0x05, 0x68, 0x0a, 0x0d, 0x1a, 0x07, 0x04, 0x45, 0x07, 0x05, + /* -0C60, */ 0x05, 0x08, 0x05, 0x0e, 0x08, 0x05, 0x58, 0x08, 0x04, 0xb6, 0x10, 0x09, 0xf8, 0x04, 0x06, 0x3c, + /* -0C70, */ 0x07, 0x09, 0xbc, 0x0c, 0x06, 0xd0, 0x0c, 0x0b, 0xe7, 0x04, 0x06, 0x44, 0x04, 0x0a, 0x31, 0x0b, + /* -0C80, */ 0x0c, 0x05, 0x04, 0x06, 0x28, 0x11, 0x07, 0x5a, 0x07, 0x0c, 0xc5, 0x07, 0x05, 0xa0, 0x0c, 0x09, + /* -0C90, */ 0x6f, 0x08, 0x0c, 0xbb, 0x08, 0x0a, 0x76, 0x09, 0x08, 0x16, 0x08, 0x08, 0x69, 0x06, 0x05, 0xe4, + /* -0CA0, */ 0x09, 0x04, 0x86, 0x07, 0x05, 0x38, 0x06, 0x0a, 0x4f, 0x08, 0x04, 0xc6, 0x0f, 0x08, 0xf4, 0x0b, + /* -0CB0, */ 0x04, 0x31, 0x07, 0x0a, 0x04, 0x07, 0x08, 0xa1, 0x0d, 0x0c, 0x55, 0x06, 0x05, 0xc0, 0x06, 0x05, + /* -0CC0, */ 0xba, 0x05, 0x05, 0x41, 0x08, 0x0b, 0x87, 0x08, 0x04, 0x89, 0x04, 0x05, 0x35, 0x0c, 0x0a, 0x5a, + /* -0CD0, */ 0x09, 0x04, 0x68, 0x09, 0x04, 0x9c, 0x0a, 0x06, 0xba, 0x06, 0x07, 0x0d, 0x05, 0x07, 0x25, 0x09, + /* -0CE0, */ 0x0b, 0x9d, 0x09, 0x0a, 0x69, 0x06, 0x0a, 0x6c, 0x04, 0x06, 0x38, 0x04, 0x06, 0x30, 0x07, 0x0d, + /* -0CF0, */ 0x13, 0x08, 0x08, 0x4c, 0x05, 0x06, 0x15, 0x06, 0x04, 0x50, 0x0a, 0x07, 0x04, 0x06, 0x07, 0xf7, + /* -0D00, */ 0x04, 0x08, 0x49, 0x0f, 0x08, 0x89, 0x0c, 0x09, 0x3f, 0x05, 0x06, 0x81, 0x11, 0x08, 0xdc, 0x0d, + /* -0D10, */ 0x04, 0x5c, 0x11, 0x06, 0x5a, 0x05, 0x0d, 0x0e, 0x06, 0x05, 0xd8, 0x04, 0x08, 0xd3, 0x06, 0x05, + /* -0D20, */ 0xd2, 0x07, 0x05, 0x7d, 0x06, 0x05, 0xcc, 0x07, 0x08, 0xd6, 0x05, 0x06, 0x0b, 0x07, 0x05, 0xa7, + /* -0D30, */ 0x05, 0x05, 0x16, 0x08, 0x05, 0x1a, 0x09, 0x05, 0x46, 0x06, 0x05, 0xc6, 0x06, 0x09, 0x31, 0x0d, + /* -0D40, */ 0x0b, 0xcf, 0x09, 0x08, 0x62, 0x08, 0x04, 0xf8, 0x04, 0x08, 0x54, 0x0a, 0x06, 0x7f, 0x04, 0x04, + /* -0D50, */ 0x71, 0x0c, 0x0c, 0x16, 0x04, 0x05, 0x2e, 0x08, 0x0b, 0x3f, 0x11, 0x0c, 0x23, 0x08, 0x0c, 0x7b, + /* -0D60, */ 0x09, 0x0b, 0xc7, 0x07, 0x07, 0xf6, 0x05, 0x0b, 0x3b, 0x09, 0x08, 0x75, 0x09, 0x0c, 0x81, 0x09, + /* -0D70, */ 0x06, 0xe9, 0x0b, 0x09, 0xb0, 0x07, 0x05, 0x22, 0x07, 0x04, 0xa3, 0x07, 0x06, 0xc2, 0x07, 0x05, + /* -0D80, */ 0x99, 0x05, 0x06, 0x06, 0x05, 0x05, 0xfc, 0x04, 0x09, 0xc3, 0x04, 0x06, 0x4c, 0x08, 0x04, 0xbe, + /* -0D90, */ 0x09, 0x0b, 0x2a +}; + +static GHashTable *state_buffer_table=NULL; + + +static void +sigcomp_init_udvm(void) { + gchar *partial_state_str; + guint8 *sip_sdp_buff, *presence_buff; + state_buffer_table = g_hash_table_new_full(g_str_hash, + g_str_equal, + g_free, /* key_destroy_func */ + g_free); /* value_destroy_func */ + /* + * Store static dictionaries in hash table + */ + sip_sdp_buff = (guint8 *)g_malloc(SIP_SDP_STATE_LENGTH + 8); + + partial_state_str = bytes_to_str(NULL, sip_sdp_state_identifier, 6); + memset(sip_sdp_buff, 0, 8); + sip_sdp_buff[0] = SIP_SDP_STATE_LENGTH >> 8; + sip_sdp_buff[1] = SIP_SDP_STATE_LENGTH & 0xff; + memcpy(sip_sdp_buff+8, sip_sdp_static_dictionaty_for_sigcomp, SIP_SDP_STATE_LENGTH); + + g_hash_table_insert(state_buffer_table, g_strdup(partial_state_str), sip_sdp_buff); + wmem_free(NULL, partial_state_str); + + presence_buff = (guint8 *)g_malloc(PRESENCE_STATE_LENGTH + 8); + + partial_state_str = bytes_to_str(NULL, presence_state_identifier, 6); + + memset(presence_buff, 0, 8); + presence_buff[0] = PRESENCE_STATE_LENGTH >> 8; + presence_buff[1] = PRESENCE_STATE_LENGTH & 0xff; + memcpy(presence_buff+8, presence_static_dictionary_for_sigcomp, PRESENCE_STATE_LENGTH); + + g_hash_table_insert(state_buffer_table, g_strdup(partial_state_str), presence_buff); + wmem_free(NULL, partial_state_str); +} + +static void +sigcomp_cleanup_udvm(void) { + g_hash_table_destroy(state_buffer_table); +} + + +static int udvm_state_access(tvbuff_t *tvb, proto_tree *tree,guint8 *buff,guint16 p_id_start, guint16 p_id_length, guint16 state_begin, guint16 *state_length, + guint16 *state_address, guint16 *state_instruction, + gint hf_id) +{ + int result_code = 0; + guint32 n; + guint16 k; + guint16 buf_size_real; + guint16 byte_copy_right; + guint16 byte_copy_left; + char partial_state[STATE_BUFFER_SIZE]; /* Size is 6 - 20 */ + guint8 *state_buff; + gchar *partial_state_str; + + /* + * Perform initial checks on validity of data + * RFC 3320 : + * 9.4.5. STATE-ACCESS + * : + * Decompression failure occurs if partial_identifier_length does not + * lie between 6 and 20 inclusive. Decompression failure also occurs if + * no state item matching the partial state identifier can be found, if + * more than one state item matches the partial identifier, or if + * partial_identifier_length is less than the minimum_access_length of + * the matched state item. Otherwise, a state item is returned from the + * state handler. + */ + + if (( p_id_length < STATE_MIN_ACCESS_LEN ) || ( p_id_length > STATE_BUFFER_SIZE )) { + result_code = 1; + return result_code; + } + + n = 0; + while ( n < p_id_length && n < STATE_BUFFER_SIZE && p_id_start + n < UDVM_MEMORY_SIZE ) { + partial_state[n] = buff[p_id_start + n]; + n++; + } + partial_state_str = bytes_to_str(wmem_packet_scope(), partial_state, p_id_length); + proto_tree_add_item(tree, hf_sigcomp_accessing_state, tvb, 0, -1, ENC_NA); + proto_tree_add_string(tree,hf_id, tvb, 0, 0, partial_state_str); + + /* Debug + * ws_warning("State Access: partial state =%s",partial_state_str); + * ws_warning("g_hash_table_lookup = 0x%x",state_buff); + * ws_warning("State Access: partial state =%s",partial_state_str); + */ + state_buff = (guint8 *)g_hash_table_lookup(state_buffer_table, partial_state_str); + if ( state_buff == NULL ) { + result_code = 2; /* No state match */ + return result_code; + } + /* + * sip_sdp_static_dictionaty + * + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + /* + * buff = Where "state" will be stored + * p_id_start = Partial state identifier start pos in the buffer(buff) + * p-id_length = Partial state identifier length + * state_begin = Where to start to read state from + * state_length = Length of state + * state_address = Address where to store the state in the buffer(buff) + * state_instruction = + * FALSE = Indicates that state_* is in the stored state + */ + + buf_size_real = (state_buff[0] << 8) | state_buff[1]; + + /* + * The value of + * state_length MUST be taken from the returned item of state in the + * case that the state_length operand is set to 0. + * + * The same is true of state_address, state_instruction. + */ + if (*state_length == 0) { + *state_length = buf_size_real; + } + if ( *state_address == 0 ) { + *state_address = state_buff[2] << 8; + *state_address = *state_address | state_buff[3]; + } + if ( *state_instruction == 0 ) { + *state_instruction = state_buff[4] << 8; + *state_instruction = *state_instruction | state_buff[5]; + } + + /* + * Decompression failure occurs if bytes are copied from beyond the end of + * the state_value. + */ + if ((state_begin + *state_length) > buf_size_real) { + return 3; + } + + /* + * Note that decompression failure will always occur if the state_length + * operand is set to 0 but the state_begin operand is non-zero. + */ + if (*state_length == 0 && state_begin != 0) { + return 17; + } + + n = state_begin + 8; + k = *state_address; + + /* + * NOTE: Strictly speaking, byte_copy_left and byte_copy_right should + * not be used if this has been called for bytecode referenced in + * the message header. However, since the memory is initialised + * to zero, the code works OK. + */ + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + /* debug + *ws_warning(" state_begin %u state_address %u",state_begin , *state_address); + */ + while ( (gint32) n < (state_begin + *state_length + 8) && n < UDVM_MEMORY_SIZE ) { + buff[k] = state_buff[n]; + /* debug + ws_warning(" Loading 0x%x at address %u",buff[k] , k); + */ + k = ( k + 1 ) & 0xffff; + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + n++; + } + return 0; + /* + * End SIP + */ + +} + +static void udvm_state_create(guint8 *state_buff,guint8 *state_identifier,guint16 p_id_length) { + + char partial_state[STATE_BUFFER_SIZE]; + guint i; + gchar *partial_state_str; + gchar *dummy_buff; + /* + * Debug + ws_warning("Received items of state,state_length_buff[0]= %u, state_length_buff[1]= %u", + state_length_buff[0],state_length_buff[1]); + + */ + i = 0; + while ( i < p_id_length && i < STATE_BUFFER_SIZE ) { + partial_state[i] = state_identifier[i]; + i++; + } + partial_state_str = bytes_to_str(NULL, partial_state, p_id_length); + + dummy_buff = (gchar *)g_hash_table_lookup(state_buffer_table, partial_state_str); + if ( dummy_buff == NULL ) { + g_hash_table_insert(state_buffer_table, g_strdup(partial_state_str), state_buff); + } else { + /* The buffer allocated by sigcomp-udvm.c wasn't needed so free it + */ + g_free(state_buff); + + } + wmem_free(NULL, partial_state_str); +} + +#if 1 +static void udvm_state_free(guint8 buff[] _U_,guint16 p_id_start _U_,guint16 p_id_length _U_) { +} +#else +void udvm_state_free(guint8 buff[],guint16 p_id_start,guint16 p_id_length) { + char partial_state[STATE_BUFFER_SIZE]; + guint i; + gchar *partial_state_str; + + gchar *dummy_buff; + + i = 0; + while ( i < p_id_length && i < STATE_BUFFER_SIZE && p_id_start + i < UDVM_MEMORY_SIZE ) { + partial_state[i] = buff[p_id_start + i]; + i++; + } + partial_state_str = bytes_to_str(NULL, partial_state, p_id_length); + /* TODO Implement a state create counter before actually freeing states + * Hmm is it a good idea to free the buffer at all? + * ws_warning("State-free on %s ",partial_state_str); + */ + dummy_buff = g_hash_table_lookup(state_buffer_table, partial_state_str); + if ( dummy_buff != NULL ) { + g_hash_table_remove (state_buffer_table, partial_state_str); + g_free(dummy_buff); + } + wmem_free(NULL, partial_state_str); +} +#endif + +/********************************************************************************************** + * + * SIGCOMP DECOMPRESSION + * + **********************************************************************************************/ +#define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0 +#define SIGCOMP_INSTR_AND 1 +#define SIGCOMP_INSTR_OR 2 +#define SIGCOMP_INSTR_NOT 3 +#define SIGCOMP_INSTR_LSHIFT 4 +#define SIGCOMP_INSTR_RSHIFT 5 +#define SIGCOMP_INSTR_ADD 6 +#define SIGCOMP_INSTR_SUBTRACT 7 +#define SIGCOMP_INSTR_MULTIPLY 8 +#define SIGCOMP_INSTR_DIVIDE 9 +#define SIGCOMP_INSTR_REMAINDER 10 +#define SIGCOMP_INSTR_SORT_ASCENDING 11 +#define SIGCOMP_INSTR_SORT_DESCENDING 12 +#define SIGCOMP_INSTR_SHA_1 13 +#define SIGCOMP_INSTR_LOAD 14 +#define SIGCOMP_INSTR_MULTILOAD 15 +#define SIGCOMP_INSTR_PUSH 16 +#define SIGCOMP_INSTR_POP 17 +#define SIGCOMP_INSTR_COPY 18 +#define SIGCOMP_INSTR_COPY_LITERAL 19 +#define SIGCOMP_INSTR_COPY_OFFSET 20 +#define SIGCOMP_INSTR_MEMSET 21 +#define SIGCOMP_INSTR_JUMP 22 +#define SIGCOMP_INSTR_COMPARE 23 +#define SIGCOMP_INSTR_CALL 24 +#define SIGCOMP_INSTR_RETURN 25 +#define SIGCOMP_INSTR_SWITCH 26 +#define SIGCOMP_INSTR_CRC 27 +#define SIGCOMP_INSTR_INPUT_BYTES 28 +#define SIGCOMP_INSTR_INPUT_BITS 29 +#define SIGCOMP_INSTR_INPUT_HUFFMAN 30 +#define SIGCOMP_INSTR_STATE_ACCESS 31 +#define SIGCOMP_INSTR_STATE_CREATE 32 +#define SIGCOMP_INSTR_STATE_FREE 33 +#define SIGCOMP_INSTR_OUTPUT 34 +#define SIGCOMP_INSTR_END_MESSAGE 35 + +static const value_string udvm_instruction_code_vals[] = { + { SIGCOMP_INSTR_DECOMPRESSION_FAILURE, "DECOMPRESSION-FAILURE" }, + { SIGCOMP_INSTR_AND, "AND" }, + { SIGCOMP_INSTR_OR, "OR" }, + { SIGCOMP_INSTR_NOT, "NOT" }, + { SIGCOMP_INSTR_LSHIFT, "LSHIFT" }, + { SIGCOMP_INSTR_RSHIFT, "RSHIFT" }, + { SIGCOMP_INSTR_ADD, "ADD" }, + { SIGCOMP_INSTR_SUBTRACT, "SUBTRACT" }, + { SIGCOMP_INSTR_MULTIPLY, "MULTIPLY" }, + { SIGCOMP_INSTR_DIVIDE, "DIVIDE" }, + { SIGCOMP_INSTR_REMAINDER, "REMAINDER" }, + { SIGCOMP_INSTR_SORT_ASCENDING, "SORT-ASCENDING" }, + { SIGCOMP_INSTR_SORT_DESCENDING, "SORT-DESCENDING" }, + { SIGCOMP_INSTR_SHA_1, "SHA-1" }, + { SIGCOMP_INSTR_LOAD, "LOAD" }, + { SIGCOMP_INSTR_MULTILOAD, "MULTILOAD" }, + { SIGCOMP_INSTR_PUSH, "PUSH" }, + { SIGCOMP_INSTR_POP, "POP" }, + { SIGCOMP_INSTR_COPY, "COPY" }, + { SIGCOMP_INSTR_COPY_LITERAL, "COPY-LITERAL" }, + { SIGCOMP_INSTR_COPY_OFFSET, "COPY-OFFSET" }, + { SIGCOMP_INSTR_MEMSET, "MEMSET" }, + { SIGCOMP_INSTR_JUMP, "JUMP" }, + { SIGCOMP_INSTR_COMPARE, "COMPARE" }, + { SIGCOMP_INSTR_CALL, "CALL" }, + { SIGCOMP_INSTR_RETURN, "RETURN" }, + { SIGCOMP_INSTR_SWITCH, "SWITCH" }, + { SIGCOMP_INSTR_CRC, "CRC" }, + { SIGCOMP_INSTR_INPUT_BYTES, "INPUT-BYTES" }, + { SIGCOMP_INSTR_INPUT_BITS, "INPUT-BITS" }, + { SIGCOMP_INSTR_INPUT_HUFFMAN, "INPUT-HUFFMAN" }, + { SIGCOMP_INSTR_STATE_ACCESS, "STATE-ACCESS" }, + { SIGCOMP_INSTR_STATE_CREATE, "STATE-CREATE" }, + { SIGCOMP_INSTR_STATE_FREE, "STATE-FREE" }, + { SIGCOMP_INSTR_OUTPUT, "OUTPUT" }, + { SIGCOMP_INSTR_END_MESSAGE, "END-MESSAGE" }, + { 0, NULL } +}; +static value_string_ext udvm_instruction_code_vals_ext = + VALUE_STRING_EXT_INIT(udvm_instruction_code_vals); + +/* Internal result code values of decompression failures */ +static const value_string result_code_vals[] = { + { 0, "No decompression failure" }, + { 1, "Partial state length less than 6 or greater than 20 bytes long" }, + { 2, "No state match" }, + { 3, "state_begin + state_length > size of state" }, + { 4, "Operand_2 is Zero" }, + { 5, "Switch statement failed j >= n" }, + { 6, "Attempt to jump outside of UDVM memory" }, + { 7, "L in input-bits > 16" }, + { 8, "input_bit_order > 7" }, + { 9, "Instruction Decompression failure encountered" }, + { 10, "Input huffman failed j > n" }, + { 11, "Input bits requested beyond end of message" }, + { 12, "more than four state creation requests are made before the END-MESSAGE instruction" }, + { 13, "state_retention_priority is 65535" }, + { 14, "Input bytes requested beyond end of message" }, + { 15, "Maximum number of UDVM cycles reached" }, + { 16, "UDVM stack underflow" }, + { 17, "state_length is 0, but state_begin is non-zero" }, + {255, "This branch isn't coded yet" }, + { 0, NULL } +}; + + /* The simplest operand type is the literal (#), which encodes a + * constant integer from 0 to 65535 inclusive. A literal operand may + * require between 1 and 3 bytes depending on its value. + * Bytecode: Operand value: Range: + * 0nnnnnnn N 0 - 127 + * 10nnnnnn nnnnnnnn N 0 - 16383 + * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535 + * + * Figure 8: Bytecode for a literal (#) operand + * + */ +static int +decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value) +{ + guint bytecode; + guint16 operand; + guint test_bits; + guint offset = operand_address; + guint8 temp_data; + + if (operand_address >= UDVM_MEMORY_SIZE) + return -1; + bytecode = buff[operand_address]; + test_bits = bytecode >> 7; + if (test_bits == 1) { + test_bits = bytecode >> 6; + if (test_bits == 2) { + /* + * 10nnnnnn nnnnnnnn N 0 - 16383 + */ + temp_data = buff[operand_address] & 0x1f; + operand = temp_data << 8; + temp_data = buff[(operand_address + 1) & 0xffff]; + operand = operand | temp_data; + *value = operand; + offset = offset + 2; + + } else { + /* + * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535 + */ + offset ++; + temp_data = buff[operand_address] & 0x1f; + operand = temp_data << 8; + temp_data = buff[(operand_address + 1) & 0xffff]; + operand = operand | temp_data; + *value = operand; + offset = offset + 2; + + } + } else { + /* + * 0nnnnnnn N 0 - 127 + */ + operand = ( bytecode & 0x7f); + *value = operand; + offset ++; + } + + return offset; + +} + +/* + * The second operand type is the reference ($), which is always used to + * access a 2-byte value located elsewhere in the UDVM memory. The + * bytecode for a reference operand is decoded to be a constant integer + * from 0 to 65535 inclusive, which is interpreted as the memory address + * containing the actual value of the operand. + * Bytecode: Operand value: Range: + * + * 0nnnnnnn memory[2 * N] 0 - 65535 + * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 + * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + * + * Figure 9: Bytecode for a reference ($) operand + */ +static int +dissect_udvm_reference_operand_memory(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest) +{ + guint bytecode; + guint16 operand; + guint offset = operand_address; + guint test_bits; + guint8 temp_data; + guint16 temp_data16; + + if (operand_address >= UDVM_MEMORY_SIZE) + return -1; + bytecode = buff[operand_address]; + test_bits = bytecode >> 7; + if (test_bits == 1) { + test_bits = bytecode >> 6; + if (test_bits == 2) { + /* + * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 + */ + temp_data = buff[operand_address] & 0x3f; + operand = temp_data << 8; + temp_data = buff[(operand_address + 1) & 0xffff]; + operand = operand | temp_data; + operand = (operand * 2); + *result_dest = operand; + temp_data16 = buff[operand] << 8; + temp_data16 = temp_data16 | buff[(operand+1) & 0xffff]; + *value = temp_data16; + offset = offset + 2; + + } else { + /* + * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + */ + operand_address++; + operand = buff[operand_address] << 8; + operand = operand | buff[(operand_address + 1) & 0xffff]; + *result_dest = operand; + temp_data16 = buff[operand] << 8; + temp_data16 = temp_data16 | buff[(operand+1) & 0xffff]; + *value = temp_data16; + offset = offset + 3; + + } + } else { + /* + * 0nnnnnnn memory[2 * N] 0 - 65535 + */ + operand = ( bytecode & 0x7f); + operand = (operand * 2); + *result_dest = operand; + temp_data16 = buff[operand] << 8; + temp_data16 = temp_data16 | buff[(operand+1) & 0xffff]; + *value = temp_data16; + offset ++; + } + + if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 ) + return -1; + + return offset; +} + +/* RFC3320 + * Figure 10: Bytecode for a multitype (%) operand + * Bytecode: Operand value: Range: HEX val + * 00nnnnnn N 0 - 63 0x00 + * 01nnnnnn memory[2 * N] 0 - 65535 0x40 + * 1000011n 2 ^ (N + 6) 64 , 128 0x86 + * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88 + * 111nnnnn N + 65504 65504 - 65535 0xe0 + * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90 + * 101nnnnn nnnnnnnn N 0 - 8191 0xa0 + * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0 + * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80 + * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81 + */ +static int +decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value) +{ + guint test_bits; + guint bytecode; + guint offset = operand_address; + guint16 operand; + guint32 result; + guint8 temp_data; + guint16 temp_data16; + guint16 memmory_addr = 0; + + *value = 0; + + if (operand_address >= UDVM_MEMORY_SIZE) + return -1; + bytecode = buff[operand_address]; + test_bits = ( bytecode & 0xc0 ) >> 6; + switch (test_bits ) { + case 0: + /* + * 00nnnnnn N 0 - 63 + */ + operand = buff[operand_address]; + /* debug + *ws_warning("Reading 0x%x From address %u",operand,offset); + */ + *value = operand; + offset ++; + break; + case 1: + /* + * 01nnnnnn memory[2 * N] 0 - 65535 + */ + memmory_addr = ( bytecode & 0x3f) * 2; + temp_data16 = buff[memmory_addr] << 8; + temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff]; + *value = temp_data16; + offset ++; + break; + case 2: + /* Check tree most significant bits */ + test_bits = ( bytecode & 0xe0 ) >> 5; + if ( test_bits == 5 ) { + /* + * 101nnnnn nnnnnnnn N 0 - 8191 + */ + temp_data = buff[operand_address] & 0x1f; + operand = temp_data << 8; + temp_data = buff[(operand_address + 1) & 0xffff]; + operand = operand | temp_data; + *value = operand; + offset = offset + 2; + } else { + test_bits = ( bytecode & 0xf0 ) >> 4; + if ( test_bits == 9 ) { + /* + * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 + */ + temp_data = buff[operand_address] & 0x0f; + operand = temp_data << 8; + temp_data = buff[(operand_address + 1) & 0xffff]; + operand = operand | temp_data; + operand = operand + 61440; + *value = operand; + offset = offset + 2; + } else { + test_bits = ( bytecode & 0x08 ) >> 3; + if ( test_bits == 1) { + /* + * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 + */ + + result = 1 << ((buff[operand_address] & 0x07) + 8); + operand = result & 0xffff; + *value = operand; + offset ++; + } else { + test_bits = ( bytecode & 0x0e ) >> 1; + if ( test_bits == 3 ) { + /* + * 1000 011n 2 ^ (N + 6) 64 , 128 + */ + result = 1 << ((buff[operand_address] & 0x01) + 6); + operand = result & 0xffff; + *value = operand; + offset ++; + } else { + /* + * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535 + * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + */ + offset ++; + temp_data16 = buff[(operand_address + 1) & 0xffff] << 8; + temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff]; + /* debug + * ws_warning("Reading 0x%x From address %u",temp_data16,operand_address); + */ + if ( (bytecode & 0x01) == 1 ) { + memmory_addr = temp_data16; + temp_data16 = buff[memmory_addr] << 8; + temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff]; + } + *value = temp_data16; + offset = offset +2; + } + + + } + } + } + break; + + case 3: + test_bits = ( bytecode & 0x20 ) >> 5; + if ( test_bits == 1 ) { + /* + * 111nnnnn N + 65504 65504 - 65535 + */ + operand = ( buff[operand_address] & 0x1f) + 65504; + *value = operand; + offset ++; + } else { + /* + * 110nnnnn nnnnnnnn memory[N] 0 - 65535 + */ + memmory_addr = buff[operand_address] & 0x1f; + memmory_addr = memmory_addr << 8; + memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff]; + temp_data16 = buff[memmory_addr] << 8; + temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff]; + *value = temp_data16; + /* debug + * ws_warning("Reading 0x%x From address %u",temp_data16,memmory_addr); + */ + offset = offset +2; + } + + default : + break; + } + return offset; +} +/* + * + * The fourth operand type is the address (@). This operand is decoded + * as a multitype operand followed by a further step: the memory address + * of the UDVM instruction containing the address operand is added to + * obtain the correct operand value. So if the operand value from + * Figure 10 is D then the actual operand value of an address is + * calculated as follows: + * + * operand_value = (memory_address_of_instruction + D) modulo 2^16 + * + * Address operands are always used in instructions that control program + * flow, because they ensure that the UDVM bytecode is position- + * independent code (i.e., it will run independently of where it is + * placed in the UDVM memory). + */ +static int +decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address) +{ + guint32 result; + guint16 value1; + gint next_operand_address; + + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value1); + result = value1 & 0xffff; + result = result + current_address; + *value = result & 0xffff; + return next_operand_address; +} + + +/* + * This is a lookup table used to reverse the bits in a byte. + */ +static guint8 reverse [] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + + +static int +decomp_dispatch_get_bits( + tvbuff_t *message_tvb, + proto_tree *udvm_tree, + guint8 bit_order, + guint8 *buff, + guint16 *old_input_bit_order, + guint16 *remaining_bits, + guint16 *input_bits, + guint *input_address, + guint16 length, + guint16 *result_code, + guint msg_end, + gboolean print_level_1) +{ + guint16 input_bit_order; + guint16 bits_still_required = length; + guint16 value = 0; + guint8 octet; + gint extra_bytes_available = msg_end - *input_address; + gint p_bit; + gint prev_p_bit = *old_input_bit_order & 0x0001; + gint bits_to_use = 0; + + + input_bit_order = buff[68] << 8; + input_bit_order = input_bit_order | buff[69]; + *result_code = 0; + p_bit = (input_bit_order & 0x0001) != 0; + + /* + * Discard any spare bits. + * Note: We take care to avoid remaining_bits having the value of 8. + */ + if (prev_p_bit != p_bit) + { + *remaining_bits = 0; + *old_input_bit_order = input_bit_order; + } + + /* + * Check we can supply the required number of bits now, before we alter + * the input buffer's state. + */ + if (*remaining_bits + extra_bytes_available * 8 < length) + { + *result_code = 11; + return 0xfbad; + } + + /* Note: This is never called with length > 16, so the following loop + * never loops more than three time. */ + while (bits_still_required > 0) + { + /* + * We only put anything into input_bits if we know we will remove + * at least one bit. That ensures we can simply discard the spare + * bits if the P-bit changes. + */ + if (*remaining_bits == 0) + { + octet = tvb_get_guint8(message_tvb, *input_address); + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_getting_value, message_tvb, *input_address, 1, octet, + " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address); + } + *input_address = *input_address + 1; + + if (p_bit != 0) + { + octet = reverse[octet]; + } + *input_bits = octet; + *remaining_bits = 8; + } + + /* Add some more bits to the accumulated value. */ + bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits; + bits_still_required -= bits_to_use; + + *input_bits <<= bits_to_use; /* Shift bits into MSByte */ + value = (value << bits_to_use) /* Then add to the accumulated value */ + | ((*input_bits >> 8) & 0xFF); + *remaining_bits -= bits_to_use; + *input_bits &= 0x00FF; /* Leave just the remaining bits */ + } + + if ((bit_order != 0) && (length <= 16)) + { + /* Bit reverse the entire word. */ + guint16 lsb = reverse[(value >> 8) & 0xFF]; + guint16 msb = reverse[value & 0xFF]; + + value = ((msb << 8) | lsb) >> (16 - length); + } + + return value; +} + +static tvbuff_t* +decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo, + proto_tree *udvm_tree, gint udvm_mem_dest, + gint print_flags, gint hf_id, + gint header_len, + gint byte_code_state_len, gint byte_code_id_len, + gint udvm_start_ip) +{ + tvbuff_t *decomp_tvb; + /* UDVM memory must be initialised to zero */ + guint8 *buff = (guint8 *)wmem_alloc0(wmem_packet_scope(), UDVM_MEMORY_SIZE); + char string[2]; + guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */ + guint32 i = 0; + guint16 n = 0; + guint16 m = 0; + guint16 x; + guint k = 0; + guint16 H; + guint16 oldH; + guint offset = 0; + guint start_offset; + guint result_dest; + guint code_length = 0; + guint8 current_instruction; + guint current_address; + guint operand_address; + guint input_address; + guint16 output_address = 0; + gint next_operand_address; + guint8 octet; + guint8 msb; + guint8 lsb; + guint16 byte_copy_right; + guint16 byte_copy_left; + guint16 input_bit_order; + guint16 stack_location; + guint16 stack_fill; + guint16 result; + guint msg_end = tvb_reported_length_remaining(message_tvb, 0); + guint16 result_code = 0; + guint16 old_input_bit_order = 0; + guint16 remaining_bits = 0; + guint16 input_bits = 0; + guint8 bit_order = 0; + gboolean outside_huffman_boundaries = TRUE; + gboolean print_in_loop = FALSE; + guint16 instruction_address; + guint8 no_of_state_create = 0; + guint16 state_length_buff[5]; + guint16 state_address_buff[5]; + guint16 state_instruction_buff[5]; + guint16 state_minimum_access_length_buff[5]; + /* guint16 state_state_retention_priority_buff[5]; */ + guint32 used_udvm_cycles = 0; + guint cycles_per_bit; + guint maximum_UDVM_cycles; + guint8 *sha1buff; + unsigned char sha1_digest_buf[STATE_BUFFER_SIZE]; + gcry_md_hd_t sha1_handle; + proto_item *addr_item = NULL, *ti = NULL; + + + /* UDVM operand variables */ + guint16 length; + guint16 at_address; + guint16 destination; + guint16 addr; + guint16 value; + guint16 p_id_start; + guint16 p_id_length; + guint16 state_begin; + guint16 state_length; + guint16 state_address; + guint16 state_instruction; + guint16 operand_1; + guint16 operand_2; + guint16 value_1; + guint16 value_2; + guint16 at_address_1; + guint16 at_address_2; + guint16 at_address_3; + guint16 j; + guint16 bits_n; + guint16 lower_bound_n; + guint16 upper_bound_n; + guint16 uncompressed_n; + guint16 position; + guint16 ref_destination; /* could I have used $destination ? */ + guint16 multy_offset; + guint16 output_start; + guint16 output_length; + guint16 minimum_access_length; + guint16 state_retention_priority; + guint16 requested_feedback_location; + guint16 returned_parameters_location; + guint16 start_value; + + /* Set print parameters */ + gboolean print_level_1 = FALSE; + gboolean print_level_2 = FALSE; + gboolean print_level_3 = FALSE; + gint show_instr_detail_level = 0; + + switch ( print_flags ) { + case 0: + break; + + case 1: + print_level_1 = TRUE; + show_instr_detail_level = 1; + break; + case 2: + print_level_1 = TRUE; + print_level_2 = TRUE; + show_instr_detail_level = 1; + break; + case 3: + print_level_1 = TRUE; + print_level_2 = TRUE; + print_level_3 = TRUE; + show_instr_detail_level = 2; + break; + default: + print_level_1 = TRUE; + show_instr_detail_level = 1; + break; + } + + /* Set initial UDVM data + * The first 32 bytes of UDVM memory are then initialized to special + * values as illustrated in Figure 5. + * + * 0 7 8 15 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | UDVM_memory_size | 0 - 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | cycles_per_bit | 2 - 3 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SigComp_version | 4 - 5 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | partial_state_ID_length | 6 - 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | state_length | 8 - 9 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * : reserved : 10 - 31 + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Figure 5: Initializing Useful Values in UDVM memory + */ + /* UDVM_memory_size */ + buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF; + buff[1] = UDVM_MEMORY_SIZE & 0x00FF; + /* cycles_per_bit */ + buff[2] = 0; + buff[3] = 16; + /* SigComp_version */ + buff[4] = 0; + buff[5] = 1; + /* partial_state_ID_length */ + buff[6] = (byte_code_id_len >> 8) & 0x00FF; + buff[7] = byte_code_id_len & 0x00FF; + /* state_length */ + buff[8] = (byte_code_state_len >> 8) & 0x00FF; + buff[9] = byte_code_state_len & 0x00FF; + + code_length = tvb_reported_length_remaining(bytecode_tvb, 0); + + cycles_per_bit = buff[2] << 8; + cycles_per_bit = cycles_per_bit | buff[3]; + /* + * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit + */ + maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit; + + proto_tree_add_uint(udvm_tree, hf_sigcomp_message_length, bytecode_tvb, offset, 1, msg_end); + proto_tree_add_uint(udvm_tree, hf_sigcomp_byte_code_length, bytecode_tvb, offset, 1, code_length); + proto_tree_add_uint(udvm_tree, hf_sigcomp_max_udvm_cycles, bytecode_tvb, offset, 1, maximum_UDVM_cycles); + + /* Load bytecode into UDVM starting at "udvm_mem_dest" */ + i = udvm_mem_dest; + if ( print_level_3 ) + proto_tree_add_uint(udvm_tree, hf_sigcomp_load_bytecode_into_udvm_start, bytecode_tvb, offset, 1, i); + while ( code_length > offset && i < UDVM_MEMORY_SIZE ) { + buff[i] = tvb_get_guint8(bytecode_tvb, offset); + if ( print_level_3 ) + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_instruction_code, bytecode_tvb, offset, 1, buff[i], + " Addr: %u Instruction code(0x%02x) ", i, buff[i]); + + i++; + offset++; + + } + /* Start executing code */ + current_address = udvm_start_ip; + input_address = 0; + + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_udvm_execution_stated, bytecode_tvb, offset, 1, current_address, + "UDVM EXECUTION STARTED at Address: %u Message size %u", current_address, msg_end); + + /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */ + out_buff = (guint8 *)wmem_alloc(pinfo->pool, UDVM_MEMORY_SIZE); + + /* Reset offset so proto_tree_add_xxx items below accurately reflect the bytes they represent */ + offset = 0; + +execute_next_instruction: + + if ( used_udvm_cycles > maximum_UDVM_cycles ) { + result_code = 15; + goto decompression_failure; + } + used_udvm_cycles++; + current_instruction = buff[current_address & 0xffff]; + + if (show_instr_detail_level == 2 ) { + addr_item = proto_tree_add_uint_format(udvm_tree, hf_sigcomp_current_instruction, bytecode_tvb, offset, 1, current_instruction, + "Addr: %u ## %s(%d)", current_address, + val_to_str_ext_const(current_instruction, &udvm_instruction_code_vals_ext, "INVALID INSTRUCTION"), + current_instruction); + } + offset++; + + switch ( current_instruction ) { + case SIGCOMP_INSTR_DECOMPRESSION_FAILURE: + if ( result_code == 0 ) + result_code = 9; + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_decompression_failure, NULL, 0, 0, + current_address, "Addr: %u ## DECOMPRESSION-FAILURE(0)", + current_address); + proto_tree_add_uint(udvm_tree, hf_sigcomp_wireshark_udvm_diagnostic, NULL, 0, 0, result_code); + if ( output_address > 0 ) { + /* At least something got decompressed, show it */ + decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address); + /* Add the tvbuff to the list of tvbuffs to which the tvbuff we + * were handed refers, so it'll get cleaned up when that tvbuff + * is cleaned up. + */ + add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)"); + proto_tree_add_expert(udvm_tree, pinfo, &ei_sigcomp_sigcomp_message_decompression_failure, decomp_tvb, 0, -1); + return decomp_tvb; + } + return NULL; + break; + + case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## AND (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 & operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## OR (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 | operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " ($operand_1)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## NOT (operand_1=%u)", + current_address, operand_1); + } + /* execute the instruction */ + result = operand_1 ^ 0xffff; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " ($operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + ti = proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + if (operand_2 > 15) { + expert_add_info(pinfo, ti, &ei_sigcomp_invalid_shift_value); + break; + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 << operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + + break; + case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + ti = proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + if (operand_2 > 15) { + expert_add_info(pinfo, ti, &ei_sigcomp_invalid_shift_value); + break; + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 >> operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## ADD (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 + operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + + case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* execute the instruction */ + result = operand_1 - operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* + * execute the instruction + * MULTIPLY (m, n) := m * n (modulo 2^16) + */ + if ( operand_2 == 0) { + result_code = 4; + goto decompression_failure; + } + result = operand_1 * operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* + * execute the instruction + * DIVIDE (m, n) := floor(m / n) + * Decompression failure occurs if a DIVIDE or REMAINDER instruction + * encounters an operand_2 that is zero. + */ + if ( operand_2 == 0) { + result_code = 4; + goto decompression_failure; + } + result = operand_1 / operand_2; + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (operand_1, operand_2)"); + } + start_offset = offset; + /* $operand_1*/ + operand_address = current_address + 1; + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &operand_1, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_1, bytecode_tvb, offset, (next_operand_address-operand_address), operand_1, + "Addr: %u operand_1 %u", operand_address, operand_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %operand_2*/ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_operand_2, bytecode_tvb, offset, (next_operand_address-operand_address), operand_2, + "Addr: %u operand_2 %u", operand_address, operand_2); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)", + current_address, operand_1, operand_2); + } + /* + * execute the instruction + * REMAINDER (m, n) := m - n * floor(m / n) + * Decompression failure occurs if a DIVIDE or REMAINDER instruction + * encounters an operand_2 that is zero. + */ + if ( operand_2 == 0) { + result_code = 4; + goto decompression_failure; + } + result = operand_1 - operand_2 * (operand_1 / operand_2); + lsb = result & 0xff; + msb = result >> 8; + buff[result_dest] = msb; + buff[(result_dest+1) & 0xffff] = lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading result %u at %u", result, result_dest); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */ + /* + * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (start, n, k))"); + } + proto_tree_add_expert(udvm_tree, pinfo, &ei_sigcomp_execution_of_this_instruction_is_not_implemented, bytecode_tvb, 0, -1); + /* + * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n) + */ + break; + + case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (start, n, k))"); + } + proto_tree_add_expert(udvm_tree, pinfo, &ei_sigcomp_execution_of_this_instruction_is_not_implemented, bytecode_tvb, 0, -1); + /* + * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n) + */ + break; + case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (position, length, destination)"); + } + operand_address = current_address + 1; + /* %position */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_position, bytecode_tvb, offset, (next_operand_address-operand_address), position, + "Addr: %u position %u", operand_address, position); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* $destination */ + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &ref_destination, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_ref_dest, bytecode_tvb, offset, (next_operand_address-operand_address), ref_destination, + "Addr: %u $destination %u", operand_address, ref_destination); + } + offset += (next_operand_address-operand_address); + used_udvm_cycles = used_udvm_cycles + length; + + n = 0; + k = position; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, 0, -1, + NULL, "byte_copy_right = %u", byte_copy_right); + } + + if (gcry_md_open(&sha1_handle, GCRY_MD_SHA1, 0)) { + goto decompression_failure; + } + + while (n<length) { + guint16 handle_now = length; + + if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ) { + handle_now = byte_copy_right - position; + } + + if ((k + handle_now >= UDVM_MEMORY_SIZE) || + (n + handle_now >= UDVM_MEMORY_SIZE)) { + gcry_md_close(sha1_handle); + goto decompression_failure; + } + gcry_md_write(sha1_handle, &buff[k], handle_now); + + k = ( k + handle_now ) & 0xffff; + n = ( n + handle_now ) & 0xffff; + + if ( k >= byte_copy_right ) { + k = byte_copy_left; + } + } + + memcpy(sha1_digest_buf, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH); + gcry_md_close(sha1_handle); + + k = ref_destination; + + for ( n=0; n< STATE_BUFFER_SIZE; n++ ) { + + buff[k] = sha1_digest_buf[n]; + + k = ( k + 1 ) & 0xffff; + n++; + + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + } + + if (print_level_2 ) { + proto_tree_add_bytes_with_length(udvm_tree, hf_sigcomp_calculated_sha_1, message_tvb, 0, -1, + sha1_digest_buf, STATE_BUFFER_SIZE); + } + + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (%%address, %%value)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %address */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_address, bytecode_tvb, offset, (next_operand_address-operand_address), addr, + "Addr: %u Address %u", operand_address, addr); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2) + { + proto_tree_add_uint_format(udvm_tree, hf_udvm_value, bytecode_tvb, offset, (next_operand_address-operand_address), value, + "Addr: %u Value %u", operand_address, value); + } + offset += (next_operand_address-operand_address); + lsb = value & 0xff; + msb = value >> 8; + + buff[addr] = msb; + buff[(addr + 1) & 0xffff] = lsb; + + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## LOAD (%%address=%u, %%value=%u)", + current_address, addr, value); + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + " Loading bytes at %u Value %u 0x%x", addr, value, value); + } + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */ + /* RFC 3320: + * The MULTILOAD instruction sets a contiguous block of 2-byte words in + * the UDVM memory to specified values. + * Hmm what if the value to load only takes one byte ? Chose to always load two bytes. + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (%%address, #n, value_0, ..., value_n-1)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %address */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_address, bytecode_tvb, offset, (next_operand_address-operand_address), addr, + "Addr: %u Address %u", operand_address, addr); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* #n */ + next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_literal_num, bytecode_tvb, offset, (next_operand_address-operand_address), n, + "Addr: %u n %u", operand_address, n); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)", + current_address, addr, n, n-1); + } + operand_address = next_operand_address; + used_udvm_cycles = used_udvm_cycles + n; + while ( n > 0) { + n = n - 1; + /* %value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value); + if (next_operand_address < 0) + goto decompression_failure; + lsb = value & 0xff; + msb = value >> 8; + + if (addr >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + + buff[addr] = msb; + buff[(addr + 1) & 0xffff] = lsb; + /* debug + */ + length = next_operand_address - operand_address; + + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, bytecode_tvb, 0, -1, + "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x", operand_address, value, addr, value, value); + } + addr = addr + 2; + operand_address = next_operand_address; + } + current_address = next_operand_address; + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */ + if (show_instr_detail_level == 2) { + proto_item_append_text(addr_item, " (value)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_value, bytecode_tvb, offset, (next_operand_address-operand_address), value, + "Addr: %u Value %u", operand_address, value); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## PUSH (value=%u)", + current_address, value); + } + current_address = next_operand_address; + + /* Push the value address onto the stack */ + stack_location = (buff[70] << 8) | buff[71]; + stack_fill = (buff[stack_location] << 8) + | buff[(stack_location+1) & 0xFFFF]; + addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF; + + if (addr >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + + buff[addr] = (value >> 8) & 0x00FF; + buff[(addr+1) & 0xFFFF] = value & 0x00FF; + + if (stack_location >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + + stack_fill = (stack_fill + 1) & 0xFFFF; + buff[stack_location] = (stack_fill >> 8) & 0x00FF; + buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF; + + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_POP: /* 17 POP (%address) */ + if (show_instr_detail_level == 2) { + proto_item_append_text(addr_item, " (value)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_address, bytecode_tvb, offset, (next_operand_address-operand_address), destination, + "Addr: %u Value %u", operand_address, destination); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## POP (address=%u)", + current_address, destination); + } + current_address = next_operand_address; + + /* Pop value from the top of the stack */ + stack_location = (buff[70] << 8) | buff[71]; + stack_fill = (buff[stack_location] << 8) + | buff[(stack_location+1) & 0xFFFF]; + if (stack_fill == 0) + { + result_code = 16; + goto decompression_failure; + } + + if (stack_location >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + + stack_fill = (stack_fill - 1) & 0xFFFF; + buff[stack_location] = (stack_fill >> 8) & 0x00FF; + buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF; + + addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF; + + if (addr >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + + value = (buff[addr] << 8) + | buff[(addr+1) & 0xFFFF]; + + /* ... and store the popped value. */ + if (destination >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[destination] = (value >> 8) & 0x00FF; + buff[(destination+1) & 0xFFFF] = value & 0x00FF; + + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (position, length, destination)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %position */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_position, bytecode_tvb, offset, (next_operand_address-operand_address), position, + "Addr: %u position %u", operand_address, position); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %destination */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_ref_dest, bytecode_tvb, offset, (next_operand_address-operand_address), destination, + "Addr: %u Destination %u", operand_address, destination); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## COPY (position=%u, length=%u, destination=%u)", + current_address, position, length, destination); + } + current_address = next_operand_address; + /* + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + n = 0; + k = destination; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, + NULL, " byte_copy_right = %u", byte_copy_right); + } + + while ( n < length ) { + buff[k] = buff[position]; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_copying_value, message_tvb, input_address, 1, + buff[position], " Copying value: %u (0x%x) to Addr: %u", + buff[position], buff[position], k); + } + position = ( position + 1 ) & 0xffff; + k = ( k + 1 ) & 0xffff; + n++; + + /* + * Check for circular buffer wrapping after the positions are + * incremented. If either started at BCR then they should continue + * to increment beyond BCR. + */ + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + if ( position == byte_copy_right ) { + position = byte_copy_left; + } + } + used_udvm_cycles = used_udvm_cycles + length; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (position, length, $destination)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %position */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_position, bytecode_tvb, offset, (next_operand_address-operand_address), position, + "Addr: %u position %u", operand_address, position); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + + /* $destination */ + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &ref_destination, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_ref_dest, bytecode_tvb, offset, (next_operand_address-operand_address), ref_destination, + "Addr: %u destination %u", operand_address, ref_destination); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)", + current_address, position, length, ref_destination); + } + current_address = next_operand_address; + + + /* + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + n = 0; + k = ref_destination; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, + NULL, " byte_copy_right = %u", byte_copy_right); + } + while ( n < length ) { + + buff[k] = buff[position]; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_copying_value, message_tvb, input_address, 1, + buff[position], " Copying value: %u (0x%x) to Addr: %u", + buff[position], buff[position], k); + } + position = ( position + 1 ) & 0xffff; + k = ( k + 1 ) & 0xffff; + n++; + + /* + * Check for circular buffer wrapping after the positions are + * incremented. It is important that k cannot be left set + * to BCR. Also, if either started at BCR then they should continue + * to increment beyond BCR. + */ + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + if ( position == byte_copy_right ) { + position = byte_copy_left; + } + } + buff[result_dest] = k >> 8; + buff[(result_dest + 1) & 0xffff] = k & 0x00ff; + + used_udvm_cycles = used_udvm_cycles + length; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (offset, length, $destination)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %offset */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_offset, bytecode_tvb, offset, (next_operand_address-operand_address), multy_offset, + "Addr: %u offset %u", operand_address, multy_offset); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + + /* $destination */ + next_operand_address = dissect_udvm_reference_operand_memory(buff, operand_address, &ref_destination, &result_dest); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_ref_dest, bytecode_tvb, offset, (next_operand_address-operand_address), ref_destination, + "Addr: %u $destination %u", operand_address, ref_destination); + } + offset += (next_operand_address-operand_address); + + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)", + current_address, multy_offset, length, result_dest); + } + current_address = next_operand_address; + + /* Execute the instruction: + * To derive the value of the position operand, starting at the memory + * address specified by destination, the UDVM counts backwards a total + * of offset memory addresses. + * + * If the memory address specified in byte_copy_left is reached, the + * next memory address is taken to be (byte_copy_right - 1) modulo 2^16. + */ + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + + /* + * In order to work out the position, simple arithmetic is tricky + * to apply because there some nasty corner cases. A simple loop + * is inefficient but the logic is simple. + * + * FUTURE: This could be optimised. + */ + for (position = ref_destination, i = 0; i < multy_offset; i++) + { + if ( position == byte_copy_left ) + { + position = (byte_copy_right - 1) & 0xffff; + } + else + { + position = (position - 1) & 0xffff; + } + } + + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, + NULL, " byte_copy_left = %u byte_copy_right = %u position= %u", + byte_copy_left, byte_copy_right, position); + } + /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL + * instruction, taking the value of the position operand to be the last + * memory address reached in the above step. + */ + + /* + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + n = 0; + k = ref_destination; + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, NULL, + " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right); + } + while ( n < length ) { + buff[k] = buff[position]; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_copying_value, message_tvb, input_address, 1, + buff[position], " Copying value: %5u (0x%x) from Addr: %u to Addr: %u", + buff[position], buff[position],(position), k); + } + n++; + k = ( k + 1 ) & 0xffff; + position = ( position + 1 ) & 0xffff; + + /* + * Check for circular buffer wrapping after the positions are + * incremented. It is important that k cannot be left set + * to BCR. Also, if either started at BCR then they should continue + * to increment beyond BCR. + */ + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + if ( position == byte_copy_right ) { + position = byte_copy_left; + } + } + buff[result_dest] = k >> 8; + buff[result_dest + 1] = k & 0x00ff; + used_udvm_cycles = used_udvm_cycles + length; + goto execute_next_instruction; + + break; + case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (address, length, start_value, offset)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* %address */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_address, bytecode_tvb, offset, (next_operand_address-operand_address), addr, + "Addr: %u Address %u", operand_address, addr); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length, */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %start_value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_start_value, bytecode_tvb, offset, (next_operand_address-operand_address), start_value, + "Addr: %u start_value %u", operand_address, start_value); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %offset */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_offset, bytecode_tvb, offset, (next_operand_address-operand_address), multy_offset, + "Addr: %u offset %u", operand_address, multy_offset); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)", + current_address, addr, length, start_value, multy_offset); + } + current_address = next_operand_address; + /* execute the instruction + * The sequence of values used by the MEMSET instruction is specified by + * the following formula: + * + * Seq[n] := (start_value + n * offset) modulo 256 + */ + n = 0; + k = addr; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, NULL, + " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right); + } + while ( n < length ) { + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + buff[k] = (start_value + ( n * multy_offset)) & 0xff; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_storing_value, message_tvb, input_address, 1, + buff[k], " Storing value: %u (0x%x) at Addr: %u", + buff[k], buff[k], k); + } + k = ( k + 1 ) & 0xffff; + n++; + }/* end while */ + used_udvm_cycles = used_udvm_cycles + length; + goto execute_next_instruction; + break; + + + case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (@address)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* @address */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## JUMP (@address=%u)", + current_address, at_address); + } + current_address = at_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_COMPARE: /* 23 */ + /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (value_1, value_2, @address_1, @address_2, @address_3)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* %value_1 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_value, bytecode_tvb, offset, (next_operand_address-operand_address), value_1, + "Addr: %u Value %u", operand_address, value_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %value_2 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_value, bytecode_tvb, offset, (next_operand_address-operand_address), value_2, + "Addr: %u Value %u", operand_address, value_2); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address_1 */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1); + if (next_operand_address < 0) + goto decompression_failure; + at_address_1 = ( current_address + at_address_1) & 0xffff; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address_1, + "Addr: %u @Address %u", operand_address, at_address_1); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + + /* @address_2 */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2); + if (next_operand_address < 0) + goto decompression_failure; + at_address_2 = ( current_address + at_address_2) & 0xffff; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address_2, + "Addr: %u @Address %u", operand_address, at_address_2); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address_3 */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3); + if (next_operand_address < 0) + goto decompression_failure; + at_address_3 = ( current_address + at_address_3) & 0xffff; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address_3, + "Addr: %u @Address %u", operand_address, at_address_3); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)", + current_address, value_1, value_2, at_address_1, at_address_2, at_address_3); + } + /* execute the instruction + * If value_1 < value_2 then the UDVM continues instruction execution at + * the memory address specified by address 1. If value_1 = value_2 then + * it jumps to the address specified by address_2. If value_1 > value_2 + * then it jumps to the address specified by address_3. + */ + if ( value_1 < value_2 ) + current_address = at_address_1; + if ( value_1 == value_2 ) + current_address = at_address_2; + if ( value_1 > value_2 ) + current_address = at_address_3; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/ + if (show_instr_detail_level == 2) { + proto_item_append_text(addr_item, " (@address) (PUSH addr )"); + } + start_offset = offset; + operand_address = current_address + 1; + /* @address */ + next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## CALL (@address=%u)", + current_address, at_address); + } + current_address = next_operand_address; + + /* Push the current address onto the stack */ + stack_location = (buff[70] << 8) | buff[71]; + stack_fill = (buff[stack_location] << 8) + | buff[(stack_location+1) & 0xFFFF]; + addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF; + if (addr >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[addr] = (current_address >> 8) & 0x00FF; + buff[(addr+1) & 0xFFFF] = current_address & 0x00FF; + + stack_fill = (stack_fill + 1) & 0xFFFF; + if (stack_location >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[stack_location] = (stack_fill >> 8) & 0x00FF; + buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF; + + /* ... and jump to the destination address */ + current_address = at_address; + + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_RETURN: /* 25 POP and return */ + /* Pop value from the top of the stack */ + stack_location = (buff[70] << 8) | buff[71]; + stack_fill = (buff[stack_location] << 8) + | buff[(stack_location+1) & 0xFFFF]; + if (stack_fill == 0) + { + result_code = 16; + goto decompression_failure; + } + + stack_fill = (stack_fill - 1) & 0xFFFF; + if (stack_location >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[stack_location] = (stack_fill >> 8) & 0x00FF; + buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF; + + addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF; + at_address = (buff[addr] << 8) + | buff[(addr+1) & 0xFFFF]; + + /* ... and set the PC to the popped value */ + current_address = at_address; + + goto execute_next_instruction; + + break; + + case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */ + /* + * When a SWITCH instruction is encountered the UDVM reads the value of + * j. It then continues instruction execution at the address specified + * by address j. + * + * Decompression failure occurs if j specifies a value of n or more, or + * if the address lies beyond the overall UDVM memory size. + */ + instruction_address = current_address; + if (show_instr_detail_level == 2) { + proto_item_append_text(addr_item, " (#n, j, @address_0, @address_1, ... , @address_n-1))"); + } + operand_address = current_address + 1; + /* #n + * Number of addresses in the instruction + */ + next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_literal_num, bytecode_tvb, offset, (next_operand_address-operand_address), n, + "Addr: %u n %u", operand_address, n); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %j */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_j, bytecode_tvb, offset, (next_operand_address-operand_address), j, + "Addr: %u j %u", operand_address, j); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + m = 0; + while ( m < n ) { + /* @address_n-1 */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1); + if (next_operand_address < 0) + goto decompression_failure; + at_address_1 = ( instruction_address + at_address_1) & 0xffff; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address_1, + "Addr: %u @Address %u", operand_address, at_address_1); + } + offset += (next_operand_address-operand_address); + if ( j == m ) { + current_address = at_address_1; + } + operand_address = next_operand_address; + m++; + } + /* Check decompression failure */ + if ( ( j == n ) || ( j > n )) { + result_code = 5; + goto decompression_failure; + } + if ( current_address > UDVM_MEMORY_SIZE ) { + result_code = 6; + goto decompression_failure; + } + used_udvm_cycles = used_udvm_cycles + n; + + goto execute_next_instruction; + + break; + case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */ + if (show_instr_detail_level == 2) { + proto_item_append_text(addr_item, " (value, position, length, @address)"); + } + start_offset = offset; + + operand_address = current_address + 1; + + /* %value */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_value, bytecode_tvb, offset, (next_operand_address-operand_address), value, + "Addr: %u Value %u", operand_address, value); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %position */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_position, bytecode_tvb, offset, (next_operand_address-operand_address), position, + "Addr: %u position %u", operand_address, position); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address); + if (next_operand_address < 0) + goto decompression_failure; + at_address = ( current_address + at_address) & 0xffff; + if (print_level_2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + used_udvm_cycles = used_udvm_cycles + length; + + n = 0; + k = position; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + result = 0; + + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, 0, -1, + NULL, "byte_copy_right = %u", byte_copy_right); + } + + while (n<length) { + + guint16 handle_now = length - n; + + if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ) { + handle_now = byte_copy_right - k; + } + + if (k + handle_now >= UDVM_MEMORY_SIZE) + goto decompression_failure; + result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff)); + + k = ( k + handle_now ) & 0xffff; + n = ( n + handle_now ) & 0xffff; + + if ( k >= byte_copy_right ) { + k = byte_copy_left; + } + } + + result = result ^ 0xffff; + + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Calculated CRC %u", result); + } + if (result != value) { + current_address = at_address; + } + else { + current_address = next_operand_address; + } + goto execute_next_instruction; + break; + + + case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " length, destination, @address)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u Length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %destination */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_destination, bytecode_tvb, offset, (next_operand_address-operand_address), destination, + "Addr: %u Destination %u", operand_address, destination); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address); + if (next_operand_address < 0) + goto decompression_failure; + at_address = ( current_address + at_address) & 0xffff; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)", + current_address, length, destination, at_address); + } + /* execute the instruction TODO insert checks + * RFC 3320 : + * + * 0 7 8 15 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | byte_copy_left | 64 - 65 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | byte_copy_right | 66 - 67 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | input_bit_order | 68 - 69 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | stack_location | 70 - 71 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Figure 7: Memory addresses of the UDVM registers + * : + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + n = 0; + k = destination; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_1 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, + NULL, " byte_copy_right = %u", byte_copy_right); + } + /* clear out remaining bits if any */ + remaining_bits = 0; + input_bits=0; + /* operand_address used as dummy */ + while ( n < length ) { + if (input_address > ( msg_end - 1)) { + current_address = at_address; + result_code = 14; + goto execute_next_instruction; + } + + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + octet = tvb_get_guint8(message_tvb, input_address); + buff[k] = octet; + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_loading_value, message_tvb, input_address, 1, + octet, " Loading value: %u (0x%x) at Addr: %u", octet, octet, k); + } + input_address++; + /* + * If the instruction requests data that lies beyond the end of the + * SigComp message, no data is returned. Instead the UDVM moves program + * execution to the address specified by the address operand. + */ + + + k = ( k + 1 ) & 0xffff; + n++; + } + used_udvm_cycles = used_udvm_cycles + length; + current_address = next_operand_address; + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */ + /* + * The length operand indicates the requested number of bits. + * Decompression failure occurs if this operand does not lie between 0 + * and 16 inclusive. + * + * The destination operand specifies the memory address to which the + * compressed data should be copied. Note that the requested bits are + * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as + * explained in Section 8.2. + * + * If the instruction requests data that lies beyond the end of the + * SigComp message, no data is returned. Instead the UDVM moves program + * execution to the address specified by the address operand. + */ + + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (length, destination, @address)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* %length */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_length, bytecode_tvb, offset, (next_operand_address-operand_address), length, + "Addr: %u length %u", operand_address, length); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %destination */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_destination, bytecode_tvb, offset, (next_operand_address-operand_address), destination, + "Addr: %u Destination %u", operand_address, destination); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)", + current_address, length, destination, at_address); + } + current_address = next_operand_address; + + /* + * Execute actual instr. + * The input_bit_order register contains the following three flags: + * + * 0 7 8 15 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | reserved |F|H|P| 68 - 69 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + input_bit_order = buff[68] << 8; + input_bit_order = input_bit_order | buff[69]; + /* + * If the instruction requests data that lies beyond the end of the + * SigComp message, no data is returned. Instead the UDVM moves program + * execution to the address specified by the address operand. + */ + + if ( length > 16 ) { + result_code = 7; + goto decompression_failure; + } + if ( input_bit_order > 7 ) { + result_code = 8; + goto decompression_failure; + } + + /* + * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use + */ + bit_order = ( input_bit_order & 0x0004 ) >> 2; + value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order, + buff, &old_input_bit_order, &remaining_bits, + &input_bits, &input_address, length, &result_code, msg_end, print_level_1); + if ( result_code == 11 ) { + current_address = at_address; + goto execute_next_instruction; + } + msb = value >> 8; + lsb = value & 0x00ff; + if (destination >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[destination] = msb; + buff[(destination + 1) & 0xffff]=lsb; + if (print_level_1 ) { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_loading_result, message_tvb, input_address, 1, + " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits); + } + + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */ + /* + * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1, + * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n, + * %upper_bound_n, %uncompressed_n) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (destination, @address, #n, bits_1, lower_bound_1,upper_bound_1, uncompressed_1, ... , bits_n, lower_bound_n,upper_bound_n, uncompressed_n)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* %destination */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_destination, bytecode_tvb, offset, (next_operand_address-operand_address), destination, + "Addr: %u Destination %u", operand_address, destination); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* @address */ + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_at_address, bytecode_tvb, offset, (next_operand_address-operand_address), at_address, + "Addr: %u @Address %u", operand_address, at_address); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* #n */ + next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_literal_num, bytecode_tvb, offset, (next_operand_address-operand_address), n, + "Addr: %u n %u", operand_address, n); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## INPUT-HUFFMAN (destination=%u, @address=%u, #n=%u, bits_1, lower_1,upper_1, unc_1, ... , bits_%d, lower_%d,upper_%d, unc_%d)", + current_address, destination, at_address, n, n, n, n, n); + } + + used_udvm_cycles = used_udvm_cycles + n; + + /* + * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and + * program execution resumes at the following instruction. + * Decompression failure occurs if (bits_1 + ... + bits_n) > 16. + * + * In all other cases, the behavior of the INPUT-HUFFMAN instruction is + * defined below: + * + * 1. Set j := 1 and set H := 0. + * + * 2. Request bits_j compressed bits. Interpret the returned bits as an + * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2. + * + * 3. Set H := H * 2^bits_j + k. + * + * 4. If data is requested that lies beyond the end of the SigComp + * message, terminate the INPUT-HUFFMAN instruction and move program + * execution to the memory address specified by the address operand. + * + * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1. + * Then go back to Step 2, unless j > n in which case decompression + * failure occurs. + * + * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the + * memory address specified by the destination operand. + * + */ + /* + * The input_bit_order register contains the following three flags: + * + * 0 7 8 15 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | reserved |F|H|P| 68 - 69 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use + */ + input_bit_order = buff[68] << 8; + input_bit_order = input_bit_order | buff[69]; + bit_order = ( input_bit_order & 0x0002 ) >> 1; + + j = 1; + H = 0; + m = n; + outside_huffman_boundaries = TRUE; + print_in_loop = print_level_3; + while ( m > 0 ) { + /* %bits_n */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n); + if (next_operand_address < 0) + goto decompression_failure; + if (print_in_loop ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_bits, bytecode_tvb, offset, (next_operand_address-operand_address), bits_n, + "Addr: %u bits_n %u", operand_address, bits_n); + } + if (bits_n > 31) + break; + + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* %lower_bound_n */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n); + if (next_operand_address < 0) + goto decompression_failure; + if (print_in_loop ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_lower_bound, bytecode_tvb, offset, (next_operand_address-operand_address), lower_bound_n, + "Addr: %u lower_bound_n %u", operand_address, lower_bound_n); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %upper_bound_n */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n); + if (next_operand_address < 0) + goto decompression_failure; + if (print_in_loop ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_upper_bound, bytecode_tvb, offset, (next_operand_address-operand_address), upper_bound_n, + "Addr: %u upper_bound_n %u", operand_address, upper_bound_n); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* %uncompressed_n */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n); + if (next_operand_address < 0) + goto decompression_failure; + if (print_in_loop ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_uncompressed, bytecode_tvb, offset, (next_operand_address-operand_address), uncompressed_n, + "Addr: %u uncompressed_n %u", operand_address, uncompressed_n); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* execute instruction */ + if ( outside_huffman_boundaries ) { + /* + * 2. Request bits_j compressed bits. Interpret the returned bits as an + * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2. + */ + k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order, + buff, &old_input_bit_order, &remaining_bits, + &input_bits, &input_address, bits_n, &result_code, msg_end, print_level_1); + if ( result_code == 11 ) { + /* + * 4. If data is requested that lies beyond the end of the SigComp + * message, terminate the INPUT-HUFFMAN instruction and move program + * execution to the memory address specified by the address operand. + */ + current_address = at_address; + goto execute_next_instruction; + } + + /* + * 3. Set H := H * 2^bits_j + k. + * [In practice is a shift+OR operation.] + */ + oldH = H; + H = (H << bits_n) | k; + if (print_level_3 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_set_hu, bytecode_tvb, 0, -1, NULL, + " Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)", + H ,oldH, 1<<bits_n,k); + } + + /* + * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1. + * Then go back to Step 2, unless j > n in which case decompression + * failure occurs. + */ + if ((H < lower_bound_n) || (H > upper_bound_n)) { + outside_huffman_boundaries = TRUE; + } else { + outside_huffman_boundaries = FALSE; + print_in_loop = FALSE; + /* + * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the + * memory address specified by the destination operand. + */ + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_set_hu, bytecode_tvb, 0, -1, NULL, + " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)", + (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n); + } + H = H + uncompressed_n - lower_bound_n; + msb = H >> 8; + lsb = H & 0x00ff; + if (destination >= UDVM_MEMORY_SIZE - 1) + goto decompression_failure; + buff[destination] = msb; + buff[(destination + 1) & 0xffff]=lsb; + if (print_level_1 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_loading_h, message_tvb, input_address, 1, H, + " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u", + H, H, destination,( n - m + 1 ), remaining_bits); + } + + } + + + } + m = m - 1; + } + if ( outside_huffman_boundaries ) { + result_code = 10; + goto decompression_failure; + } + + current_address = next_operand_address; + goto execute_next_instruction; + break; + + case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */ + /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length, + * %state_begin, %state_length, %state_address, %state_instruction) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* + * %partial_identifier_start + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_partial_identifier_start, bytecode_tvb, offset, (next_operand_address-operand_address), p_id_start, + "Addr: %u partial_identifier_start %u", operand_address, p_id_start); + } + offset += (next_operand_address-operand_address); + + /* + * %partial_identifier_length + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_partial_identifier_length, bytecode_tvb, offset, (next_operand_address-operand_address), p_id_length, + "Addr: %u partial_identifier_length %u", operand_address, p_id_length); + } + offset += (next_operand_address-operand_address); + /* + * %state_begin + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_state_begin, bytecode_tvb, offset, (next_operand_address-operand_address), state_begin, + "Addr: %u state_begin %u", operand_address, state_begin); + } + offset += (next_operand_address-operand_address); + /* + * %state_length + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_length, bytecode_tvb, offset, (next_operand_address-operand_address), state_length, + "Addr: %u state_length %u", operand_address, state_length); + } + offset += (next_operand_address-operand_address); + /* + * %state_address + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_address, bytecode_tvb, offset, (next_operand_address-operand_address), state_address, + "Addr: %u state_address %u", operand_address, state_address); + } + offset += (next_operand_address-operand_address); + /* + * %state_instruction + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_instr, bytecode_tvb, offset, (next_operand_address-operand_address), state_instruction, + "Addr: %u state_instruction %u", operand_address, state_instruction); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start=%u, partial_identifier_length=%u,state_begin=%u, state_length=%u, state_address=%u, state_instruction=%u)", + current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction); + } + current_address = next_operand_address; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_2 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, message_tvb, input_address, 1, NULL, + " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left); + } + + result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length, + &state_address, &state_instruction, hf_id); + if ( result_code != 0 ) { + goto decompression_failure; + } + used_udvm_cycles = used_udvm_cycles + state_length; + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_STATE_CREATE: /* 32 */ + /* + * STATE-CREATE (%state_length, %state_address, %state_instruction, + * %minimum_access_length, %state_retention_priority) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* + * %state_length + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_length, bytecode_tvb, offset, (next_operand_address-operand_address), state_length, + "Addr: %u state_length %u", operand_address, state_length); + } + offset += (next_operand_address-operand_address); + /* + * %state_address + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_address, bytecode_tvb, offset, (next_operand_address-operand_address), state_address, + "Addr: %u state_address %u", operand_address, state_address); + } + offset += (next_operand_address-operand_address); + /* + * %state_instruction + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_instr, bytecode_tvb, offset, (next_operand_address-operand_address), state_instruction, + "Addr: %u state_instruction %u", operand_address, state_instruction); + } + offset += (next_operand_address-operand_address); + /* + * %minimum_access_length + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_min_acc_len, bytecode_tvb, offset, (next_operand_address-operand_address), minimum_access_length, + "Addr: %u minimum_access_length %u", operand_address, minimum_access_length); + } + offset += (next_operand_address-operand_address); + /* + * %state_retention_priority + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_ret_pri, bytecode_tvb, offset, (next_operand_address-operand_address), state_retention_priority, + "Addr: %u state_retention_priority %u", operand_address, state_retention_priority); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)", + current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority); + } + current_address = next_operand_address; + /* Execute the instruction + * TODO Implement the instruction + * RFC3320: + * Note that the new state item cannot be created until a valid + * compartment identifier has been returned by the application. + * Consequently, when a STATE-CREATE instruction is encountered the UDVM + * simply buffers the five supplied operands until the END-MESSAGE + * instruction is reached. The steps taken at this point are described + * in Section 9.4.9. + * + * Decompression failure MUST occur if more than four state creation + * requests are made before the END-MESSAGE instruction is encountered. + * Decompression failure also occurs if the minimum_access_length does + * not lie between 6 and 20 inclusive, or if the + * state_retention_priority is 65535. + */ + no_of_state_create++; + if ( no_of_state_create > 4 ) { + result_code = 12; + goto decompression_failure; + } + if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )) { + result_code = 1; + goto decompression_failure; + } + if ( state_retention_priority == 65535 ) { + result_code = 13; + goto decompression_failure; + } + state_length_buff[no_of_state_create] = state_length; + state_address_buff[no_of_state_create] = state_address; + state_instruction_buff[no_of_state_create] = state_instruction; + state_minimum_access_length_buff[no_of_state_create] = minimum_access_length; + /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */ + used_udvm_cycles = used_udvm_cycles + state_length; + /* Debug */ + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + n = 0; + k = state_address; + while ( n < state_length ) { + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + string[0]= buff[k]; + string[1]= '\0'; + if (print_level_3 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_state_value, bytecode_tvb, 0, 0, buff[k], + " Addr: %5u State value: %u (0x%x) ASCII(%s)", + k,buff[k],buff[k],format_text(wmem_packet_scope(), string, 1)); + } + k = ( k + 1 ) & 0xffff; + n++; + } + /* End debug */ + + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_STATE_FREE: /* 33 */ + /* + * STATE-FREE (%partial_identifier_start, %partial_identifier_length) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (partial_identifier_start, partial_identifier_length)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* + * %partial_identifier_start + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_partial_identifier_start, bytecode_tvb, offset, (next_operand_address-operand_address), p_id_start, + "Addr: %u partial_identifier_start %u", operand_address, p_id_start); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + + /* + * %partial_identifier_length + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_partial_identifier_length, bytecode_tvb, offset, (next_operand_address-operand_address), p_id_length, + "Addr: %u partial_identifier_length %u", operand_address, p_id_length); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)", + current_address, p_id_start, p_id_length); + } + current_address = next_operand_address; + + /* Execute the instruction: + * TODO implement it + */ + udvm_state_free(buff,p_id_start,p_id_length); + + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (output_start, output_length)"); + } + start_offset = offset; + operand_address = current_address + 1; + /* + * %output_start + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_output_start, bytecode_tvb, offset, (next_operand_address-operand_address), output_start, + "Addr: %u output_start %u", operand_address, output_start); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* + * %output_length + */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_output_length, bytecode_tvb, offset, (next_operand_address-operand_address), output_length, + "Addr: %u output_length %u", operand_address, output_length); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)", + current_address, output_start, output_length); + } + current_address = next_operand_address; + + /* + * Execute instruction + * 8.4. Byte copying + * : + * The string of bytes is copied in ascending order of memory address, + * respecting the bounds set by byte_copy_left and byte_copy_right. + * More precisely, if a byte is copied from/to Address m then the next + * byte is copied from/to Address n where n is calculated as follows: + * + * Set k := m + 1 (modulo 2^16) + * If k = byte_copy_right then set n := byte_copy_left, else set n := k + * + */ + + n = 0; + k = output_start; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + if (print_level_3 ) { + proto_tree_add_bytes_format(udvm_tree, hf_sigcomp_byte_copy, bytecode_tvb, 0, -1, + NULL, " byte_copy_right = %u", byte_copy_right); + } + while ( n < output_length ) { + + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + out_buff[output_address] = buff[k]; + string[0]= buff[k]; + string[1]= '\0'; + if (print_level_3 ) { + proto_tree_add_uint_format(udvm_tree, hf_sigcomp_output_value, bytecode_tvb, 0, -1, buff[k], + " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u", + buff[k],buff[k],format_text(wmem_packet_scope(), string,1), k,output_address); + } + k = ( k + 1 ) & 0xffff; + output_address ++; + n++; + } + used_udvm_cycles = used_udvm_cycles + output_length; + goto execute_next_instruction; + break; + case SIGCOMP_INSTR_END_MESSAGE: /* 35 */ + /* + * END-MESSAGE (%requested_feedback_location, + * %returned_parameters_location, %state_length, %state_address, + * %state_instruction, %minimum_access_length, + * %state_retention_priority) + */ + if (show_instr_detail_level == 2 ) { + proto_item_append_text(addr_item, " (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)"); + } + start_offset = offset; + operand_address = current_address + 1; + + /* %requested_feedback_location */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_req_feedback_loc, bytecode_tvb, offset, (next_operand_address-operand_address), requested_feedback_location, + "Addr: %u requested_feedback_location %u", + operand_address, requested_feedback_location); + } + offset += (next_operand_address-operand_address); + operand_address = next_operand_address; + /* returned_parameters_location */ + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_ret_param_loc, bytecode_tvb, offset, (next_operand_address-operand_address), returned_parameters_location, + "Addr: %u returned_parameters_location %u", operand_address, returned_parameters_location); + } + offset += (next_operand_address-operand_address); + /* + * %state_length + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_length, bytecode_tvb, offset, (next_operand_address-operand_address), state_length, + "Addr: %u state_length %u", operand_address, state_length); + } + offset += (next_operand_address-operand_address); + /* + * %state_address + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_address, bytecode_tvb, offset, (next_operand_address-operand_address), state_address, + "Addr: %u state_address %u", operand_address, state_address); + } + offset += (next_operand_address-operand_address); + /* + * %state_instruction + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_instr, bytecode_tvb, offset, (next_operand_address-operand_address), state_instruction, + "Addr: %u state_instruction %u", operand_address, state_instruction); + } + offset += (next_operand_address-operand_address); + + /* + * %minimum_access_length + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_min_acc_len, bytecode_tvb, offset, (next_operand_address-operand_address), minimum_access_length, + "Addr: %u minimum_access_length %u", operand_address, minimum_access_length); + } + offset += (next_operand_address-operand_address); + + /* + * %state_retention_priority + */ + operand_address = next_operand_address; + next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority); + if (next_operand_address < 0) + goto decompression_failure; + if (show_instr_detail_level == 2 ) { + proto_tree_add_uint_format(udvm_tree, hf_udvm_state_ret_pri, bytecode_tvb, offset, (next_operand_address-operand_address), state_retention_priority, + "Addr: %u state_retention_priority %u", operand_address, state_retention_priority); + } + offset += (next_operand_address-operand_address); + if (show_instr_detail_level == 1) + { + proto_tree_add_none_format(udvm_tree, hf_sigcomp_decompress_instruction, bytecode_tvb, start_offset, offset-start_offset, + "Addr: %u ## END-MESSAGE (requested_feedback_location=%u, returned_parameters_location=%u, state_length=%u, state_address=%u, state_instruction=%u, minimum_access_length=%u, state_retention_priority=%u)", + current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority); + } + /* TODO: This isn't currently totally correct as END_INSTRUCTION might not create state */ + no_of_state_create++; + if ( no_of_state_create > 4 ) { + result_code = 12; + goto decompression_failure; + } + state_length_buff[no_of_state_create] = state_length; + state_address_buff[no_of_state_create] = state_address; + state_instruction_buff[no_of_state_create] = state_instruction; + /* Not used ? */ + state_minimum_access_length_buff[no_of_state_create] = minimum_access_length; + /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */ + + /* Execute the instruction + */ + proto_tree_add_uint(udvm_tree, hf_sigcomp_num_state_create, bytecode_tvb, 0, 0, no_of_state_create); + if ( no_of_state_create != 0 ) { + memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE); + n = 1; + byte_copy_right = buff[66] << 8; + byte_copy_right = byte_copy_right | buff[67]; + byte_copy_left = buff[64] << 8; + byte_copy_left = byte_copy_left | buff[65]; + while ( n < no_of_state_create + 1 ) { + sha1buff = (guint8 *)g_malloc(state_length_buff[n]+8); + sha1buff[0] = state_length_buff[n] >> 8; + sha1buff[1] = state_length_buff[n] & 0xff; + sha1buff[2] = state_address_buff[n] >> 8; + sha1buff[3] = state_address_buff[n] & 0xff; + sha1buff[4] = state_instruction_buff[n] >> 8; + sha1buff[5] = state_instruction_buff[n] & 0xff; + sha1buff[6] = state_minimum_access_length_buff[n] >> 8; + sha1buff[7] = state_minimum_access_length_buff[n] & 0xff; + if (print_level_3 ) { + proto_tree_add_bytes_with_length(udvm_tree, hf_sigcomp_sha1buff, bytecode_tvb, 0, -1, sha1buff, 8); + } + k = state_address_buff[n]; + for ( x=0; x < state_length_buff[n]; x++) + { + if ( k == byte_copy_right ) { + k = byte_copy_left; + } + sha1buff[8+x] = buff[k]; + k = ( k + 1 ) & 0xffff; + } + + gcry_md_hash_buffer(GCRY_MD_SHA1, sha1_digest_buf, (guint8 *) sha1buff, state_length_buff[n] + 8); + if (print_level_3 ) { + proto_tree_add_bytes_with_length(udvm_tree, hf_sigcomp_sha1_digest, bytecode_tvb, 0, -1, sha1_digest_buf, STATE_BUFFER_SIZE); + } +/* begin partial state-id change cco@iptel.org */ +#if 0 + udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]); +#endif + udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN); +/* end partial state-id change cco@iptel.org */ + proto_tree_add_item(udvm_tree, hf_sigcomp_creating_state, bytecode_tvb, 0, -1, ENC_NA); + proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(wmem_packet_scope(), sha1_digest_buf, STATE_MIN_ACCESS_LEN)); + + n++; + + } + } + + + + /* At least something got decompressed, show it */ + decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address); + + add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message"); + proto_tree_add_item(udvm_tree, hf_sigcomp_sigcomp_message_decompressed, decomp_tvb, 0, -1, ENC_NA); + + used_udvm_cycles += state_length; + proto_tree_add_uint(udvm_tree, hf_sigcomp_max_udvm_cycles, bytecode_tvb, 0, 0, maximum_UDVM_cycles); + proto_tree_add_uint(udvm_tree, hf_sigcomp_used_udvm_cycles, bytecode_tvb, 0, 0, used_udvm_cycles); + return decomp_tvb; + break; + + default: + expert_add_info_format(pinfo, addr_item, &ei_sigcomp_invalid_instruction, + "Addr %u Invalid instruction: %u (0x%x)", current_address,current_instruction,current_instruction); + break; + } + return NULL; +decompression_failure: + + proto_tree_add_expert_format(udvm_tree, pinfo, &ei_sigcomp_decompression_failure, bytecode_tvb, 0, -1, + "DECOMPRESSION FAILURE: %s", val_to_str(result_code, result_code_vals,"Unknown (%u)")); + return NULL; + +} + +/********************************************************************************************** + * + * SIGCOMP DISSECTOR + * + **********************************************************************************************/ + + +/* Sigcomp over TCP record marking used + * RFC 3320 + * 4.2.2. Record Marking + * + * For a stream-based transport, the dispatcher delimits messages by + * parsing the compressed data stream for instances of 0xFF and taking + * the following actions: + * Occurs in data stream: Action: + * + * 0xFF 00 one 0xFF byte in the data stream + * 0xFF 01 same, but the next byte is quoted (could + * be another 0xFF) + * : : + * 0xFF 7F same, but the next 127 bytes are quoted + * 0xFF 80 to 0xFF FE (reserved for future standardization) + * 0xFF FF end of SigComp message + * : + * In UDVM version 0x01, any occurrence of the combinations 0xFF80 to + * 0xFFFE that are not protected by quoting causes decompression + * failure; the decompressor SHOULD close the stream-based transport in + * this case. + */ + +/* + * TODO: Reassembly, handle more than one message in a tcp segment. + */ + +static int +dissect_sigcomp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data _U_) +{ + proto_item *ti; + proto_tree *sigcomp_tree; + tvbuff_t *unescaped_tvb; + + guint8 *buff; + int offset = 0; + int length; + guint8 octet; + guint16 data; + int i; + int n; + gboolean end_off_message; + + top_tree = tree; + + /* Is this SIGCOMP ? */ + data = tvb_get_ntohs(tvb, offset); + if (data == 0xffff) { + /* delimiter */ + offset = offset + 2; + octet = tvb_get_guint8(tvb,offset); + } else { + octet = tvb_get_guint8(tvb,offset); + } + if ((octet & 0xf8) != 0xf8) + return offset; + + /* Search for delimiter 0xffff in the remain tvb buffer */ + length = tvb_reported_length_remaining(tvb, offset); + for (i=0; i<(length-1); ++i) { + /* Loop end criteria is (length-1) because we take 2 bytes each loop */ + data = tvb_get_ntohs(tvb, offset+i); + if (0xffff == data) break; + } + if (i >= (length-1)) { + /* SIGCOMP may be subdissector of SIP, so we use + * pinfo->saved_can_desegment to determine whether do desegment + * as well as pinfo->can_desegment */ + if (pinfo->can_desegment || pinfo->saved_can_desegment) { + /* Delimiter oxffff was not found, not a complete SIGCOMP PDU */ + pinfo->desegment_offset = offset; + pinfo->desegment_len=DESEGMENT_ONE_MORE_SEGMENT; + return -1; + } + } + + /* Make entries in Protocol column and Info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIGCOMP"); + + col_clear(pinfo->cinfo, COL_INFO); + + length = tvb_reported_length(tvb); + +try_again: + /* create display subtree for the protocol */ + ti = proto_tree_add_item(tree, proto_sigcomp, tvb, 0, -1, ENC_NA); + sigcomp_tree = proto_item_add_subtree(ti, ett_sigcomp); + i=0; + end_off_message = FALSE; + buff = (guint8 *)wmem_alloc(pinfo->pool, length-offset); + if (udvm_print_detail_level>2) + proto_tree_add_item(sigcomp_tree, hf_sigcomp_starting_to_remove_escape_digits, tvb, offset, -1, ENC_NA); + while ((offset < length) && (end_off_message == FALSE)) { + octet = tvb_get_guint8(tvb,offset); + if ( octet == 0xff ) { + if ( offset +1 >= length ) { + /* if the tvb is short don't check for the second escape digit */ + offset++; + continue; + } + if (udvm_print_detail_level>2) + proto_tree_add_none_format(sigcomp_tree, hf_sigcomp_escape_digit_found, tvb, offset, 2, + " Escape digit found (0xFF)"); + octet = tvb_get_guint8(tvb, offset+1); + if ( octet == 0) { + buff[i] = 0xff; + offset = offset +2; + i++; + continue; + } + if ((octet > 0x7f) && (octet < 0xff )) { + if (udvm_print_detail_level>2) + proto_tree_add_none_format(sigcomp_tree, hf_sigcomp_illegal_escape_code, tvb, offset, 2, + " Illegal escape code"); + offset += tvb_captured_length_remaining(tvb,offset); + return offset; + } + if ( octet == 0xff) { + if (udvm_print_detail_level>2) + proto_tree_add_none_format(sigcomp_tree, hf_sigcomp_end_of_sigcomp_message_indication_found, tvb, offset, 2, + " End of SigComp message indication found (0xFFFF)"); + end_off_message = TRUE; + offset = offset+2; + continue; + } + buff[i] = 0xff; + if (udvm_print_detail_level>2) + proto_tree_add_uint_format(sigcomp_tree, hf_sigcomp_addr_value, tvb, offset, 1, buff[i], + " Addr: %u tvb value(0x%0x) ", i, buff[i]); + i++; + offset = offset+2; + if (udvm_print_detail_level>2) + proto_tree_add_bytes_format(sigcomp_tree, hf_sigcomp_copying_bytes_literally, tvb, offset, octet, + NULL, " Copying %u bytes literally",octet); + if ( offset+octet >= length) + /* if the tvb is short don't copy further than the end */ + octet = length - offset; + for ( n=0; n < octet; n++ ) { + buff[i] = tvb_get_guint8(tvb, offset); + if (udvm_print_detail_level>2) + proto_tree_add_uint_format(sigcomp_tree, hf_sigcomp_addr_value, tvb, offset, 1, buff[i], + " Addr: %u tvb value(0x%0x) ", i, buff[i]); + i++; + offset++; + } + continue; + } + buff[i] = octet; + if (udvm_print_detail_level>2) + proto_tree_add_uint_format(sigcomp_tree, hf_sigcomp_addr_value, tvb, offset, 1, buff[i], + " Addr: %u tvb value(0x%0x) ", i, buff[i]); + + i++; + offset++; + } + unescaped_tvb = tvb_new_child_real_data(tvb, buff,i,i); + + add_new_data_source(pinfo, unescaped_tvb, "Unescaped Data handed to the SigComp dissector"); + + proto_tree_add_item(sigcomp_tree, hf_sigcomp_data_for_sigcomp_dissector, unescaped_tvb, 0, -1, ENC_NA); + if (end_off_message == TRUE) { + dissect_sigcomp_common(unescaped_tvb, pinfo, sigcomp_tree); + } else { + proto_tree_add_expert(sigcomp_tree, pinfo, &ei_sigcomp_tcp_fragment, unescaped_tvb, 0, -1); + } + if ( offset < length) { + goto try_again; + } + + return offset; +} +/* Code to actually dissect the packets */ +static int +dissect_sigcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + proto_item *ti; + proto_tree *sigcomp_tree; + gint offset = 0; + gint8 octet; + + /* If we got called from SIP this might be over TCP */ + if ( pinfo->ptype == PT_TCP ) + return dissect_sigcomp_tcp(tvb, pinfo, tree, NULL); + + /* Is this a SigComp message or not ? */ + octet = tvb_get_guint8(tvb, offset); + if ((octet & 0xf8) != 0xf8) + return 0; + + /* Make entries in Protocol column and Info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIGCOMP"); + + col_clear(pinfo->cinfo, COL_INFO); + + top_tree = tree; + + /* create display subtree for the protocol */ + ti = proto_tree_add_item(tree, proto_sigcomp, tvb, 0, -1, ENC_NA); + sigcomp_tree = proto_item_add_subtree(ti, ett_sigcomp); + + return dissect_sigcomp_common(tvb, pinfo, sigcomp_tree); +} +/* Code to actually dissect the packets */ +static int +dissect_sigcomp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sigcomp_tree) +{ + +/* Set up structures needed to add the protocol subtree and manage it */ + tvbuff_t *udvm_tvb, *msg_tvb, *udvm2_tvb; + tvbuff_t *decomp_tvb = NULL; + proto_item *udvm_bytecode_item, *udvm_exe_item; + proto_tree *sigcomp_udvm_tree, *sigcomp_udvm_exe_tree; + gint offset = 0; + gint bytecode_offset; + guint16 partial_state_len; + guint octet; + guint8 returned_feedback_field[128]; + guint8 partial_state[12]; + guint tbit; + guint16 len = 0; + guint16 bytecode_len = 0; + guint destination; + gint msg_len = 0; + guint8 *buff; + guint16 p_id_start; + guint8 i; + guint16 state_begin; + guint16 state_length; + guint16 state_address; + guint16 state_instruction; + guint16 result_code; + gchar *partial_state_str; + guint8 nack_version; + + + +/* add an item to the subtree, see section 1.6 for more information */ + octet = tvb_get_guint8(tvb, offset); + +/* A SigComp message takes one of two forms depending on whether it + * accesses a state item at the receiving endpoint. The two variants of + * a SigComp message are given in Figure 3. (The T-bit controls the + * format of the returned feedback item and is defined in Section 7.1.) + * + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | 1 1 1 1 1 | T | len | | 1 1 1 1 1 | T | 0 | + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | | | | + * : returned feedback item : : returned feedback item : + * | | | | + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | | | code_len | + * : partial state identifier : +---+---+---+---+---+---+---+---+ + * + * | | | code_len | destination | + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | | | | + * : remaining SigComp message : : uploaded UDVM bytecode : + * | | | | + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | | + * : remaining SigComp message : + * | | + * +---+---+---+---+---+---+---+---+ + * + * RFC 4077: + * The format of the NACK message and the use of the fields within it + * are shown in Figure 1. + * + * 0 1 2 3 4 5 6 7 + * +---+---+---+---+---+---+---+---+ + * | 1 1 1 1 1 | T | 0 | + * +---+---+---+---+---+---+---+---+ + * | | + * : returned feedback item : + * | | + * +---+---+---+---+---+---+---+---+ + * | code_len = 0 | + * +---+---+---+---+---+---+---+---+ + * | code_len = 0 | version = 1 | + * +---+---+---+---+---+---+---+---+ + * | Reason Code | + * +---+---+---+---+---+---+---+---+ + * | OPCODE of failed instruction | + * +---+---+---+---+---+---+---+---+ + * | PC of failed instruction | + * | | + * +---+---+---+---+---+---+---+---+ + * | | + * : SHA-1 Hash of failed message : + * | | + * +---+---+---+---+---+---+---+---+ + * | | + * : Error Details : + * | | + * +---+---+---+---+---+---+---+---+ + * Figure 1: SigComp NACK Message Format + */ + + proto_tree_add_item(sigcomp_tree,hf_sigcomp_t_bit, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sigcomp_tree,hf_sigcomp_len, tvb, offset, 1, ENC_BIG_ENDIAN); + tbit = ( octet & 0x04)>>2; + partial_state_len = octet & 0x03; + offset ++; + if ( partial_state_len != 0 ) { + /* + * The len field encodes the number of transmitted bytes as follows: + * + * Encoding: Length of partial state identifier + * + * 01 6 bytes + * 10 9 bytes + * 11 12 bytes + * + */ + partial_state_len = partial_state_len * 3 + 3; + + /* + * Message format 1 + */ + col_set_str(pinfo->cinfo, COL_INFO, "Msg format 1"); + + if ( tbit == 1 ) { + /* + * Returned feedback item exists + */ + len = 1; + octet = tvb_get_guint8(tvb, offset); + /* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | 0 | returned_feedback_field | | 1 | returned_feedback_length | + * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ + * | | + * : returned_feedback_field : + * | | + * +---+---+---+---+---+---+---+---+ + * Figure 4: Format of returned feedback item + */ + + if ( (octet & 0x80) != 0 ) { + len = octet & 0x7f; + proto_tree_add_item(sigcomp_tree,hf_sigcomp_returned_feedback_item_len, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset ++; + tvb_memcpy(tvb,returned_feedback_field,offset, len); + } else { + returned_feedback_field[0] = tvb_get_guint8(tvb, offset) & 0x7f; + } + proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item, + tvb, offset, len, returned_feedback_field); + offset = offset + len; + } + tvb_memcpy(tvb, partial_state, offset, partial_state_len); + partial_state_str = bytes_to_str(wmem_packet_scope(), partial_state, partial_state_len); + proto_tree_add_string(sigcomp_tree,hf_sigcomp_partial_state, + tvb, offset, partial_state_len, partial_state_str); + offset = offset + partial_state_len; + msg_len = tvb_reported_length_remaining(tvb, offset); + + if (msg_len>0) { + proto_item *ti; + ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_remaining_message_bytes, tvb, + offset, 0, msg_len); + proto_item_set_generated(ti); + } + + if ( decompress ) { + msg_tvb = tvb_new_subset_length(tvb, offset, msg_len); + /* + * buff = Where "state" will be stored + * p_id_start = Partial state identifier start pos in the buffer(buff) + * partial_state_len = Partial state identifier length + * state_begin = Where to start to read state from + * state_length = Length of state + * state_address = Address where to store the state in the buffer(buff) + * state_instruction = + * TRUE = Indicates that state_* is in the stored state + */ + /* + * Note: The allocated buffer must be zeroed or some strange effects might occur. + */ + buff = (guint8 *)wmem_alloc0(pinfo->pool, UDVM_MEMORY_SIZE); + + + p_id_start = 0; + state_begin = 0; + /* These values will be loaded from the buffered state in sigcomp_state_hdlr + */ + state_length = 0; + state_address = 0; + state_instruction =0; + + i = 0; + while ( i < partial_state_len ) { + buff[i] = partial_state[i]; + i++; + } + +/* begin partial state-id change cco@iptel.org */ +#if 0 + result_code = udvm_state_access(tvb, sigcomp_tree, buff, p_id_start, partial_state_len, state_begin, &state_length, + &state_address, &state_instruction, hf_sigcomp_partial_state); +#endif + result_code = udvm_state_access(tvb, sigcomp_tree, buff, p_id_start, STATE_MIN_ACCESS_LEN, state_begin, &state_length, + &state_address, &state_instruction, hf_sigcomp_partial_state); + +/* end partial state-id change cco@iptel.org */ + if ( result_code != 0 ) { + proto_tree_add_expert_format(sigcomp_tree, pinfo, &ei_sigcomp_failed_to_access_state_wireshark_udvm_diagnostic, tvb, 0, -1, + "Failed to Access state Wireshark UDVM diagnostic: %s", val_to_str(result_code, result_code_vals,"Unknown (%u)")); + return tvb_captured_length(tvb); + } + + udvm_tvb = tvb_new_child_real_data(tvb, buff,state_length+state_address,state_length+state_address); + add_new_data_source(pinfo, udvm_tvb, "State/ExecutionTrace"); + + udvm2_tvb = tvb_new_subset_length(udvm_tvb, state_address, state_length); + udvm_exe_item = proto_tree_add_item(sigcomp_tree, hf_udvm_execution_trace, + udvm2_tvb, 0, state_length, + ENC_NA); + sigcomp_udvm_exe_tree = proto_item_add_subtree( udvm_exe_item, ett_sigcomp_udvm_exe); + + decomp_tvb = decompress_sigcomp_message(udvm2_tvb, msg_tvb, pinfo, + sigcomp_udvm_exe_tree, state_address, + udvm_print_detail_level, hf_sigcomp_partial_state, + offset, state_length, partial_state_len, state_instruction); + + + if ( decomp_tvb ) { + proto_item *ti; + guint32 compression_ratio = + (guint32)(((float)tvb_reported_length(decomp_tvb) / (float)tvb_reported_length(tvb)) * 100); + + /* Show compression ratio achieved */ + ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_compression_ratio, decomp_tvb, + 0, 0, compression_ratio); + proto_item_set_generated(ti); + + if ( display_raw_txt ) + tvb_raw_text_add(decomp_tvb, top_tree); + + col_append_str(pinfo->cinfo, COL_PROTOCOL, "/"); + col_set_fence(pinfo->cinfo,COL_PROTOCOL); + call_dissector(sip_handle, decomp_tvb, pinfo, top_tree); + } + }/* if decompress */ + + } + else{ + /* + * Message format 2 + */ + col_set_str(pinfo->cinfo, COL_INFO, "Msg format 2"); + if ( tbit == 1 ) { + /* + * Returned feedback item exists + */ + len = 1; + octet = tvb_get_guint8(tvb, offset); + if ( (octet & 0x80) != 0 ) { + len = octet & 0x7f; + proto_tree_add_item(sigcomp_tree,hf_sigcomp_returned_feedback_item_len, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset ++; + } + tvb_memcpy(tvb,returned_feedback_field,offset, len); + proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item, + tvb, offset, len, returned_feedback_field); + offset = offset + len; + } + len = tvb_get_ntohs(tvb, offset) >> 4; + nack_version = tvb_get_guint8(tvb, offset+1) & 0x0f; + if ((len == 0) && (nack_version == 1)) { + /* NACK MESSAGE */ + proto_item *reason_ti; + guint8 opcode; + offset++; + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_ver, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + octet = tvb_get_guint8(tvb, offset); + reason_ti = proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_failed_op_code, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + /* Add expert item for NACK */ + expert_add_info_format(pinfo, reason_ti, &ei_sigcomp_nack_failed_op_code, + "SigComp NACK (reason=%s, opcode=%s)", + val_to_str_ext_const(octet, &sigcomp_nack_reason_code_vals_ext, "Unknown"), + val_to_str_ext_const(opcode, &udvm_instruction_code_vals_ext, "Unknown")); + + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_pc, tvb, offset, 2, ENC_BIG_ENDIAN); + offset = offset +2; + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_sha1, tvb, offset, HASH_SHA1_LENGTH, ENC_NA); + offset = offset + HASH_SHA1_LENGTH; + + /* Add NACK info to info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " NACK reason=%s, opcode=%s", + val_to_str_ext_const(octet, &sigcomp_nack_reason_code_vals_ext, "Unknown"), + val_to_str_ext_const(opcode, &udvm_instruction_code_vals_ext, "Unknown")); + + switch ( octet) { + case SIGCOMP_NACK_STATE_NOT_FOUND: + case SIGCOMP_NACK_ID_NOT_UNIQUE: + case SIGCOMP_NACK_STATE_TOO_SHORT: + /* State ID (6 - 20 bytes) */ + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_state_id, tvb, offset, -1, ENC_NA); + break; + case SIGCOMP_NACK_CYCLES_EXHAUSTED: + /* Cycles Per Bit (1 byte) */ + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_cycles_per_bit, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SIGCOMP_NACK_BYTECODES_TOO_LARGE: + /* Memory size (2 bytes) */ + proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_memory_size, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + default: + break; + } + } else { + octet = tvb_get_guint8(tvb, (offset + 1)); + destination = (octet & 0x0f); + if ( destination != 0 ) + destination = 64 + ( destination * 64 ); + proto_tree_add_item(sigcomp_tree,hf_sigcomp_code_len, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sigcomp_tree,hf_sigcomp_destination, tvb, (offset+ 1), 1, ENC_BIG_ENDIAN); + offset = offset +2; + + bytecode_len = len; + bytecode_offset = offset; + udvm_bytecode_item = proto_tree_add_item(sigcomp_tree, hf_sigcomp_udvm_bytecode, tvb, + bytecode_offset, bytecode_len, ENC_NA); + proto_item_append_text(udvm_bytecode_item, + " %u (0x%x) bytes", bytecode_len, bytecode_len); + sigcomp_udvm_tree = proto_item_add_subtree( udvm_bytecode_item, ett_sigcomp_udvm); + + udvm_tvb = tvb_new_subset_length(tvb, offset, len); + if ( dissect_udvm_code ) + dissect_udvm_bytecode(udvm_tvb, pinfo, sigcomp_udvm_tree, destination); + + offset = offset + len; + msg_len = tvb_reported_length_remaining(tvb, offset); + if (msg_len>0) { + proto_item *ti = proto_tree_add_item(sigcomp_tree, hf_sigcomp_remaining_sigcomp_message, tvb, offset, -1, ENC_NA); + proto_item_set_generated(ti); + } + if ( decompress ) { + + msg_tvb = tvb_new_subset_length(tvb, offset, msg_len); + + udvm_exe_item = proto_tree_add_item(sigcomp_tree, hf_udvm_execution_trace, + tvb, bytecode_offset, bytecode_len, + ENC_NA); + sigcomp_udvm_exe_tree = proto_item_add_subtree( udvm_exe_item, ett_sigcomp_udvm_exe); + decomp_tvb = decompress_sigcomp_message(udvm_tvb, msg_tvb, pinfo, + sigcomp_udvm_exe_tree, destination, + udvm_print_detail_level, hf_sigcomp_partial_state, + offset, 0, 0, destination); + if ( decomp_tvb ) { + proto_item *ti; + guint32 compression_ratio = + (guint32)(((float)tvb_reported_length(decomp_tvb) / (float)tvb_reported_length(tvb)) * 100); + + /* Show compression ratio achieved */ + ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_compression_ratio, decomp_tvb, + 0, 0, compression_ratio); + proto_item_set_generated(ti); + + if ( display_raw_txt ) + tvb_raw_text_add(decomp_tvb, top_tree); + + col_append_str(pinfo->cinfo, COL_PROTOCOL, "/"); + col_set_fence(pinfo->cinfo,COL_PROTOCOL); + call_dissector(sip_handle, decomp_tvb, pinfo, top_tree); + } + } /* if decompress */ + }/*if len==0 */ + + } + return tvb_captured_length(tvb); +} + +static void +dissect_udvm_bytecode(tvbuff_t *udvm_tvb, packet_info* pinfo, proto_tree *sigcomp_udvm_tree,guint start_address) +{ + guint instruction; + gint offset = 0; + gint start_offset = 0; + gint len; + gint n; + guint instruction_no = 0; + guint16 value = 0; + proto_item *item, *item2; + guint UDVM_address = start_address; + gboolean is_memory_address; + guint16 msg_length = tvb_reported_length_remaining(udvm_tvb, offset); + + + while (msg_length > offset) { + instruction = tvb_get_guint8(udvm_tvb, offset); + instruction_no ++; + UDVM_address = start_address + offset; + + item = proto_tree_add_uint_format(sigcomp_udvm_tree, hf_sigcomp_udvm_instruction, udvm_tvb, offset, 1, + instruction_no, "######### UDVM instruction %u at UDVM-address %u (0x%x) #########", + instruction_no,UDVM_address,UDVM_address); + proto_item_set_generated(item); + proto_tree_add_item(sigcomp_udvm_tree, hf_sigcomp_udvm_instr, udvm_tvb, offset, 1, ENC_BIG_ENDIAN); + offset ++; + switch ( instruction ) { + + case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */ + /* $operand_1*/ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, + udvm_tvb, start_offset, len, value); + /* %operand_2*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, + udvm_tvb, start_offset, len, value); + } + break; + case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */ + /* while programming stop while loop */ + offset = offset + tvb_reported_length_remaining(udvm_tvb, offset); + break; + + case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */ + offset = offset + tvb_reported_length_remaining(udvm_tvb, offset); + break; + case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */ + /* %position */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, + udvm_tvb, start_offset, len, value); + + /* %length, */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* $destination */ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */ + /* %address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, + udvm_tvb, start_offset, len, value); + /* %value */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */ + /* %address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, + udvm_tvb, start_offset, len, value); + /* #n */ + offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, + udvm_tvb, start_offset, len, value); + n = value; + while ( n > 0) { + n = n -1; + /* %value */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + } + break; + + case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */ + /* %value */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_POP: /* 17 POP (%address) */ + /* %address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */ + /* %position */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, + udvm_tvb, start_offset, len, value); + + /* %length, */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* $destination */ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */ + /* %position */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, + udvm_tvb, start_offset, len, value); + + /* %length, */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* $destination */ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */ + /* %offset */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_offset, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset, + udvm_tvb, start_offset, len, value); + } + + /* %length, */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* $destination */ + offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */ + + /* %address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, + udvm_tvb, start_offset, len, value); + + /* %length, */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* %start_value */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_start_value, + udvm_tvb, start_offset, len, value); + + /* %offset */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset, + udvm_tvb, start_offset, len, value); + break; + + + case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */ + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_COMPARE: /* 23 */ + /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3) + */ + /* %value_1 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + + /* %value_2 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + + /* @address_1 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + + /* @address_2 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + + /* @address_3 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + + case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/ + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_RETURN: /* 25 POP and return */ + + break; + + case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */ + /* #n */ + offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, + udvm_tvb, start_offset, len, value); + + /* Number of addresses in the instruction */ + n = value; + /* %j */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_j, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_j, + udvm_tvb, start_offset, len, value); + } + + while ( n > 0) { + n = n -1; + /* @address_n-1 */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + } + break; + case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */ + /* %value */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, + udvm_tvb, start_offset, len, value); + } + + /* %position */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, + udvm_tvb, start_offset, len, value); + + /* %length */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + + + case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */ + /* %length */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* %destination */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, + udvm_tvb, start_offset, len, value); + } + + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */ + /* %length */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, + udvm_tvb, start_offset, len, value); + } + + /* %destination */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, + udvm_tvb, start_offset, len, value); + } + + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */ + /* + * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1, + * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n, + * %upper_bound_n, %uncompressed_n) + */ + /* %destination */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, + udvm_tvb, start_offset, len, value); + } + /* @address */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */ + value = ( value + UDVM_address ) & 0xffff; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, + udvm_tvb, start_offset, len, value); + /* #n */ + offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, + udvm_tvb, start_offset, len, value); + n = value; + while ( n > 0) { + n = n -1; + /* %bits_n */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_bits, + udvm_tvb, start_offset, len, value); + /* %lower_bound_n*/ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_lower_bound, + udvm_tvb, start_offset, len, value); + /* %upper_bound_n */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_upper_bound, + udvm_tvb, start_offset, len, value); + /* %uncompressed_n */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_uncompressed, + udvm_tvb, start_offset, len, value); + } + break; + + case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */ + /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length, + * %state_begin, %state_length, %state_address, %state_instruction) + */ + + /* + * %partial_identifier_start + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start, + udvm_tvb, start_offset, len, value); + + /* + * %partial_identifier_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length, + udvm_tvb, start_offset, len, value); + /* + * %state_begin + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_state_begin, + udvm_tvb, start_offset, len, value); + + /* + * %state_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, + udvm_tvb, start_offset, len, value); + } + /* + * %state_address + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, + udvm_tvb, start_offset, len, value); + } + /* + * %state_instruction + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_STATE_CREATE: /* 32 */ + /* + * STATE-CREATE (%state_length, %state_address, %state_instruction, + * %minimum_access_length, %state_retention_priority) + */ + + /* + * %state_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, + udvm_tvb, start_offset, len, value); + } + /* + * %state_address + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, + udvm_tvb, start_offset, len, value); + } + /* + * %state_instruction + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, + udvm_tvb, start_offset, len, value); + /* + * %minimum_access_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len, + udvm_tvb, start_offset, len, value); + /* + * %state_retention_priority + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri, + udvm_tvb, start_offset, len, value); + + break; + case SIGCOMP_INSTR_STATE_FREE: /* 33 */ + /* + * STATE-FREE (%partial_identifier_start, %partial_identifier_length) + */ + /* + * %partial_identifier_start + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start, + udvm_tvb, start_offset, len, value); + + /* + * %partial_identifier_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length, + udvm_tvb, start_offset, len, value); + break; + case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */ + /* + * %output_start + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_output_start, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_start, + udvm_tvb, start_offset, len, value); + } + /* + * %output_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length, + udvm_tvb, start_offset, len, value); + } + break; + case SIGCOMP_INSTR_END_MESSAGE: /* 35 */ + /* + * END-MESSAGE (%requested_feedback_location, + * %returned_parameters_location, %state_length, %state_address, + * %state_instruction, %minimum_access_length, + * %state_retention_priority) + */ + /* %requested_feedback_location */ + if ((msg_length-1) < offset) { + proto_tree_add_expert(sigcomp_udvm_tree, pinfo, &ei_sigcomp_all_remaining_parameters_zero, udvm_tvb, 0, -1); + return; + } + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_req_feedback_loc, + udvm_tvb, start_offset, len, value); + /* returned_parameters_location */ + if ((msg_length-1) < offset) { + proto_tree_add_expert(sigcomp_udvm_tree, pinfo, &ei_sigcomp_all_remaining_parameters_zero, udvm_tvb, offset-1, -1); + return; + } + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ret_param_loc, + udvm_tvb, start_offset, len, value); + /* + * %state_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, + udvm_tvb, start_offset, len, value); + } + /* + * %state_address + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + if ( is_memory_address ) { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, + udvm_tvb, start_offset, len, value); + } else { + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, + udvm_tvb, start_offset, len, value); + } + /* + * %state_instruction + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, + udvm_tvb, start_offset, len, value); + /* + * %minimum_access_length + */ + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len, + udvm_tvb, start_offset, len, value); + /* + * %state_retention_priority + */ + if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ) { + offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address); + len = offset - start_offset; + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri, + udvm_tvb, start_offset, len, value); + } else { + item2 = proto_tree_add_uint_format_value(sigcomp_udvm_tree, hf_udvm_state_ret_pri, udvm_tvb, offset, 1, 0, + "0 (Not in the uploaded code as UDVM buffer initialized to Zero"); + proto_item_set_generated(item2); + } + if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ) { + len = tvb_reported_length_remaining(udvm_tvb, offset); + UDVM_address = start_address + offset; + proto_tree_add_bytes_format(sigcomp_udvm_tree, hf_sigcomp_remaining_bytes, udvm_tvb, offset, len, NULL, + "Remaining %u bytes starting at UDVM addr %u (0x%x)- State information ?",len, UDVM_address, UDVM_address); + } + offset = offset + tvb_reported_length_remaining(udvm_tvb, offset); + break; + + default: + offset = offset + tvb_reported_length_remaining(udvm_tvb, offset); + break; + } + + + } + return; +} + /* The simplest operand type is the literal (#), which encodes a + * constant integer from 0 to 65535 inclusive. A literal operand may + * require between 1 and 3 bytes depending on its value. + * Bytecode: Operand value: Range: + * 0nnnnnnn N 0 - 127 + * 10nnnnnn nnnnnnnn N 0 - 16383 + * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535 + * + * Figure 8: Bytecode for a literal (#) operand + * + */ +static int +dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset, gint *start_offset, guint16 *value) +{ + guint bytecode; + guint16 operand; + guint test_bits; + guint display_bytecode; + + bytecode = tvb_get_guint8(udvm_tvb, offset); + test_bits = bytecode >> 7; + if (test_bits == 1) { + test_bits = bytecode >> 6; + if (test_bits == 2) { + /* + * 10nnnnnn nnnnnnnn N 0 - 16383 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff; + *value = operand; + *start_offset = offset; + offset = offset + 2; + + } else { + /* + * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode, + udvm_tvb, offset, 1, display_bytecode); + offset ++; + operand = tvb_get_ntohs(udvm_tvb, offset); + *value = operand; + *start_offset = offset; + offset = offset + 2; + + } + } else { + /* + * 0nnnnnnn N 0 - 127 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = ( bytecode & 0x7f); + *value = operand; + *start_offset = offset; + offset ++; + } + + return offset; + +} +/* + * The second operand type is the reference ($), which is always used to + * access a 2-byte value located elsewhere in the UDVM memory. The + * bytecode for a reference operand is decoded to be a constant integer + * from 0 to 65535 inclusive, which is interpreted as the memory address + * containing the actual value of the operand. + * Bytecode: Operand value: Range: + * + * 0nnnnnnn memory[2 * N] 0 - 65535 + * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 + * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + * + * Figure 9: Bytecode for a reference ($) operand + */ +static int +dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset, gint *start_offset, guint16 *value) +{ + guint bytecode; + guint16 operand; + guint test_bits; + guint display_bytecode; + + bytecode = tvb_get_guint8(udvm_tvb, offset); + test_bits = bytecode >> 7; + if (test_bits == 1) { + test_bits = bytecode >> 6; + if (test_bits == 2) { + /* + * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff; + *value = (operand * 2); + *start_offset = offset; + offset = offset + 2; + + } else { + /* + * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode, + udvm_tvb, offset, 1, display_bytecode); + offset ++; + operand = tvb_get_ntohs(udvm_tvb, offset); + *value = operand; + *start_offset = offset; + offset = offset + 2; + + } + } else { + /* + * 0nnnnnnn memory[2 * N] 0 - 65535 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = ( bytecode & 0x7f); + *value = (operand * 2); + *start_offset = offset; + offset ++; + } + + return offset; +} + +/* + *The fourth operand type is the address (@). This operand is decoded + * as a multitype operand followed by a further step: the memory address + * of the UDVM instruction containing the address operand is added to + * obtain the correct operand value. So if the operand value from + * Figure 10 is D then the actual operand value of an address is + * calculated as follows: + * + * operand_value = (is_memory_address_of_instruction + D) modulo 2^16 + * TODO calculate correct value for operand in case of ADDR + */ +static int +dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, + gint offset, gboolean is_addr _U_, gint *start_offset, guint16 *value, gboolean *is_memory_address ) +{ + guint bytecode; + guint display_bytecode; + guint16 operand; + guint32 result; + guint test_bits; + /* RFC3320 + * Figure 10: Bytecode for a multitype (%) operand + * Bytecode: Operand value: Range: HEX val + * 00nnnnnn N 0 - 63 0x00 + * 01nnnnnn memory[2 * N] 0 - 65535 0x40 + * 1000011n 2 ^ (N + 6) 64 , 128 0x86 + * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88 + * 111nnnnn N + 65504 65504 - 65535 0xe0 + * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90 + * 101nnnnn nnnnnnnn N 0 - 8191 0xa0 + * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0 + * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80 + * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81 + */ + *is_memory_address = FALSE; + bytecode = tvb_get_guint8(udvm_tvb, offset); + test_bits = ( bytecode & 0xc0 ) >> 6; + switch (test_bits ) { + case 0: + /* + * 00nnnnnn N 0 - 63 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = ( bytecode & 0x3f); + *value = operand; + *start_offset = offset; + offset ++; + break; + case 1: + /* + * 01nnnnnn memory[2 * N] 0 - 65535 + */ + display_bytecode = bytecode & 0xc0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = ( bytecode & 0x3f) * 2; + *is_memory_address = TRUE; + *value = operand; + *start_offset = offset; + offset ++; + break; + case 2: + /* Check tree most significant bits */ + test_bits = ( bytecode & 0xe0 ) >> 5; + if ( test_bits == 5 ) { + /* + * 101nnnnn nnnnnnnn N 0 - 8191 + */ + display_bytecode = bytecode & 0xe0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = tvb_get_ntohs(udvm_tvb, offset) & 0x1fff; + *value = operand; + *start_offset = offset; + offset = offset + 2; + } else { + test_bits = ( bytecode & 0xf0 ) >> 4; + if ( test_bits == 9 ) { + /* + * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 + */ + display_bytecode = bytecode & 0xf0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x0fff) + 61440; + *start_offset = offset; + *value = operand; + offset = offset + 2; + } else { + test_bits = ( bytecode & 0x08 ) >> 3; + if ( test_bits == 1) { + /* + * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 + */ + display_bytecode = bytecode & 0xf8; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + result = pow2(guint32, (bytecode & 0x07) + 8); + operand = result & 0xffff; + *start_offset = offset; + *value = operand; + offset ++; + } else { + test_bits = ( bytecode & 0x0e ) >> 1; + if ( test_bits == 3 ) { + /* + * 1000 011n 2 ^ (N + 6) 64 , 128 + */ + display_bytecode = bytecode & 0xfe; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + result = pow2(guint32, (bytecode & 0x01) + 6); + operand = result & 0xffff; + *start_offset = offset; + *value = operand; + offset ++; + } else { + /* + * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535 + * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 + */ + display_bytecode = bytecode; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + if ( (bytecode & 0x01) == 1 ) + *is_memory_address = TRUE; + offset ++; + operand = tvb_get_ntohs(udvm_tvb, offset); + *value = operand; + *start_offset = offset; + offset = offset +2; + } + + + } + } + } + break; + + case 3: + test_bits = ( bytecode & 0x20 ) >> 5; + if ( test_bits == 1 ) { + /* + * 111nnnnn N + 65504 65504 - 65535 + */ + display_bytecode = bytecode & 0xe0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = ( bytecode & 0x1f) + 65504; + *start_offset = offset; + *value = operand; + offset ++; + } else { + /* + * 110nnnnn nnnnnnnn memory[N] 0 - 65535 + */ + display_bytecode = bytecode & 0xe0; + if ( display_udvm_bytecode ) + proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode, + udvm_tvb, offset, 1, display_bytecode); + operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x1fff); + *is_memory_address = TRUE; + *start_offset = offset; + *value = operand; + offset = offset +2; + } + + default : + break; + } + return offset; +} + +static void +tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree) +{ + proto_tree *raw_tree = NULL; + proto_item *ti = NULL; + int offset, next_offset, linelen; + + if (tree) { + ti = proto_tree_add_item(tree, proto_raw_sigcomp, tvb, 0, -1, ENC_NA); + raw_tree = proto_item_add_subtree(ti, ett_raw_text); + } + + offset = 0; + + while (tvb_offset_exists(tvb, offset)) { + tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); + linelen = next_offset - offset; + proto_tree_add_format_text(raw_tree, tvb, offset, linelen); + offset = next_offset; + } +} + +/* Register the protocol with Wireshark */ + +void +proto_register_sigcomp(void) +{ +/* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_sigcomp_t_bit, + { "T bit", "sigcomp.t.bit", + FT_UINT8, BASE_DEC, NULL, 0x04, + "Sigcomp T bit", HFILL } + }, + { &hf_sigcomp_len, + { "Partial state id length","sigcomp.length", + FT_UINT8, BASE_HEX, VALS(length_encoding_vals), 0x03, + "Sigcomp length", HFILL } + }, + { &hf_sigcomp_returned_feedback_item, + { "Returned_feedback item", "sigcomp.returned.feedback.item", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Returned feedback item", HFILL } + }, + { &hf_sigcomp_partial_state, + { "Partial state identifier", "sigcomp.partial.state.identifier", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_sigcomp_remaining_message_bytes, + { "Remaining SigComp message bytes", "sigcomp.remaining-bytes", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Number of bytes remaining in message", HFILL } + }, + { &hf_sigcomp_compression_ratio, + { "Compression ratio (%)", "sigcomp.compression-ratio", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Compression ratio (decompressed / compressed) %", HFILL } + }, + { &hf_sigcomp_returned_feedback_item_len, + { "Returned feedback item length", "sigcomp.returned.feedback.item.len", + FT_UINT8, BASE_DEC, NULL, 0x7f, + NULL, HFILL } + }, + { &hf_sigcomp_code_len, + { "Code length","sigcomp.code.len", + FT_UINT16, BASE_HEX, NULL, 0xfff0, + NULL, HFILL } + }, + { &hf_sigcomp_destination, + { "Destination","sigcomp.destination", + FT_UINT8, BASE_HEX | BASE_EXT_STRING, &destination_address_encoding_vals_ext, 0xf, + NULL, HFILL } + }, + { &hf_sigcomp_udvm_bytecode, + { "Uploaded UDVM bytecode","sigcomp.udvm.byte-code", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_sigcomp_udvm_instr, + { "UDVM instruction code","sigcomp.udvm.instr", + FT_UINT8, BASE_DEC | BASE_EXT_STRING, &udvm_instruction_code_vals_ext, 0x0, + NULL, HFILL } + }, + { &hf_udvm_execution_trace, + { "UDVM execution trace","sigcomp.udvm.execution-trace", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_udvm_multitype_bytecode, + { "UDVM bytecode", "sigcomp.udvm.multyt.bytecode", + FT_UINT8, BASE_HEX, VALS(display_bytecode_vals), 0x0, + NULL, HFILL } + }, + { &hf_udvm_reference_bytecode, + { "UDVM bytecode", "sigcomp.udvm.ref.bytecode", + FT_UINT8, BASE_HEX, VALS(display_ref_bytecode_vals), 0x0, + NULL, HFILL } + }, + { &hf_udvm_literal_bytecode, + { "UDVM bytecode", "sigcomp.udvm.lit.bytecode", + FT_UINT8, BASE_HEX, VALS(display_lit_bytecode_vals), 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_udvm_operand, + { "UDVM operand", "sigcomp.udvm.operand", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_udvm_length, + { "%Length", "sigcomp.udvm.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Length", HFILL } + }, + { &hf_udvm_addr_length, + { "%Length[memory address]", "sigcomp.udvm.addr.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Length", HFILL } + }, + { &hf_udvm_destination, + { "%Destination", "sigcomp.udvm.destination", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Destination", HFILL } + }, + { &hf_udvm_addr_destination, + { "%Destination[memory address]", "sigcomp.udvm.addr.destination", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Destination", HFILL } + }, + { &hf_udvm_at_address, + { "@Address(mem_add_of_inst + D) mod 2^16)", "sigcomp.udvm.at.address", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Address", HFILL } + }, + { &hf_udvm_address, + { "%Address", "sigcomp.udvm.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Address", HFILL } + }, + { &hf_udvm_literal_num, + { "#n", "sigcomp.udvm.literal-num", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Literal number", HFILL } + }, + { &hf_udvm_value, + { "%Value", "sigcomp.udvm.value", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Value", HFILL } + }, + { &hf_udvm_addr_value, + { "%Value[memory address]", "sigcomp.udvm.value", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Value", HFILL } + }, + { &hf_partial_identifier_start, + { "%Partial identifier start", "sigcomp.udvm.partial.identifier.start", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Partial identifier start", HFILL } + }, + { &hf_partial_identifier_length, + { "%Partial identifier length", "sigcomp.udvm.partial.identifier.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Partial identifier length", HFILL } + }, + { &hf_state_begin, + { "%State begin", "sigcomp.udvm.state.begin", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State begin", HFILL } + }, + { &hf_udvm_state_length, + { "%State length", "sigcomp.udvm.state.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State length", HFILL } + }, + + { &hf_udvm_state_length_addr, + { "%State length[memory address]", "sigcomp.udvm.state.length.addr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State length", HFILL } + }, + { &hf_udvm_state_address, + { "%State address", "sigcomp.udvm.start.address", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State address", HFILL } + }, + { &hf_udvm_state_address_addr, + { "%State address[memory address]", "sigcomp.udvm.start.address.addr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State address", HFILL } + }, + { &hf_udvm_state_instr, + { "%State instruction", "sigcomp.udvm.start.instr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State instruction", HFILL } + }, + { &hf_udvm_operand_1, + { "$Operand 1[memory address]", "sigcomp.udvm.operand.1", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Reference $ Operand 1", HFILL } + }, + { &hf_udvm_operand_2, + { "%Operand 2", "sigcomp.udvm.operand.2", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Operand 2", HFILL } + }, + { &hf_udvm_operand_2_addr, + { "%Operand 2[memory address]", "sigcomp.udvm.operand.2.addr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Operand 2", HFILL } + }, + { &hf_udvm_j, + { "%j", "sigcomp.udvm.j", + FT_UINT16, BASE_DEC, NULL, 0x0, + "j", HFILL } + }, + { &hf_udvm_addr_j, + { "%j[memory address]", "sigcomp.udvm.addr.j", + FT_UINT16, BASE_DEC, NULL, 0x0, + "j", HFILL } + }, + { &hf_udvm_output_start, + { "%Output_start", "sigcomp.output.start", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Output start", HFILL } + }, + { &hf_udvm_addr_output_start, + { "%Output_start[memory address]", "sigcomp.addr.output.start", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Output start", HFILL } + }, + { &hf_udvm_output_length, + { "%Output_length", "sigcomp.output.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Output length", HFILL } + }, + { &hf_udvm_output_length_addr, + { "%Output_length[memory address]", "sigcomp.output.length.addr", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Output length", HFILL } + }, + { &hf_udvm_req_feedback_loc, + { "%Requested feedback location", "sigcomp.req.feedback.loc", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Requested feedback location", HFILL } + }, + { &hf_udvm_min_acc_len, + { "%Minimum access length", "sigcomp.min.acc.len", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Minimum access length", HFILL } + }, + { &hf_udvm_state_ret_pri, + { "%State retention priority", "sigcomp.udvm.state.ret.pri", + FT_UINT16, BASE_DEC, NULL, 0x0, + "State retention priority", HFILL } + }, + { &hf_udvm_ret_param_loc, + { "%Returned parameters location", "sigcomp.ret.param.loc", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Returned parameters location", HFILL } + }, + { &hf_udvm_position, + { "%Position", "sigcomp.udvm.position", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Position", HFILL } + }, + { &hf_udvm_ref_dest, + { "$Destination[memory address]", "sigcomp.udvm.ref.destination", + FT_UINT16, BASE_DEC, NULL, 0x0, + "(reference)Destination", HFILL } + }, + { &hf_udvm_bits, + { "%Bits", "sigcomp.udvm.bits", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Bits", HFILL } + }, + { &hf_udvm_lower_bound, + { "%Lower bound", "sigcomp.udvm.lower.bound", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Lower_bound", HFILL } + }, + { &hf_udvm_upper_bound, + { "%Upper bound", "sigcomp.udvm.upper.bound", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Upper bound", HFILL } + }, + { &hf_udvm_uncompressed, + { "%Uncompressed", "sigcomp.udvm.uncompressed", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Uncompressed", HFILL } + }, + { &hf_udvm_start_value, + { "%Start value", "sigcomp.udvm.start.value", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Start value", HFILL } + }, + { &hf_udvm_offset, + { "%Offset", "sigcomp.udvm.offset", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Offset", HFILL } + }, + { &hf_udvm_addr_offset, + { "%Offset[memory address]", "sigcomp.udvm.addr.offset", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Offset", HFILL } + }, + { &hf_sigcomp_nack_ver, + { "NACK Version", "sigcomp.nack.ver", + FT_UINT8, BASE_DEC, NULL, 0x0f, + NULL, HFILL } + }, + { &hf_sigcomp_nack_reason_code, + { "Reason Code", "sigcomp.nack.reason", + FT_UINT8, BASE_DEC | BASE_EXT_STRING, &sigcomp_nack_reason_code_vals_ext, 0x0, + "NACK Reason Code", HFILL } + }, + { &hf_sigcomp_nack_failed_op_code, + { "OPCODE of failed instruction", "sigcomp.nack.failed_op_code", + FT_UINT8, BASE_DEC | BASE_EXT_STRING, &udvm_instruction_code_vals_ext, 0x0, + "NACK OPCODE of failed instruction", HFILL } + }, + { &hf_sigcomp_nack_pc, + { "PC of failed instruction", "sigcomp.nack.pc", + FT_UINT16, BASE_DEC, NULL, 0x0, + "NACK PC of failed instruction", HFILL } + }, + { &hf_sigcomp_nack_sha1, + { "SHA-1 Hash of failed message", "sigcomp.nack.sha1", + FT_BYTES, BASE_NONE, NULL, 0x0, + "NACK SHA-1 Hash of failed message", HFILL } + }, + { &hf_sigcomp_nack_state_id, + { "State ID (6 - 20 bytes)", "sigcomp.nack.state_id", + FT_BYTES, BASE_NONE, NULL, 0x0, + "NACK State ID (6 - 20 bytes)", HFILL } + }, + { &hf_sigcomp_nack_cycles_per_bit, + { "Cycles Per Bit", "sigcomp.nack.cycles_per_bit", + FT_UINT8, BASE_DEC, NULL, 0x0, + "NACK Cycles Per Bit", HFILL } + }, + { &hf_sigcomp_nack_memory_size, + { "Memory size", "sigcomp.memory_size", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_sigcomp_decompress_instruction, + { "Instruction", "sigcomp.decompress_instruction", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_sigcomp_loading_result, + { "Loading result", "sigcomp.loading_result", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_sigcomp_byte_copy, + { "byte copy", "sigcomp.byte_copy", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + /* Generated from convert_proto_tree_add_text.pl */ + { &hf_sigcomp_accessing_state, { "### Accessing state ###", "sigcomp.accessing_state", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_getting_value, { "Getting value", "sigcomp.getting_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_load_bytecode_into_udvm_start, { "Load bytecode into UDVM starting at", "sigcomp.load_bytecode_into_udvm_start", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_instruction_code, { "Instruction code", "sigcomp.instruction_code", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_current_instruction, { "Addr", "sigcomp.current_instruction", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &udvm_instruction_code_vals_ext, 0x0, NULL, HFILL }}, + { &hf_sigcomp_decompression_failure, { "DECOMPRESSION-FAILURE", "sigcomp.decompression_failure", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_wireshark_udvm_diagnostic, { "Wireshark UDVM diagnostic", "sigcomp.wireshark_udvm_diagnostic", FT_UINT32, BASE_DEC, VALS(result_code_vals), 0x0, NULL, HFILL }}, + { &hf_sigcomp_calculated_sha_1, { "Calculated SHA-1", "sigcomp.calculated_sha_1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_copying_value, { "Copying value", "sigcomp.copying_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_storing_value, { "Storing value", "sigcomp.storing_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_loading_value, { "Loading value", "sigcomp.loading_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_set_hu, { "Set Hu", "sigcomp.set_hu", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_loading_h, { "Loading H", "sigcomp.loading_h", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_state_value, { "Addr", "sigcomp.state_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_output_value, { "Output value", "sigcomp.output_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_num_state_create, { "no_of_state_create", "sigcomp.num_state_create", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_sha1_digest, { "SHA1 digest", "sigcomp.sha1_digest", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_creating_state, { "### Creating state ###", "sigcomp.creating_state", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_sigcomp_message_decompressed, { "SigComp message Decompressed", "sigcomp.message_decompressed", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_starting_to_remove_escape_digits, { "Starting to remove escape digits", "sigcomp.starting_to_remove_escape_digits", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_escape_digit_found, { "Escape digit found", "sigcomp.escape_digit_found", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_illegal_escape_code, { "Illegal escape code", "sigcomp.illegal_escape_code", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_end_of_sigcomp_message_indication_found, { "End of SigComp message indication found", "sigcomp.end_of_sigcomp_message_indication_found", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_addr_value, { "Addr", "sigcomp.addr", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_copying_bytes_literally, { "Copying bytes literally", "sigcomp.copying_bytes_literally", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_data_for_sigcomp_dissector, { "Data handed to the Sigcomp dissector", "sigcomp.data_for_sigcomp_dissector", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_remaining_sigcomp_message, { "Remaining SigComp message", "sigcomp.remaining_sigcomp_message", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_sha1buff, { "sha1buff", "sigcomp.sha1buff", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_udvm_instruction, { "UDVM instruction", "sigcomp.udvm_instruction", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_remaining_bytes, { "Remaining bytes", "sigcomp.remaining_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_max_udvm_cycles, { "maximum_UDVM_cycles", "sigcomp.max_udvm_cycles", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_used_udvm_cycles, { "used_udvm_cycles", "sigcomp.used_udvm_cycles", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_udvm_execution_stated, { "UDVM EXECUTION STARTED", "sigcomp.udvm_execution_stated", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_message_length, { "Message Length", "sigcomp.message_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_sigcomp_byte_code_length, { "Byte code length", "sigcomp.byte_code_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + }; + +/* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sigcomp, + &ett_sigcomp_udvm, + &ett_sigcomp_udvm_exe, + }; + static gint *ett_raw[] = { + &ett_raw_text, + }; + + static ei_register_info ei[] = { + { &ei_sigcomp_nack_failed_op_code, { "sigcomp.nack.failed_op_code.expert", PI_SEQUENCE, PI_WARN, "SigComp NACK", EXPFILL }}, + { &ei_sigcomp_invalid_instruction, { "sigcomp.invalid_instruction", PI_PROTOCOL, PI_WARN, "Invalid instruction", EXPFILL }}, + { &ei_sigcomp_invalid_shift_value, { "sigcomp.invalid_shift_value", PI_PROTOCOL, PI_WARN, "Invalid shift value", EXPFILL }}, + /* Generated from convert_proto_tree_add_text.pl */ + { &ei_sigcomp_sigcomp_message_decompression_failure, { "sigcomp.message_decompression_failure", PI_PROTOCOL, PI_WARN, "SigComp message Decompression failure", EXPFILL }}, + { &ei_sigcomp_execution_of_this_instruction_is_not_implemented, { "sigcomp.execution_of_this_instruction_is_not_implemented", PI_UNDECODED, PI_WARN, "Execution of this instruction is NOT implemented", EXPFILL }}, + { &ei_sigcomp_decompression_failure, { "sigcomp.decompression_failure_expert", PI_PROTOCOL, PI_WARN, "DECOMPRESSION FAILURE", EXPFILL }}, + { &ei_sigcomp_tcp_fragment, { "sigcomp.tcp_fragment", PI_MALFORMED, PI_ERROR, "TCP Fragment", EXPFILL }}, + { &ei_sigcomp_failed_to_access_state_wireshark_udvm_diagnostic, { "sigcomp.failed_to_access_state_wireshark_udvm_diagnostic", PI_PROTOCOL, PI_WARN, "Failed to Access state Wireshark UDVM diagnostic", EXPFILL }}, + { &ei_sigcomp_all_remaining_parameters_zero, { "sigcomp.all_remaining_parameters", PI_PROTOCOL, PI_NOTE, "All remaining parameters = 0(Not in the uploaded code as UDVM buffer initialized to Zero", EXPFILL }}, + }; + + module_t *sigcomp_module; + expert_module_t* expert_sigcomp; + + static const enum_val_t udvm_detail_vals[] = { + {"no-printout", "No-Printout", 0}, + {"low-detail", "Low-detail", 1}, + {"medium-detail", "Medium-detail", 2}, + {"high-detail", "High-detail", 3}, + {NULL, NULL, -1} + }; + + +/* Register the protocol name and description */ + proto_sigcomp = proto_register_protocol("Signaling Compression", "SIGCOMP", "sigcomp"); + proto_raw_sigcomp = proto_register_protocol("Decompressed SigComp message as raw text", "Raw_SigComp", "raw_sigcomp"); + + sigcomp_handle = register_dissector("sigcomp", dissect_sigcomp, proto_sigcomp); + sigcomp_tcp_handle = register_dissector("sigcomp_tcp", dissect_sigcomp_tcp,proto_sigcomp); + +/* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_sigcomp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + proto_register_subtree_array(ett_raw, array_length(ett_raw)); + expert_sigcomp = expert_register_protocol(proto_sigcomp); + expert_register_field_array(expert_sigcomp, ei, array_length(ei)); + +/* Register a configuration option for port */ + sigcomp_module = prefs_register_protocol(proto_sigcomp, NULL); + + prefs_register_bool_preference(sigcomp_module, "display.udvm.code", + "Dissect the UDVM code", + "Preference whether to Dissect the UDVM code or not", + &dissect_udvm_code); + + prefs_register_bool_preference(sigcomp_module, "display.bytecode", + "Display the bytecode of operands", + "preference whether to display the bytecode in " + "UDVM operands or not", + &display_udvm_bytecode); + prefs_register_bool_preference(sigcomp_module, "decomp.msg", + "Decompress message", + "preference whether to decompress message or not", + &decompress); + prefs_register_bool_preference(sigcomp_module, "display.decomp.msg.as.txt", + "Displays the decompressed message as text", + "preference whether to display the decompressed message " + "as raw text or not", + &display_raw_txt); + prefs_register_enum_preference(sigcomp_module, "show.udvm.execution", + "Level of detail of UDVM execution:", + "'No-Printout' = UDVM executes silently, then increasing detail " + "about execution of UDVM instructions; " + "Warning! CPU intense at high detail", + &udvm_print_detail_level, udvm_detail_vals, FALSE); + + register_init_routine(&sigcomp_init_udvm); + register_cleanup_routine(&sigcomp_cleanup_udvm); + + + +} + +void +proto_reg_handoff_sigcomp(void) +{ + sip_handle = find_dissector_add_dependency("sip",proto_sigcomp); + dissector_add_uint_range_with_preference("tcp.port", SIGCOMP_TCP_PORT_RANGE, sigcomp_tcp_handle); + dissector_add_uint_range_with_preference("udp.port", SIGCOMP_TCP_PORT_RANGE, sigcomp_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: + */ |