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