/* packet-sigcomp.c * Routines for Signaling Compression (SigComp) dissection. * Copyright 2004-2005, Anders Broman * * Wireshark - Network traffic analyzer * By Gerald Combs * 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 #include #include #include #include #include #include #include #include void proto_register_sigcomp(void); void proto_reg_handoff_sigcomp(void); /* Initialize the protocol and registered fields */ static int proto_sigcomp; static int proto_raw_sigcomp; static int hf_sigcomp_t_bit; static int hf_sigcomp_len; static int hf_sigcomp_returned_feedback_item; static int hf_sigcomp_returned_feedback_item_len; static int hf_sigcomp_code_len; static int hf_sigcomp_destination; static int hf_sigcomp_partial_state; static int hf_sigcomp_remaining_message_bytes; static int hf_sigcomp_compression_ratio; static int hf_sigcomp_udvm_bytecode; static int hf_sigcomp_udvm_instr; static int hf_udvm_multitype_bytecode; static int hf_udvm_reference_bytecode; static int hf_udvm_literal_bytecode; /* static int hf_udvm_operand; */ static int hf_udvm_length; static int hf_udvm_addr_length; static int hf_udvm_destination; static int hf_udvm_addr_destination; static int hf_udvm_at_address; static int hf_udvm_address; static int hf_udvm_literal_num; static int hf_udvm_value; static int hf_udvm_addr_value; static int hf_partial_identifier_start; static int hf_partial_identifier_length; static int hf_state_begin; static int hf_udvm_state_length; static int hf_udvm_state_length_addr; static int hf_udvm_state_address; static int hf_udvm_state_address_addr; static int hf_udvm_state_instr; static int hf_udvm_operand_1; static int hf_udvm_operand_2; static int hf_udvm_operand_2_addr; static int hf_udvm_j; static int hf_udvm_addr_j; static int hf_udvm_output_start; static int hf_udvm_addr_output_start; static int hf_udvm_output_length; static int hf_udvm_output_length_addr; static int hf_udvm_req_feedback_loc; static int hf_udvm_min_acc_len; static int hf_udvm_state_ret_pri; static int hf_udvm_ret_param_loc; static int hf_udvm_position; static int hf_udvm_ref_dest; static int hf_udvm_bits; static int hf_udvm_lower_bound; static int hf_udvm_upper_bound; static int hf_udvm_uncompressed; static int hf_udvm_offset; static int hf_udvm_addr_offset; static int hf_udvm_start_value; static int hf_udvm_execution_trace; static int hf_sigcomp_nack_ver; static int hf_sigcomp_nack_reason_code; static int hf_sigcomp_nack_failed_op_code; static int hf_sigcomp_nack_pc; static int hf_sigcomp_nack_sha1; static int hf_sigcomp_nack_state_id; static int hf_sigcomp_nack_memory_size; static int hf_sigcomp_nack_cycles_per_bit; static int hf_sigcomp_decompress_instruction; static int hf_sigcomp_loading_result; static int hf_sigcomp_byte_copy; /* Generated from convert_proto_tree_add_text.pl */ static int hf_sigcomp_accessing_state; static int hf_sigcomp_getting_value; static int hf_sigcomp_load_bytecode_into_udvm_start; static int hf_sigcomp_instruction_code; static int hf_sigcomp_current_instruction; static int hf_sigcomp_decompression_failure; static int hf_sigcomp_wireshark_udvm_diagnostic; static int hf_sigcomp_calculated_sha_1; static int hf_sigcomp_copying_value; static int hf_sigcomp_storing_value; static int hf_sigcomp_loading_value; static int hf_sigcomp_set_hu; static int hf_sigcomp_loading_h; static int hf_sigcomp_state_value; static int hf_sigcomp_output_value; static int hf_sigcomp_num_state_create; static int hf_sigcomp_sha1_digest; static int hf_sigcomp_creating_state; static int hf_sigcomp_sigcomp_message_decompressed; static int hf_sigcomp_starting_to_remove_escape_digits; static int hf_sigcomp_escape_digit_found; static int hf_sigcomp_illegal_escape_code; static int hf_sigcomp_end_of_sigcomp_message_indication_found; static int hf_sigcomp_addr_value; static int hf_sigcomp_copying_bytes_literally; static int hf_sigcomp_data_for_sigcomp_dissector; static int hf_sigcomp_remaining_sigcomp_message; static int hf_sigcomp_sha1buff; static int hf_sigcomp_udvm_instruction; static int hf_sigcomp_remaining_bytes; static int hf_sigcomp_max_udvm_cycles; static int hf_sigcomp_used_udvm_cycles; static int hf_sigcomp_udvm_execution_stated; static int hf_sigcomp_message_length; static int hf_sigcomp_byte_code_length; /* Initialize the subtree pointers */ static int ett_sigcomp; static int ett_sigcomp_udvm; static int ett_sigcomp_udvm_exe; static int ett_raw_text; static expert_field ei_sigcomp_nack_failed_op_code; static expert_field ei_sigcomp_invalid_instruction; static expert_field ei_sigcomp_invalid_shift_value; /* Generated from convert_proto_tree_add_text.pl */ static expert_field ei_sigcomp_tcp_fragment; static expert_field ei_sigcomp_decompression_failure; static expert_field ei_sigcomp_failed_to_access_state_wireshark_udvm_diagnostic; static expert_field ei_sigcomp_all_remaining_parameters_zero; static expert_field ei_sigcomp_sigcomp_message_decompression_failure; static expert_field ei_sigcomp_execution_of_this_instruction_is_not_implemented; 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 bool display_udvm_bytecode; /* 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 bool dissect_udvm_code; static bool display_raw_txt; /* 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 bool decompress; /* 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 int udvm_print_detail_level; /* 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, unsigned destination); static int dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, int offset,bool is_addr,int *start_offset, uint16_t *value, bool *is_memory_address ); static int dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, int offset, int *start_offset, uint16_t *value); static int dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, int offset, int *start_offset, uint16_t *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 uint8_t 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 uint8_t 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 uint8_t 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 uint8_t 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; static void sigcomp_init_udvm(void) { char *partial_state_str; uint8_t *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 = (uint8_t *)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 = (uint8_t *)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,uint8_t *buff,uint16_t p_id_start, uint16_t p_id_length, uint16_t state_begin, uint16_t *state_length, uint16_t *state_address, uint16_t *state_instruction, int hf_id) { int result_code = 0; uint32_t n; uint16_t k; uint16_t buf_size_real; uint16_t byte_copy_right; uint16_t byte_copy_left; char partial_state[STATE_BUFFER_SIZE]; /* Size is 6 - 20 */ uint8_t *state_buff; char *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 = (uint8_t *)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 ( (int32_t) 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(uint8_t *state_buff,uint8_t *state_identifier,uint16_t p_id_length) { char partial_state[STATE_BUFFER_SIZE]; unsigned i; char *partial_state_str; char *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 = (char *)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(uint8_t buff[] _U_,uint16_t p_id_start _U_,uint16_t p_id_length _U_) { } #else void udvm_state_free(uint8_t buff[],uint16_t p_id_start,uint16_t p_id_length) { char partial_state[STATE_BUFFER_SIZE]; unsigned i; char *partial_state_str; char *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(uint8_t *buff,unsigned operand_address, uint16_t *value) { unsigned bytecode; uint16_t operand; unsigned test_bits; unsigned offset = operand_address; uint8_t 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(uint8_t *buff,unsigned operand_address, uint16_t *value,unsigned *result_dest) { unsigned bytecode; uint16_t operand; unsigned offset = operand_address; unsigned test_bits; uint8_t temp_data; uint16_t 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(uint8_t *buff,unsigned operand_address, uint16_t *value) { unsigned test_bits; unsigned bytecode; unsigned offset = operand_address; uint16_t operand; uint32_t result; uint8_t temp_data; uint16_t temp_data16; uint16_t 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(uint8_t *buff,unsigned operand_address, uint16_t *value,unsigned current_address) { uint32_t result; uint16_t value1; int 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 uint8_t 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, uint8_t bit_order, uint8_t *buff, uint16_t *old_input_bit_order, uint16_t *remaining_bits, uint16_t *input_bits, unsigned *input_address, uint16_t length, uint16_t *result_code, unsigned msg_end, bool print_level_1) { uint16_t input_bit_order; uint16_t bits_still_required = length; uint16_t value = 0; uint8_t octet; int extra_bytes_available = msg_end - *input_address; int p_bit; int prev_p_bit = *old_input_bit_order & 0x0001; int 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_uint8(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. */ uint16_t lsb = reverse[(value >> 8) & 0xFF]; uint16_t 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, int udvm_mem_dest, int print_flags, int hf_id, int header_len, int byte_code_state_len, int byte_code_id_len, int udvm_start_ip) { tvbuff_t *decomp_tvb; /* UDVM memory must be initialised to zero */ uint8_t *buff = (uint8_t *)wmem_alloc0(wmem_packet_scope(), UDVM_MEMORY_SIZE); char string[2]; uint8_t *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */ uint32_t i = 0; uint16_t n = 0; uint16_t m = 0; uint16_t x; unsigned k = 0; uint16_t H; uint16_t oldH; unsigned offset = 0; unsigned start_offset; unsigned result_dest; unsigned code_length = 0; uint8_t current_instruction; unsigned current_address; unsigned operand_address; unsigned input_address; uint16_t output_address = 0; int next_operand_address; uint8_t octet; uint8_t msb; uint8_t lsb; uint16_t byte_copy_right; uint16_t byte_copy_left; uint16_t input_bit_order; uint16_t stack_location; uint16_t stack_fill; uint16_t result; unsigned msg_end = tvb_reported_length_remaining(message_tvb, 0); uint16_t result_code = 0; uint16_t old_input_bit_order = 0; uint16_t remaining_bits = 0; uint16_t input_bits = 0; uint8_t bit_order = 0; bool outside_huffman_boundaries = true; bool print_in_loop = false; uint16_t instruction_address; uint8_t no_of_state_create = 0; uint16_t state_length_buff[5]; uint16_t state_address_buff[5]; uint16_t state_instruction_buff[5]; uint16_t state_minimum_access_length_buff[5]; /* uint16_t state_state_retention_priority_buff[5]; */ uint32_t used_udvm_cycles = 0; unsigned cycles_per_bit; unsigned maximum_UDVM_cycles; uint8_t *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 */ uint16_t length; uint16_t at_address; uint16_t destination; uint16_t addr; uint16_t value; uint16_t p_id_start; uint16_t p_id_length; uint16_t state_begin; uint16_t state_length; uint16_t state_address; uint16_t state_instruction; uint16_t operand_1; uint16_t operand_2; uint16_t value_1; uint16_t value_2; uint16_t at_address_1; uint16_t at_address_2; uint16_t at_address_3; uint16_t j; uint16_t bits_n; uint16_t lower_bound_n; uint16_t upper_bound_n; uint16_t uncompressed_n; uint16_t position; uint16_t ref_destination; /* could I have used $destination ? */ uint16_t multy_offset; uint16_t output_start; uint16_t output_length; uint16_t minimum_access_length; uint16_t state_retention_priority; uint16_t requested_feedback_location; uint16_t returned_parameters_location; uint16_t start_value; /* Set print parameters */ bool print_level_1 = false; bool print_level_2 = false; bool print_level_3 = false; int 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_uint8(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 = (uint8_t *)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; 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= 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= UDVM_MEMORY_SIZE) goto decompression_failure; result = crc16_ccitt_seed(&buff[k], handle_now, (uint16_t) (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_uint8(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< 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 = (uint8_t *)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, (uint8_t *) 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; 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; uint8_t *buff; int offset = 0; int length; uint8_t octet; uint16_t data; int i; int n; bool 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_uint8(tvb,offset); } else { octet = tvb_get_uint8(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 = (uint8_t *)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_uint8(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_uint8(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_uint8(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; int offset = 0; int8_t 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_uint8(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; int offset = 0; int bytecode_offset; uint16_t partial_state_len; unsigned octet; uint8_t returned_feedback_field[128]; uint8_t partial_state[12]; unsigned tbit; uint16_t len = 0; uint16_t bytecode_len = 0; unsigned destination; int msg_len = 0; uint8_t *buff; uint16_t p_id_start; uint8_t i; uint16_t state_begin; uint16_t state_length; uint16_t state_address; uint16_t state_instruction; uint16_t result_code; char *partial_state_str; uint8_t nack_version; /* add an item to the subtree, see section 1.6 for more information */ octet = tvb_get_uint8(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_uint8(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_uint8(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 = (uint8_t *)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; uint32_t compression_ratio = (uint32_t)(((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_uint8(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_uint8(tvb, offset+1) & 0x0f; if ((len == 0) && (nack_version == 1)) { /* NACK MESSAGE */ proto_item *reason_ti; uint8_t opcode; offset++; proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; octet = tvb_get_uint8(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_uint8(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_uint8(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; uint32_t compression_ratio = (uint32_t)(((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,unsigned start_address) { unsigned instruction; int offset = 0; int start_offset = 0; int len; int n; unsigned instruction_no = 0; uint16_t value = 0; proto_item *item, *item2; unsigned UDVM_address = start_address; bool is_memory_address; uint16_t msg_length = tvb_reported_length_remaining(udvm_tvb, offset); while (msg_length > offset) { instruction = tvb_get_uint8(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, int offset, int *start_offset, uint16_t *value) { unsigned bytecode; uint16_t operand; unsigned test_bits; unsigned display_bytecode; bytecode = tvb_get_uint8(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, int offset, int *start_offset, uint16_t *value) { unsigned bytecode; uint16_t operand; unsigned test_bits; unsigned display_bytecode; bytecode = tvb_get_uint8(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, int offset, bool is_addr _U_, int *start_offset, uint16_t *value, bool *is_memory_address ) { unsigned bytecode; unsigned display_bytecode; uint16_t operand; uint32_t result; unsigned 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_uint8(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(uint32_t, (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(uint32_t, (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.address", 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 int *ett[] = { &ett_sigcomp, &ett_sigcomp_udvm, &ett_sigcomp_udvm_exe, }; static int *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: */