ab76196cb99b185d6bd512d9b6f0576f1549bd09
[obnox/wireshark/wip.git] / epan / dissectors / packet-sigcomp.c
1 /* packet-sigcomp.c
2  * Routines for Signaling Compression (SigComp) dissection.
3  * Copyright 2004-2005, Anders Broman <anders.broman@ericsson.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  * References:
25  * http://www.ietf.org/rfc/rfc3320.txt?number=3320
26  * http://www.ietf.org/rfc/rfc3321.txt?number=3321
27  * http://www.ietf.org/rfc/rfc4077.txt?number=4077
28  * Useful links :
29  * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-03.txt
30  * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
41 #include <glib.h>
42
43 #include <epan/packet.h>
44 #include "prefs.h"
45 #include "strutil.h"
46 #include <epan/expert.h>
47 #include <epan/sigcomp-udvm.h>
48 #include <epan/sigcomp_state_hdlr.h>
49
50 /* Initialize the protocol and registered fields */
51 static int proto_sigcomp                                                        = -1;
52 static int proto_raw_sigcomp                                            = -1;
53 static int hf_sigcomp_t_bit                                                     = -1;
54 static int hf_sigcomp_len                                                       = -1;
55 static int hf_sigcomp_returned_feedback_item            = -1;
56 static int hf_sigcomp_returned_feedback_item_len        = -1;
57 static int hf_sigcomp_code_len                                          = -1;
58 static int hf_sigcomp_destination                                       = -1;
59 static int hf_sigcomp_partial_state                                     = -1;
60 static int hf_sigcomp_remaining_message_bytes           = -1;
61 static int hf_sigcomp_compression_ratio                         = -1;
62 static int hf_sigcomp_udvm_bytecode                                     = -1;
63 static int hf_sigcomp_udvm_instr                                        = -1;
64 static int hf_udvm_multitype_bytecode                           = -1;
65 static int hf_udvm_reference_bytecode                           = -1;
66 static int hf_udvm_literal_bytecode                                     = -1;
67 static int hf_udvm_operand                                                      = -1;
68 static int hf_udvm_length                                                       = -1;
69 static int hf_udvm_addr_length                                          = -1;
70 static int hf_udvm_destination                                          = -1;
71 static int hf_udvm_addr_destination                                     = -1;
72 static int hf_udvm_at_address                                           = -1;
73 static int hf_udvm_address                                                      = -1;
74 static int hf_udvm_literal_num                                          = -1;
75 static int hf_udvm_value                                                        = -1;
76 static int hf_udvm_addr_value                                           = -1;
77 static int hf_partial_identifier_start                          = -1;
78 static int hf_partial_identifier_length                         = -1;
79 static int hf_state_begin                                                       = -1;
80 static int hf_udvm_state_length                                         = -1;
81 static int hf_udvm_state_length_addr                            = -1;
82 static int hf_udvm_state_address                                        = -1;
83 static int hf_udvm_state_address_addr                           = -1;
84 static int hf_udvm_state_instr                                          = -1;
85 static int hf_udvm_operand_1                                            = -1;
86 static int hf_udvm_operand_2                                            = -1;
87 static int hf_udvm_operand_2_addr                                       = -1;
88 static int hf_udvm_j                                                            = -1;
89 static int hf_udvm_addr_j                                                       = -1;
90 static int hf_udvm_output_start                                         = -1;
91 static int hf_udvm_addr_output_start                            = -1;
92 static int hf_udvm_output_length                                        = -1;
93 static int hf_udvm_output_length_addr                           = -1;
94 static int hf_udvm_req_feedback_loc                                     = -1;
95 static int hf_udvm_min_acc_len                                          = -1;
96 static int hf_udvm_state_ret_pri                                        = -1;
97 static int hf_udvm_ret_param_loc                                        = -1;
98 static int hf_udvm_position                                                     = -1;
99 static int hf_udvm_ref_dest                                                     = -1;
100 static int hf_udvm_bits                                                         = -1;
101 static int hf_udvm_lower_bound                                          = -1;
102 static int hf_udvm_upper_bound                                          = -1;
103 static int hf_udvm_uncompressed                                         = -1;
104 static int hf_udvm_offset                                                       = -1;
105 static int hf_udvm_addr_offset                                          = -1;
106 static int hf_udvm_start_value                                          = -1;
107 static int hf_udvm_execution_trace                                      = -1;
108 static int hf_sigcomp_nack_ver                                          = -1;
109 static int hf_sigcomp_nack_reason_code                          = -1;
110 static int hf_sigcomp_nack_failed_op_code                       = -1;
111 static int hf_sigcomp_nack_pc                                           = -1;
112 static int hf_sigcomp_nack_sha1                                         = -1;
113 static int hf_sigcomp_nack_state_id                                     = -1;
114 static int hf_sigcomp_nack_memory_size                          = -1;
115 static int hf_sigcomp_nack_cycles_per_bit                       = -1;
116
117 /* Initialize the subtree pointers */
118 static gint ett_sigcomp                         = -1;
119 static gint ett_sigcomp_udvm            = -1;
120 static gint ett_sigcomp_udvm_exe        = -1;
121 static gint ett_raw_text                        = -1;
122
123 static dissector_handle_t sip_handle;
124 /* set the udp ports */
125 static guint SigCompUDPPort1 = 5555;
126 static guint SigCompUDPPort2 = 6666;
127
128 /* set the tcp ports */
129 static guint SigCompTCPPort1 = 5555;
130 static guint SigCompTCPPort2 = 6666;
131
132 /* Default preference whether to display the bytecode in UDVM operands or not */
133 static gboolean display_udvm_bytecode = FALSE;
134 /* Default preference whether to dissect the UDVM code or not */
135 static gboolean dissect_udvm_code = TRUE;
136 static gboolean display_raw_txt = FALSE;
137 /* Default preference whether to decompress the message or not */
138 static gboolean decompress = TRUE;
139 /* Default preference whether to print debug info at execution of UDVM 
140  * 0 = No printout
141  * 1 = details level 1
142  * 2 = details level 2
143  * 3 = details level 3
144  * 4 = details level 4
145  */
146 static gint udvm_print_detail_level = 0;
147
148 /* Value strings */
149 static const value_string length_encoding_vals[] = {
150         { 0x00, "No partial state (Message type 2)" },
151         { 0x01, "(6 bytes)" },
152         { 0x02, "(9 bytes)" },
153         { 0x03, "(12 bytes)" },
154         { 0,    NULL }
155 };
156
157
158 static const value_string destination_address_encoding_vals[] = {
159         { 0x00, "Reserved" },
160         { 0x01, "128" },
161         { 0x02, "192" },
162         { 0x03, "256" },
163         { 0x04, "320" },
164         { 0x05, "384" },
165         { 0x06, "448" },
166         { 0x07, "512" },
167         { 0x08, "576" },
168         { 0x09, "640" },
169         { 0x0a, "704" },
170         { 0x0b, "768" },
171         { 0x0c, "832" },
172         { 0x0d, "896" },
173         { 0x0e, "960" },
174         { 0x0F, "1024" },
175         { 0,    NULL }
176 };
177
178 static const value_string udvm_instruction_code_vals[] = {
179         { 0,    "DECOMPRESSION-FAILURE" },
180         { 1,    "AND" },
181         { 2,    "OR" },
182         { 3,    "NOT" },
183         { 4,    "LSHIFT" },
184         { 5,    "RSHIFT" },
185         { 6,    "ADD" },
186         { 7,    "SUBTRACT" },
187         { 8,    "MULTIPLY" },
188         { 9,    "DIVIDE" },
189         { 10,   "REMAINDER" },
190         { 11,   "SORT-ASCENDING" },
191         { 12,   "SORT-DESCENDING" },
192         { 13,   "SHA-1" },
193         { 14,   "LOAD" },
194         { 15,   "MULTILOAD" },
195         { 16,   "PUSH" },
196         { 17,   "POP" },
197         { 18,   "COPY" },
198         { 19,   "COPY-LITERAL" },
199         { 20,   "COPY-OFFSET" },
200         { 21,   "MEMSET" },
201         { 22,   "JUMP" },
202         { 23,   "COMPARE" },
203         { 24,   "CALL" },
204         { 25,   "RETURN" },
205         { 26,   "SWITCH" },
206         { 27,   "CRC" },
207         { 28,   "INPUT-BYTES" },
208         { 29,   "INPUT-BITS" },
209         { 30,   "INPUT-HUFFMAN" },
210         { 31,   "STATE-ACCESS" },
211         { 32,   "STATE-CREATE" },
212         { 33,   "STATE-FREE" },
213         { 34,   "OUTPUT" },
214         { 35,   "END-MESSAGE" },
215         { 0,    NULL }
216 };
217         /* RFC3320
218          * Figure 10: Bytecode for a multitype (%) operand
219          * Bytecode:                       Operand value:      Range:               HEX val
220          * 00nnnnnn                        N                   0 - 63                           0x00
221          * 01nnnnnn                        memory[2 * N]       0 - 65535                        0x40
222          * 1000011n                        2 ^ (N + 6)        64 , 128                          0x86    
223          * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768                     0x88
224          * 111nnnnn                        N + 65504       65504 - 65535                        0xe0
225          * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535                        0x90
226          * 101nnnnn nnnnnnnn               N                   0 - 8191                         0xa0
227          * 110nnnnn nnnnnnnn               memory[N]           0 - 65535                        0xc0
228          * 10000000 nnnnnnnn nnnnnnnn      N                   0 - 65535                        0x80
229          * 10000001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535                        0x81
230          */
231
232 static const value_string display_bytecode_vals[] = {
233         { 0x00, "00nnnnnn, N, 0 - 63" },
234         { 0x40, "01nnnnnn, memory[2 * N],0 - 65535" },
235         { 0x86, "1000011n, 2 ^ (N + 6), 64 , 128" },
236         { 0x88, "10001nnn, 2 ^ (N + 8), 256,..., 32768" },
237         { 0xe0, "111nnnnn N + 65504, 65504 - 65535" },
238         { 0x90, "1001nnnn nnnnnnnn, N + 61440, 61440 - 65535" },
239         { 0xa0, "101nnnnn nnnnnnnn, N, 0 - 8191" },
240         { 0xc0, "110nnnnn nnnnnnnn, memory[N], 0 - 65535" },
241         { 0x80, "10000000 nnnnnnnn nnnnnnnn, N, 0 - 65535" },
242         { 0x81, "10000001 nnnnnnnn nnnnnnnn, memory[N], 0 - 65535" },
243         { 0,    NULL }
244 };
245 /* RFC3320
246  * 0nnnnnnn                        memory[2 * N]       0 - 65535
247  * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
248  * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
249  */
250 static const value_string display_ref_bytecode_vals[] = {
251         { 0x00, "0nnnnnnn memory[2 * N] 0 - 65535" },
252         { 0x80, "10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535" },
253         { 0xc0, "11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535" },
254         { 0,    NULL }
255 };
256  /*  The simplest operand type is the literal (#), which encodes a
257   * constant integer from 0 to 65535 inclusive.  A literal operand may
258   * require between 1 and 3 bytes depending on its value.
259   * Bytecode:                       Operand value:      Range:
260   * 0nnnnnnn                        N                   0 - 127
261   * 10nnnnnn nnnnnnnn               N                   0 - 16383
262   * 11000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
263   *
264   *            Figure 8: Bytecode for a literal (#) operand
265   *
266   */
267
268 static const value_string display_lit_bytecode_vals[] = {
269         { 0x00, "0nnnnnnn N 0 - 127" },
270         { 0x80, "10nnnnnn nnnnnnnn N 0 - 16383" },
271         { 0xc0, "11000000 nnnnnnnn nnnnnnnn N 0 - 65535" },
272         { 0,    NULL }
273 };
274
275 #define SIGCOMP_NACK_STATE_NOT_FOUND              1
276 #define SIGCOMP_NACK_CYCLES_EXHAUSTED             2
277 #define SIGCOMP_NACK_BYTECODES_TOO_LARGE         18  
278 #define SIGCOMP_NACK_ID_NOT_UNIQUE               21  
279 #define SIGCOMP_NACK_STATE_TOO_SHORT             23  
280
281 static const value_string sigcomp_nack_reason_code_vals[] = {
282         {  1,   "STATE_NOT_FOUND" },                    /*1  State ID (6 - 20 bytes) */
283         {  2,   "CYCLES_EXHAUSTED" },                   /*2  Cycles Per Bit (1 byte) */
284         {  3,   "USER_REQUESTED" },
285         {  4,   "SEGFAULT" },
286         {  5,   "TOO_MANY_STATE_REQUESTS" },
287         {  6,   "INVALID_STATE_ID_LENGTH" },
288         {  7,   "INVALID_STATE_PRIORITY" },
289         {  8,   "OUTPUT_OVERFLOW" },
290         {  9,   "STACK_UNDERFLOW" },
291         { 10,   "BAD_INPUT_BITORDER" },
292         { 11,   "DIV_BY_ZERO" },
293         { 12,   "SWITCH_VALUE_TOO_HIGH" },
294         { 13,   "TOO_MANY_BITS_REQUESTED" },
295         { 14,   "INVALID_OPERAND" },
296         { 15,   "HUFFMAN_NO_MATCH" },
297         { 16,   "MESSAGE_TOO_SHORT" },
298         { 17,   "INVALID_CODE_LOCATION" },
299         { 18,   "BYTECODES_TOO_LARGE" },                /*18  Memory size (2 bytes) */
300         { 19,   "INVALID_OPCODE" },
301         { 20,   "INVALID_STATE_PROBE" },
302         { 21,   "ID_NOT_UNIQUE" },                              /*21  State ID (6 - 20 bytes) */
303         { 22,   "MULTILOAD_OVERWRITTEN" },
304         { 23,   "STATE_TOO_SHORT" },                    /*23  State ID (6 - 20 bytes) */
305         { 24,   "INTERNAL_ERROR" },
306         { 25,   "FRAMING_ERROR" },
307         { 0,    NULL }
308 };
309
310
311 static void dissect_udvm_bytecode(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, guint destination);
312
313 static int dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
314                                                                                   gint offset,gboolean is_addr,gint *start_offset,
315                                                                                   guint16 *value, gboolean *is_memory_address );
316
317 static int dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
318                                                            gint offset, gint *start_offset, guint16 *value);
319
320 static int dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
321                                                            gint offset, gint *start_offset, guint16 *value);
322 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
323
324 static int dissect_sigcomp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
325
326 static proto_tree *top_tree;
327
328 /* Initialize the state handler
329  *
330  */
331 static void
332 sigcomp_init_protocol(void)
333 {
334         sigcomp_init_udvm();
335
336 /* Sigcomp over TCP record marking used 
337  * RFC 3320
338  * 4.2.2.  Record Marking
339  *
340  * For a stream-based transport, the dispatcher delimits messages by
341  * parsing the compressed data stream for instances of 0xFF and taking
342  * the following actions:
343  * Occurs in data stream:     Action:
344  *
345  *   0xFF 00                    one 0xFF byte in the data stream
346  *   0xFF 01                    same, but the next byte is quoted (could
347  *                              be another 0xFF)
348  *      :                                           :
349  *   0xFF 7F                    same, but the next 127 bytes are quoted
350  *   0xFF 80 to 0xFF FE         (reserved for future standardization)
351  *   0xFF FF                    end of SigComp message                   
352  *   :
353  *   In UDVM version 0x01, any occurrence of the combinations 0xFF80 to
354  *   0xFFFE that are not protected by quoting causes decompression
355  *   failure; the decompressor SHOULD close the stream-based transport in
356  *   this case.
357  */
358
359 /*
360  * TODO: Reassembly, handle more than one message in a tcp segment.
361  */
362
363 static int
364 dissect_sigcomp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
365 {
366         proto_item      *ti;
367         proto_tree      *sigcomp_tree;
368         tvbuff_t        *unescaped_tvb;
369
370         guint8          *buff;
371         int                     offset = 0;
372         int                     length;
373         guint8          octet;
374         guint16         data;
375         int                     i;
376         int                     n;
377         gboolean        end_off_message;
378
379         top_tree = tree;
380
381         /* Is this SIGCOMP ? */
382         data = tvb_get_ntohs(tvb, offset);
383         if(data == 0xffff){
384                 /* delimiter */
385                 offset = offset + 2;
386                 octet = tvb_get_guint8(tvb,offset);
387         }else{
388                 octet = tvb_get_guint8(tvb,offset);
389         }
390         if ((octet  & 0xf8) != 0xf8)
391          return offset;
392
393         /* Search for delimiter 0xffff in the remain tvb buffer */
394         length = tvb_ensure_length_remaining(tvb, offset);
395         for(i=0; i<(length-1); ++i){
396                 /* Loop end criteria is (length-1) because we take 2 bytes each loop */
397                 data = tvb_get_ntohs(tvb, offset+i);
398                 if (0xffff == data) break;
399         }
400         if (i >= (length-1)){
401                 /* SIGCOMP may be subdissector of SIP, so we use  
402                  * pinfo->saved_can_desegment to determine whether do desegment 
403                  * as well as pinfo->can_desegment */
404                 if (pinfo->can_desegment || pinfo->saved_can_desegment){
405                         /* Delimiter oxffff was not found, not a complete SIGCOMP PDU */
406                         pinfo->desegment_offset = offset;
407                         pinfo->desegment_len=DESEGMENT_ONE_MORE_SEGMENT;
408                         return -1;
409                 }
410         }
411
412         /* Make entries in Protocol column and Info column on summary display */
413         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIGCOMP");
414
415         col_clear(pinfo->cinfo, COL_INFO);
416
417         length = tvb_length_remaining(tvb,offset);
418
419 try_again:
420         /* create display subtree for the protocol */
421         ti = proto_tree_add_item(tree, proto_sigcomp, tvb, 0, -1, FALSE);
422         sigcomp_tree = proto_item_add_subtree(ti, ett_sigcomp);
423         i=0;
424         end_off_message = FALSE;
425         buff = g_malloc(length-offset);
426         if (udvm_print_detail_level>2)
427                 proto_tree_add_text(sigcomp_tree, tvb, offset, -1,"Starting to remove escape digits");
428         while ((offset < length) && (end_off_message == FALSE)){
429                 octet = tvb_get_guint8(tvb,offset);
430                 if ( octet == 0xff ){
431                         if ( offset +1 >= length ){
432                                 /* if the tvb is short dont check for the second escape digit */
433                                 offset++;
434                                 continue;
435                         }
436                         if (udvm_print_detail_level>2)
437                                 proto_tree_add_text(sigcomp_tree, tvb, offset, 2,
438                                         "              Escape digit found (0xFF)");
439                         octet = tvb_get_guint8(tvb, offset+1);
440                         if ( octet == 0){
441                                 buff[i] = 0xff;
442                                 offset = offset +2;
443                                 i++;
444                                 continue;
445                         }
446                         if ((octet > 0x7f) && (octet < 0xff )){
447                                 if (udvm_print_detail_level>2)
448                                         proto_tree_add_text(sigcomp_tree, tvb, offset, 2,
449                                                 "              Illegal escape code");
450                                 offset = offset + tvb_length_remaining(tvb,offset);
451                                 return offset;
452                         }
453                         if ( octet == 0xff){
454                                 if (udvm_print_detail_level>2)
455                                         proto_tree_add_text(sigcomp_tree, tvb, offset, 2,
456                                                 "              End of SigComp message indication found (0xFFFF)");
457                                 end_off_message = TRUE;
458                                 offset = offset+2;
459                                 continue;
460                         }
461                         buff[i] = 0xff;
462                         if (udvm_print_detail_level>2)
463                                 proto_tree_add_text(sigcomp_tree, tvb, offset, 1,
464                                                         "              Addr: %u tvb value(0x%0x) ", i, buff[i]);
465                         i++;
466                         offset = offset+2;
467                         if (udvm_print_detail_level>2)
468                         proto_tree_add_text(sigcomp_tree, tvb, offset, octet,
469                                                 "              Copying %u bytes literally",octet);
470                         if( offset+octet >= length)
471                                 /* if the tvb is short dont copy further than the end */
472                                 octet = length - offset;
473                         for ( n=0; n < octet; n++ ){
474                                 buff[i] = tvb_get_guint8(tvb, offset);
475                                 if (udvm_print_detail_level>2)
476                                         proto_tree_add_text(sigcomp_tree, tvb, offset, 1,
477                                                                 "                  Addr: %u tvb value(0x%0x) ", i, buff[i]);
478                                 i++;
479                                 offset++;
480                         }
481                         continue;
482                 }
483                 buff[i] = octet;
484                 if (udvm_print_detail_level>2)
485                         proto_tree_add_text(sigcomp_tree, tvb, offset, 1,
486                                                 "              Addr: %u tvb value(0x%0x) ", i, buff[i]);
487
488                 i++;
489                 offset++;
490         }
491         unescaped_tvb = tvb_new_child_real_data(tvb, buff,i,i);
492         /* Arrange that the allocated packet data copy be freed when the
493          * tvbuff is freed. 
494          */
495         tvb_set_free_cb( unescaped_tvb, g_free );
496
497         add_new_data_source(pinfo, unescaped_tvb, "Unescaped Data handed to the SigComp dissector");
498
499         proto_tree_add_text(sigcomp_tree, unescaped_tvb, 0, -1,"Data handed to the Sigcomp dissector");
500         if (end_off_message == TRUE){
501                 dissect_sigcomp_common(unescaped_tvb, pinfo, sigcomp_tree);
502         }else{
503                 proto_tree_add_text(sigcomp_tree, unescaped_tvb, 0, -1,"TCP Fragment, no end mark found");
504         }
505         if ( offset < length){
506                 goto try_again;
507         }
508
509         return offset;
510 }
511 /* Code to actually dissect the packets */
512 static int
513 dissect_sigcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
514 {
515         proto_item      *ti;
516         proto_tree      *sigcomp_tree;
517         gint            offset = 0;
518         gint8           octet;
519
520         /* If we got called from SIP this might be over TCP */
521         if ( pinfo->ptype == PT_TCP )
522                 return dissect_sigcomp_tcp(tvb, pinfo, tree);
523
524         /* Is this a SigComp message or not ? */
525         octet = tvb_get_guint8(tvb, offset);
526         if ((octet  & 0xf8) != 0xf8)
527          return 0;
528
529         /* Make entries in Protocol column and Info column on summary display */
530         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIGCOMP");
531
532         col_clear(pinfo->cinfo, COL_INFO);
533
534         top_tree = tree;
535
536         /* create display subtree for the protocol */
537         ti = proto_tree_add_item(tree, proto_sigcomp, tvb, 0, -1, FALSE);
538         sigcomp_tree = proto_item_add_subtree(ti, ett_sigcomp);
539
540         return dissect_sigcomp_common(tvb, pinfo, sigcomp_tree);
541 }
542 /* Code to actually dissect the packets */
543 static int
544 dissect_sigcomp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sigcomp_tree)
545 {
546
547 /* Set up structures needed to add the protocol subtree and manage it */
548         tvbuff_t        *udvm_tvb, *msg_tvb, *udvm2_tvb;
549         tvbuff_t        *decomp_tvb = NULL;
550         proto_item      *udvm_bytecode_item, *udvm_exe_item;
551         proto_tree      *sigcomp_udvm_tree, *sigcomp_udvm_exe_tree;
552         gint            offset = 0;
553         gint            bytecode_offset;
554         guint16         partial_state_len;
555         guint           octet;
556         guint8          returned_feedback_field[128];
557         guint8          partial_state[12];
558         guint           tbit;
559         guint16         len = 0;
560         guint16         bytecode_len = 0;
561         guint           destination;
562         gint            msg_len = 0;
563         guint8          *buff;
564         guint16         p_id_start;
565         guint8          i;
566         guint16         state_begin;
567         guint16         state_length;
568         guint16         state_address;
569         guint16         state_instruction;
570         guint16         result_code;
571         gchar           *partial_state_str;
572         guint8          nack_version;
573
574
575
576 /* add an item to the subtree, see section 1.6 for more information */
577         octet = tvb_get_guint8(tvb, offset);
578
579 /*       A SigComp message takes one of two forms depending on whether it
580  *  accesses a state item at the receiving endpoint.  The two variants of
581  *  a SigComp message are given in Figure 3.  (The T-bit controls the
582  *  format of the returned feedback item and is defined in Section 7.1.)
583  *
584  *   0   1   2   3   4   5   6   7       0   1   2   3   4   5   6   7
585  * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
586  * | 1   1   1   1   1 | T |  len  |   | 1   1   1   1   1 | T |   0   |
587  * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
588  * |                               |   |                               |
589  * :    returned feedback item     :   :    returned feedback item     :
590  * |                               |   |                               |
591  * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
592  * |                               |   |           code_len            |
593  * :   partial state identifier    :   +---+---+---+---+---+---+---+---+
594  *
595  * |                               |   |   code_len    |  destination  |
596  * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
597  * |                               |   |                               |
598  * :   remaining SigComp message   :   :    uploaded UDVM bytecode     :
599  * |                               |   |                               |
600  * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
601  *                                     |                               |
602  *                                     :   remaining SigComp message   :
603  *                                     |                               |
604  *                                     +---+---+---+---+---+---+---+---+
605  *
606  * RFC 4077:
607  * The format of the NACK message and the use of the fields within it
608  * are shown in Figure 1.
609  *
610  *                     0   1   2   3   4   5   6   7
611  *                  +---+---+---+---+---+---+---+---+
612  *                  | 1   1   1   1   1 | T |   0   |
613  *                  +---+---+---+---+---+---+---+---+
614  *                  |                               |
615  *                  :    returned feedback item     :
616  *                  |                               |
617  *                  +---+---+---+---+---+---+---+---+
618  *                  |         code_len = 0          |
619  *                  +---+---+---+---+---+---+---+---+
620  *                  | code_len = 0  |  version = 1  |
621  *                  +---+---+---+---+---+---+---+---+
622  *                  |          Reason Code          |
623  *                  +---+---+---+---+---+---+---+---+
624  *                  |  OPCODE of failed instruction |
625  *                  +---+---+---+---+---+---+---+---+
626  *                  |   PC of failed instruction    |
627  *                  |                               |
628  *                  +---+---+---+---+---+---+---+---+
629  *                  |                               |
630  *                  : SHA-1 Hash of failed message  :
631  *                  |                               |
632  *                  +---+---+---+---+---+---+---+---+
633  *                  |                               |
634  *                  :         Error Details         :
635  *                  |                               |
636  *                  +---+---+---+---+---+---+---+---+
637  *                  Figure 1: SigComp NACK Message Format
638  */
639
640         proto_tree_add_item(sigcomp_tree,hf_sigcomp_t_bit, tvb, offset, 1, FALSE);
641         proto_tree_add_item(sigcomp_tree,hf_sigcomp_len, tvb, offset, 1, FALSE);
642         tbit = ( octet & 0x04)>>2;
643         partial_state_len = octet & 0x03;
644         offset ++;
645         if ( partial_state_len != 0 ){
646                 /*
647                  * The len field encodes the number of transmitted bytes as follows:
648                  *
649                  *   Encoding:   Length of partial state identifier
650                  *
651                  *   01          6 bytes
652                  *       10          9 bytes
653                  *       11          12 bytes
654                  * 
655                  */
656                 partial_state_len = partial_state_len * 3 + 3;
657
658                 /*
659                  * Message format 1
660                  */
661                 col_set_str(pinfo->cinfo, COL_INFO, "Msg format 1");
662
663                 if ( tbit == 1 ) {
664                         /*
665                          * Returned feedback item exists
666                          */
667                         len = 1;
668                         octet = tvb_get_guint8(tvb, offset);
669                         /* 0   1   2   3   4   5   6   7       0   1   2   3   4   5   6   7
670                          * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
671                          * | 0 |  returned_feedback_field  |   | 1 | returned_feedback_length  |
672                          * +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
673                          *                                     |                               |
674                          *                                     :    returned_feedback_field    :
675                          *                                     |                               |
676                          *                                     +---+---+---+---+---+---+---+---+
677                          * Figure 4: Format of returned feedback item
678                          */
679
680                         if ( (octet & 0x80) != 0 ){
681                                 len = octet & 0x7f;
682                                 proto_tree_add_item(sigcomp_tree,hf_sigcomp_returned_feedback_item_len,
683                                                     tvb, offset, 1, FALSE);
684                                 offset ++;
685                                 tvb_memcpy(tvb,returned_feedback_field,offset, len);
686                         } else {
687                                 returned_feedback_field[0] = tvb_get_guint8(tvb, offset) & 0x7f;
688                         }
689                         proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item,
690                                              tvb, offset, len, returned_feedback_field);
691                         offset = offset + len;
692                 }
693                 tvb_memcpy(tvb, partial_state, offset, partial_state_len);
694                 partial_state_str = bytes_to_str(partial_state, partial_state_len);
695                 proto_tree_add_string(sigcomp_tree,hf_sigcomp_partial_state,
696                         tvb, offset, partial_state_len, partial_state_str);
697                 offset = offset + partial_state_len;
698                 msg_len = tvb_reported_length_remaining(tvb, offset);
699
700                 if(msg_len>0){
701                         proto_item *ti;
702                         ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_remaining_message_bytes, tvb,
703                                                  offset, 0, msg_len);
704                         PROTO_ITEM_SET_GENERATED(ti);
705                 }
706
707                 if ( decompress ) {
708                         msg_tvb = tvb_new_subset(tvb, offset, msg_len, msg_len);
709                         /*
710                          * buff                                 = Where "state" will be stored
711                          * p_id_start                   = Partial state identifier start pos in the buffer(buff)
712                          * partial_state_len    = Partial state identifier length
713                          * state_begin                  = Where to start to read state from
714                          * state_length                 = Length of state
715                          * state_address                        = Address where to store the state in the buffer(buff)
716                          * state_instruction    =
717                          * TRUE                                 = Indicates that state_* is in the stored state 
718                          */
719                         /* 
720                          * Note: The allocate buffer must be zeroed or some strange effects might occur.
721                          */
722                         buff = g_malloc0(UDVM_MEMORY_SIZE);
723
724
725                         p_id_start = 0;
726                         state_begin = 0;
727                         /* These values will be loaded from the buffered state in sigcomp_state_hdlr 
728                          */
729                         state_length = 0;
730                         state_address = 0;
731                         state_instruction =0;
732
733                         i = 0;
734                         while ( i < partial_state_len ){
735                                 buff[i] = partial_state[i];
736                                 i++;
737                         }
738
739 /* begin partial state-id change cco@iptel.org */                               
740 #if 0
741                         result_code = udvm_state_access(tvb, sigcomp_tree, buff, p_id_start, partial_state_len, state_begin, &state_length, 
742                                 &state_address, &state_instruction, hf_sigcomp_partial_state);
743 #endif
744                         result_code = udvm_state_access(tvb, sigcomp_tree, buff, p_id_start, STATE_MIN_ACCESS_LEN, state_begin, &state_length, 
745                                 &state_address, &state_instruction, hf_sigcomp_partial_state);
746
747 /* end partial state-id change cco@iptel.org */                         
748                         if ( result_code != 0 ){
749                                 proto_item *ti;
750                                 ti = proto_tree_add_text(sigcomp_tree, tvb, 0, -1,"Failed to Access state Wireshark UDVM diagnostic: %s.",
751                                                          val_to_str(result_code, result_code_vals,"Unknown (%u)"));
752                                 PROTO_ITEM_SET_GENERATED(ti);
753                                 g_free(buff);
754                                 return tvb_length(tvb);
755                         }
756
757                         udvm_tvb = tvb_new_child_real_data(tvb, buff,state_length+state_address,state_length+state_address);
758                         /* Arrange that the allocated packet data copy be freed when the
759                          * tvbuff is freed. 
760                          */
761                         tvb_set_free_cb( udvm_tvb, g_free );
762
763
764                         udvm2_tvb = tvb_new_subset(udvm_tvb, state_address, state_length, state_length);
765                         /* TODO Check if buff needs to be free'd */
766                         udvm_exe_item = proto_tree_add_item(sigcomp_tree, hf_udvm_execution_trace,
767                                                             udvm2_tvb, 0, state_length,
768                                                             FALSE);
769                         sigcomp_udvm_exe_tree = proto_item_add_subtree( udvm_exe_item, ett_sigcomp_udvm_exe);
770
771                         decomp_tvb = decompress_sigcomp_message(udvm2_tvb, msg_tvb, pinfo,
772                                                    sigcomp_udvm_exe_tree, state_address, 
773                                                    udvm_print_detail_level, hf_sigcomp_partial_state,
774                                                    offset, state_length, partial_state_len, state_instruction);
775                 
776
777                         if ( decomp_tvb ){
778                                 proto_item *ti;
779                                 guint32 compression_ratio = 
780                                         (guint32)(((float)tvb_length(decomp_tvb) / (float)tvb_length(tvb)) * 100);
781
782                                 /* Celebrate success and show compression ratio achieved */
783                                 proto_tree_add_text(sigcomp_tree, decomp_tvb, 0, -1,"SigComp message Decompressed WOHO!!");
784                                 ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_compression_ratio, decomp_tvb,
785                                                          0, 0, compression_ratio);
786                                 PROTO_ITEM_SET_GENERATED(ti);
787
788                                 if ( display_raw_txt )
789                                         tvb_raw_text_add(decomp_tvb, top_tree);
790                                 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
791                                         col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
792                                         col_set_fence(pinfo->cinfo,COL_PROTOCOL);
793                                 }
794                                 call_dissector(sip_handle, decomp_tvb, pinfo, top_tree);
795                         }
796                 }/* if decompress */
797
798         }
799         else{
800                 /*
801                  * Message format 2
802                  */
803         col_set_str(pinfo->cinfo, COL_INFO, "Msg format 2");
804                 if ( tbit == 1 ) {
805                         /*
806                          * Returned feedback item exists
807                          */
808                         len = 1;
809                         octet = tvb_get_guint8(tvb, offset);
810                         if ( (octet & 0x80) != 0 ){
811                                 len = octet & 0x7f;
812                                 proto_tree_add_item(sigcomp_tree,hf_sigcomp_returned_feedback_item_len,
813                                                     tvb, offset, 1, FALSE);
814                                 offset ++;
815                         }
816                         tvb_memcpy(tvb,returned_feedback_field,offset, len);
817                         proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item,
818                                              tvb, offset, len, returned_feedback_field);
819                         offset = offset + len;
820                 }
821                 len = tvb_get_ntohs(tvb, offset) >> 4;
822                 nack_version = tvb_get_guint8(tvb, offset+1) & 0x0f;
823                 if ((len == 0) && (nack_version == 1)){
824                         /* NACK MESSAGE */
825                         proto_item *reason_ti;
826                         guint8 opcode;
827                         offset++;
828                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_ver, tvb, offset, 1, FALSE);
829                         offset++;
830                         octet = tvb_get_guint8(tvb, offset);
831                         reason_ti = proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_reason_code, tvb, offset, 1, FALSE);
832                         offset++;
833                         opcode = tvb_get_guint8(tvb, offset);
834                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_failed_op_code, tvb, offset, 1, FALSE);
835                         offset++;
836
837                         /* Add expert item for NACK */
838                         expert_add_info_format(pinfo, reason_ti, PI_SEQUENCE, PI_WARN,
839                                                "SigComp NACK (reason=%s, opcode=%s)",
840                                                val_to_str(octet, sigcomp_nack_reason_code_vals, "Unknown"),
841                                                val_to_str(opcode, udvm_instruction_code_vals, "Unknown"));
842
843                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_pc, tvb, offset, 2, FALSE);
844                         offset = offset +2;
845                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_sha1, tvb, offset, 20, FALSE);
846                         offset = offset +20;
847
848                         /* Add NACK info to info column */
849                         if (check_col(pinfo->cinfo, COL_INFO)){
850                                 col_append_fstr(pinfo->cinfo, COL_INFO, "  NACK reason=%s, opcode=%s",
851                                                 val_to_str(octet, sigcomp_nack_reason_code_vals, "Unknown"),
852                                                 val_to_str(opcode, udvm_instruction_code_vals, "Unknown"));
853                         }
854
855                         switch ( octet){
856                         case SIGCOMP_NACK_STATE_NOT_FOUND:
857                         case SIGCOMP_NACK_ID_NOT_UNIQUE:
858                         case SIGCOMP_NACK_STATE_TOO_SHORT:
859                                 /* State ID (6 - 20 bytes) */
860                                 proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_state_id, tvb, offset, -1, FALSE);
861                                 break;
862                         case SIGCOMP_NACK_CYCLES_EXHAUSTED:
863                                 /* Cycles Per Bit (1 byte) */
864                                 proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_cycles_per_bit, tvb, offset, 1, FALSE);
865                                 break;
866                         case SIGCOMP_NACK_BYTECODES_TOO_LARGE:
867                                 /* Memory size (2 bytes) */
868                                 proto_tree_add_item(sigcomp_tree,hf_sigcomp_nack_memory_size, tvb, offset, 2, FALSE);
869                                 break;
870                         default:
871                                 break;
872                         }
873                 }else{
874                         octet = tvb_get_guint8(tvb, (offset + 1));
875                         destination = (octet & 0x0f);
876                         if ( destination != 0 )
877                                 destination = 64 + ( destination * 64 );
878                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_code_len, tvb, offset, 2, FALSE);
879                         proto_tree_add_item(sigcomp_tree,hf_sigcomp_destination, tvb, (offset+ 1), 1, FALSE);
880                         offset = offset +2;
881
882                         bytecode_len = len;
883                         bytecode_offset = offset;
884                         udvm_bytecode_item = proto_tree_add_item(sigcomp_tree, hf_sigcomp_udvm_bytecode, tvb,
885                                                                  bytecode_offset, bytecode_len, FALSE);
886                         proto_item_append_text(udvm_bytecode_item,
887                                                " %u (0x%x) bytes", bytecode_len, bytecode_len);
888                         sigcomp_udvm_tree = proto_item_add_subtree( udvm_bytecode_item, ett_sigcomp_udvm);
889
890                         udvm_tvb = tvb_new_subset(tvb, offset, len, len);
891                         if ( dissect_udvm_code )
892                                 dissect_udvm_bytecode(udvm_tvb, sigcomp_udvm_tree, destination); 
893
894                         offset = offset + len;
895                         msg_len = tvb_reported_length_remaining(tvb, offset);
896                         if (msg_len>0) {
897                                 proto_item *ti = proto_tree_add_text(sigcomp_tree, tvb, offset, -1,
898                                                                      "Remaining SigComp message %u bytes",
899                                                                      tvb_reported_length_remaining(tvb, offset));
900                                 PROTO_ITEM_SET_GENERATED(ti);
901                         }
902                         if ( decompress ){
903
904                                 msg_tvb = tvb_new_subset(tvb, offset, msg_len, msg_len);
905         
906                                 udvm_exe_item = proto_tree_add_item(sigcomp_tree, hf_udvm_execution_trace,
907                                                                     tvb, bytecode_offset, bytecode_len, 
908                                                                     FALSE);
909                                 sigcomp_udvm_exe_tree = proto_item_add_subtree( udvm_exe_item, ett_sigcomp_udvm_exe);
910                                 decomp_tvb = decompress_sigcomp_message(udvm_tvb, msg_tvb, pinfo,
911                                                    sigcomp_udvm_exe_tree, destination, 
912                                                    udvm_print_detail_level, hf_sigcomp_partial_state,
913                                                    offset, 0, 0, destination);
914                                 if ( decomp_tvb ){
915                                         proto_item *ti;
916                                         guint32 compression_ratio = 
917                                                 (guint32)(((float)tvb_length(decomp_tvb) / (float)tvb_length(tvb)) * 100);
918
919                                         /* Celebrate success and show compression ratio achieved */
920                                         proto_tree_add_text(sigcomp_tree, decomp_tvb, 0, -1,"SigComp message Decompressed WOHO!!");
921                                         ti = proto_tree_add_uint(sigcomp_tree, hf_sigcomp_compression_ratio, decomp_tvb,
922                                                                                          0, 0, compression_ratio);
923                                         PROTO_ITEM_SET_GENERATED(ti);
924
925                                         if ( display_raw_txt )
926                                                 tvb_raw_text_add(decomp_tvb, top_tree);
927                                         if (check_col(pinfo->cinfo, COL_PROTOCOL)){
928                                                 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/");
929                                                 col_set_fence(pinfo->cinfo,COL_PROTOCOL);
930                                         }
931                                         call_dissector(sip_handle, decomp_tvb, pinfo, top_tree);
932                                 }
933                         } /* if decompress */
934                 }/*if len==0 */
935
936         }
937         return tvb_length(tvb);
938 }
939
940                 
941 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE     0
942 #define SIGCOMP_INSTR_AND                       1
943 #define SIGCOMP_INSTR_OR                        2
944 #define SIGCOMP_INSTR_NOT                       3
945 #define SIGCOMP_INSTR_LSHIFT                    4
946 #define SIGCOMP_INSTR_RSHIFT                    5
947 #define SIGCOMP_INSTR_ADD                       6
948 #define SIGCOMP_INSTR_SUBTRACT                  7
949 #define SIGCOMP_INSTR_MULTIPLY                  8
950 #define SIGCOMP_INSTR_DIVIDE                    9
951 #define SIGCOMP_INSTR_REMAINDER                 10
952 #define SIGCOMP_INSTR_SORT_ASCENDING            11
953 #define SIGCOMP_INSTR_SORT_DESCENDING           12
954 #define SIGCOMP_INSTR_SHA_1                     13
955 #define SIGCOMP_INSTR_LOAD                      14
956 #define SIGCOMP_INSTR_MULTILOAD                 15
957 #define SIGCOMP_INSTR_PUSH                      16
958 #define SIGCOMP_INSTR_POP                       17
959 #define SIGCOMP_INSTR_COPY                      18
960 #define SIGCOMP_INSTR_COPY_LITERAL              19
961 #define SIGCOMP_INSTR_COPY_OFFSET               20
962 #define SIGCOMP_INSTR_MEMSET                    21
963 #define SIGCOMP_INSTR_JUMP                      22
964 #define SIGCOMP_INSTR_COMPARE                   23
965 #define SIGCOMP_INSTR_CALL                      24
966 #define SIGCOMP_INSTR_RETURN                    25
967 #define SIGCOMP_INSTR_SWITCH                    26
968 #define SIGCOMP_INSTR_CRC                       27
969 #define SIGCOMP_INSTR_INPUT_BYTES               28
970 #define SIGCOMP_INSTR_INPUT_BITS                29
971 #define SIGCOMP_INSTR_INPUT_HUFFMAN             30
972 #define SIGCOMP_INSTR_STATE_ACCESS              31
973 #define SIGCOMP_INSTR_STATE_CREATE              32
974 #define SIGCOMP_INSTR_STATE_FREE                33
975 #define SIGCOMP_INSTR_OUTPUT                    34
976 #define SIGCOMP_INSTR_END_MESSAGE               35      
977
978
979 static void
980 dissect_udvm_bytecode(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,guint start_address)
981 {
982         guint instruction;
983         gint offset = 0;
984         gint start_offset;
985         gint len;
986         gint n;
987         guint instruction_no = 0;
988         guint16 value = 0;
989         proto_item *item, *item2;
990         guint UDVM_address = start_address;
991         gboolean is_memory_address;
992         guint16 msg_length = tvb_reported_length_remaining(udvm_tvb, offset);
993
994
995         while (msg_length > offset) { 
996                 instruction = tvb_get_guint8(udvm_tvb, offset);
997                 instruction_no ++;
998                 UDVM_address = start_address + offset;
999 ;
1000
1001                 item = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, 1,
1002                                         "######### UDVM instruction %u at UDVM-address %u (0x%x) #########",
1003                                         instruction_no,UDVM_address,UDVM_address);
1004                 PROTO_ITEM_SET_GENERATED(item);
1005                 proto_tree_add_item(sigcomp_udvm_tree, hf_sigcomp_udvm_instr, udvm_tvb, offset, 1, FALSE);
1006                 offset ++;
1007                 switch ( instruction ) {
1008
1009                 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
1010                         /* $operand_1*/
1011                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1012                         len = offset - start_offset;
1013                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1014                                 udvm_tvb, start_offset, len, value);
1015                         /* %operand_2*/
1016                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1017                         len = offset - start_offset;
1018                         if ( is_memory_address ){
1019                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1020                                         udvm_tvb, start_offset, len, value);
1021                         }else{
1022                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1023                                         udvm_tvb, start_offset, len, value);
1024                         }
1025                         break;
1026
1027                 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
1028                         /* $operand_1*/
1029                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1030                         len = offset - start_offset;
1031                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1032                                 udvm_tvb, start_offset, len, value);
1033                         /* %operand_2*/
1034                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1035                         len = offset - start_offset;
1036                         if ( is_memory_address ){
1037                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1038                                         udvm_tvb, start_offset, len, value);
1039                         }else{
1040                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1041                                         udvm_tvb, start_offset, len, value);
1042                         }
1043                         break;
1044
1045                 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
1046                         /* $operand_1*/
1047                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1048                         len = offset - start_offset;
1049                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1050                                 udvm_tvb, start_offset, len, value);
1051                         break;
1052
1053                 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
1054                         /* $operand_1*/
1055                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1056                         len = offset - start_offset;
1057                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1058                                 udvm_tvb, start_offset, len, value);
1059                         /* %operand_2*/
1060                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1061                         len = offset - start_offset;
1062                         if ( is_memory_address ){
1063                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1064                                         udvm_tvb, start_offset, len, value);
1065                         }else{
1066                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1067                                         udvm_tvb, start_offset, len, value);
1068                         }
1069                         break;
1070
1071                 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
1072                         /* $operand_1*/
1073                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1074                         len = offset - start_offset;
1075                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1076                                 udvm_tvb, start_offset, len, value);
1077                         /* %operand_2*/
1078                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1079                         len = offset - start_offset;
1080                         if ( is_memory_address ){
1081                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1082                                         udvm_tvb, start_offset, len, value);
1083                         }else{
1084                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1085                                         udvm_tvb, start_offset, len, value);
1086                         }
1087                         break;
1088
1089                 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
1090                         /* $operand_1*/
1091                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1092                         len = offset - start_offset;
1093                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1094                                 udvm_tvb, start_offset, len, value);
1095                         /* %operand_2*/
1096                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1097                         len = offset - start_offset;
1098                         if ( is_memory_address ){
1099                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1100                                         udvm_tvb, start_offset, len, value);
1101                         }else{
1102                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1103                                         udvm_tvb, start_offset, len, value);
1104                         }
1105                         break;
1106
1107                 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
1108                         /* $operand_1*/
1109                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1110                         len = offset - start_offset;
1111                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1112                                 udvm_tvb, start_offset, len, value);
1113                         /* %operand_2*/
1114                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1115                         len = offset - start_offset;
1116                         if ( is_memory_address ){
1117                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1118                                         udvm_tvb, start_offset, len, value);
1119                         }else{
1120                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1121                                         udvm_tvb, start_offset, len, value);
1122                         }
1123                         break;
1124
1125                 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
1126                         /* $operand_1*/
1127                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1128                         len = offset - start_offset;
1129                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1130                                 udvm_tvb, start_offset, len, value);
1131                         /* %operand_2*/
1132                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1133                         len = offset - start_offset;
1134                         if ( is_memory_address ){
1135                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1136                                         udvm_tvb, start_offset, len, value);
1137                         }else{
1138                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1139                                         udvm_tvb, start_offset, len, value);
1140                         }
1141                         break;
1142
1143                 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
1144                         /* $operand_1*/
1145                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1146                         len = offset - start_offset;
1147                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1148                                 udvm_tvb, start_offset, len, value);
1149                         /* %operand_2*/
1150                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1151                         len = offset - start_offset;
1152                         if ( is_memory_address ){
1153                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1154                                         udvm_tvb, start_offset, len, value);
1155                         }else{
1156                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1157                                         udvm_tvb, start_offset, len, value);
1158                         }
1159                         break;
1160
1161                 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
1162                         /* $operand_1*/
1163                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1164                         len = offset - start_offset;
1165                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1, 
1166                                 udvm_tvb, start_offset, len, value);
1167                         /* %operand_2*/
1168                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1169                         len = offset - start_offset;
1170                         if ( is_memory_address ){
1171                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr, 
1172                                         udvm_tvb, start_offset, len, value);
1173                         }else{
1174                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2, 
1175                                         udvm_tvb, start_offset, len, value);
1176                         }
1177                         break;
1178                 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
1179                                                 /* while programming stop while loop */
1180                         offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
1181                         break;
1182
1183                 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
1184                         offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
1185                         break;
1186                 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
1187                         /* %position */
1188                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1189                         len = offset - start_offset;
1190                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, 
1191                                 udvm_tvb, start_offset, len, value);
1192
1193                         /*  %length, */
1194                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1195                         len = offset - start_offset;
1196                         if ( is_memory_address ){
1197                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1198                                         udvm_tvb, start_offset, len, value);
1199                         }else{
1200                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1201                                         udvm_tvb, start_offset, len, value);
1202                         }
1203
1204                         /* $destination */
1205                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1206                         len = offset - start_offset;
1207                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, 
1208                                 udvm_tvb, start_offset, len, value);
1209                         break;
1210
1211                 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
1212                         /* %address */
1213                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address);
1214                         len = offset - start_offset;
1215                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, 
1216                                 udvm_tvb, start_offset, len, value);
1217                         /* %value */
1218                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1219                         len = offset - start_offset;
1220                         if ( is_memory_address ){
1221                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1222                                         udvm_tvb, start_offset, len, value);
1223                         }else{
1224                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1225                                         udvm_tvb, start_offset, len, value);
1226                         }
1227                         break;
1228
1229                 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
1230                         /* %address */
1231                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1232                         len = offset - start_offset;
1233                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, 
1234                                 udvm_tvb, start_offset, len, value);
1235                         /* #n */
1236                         offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1237                         len = offset - start_offset;
1238                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, 
1239                                 udvm_tvb, start_offset, len, value);
1240                         n = value;
1241                         while ( n > 0) {
1242                                 n = n -1;
1243                                 /* %value */
1244                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1245                                 len = offset - start_offset;
1246                                 if ( is_memory_address ){
1247                                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1248                                                 udvm_tvb, start_offset, len, value);
1249                                 }else{
1250                                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1251                                                 udvm_tvb, start_offset, len, value);
1252                                 }
1253                         }
1254                         break;
1255                          
1256                 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1257                         /* %value */
1258                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1259                         len = offset - start_offset;
1260                         if ( is_memory_address ){
1261                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1262                                         udvm_tvb, start_offset, len, value);
1263                         }else{
1264                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1265                                         udvm_tvb, start_offset, len, value);
1266                         }
1267                         break;
1268
1269                 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1270                         /* %address */                  
1271                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1272
1273                         len = offset - start_offset;
1274                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, 
1275                                 udvm_tvb, start_offset, len, value);
1276                         break;
1277
1278                 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1279                         /* %position */
1280                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1281                         len = offset - start_offset;
1282                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, 
1283                                 udvm_tvb, start_offset, len, value);
1284
1285                         /*  %length, */
1286                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1287                         len = offset - start_offset;
1288                         if ( is_memory_address ){
1289                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1290                                         udvm_tvb, start_offset, len, value);
1291                         }else{
1292                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1293                                         udvm_tvb, start_offset, len, value);
1294                         }
1295
1296                         /* $destination */
1297                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1298                         len = offset - start_offset;
1299                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, 
1300                                 udvm_tvb, start_offset, len, value);
1301                         break;
1302
1303                 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1304                         /* %position */
1305                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1306                         len = offset - start_offset;
1307                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, 
1308                                 udvm_tvb, start_offset, len, value);
1309
1310                         /*  %length, */
1311                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1312                         len = offset - start_offset;
1313                         if ( is_memory_address ){
1314                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1315                                         udvm_tvb, start_offset, len, value);
1316                         }else{
1317                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1318                                         udvm_tvb, start_offset, len, value);
1319                         }
1320
1321                         /* $destination */
1322                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1323                         len = offset - start_offset;
1324                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, 
1325                                 udvm_tvb, start_offset, len, value);
1326                         break;
1327  
1328                 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1329                         /* %offset */
1330                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1331                         len = offset - start_offset;
1332                         if ( is_memory_address ){
1333                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_offset, 
1334                                         udvm_tvb, start_offset, len, value);
1335                         }else{
1336                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset, 
1337                                         udvm_tvb, start_offset, len, value);
1338                         }
1339
1340                         /*  %length, */
1341                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1342                         len = offset - start_offset;
1343                         if ( is_memory_address ){
1344                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1345                                         udvm_tvb, start_offset, len, value);
1346                         }else{
1347                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1348                                         udvm_tvb, start_offset, len, value);
1349                         }
1350
1351                         /* $destination */
1352                         offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1353                         len = offset - start_offset;
1354                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest, 
1355                                 udvm_tvb, start_offset, len, value);
1356                         break;
1357                 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1358
1359                         /* %address */
1360                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1361                         len = offset - start_offset;
1362                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address, 
1363                                 udvm_tvb, start_offset, len, value);
1364
1365                         /*  %length, */
1366                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE, &start_offset, &value, &is_memory_address);
1367                         len = offset - start_offset;
1368                         if ( is_memory_address ){
1369                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1370                                         udvm_tvb, start_offset, len, value);
1371                         }else{
1372                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1373                                         udvm_tvb, start_offset, len, value);
1374                         }
1375
1376                         /* %start_value */
1377                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1378                         len = offset - start_offset;
1379                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_start_value, 
1380                                 udvm_tvb, start_offset, len, value);
1381
1382                         /* %offset */
1383                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1384                         len = offset - start_offset;
1385                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset, 
1386                                 udvm_tvb, start_offset, len, value);
1387                         break;
1388
1389
1390                 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1391                         /* @address */
1392                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1393                         len = offset - start_offset;
1394                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1395                         value = ( value + UDVM_address ) & 0xffff;
1396                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1397                                 udvm_tvb, start_offset, len, value);
1398                         break;
1399
1400                 case SIGCOMP_INSTR_COMPARE: /* 23 */
1401                         /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1402                          */
1403                         /* %value_1 */
1404                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1405                         len = offset - start_offset;
1406                         if ( is_memory_address ){
1407                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1408                                         udvm_tvb, start_offset, len, value);
1409                         }else{
1410                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1411                                         udvm_tvb, start_offset, len, value);
1412                         }
1413
1414                         /* %value_2 */
1415                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1416                         len = offset - start_offset;
1417                         if ( is_memory_address ){
1418                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1419                                         udvm_tvb, start_offset, len, value);
1420                         }else{
1421                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1422                                         udvm_tvb, start_offset, len, value);
1423                         }
1424
1425                         /* @address_1 */
1426                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1427                         len = offset - start_offset;
1428                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1429                         value = ( value + UDVM_address ) & 0xffff;
1430                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1431                                 udvm_tvb, start_offset, len, value);
1432
1433                         /* @address_2 */
1434                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1435                         len = offset - start_offset;
1436                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1437                         value = ( value + UDVM_address ) & 0xffff;
1438                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1439                                 udvm_tvb, start_offset, len, value);
1440
1441                         /* @address_3 */
1442                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1443                         len = offset - start_offset;
1444                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1445                         value = ( value + UDVM_address ) & 0xffff;
1446                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1447                                 udvm_tvb, start_offset, len, value);
1448                         break;
1449
1450                 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1451                         /* @address */
1452                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1453                         len = offset - start_offset;
1454                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1455                         value = ( value + UDVM_address ) & 0xffff;
1456                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1457                                 udvm_tvb, start_offset, len, value);
1458                         break;
1459                 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1460
1461                 break;
1462
1463                 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1464                         /* #n */
1465                         offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1466                         len = offset - start_offset;
1467                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, 
1468                                 udvm_tvb, start_offset, len, value);
1469
1470                         /* Number of addresses in the instruction */
1471                         n = value;
1472                         /* %j */
1473                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1474                         len = offset - start_offset;
1475                         if ( is_memory_address ){
1476                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_j, 
1477                                         udvm_tvb, start_offset, len, value);
1478                         }else{
1479                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_j, 
1480                                         udvm_tvb, start_offset, len, value);
1481                         }
1482
1483                         while ( n > 0) {
1484                                 n = n -1;
1485                                 /* @address_n-1 */
1486                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address);
1487                                 len = offset - start_offset;
1488                                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1489                                 value = ( value + UDVM_address ) & 0xffff;
1490                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1491                                         udvm_tvb, start_offset, len, value);
1492                         }
1493                         break;
1494                 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1495                         /* %value */
1496                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1497                         len = offset - start_offset;
1498                         if ( is_memory_address ){
1499                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value, 
1500                                         udvm_tvb, start_offset, len, value);
1501                         }else{
1502                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value, 
1503                                         udvm_tvb, start_offset, len, value);
1504                         }
1505
1506                         /* %position */
1507                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1508                         len = offset - start_offset;
1509                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position, 
1510                                 udvm_tvb, start_offset, len, value);
1511
1512                         /* %length */
1513                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1514                         len = offset - start_offset;
1515                         if ( is_memory_address ){
1516                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1517                                         udvm_tvb, start_offset, len, value);
1518                         }else{
1519                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1520                                         udvm_tvb, start_offset, len, value);
1521                         }
1522
1523                         /* @address */
1524                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1525                         len = offset - start_offset;
1526                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1527                         value = ( value + UDVM_address ) & 0xffff;
1528                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1529                                 udvm_tvb, start_offset, len, value);
1530                         break;
1531
1532
1533                 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1534                         /* %length */
1535                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1536                         len = offset - start_offset;
1537                         if ( is_memory_address ){
1538                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1539                                         udvm_tvb, start_offset, len, value);
1540                         }else{
1541                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1542                                         udvm_tvb, start_offset, len, value);
1543                         }
1544
1545                         /* %destination */
1546                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1547                         len = offset - start_offset;
1548                         if ( is_memory_address ){
1549                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, 
1550                                         udvm_tvb, start_offset, len, value);
1551                         }else{
1552                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, 
1553                                         udvm_tvb, start_offset, len, value);
1554                         }
1555
1556                         /* @address */
1557                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1558                         len = offset - start_offset;
1559                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1560                         value = ( value + UDVM_address ) & 0xffff;
1561                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1562                                 udvm_tvb, start_offset, len, value);
1563                         break;
1564                 case SIGCOMP_INSTR_INPUT_BITS:/* 29   INPUT-BITS (%length, %destination, @address) */
1565                         /* %length */
1566                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1567                         len = offset - start_offset;
1568                         if ( is_memory_address ){
1569                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_length, 
1570                                         udvm_tvb, start_offset, len, value);
1571                         }else{
1572                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length, 
1573                                         udvm_tvb, start_offset, len, value);
1574                         }
1575
1576                         /* %destination */
1577                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1578                         len = offset - start_offset;
1579                         if ( is_memory_address ){
1580                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, 
1581                                         udvm_tvb, start_offset, len, value);
1582                         }else{
1583                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, 
1584                                         udvm_tvb, start_offset, len, value);
1585                         }
1586
1587                         /* @address */
1588                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1589                         len = offset - start_offset;
1590                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1591                         value = ( value + UDVM_address ) & 0xffff;
1592                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1593                                 udvm_tvb, start_offset, len, value);
1594                         break;
1595                 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
1596                         /*
1597                          * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
1598                          *  %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
1599                          *  %upper_bound_n, %uncompressed_n)
1600                          */
1601                         /* %destination */
1602                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1603                         len = offset - start_offset;
1604                         if ( is_memory_address ){
1605                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_destination, 
1606                                         udvm_tvb, start_offset, len, value);
1607                         }else{
1608                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination, 
1609                                         udvm_tvb, start_offset, len, value);
1610                         }
1611                         /* @address */
1612                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1613                         len = offset - start_offset;
1614                          /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1615                         value = ( value + UDVM_address ) & 0xffff;
1616                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address, 
1617                                 udvm_tvb, start_offset, len, value);
1618                         /* #n */
1619                         offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
1620                         len = offset - start_offset;
1621                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num, 
1622                                 udvm_tvb, start_offset, len, value);
1623                         n = value;
1624                         while ( n > 0) {
1625                                 n = n -1;
1626                                 /* %bits_n */
1627                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1628                                 len = offset - start_offset;
1629                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_bits, 
1630                                         udvm_tvb, start_offset, len, value);
1631                                 /* %lower_bound_n*/
1632                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1633                                 len = offset - start_offset;
1634                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_lower_bound, 
1635                                         udvm_tvb, start_offset, len, value);
1636                                 /* %upper_bound_n */
1637                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1638                                 len = offset - start_offset;
1639                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_upper_bound, 
1640                                         udvm_tvb, start_offset, len, value);
1641                                 /* %uncompressed_n */
1642                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
1643                                 len = offset - start_offset;
1644                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_uncompressed, 
1645                                         udvm_tvb, start_offset, len, value);
1646                         }
1647                         break;
1648
1649                 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
1650                         /*   STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
1651                          * %state_begin, %state_length, %state_address, %state_instruction)
1652                          */
1653
1654                         /* 
1655                          * %partial_identifier_start
1656                          */
1657                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
1658                         len = offset - start_offset;
1659                         proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start, 
1660                                 udvm_tvb, start_offset, len, value);
1661
1662                         /*
1663                          * %partial_identifier_length
1664                          */
1665                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
1666                         len = offset - start_offset;
1667                         proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length, 
1668                                 udvm_tvb, start_offset, len, value);
1669                         /*
1670                          * %state_begin
1671                          */
1672                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1673                         len = offset - start_offset;
1674                         proto_tree_add_uint(sigcomp_udvm_tree, hf_state_begin, 
1675                                 udvm_tvb, start_offset, len, value);
1676
1677                         /*
1678                          * %state_length
1679                          */
1680                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1681                         len = offset - start_offset;
1682                         if ( is_memory_address ) {
1683                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, 
1684                                         udvm_tvb, start_offset, len, value);
1685                         }else{
1686                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, 
1687                                         udvm_tvb, start_offset, len, value);
1688                         }
1689                         /*
1690                          * %state_address
1691                          */
1692                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
1693                         len = offset - start_offset;
1694                         if ( is_memory_address ) {
1695                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, 
1696                                         udvm_tvb, start_offset, len, value);
1697                         }else{
1698                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, 
1699                                         udvm_tvb, start_offset, len, value);
1700                         }
1701                         /*
1702                          * %state_instruction
1703                          */
1704                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1705                         len = offset - start_offset;
1706                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, 
1707                                 udvm_tvb, start_offset, len, value);
1708                         break;
1709                 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
1710                         /*
1711                          * STATE-CREATE (%state_length, %state_address, %state_instruction,
1712                          * %minimum_access_length, %state_retention_priority)
1713                          */
1714
1715                         /*
1716                          * %state_length
1717                          */
1718                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1719                         len = offset - start_offset;
1720                         if ( is_memory_address ) {
1721                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, 
1722                                         udvm_tvb, start_offset, len, value);
1723                         }else{
1724                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, 
1725                                         udvm_tvb, start_offset, len, value);
1726                         }
1727                         /*
1728                          * %state_address
1729                          */
1730                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1731                         len = offset - start_offset;
1732                         if ( is_memory_address ) {
1733                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, 
1734                                         udvm_tvb, start_offset, len, value);
1735                         }else{
1736                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, 
1737                                         udvm_tvb, start_offset, len, value);
1738                         }
1739                         /*
1740                          * %state_instruction
1741                          */
1742                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1743                         len = offset - start_offset;
1744                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, 
1745                                 udvm_tvb, start_offset, len, value);
1746                         /*
1747                          * %minimum_access_length
1748                          */
1749                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1750                         len = offset - start_offset;
1751                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len, 
1752                                 udvm_tvb, start_offset, len, value);
1753                         /*
1754                          * %state_retention_priority
1755                          */
1756                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1757                         len = offset - start_offset;
1758                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri, 
1759                                 udvm_tvb, start_offset, len, value);
1760
1761                         break;
1762                 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
1763                         /*
1764                          * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
1765                          */
1766                         /* 
1767                          * %partial_identifier_start
1768                          */
1769                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1770                         len = offset - start_offset;
1771                         proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start, 
1772                                 udvm_tvb, start_offset, len, value);
1773
1774                         /*
1775                          * %partial_identifier_length
1776                          */
1777                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1778                         len = offset - start_offset;
1779                         proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length, 
1780                                 udvm_tvb, start_offset, len, value);
1781                         break;
1782                 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
1783                         /* 
1784                          * %output_start
1785                          */
1786                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1787                         len = offset - start_offset;
1788                         if ( is_memory_address ) {
1789                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_output_start, 
1790                                         udvm_tvb, start_offset, len, value);
1791                         }else{
1792                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_start, 
1793                                         udvm_tvb, start_offset, len, value);
1794                         }
1795                         /* 
1796                          * %output_length
1797                          */
1798                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1799                         len = offset - start_offset;
1800                         if ( is_memory_address ) {
1801                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length_addr, 
1802                                         udvm_tvb, start_offset, len, value);
1803                         }else{
1804                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length, 
1805                                         udvm_tvb, start_offset, len, value);
1806                         }
1807                         break;
1808                 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
1809                         /*
1810                          * END-MESSAGE (%requested_feedback_location,
1811                          * %returned_parameters_location, %state_length, %state_address,
1812                          * %state_instruction, %minimum_access_length,
1813                          * %state_retention_priority)
1814                          */
1815                         /* %requested_feedback_location */
1816                         if ((msg_length-1) < offset){
1817                                 item2 = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, 0, -1,
1818                                                 "All remaining parameters = 0(Not in the uploaded code as UDVM buffer initialized to Zero");
1819                                 PROTO_ITEM_SET_GENERATED(item2);
1820                                 return;
1821                         }
1822                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1823                         len = offset - start_offset;
1824                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_req_feedback_loc, 
1825                                 udvm_tvb, start_offset, len, value);
1826                         /* returned_parameters_location */
1827                         if ((msg_length-1) < offset){
1828                                 item2 = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset-1, -1,
1829                                                 "All remaining parameters = 0(Not in the uploaded code as UDVM buffer initialized to Zero");
1830                                 PROTO_ITEM_SET_GENERATED(item2);
1831                                 return;
1832                         }
1833                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1834                         len = offset - start_offset;
1835                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ret_param_loc, 
1836                                 udvm_tvb, start_offset, len, value);
1837                         /*
1838                          * %state_length
1839                          */
1840                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1841                         len = offset - start_offset;
1842                         if ( is_memory_address ) {
1843                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr, 
1844                                         udvm_tvb, start_offset, len, value);
1845                         }else{
1846                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length, 
1847                                         udvm_tvb, start_offset, len, value);
1848                         }
1849                         /*
1850                          * %state_address
1851                          */
1852                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1853                         len = offset - start_offset;
1854                         if ( is_memory_address ) {
1855                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr, 
1856                                         udvm_tvb, start_offset, len, value);
1857                         }else{
1858                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address, 
1859                                         udvm_tvb, start_offset, len, value);
1860                         }
1861                         /*
1862                          * %state_instruction
1863                          */
1864                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1865                         len = offset - start_offset;
1866                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr, 
1867                                 udvm_tvb, start_offset, len, value);
1868                         /*
1869                          * %minimum_access_length
1870                          */
1871                         offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1872                         len = offset - start_offset;
1873                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len, 
1874                                 udvm_tvb, start_offset, len, value);
1875                         /*
1876                          * %state_retention_priority
1877                          */
1878                         if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ){
1879                                 offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
1880                                 len = offset - start_offset;
1881                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri, 
1882                                         udvm_tvb, start_offset, len, value);
1883                         }else{
1884                                 item2 = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, 1,
1885                                                 "state_retention_priority = 0(Not in the uploaded code as UDVM buffer initialized to Zero");
1886                                 PROTO_ITEM_SET_GENERATED(item2);
1887                         }
1888                         if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ){
1889                                 len = tvb_reported_length_remaining(udvm_tvb, offset);
1890                                 UDVM_address = start_address + offset;
1891                                 proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, len,
1892                                                 "Remaining %u bytes starting at UDVM addr %u (0x%x)- State information ?",len, UDVM_address, UDVM_address);
1893                         }
1894                         offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);                      
1895                         break;
1896
1897                 default:
1898                         offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);                      
1899                         break;
1900                 }
1901
1902                 
1903         } 
1904         return;
1905 }
1906  /*  The simplest operand type is the literal (#), which encodes a
1907   * constant integer from 0 to 65535 inclusive.  A literal operand may
1908   * require between 1 and 3 bytes depending on its value.
1909   * Bytecode:                       Operand value:      Range:
1910   * 0nnnnnnn                        N                   0 - 127
1911   * 10nnnnnn nnnnnnnn               N                   0 - 16383
1912   * 11000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
1913   *
1914   *            Figure 8: Bytecode for a literal (#) operand
1915   *
1916   */
1917 static int
1918 dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
1919                                                            gint offset, gint *start_offset, guint16 *value)
1920 {
1921         guint bytecode;
1922         guint16 operand;
1923         guint test_bits;
1924         guint display_bytecode;
1925
1926         bytecode = tvb_get_guint8(udvm_tvb, offset);
1927         test_bits = bytecode >> 7;
1928         if (test_bits == 1){
1929                 test_bits = bytecode >> 6;
1930                 if (test_bits == 2){
1931                         /*
1932                          * 10nnnnnn nnnnnnnn               N                   0 - 16383
1933                          */
1934                         display_bytecode = bytecode & 0xc0;
1935                         if ( display_udvm_bytecode )
1936                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
1937                                         udvm_tvb, offset, 1, display_bytecode);
1938                         operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff;
1939                         *value = operand;
1940                         *start_offset = offset;
1941                         offset = offset + 2;
1942
1943                 }else{
1944                         /*
1945                          * 111000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
1946                          */
1947                         display_bytecode = bytecode & 0xc0;
1948                         if ( display_udvm_bytecode )
1949                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
1950                                         udvm_tvb, offset, 1, display_bytecode);
1951                         offset ++;
1952                         operand = tvb_get_ntohs(udvm_tvb, offset);
1953                         *value = operand;
1954                         *start_offset = offset;
1955                         offset = offset + 2;
1956
1957                 }
1958         }else{
1959                 /*
1960                  * 0nnnnnnn                        N                   0 - 127
1961                  */
1962                 display_bytecode = bytecode & 0xc0;
1963                 if ( display_udvm_bytecode )
1964                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
1965                                 udvm_tvb, offset, 1, display_bytecode);
1966                 operand = ( bytecode & 0x7f);
1967                 *value = operand;
1968                 *start_offset = offset;
1969                 offset ++;
1970         }
1971
1972         return offset;
1973
1974 }
1975 /*
1976  * The second operand type is the reference ($), which is always used to
1977  * access a 2-byte value located elsewhere in the UDVM memory.  The
1978  * bytecode for a reference operand is decoded to be a constant integer
1979  * from 0 to 65535 inclusive, which is interpreted as the memory address
1980  * containing the actual value of the operand.
1981  * Bytecode:                       Operand value:      Range:
1982  *
1983  * 0nnnnnnn                        memory[2 * N]       0 - 65535
1984  * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
1985  * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
1986  *
1987  *            Figure 9: Bytecode for a reference ($) operand
1988  */
1989 static int
1990 dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
1991                                                            gint offset, gint *start_offset, guint16 *value)
1992 {
1993         guint bytecode;
1994         guint16 operand;
1995         guint test_bits;
1996         guint display_bytecode;
1997
1998         bytecode = tvb_get_guint8(udvm_tvb, offset);
1999         test_bits = bytecode >> 7;
2000         if (test_bits == 1){
2001                 test_bits = bytecode >> 6;
2002                 if (test_bits == 2){
2003                         /*
2004                          * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
2005                          */
2006                         display_bytecode = bytecode & 0xc0;
2007                         if ( display_udvm_bytecode )
2008                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
2009                                         udvm_tvb, offset, 1, display_bytecode);
2010                         operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff;
2011                         *value = (operand * 2);
2012                         *start_offset = offset;
2013                         offset = offset + 2;
2014
2015                 }else{
2016                         /*
2017                          * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2018                          */
2019                         display_bytecode = bytecode & 0xc0;
2020                         if ( display_udvm_bytecode )
2021                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
2022                                         udvm_tvb, offset, 1, display_bytecode);
2023                         offset ++;
2024                         operand = tvb_get_ntohs(udvm_tvb, offset);
2025                         *value = operand;
2026                         *start_offset = offset;
2027                         offset = offset + 2;
2028
2029                 }
2030         }else{
2031                 /*
2032                  * 0nnnnnnn                        memory[2 * N]       0 - 65535
2033                  */
2034                 display_bytecode = bytecode & 0xc0;
2035                 if ( display_udvm_bytecode )
2036                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
2037                                 udvm_tvb, offset, 1, display_bytecode);
2038                 operand = ( bytecode & 0x7f);
2039                 *value = (operand * 2);
2040                 *start_offset = offset;
2041                 offset ++;
2042         }
2043
2044         return offset;
2045 }
2046
2047 /*
2048  *The fourth operand type is the address (@).  This operand is decoded
2049  * as a multitype operand followed by a further step: the memory address
2050  * of the UDVM instruction containing the address operand is added to
2051  * obtain the correct operand value.  So if the operand value from
2052  * Figure 10 is D then the actual operand value of an address is
2053  * calculated as follows:
2054  *
2055  * operand_value = (is_memory_address_of_instruction + D) modulo 2^16
2056  * TODO calculate correct value for operand in case of ADDR
2057  */
2058 static int
2059 dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, 
2060                                                            gint offset, gboolean is_addr _U_, gint *start_offset, guint16 *value, gboolean *is_memory_address )
2061 {
2062         guint bytecode;
2063         guint display_bytecode;
2064         guint16 operand;
2065         guint32 result;
2066         guint test_bits;
2067         /* RFC3320
2068          * Figure 10: Bytecode for a multitype (%) operand
2069          * Bytecode:                       Operand value:      Range:               HEX val
2070          * 00nnnnnn                        N                   0 - 63                           0x00
2071          * 01nnnnnn                        memory[2 * N]       0 - 65535                        0x40
2072          * 1000011n                        2 ^ (N + 6)        64 , 128                          0x86    
2073          * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768                     0x88
2074          * 111nnnnn                        N + 65504       65504 - 65535                        0xe0
2075          * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535                        0x90
2076          * 101nnnnn nnnnnnnn               N                   0 - 8191                         0xa0
2077          * 110nnnnn nnnnnnnn               memory[N]           0 - 65535                        0xc0
2078          * 10000000 nnnnnnnn nnnnnnnn      N                   0 - 65535                        0x80
2079          * 10000001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535                        0x81
2080          */
2081         *is_memory_address = FALSE; 
2082         bytecode = tvb_get_guint8(udvm_tvb, offset);
2083         test_bits = ( bytecode & 0xc0 ) >> 6;
2084         switch (test_bits ){
2085         case 0:
2086                 /*  
2087                  * 00nnnnnn                        N                   0 - 63
2088                  */
2089                 display_bytecode = bytecode & 0xc0;
2090                 if ( display_udvm_bytecode )
2091                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2092                         udvm_tvb, offset, 1, display_bytecode);
2093                 operand = ( bytecode & 0x3f);
2094                 *value = operand;
2095                 *start_offset = offset;
2096                 offset ++;
2097                 break;
2098         case 1:
2099                 /*  
2100                  * 01nnnnnn                        memory[2 * N]       0 - 65535
2101                  */
2102                 display_bytecode = bytecode & 0xc0;
2103                 if ( display_udvm_bytecode )
2104                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2105                                 udvm_tvb, offset, 1, display_bytecode);
2106                 operand = ( bytecode & 0x3f) * 2;
2107                 *is_memory_address = TRUE;
2108                 *value = operand;
2109                 *start_offset = offset;
2110                 offset ++;
2111                 break;
2112         case 2:
2113                 /* Check tree most significant bits */
2114                 test_bits = ( bytecode & 0xe0 ) >> 5;
2115                 if ( test_bits == 5 ){
2116                 /*
2117                  * 101nnnnn nnnnnnnn               N                   0 - 8191
2118                  */
2119                         display_bytecode = bytecode & 0xe0;
2120                         if ( display_udvm_bytecode )
2121                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2122                                         udvm_tvb, offset, 1, display_bytecode);
2123                         operand = tvb_get_ntohs(udvm_tvb, offset) & 0x1fff;
2124                         *value = operand;
2125                         *start_offset = offset;
2126                         offset = offset + 2;
2127                 }else{
2128                         test_bits = ( bytecode & 0xf0 ) >> 4;
2129                         if ( test_bits == 9 ){
2130                 /*
2131                  * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535
2132                  */
2133                                 display_bytecode = bytecode & 0xf0;
2134                                 if ( display_udvm_bytecode )
2135                                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2136                                                         udvm_tvb, offset, 1, display_bytecode);
2137                                 operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x0fff) + 61440;
2138                                 *start_offset = offset;
2139                                 *value = operand;
2140                                 offset = offset + 2;
2141                         }else{
2142                                 test_bits = ( bytecode & 0x08 ) >> 3;
2143                                 if ( test_bits == 1){
2144                 /*
2145                  * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768
2146                  */
2147                                         display_bytecode = bytecode & 0xf8;
2148                                         if ( display_udvm_bytecode )
2149                                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2150                                                                 udvm_tvb, offset, 1, display_bytecode);
2151                                         result = (guint32)pow(2,( bytecode & 0x07) + 8);
2152                                         operand = result & 0xffff;
2153                                         *start_offset = offset;
2154                                         *value = operand;
2155                                         offset ++;
2156                                 }else{
2157                                         test_bits = ( bytecode & 0x0e ) >> 1;
2158                                         if ( test_bits == 3 ){
2159                                                 /*
2160                                                  * 1000 011n                        2 ^ (N + 6)        64 , 128
2161                                                  */
2162                                                 display_bytecode = bytecode & 0xfe;
2163                                                 if ( display_udvm_bytecode )
2164                                                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2165                                                                 udvm_tvb, offset, 1, display_bytecode);
2166                                                 result = (guint32)pow(2,( bytecode & 0x01) + 6);
2167                                                 operand = result & 0xffff;
2168                                                 *start_offset = offset;
2169                                                 *value = operand;
2170                                                 offset ++;
2171                                         }else{
2172                                         /*
2173                                          * 1000 0000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2174                                          * 1000 0001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2175                                          */
2176                                                 display_bytecode = bytecode;
2177                                                 if ( display_udvm_bytecode )
2178                                                         proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2179                                                                 udvm_tvb, offset, 1, display_bytecode);
2180                                                 if ( (bytecode & 0x01) == 1 )
2181                                                         *is_memory_address = TRUE;
2182                                                 offset ++;
2183                                                 operand = tvb_get_ntohs(udvm_tvb, offset);
2184                                                 *value = operand;
2185                                                 *start_offset = offset;
2186                                                 offset = offset +2;
2187                                         }
2188
2189
2190                                 }
2191                         }
2192                 }
2193                 break;
2194
2195         case 3:
2196                 test_bits = ( bytecode & 0x20 ) >> 5;
2197                 if ( test_bits == 1 ){
2198                 /*
2199                  * 111nnnnn                        N + 65504       65504 - 65535
2200                  */
2201                         display_bytecode = bytecode & 0xe0;
2202                         if ( display_udvm_bytecode )
2203                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2204                                                 udvm_tvb, offset, 1, display_bytecode);
2205                         operand = ( bytecode & 0x1f) + 65504;
2206                         *start_offset = offset;
2207                         *value = operand;
2208                         offset ++;
2209                 }else{
2210                 /*
2211                  * 110nnnnn nnnnnnnn               memory[N]           0 - 65535
2212                  */
2213                         display_bytecode = bytecode & 0xe0;
2214                         if ( display_udvm_bytecode )
2215                                 proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
2216                                                 udvm_tvb, offset, 1, display_bytecode);
2217                         operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x1fff);
2218                         *is_memory_address = TRUE;
2219                         *start_offset = offset;
2220                         *value = operand;
2221                         offset = offset +2;
2222                 }
2223                         
2224         default :
2225                 break;
2226         }
2227         return offset;
2228 }
2229
2230 static void
2231 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
2232 {
2233         proto_tree *raw_tree = NULL;
2234         proto_item *ti = NULL;
2235         int offset, next_offset, linelen;
2236
2237         if(tree) {
2238                 ti = proto_tree_add_item(tree, proto_raw_sigcomp, tvb, 0, -1, FALSE);
2239                 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
2240         }
2241
2242         offset = 0;
2243
2244         while (tvb_offset_exists(tvb, offset)) {
2245                 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2246                 linelen = next_offset - offset;
2247                 if(raw_tree) {
2248                         proto_tree_add_text(raw_tree, tvb, offset, linelen,
2249                             "%s", tvb_format_text(tvb, offset, linelen));
2250                 }
2251                 offset = next_offset;
2252         }
2253 }
2254
2255 /* Register the protocol with Wireshark */
2256
2257
2258 /* If this dissector uses sub-dissector registration add a registration routine.
2259    This format is required because a script is used to find these routines and
2260    create the code that calls these routines.
2261 */
2262 void
2263 proto_reg_handoff_sigcomp(void)
2264 {
2265         static dissector_handle_t sigcomp_handle;
2266         static dissector_handle_t sigcomp_tcp_handle;
2267         static gboolean Initialized=FALSE;
2268         static guint udp_port1;
2269         static guint udp_port2;
2270         static guint tcp_port1;
2271         static guint tcp_port2;
2272
2273         if (!Initialized) {
2274                 sigcomp_handle = find_dissector("sigcomp");
2275                 sigcomp_tcp_handle = new_create_dissector_handle(dissect_sigcomp_tcp,proto_sigcomp);
2276                 sip_handle = find_dissector("sip");
2277                 Initialized=TRUE;
2278         }else{
2279                 dissector_delete("udp.port", udp_port1, sigcomp_handle);
2280                 dissector_delete("udp.port", udp_port2, sigcomp_handle);
2281                 dissector_delete("tcp.port", tcp_port1, sigcomp_tcp_handle);
2282                 dissector_delete("tcp.port", tcp_port2, sigcomp_tcp_handle);
2283         }
2284
2285         udp_port1 = SigCompUDPPort1;
2286         udp_port2 = SigCompUDPPort2;
2287         tcp_port1 = SigCompTCPPort1;
2288         tcp_port2 = SigCompTCPPort2;
2289
2290
2291         dissector_add("udp.port", SigCompUDPPort1, sigcomp_handle);
2292         dissector_add("udp.port", SigCompUDPPort2, sigcomp_handle);
2293         dissector_add("tcp.port", SigCompTCPPort1, sigcomp_tcp_handle);
2294         dissector_add("tcp.port", SigCompTCPPort2, sigcomp_tcp_handle);
2295
2296 }
2297
2298 /* this format is require because a script is used to build the C function
2299    that calls all the protocol registration.
2300 */
2301
2302 void
2303 proto_register_sigcomp(void)
2304 {                 
2305
2306 /* Setup list of header fields  See Section 1.6.1 for details*/
2307         static hf_register_info hf[] = {
2308                 { &hf_sigcomp_t_bit,
2309                         { "T bit", "sigcomp.t.bit",
2310                         FT_UINT8, BASE_DEC, NULL, 0x04,          
2311                         "Sigcomp T bit", HFILL }
2312                 },
2313                 { &hf_sigcomp_len,
2314                         { "Partial state id length","sigcomp.length",
2315                         FT_UINT8, BASE_HEX, VALS(&length_encoding_vals), 0x03,          
2316                         "Sigcomp length", HFILL }
2317                 },
2318                 { &hf_sigcomp_returned_feedback_item,
2319                         { "Returned_feedback item", "sigcomp.returned.feedback.item",
2320                         FT_BYTES, BASE_NONE, NULL, 0x0,          
2321                         "Returned feedback item", HFILL }
2322                 },
2323                 { &hf_sigcomp_partial_state,
2324                         { "Partial state identifier", "sigcomp.partial.state.identifier",
2325                         FT_STRING, BASE_NONE, NULL, 0x0,          
2326                         NULL, HFILL }
2327                 },
2328                 { &hf_sigcomp_remaining_message_bytes,
2329                         { "Remaining SigComp message bytes", "sigcomp.remaining-bytes",
2330                         FT_UINT32, BASE_DEC, NULL, 0x0,          
2331                         "Number of bytes remaining in message", HFILL }
2332                 },
2333                 { &hf_sigcomp_compression_ratio,
2334                         { "Compression ratio (%)", "sigcomp.compression-ratio",
2335                         FT_UINT32, BASE_DEC, NULL, 0x0,          
2336                         "Compression ratio (decompressed / compressed) %", HFILL }
2337                 },
2338                 { &hf_sigcomp_returned_feedback_item_len,
2339                         { "Returned feedback item length", "sigcomp.returned.feedback.item.len",
2340                         FT_UINT8, BASE_DEC, NULL, 0x7f,          
2341                         NULL, HFILL }
2342                 },
2343                 { &hf_sigcomp_code_len,
2344                         { "Code length","sigcomp.code.len",
2345                         FT_UINT16, BASE_HEX, NULL, 0xfff0,          
2346                         NULL, HFILL }
2347                 },
2348                 { &hf_sigcomp_destination,
2349                         { "Destination","sigcomp.destination",
2350                         FT_UINT8, BASE_HEX, VALS(&destination_address_encoding_vals), 0xf,          
2351                         NULL, HFILL }
2352                 },
2353                 { &hf_sigcomp_udvm_bytecode,
2354                         { "Uploaded UDVM bytecode","sigcomp.udvm.byte-code",
2355                         FT_NONE, BASE_NONE, NULL, 0x0,          
2356                         NULL, HFILL }
2357                 },
2358                 { &hf_sigcomp_udvm_instr,
2359                         { "UDVM instruction code","sigcomp.udvm.instr",
2360                         FT_UINT8, BASE_DEC, VALS(&udvm_instruction_code_vals), 0x0,          
2361                         NULL, HFILL }
2362                 },
2363                 { &hf_udvm_execution_trace,
2364                         { "UDVM execution trace","sigcomp.udvm.execution-trace",
2365                         FT_NONE, BASE_NONE, NULL, 0x0,          
2366                         NULL, HFILL }
2367                 },
2368                 { &hf_udvm_multitype_bytecode,
2369                         { "UDVM bytecode", "sigcomp.udvm.multyt.bytecode",
2370                         FT_UINT8, BASE_HEX, VALS(&display_bytecode_vals), 0x0,          
2371                         NULL, HFILL }
2372                 },
2373                 { &hf_udvm_reference_bytecode,
2374                         { "UDVM bytecode", "sigcomp.udvm.ref.bytecode",
2375                         FT_UINT8, BASE_HEX, VALS(&display_ref_bytecode_vals), 0x0,          
2376                         NULL, HFILL }
2377                 },
2378                 { &hf_udvm_literal_bytecode,
2379                         { "UDVM bytecode", "sigcomp.udvm.lit.bytecode",
2380                         FT_UINT8, BASE_HEX, VALS(&display_lit_bytecode_vals), 0x0,          
2381                         NULL, HFILL }
2382                 },
2383                 { &hf_udvm_operand,
2384                         { "UDVM operand", "sigcomp.udvm.operand",
2385                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2386                         NULL, HFILL }
2387                 },
2388                 { &hf_udvm_length,
2389                         { "%Length", "sigcomp.udvm.length",
2390                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2391                         "Length", HFILL }
2392                 },
2393                 { &hf_udvm_addr_length,
2394                         { "%Length[memory address]", "sigcomp.udvm.addr.length",
2395                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2396                         "Length", HFILL }
2397                 },
2398                 { &hf_udvm_destination,
2399                         { "%Destination", "sigcomp.udvm.destination",
2400                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2401                         "Destination", HFILL }
2402                 },
2403                 { &hf_udvm_addr_destination,
2404                         { "%Destination[memory address]", "sigcomp.udvm.addr.destination",
2405                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2406                         "Destination", HFILL }
2407                 },
2408                 { &hf_udvm_at_address,
2409                         { "@Address(mem_add_of_inst + D) mod 2^16)", "sigcomp.udvm.at.address",
2410                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2411                         "Address", HFILL }
2412                 },
2413                 { &hf_udvm_address,
2414                         { "%Address", "sigcomp.udvm.length",
2415                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2416                         "Address", HFILL }
2417                 },
2418                 { &hf_udvm_literal_num,
2419                         { "#n", "sigcomp.udvm.literal-num",
2420                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2421                         "Literal number", HFILL }
2422                 },
2423                 { &hf_udvm_value,
2424                         { "%Value", "sigcomp.udvm.value",
2425                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2426                         "Value", HFILL }
2427                 },
2428                 { &hf_udvm_addr_value,
2429                         { "%Value[memory address]", "sigcomp.udvm.value",
2430                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2431                         "Value", HFILL }
2432                 },
2433                 { &hf_partial_identifier_start,
2434                         { "%Partial identifier start", "sigcomp.udvm.partial.identifier.start",
2435                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2436                         "Partial identifier start", HFILL }
2437                 },
2438                 { &hf_partial_identifier_length,
2439                         { "%Partial identifier length", "sigcomp.udvm.partial.identifier.length",
2440                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2441                         "Partial identifier length", HFILL }
2442                 },
2443                 { &hf_state_begin,
2444                         { "%State begin", "sigcomp.udvm.state.begin",
2445                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2446                         "State begin", HFILL }
2447                 },
2448                 { &hf_udvm_state_length,
2449                         { "%State length", "sigcomp.udvm.state.length",
2450                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2451                         "State length", HFILL }
2452                 },
2453
2454                 { &hf_udvm_state_length_addr,
2455                         { "%State length[memory address]", "sigcomp.udvm.state.length.addr",
2456                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2457                         "State length", HFILL }
2458                 },
2459                 { &hf_udvm_state_address,
2460                         { "%State address", "sigcomp.udvm.start.address",
2461                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2462                         "State address", HFILL }
2463                 },
2464                 { &hf_udvm_state_address_addr,
2465                         { "%State address[memory address]", "sigcomp.udvm.start.address.addr",
2466                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2467                         "State address", HFILL }
2468                 },
2469                 { &hf_udvm_state_instr,
2470                         { "%State instruction", "sigcomp.udvm.start.instr",
2471                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2472                         "State instruction", HFILL }
2473                 },
2474                 { &hf_udvm_operand_1,
2475                         { "$Operand 1[memory address]", "sigcomp.udvm.operand.1",
2476                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2477                         "Reference $ Operand 1", HFILL }
2478                 },
2479                 { &hf_udvm_operand_2,
2480                         { "%Operand 2", "sigcomp.udvm.operand.2",
2481                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2482                         "Operand 2", HFILL }
2483                 },
2484                 { &hf_udvm_operand_2_addr,
2485                         { "%Operand 2[memory address]", "sigcomp.udvm.operand.2.addr",
2486                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2487                         "Operand 2", HFILL }
2488                 },
2489                 { &hf_udvm_j,
2490                         { "%j", "sigcomp.udvm.j",
2491                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2492                         "j", HFILL }
2493                 },
2494                 { &hf_udvm_addr_j,
2495                         { "%j[memory address]", "sigcomp.udvm.addr.j",
2496                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2497                         "j", HFILL }
2498                 },
2499                 { &hf_udvm_output_start,
2500                         { "%Output_start", "sigcomp.output.start",
2501                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2502                         "Output start", HFILL }
2503                 },
2504                 { &hf_udvm_addr_output_start,
2505                         { "%Output_start[memory address]", "sigcomp.addr.output.start",
2506                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2507                         "Output start", HFILL }
2508                 },
2509                 { &hf_udvm_output_length,
2510                         { "%Output_length", "sigcomp.output.length",
2511                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2512                         "Output length", HFILL }
2513                 },
2514                 { &hf_udvm_output_length_addr,
2515                         { "%Output_length[memory address]", "sigcomp.output.length.addr",
2516                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2517                         "Output length", HFILL }
2518                 },
2519                 { &hf_udvm_req_feedback_loc,
2520                         { "%Requested feedback location", "sigcomp.req.feedback.loc",
2521                         FT_UINT16, BASE_DEC, NULL, 0x0,
2522                         "Requested feedback location", HFILL }
2523                 },
2524                 { &hf_udvm_min_acc_len,
2525                         { "%Minimum access length", "sigcomp.min.acc.len",
2526                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2527                         "Minimum access length", HFILL }
2528                 },
2529                 { &hf_udvm_state_ret_pri,
2530                         { "%State retention priority", "sigcomp.udvm.state.ret.pri",
2531                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2532                         "State retention priority", HFILL }
2533                 },
2534                 { &hf_udvm_ret_param_loc,
2535                         { "%Returned parameters location", "sigcomp.ret.param.loc",
2536                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2537                         "Returned parameters location", HFILL }
2538                 },
2539                 { &hf_udvm_position,
2540                         { "%Position", "sigcomp.udvm.position",
2541                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2542                         "Position", HFILL }
2543                 },
2544                 { &hf_udvm_ref_dest,
2545                         { "$Destination[memory address]", "sigcomp.udvm.ref.destination",
2546                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2547                         "(reference)Destination", HFILL }
2548                 },
2549                 { &hf_udvm_bits,
2550                         { "%Bits", "sigcomp.udvm.bits",
2551                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2552                         "Bits", HFILL }
2553                 },
2554                 { &hf_udvm_lower_bound,
2555                         { "%Lower bound", "sigcomp.udvm.lower.bound",
2556                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2557                         "Lower_bound", HFILL }
2558                 },
2559                 { &hf_udvm_upper_bound,
2560                         { "%Upper bound", "sigcomp.udvm.upper.bound",
2561                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2562                         "Upper bound", HFILL }
2563                 },
2564                 { &hf_udvm_uncompressed,
2565                         { "%Uncompressed", "sigcomp.udvm.uncompressed",
2566                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2567                         "Uncompressed", HFILL }
2568                 },
2569                 { &hf_udvm_start_value,
2570                         { "%Start value", "sigcomp.udvm.start.value",
2571                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2572                         "Start value", HFILL }
2573                 },
2574                 { &hf_udvm_offset,
2575                         { "%Offset", "sigcomp.udvm.offset",
2576                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2577                         "Offset", HFILL }
2578                 },
2579                 { &hf_udvm_addr_offset,
2580                         { "%Offset[memory address]", "sigcomp.udvm.addr.offset",
2581                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2582                         "Offset", HFILL }
2583                 },
2584                 { &hf_sigcomp_nack_ver,
2585                         { "NACK Version", "sigcomp.nack.ver",
2586                         FT_UINT8, BASE_DEC, NULL, 0x0f,          
2587                         NULL, HFILL }
2588                 },
2589                 { &hf_sigcomp_nack_reason_code,
2590                         { "Reason Code", "sigcomp.nack.reason",
2591                         FT_UINT8, BASE_DEC, VALS(sigcomp_nack_reason_code_vals), 0x0,          
2592                         "NACK Reason Code", HFILL }
2593                 },
2594                 { &hf_sigcomp_nack_failed_op_code,
2595                         { "OPCODE of failed instruction", "sigcomp.nack.failed_op_code",
2596                         FT_UINT8, BASE_DEC, VALS(udvm_instruction_code_vals), 0x0,          
2597                         "NACK OPCODE of failed instruction", HFILL }
2598                 },
2599                 { &hf_sigcomp_nack_pc,
2600                         { "PC of failed instruction", "sigcomp.nack.pc",
2601                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2602                         "NACK PC of failed instruction", HFILL }
2603                 },
2604                 { &hf_sigcomp_nack_sha1,
2605                         { "SHA-1 Hash of failed message", "sigcomp.nack.sha1",
2606                         FT_BYTES, BASE_NONE, NULL, 0x0,          
2607                         "NACK SHA-1 Hash of failed message", HFILL }
2608                 },
2609                 { &hf_sigcomp_nack_state_id,
2610                         { "State ID (6 - 20 bytes)", "sigcomp.nack.state_id",
2611                         FT_BYTES, BASE_NONE, NULL, 0x0,          
2612                         "NACK State ID (6 - 20 bytes)", HFILL }
2613                 },
2614                 { &hf_sigcomp_nack_cycles_per_bit,
2615                         { "Cycles Per Bit", "sigcomp.nack.cycles_per_bit",
2616                         FT_UINT8, BASE_DEC, NULL, 0x0,          
2617                         "NACK Cycles Per Bit", HFILL }
2618                 },
2619                 { &hf_sigcomp_nack_memory_size,
2620                         { "Memory size", "sigcomp.memory_size",
2621                         FT_UINT16, BASE_DEC, NULL, 0x0,          
2622                         NULL, HFILL }
2623                 },
2624         };
2625
2626 /* Setup protocol subtree array */
2627         static gint *ett[] = {
2628                 &ett_sigcomp,
2629                 &ett_sigcomp_udvm,
2630                 &ett_sigcomp_udvm_exe,
2631         };
2632         static gint *ett_raw[] = {
2633                 &ett_raw_text,
2634         };
2635
2636         module_t *sigcomp_module;
2637     static enum_val_t udvm_detail_vals[] = {
2638         {"no-printout", "No-Printout", 0},
2639         {"low-detail", "Low-detail", 1},
2640         {"medium-detail", "Medium-detail", 2},
2641         {"high-detail", "High-detail", 3},
2642         {NULL, NULL, -1}
2643     };
2644
2645
2646 /* Register the protocol name and description */
2647         proto_sigcomp = proto_register_protocol("Signaling Compression",
2648             "SIGCOMP", "sigcomp");
2649         proto_raw_sigcomp = proto_register_protocol("Decompressed SigComp message as raw text",
2650                 "Raw_SigComp", "raw_sigcomp");
2651
2652         new_register_dissector("sigcomp", dissect_sigcomp, proto_sigcomp);
2653
2654 /* Required function calls to register the header fields and subtrees used */
2655         proto_register_field_array(proto_sigcomp, hf, array_length(hf));
2656         proto_register_subtree_array(ett, array_length(ett));
2657         proto_register_subtree_array(ett_raw, array_length(ett_raw));
2658
2659 /* Register a configuration option for port */
2660         sigcomp_module = prefs_register_protocol(proto_sigcomp,
2661                                                                                           proto_reg_handoff_sigcomp);
2662
2663         prefs_register_uint_preference(sigcomp_module, "udp.port",
2664                                                                    "Sigcomp UDP Port 1",
2665                                                                    "Set UDP port 1 for SigComp messages",
2666                                                                    10,
2667                                                                    &SigCompUDPPort1);
2668
2669         prefs_register_uint_preference(sigcomp_module, "udp.port2",
2670                                                                    "Sigcomp UDP Port 2",
2671                                                                    "Set UDP port 2 for SigComp messages",
2672                                                                    10,
2673                                                                    &SigCompUDPPort2);
2674         prefs_register_uint_preference(sigcomp_module, "tcp.port",
2675                                                                    "Sigcomp TCP Port 1",
2676                                                                    "Set TCP port 1 for SigComp messages",
2677                                                                    10,
2678                                                                    &SigCompTCPPort1);
2679
2680         prefs_register_uint_preference(sigcomp_module, "tcp.port2",
2681                                                                    "Sigcomp TCP Port 2",
2682                                                                    "Set TCP port 2 for SigComp messages",
2683                                                                    10,
2684                                                                    &SigCompTCPPort2);
2685         prefs_register_bool_preference(sigcomp_module, "display.udvm.code",
2686                                                                    "Dissect the UDVM code",
2687                                                                    "Preference whether to Dissect the UDVM code or not",
2688                                                                    &dissect_udvm_code);
2689
2690         prefs_register_bool_preference(sigcomp_module, "display.bytecode",
2691                                                                    "Display the bytecode of operands",
2692                                                                    "preference whether to display the bytecode in "
2693                                                                    "UDVM operands or not",
2694                                                                    &display_udvm_bytecode);
2695         prefs_register_bool_preference(sigcomp_module, "decomp.msg",
2696                                                                    "Decompress message",
2697                                                                    "preference whether to decompress message or not",
2698                                                                    &decompress);
2699         prefs_register_bool_preference(sigcomp_module, "display.decomp.msg.as.txt",
2700                                                                    "Displays the decompressed message as text",
2701                                                                    "preference whether to display the decompressed message "
2702                                                                    "as raw text or not",
2703                                                                    &display_raw_txt);
2704         prefs_register_enum_preference(sigcomp_module, "show.udvm.execution",
2705                                                                    "Level of detail of UDVM execution:",
2706                                                                    "'No-Printout' = UDVM executes silently, then increasing detail "
2707                                                                    "about execution of UDVM instructions; "
2708                                                                    "Warning! CPU intense at high detail",
2709                                                                    &udvm_print_detail_level, udvm_detail_vals, FALSE);
2710
2711         register_init_routine(&sigcomp_init_protocol);
2712
2713
2714
2715 }