967beaf22dc84e4bf8429475cd310eeca169add6
[obnox/wireshark/wip.git] / epan / dissectors / packet-vnc.c
1 /* packet-vnc.c
2  * Routines for VNC dissection (Virtual Network Computing)
3  * Copyright 2005, Ulf Lamping <ulf.lamping@web.de>
4  * Copyright 2006-2007, Stephen Fisher <stephentfisher@yahoo.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /* Dissection of the VNC (Virtual Network Computing) network traffic.
28  *
29  * All versions of RealVNC and TightVNC are supported.
30  * Note: The addition of TightVNC support is not yet complete.
31  *
32  * Several VNC implementations available, see:
33  * http://www.realvnc.com/
34  * http://www.tightvnc.com/
35  * http://ultravnc.sourceforge.net/
36  * ...
37  *
38  * The protocol itself is known as RFB - Remote Frame Buffer Protocol.
39  *
40  * This code is based on the protocol specification:
41  *   http://www.realvnc.com/docs/rfbproto.pdf
42  *  and the RealVNC free edition & TightVNC source code
43  */
44
45 #ifdef HAVE_CONFIG_H
46 # include "config.h"
47 #endif
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <math.h>
53 #include <glib.h>
54
55 #include <epan/conversation.h>
56 #include <epan/emem.h>
57 #include <epan/packet.h>
58 #include <epan/prefs.h>
59 #include "packet-x11-keysym.h" /* This contains the X11 value_string
60                                 * "keysym_vals_source" that VNC also uses. */
61
62
63 static const value_string security_types_vs[] = {
64         { 0,  "Invalid"  },
65         { 1,  "None"     },
66         { 2,  "VNC"      },
67         { 5,  "RA2"      },
68         { 6,  "RA2ne"    },
69         { 16, "Tight"    },
70         { 17, "Ultra"    },
71         { 18, "TLS"      },
72         { 19, "VeNCrypt" },
73         { 0,  NULL       }
74 };
75
76 typedef enum {
77         INVALID  = 0,
78         NONE     = 1,
79         VNC      = 2,
80         RA2      = 5,
81         RA2ne    = 6,
82         TIGHT    = 16,
83         ULTRA    = 17,
84         TLS      = 18,
85         VENCRYPT = 19
86 } security_types_e;
87
88 static const value_string auth_result_vs[] = {
89         { 0, "OK"     },
90         { 1, "Failed" },
91         { 0,  NULL    }
92 };
93
94 static const value_string yes_no_vs[] = {
95         { 0, "No"  },
96         { 1, "Yes" },
97         { 0,  NULL }
98 };
99
100 static const value_string client_message_types_vs[] = {
101         { 0, "Set Pixel Format"           },
102         { 2, "Set Encodings"              },
103         { 3, "Framebuffer Update Request" },
104         { 4, "Key Event"                  },
105         { 5, "Pointer Event"              },
106         { 6, "Cut Text"                   },
107         { 0,  NULL                        }
108 };
109
110 static const value_string server_message_types_vs[] = {
111         { 0, "Framebuffer Update"   },
112         { 1, "Set Colormap Entries" },
113         { 2, "Ring Bell"            },
114         { 3, "Cut Text"             },
115         { 0,  NULL                  }
116 };
117
118 static const value_string button_mask_vs[] = {
119         { 0, "Not pressed" },
120         { 1, "Pressed"     },
121         { 0,  NULL         }
122 };
123
124 typedef enum {
125         ENCODING_DESKTOP_SIZE   = -223,
126         ENCODING_LAST_RECT      = -224,
127         ENCODING_POINTER_POS    = -232,
128         ENCODING_RICH_CURSOR    = -239,
129         ENCODING_X_CURSOR       = -240,
130         ENCODING_RAW            = 0,
131         ENCODING_COPY_RECT      = 1,
132         ENCODING_RRE            = 2,
133         ENCODING_CORRE          = 4,
134         ENCODING_HEXTILE        = 5,
135         ENCODING_ZLIB           = 6,
136         ENCODING_TIGHT          = 7,
137         ENCODING_ZLIBHEX        = 8,
138         ENCODING_RLE            = 16,
139 } encoding_type_e;
140
141 static const value_string encoding_types_vs[] = {
142         { ENCODING_DESKTOP_SIZE,        "DesktopSize (pseudo)" },
143         { ENCODING_LAST_RECT,           "LastRect (pseudo)"    },
144         { ENCODING_POINTER_POS,         "Pointer pos (pseudo)" },
145         { ENCODING_RICH_CURSOR,         "Rich Cursor (pseudo)" },
146         { ENCODING_X_CURSOR,            "X Cursor (pseudo)"    },
147         { ENCODING_RAW,                 "Raw"                  },
148         { ENCODING_COPY_RECT,           "CopyRect"             },
149         { ENCODING_RRE,                 "RRE"                  },
150         { ENCODING_CORRE,               "CoRRE"                },
151         { ENCODING_HEXTILE,             "Hextile"              },
152         { ENCODING_ZLIB,                "Zlib"                 },
153         { ENCODING_TIGHT,               "Tight"                },
154         { ENCODING_ZLIBHEX,             "ZlibHex"              },
155         { ENCODING_RLE,                 "ZRLE"                 },
156         { 0,                            NULL                   }
157 };
158
159 /* Rectangle types for Tight encoding.  These come in the "control byte" at the
160  * start of a rectangle's payload.  Note that these are with respect to the most
161  * significant bits 4-7 of the control byte, so you must shift it to the right 4
162  * bits before comparing against these values.
163  */
164 #define TIGHT_RECT_FILL      0x08
165 #define TIGHT_RECT_JPEG      0x09
166 #define TIGHT_RECT_MAX_VALUE 0x09
167
168 #define TIGHT_RECT_EXPLICIT_FILTER_FLAG 0x04
169
170 /* Filter types for Basic encoding of Tight rectangles */
171 #define TIGHT_RECT_FILTER_COPY     0x00
172 #define TIGHT_RECT_FILTER_PALETTE  0x01
173 #define TIGHT_RECT_FILTER_GRADIENT 0x02
174
175 /* Minimum number of bytes to compress for Tight encoding */
176 #define TIGHT_MIN_BYTES_TO_COMPRESS 12
177
178 static const value_string tight_filter_ids_vs[] = {
179         { TIGHT_RECT_FILTER_COPY,     "Copy"     },
180         { TIGHT_RECT_FILTER_PALETTE,  "Palette"  },
181         { TIGHT_RECT_FILTER_GRADIENT, "Gradient" },
182         { 0, NULL }
183 };
184
185
186 typedef enum {
187         SERVER_VERSION,
188         CLIENT_VERSION,
189
190         SECURITY,
191         SECURITY_TYPES,
192
193         TIGHT_TUNNELING_CAPABILITIES,
194         TIGHT_TUNNEL_TYPE_REPLY,
195         TIGHT_AUTH_CAPABILITIES,
196         TIGHT_AUTH_TYPE_REPLY,
197         TIGHT_AUTH_TYPE_AND_VENDOR_CODE,
198         TIGHT_UNKNOWN_PACKET3,
199
200         VNC_AUTHENTICATION_CHALLENGE,
201         VNC_AUTHENTICATION_RESPONSE,
202
203         SECURITY_RESULT,
204
205         CLIENT_INIT,
206         SERVER_INIT,
207
208         TIGHT_INTERACTION_CAPS,
209         TIGHT_INTERACTION_CAPS_LIST,
210
211         NORMAL_TRAFFIC
212 } vnc_session_state_e;
213
214 /* This structure will be tied to each conversation. */
215 typedef struct {
216         guint8 security_type_selected;
217         gdouble server_proto_ver, client_proto_ver;
218         vnc_session_state_e vnc_next_state;
219
220         /* These are specific to TightVNC */
221         gint num_server_message_types;
222         gint num_client_message_types;
223         gint num_encoding_types;
224 } vnc_conversation_t;
225
226 /* This structure will be tied to each packet */
227 typedef struct {
228         guint8 bytes_per_pixel;
229         guint8 depth;
230         vnc_session_state_e state;
231         gint preferred_encoding;
232 } vnc_packet_t;
233
234 void proto_reg_handoff_vnc(void);
235
236 static gboolean vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo,
237                                      gint offset, proto_tree *tree,
238                                      vnc_conversation_t *per_conversation_info);
239 static void vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo,
240                                  gint *offset, proto_tree *tree);
241 static void vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo,
242                                  gint *offset, proto_tree *tree);
243 static void vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo,
244                                         gint *offset, proto_tree *tree);
245 static void vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo,
246                                      gint *offset, proto_tree *tree);
247 static void vnc_client_framebuffer_update_request(tvbuff_t *tvb,
248                                                   packet_info *pinfo,
249                                                   gint *offset,
250                                                   proto_tree *tree);
251 static void vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo,
252                                  gint *offset, proto_tree *tree);
253 static void vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo,
254                                      gint *offset, proto_tree *tree);
255 static void vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
256                                 proto_tree *tree);
257
258 static guint vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo,
259                                            gint *offset, proto_tree *tree);
260 static guint vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
261                               proto_tree *tree, guint16 width, guint16 height);
262 static guint vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo,
263                                    gint *offset, proto_tree *tree,
264                                    guint16 width, guint16 height);
265 static guint vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
266                               proto_tree *tree, guint16 width, guint16 height);
267 static guint vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo,
268                                   gint *offset, proto_tree *tree,
269                                   guint16 width, guint16 height);
270 static guint vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
271                                proto_tree *tree, guint16 width, guint16 height);
272 static guint vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
273                                 proto_tree *tree, guint16 width, guint16 height);
274 static guint vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
275                                       gint *offset, proto_tree *tree, guint16 width,
276                                       guint16 height);
277 static guint vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
278                                    gint *offset, proto_tree *tree, guint16 width,
279                                    guint16 height);
280 static guint vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo,
281                                              gint *offset, proto_tree *tree);
282 static void vnc_server_ring_bell(tvbuff_t *tvb, packet_info *pinfo,
283                                  gint *offset, proto_tree *tree);
284 static guint vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo,
285                                  gint *offset, proto_tree *tree);
286 static void vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel);
287 static void vnc_set_depth(packet_info *pinfo, guint8 depth);
288 static guint8 vnc_get_bytes_per_pixel(packet_info *pinfo);
289
290
291 #define DEST_PORT_VNC pinfo->destport == 5500 || pinfo->destport == 5501 || \
292                 pinfo->destport == 5900 || pinfo->destport == 5901 ||   \
293                 pinfo->destport == vnc_preference_alternate_port
294
295 #define VNC_BYTES_NEEDED(a)                                     \
296         if(a > (guint)tvb_length_remaining(tvb, *offset))       \
297                 return a;
298
299
300 /* Variables for our preferences */
301 static guint vnc_preference_alternate_port = 0;
302
303 /* Initialize the protocol and registered fields */
304 static int proto_vnc = -1; /* Protocol subtree */
305 static int hf_vnc_padding = -1;
306 static int hf_vnc_server_proto_ver = -1;
307 static int hf_vnc_client_proto_ver = -1;
308 static int hf_vnc_num_security_types = -1;
309 static int hf_vnc_security_type = -1;
310 static int hf_vnc_server_security_type = -1;
311 static int hf_vnc_client_security_type = -1;
312 static int hf_vnc_vendor_code = -1;
313 static int hf_vnc_security_type_string = -1;
314 static int hf_vnc_auth_challenge = -1;
315 static int hf_vnc_auth_response = -1;
316 static int hf_vnc_auth_result = -1;
317 static int hf_vnc_auth_error = -1;
318
319 static int hf_vnc_share_desktop_flag = -1;
320 static int hf_vnc_width = -1;
321 static int hf_vnc_height = -1;
322 static int hf_vnc_server_bits_per_pixel = -1;
323 static int hf_vnc_server_depth = -1;
324 static int hf_vnc_server_big_endian_flag = -1;
325 static int hf_vnc_server_true_color_flag = -1;
326 static int hf_vnc_server_red_max = -1;
327 static int hf_vnc_server_green_max = -1;
328 static int hf_vnc_server_blue_max = -1;
329 static int hf_vnc_server_red_shift = -1;
330 static int hf_vnc_server_green_shift = -1;
331 static int hf_vnc_server_blue_shift = -1;
332 static int hf_vnc_desktop_name = -1;
333 static int hf_vnc_desktop_name_len = -1;
334
335 static int hf_vnc_num_server_message_types = -1;
336 static int hf_vnc_num_client_message_types = -1;
337 static int hf_vnc_num_encoding_types = -1;
338
339 /********** Client Message Types **********/
340
341 static int hf_vnc_client_message_type = -1; /* A subtree under VNC */
342 static int hf_vnc_client_bits_per_pixel = -1;
343 static int hf_vnc_client_depth = -1;
344 static int hf_vnc_client_big_endian_flag = -1;
345 static int hf_vnc_client_true_color_flag = -1;
346 static int hf_vnc_client_red_max = -1;
347 static int hf_vnc_client_green_max = -1;
348 static int hf_vnc_client_blue_max = -1;
349 static int hf_vnc_client_red_shift = -1;
350 static int hf_vnc_client_green_shift = -1;
351 static int hf_vnc_client_blue_shift = -1;
352
353 /* Client Key Event */
354 static int hf_vnc_key_down = -1;
355 static int hf_vnc_key = -1;
356
357 /* Client Pointer Event */
358 static int hf_vnc_button_1_pos = -1;
359 static int hf_vnc_button_2_pos = -1;
360 static int hf_vnc_button_3_pos = -1;
361 static int hf_vnc_button_4_pos = -1;
362 static int hf_vnc_button_5_pos = -1;
363 static int hf_vnc_button_6_pos = -1;
364 static int hf_vnc_button_7_pos = -1;
365 static int hf_vnc_button_8_pos = -1;
366 static int hf_vnc_pointer_x_pos = -1;
367 static int hf_vnc_pointer_y_pos = -1;
368
369 /* Client Framebuffer Update Request */
370 static int hf_vnc_update_req_incremental = -1;
371 static int hf_vnc_update_req_x_pos = -1;
372 static int hf_vnc_update_req_y_pos = -1;
373 static int hf_vnc_update_req_width = -1;
374 static int hf_vnc_update_req_height = -1;
375
376 /* Client Set Encodings */
377 static int hf_vnc_client_set_encodings_encoding_type = -1;
378
379 /* Client Cut Text */
380 static int hf_vnc_client_cut_text_len = -1;
381 static int hf_vnc_client_cut_text = -1;
382
383 /********** Server Message Types **********/
384
385 static int hf_vnc_server_message_type = -1; /* Subtree */
386
387 /* Tunneling capabilities (TightVNC extension) */
388 static int hf_vnc_tight_num_tunnel_types = -1;
389 static int hf_vnc_tight_tunnel_type = -1;
390
391 /* Authentication capabilities (TightVNC extension) */
392 static int hf_vnc_tight_num_auth_types = -1;
393 static int hf_vnc_tight_auth_type = -1;
394
395 /* TightVNC capabilities */
396 static int hf_vnc_tight_server_message_type = -1;
397 static int hf_vnc_tight_server_vendor = -1;
398 static int hf_vnc_tight_server_name = -1;
399
400 static int hf_vnc_tight_client_message_type = -1;
401 static int hf_vnc_tight_client_vendor = -1;
402 static int hf_vnc_tight_client_name = -1;
403
404 static int hf_vnc_tight_encoding_type = -1;
405 static int hf_vnc_tight_encoding_vendor = -1;
406 static int hf_vnc_tight_encoding_name = -1;
407
408 /* Tight compression parameters */
409 static int hf_vnc_tight_reset_stream0 = -1;
410 static int hf_vnc_tight_reset_stream1 = -1;
411 static int hf_vnc_tight_reset_stream2 = -1;
412 static int hf_vnc_tight_reset_stream3 = -1;
413
414 static int hf_vnc_tight_rect_type = -1;
415
416 static int hf_vnc_tight_image_len = -1;
417 static int hf_vnc_tight_image_data = -1;
418
419 static int hf_vnc_tight_fill_color = -1;
420
421 static int hf_vnc_tight_filter_flag = -1;
422 static int hf_vnc_tight_filter_id = -1;
423
424 static int hf_vnc_tight_palette_num_colors = -1;
425 static int hf_vnc_tight_palette_data = -1;
426
427 /* Server Framebuffer Update */
428 static int hf_vnc_fb_update_x_pos = -1;
429 static int hf_vnc_fb_update_y_pos = -1;
430 static int hf_vnc_fb_update_width = -1;
431 static int hf_vnc_fb_update_height = -1;
432 static int hf_vnc_fb_update_encoding_type = -1;
433
434 /* Raw Encoding */
435 static int hf_vnc_raw_pixel_data = -1;
436
437 /* CopyRect Encoding */
438 static int hf_vnc_copyrect_src_x_pos = -1;
439 static int hf_vnc_copyrect_src_y_pos = -1;
440
441 /* RRE Encoding */
442 static int hf_vnc_rre_num_subrects = -1;
443 static int hf_vnc_rre_bg_pixel = -1;
444
445 static int hf_vnc_rre_subrect_pixel = -1;
446 static int hf_vnc_rre_subrect_x_pos = -1;
447 static int hf_vnc_rre_subrect_y_pos = -1;
448 static int hf_vnc_rre_subrect_width = -1;
449 static int hf_vnc_rre_subrect_height = -1;
450
451 /* Hextile Encoding */
452 static int hf_vnc_hextile_subencoding_mask = -1;
453 static int hf_vnc_hextile_raw = -1;
454 static int hf_vnc_hextile_raw_value = -1;
455 static int hf_vnc_hextile_bg = -1;
456 static int hf_vnc_hextile_bg_value = -1;
457 static int hf_vnc_hextile_fg = -1;
458 static int hf_vnc_hextile_fg_value = -1;
459 static int hf_vnc_hextile_anysubrects = -1;
460 static int hf_vnc_hextile_num_subrects = -1;
461 static int hf_vnc_hextile_subrectscolored = -1;
462 static int hf_vnc_hextile_subrect_pixel_value = -1;
463 static int hf_vnc_hextile_subrect_x_pos = -1;
464 static int hf_vnc_hextile_subrect_y_pos = -1;
465 static int hf_vnc_hextile_subrect_width = -1;
466 static int hf_vnc_hextile_subrect_height = -1;
467
468 /* ZRLE Encoding */
469 static int hf_vnc_zrle_len = -1;
470 static int hf_vnc_zrle_subencoding = -1;
471 static int hf_vnc_zrle_rle = -1;
472 static int hf_vnc_zrle_palette_size = -1;
473 static int hf_vnc_zrle_data = -1;
474 static int hf_vnc_zrle_raw = -1;
475 static int hf_vnc_zrle_palette = -1;
476
477 /* Cursor Encoding */
478 static int hf_vnc_cursor_x_fore_back = -1;
479 static int hf_vnc_cursor_encoding_pixels = -1;
480 static int hf_vnc_cursor_encoding_bitmask = -1;
481
482 /* Server Set Colormap Entries */
483 static int hf_vnc_colormap_first_color = -1;
484 static int hf_vnc_colormap_num_colors = -1;
485 static int hf_vnc_colormap_red = -1;
486 static int hf_vnc_colormap_green = -1;
487 static int hf_vnc_colormap_blue = -1;
488
489 /* Server Cut Text */
490 static int hf_vnc_server_cut_text_len = -1;
491 static int hf_vnc_server_cut_text = -1;
492
493 /********** End of Server Message Types **********/
494
495 static gboolean vnc_preference_desegment = TRUE;
496
497 /* Initialize the subtree pointers */
498 static gint ett_vnc = -1;
499 static gint ett_vnc_client_message_type = -1;
500 static gint ett_vnc_server_message_type = -1;
501 static gint ett_vnc_rect = -1;
502 static gint ett_vnc_encoding_type = -1;
503 static gint ett_vnc_rre_subrect = -1;
504 static gint ett_vnc_hextile_subencoding_mask = -1;
505 static gint ett_vnc_hextile_num_subrects = -1;
506 static gint ett_vnc_hextile_subrect = -1;
507 static gint ett_vnc_zrle_subencoding = -1;
508 static gint ett_vnc_colormap_num_groups = -1;
509 static gint ett_vnc_colormap_color_group = -1;
510
511 /* Global so they keep their value between packets */
512 guint8 vnc_bytes_per_pixel;
513 guint8 vnc_depth;
514
515
516 /* Code to dissect the packets */
517 static void
518 dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
519 {
520         gboolean ret;
521         gint offset = 0;
522
523         /* Set up structures needed to add the protocol subtree and manage it */
524         proto_item *ti=NULL;
525         proto_tree *vnc_tree=NULL;
526
527         conversation_t *conversation;
528         vnc_conversation_t *per_conversation_info;
529
530         conversation = find_conversation(pinfo->fd->num, &pinfo->src,
531                                          &pinfo->dst, pinfo->ptype,
532                                          pinfo->srcport, pinfo->destport, 0);
533
534         if(!conversation) {  /* Conversation does not exist yet - create it */
535                 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
536                                                 &pinfo->dst, pinfo->ptype,
537                                                 pinfo->srcport,
538                                                 pinfo->destport, 0);
539         }
540
541         /* Retrieve information from conversation, or add it if it isn't
542          * there yet */
543         per_conversation_info = conversation_get_proto_data(conversation,
544                                                             proto_vnc);
545         if(!per_conversation_info) {
546                 per_conversation_info = se_alloc(sizeof(vnc_conversation_t));
547                 
548                 per_conversation_info->vnc_next_state = SERVER_VERSION;
549
550                 conversation_add_proto_data(conversation, proto_vnc,
551                                             per_conversation_info);
552         }
553
554
555         /* Make entries in Protocol column and Info column on summary display */
556         if (check_col(pinfo->cinfo, COL_PROTOCOL))
557                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "VNC");
558
559         /* First, clear the info column */
560         if(check_col(pinfo->cinfo, COL_INFO))
561                 col_clear(pinfo->cinfo, COL_INFO);
562
563         /* create display subtree for the protocol */
564         if(tree) {
565                 ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, FALSE);
566                 vnc_tree = proto_item_add_subtree(ti, ett_vnc);
567         }
568
569         offset = 0; /* Start at the beginning of the VNC protocol data */
570
571         /* Dissect any remaining session startup messages */
572         ret = vnc_startup_messages(tvb, pinfo, offset, vnc_tree,
573                                    per_conversation_info);
574
575         vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
576         vnc_set_depth(pinfo, vnc_depth);
577
578         if(!ret) {      
579                 if(DEST_PORT_VNC)
580                         vnc_client_to_server(tvb, pinfo, &offset, vnc_tree);
581                 else
582                         vnc_server_to_client(tvb, pinfo, &offset, vnc_tree);
583         }
584 }
585
586 /* Returns the new offset after processing the 4-byte vendor string */
587 static gint
588 process_vendor(proto_tree *tree, gint hfindex, tvbuff_t *tvb, gint offset)
589 {
590         gchar *vendor;
591         proto_item *ti;
592
593         vendor = tvb_get_ephemeral_string(tvb, offset, 4);
594
595         ti = proto_tree_add_string(tree, hfindex, tvb, offset, 4, vendor);
596
597         if(g_ascii_strcasecmp(vendor, "STDV") == 0)
598                 proto_item_append_text(ti, " (Standard VNC vendor)");
599         else if(g_ascii_strcasecmp(vendor, "TRDV") == 0)
600                 proto_item_append_text(ti, " (Tridia VNC vendor)");
601         else if(g_ascii_strcasecmp(vendor, "TGHT") == 0)
602                 proto_item_append_text(ti, " (Tight VNC vendor)");
603                         
604         offset += 4;
605         return offset;
606 }
607
608 /* Returns the new offset after processing the specified number of capabilities */
609 static gint
610 process_tight_capabilities(proto_tree *tree,
611                            gint type_index, gint vendor_index, gint name_index,
612                            tvbuff_t *tvb, gint offset, gint num_capabilities)
613 {
614         gint i;
615
616         /* See vnc_unixsrc/include/rfbproto.h:rfbCapabilityInfo */
617
618         for (i = 0; i < num_capabilities; i++) {
619                 char *name;
620
621                 proto_tree_add_item(tree, type_index, tvb, offset, 4, FALSE);
622                 offset += 4;
623
624                 offset = process_vendor(tree, vendor_index, tvb, offset);
625
626                 name = tvb_get_ephemeral_string(tvb, offset, 8);
627                 proto_tree_add_string(tree, name_index, tvb, offset, 8, name);
628                 offset += 8;
629         }
630
631         return offset;
632 }
633
634 /* Returns true if additional session startup messages follow */
635 static gboolean
636 vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
637                      proto_tree *tree, vnc_conversation_t
638                      *per_conversation_info)
639 {
640         guint8 num_security_types;
641         guint32 desktop_name_len, auth_result, text_len;
642         vnc_packet_t *per_packet_info;
643         gint num_tunnel_types;
644         gint num_auth_types;
645
646         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
647
648         if(!per_packet_info) {
649                 per_packet_info = se_alloc(sizeof(vnc_packet_t));
650
651                 per_packet_info->state = per_conversation_info->vnc_next_state;
652                 per_packet_info->preferred_encoding = -1;
653
654                 p_add_proto_data(pinfo->fd, proto_vnc, per_packet_info);
655         } 
656                 
657         /* Packet dissection follows */
658         switch(per_packet_info->state) {
659
660         case SERVER_VERSION :
661                 proto_tree_add_item(tree, hf_vnc_server_proto_ver, tvb, 4,
662                                     7, FALSE);
663
664                 per_conversation_info->server_proto_ver =
665                         g_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7),
666                                  NULL);
667                 
668                 if (check_col(pinfo->cinfo, COL_INFO))
669                         col_add_fstr(pinfo->cinfo, COL_INFO,
670                                      "Server protocol version: %s",
671                                      tvb_format_text(tvb, 4, 7));
672                 
673                 per_conversation_info->vnc_next_state = CLIENT_VERSION;
674                 break;
675                 
676         case CLIENT_VERSION :
677                 proto_tree_add_item(tree, hf_vnc_client_proto_ver, tvb,
678                                     4, 7, FALSE);
679
680                 per_conversation_info->client_proto_ver =
681                         g_strtod((char *)tvb_get_ephemeral_string(tvb, 4, 7),
682                                  NULL);
683                 
684                 if (check_col(pinfo->cinfo, COL_INFO))
685                         col_add_fstr(pinfo->cinfo, COL_INFO,
686                                      "Client protocol version: %s",
687                                      tvb_format_text(tvb, 4, 7));
688                 
689                 per_conversation_info->vnc_next_state = SECURITY;
690                 break;
691
692         case SECURITY :
693                 if (check_col(pinfo->cinfo, COL_INFO))
694                         col_set_str(pinfo->cinfo, COL_INFO,
695                                     "Security types supported");
696                 
697                 /* We're checking against the client protocol version because
698                  * the client is the final decider on which version to use
699                  * after the server offers the highest version it supports. */
700                 
701                 if(per_conversation_info->client_proto_ver >= 3.007) {
702                         proto_tree_add_item(tree,
703                                             hf_vnc_num_security_types, tvb,
704                                             offset, 1, FALSE);
705                         num_security_types = tvb_get_guint8(tvb, offset);
706                         
707                         for(offset = 1; offset <= num_security_types; offset++){
708                                 proto_tree_add_item(tree,
709                                                     hf_vnc_security_type, tvb,
710                                                     offset, 1, FALSE);
711
712                         }
713                 } else {
714                         /* Version < 3.007: The server decides the
715                          * authentication type for us to use */
716                         proto_tree_add_item(tree,
717                                             hf_vnc_server_security_type, tvb,
718                                             offset, 4, FALSE);
719                 }
720
721                 per_conversation_info->vnc_next_state = SECURITY_TYPES;
722                 break;
723
724         case SECURITY_TYPES :
725                 if (check_col(pinfo->cinfo, COL_INFO))
726                         col_set_str(pinfo->cinfo, COL_INFO,
727                                     "Authentication type selected by client");
728                 
729                 proto_tree_add_item(tree, hf_vnc_client_security_type, tvb,
730                                     offset, 1, FALSE);
731                 per_conversation_info->security_type_selected =
732                         tvb_get_guint8(tvb, offset);
733         
734                 switch(per_conversation_info->security_type_selected) {
735
736                 case 1 : /* None */
737                         if(per_conversation_info->client_proto_ver >= 3.008)
738                                 per_conversation_info->vnc_next_state =
739                                         SECURITY_RESULT;
740                         else
741                                 per_conversation_info->vnc_next_state =
742                                         CLIENT_INIT;
743
744                         break;
745
746                 case 2 : /* VNC */
747                         per_conversation_info->vnc_next_state =
748                                 VNC_AUTHENTICATION_CHALLENGE;
749                         break;
750
751                 case 16 : /* Tight */
752                         per_conversation_info->vnc_next_state =
753                                 TIGHT_TUNNELING_CAPABILITIES;
754                         
755                 default :
756                         /* Security type not supported by this dissector */
757                         break;
758                 }
759
760                 break;
761
762         case TIGHT_TUNNELING_CAPABILITIES :
763                 if (check_col(pinfo->cinfo, COL_INFO))
764                         col_set_str(pinfo->cinfo, COL_INFO,
765                                     "TightVNC tunneling capabilities supported");
766
767                 proto_tree_add_item(tree, hf_vnc_tight_num_tunnel_types, tvb, offset, 4, FALSE);
768                 num_tunnel_types = tvb_get_ntohl(tvb, offset);
769                 offset += 4;
770
771                 {
772                         gint i;
773
774                         for(i = 0; i < num_tunnel_types; i++) {
775                                 /* TightVNC and Xvnc don't support any tunnel capabilities yet, but each capability
776                                  * is 16 bytes, so skip them.
777                                  */
778
779                                 proto_tree_add_item(tree, hf_vnc_tight_tunnel_type, tvb, offset, 16, FALSE);
780                                 offset += 16;
781                         }
782                 }
783
784                 if (num_tunnel_types == 0)
785                         per_conversation_info->vnc_next_state = TIGHT_AUTH_CAPABILITIES;
786                 else
787                         per_conversation_info->vnc_next_state = TIGHT_TUNNEL_TYPE_REPLY;
788                 break;
789
790         case TIGHT_TUNNEL_TYPE_REPLY:
791                 /* Neither TightVNC nor Xvnc implement this; they just have a placeholder that emits an error
792                  * message and closes the connection (xserver/hw/vnc/auth.c:rfbProcessClientTunnelingType).
793                  * We should actually never get here...
794                  */
795                 break;
796
797         case TIGHT_AUTH_CAPABILITIES:
798                 if (check_col(pinfo->cinfo, COL_INFO))
799                         col_set_str(pinfo->cinfo, COL_INFO,
800                                     "TightVNC authentication capabilities supported");
801
802                 proto_tree_add_item(tree, hf_vnc_tight_num_auth_types, tvb, offset, 4, FALSE);
803                 num_auth_types = tvb_get_ntohl(tvb, offset);
804                 offset += 4;
805
806                 {
807                         int i;
808
809                         for (i = 0; i < num_auth_types; i++) {
810                                 /* See xserver/hw/vnc/auth.c:rfbSendAuthCaps()
811                                  * We don't actually display the auth types for now.
812                                  */
813                                 proto_tree_add_item(tree, hf_vnc_tight_auth_type, tvb, offset, 16, FALSE);
814                                 offset += 16;
815                         }
816                 }
817
818                 if (num_auth_types == 0)
819                         per_conversation_info->vnc_next_state = CLIENT_INIT;
820                 else
821                         per_conversation_info->vnc_next_state = TIGHT_AUTH_TYPE_REPLY;
822                 break;
823
824         case TIGHT_AUTH_TYPE_REPLY:
825                 REPORT_DISSECTOR_BUG("Unimplemented case: TightVNC authentication reply");
826                 /* FIXME: implement.  See xserver/hw/vnc/auth.c:rfbProcessClientAuthType() */
827                 break;          
828
829         case TIGHT_AUTH_TYPE_AND_VENDOR_CODE :
830                 if (check_col(pinfo->cinfo, COL_INFO))
831                         col_set_str(pinfo->cinfo, COL_INFO,
832                                     "Authentication type / vendor code");
833
834                 proto_tree_add_item(tree, hf_vnc_server_security_type, tvb,
835                                     offset, 4, FALSE);          
836
837                 offset += 4;
838
839                 offset = process_vendor(tree, hf_vnc_vendor_code, tvb, offset);
840
841                 /* Display authentication method string */
842                 proto_tree_add_item(tree, hf_vnc_security_type_string, tvb,
843                                     offset, 8, FALSE);
844
845                 per_conversation_info->vnc_next_state =
846                         TIGHT_UNKNOWN_PACKET3;
847
848                 break;
849                 
850         case TIGHT_UNKNOWN_PACKET3 :
851                 if (check_col(pinfo->cinfo, COL_INFO))
852                         col_set_str(pinfo->cinfo, COL_INFO,
853                                     "Unknown packet (TightVNC)");
854                 
855                 proto_tree_add_text(tree, tvb, offset, -1,
856                                     "Unknown packet (TightVNC)");
857
858                 per_conversation_info->vnc_next_state =
859                         VNC_AUTHENTICATION_CHALLENGE;
860
861                 break;
862
863         case VNC_AUTHENTICATION_CHALLENGE :
864                 if (check_col(pinfo->cinfo, COL_INFO))
865                         col_set_str(pinfo->cinfo, COL_INFO,
866                                     "Authentication challenge from server");
867                 
868                 proto_tree_add_item(tree, hf_vnc_auth_challenge, tvb,
869                                     offset, 16, FALSE);
870
871                 per_conversation_info->vnc_next_state =
872                         VNC_AUTHENTICATION_RESPONSE;
873                 break;
874
875         case VNC_AUTHENTICATION_RESPONSE :
876                 if (check_col(pinfo->cinfo, COL_INFO))
877                         col_set_str(pinfo->cinfo, COL_INFO,
878                                     "Authentication response from client");
879                 
880                 proto_tree_add_item(tree, hf_vnc_auth_response, tvb,
881                                     offset, 16, FALSE);
882                 
883                 per_conversation_info->vnc_next_state = SECURITY_RESULT;
884                 break;
885
886         case SECURITY_RESULT :
887                 if (check_col(pinfo->cinfo, COL_INFO))
888                         col_set_str(pinfo->cinfo, COL_INFO,
889                                     "Authentication result");
890                 
891                 proto_tree_add_item(tree, hf_vnc_auth_result, tvb, offset,
892                                     4, FALSE);
893                 auth_result = tvb_get_ntohl(tvb, offset);
894                 offset += 4;
895
896                 switch(auth_result) {
897
898                 case 0 : /* OK */
899                         per_conversation_info->vnc_next_state = CLIENT_INIT;
900                         break;
901
902                 case 1 : /* Failed */
903                         if(per_conversation_info->client_proto_ver >= 3.008) {
904                                 text_len = tvb_get_ntohl(tvb, offset);
905                                 proto_tree_add_text(tree, tvb, offset, 4, "Length of authentication error: %d", text_len);
906                                 offset += 4;
907                                 
908                                 proto_tree_add_item(tree, hf_vnc_auth_error, tvb,
909                                                     offset, text_len, FALSE);
910                                 offset += text_len;
911                         }
912
913                         return TRUE; /* All versions: Do not continue
914                                         processing VNC packets as connection
915                                         will be closed after this packet. */
916                         
917                         break;
918                 }
919
920                 break;
921
922         case CLIENT_INIT :
923                 if (check_col(pinfo->cinfo, COL_INFO))
924                         col_set_str(pinfo->cinfo, COL_INFO,
925                                     "Share desktop flag");
926
927                 proto_tree_add_item(tree, hf_vnc_share_desktop_flag, tvb,
928                                     offset, 1, FALSE);
929                 
930                 per_conversation_info->vnc_next_state = SERVER_INIT;
931
932                 break;
933                 
934         case SERVER_INIT :
935                 if (check_col(pinfo->cinfo, COL_INFO))
936                         col_set_str(pinfo->cinfo, COL_INFO,
937                                     "Server framebuffer parameters");
938                
939                 proto_tree_add_item(tree, hf_vnc_width, tvb, offset, 2,
940                                     FALSE);
941                 offset += 2;
942
943                 proto_tree_add_item(tree, hf_vnc_height, tvb, offset, 2,
944                                     FALSE);
945                 offset += 2;
946
947                 proto_tree_add_item(tree, hf_vnc_server_bits_per_pixel,
948                                     tvb, offset, 1, FALSE);
949                 vnc_bytes_per_pixel = tvb_get_guint8(tvb, offset)/8;
950                 vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
951                 offset += 1;
952
953                 proto_tree_add_item(tree, hf_vnc_server_depth, tvb, offset,
954                                     1, FALSE);
955                 offset += 1;
956
957                 proto_tree_add_item(tree, hf_vnc_server_big_endian_flag,
958                                     tvb, offset, 1, FALSE);
959                 offset += 1;
960
961                 proto_tree_add_item(tree, hf_vnc_server_true_color_flag,
962                                     tvb, offset, 1, FALSE);
963                 offset += 1;
964
965                 proto_tree_add_item(tree, hf_vnc_server_red_max,
966                                     tvb, offset, 2, FALSE);
967                 offset += 2;
968
969                 proto_tree_add_item(tree, hf_vnc_server_green_max,
970                                     tvb, offset, 2, FALSE);
971                 offset += 2;
972
973                 proto_tree_add_item(tree, hf_vnc_server_blue_max,
974                                     tvb, offset, 2, FALSE);
975                 offset += 2;
976
977                 proto_tree_add_item(tree, hf_vnc_server_red_shift,
978                                     tvb, offset, 1, FALSE);
979                 offset += 1;
980
981                 proto_tree_add_item(tree, hf_vnc_server_green_shift,
982                                     tvb, offset, 1, FALSE);
983                 offset += 1;
984
985                 proto_tree_add_item(tree, hf_vnc_server_blue_shift,
986                                     tvb, offset, 1, FALSE);
987                 offset += 1;
988
989                 proto_tree_add_item(tree, hf_vnc_padding,
990                                     tvb, offset, 3, FALSE);
991                 offset += 3; /* Skip over 3 bytes of padding */
992                 
993                 if(tvb_length_remaining(tvb, offset) > 0) {
994                         /* Sometimes the desktop name & length is skipped */
995                         proto_tree_add_item(tree, hf_vnc_desktop_name_len,
996                                             tvb, offset, 4, FALSE);
997                         desktop_name_len = tvb_get_ntohl(tvb, offset);
998                         offset += 4;
999
1000                         proto_tree_add_item(tree, hf_vnc_desktop_name,
1001                                             tvb, offset, desktop_name_len,
1002                                             FALSE);
1003                 }
1004
1005                 if(per_conversation_info->security_type_selected == TIGHT)
1006                         per_conversation_info->vnc_next_state =
1007                                 TIGHT_INTERACTION_CAPS;
1008                 else
1009                         per_conversation_info->vnc_next_state = NORMAL_TRAFFIC;
1010                 break;
1011                 
1012         case TIGHT_INTERACTION_CAPS :
1013                 if (check_col(pinfo->cinfo, COL_INFO))
1014                         col_set_str(pinfo->cinfo, COL_INFO,
1015                                     "TightVNC Interaction Capabilities");
1016
1017                 proto_tree_add_item(tree, hf_vnc_num_server_message_types,
1018                                     tvb, offset, 2, FALSE);
1019                 per_conversation_info->num_server_message_types = tvb_get_ntohs(tvb, offset);
1020                 offset += 2;
1021
1022                 proto_tree_add_item(tree, hf_vnc_num_client_message_types,
1023                                     tvb, offset, 2, FALSE);
1024                 per_conversation_info->num_client_message_types = tvb_get_ntohs(tvb, offset);
1025                 offset += 2;
1026
1027                 proto_tree_add_item(tree, hf_vnc_num_encoding_types,
1028                                     tvb, offset, 2, FALSE);
1029                 per_conversation_info->num_encoding_types = tvb_get_ntohs(tvb, offset);
1030                 offset += 2;
1031
1032                 proto_tree_add_item(tree, hf_vnc_padding, tvb, offset, 2,
1033                                     FALSE);
1034                 offset += 2;
1035
1036                 per_conversation_info->vnc_next_state = TIGHT_INTERACTION_CAPS_LIST;
1037                 break;
1038
1039         case TIGHT_INTERACTION_CAPS_LIST:
1040                 if (check_col(pinfo->cinfo, COL_INFO))
1041                         col_set_str(pinfo->cinfo, COL_INFO,
1042                                     "TightVNC Interaction Capabilities list");
1043
1044                 offset = process_tight_capabilities(tree,
1045                                                     hf_vnc_tight_server_message_type,
1046                                                     hf_vnc_tight_server_vendor,
1047                                                     hf_vnc_tight_server_name,
1048                                                     tvb, offset, per_conversation_info->num_server_message_types);
1049                 offset = process_tight_capabilities(tree,
1050                                                     hf_vnc_tight_client_message_type,
1051                                                     hf_vnc_tight_client_vendor,
1052                                                     hf_vnc_tight_client_name,
1053                                                     tvb, offset, per_conversation_info->num_client_message_types);
1054                 offset = process_tight_capabilities(tree,
1055                                                     hf_vnc_tight_encoding_type,
1056                                                     hf_vnc_tight_encoding_vendor,
1057                                                     hf_vnc_tight_encoding_name,
1058                                                     tvb, offset, per_conversation_info->num_encoding_types);
1059
1060                 per_conversation_info->vnc_next_state = NORMAL_TRAFFIC;
1061                 break;
1062
1063         case NORMAL_TRAFFIC :
1064                 return FALSE;
1065         }
1066
1067         return TRUE;
1068 }
1069
1070
1071 static void
1072 vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1073                      proto_tree *tree)
1074 {
1075         guint8 message_type;
1076
1077         proto_item *ti=NULL;
1078         proto_tree *vnc_client_message_type_tree;
1079
1080         message_type = tvb_get_guint8(tvb, *offset);
1081
1082         ti = proto_tree_add_item(tree, hf_vnc_client_message_type, tvb,
1083                                  *offset, 1, FALSE);
1084
1085         vnc_client_message_type_tree =
1086                 proto_item_add_subtree(ti, ett_vnc_client_message_type);
1087
1088         *offset += 1;
1089
1090         switch(message_type) {
1091                 
1092         case 0 :
1093                 vnc_client_set_pixel_format(tvb, pinfo, offset,
1094                                             vnc_client_message_type_tree);
1095                 break;
1096
1097         case 2 :
1098                 vnc_client_set_encodings(tvb, pinfo, offset,
1099                                          vnc_client_message_type_tree);
1100                 break;
1101
1102         case 3 :
1103                 vnc_client_framebuffer_update_request(tvb, pinfo, offset,
1104                                                       vnc_client_message_type_tree);
1105                 break;
1106
1107         case 4 :
1108                 vnc_client_key_event(tvb, pinfo, offset,
1109                                      vnc_client_message_type_tree);
1110                 break;
1111
1112         case 5:
1113                 vnc_client_pointer_event(tvb, pinfo, offset,
1114                                          vnc_client_message_type_tree);
1115                 break;
1116
1117         case 6 :
1118                 vnc_client_cut_text(tvb, pinfo, offset,
1119                                     vnc_client_message_type_tree);
1120                 break;
1121
1122         default :
1123                 if (check_col(pinfo->cinfo, COL_INFO))
1124                         col_append_fstr(pinfo->cinfo, COL_INFO,
1125                                         "Unknown client message type (%u)",
1126                                         message_type);
1127                 break;
1128         }
1129 }
1130
1131 static void
1132 vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1133                      proto_tree *tree)
1134 {
1135         gint start_offset;
1136         guint8 message_type;
1137         gint bytes_needed = 0, length_remaining;
1138         
1139         proto_item *ti=NULL;
1140         proto_tree *vnc_server_message_type_tree;
1141
1142         start_offset = *offset;
1143
1144         message_type = tvb_get_guint8(tvb, *offset);
1145
1146         ti = proto_tree_add_item(tree, hf_vnc_server_message_type, tvb,
1147                                  *offset, 1, FALSE);
1148         vnc_server_message_type_tree =
1149                 proto_item_add_subtree(ti, ett_vnc_server_message_type);
1150
1151         *offset += 1;
1152
1153         switch(message_type) {
1154
1155         case 0 :
1156                 bytes_needed =
1157                         vnc_server_framebuffer_update(tvb, pinfo, offset,
1158                                                       vnc_server_message_type_tree);
1159                 break;
1160
1161         case 1 :
1162                 bytes_needed = vnc_server_set_colormap_entries(tvb, pinfo, offset, vnc_server_message_type_tree);
1163                 break;
1164
1165         case 2 :
1166                 vnc_server_ring_bell(tvb, pinfo, offset,
1167                                      vnc_server_message_type_tree);
1168                 break;
1169
1170         case 3 :
1171                 bytes_needed = vnc_server_cut_text(tvb, pinfo, offset,
1172                                                    vnc_server_message_type_tree);
1173                 break;
1174
1175         default :
1176                 if (check_col(pinfo->cinfo, COL_INFO))
1177                         col_append_str(pinfo->cinfo, COL_INFO,
1178                                        "Unknown server message type");
1179                 break;
1180         }
1181
1182         if(bytes_needed > 0 && vnc_preference_desegment &&
1183            pinfo->can_desegment) {
1184                 length_remaining = tvb_length_remaining(tvb, *offset);
1185
1186                 pinfo->desegment_offset = start_offset;
1187                 pinfo->desegment_len = bytes_needed - length_remaining;
1188                 return;
1189         }
1190 }
1191
1192
1193 static void
1194 vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1195                             proto_tree *tree)
1196 {
1197         if (check_col(pinfo->cinfo, COL_INFO))
1198                 col_set_str(pinfo->cinfo, COL_INFO, "Client set pixel format");
1199         
1200         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
1201                             3, FALSE);
1202         *offset += 3; /* Skip over 3 bytes of padding */
1203                 
1204         proto_tree_add_item(tree, hf_vnc_client_bits_per_pixel, tvb, *offset,
1205                             1, FALSE);
1206         vnc_bytes_per_pixel = tvb_get_guint8(tvb, *offset)/8;
1207         vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
1208         *offset += 1;
1209
1210         proto_tree_add_item(tree, hf_vnc_client_depth, tvb, *offset,
1211                             1, FALSE);
1212         vnc_depth = tvb_get_guint8(tvb, *offset);
1213         vnc_set_depth(pinfo, vnc_depth);
1214         *offset += 1;
1215
1216         proto_tree_add_item(tree, hf_vnc_client_big_endian_flag, tvb, *offset,
1217                             1, FALSE);
1218         *offset += 1;
1219
1220         proto_tree_add_item(tree, hf_vnc_client_true_color_flag, tvb, *offset,
1221                             1, FALSE);
1222         *offset += 1;
1223
1224         proto_tree_add_item(tree, hf_vnc_client_red_max, tvb, *offset,
1225                             2, FALSE);
1226         *offset += 2;
1227
1228         proto_tree_add_item(tree, hf_vnc_client_green_max, tvb, *offset,
1229                             2, FALSE);
1230         *offset += 2;
1231
1232         proto_tree_add_item(tree, hf_vnc_client_blue_max, tvb, *offset,
1233                             2, FALSE);
1234         *offset += 2;
1235
1236         proto_tree_add_item(tree, hf_vnc_client_red_shift, tvb, *offset,
1237                             1, FALSE);
1238         *offset += 1;
1239
1240         proto_tree_add_item(tree, hf_vnc_client_green_shift, tvb, *offset,
1241                             1, FALSE);
1242         *offset += 1;
1243
1244         proto_tree_add_item(tree, hf_vnc_client_blue_shift, tvb, *offset,
1245                             1, FALSE);
1246         *offset += 1;
1247
1248         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
1249                             3, FALSE);
1250         *offset += 3; /* Skip over 3 bytes of padding */
1251 }
1252
1253
1254 static void
1255 vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1256                          proto_tree *tree)
1257 {
1258         guint16 number_of_encodings;
1259         guint counter;
1260         vnc_packet_t *per_packet_info;
1261
1262         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
1263
1264         if (check_col(pinfo->cinfo, COL_INFO))
1265                 col_set_str(pinfo->cinfo, COL_INFO, "Client set encodings");
1266
1267         proto_tree_add_item(tree, hf_vnc_padding,
1268                             tvb, *offset, 1, FALSE);
1269         *offset += 1; /* Skip over 1 byte of padding */
1270
1271         number_of_encodings = tvb_get_ntohs(tvb, *offset);
1272
1273         proto_tree_add_text(tree, tvb, *offset, 2,
1274                             "Number of encodings: %d", number_of_encodings);
1275         *offset += 2;
1276
1277         per_packet_info->preferred_encoding = -1;
1278
1279         for(counter = 1; counter <= number_of_encodings; counter++) {
1280                 proto_tree_add_item(tree,
1281                                     hf_vnc_client_set_encodings_encoding_type,
1282                                     tvb, *offset, 4, FALSE);
1283
1284                 /* Remember the first real encoding as the preferred encoding,
1285                  * per xserver/hw/vnc/rfbserver.c:rfbProcessClientNormalMessage().
1286                  * Otherwise, use RAW as the preferred encoding.
1287                  */
1288                 if (per_packet_info->preferred_encoding == -1) {
1289                         int encoding;
1290
1291                         encoding = tvb_get_ntohl(tvb, *offset);
1292
1293                         switch(encoding) {
1294                         case ENCODING_RAW:
1295                         case ENCODING_RRE:
1296                         case ENCODING_CORRE:
1297                         case ENCODING_HEXTILE:
1298                         case ENCODING_ZLIB:
1299                         case ENCODING_TIGHT:
1300                                 per_packet_info->preferred_encoding = encoding;
1301                                 break;
1302                         }
1303                 }
1304
1305                 *offset += 4;
1306         }
1307
1308         if (per_packet_info->preferred_encoding == -1)
1309                 per_packet_info->preferred_encoding = ENCODING_RAW;
1310 }
1311
1312
1313 static void
1314 vnc_client_framebuffer_update_request(tvbuff_t *tvb, packet_info *pinfo,
1315                                       gint *offset, proto_tree *tree)
1316 {
1317         if (check_col(pinfo->cinfo, COL_INFO))
1318                 col_set_str(pinfo->cinfo, COL_INFO,
1319                             "Client framebuffer update request");
1320
1321         proto_tree_add_item(tree, hf_vnc_update_req_incremental,
1322                             tvb, *offset, 1, FALSE);
1323         *offset += 1;
1324
1325         proto_tree_add_item(tree, hf_vnc_update_req_x_pos,
1326                             tvb, *offset, 2, FALSE);
1327         *offset += 2;
1328
1329         proto_tree_add_item(tree, hf_vnc_update_req_y_pos,
1330                             tvb, *offset, 2, FALSE);
1331         *offset += 2;
1332
1333         proto_tree_add_item(tree, hf_vnc_update_req_width, tvb,
1334                             *offset, 2, FALSE);
1335         *offset += 2;
1336
1337         proto_tree_add_item(tree, hf_vnc_update_req_height, tvb,
1338                             *offset, 2, FALSE);
1339         *offset += 2;
1340 }
1341
1342
1343 static void
1344 vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1345                      proto_tree *tree)
1346 {
1347         if (check_col(pinfo->cinfo, COL_INFO))
1348                 col_set_str(pinfo->cinfo, COL_INFO, "Client key event");
1349         
1350         proto_tree_add_item(tree, hf_vnc_key_down, tvb, *offset, 1, FALSE);
1351         *offset += 1;
1352         
1353         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 2, FALSE);
1354         *offset += 2; /* Skip over 2 bytes of padding */
1355         
1356         proto_tree_add_item(tree, hf_vnc_key, tvb, *offset, 4, FALSE);
1357         *offset += 4;
1358 }
1359
1360
1361 static void
1362 vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1363                          proto_tree *tree)
1364 {
1365         if (check_col(pinfo->cinfo, COL_INFO))
1366                 col_set_str(pinfo->cinfo, COL_INFO, "Client pointer event");
1367         
1368         proto_tree_add_item(tree, hf_vnc_button_1_pos, tvb, *offset, 1, FALSE);
1369         proto_tree_add_item(tree, hf_vnc_button_2_pos, tvb, *offset, 1, FALSE);
1370         proto_tree_add_item(tree, hf_vnc_button_3_pos, tvb, *offset, 1, FALSE);
1371         proto_tree_add_item(tree, hf_vnc_button_4_pos, tvb, *offset, 1, FALSE);
1372         proto_tree_add_item(tree, hf_vnc_button_5_pos, tvb, *offset, 1, FALSE);
1373         proto_tree_add_item(tree, hf_vnc_button_6_pos, tvb, *offset, 1, FALSE);
1374         proto_tree_add_item(tree, hf_vnc_button_7_pos, tvb, *offset, 1, FALSE);
1375         proto_tree_add_item(tree, hf_vnc_button_8_pos, tvb, *offset, 1, FALSE);
1376         *offset += 1;
1377         
1378         proto_tree_add_item(tree, hf_vnc_pointer_x_pos, tvb, *offset, 2, FALSE);
1379         *offset += 2;
1380         
1381         proto_tree_add_item(tree, hf_vnc_pointer_y_pos, tvb, *offset, 2, FALSE);
1382         *offset += 2;
1383 }
1384
1385
1386 static void
1387 vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1388                     proto_tree *tree)
1389 {
1390         guint32 text_len;
1391
1392         if (check_col(pinfo->cinfo, COL_INFO))
1393                 col_set_str(pinfo->cinfo, COL_INFO, "Client cut text");
1394
1395         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, FALSE);
1396         *offset += 3; /* Skip over 3 bytes of padding */
1397
1398         text_len = tvb_get_ntohl(tvb, *offset);
1399         proto_tree_add_item(tree, hf_vnc_client_cut_text_len, tvb, *offset, 4,
1400                             FALSE);
1401         *offset += 4;
1402
1403         proto_tree_add_item(tree, hf_vnc_client_cut_text, tvb, *offset,
1404                             text_len, FALSE);
1405         *offset += text_len;
1406
1407 }
1408
1409
1410 static guint
1411 vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1412                               proto_tree *tree)
1413 {
1414         gint num_rects, i;
1415         guint16 width, height;
1416         guint bytes_needed = 0;
1417         gint32 encoding_type;
1418         proto_item *ti, *ti_x, *ti_y, *ti_width, *ti_height;
1419         proto_tree *vnc_rect_tree, *vnc_encoding_type_tree;
1420         
1421         if (check_col(pinfo->cinfo, COL_INFO))
1422                 col_set_str(pinfo->cinfo, COL_INFO,
1423                             "Server framebuffer update");       
1424
1425         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
1426         *offset += 1;
1427         
1428         num_rects = tvb_get_ntohs(tvb, *offset);
1429         proto_tree_add_text(tree, tvb, *offset, 2, "Number of rectangles: %d",
1430                             num_rects);
1431         *offset += 2;
1432         
1433         for(i = 1; i <= num_rects; i++) {
1434
1435                 VNC_BYTES_NEEDED(12);
1436
1437                 ti = proto_tree_add_text(tree, tvb, *offset, 12,
1438                                          "Rectangle #%d", i);
1439
1440                 vnc_rect_tree =
1441                         proto_item_add_subtree(ti, ett_vnc_rect);
1442
1443                 ti_x = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_x_pos,
1444                                            tvb, *offset, 2, FALSE);
1445                 *offset += 2;
1446                 
1447                 ti_y = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_y_pos,
1448                                            tvb, *offset, 2, FALSE);
1449                 *offset += 2;
1450                 
1451                 ti_width = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_width,
1452                                                tvb, *offset, 2, FALSE);
1453                 width = tvb_get_ntohs(tvb, *offset);
1454                 *offset += 2;
1455                 
1456                 ti_height = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_height,
1457                                                 tvb, *offset, 2, FALSE);
1458                 height = tvb_get_ntohs(tvb, *offset);
1459                 *offset += 2;
1460
1461                 ti = proto_tree_add_item(vnc_rect_tree,
1462                                          hf_vnc_fb_update_encoding_type,
1463                                          tvb, *offset, 4, FALSE);
1464
1465                 encoding_type = tvb_get_ntohl(tvb, *offset);
1466                 *offset += 4;
1467
1468                 if (encoding_type == ENCODING_LAST_RECT)
1469                         break; /* exit the loop */
1470
1471                 vnc_encoding_type_tree =
1472                         proto_item_add_subtree(ti, ett_vnc_encoding_type);
1473
1474                 switch(encoding_type) {
1475                         
1476                 case ENCODING_RAW:
1477                         bytes_needed = vnc_raw_encoding(tvb, pinfo, offset,
1478                                                         vnc_encoding_type_tree,
1479                                                         width, height);
1480                         break;
1481                         
1482                 case ENCODING_COPY_RECT:
1483                         bytes_needed =
1484                                 vnc_copyrect_encoding(tvb, pinfo, offset,
1485                                                       vnc_encoding_type_tree,
1486                                                       width, height);
1487                         break;
1488                         
1489                 case ENCODING_RRE:
1490                         bytes_needed = 
1491                                 vnc_rre_encoding(tvb, pinfo, offset,
1492                                                  vnc_encoding_type_tree,
1493                                                  width, height);
1494                         break;
1495                         
1496                 case ENCODING_HEXTILE:
1497                         bytes_needed =
1498                                 vnc_hextile_encoding(tvb, pinfo, offset,
1499                                                      vnc_encoding_type_tree,
1500                                                      width, height);
1501                         break;
1502                         
1503                 case ENCODING_RLE:
1504                         bytes_needed =
1505                                 vnc_zrle_encoding(tvb, pinfo, offset,
1506                                                   vnc_encoding_type_tree,
1507                                                   width, height);
1508                         break;
1509
1510                 case ENCODING_TIGHT:
1511                         bytes_needed =
1512                                 vnc_tight_encoding(tvb, pinfo, offset,
1513                                                    vnc_encoding_type_tree,
1514                                                    width, height);
1515                         break;
1516
1517                 case ENCODING_RICH_CURSOR:
1518                 case ENCODING_X_CURSOR:
1519                         proto_item_append_text (ti_x,      " (hotspot X)");
1520                         proto_item_append_text (ti_y,      " (hotspot Y)");
1521                         proto_item_append_text (ti_width,  " (cursor width)");
1522                         proto_item_append_text (ti_height, " (cursor height)");
1523
1524                         if (encoding_type == ENCODING_RICH_CURSOR)
1525                                 bytes_needed = vnc_rich_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
1526                         else
1527                                 bytes_needed = vnc_x_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
1528
1529                         break;
1530
1531                 case ENCODING_POINTER_POS:
1532                         proto_item_append_text (ti_x,      " (pointer X)");
1533                         proto_item_append_text (ti_y,      " (pointer Y)");
1534                         proto_item_append_text (ti_width,  " (unused)");
1535                         proto_item_append_text (ti_height, " (unused)");
1536                         bytes_needed = 0;
1537                         break;
1538
1539                 case ENCODING_DESKTOP_SIZE:
1540
1541                         /* There is no payload for this message type */
1542
1543                         bytes_needed = 0;
1544                         break;
1545
1546                 }
1547
1548                 /* Check if the routines above requested more bytes to
1549                  * be desegmented. */
1550                 if(bytes_needed > 0)
1551                         return bytes_needed;
1552         }
1553
1554         return 0;
1555 }
1556
1557
1558 static guint
1559 vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1560                  proto_tree *tree, guint16 width, guint16 height)
1561 {
1562         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1563         guint length;
1564
1565         length = width * height * bytes_per_pixel;
1566         VNC_BYTES_NEEDED(length);
1567
1568         proto_tree_add_item(tree, hf_vnc_raw_pixel_data, tvb, *offset, 
1569                             length, FALSE);
1570         *offset += length;
1571
1572         return 0; /* bytes_needed */
1573 }
1574
1575
1576 static guint
1577 vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
1578                       proto_tree *tree, guint16 width _U_, guint16 height _U_)
1579 {
1580         proto_tree_add_item(tree, hf_vnc_copyrect_src_x_pos, tvb, *offset, 
1581                             2, FALSE);
1582         *offset += 2;
1583
1584         proto_tree_add_item(tree, hf_vnc_copyrect_src_y_pos, tvb, *offset, 
1585                             2, FALSE);
1586         *offset += 2;
1587
1588         return 0; /* bytes_needed */
1589 }
1590
1591
1592 static guint
1593 vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1594                  proto_tree *tree, guint16 width _U_, guint16 height _U_)
1595 {
1596         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1597         guint32 num_subrects, i;
1598         guint bytes_needed;
1599         proto_item *ti;
1600         proto_tree *subrect_tree;
1601
1602         VNC_BYTES_NEEDED(4);
1603         proto_tree_add_item(tree, hf_vnc_rre_num_subrects, tvb, *offset, 
1604                             4, FALSE);
1605         num_subrects = tvb_get_ntohl(tvb, *offset);
1606         *offset += 4;
1607
1608         VNC_BYTES_NEEDED(bytes_per_pixel);
1609         proto_tree_add_item(tree, hf_vnc_rre_bg_pixel, tvb, *offset, 
1610                             bytes_per_pixel, FALSE);
1611         *offset += bytes_per_pixel;
1612
1613         for(i = 1; i <= num_subrects; i++) {
1614                 bytes_needed = bytes_per_pixel + 8;
1615                 VNC_BYTES_NEEDED(bytes_needed);
1616
1617                 ti = proto_tree_add_text(tree, tvb, *offset, bytes_per_pixel +
1618                                          8, "Subrectangle #%d", i);
1619                 subrect_tree =
1620                         proto_item_add_subtree(ti, ett_vnc_rre_subrect);
1621
1622                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_pixel,
1623                                     tvb, *offset, bytes_per_pixel, FALSE);
1624                 *offset += bytes_per_pixel;
1625
1626                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_x_pos,
1627                                     tvb, *offset, 2, FALSE);
1628                 *offset += 2;
1629
1630                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_y_pos,
1631                                     tvb, *offset, 2, FALSE);
1632                 *offset += 2;
1633
1634                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_width,
1635                                     tvb, *offset, 2, FALSE);
1636                 *offset += 2;
1637
1638                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_height,
1639                                     tvb, *offset, 2, FALSE);
1640                 *offset += 2;
1641         }
1642
1643         return 0; /* bytes_needed */
1644 }
1645
1646
1647 static guint
1648 vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1649                      proto_tree *tree, guint16 width, guint16 height)
1650 {
1651         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1652         guint8 i, subencoding_mask, num_subrects, subrect_len;
1653         guint length;
1654         proto_tree *subencoding_mask_tree, *subrect_tree, *num_subrects_tree;
1655         proto_item *ti;
1656
1657         VNC_BYTES_NEEDED(1);
1658         ti = proto_tree_add_item(tree, hf_vnc_hextile_subencoding_mask, tvb,
1659                                  *offset, 1, FALSE);
1660         subencoding_mask = tvb_get_guint8(tvb, *offset);
1661
1662         subencoding_mask_tree =
1663                 proto_item_add_subtree(ti, ett_vnc_hextile_subencoding_mask);
1664
1665         proto_tree_add_item(subencoding_mask_tree,
1666                             hf_vnc_hextile_raw, tvb, *offset, 1,
1667                             FALSE);
1668         proto_tree_add_item(subencoding_mask_tree,
1669                             hf_vnc_hextile_bg, tvb, *offset, 1,
1670                             FALSE);
1671         proto_tree_add_item(subencoding_mask_tree,
1672                             hf_vnc_hextile_fg, tvb, *offset, 1,
1673                             FALSE);
1674         proto_tree_add_item(subencoding_mask_tree,
1675                             hf_vnc_hextile_anysubrects, tvb, *offset, 1,
1676                             FALSE);
1677         proto_tree_add_item(subencoding_mask_tree,
1678                             hf_vnc_hextile_subrectscolored, tvb, *offset, 1,
1679                             FALSE);
1680         *offset += 1;
1681         
1682         if(subencoding_mask & 0x1) { /* Raw */
1683                 length = width * height * bytes_per_pixel;
1684
1685                 VNC_BYTES_NEEDED(length);
1686
1687                 proto_tree_add_item(tree, hf_vnc_hextile_raw_value, tvb,
1688                                     *offset, length, FALSE);
1689                 *offset += length;
1690         } else { 
1691                 if(subencoding_mask & 0x2) { /* Background Specified */
1692                         proto_tree_add_item(tree, hf_vnc_hextile_bg_value,
1693                                             tvb, *offset, bytes_per_pixel,
1694                                             FALSE);
1695                         *offset += bytes_per_pixel;
1696                 }
1697
1698                 if(subencoding_mask & 0x4) { /* Foreground Specified */
1699                         proto_tree_add_item(tree, hf_vnc_hextile_fg_value,
1700                                             tvb, *offset, bytes_per_pixel,
1701                                             FALSE);
1702                         *offset += bytes_per_pixel;
1703                 }
1704
1705                 if(subencoding_mask & 0x8) { /* Any Subrects */
1706                         ti = proto_tree_add_item(tree,
1707                                                  hf_vnc_hextile_num_subrects,
1708                                                  tvb, *offset, 1,
1709                                                  FALSE);
1710                         num_subrects = tvb_get_guint8(tvb, *offset);
1711                         *offset += 1;
1712                         
1713                         num_subrects_tree =
1714                                 proto_item_add_subtree(ti, ett_vnc_hextile_num_subrects);
1715
1716                         for(i = 1; i <= num_subrects; i++) {
1717
1718                                 if(subencoding_mask & 0x16) 
1719                                         subrect_len = bytes_per_pixel + 2;
1720                                 else
1721                                         subrect_len = 2;
1722
1723                                 ti = proto_tree_add_text(num_subrects_tree, tvb,
1724                                                          *offset, subrect_len,
1725                                                          "Subrectangle #%d", i);
1726
1727                                 subrect_tree = 
1728                                         proto_item_add_subtree(ti, ett_vnc_hextile_subrect);
1729
1730                                 if(subencoding_mask & 0x16) {
1731                                         /* Subrects Colored */
1732                                         proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_pixel_value, tvb, *offset, bytes_per_pixel, FALSE);
1733                                         
1734                                         *offset += bytes_per_pixel;
1735                                 }
1736
1737                                 proto_tree_add_item(subrect_tree,
1738                                                     hf_vnc_hextile_subrect_x_pos, tvb, *offset, 1, FALSE);
1739
1740                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_y_pos, tvb, *offset, 1, FALSE);
1741
1742                                 *offset += 1;
1743
1744                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_width, tvb, *offset, 1, FALSE);
1745
1746                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_height, tvb, *offset, 1, FALSE);
1747
1748                                 *offset += 1;
1749                         }
1750                 }
1751         }
1752
1753         return 0; /* bytes_needed */
1754 }
1755
1756 #ifdef HAVE_LIBZ
1757 static guint
1758 vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1759                   proto_tree *tree, guint16 width, guint16 height)
1760 #else
1761 static guint
1762 vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
1763                   proto_tree *tree, guint16 width _U_, guint16 height _U_)
1764 #endif
1765 {
1766         guint32 data_len;
1767 #ifdef HAVE_LIBZ
1768         guint8 palette_size;
1769         guint8 bytes_per_cpixel = vnc_get_bytes_per_pixel(pinfo);
1770         gint uncomp_offset = 0;
1771         guint length;
1772         gint subencoding_type;
1773         tvbuff_t *uncomp_tvb = NULL;
1774         proto_tree *zrle_subencoding_tree;
1775         proto_item *ti;
1776 #endif
1777
1778         VNC_BYTES_NEEDED(4);
1779         proto_tree_add_item(tree, hf_vnc_zrle_len, tvb, *offset, 
1780                             4, FALSE);
1781         data_len = tvb_get_ntohl(tvb, *offset);
1782
1783         *offset += 4;
1784
1785         VNC_BYTES_NEEDED(data_len);
1786
1787         proto_tree_add_item(tree, hf_vnc_zrle_data, tvb, *offset,
1788                             data_len, FALSE);
1789
1790 #ifdef HAVE_LIBZ
1791         uncomp_tvb = tvb_uncompress(tvb, *offset, data_len);
1792
1793         if(uncomp_tvb != NULL) {
1794                 tvb_set_child_real_data_tvbuff(tvb, uncomp_tvb);
1795                 add_new_data_source(pinfo, uncomp_tvb,
1796                                     "Uncompressed ZRLE data");
1797
1798                 ti = proto_tree_add_item(tree, hf_vnc_zrle_subencoding,
1799                                          uncomp_tvb, uncomp_offset, 1, FALSE);
1800                 zrle_subencoding_tree =
1801                         proto_item_add_subtree(ti, ett_vnc_zrle_subencoding);
1802
1803                 proto_tree_add_item(zrle_subencoding_tree, hf_vnc_zrle_rle,
1804                                     uncomp_tvb, uncomp_offset, 1, FALSE);
1805
1806                 proto_tree_add_item(zrle_subencoding_tree,
1807                                     hf_vnc_zrle_palette_size, uncomp_tvb,
1808                                     uncomp_offset, 1, FALSE);
1809
1810                 subencoding_type = tvb_get_guint8(uncomp_tvb, uncomp_offset);
1811                 palette_size = subencoding_type & 0x7F;
1812
1813                 uncomp_offset += 1;
1814
1815                 if(subencoding_type == 0) { /* Raw */
1816                         length = width * height * bytes_per_cpixel;
1817                         VNC_BYTES_NEEDED(length);
1818
1819                         /* XXX - not working yet! */
1820
1821                         proto_tree_add_item(zrle_subencoding_tree,
1822                                             hf_vnc_zrle_raw, uncomp_tvb,
1823                                             uncomp_offset, length, FALSE);
1824
1825                 } else if(subencoding_type >= 130 && subencoding_type <= 255) {
1826                         length = palette_size * bytes_per_cpixel;
1827                         VNC_BYTES_NEEDED(length);
1828
1829                         proto_tree_add_item(zrle_subencoding_tree,
1830                                             hf_vnc_zrle_palette, uncomp_tvb,
1831                                             uncomp_offset, length, FALSE);
1832                 
1833                         /* XXX - Not complete! */
1834                 }
1835                         
1836         } else {
1837                 proto_tree_add_text(tree, tvb, *offset, data_len,
1838                                     "Decompression of ZRLE data failed");
1839         }
1840 #endif /* HAVE_LIBZ */
1841         
1842         *offset += data_len;
1843
1844         return 0; /* bytes_needed */
1845 }
1846
1847
1848 static guint
1849 read_compact_len(tvbuff_t *tvb, gint *offset, gint *length, gint *value_length)
1850 {
1851         gint b;
1852
1853         VNC_BYTES_NEEDED(1);
1854
1855         *value_length = 0;
1856
1857         b = tvb_get_guint8(tvb, *offset);
1858         *offset += 1;
1859         *value_length += 1;
1860
1861         *length = b & 0x7f;
1862         if ((b & 0x80) != 0) {
1863                 VNC_BYTES_NEEDED(1);
1864
1865                 b = tvb_get_guint8(tvb, *offset);
1866                 *offset += 1;
1867                 *value_length += 1;
1868
1869                 *length |= (b & 0x7f) << 7;
1870
1871                 if ((b & 0x80) != 0) {
1872                         VNC_BYTES_NEEDED (1);
1873
1874                         b = tvb_get_guint8(tvb, *offset);
1875                         *offset += 1;
1876                         *value_length += 1;
1877
1878                         *length |= (b & 0xff) << 14;
1879                 }
1880         }
1881
1882         return 0;
1883 }
1884
1885
1886 static guint
1887 process_compact_length_and_image_data(tvbuff_t *tvb, gint *offset, proto_tree *tree)
1888 {
1889         guint bytes_needed;
1890         guint length, value_length;
1891
1892         bytes_needed = read_compact_len (tvb, offset, &length, &value_length);
1893         if (bytes_needed != 0)
1894                 return bytes_needed;
1895
1896         proto_tree_add_uint(tree, hf_vnc_tight_image_len, tvb, *offset - value_length, value_length, length);
1897
1898         VNC_BYTES_NEEDED(length);
1899         proto_tree_add_item(tree, hf_vnc_tight_image_data, tvb, *offset, length, FALSE);
1900         *offset += length;
1901
1902         return 0; /* bytes_needed */
1903 }
1904
1905
1906 static guint
1907 process_tight_rect_filter_palette(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1908                                   proto_tree *tree, gint *bits_per_pixel)
1909 {
1910         vnc_packet_t *per_packet_info;
1911         gint num_colors;
1912         guint palette_bytes;
1913
1914         /* See TightVNC's vnc_unixsrc/vncviewer/tight.c:InitFilterPaletteBPP() */
1915
1916         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
1917
1918         VNC_BYTES_NEEDED(1);
1919         proto_tree_add_item(tree, hf_vnc_tight_palette_num_colors, tvb, *offset, 1, FALSE);
1920         num_colors = tvb_get_guint8(tvb, *offset);
1921         *offset += 1;
1922
1923         num_colors++;
1924         if (num_colors < 2)
1925                 return 0;
1926
1927         if (per_packet_info->depth == 24)
1928                 palette_bytes = num_colors * 3;
1929         else
1930                 palette_bytes = num_colors * per_packet_info->depth / 8;
1931
1932         VNC_BYTES_NEEDED(palette_bytes);
1933         proto_tree_add_item(tree, hf_vnc_tight_palette_data, tvb, *offset, palette_bytes, FALSE);
1934         *offset += palette_bytes;
1935
1936         /* This is the number of bits per pixel *in the image data*, not the actual client depth */
1937         if (num_colors == 2)
1938                 *bits_per_pixel = 1;
1939         else
1940                 *bits_per_pixel = 8;
1941
1942         return 0;
1943 }
1944
1945 static guint
1946 vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1947                    proto_tree *tree, guint16 width, guint16 height)
1948 {
1949         vnc_packet_t *per_packet_info;
1950         guint8 comp_ctl;
1951         proto_item *compression_type_ti;
1952         gint bit_offset;
1953         gint bytes_needed = -1;
1954
1955         /* unused arguments */
1956         (void) width;
1957         (void) height;
1958
1959         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
1960
1961         /* See xserver/hw/vnc/rfbproto.h and grep for "Tight Encoding." for the following layout */
1962
1963         VNC_BYTES_NEEDED(1);
1964
1965         /* least significant bits 0-3 are "reset compression stream N" */
1966         bit_offset = *offset * 8;
1967         proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream0, tvb, bit_offset + 7, 1, FALSE);
1968         proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream1, tvb, bit_offset + 6, 1, FALSE);
1969         proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream2, tvb, bit_offset + 5, 1, FALSE);
1970         proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream3, tvb, bit_offset + 4, 1, FALSE);
1971
1972         /* most significant bits 4-7 are "compression type" */
1973         compression_type_ti = proto_tree_add_bits_item(tree, hf_vnc_tight_rect_type, tvb, bit_offset + 0, 4, FALSE);
1974
1975         comp_ctl = tvb_get_guint8(tvb, *offset);
1976         *offset += 1;
1977
1978         comp_ctl >>= 4; /* skip over the "reset compression" bits from above */
1979
1980         /* compression format */
1981
1982         if (comp_ctl == TIGHT_RECT_FILL) {
1983                 /* "fill" encoding (solid rectangle) */
1984
1985                 proto_item_append_text(compression_type_ti, " (fill encoding - solid rectangle)");
1986
1987                 if (per_packet_info->depth == 24) {
1988                         VNC_BYTES_NEEDED(3);
1989                         proto_tree_add_item(tree, hf_vnc_tight_fill_color, tvb, *offset, 3, FALSE);
1990                         *offset += 3;
1991                 } else {
1992                         VNC_BYTES_NEEDED(per_packet_info->bytes_per_pixel);
1993                         proto_tree_add_item(tree, hf_vnc_tight_fill_color, tvb, *offset, per_packet_info->bytes_per_pixel, FALSE);
1994                         *offset += per_packet_info->bytes_per_pixel;
1995                 }
1996
1997                 bytes_needed = 0;
1998         } else if (comp_ctl == TIGHT_RECT_JPEG) {
1999                 /* jpeg encoding */
2000
2001                 proto_item_append_text(compression_type_ti, " (JPEG encoding)");
2002                 bytes_needed = process_compact_length_and_image_data(tvb, offset, tree);
2003                 if (bytes_needed != 0)
2004                         return bytes_needed;
2005         } else if (comp_ctl > TIGHT_RECT_MAX_VALUE) {
2006                 /* invalid encoding */
2007
2008                 proto_item_append_text(compression_type_ti, " (invalid encoding)");
2009                 DISSECTOR_ASSERT_NOT_REACHED();
2010         } else {
2011                 guint row_size;
2012                 gint bits_per_pixel;
2013
2014                 /* basic encoding */
2015
2016                 proto_item_append_text(compression_type_ti, " (basic encoding)");
2017
2018                 proto_tree_add_bits_item(tree, hf_vnc_tight_filter_flag, tvb, bit_offset + 1, 1, FALSE);
2019
2020                 bits_per_pixel = per_packet_info->depth;
2021
2022                 if ((comp_ctl & TIGHT_RECT_EXPLICIT_FILTER_FLAG) != 0) {
2023                         guint8 filter_id;
2024
2025                         /* explicit filter */
2026
2027                         VNC_BYTES_NEEDED(1);
2028                         proto_tree_add_item(tree, hf_vnc_tight_filter_id, tvb, *offset, 1, FALSE);
2029                         filter_id = tvb_get_guint8(tvb, *offset);
2030                         *offset += 1;
2031
2032                         switch (filter_id) {
2033                         case TIGHT_RECT_FILTER_COPY:
2034                                 /* nothing to do */
2035                                 break;
2036
2037                         case TIGHT_RECT_FILTER_PALETTE:
2038                                 bytes_needed = process_tight_rect_filter_palette(tvb, pinfo, offset, tree, &bits_per_pixel);
2039                                 if (bytes_needed != 0)
2040                                         return bytes_needed;
2041
2042                                 break;
2043
2044                         case TIGHT_RECT_FILTER_GRADIENT:
2045                                 /* nothing to do */
2046                                 break;
2047                         }
2048                 } else {
2049                         /* this is the same case as TIGHT_RECT_FILTER_COPY, so there's nothing special to do */
2050                 }
2051
2052                 row_size = ((guint) width * bits_per_pixel + 7) / 8;
2053                 if (row_size * height < TIGHT_MIN_BYTES_TO_COMPRESS) {
2054                         guint num_bytes;
2055
2056                         /* The data is not compressed; just skip over it */
2057
2058                         num_bytes = row_size * height;
2059                         VNC_BYTES_NEEDED(num_bytes);
2060                         proto_tree_add_item(tree, hf_vnc_tight_image_data, tvb, *offset, num_bytes, FALSE);
2061                         *offset += num_bytes;
2062
2063                         bytes_needed = 0;
2064                 } else {
2065                         /* The data is compressed; read its length and data */
2066                         bytes_needed = process_compact_length_and_image_data(tvb, offset, tree);
2067                         if (bytes_needed != 0)
2068                                 return bytes_needed;
2069                 }
2070         }
2071
2072         DISSECTOR_ASSERT(bytes_needed != -1);
2073
2074         return bytes_needed;
2075 }
2076
2077
2078 static guint
2079 decode_cursor(tvbuff_t *tvb, gint *offset, proto_tree *tree,
2080               guint pixels_bytes, guint mask_bytes)
2081 {
2082         guint total_bytes;
2083
2084         total_bytes = pixels_bytes + mask_bytes;
2085         VNC_BYTES_NEEDED (total_bytes);
2086
2087         proto_tree_add_item(tree, hf_vnc_cursor_encoding_pixels, tvb, *offset, 
2088                             pixels_bytes, FALSE);
2089         *offset += pixels_bytes;
2090
2091         proto_tree_add_item(tree, hf_vnc_cursor_encoding_bitmask, tvb, *offset,
2092                             mask_bytes, FALSE);
2093         *offset += mask_bytes;
2094
2095         return 0; /* bytes_needed */
2096 }
2097
2098
2099 static guint
2100 vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
2101                          proto_tree *tree, guint16 width, guint16 height)
2102 {
2103         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
2104         guint pixels_bytes, mask_bytes;
2105
2106         pixels_bytes = width * height * bytes_per_pixel;
2107         mask_bytes = ((width + 7) / 8) * height;
2108
2109         return decode_cursor(tvb, offset, tree,
2110                              pixels_bytes, mask_bytes);
2111 }
2112
2113
2114 static guint
2115 vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
2116                       proto_tree *tree, guint16 width, guint16 height)
2117 {
2118         gint bitmap_row_bytes = (width + 7) / 8;
2119         gint mask_bytes = bitmap_row_bytes * height;
2120         (void) pinfo; /* unused argument */
2121
2122         VNC_BYTES_NEEDED (6);
2123         proto_tree_add_item(tree, hf_vnc_cursor_x_fore_back, tvb, *offset, 6, FALSE);
2124         *offset += 6;
2125
2126         /* The length of the pixel data is the same as the length of the mask data (X cursors are strictly black/white) */
2127         return decode_cursor(tvb, offset, tree,
2128                              mask_bytes, mask_bytes);
2129 }
2130
2131
2132 static guint
2133 vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
2134                                 proto_tree *tree)
2135 {
2136         guint16 number_of_colors;
2137         guint counter, bytes_needed;
2138         proto_item *ti;
2139         proto_tree *vnc_colormap_num_groups, *vnc_colormap_color_group;
2140
2141         if (check_col(pinfo->cinfo, COL_INFO))
2142                 col_set_str(pinfo->cinfo, COL_INFO,
2143                             "Server set colormap entries");
2144
2145         number_of_colors = tvb_get_ntohs(tvb, 4);
2146
2147         bytes_needed = (number_of_colors * 6) + 6;
2148         VNC_BYTES_NEEDED(bytes_needed);
2149
2150         ti = proto_tree_add_item(tree, hf_vnc_server_message_type, tvb,
2151                                  *offset, 1, FALSE);
2152         tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
2153         *offset += 1;
2154
2155         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
2156         *offset += 1; /* Skip over 1 byte of padding */
2157
2158         proto_tree_add_item(tree,
2159                             hf_vnc_colormap_first_color,
2160                             tvb, *offset, 2, FALSE);
2161         *offset += 2;
2162
2163         ti = proto_tree_add_item(tree, hf_vnc_colormap_num_colors, tvb,
2164                                  *offset, 2, FALSE);
2165         vnc_colormap_num_groups =
2166                 proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
2167
2168         *offset += 2;
2169
2170         for(counter = 1; counter <= number_of_colors; counter++) {
2171                 ti = proto_tree_add_text(vnc_colormap_num_groups, tvb,
2172                                          *offset, 6,
2173                                          "Color group #%d", counter);
2174
2175                 vnc_colormap_color_group =
2176                         proto_item_add_subtree(ti,
2177                                                ett_vnc_colormap_color_group);
2178
2179                 proto_tree_add_item(vnc_colormap_color_group,
2180                                     hf_vnc_colormap_red, tvb,
2181                                     *offset, 2, FALSE);
2182                 *offset += 2;
2183
2184                 proto_tree_add_item(vnc_colormap_color_group,
2185                                     hf_vnc_colormap_green, tvb,
2186                                     *offset, 2, FALSE);
2187                 *offset += 2;
2188
2189                 proto_tree_add_item(vnc_colormap_color_group,
2190                                     hf_vnc_colormap_blue, tvb,
2191                                     *offset, 2, FALSE);
2192                 *offset += 2;
2193         }
2194         return *offset;
2195 }
2196
2197
2198 static void
2199 vnc_server_ring_bell(tvbuff_t *tvb _U_, packet_info *pinfo, gint *offset _U_,
2200                      proto_tree *tree _U_)
2201 {
2202         if (check_col(pinfo->cinfo, COL_INFO))
2203                 col_set_str(pinfo->cinfo, COL_INFO, "Server ring bell on client");
2204         /* This message type has no payload... */
2205 }
2206
2207
2208 static guint
2209 vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
2210                     proto_tree *tree)
2211 {
2212         guint32 text_len;
2213
2214         if (check_col(pinfo->cinfo, COL_INFO))
2215                 col_set_str(pinfo->cinfo, COL_INFO,
2216                             "Server cut text");
2217
2218         text_len = tvb_get_ntohl(tvb, *offset);
2219         proto_tree_add_item(tree,
2220                             hf_vnc_server_cut_text_len, tvb, *offset, 4,
2221                             FALSE);
2222         *offset += 4;
2223         
2224         VNC_BYTES_NEEDED(text_len);
2225
2226         proto_tree_add_item(tree, hf_vnc_server_cut_text, tvb, *offset,
2227                             text_len, FALSE);
2228         *offset += text_len;
2229
2230         return *offset;
2231 }
2232
2233
2234 static void
2235 vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel)
2236 {
2237         vnc_packet_t *per_packet_info;
2238
2239         /* The per_packet_info has already been created by the
2240          * vnc_startup_messages() routine. */
2241         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
2242         per_packet_info->bytes_per_pixel = bytes_per_pixel;
2243 }
2244
2245
2246 static void
2247 vnc_set_depth(packet_info *pinfo, guint8 depth)
2248 {
2249         vnc_packet_t *per_packet_info;
2250
2251         /* The per_packet_info has already been created by the
2252          * vnc_startup_messages() routine. */
2253         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
2254         per_packet_info->depth = depth;
2255 }
2256
2257
2258 static guint8
2259 vnc_get_bytes_per_pixel(packet_info *pinfo)
2260 {
2261         vnc_packet_t *per_packet_info;
2262
2263         /* The per_packet_info has already been created by the
2264          * vnc_startup_messages() routine. */
2265         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
2266         return per_packet_info->bytes_per_pixel;
2267 }
2268
2269
2270 /* Register the protocol with Wireshark */
2271 void
2272 proto_register_vnc(void)
2273 {
2274         module_t *vnc_module; /* To handle our preferences */
2275
2276         /* Setup list of header fields */
2277         static hf_register_info hf[] = {
2278                 { &hf_vnc_padding,
2279                   { "Padding", "vnc.padding",
2280                     FT_NONE, BASE_NONE, NULL, 0x0,
2281                     "Unused space", HFILL }
2282                 },
2283
2284                 { &hf_vnc_server_proto_ver,
2285                   { "Server protocol version", "vnc.server_proto_ver",
2286                     FT_STRING, BASE_NONE, NULL, 0x0,
2287                     "VNC protocol version on server", HFILL }
2288                 },
2289                 { &hf_vnc_client_proto_ver,
2290                   { "Client protocol version", "vnc.client_proto_ver",
2291                     FT_STRING, BASE_NONE, NULL, 0x0,
2292                     "VNC protocol version on client", HFILL }
2293                 },
2294                 { &hf_vnc_num_security_types,
2295                   { "Number of security types", "vnc.num_security_types",
2296                     FT_UINT8, BASE_DEC, NULL, 0x0,
2297                     "Number of security (authentication) types supported by the server", HFILL }
2298                 },
2299                 { &hf_vnc_security_type,
2300                   { "Security type", "vnc.security_type",
2301                     FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
2302                     "Security types offered by the server (VNC versions => 3.007", HFILL }
2303                 },
2304                 { &hf_vnc_server_security_type,
2305                   { "Security type", "vnc.server_security_type",
2306                     FT_UINT32, BASE_DEC, VALS(security_types_vs), 0x0,
2307                     "Security type mandated by the server", HFILL }
2308                 },
2309                 { &hf_vnc_client_security_type,
2310                   { "Security type selected", "vnc.security_type",
2311                     FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
2312                     "Security type selected by the client", HFILL }
2313                 },
2314                 { &hf_vnc_tight_num_tunnel_types,
2315                   { "Number of supported tunnel types",  "vnc.num_tunnel_types",
2316                     FT_UINT32, BASE_DEC, NULL, 0x0,
2317                     "Number of tunnel types for TightVNC", HFILL }
2318                 },
2319                 { &hf_vnc_tight_tunnel_type,
2320                   { "Tunnel type", "vnc.tunnel_type",
2321                     FT_UINT8, BASE_DEC, NULL, 0x0,
2322                     "Tunnel type specific to TightVNC", HFILL }
2323                 },
2324                 { &hf_vnc_tight_num_auth_types,
2325                   { "Number of supported authentication types", "vnc.num_auth_types",
2326                     FT_UINT32, BASE_DEC, NULL, 0x0,
2327                     "Authentication types specific to TightVNC", HFILL }
2328                 },
2329                 { &hf_vnc_tight_auth_type,
2330                   { "Authentication type", "vnc.auth_type",
2331                     FT_UINT8, BASE_DEC, NULL, 0x0,
2332                     "Authentication type specific to TightVNC", HFILL }
2333                 },
2334                 { &hf_vnc_tight_server_message_type,
2335                   { "Server message type", "vnc.server_message_type",
2336                     FT_INT32, BASE_DEC, NULL, 0x0,
2337                     "Server message type specific to TightVNC", HFILL }
2338                 },
2339                 { &hf_vnc_tight_server_vendor,
2340                   { "Server vendor code", "vnc.server_vendor",
2341                     FT_STRING, BASE_NONE, NULL, 0x0,
2342                     "Server vendor code specific to TightVNC", HFILL }
2343                 },
2344                 { &hf_vnc_tight_server_name,
2345                   { "Server name", "vnc.server_name",
2346                     FT_STRING, BASE_NONE, NULL, 0x0,
2347                     "Server name specific to TightVNC", HFILL }
2348                 },
2349                 { &hf_vnc_tight_client_message_type,
2350                   { "Client message type", "vnc.client_message_type",
2351                     FT_INT32, BASE_DEC, NULL, 0x0,
2352                     "Client message type specific to TightVNC", HFILL }
2353                 },
2354                 { &hf_vnc_tight_client_vendor,
2355                   { "Client vendor code", "vnc.client_vendor",
2356                     FT_STRING, BASE_NONE, NULL, 0x0,
2357                     "Client vendor code specific to TightVNC", HFILL }
2358                 },
2359                 { &hf_vnc_tight_client_name,
2360                   { "Client name", "vnc.client_name",
2361                     FT_STRING, BASE_NONE, NULL, 0x0,
2362                     "Client name specific to TightVNC", HFILL }
2363                 },
2364                 { &hf_vnc_tight_encoding_type,
2365                   { "Encoding type", "vnc.encoding_type",
2366                     FT_INT32, BASE_DEC, NULL, 0x0,
2367                     "Encoding type specific to TightVNC", HFILL }
2368                 },
2369                 { &hf_vnc_tight_encoding_vendor,
2370                   { "Encoding vendor code", "vnc.encoding_vendor",
2371                     FT_STRING, BASE_NONE, NULL, 0x0,
2372                     "Encoding vendor code specific to TightVNC", HFILL }
2373                 },
2374                 { &hf_vnc_tight_encoding_name,
2375                   { "Encoding name", "vnc.encoding_name",
2376                     FT_STRING, BASE_NONE, NULL, 0x0,
2377                     "Encoding name specific to TightVNC", HFILL }
2378                 },
2379                 { &hf_vnc_tight_reset_stream0,
2380                   { "Reset compression stream 0", "vnc.tight_reset_stream0",
2381                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2382                     "Tight compression, reset compression stream 0", HFILL }
2383                 },
2384                 { &hf_vnc_tight_reset_stream1,
2385                   { "Reset compression stream 1", "vnc.tight_reset_stream0",
2386                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2387                     "Tight compression, reset compression stream 1", HFILL }
2388                 },
2389                 { &hf_vnc_tight_reset_stream2,
2390                   { "Reset compression stream 2", "vnc.tight_reset_stream0",
2391                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2392                     "Tight compression, reset compression stream 2", HFILL }
2393                 },
2394                 { &hf_vnc_tight_reset_stream3,
2395                   { "Reset compression stream 3", "vnc.tight_reset_stream0",
2396                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2397                     "Tight compression, reset compression stream 3", HFILL }
2398                 },
2399                 { &hf_vnc_tight_rect_type,
2400                   { "Rectangle type", "vnc.tight_rect_type",
2401                     FT_UINT8, BASE_HEX, NULL, 0x0,
2402                     "Tight compression, rectangle type", HFILL }
2403                 },
2404                 { &hf_vnc_tight_image_len,
2405                   { "Image data length", "vnc.tight_image_len",
2406                     FT_UINT32, BASE_DEC, NULL, 0x0,
2407                     "Tight compression, length of image data", HFILL }
2408                 },
2409                 { &hf_vnc_tight_image_data,
2410                   { "Image data", "vnc.tight_image_data",
2411                     FT_BYTES, BASE_NONE, NULL, 0x0,
2412                     "Tight compression, image data", HFILL }
2413                 },
2414                 { &hf_vnc_tight_fill_color,
2415                   { "Fill color (RGB)", "vnc.tight_fill_color",
2416                     FT_BYTES, BASE_NONE, NULL, 0x0,
2417                     "Tight compression, fill color for solid rectangle", HFILL }
2418                 },
2419                 { &hf_vnc_tight_filter_flag,
2420                   { "Explicit filter flag", "vnc.tight_filter_flag",
2421                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2422                     "Tight compression, explicit filter flag", HFILL }
2423                 },
2424                 { &hf_vnc_tight_filter_id,
2425                   { "Filter ID", "vnc.tight_filter_id",
2426                     FT_UINT8, BASE_DEC, VALS(tight_filter_ids_vs), 0x0,
2427                     "Tight compression, filter ID", HFILL }
2428                 },
2429                 { &hf_vnc_tight_palette_num_colors,
2430                   { "Number of colors in palette", "vnc.tight_palette_num_colors",
2431                     FT_UINT8, BASE_DEC, NULL, 0x0,
2432                     "Tight compression, number of colors in rectangle's palette", HFILL }
2433                 },
2434                 { &hf_vnc_tight_palette_data,
2435                   { "Palette data", "vnc.tight_palette_data",
2436                     FT_BYTES, BASE_NONE, NULL, 0x0,
2437                     "Tight compression, palette data for a rectangle", HFILL }
2438                 },
2439                 { &hf_vnc_vendor_code,
2440                   { "Vendor code", "vnc.vendor_code",
2441                     FT_STRING, BASE_NONE, NULL, 0x0,
2442                     "Identifies the VNC server software's vendor", HFILL }
2443                 },
2444                 { &hf_vnc_security_type_string,
2445                   { "Security type string", "vnc.security_type_string",
2446                     FT_STRING, BASE_NONE, NULL, 0x0,
2447                     "Security type being used", HFILL }
2448                 },
2449                 { &hf_vnc_auth_challenge,
2450                   { "Authentication challenge", "vnc.auth_challenge",
2451                     FT_STRING, BASE_NONE, NULL, 0x0,
2452                     "Random authentication challenge from server to client", HFILL }
2453                 },
2454                 { &hf_vnc_auth_response,
2455                   { "Authentication response", "vnc.auth_response",
2456                     FT_STRING, BASE_NONE, NULL, 0x0,
2457                     "Client's encrypted response to the server's authentication challenge", HFILL }
2458                 },
2459                 { &hf_vnc_auth_result,
2460                   { "Authentication result", "vnc.auth_result",
2461                     FT_UINT32, BASE_DEC, VALS(auth_result_vs), 0x0,
2462                     "Authentication result", HFILL }
2463                 },
2464                 { &hf_vnc_auth_error,
2465                   { "Authentication error", "vnc.auth_error",
2466                     FT_STRING, BASE_NONE, NULL, 0x0,
2467                     "Authentication error (present only if the authentication result is fail", HFILL }
2468                 },
2469                 { &hf_vnc_share_desktop_flag,
2470                   { "Share desktop flag", "vnc.share_desktop_flag",
2471                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
2472                     "Client's desire to share the server's desktop with other clients", HFILL }
2473                 },
2474                 { &hf_vnc_width,
2475                   { "Framebuffer width", "vnc.width",
2476                     FT_UINT16, BASE_DEC, NULL, 0x0,
2477                     "Width of the framebuffer (screen) in pixels", HFILL }
2478                 },
2479                 { &hf_vnc_height,
2480                   { "Framebuffer height", "vnc.width",
2481                     FT_UINT16, BASE_DEC, NULL, 0x0,
2482                     "Height of the framebuffer (screen) in pixels", HFILL }
2483                 },
2484                 { &hf_vnc_server_bits_per_pixel,
2485                   { "Bits per pixel", "vnc.server_bits_per_pixel",
2486                     FT_UINT8, BASE_DEC, NULL, 0x0,
2487                     "Number of bits used by server for each pixel value on the wire from the server", HFILL }
2488                 },
2489                 { &hf_vnc_server_depth,
2490                   { "Depth", "vnc.server_depth",
2491                     FT_UINT8, BASE_DEC, NULL, 0x0,
2492                     "Number of useful bits in the pixel value on server", HFILL }
2493                 },
2494                 { &hf_vnc_server_big_endian_flag,
2495                   { "Big endian flag", "vnc.server_big_endian_flag",
2496                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2497                     "True if multi-byte pixels are interpreted as big endian by server", HFILL }
2498                 },
2499                 { &hf_vnc_server_true_color_flag,
2500                   { "True color flag", "vnc.server_true_color_flag",
2501                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2502                     "If true, then the next six items specify how to extract the red, green and blue intensities from the pixel value on the server.", HFILL }
2503                 },
2504                 { &hf_vnc_server_red_max,
2505                   { "Red maximum", "vnc.server_red_max",
2506                     FT_UINT16, BASE_DEC, NULL, 0x0,
2507                     "Maximum red value on server as n: 2^n - 1", HFILL }
2508                 },
2509                 { &hf_vnc_server_green_max,
2510                   { "Green maximum", "vnc.server_green_max",
2511                     FT_UINT16, BASE_DEC, NULL, 0x0,
2512                     "Maximum green value on server as n: 2^n - 1", HFILL }
2513                 },
2514                 { &hf_vnc_server_blue_max,
2515                   { "Blue maximum", "vnc.server_blue_max",
2516                     FT_UINT16, BASE_DEC, NULL, 0x0,
2517                     "Maximum blue value on server as n: 2^n - 1", HFILL }
2518                 },
2519                 { &hf_vnc_server_red_shift,
2520                   { "Red shift", "vnc.server_red_shift",
2521                     FT_UINT8, BASE_DEC, NULL, 0x0,
2522                     "Number of shifts needed to get the red value in a pixel to the least significant bit on the server", HFILL }
2523                 },
2524                 { &hf_vnc_server_green_shift,
2525                   { "Green shift", "vnc.server_green_shift",
2526                     FT_UINT8, BASE_DEC, NULL, 0x0,
2527                     "Number of shifts needed to get the green value in a pixel to the least significant bit on the server", HFILL }
2528                 },
2529                 { &hf_vnc_server_blue_shift,
2530                   { "Blue shift", "vnc.server_blue_shift",
2531                     FT_UINT8, BASE_DEC, NULL, 0x0,
2532                     "Number of shifts needed to get the blue value in a pixel to the least significant bit on the server", HFILL }
2533                 },
2534                 { &hf_vnc_desktop_name_len,
2535                   { "Desktop name length", "vnc.desktop_name_len",
2536                     FT_UINT32, BASE_DEC, NULL, 0x0,
2537                     "Length of desktop name in bytes", HFILL }
2538                 },
2539                 { &hf_vnc_desktop_name,
2540                   { "Desktop name", "vnc.desktop_name",
2541                     FT_STRING, BASE_NONE, NULL, 0x0,
2542                     "Name of the VNC desktop on the server", HFILL }
2543                 },
2544                 { &hf_vnc_num_server_message_types,
2545                   { "Server message types", "vnc.num_server_message_types",
2546                     FT_UINT16, BASE_DEC, NULL, 0x0,
2547                     "Unknown", HFILL } /* XXX - Needs description */
2548                 },
2549                 { &hf_vnc_num_client_message_types,
2550                   { "Client message types", "vnc.num_client_message_types",
2551                     FT_UINT16, BASE_DEC, NULL, 0x0,
2552                     "Unknown", HFILL } /* XXX - Needs description */
2553                 },
2554                 { &hf_vnc_num_encoding_types,
2555                   { "Encoding types", "vnc.num_encoding_types",
2556                     FT_UINT16, BASE_DEC, NULL, 0x0,
2557                     "Unknown", HFILL } /* XXX - Needs description */
2558                 },
2559                 { &hf_vnc_client_message_type,
2560                   { "Client Message Type", "vnc.client_message_type",
2561                     FT_UINT8, BASE_DEC, VALS(client_message_types_vs), 0x0,
2562                     "Message type from client", HFILL }
2563                 },
2564                 { &hf_vnc_client_bits_per_pixel,
2565                   { "Bits per pixel", "vnc.client_bits_per_pixel",
2566                     FT_UINT8, BASE_DEC, NULL, 0x0,
2567                     "Number of bits used by server for each pixel value on the wire from the client", HFILL }
2568                 },
2569                 { &hf_vnc_client_depth,
2570                   { "Depth", "vnc.client_depth",
2571                     FT_UINT8, BASE_DEC, NULL, 0x0,
2572                     "Number of useful bits in the pixel value on client", HFILL }
2573                 },
2574                 { &hf_vnc_client_big_endian_flag,
2575                   { "Big endian flag", "vnc.client_big_endian_flag",
2576                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2577                     "True if multi-byte pixels are interpreted as big endian by client", HFILL }
2578                 },
2579                 { &hf_vnc_client_true_color_flag,
2580                   { "True color flag", "vnc.client_true_color_flag",
2581                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2582                     "If true, then the next six items specify how to extract the red, green and blue intensities from the pixel value on the client.", HFILL }
2583                 },
2584                 { &hf_vnc_client_red_max,
2585                   { "Red maximum", "vnc.client_red_max",
2586                     FT_UINT16, BASE_DEC, NULL, 0x0,
2587                     "Maximum red value on client as n: 2^n - 1", HFILL }
2588                 },
2589                 { &hf_vnc_client_green_max,
2590                   { "Green maximum", "vnc.client_green_max",
2591                     FT_UINT16, BASE_DEC, NULL, 0x0,
2592                     "Maximum green value on client as n: 2^n - 1", HFILL }
2593                 },
2594                 { &hf_vnc_client_blue_max,
2595                   { "Blue maximum", "vnc.client_blue_max",
2596                     FT_UINT16, BASE_DEC, NULL, 0x0,
2597                     "Maximum blue value on client as n: 2^n - 1", HFILL }
2598                 },
2599                 { &hf_vnc_client_red_shift,
2600                   { "Red shift", "vnc.client_red_shift",
2601                     FT_UINT8, BASE_DEC, NULL, 0x0,
2602                     "Number of shifts needed to get the red value in a pixel to the least significant bit on the client", HFILL }
2603                 },
2604                 { &hf_vnc_client_green_shift,
2605                   { "Green shift", "vnc.client_green_shift",
2606                     FT_UINT8, BASE_DEC, NULL, 0x0,
2607                     "Number of shifts needed to get the green value in a pixel to the least significant bit on the client", HFILL }
2608                 },
2609                 { &hf_vnc_client_blue_shift,
2610                   { "Blue shift", "vnc.client_blue_shift",
2611                     FT_UINT8, BASE_DEC, NULL, 0x0,
2612                     "Number of shifts needed to get the blue value in a pixel to the least significant bit on the client", HFILL }
2613                 },
2614
2615                 /* Client Key Event */
2616                 { &hf_vnc_key_down,
2617                   { "Key down", "vnc.key_down",
2618                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
2619                     "Specifies whether the key is being pressed or not", HFILL }
2620                 },
2621                 { &hf_vnc_key,
2622                   { "Key", "vnc.key",
2623                     FT_UINT32, BASE_HEX, VALS(keysym_vals_source), 0x0, /* keysym_vals_source is from packet-x11-keysym.h */
2624                     "Key being pressed/depressed", HFILL }
2625                 },
2626
2627                 /* Client Pointer Event */
2628                 { &hf_vnc_button_1_pos,
2629                   { "Mouse button #1 position", "vnc.button_1_pos",
2630                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x1,
2631                     "Whether mouse button #1 is being pressed or not", HFILL }
2632                 },
2633                 { &hf_vnc_button_2_pos,
2634                   { "Mouse button #2 position", "vnc.button_2_pos",
2635                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x2,
2636                     "Whether mouse button #2 is being pressed or not", HFILL }
2637                 },
2638                 { &hf_vnc_button_3_pos,
2639                   { "Mouse button #3 position", "vnc.button_3_pos",
2640                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x4,
2641                     "Whether mouse button #3 is being pressed or not", HFILL }
2642                 },
2643                 { &hf_vnc_button_4_pos,
2644                   { "Mouse button #4 position", "vnc.button_4_pos",
2645                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x8,
2646                     "Whether mouse button #4 is being pressed or not", HFILL }
2647                 },
2648                 { &hf_vnc_button_5_pos,
2649                   { "Mouse button #5 position", "vnc.button_5_pos",
2650                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x10,
2651                     "Whether mouse button #5 is being pressed or not", HFILL }
2652                 },
2653                 { &hf_vnc_button_6_pos,
2654                   { "Mouse button #6 position", "vnc.button_6_pos",
2655                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x20,
2656                     "Whether mouse button #6 is being pressed or not", HFILL }
2657                 },
2658                 { &hf_vnc_button_7_pos,
2659                   { "Mouse button #7 position", "vnc.button_7_pos",
2660                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x40,
2661                     "Whether mouse button #7 is being pressed or not", HFILL }
2662                 },
2663                 { &hf_vnc_button_8_pos,
2664                   { "Mouse button #8 position", "vnc.button_8_pos",
2665                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x80,
2666                     "Whether mouse button #8 is being pressed or not", HFILL }
2667                 },
2668                 { &hf_vnc_pointer_x_pos,
2669                   { "X position", "vnc.pointer_x_pos",
2670                     FT_UINT16, BASE_DEC, NULL, 0x0,
2671                     "Position of mouse cursor on the x-axis", HFILL }
2672                 },
2673                 { &hf_vnc_pointer_y_pos,
2674                   { "Y position", "vnc.pointer_y_pos",
2675                     FT_UINT16, BASE_DEC, NULL, 0x0,
2676                     "Position of mouse cursor on the y-axis", HFILL }
2677                 },
2678                 { &hf_vnc_client_set_encodings_encoding_type,
2679                   { "Encoding type", "vnc.client_set_encodings_encoding_type",
2680                     FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
2681                     "Type of encoding used to send pixel data from server to client", HFILL }
2682                 },
2683
2684                 /* Client Framebuffer Update Request */
2685                 { &hf_vnc_update_req_incremental,
2686                   { "Incremental update", "vnc.update_req_incremental",
2687                     FT_BOOLEAN, BASE_DEC, NULL, 0x0,
2688                     "Specifies if the client wants an incremental update instead of a full one", HFILL }
2689                 },
2690                 { &hf_vnc_update_req_x_pos,
2691                   { "X position", "vnc.update_req_x_pos",
2692                     FT_UINT16, BASE_DEC, NULL, 0x0,
2693                     "X position of framebuffer (screen) update requested", HFILL }
2694                 },
2695                 { &hf_vnc_update_req_y_pos,
2696                   { "Y position", "vnc.update_req_y_pos",
2697                     FT_UINT16, BASE_DEC, NULL, 0x0,
2698                     "Y position of framebuffer (screen) update request", HFILL }
2699                 },
2700                 { &hf_vnc_update_req_width,
2701                   { "Width", "vnc.update_req_width",
2702                     FT_UINT16, BASE_DEC, NULL, 0x0,
2703                     "Width of framebuffer (screen) update request", HFILL }
2704                 },
2705                 { &hf_vnc_update_req_height,
2706                   { "Height", "vnc.update_req_height",
2707                     FT_UINT16, BASE_DEC, NULL, 0x0,
2708                     "Height of framebuffer (screen) update request", HFILL }
2709                 },
2710                 { &hf_vnc_client_cut_text_len,
2711                   { "Length", "vnc.client_cut_text_len",
2712                     FT_UINT32, BASE_DEC, NULL, 0x0,
2713                     "Length of client's copy/cut text (clipboard) string in bytes", HFILL }
2714                 },
2715                 { &hf_vnc_client_cut_text,
2716                   { "Text", "vnc.client_cut_text",
2717                     FT_STRING, BASE_NONE, NULL, 0x0,
2718                     "Text string in the client's copy/cut text (clipboard)", HFILL }
2719                 },
2720
2721
2722                 /********** Server Message Types **********/
2723                 { &hf_vnc_server_message_type,
2724                   { "Server Message Type", "vnc.server_message_type",
2725                     FT_UINT8, BASE_DEC, VALS(server_message_types_vs), 0x0,
2726                     "Message type from server", HFILL }
2727                 },
2728
2729                 { &hf_vnc_fb_update_x_pos,
2730                   { "X position", "vnc.fb_update_x_pos",
2731                     FT_UINT16, BASE_DEC, NULL, 0x0,
2732                     "X position of this server framebuffer update", HFILL }
2733                 },
2734
2735                 { &hf_vnc_fb_update_y_pos,
2736                   { "Y position", "vnc.fb_update_x_pos",
2737                     FT_UINT16, BASE_DEC, NULL, 0x0,
2738                     "Y position of this server framebuffer update", HFILL }
2739                 },
2740
2741                 { &hf_vnc_fb_update_width,
2742                   { "Width", "vnc.fb_update_width",
2743                     FT_UINT16, BASE_DEC, NULL, 0x0,
2744                     "Width of this server framebuffer update", HFILL }
2745                 },
2746
2747                 { &hf_vnc_fb_update_height,
2748                   { "Height", "vnc.fb_update_height",
2749                     FT_UINT16, BASE_DEC, NULL, 0x0,
2750                     "Height of this server framebuffer update", HFILL }
2751                 },
2752
2753                 { &hf_vnc_fb_update_encoding_type,
2754                   { "Encoding type", "vnc.fb_update_encoding_type",
2755                     FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
2756                     "Encoding type of this server framebuffer update", HFILL }
2757                 },
2758
2759                 /* Cursor encoding */
2760                 { &hf_vnc_cursor_x_fore_back,
2761                   { "X Cursor foreground RGB / background RGB", "vnc.cursor_x_fore_back",
2762                     FT_BYTES, BASE_NONE, NULL, 0x0,
2763                     "RGB values for the X cursor's foreground and background", HFILL }
2764                 },
2765
2766                 { &hf_vnc_cursor_encoding_pixels,
2767                   { "Cursor encoding pixels", "vnc.cursor_encoding_pixels",
2768                     FT_BYTES, BASE_NONE, NULL, 0x0,
2769                     "Cursor encoding pixel data", HFILL }
2770                 },              
2771
2772                 { &hf_vnc_cursor_encoding_bitmask,
2773                   { "Cursor encoding bitmask", "vnc.cursor_encoding_bitmask",
2774                     FT_BYTES, BASE_NONE, NULL, 0x0,
2775                     "Cursor encoding pixel bitmask", HFILL }
2776                 },              
2777
2778                 /* Raw Encoding */
2779                 { &hf_vnc_raw_pixel_data,
2780                   { "Pixel data", "vnc.raw_pixel_data",
2781                     FT_BYTES, BASE_NONE, NULL, 0x0,
2782                     "Raw pixel data.", HFILL }
2783                 },              
2784
2785                 /* CopyRect Encoding*/
2786                 { &hf_vnc_copyrect_src_x_pos,
2787                   { "Source x position", "vnc.copyrect_src_x_pos",
2788                     FT_UINT16, BASE_DEC, NULL, 0x0,
2789                     "X position of the rectangle to copy from", HFILL }
2790                 },              
2791
2792                 { &hf_vnc_copyrect_src_y_pos,
2793                   { "Source y position", "vnc.copyrect_src_y_pos",
2794                     FT_UINT16, BASE_DEC, NULL, 0x0,
2795                     "Y position of the rectangle to copy from", HFILL }
2796                 },              
2797
2798                 /* RRE Encoding */
2799                 { &hf_vnc_rre_num_subrects,
2800                   { "Number of subrectangles", "vnc.rre_num_subrects",
2801                     FT_UINT32, BASE_DEC, NULL, 0x0,
2802                     "Number of subrectangles contained in this encoding type", HFILL }
2803                 },
2804
2805                 { &hf_vnc_rre_bg_pixel,
2806                   { "Background pixel value", "vnc.rre_bg_pixel",
2807                     FT_BYTES, BASE_NONE, NULL, 0x0,
2808                     "Background pixel value", HFILL }
2809                 },
2810
2811                 { &hf_vnc_rre_subrect_pixel,
2812                   { "Pixel value", "vnc.rre_subrect_pixel",
2813                     FT_BYTES, BASE_NONE, NULL, 0x0,
2814                     "Subrectangle pixel value", HFILL }
2815                 },
2816
2817                 { &hf_vnc_rre_subrect_x_pos,
2818                   { "X position", "vnc.rre_subrect_x_pos",
2819                     FT_UINT16, BASE_DEC, NULL, 0x0,
2820                     "Position of this subrectangle on the x axis", HFILL }
2821                 },
2822
2823                 { &hf_vnc_rre_subrect_y_pos,
2824                   { "Y position", "vnc.rre_subrect_y_pos",
2825                     FT_UINT16, BASE_DEC, NULL, 0x0,
2826                     "Position of this subrectangle on the y axis", HFILL }
2827                 },
2828
2829                 { &hf_vnc_rre_subrect_width,
2830                   { "Width", "vnc.rre_subrect_width",
2831                     FT_UINT16, BASE_DEC, NULL, 0x0,
2832                     "Width of this subrectangle", HFILL }
2833                 },
2834
2835                 { &hf_vnc_rre_subrect_height,
2836                   { "Height", "vnc.rre_subrect_height",
2837                     FT_UINT16, BASE_DEC, NULL, 0x0,
2838                     "Height of this subrectangle", HFILL }
2839                 },
2840
2841
2842                 /* Hextile Encoding */
2843                 { &hf_vnc_hextile_subencoding_mask,
2844                   { "Subencoding type", "vnc.hextile_subencoding",
2845                     FT_UINT8, BASE_DEC, NULL, 0x0,
2846                     "Hextile subencoding type.", HFILL }
2847                 },              
2848
2849                 { &hf_vnc_hextile_raw,
2850                   { "Raw", "vnc.hextile_raw",
2851                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x1,
2852                     "Raw subencoding is used in this tile", HFILL }
2853                 },              
2854
2855                 { &hf_vnc_hextile_raw_value,
2856                   { "Raw pixel values", "vnc.hextile_raw_value",
2857                     FT_BYTES, BASE_NONE, NULL, 0x0,
2858                     "Raw subencoding pixel values", HFILL }
2859                 },              
2860
2861                 { &hf_vnc_hextile_bg,
2862                   { "Background Specified", "vnc.hextile_bg",
2863                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x2,
2864                     "Background Specified subencoding is used in this tile", HFILL }
2865                 },
2866
2867                 { &hf_vnc_hextile_bg_value,
2868                   { "Background pixel value", "vnc.hextile_bg_value",
2869                     FT_BYTES, BASE_NONE, NULL, 0x0,
2870                     "Background color for this tile", HFILL }
2871                 },
2872
2873                 { &hf_vnc_hextile_fg,
2874                   { "Foreground Specified", "vnc.hextile_fg",
2875                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x4,
2876                     "Foreground Specified subencoding is used in this tile", HFILL }
2877                 },              
2878
2879                 { &hf_vnc_hextile_fg_value,
2880                   { "Foreground pixel value", "vnc.hextile_fg_value",
2881                     FT_BYTES, BASE_NONE, NULL, 0x0,
2882                     "Foreground color for this tile", HFILL }
2883                 },
2884
2885                 { &hf_vnc_hextile_anysubrects,
2886                   { "Any Subrects", "vnc.hextile_anysubrects",
2887                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x8,
2888                     "Any subrects subencoding is used in this tile", HFILL }
2889                 },              
2890
2891                 { &hf_vnc_hextile_num_subrects,
2892                   { "Number of subrectangles", "vnc.hextile_num_subrects",
2893                     FT_UINT8, BASE_DEC, NULL, 0x0,
2894                     "Number of subrectangles that follow", HFILL }
2895                 },              
2896
2897                 { &hf_vnc_hextile_subrectscolored,
2898                   { "Subrects Colored", "vnc.hextile_subrectscolored",
2899                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x10,
2900                     "Subrects colored subencoding is used in this tile", HFILL }
2901                 },              
2902
2903                 { &hf_vnc_hextile_subrect_pixel_value,
2904                   { "Pixel value", "vnc.hextile_subrect_pixel_value",
2905                     FT_BYTES, BASE_NONE, NULL, 0x0,
2906                     "Pixel value of this subrectangle", HFILL }
2907                 },              
2908
2909                 { &hf_vnc_hextile_subrect_x_pos,
2910                   { "X position", "vnc.hextile_subrect_x_pos",
2911                     FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
2912                     "X position of this subrectangle", HFILL }
2913                 },              
2914
2915                 { &hf_vnc_hextile_subrect_y_pos,
2916                   { "Y position", "vnc.hextile_subrect_y_pos",
2917                     FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
2918                     "Y position of this subrectangle", HFILL }
2919                 },              
2920
2921                 { &hf_vnc_hextile_subrect_width,
2922                   { "Width", "vnc.hextile_subrect_width",
2923                     FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
2924                     "Subrectangle width minus one", HFILL }
2925                 },              
2926
2927                 { &hf_vnc_hextile_subrect_height,
2928                   { "Height", "vnc.hextile_subrect_height",
2929                     FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
2930                     "Subrectangle height minus one", HFILL }
2931                 },              
2932
2933
2934                 /* ZRLE Encoding */
2935                 { &hf_vnc_zrle_len,
2936                   { "ZRLE compressed length", "vnc.zrle_len",
2937                     FT_UINT32, BASE_DEC, NULL, 0x0,
2938                     "Length of compressed ZRLE data that follows", HFILL }
2939                 },
2940
2941                 { &hf_vnc_zrle_subencoding,
2942                   { "Subencoding type", "vnc.zrle_subencoding",
2943                     FT_UINT8, BASE_DEC, NULL, 0x0,
2944                     "Subencoding type byte", HFILL }
2945                 },
2946
2947                 { &hf_vnc_zrle_rle,
2948                   { "RLE", "vnc.zrle_rle",
2949                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x80, /* Upper bit */
2950                     "Specifies that data is run-length encoded", HFILL }
2951                 },
2952
2953                 { &hf_vnc_zrle_palette_size,
2954                   { "Palette size", "vnc.zrle_palette_size",
2955                     FT_UINT8, BASE_DEC, NULL, 0x7F, /* Lower 7 bits */
2956                     "Palette size", HFILL }
2957                 },
2958
2959                 { &hf_vnc_zrle_data,
2960                   { "ZRLE compressed data", "vnc.zrle_data",
2961                     FT_BYTES, BASE_NONE, NULL, 0x0,
2962                     "Compressed ZRLE data.  Compiling with zlib support will uncompress and dissect this data", HFILL }
2963                 },
2964
2965                 { &hf_vnc_zrle_raw,
2966                   { "Pixel values", "vnc.zrle_raw",
2967                     FT_BYTES, BASE_NONE, NULL, 0x0,
2968                     "Raw pixel values for this tile", HFILL }
2969                 },
2970
2971                 { &hf_vnc_zrle_palette,
2972                   { "Palette", "vnc.zrle_palette",
2973                     FT_BYTES, BASE_NONE, NULL, 0x0,
2974                     "Palette pixel values", HFILL }
2975                 },
2976
2977                 /* Server Set Colormap Entries */
2978                 { &hf_vnc_colormap_first_color,
2979                   { "First color", "vnc.colormap_first_color",
2980                     FT_UINT16, BASE_DEC, NULL, 0x0,
2981                     "First color that should be mapped to given RGB intensities", HFILL }
2982                 },
2983                 { &hf_vnc_colormap_num_colors,
2984                   { "Number of color groups", "vnc.colormap_groups",
2985                     FT_UINT16, BASE_DEC, NULL, 0x0,
2986                     "Number of red/green/blue color groups", HFILL }
2987                 },
2988                 { &hf_vnc_colormap_red,
2989                   { "Red", "vnc.colormap_red",
2990                     FT_UINT16, BASE_DEC, NULL, 0x0,
2991                     "Red intensity", HFILL }
2992                 },
2993                 { &hf_vnc_colormap_green,
2994                   { "Green", "vnc.colormap_green",
2995                     FT_UINT16, BASE_DEC, NULL, 0x0,
2996                     "Green intensity", HFILL }
2997                 },
2998                 { &hf_vnc_colormap_blue,
2999                   { "Blue", "vnc.colormap_blue",
3000                     FT_UINT16, BASE_DEC, NULL, 0x0,
3001                     "Blue intensity", HFILL }
3002                 },
3003
3004                 /* Server Cut Text */
3005                 { &hf_vnc_server_cut_text_len,
3006                   { "Length", "vnc.server_cut_text_len",
3007                     FT_UINT32, BASE_DEC, NULL, 0x0,
3008                     "Length of server's copy/cut text (clipboard) string in bytes", HFILL }
3009                 },
3010                 { &hf_vnc_server_cut_text,
3011                   { "Text", "vnc.server_cut_text",
3012                     FT_STRING, BASE_NONE, NULL, 0x0,
3013                     "Text string in the server's copy/cut text (clipboard)", HFILL }
3014                 },
3015         };
3016
3017         /* Setup protocol subtree arrays */
3018         static gint *ett[] = {
3019                 &ett_vnc,
3020                 &ett_vnc_client_message_type,
3021                 &ett_vnc_server_message_type,
3022                 &ett_vnc_rect,
3023                 &ett_vnc_encoding_type,
3024                 &ett_vnc_rre_subrect,
3025                 &ett_vnc_hextile_subencoding_mask,
3026                 &ett_vnc_hextile_num_subrects,
3027                 &ett_vnc_hextile_subrect,
3028                 &ett_vnc_zrle_subencoding,
3029                 &ett_vnc_colormap_num_groups,
3030                 &ett_vnc_colormap_color_group
3031         };
3032
3033         /* Register the protocol name and description */
3034         proto_vnc = proto_register_protocol("Virtual Network Computing",
3035                                             "VNC", "vnc");
3036
3037         /* Required function calls to register the header fields and subtrees */
3038         proto_register_field_array(proto_vnc, hf, array_length(hf));
3039         proto_register_subtree_array(ett, array_length(ett));
3040
3041         /* Register our preferences module */
3042         vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);
3043
3044         prefs_register_bool_preference(vnc_module, "desegment", "Reassemble VNC messages spanning multiple TCP segments.", "Whether the VNC dissector should reasss emble messages spanning multiple TCP segments.  To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &vnc_preference_desegment);
3045
3046         prefs_register_uint_preference(vnc_module, "alternate_port", "Alternate TCP port", "Decode this port's traffic as VNC in addition to the default ports (5500, 5501, 5900, 5901)", 10, &vnc_preference_alternate_port);
3047
3048 }
3049
3050 void
3051 proto_reg_handoff_vnc(void)
3052 {
3053         static gboolean inited = FALSE;
3054         static dissector_handle_t vnc_handle;
3055         /* This is a behind the scenes variable that is not changed by the user.
3056          * This stores last setting of the vnc_preference_alternate_port.  Used to keep
3057          * track of when the user has changed the setting so that we can delete
3058          * and re-register with the new port number. */
3059         static guint vnc_preference_alternate_port_last = 0;
3060
3061         if(!inited) {
3062                 vnc_handle = create_dissector_handle(dissect_vnc, proto_vnc);
3063
3064                 dissector_add("tcp.port", 5500, vnc_handle);
3065                 dissector_add("tcp.port", 5501, vnc_handle);
3066                 dissector_add("tcp.port", 5900, vnc_handle);
3067                 dissector_add("tcp.port", 5901, vnc_handle);
3068
3069                 /* We don't register a port for the VNC HTTP server because
3070                  * that simply provides a java program for download via the
3071                  * HTTP protocol.  The java program then connects to a standard
3072                  * VNC port. */
3073
3074                 inited = TRUE;
3075         } else {  /* only after preferences have been read/changed */
3076                 if(vnc_preference_alternate_port != vnc_preference_alternate_port_last &&
3077                    vnc_preference_alternate_port != 5500 &&
3078                    vnc_preference_alternate_port != 5501 &&
3079                    vnc_preference_alternate_port != 5900 &&
3080                    vnc_preference_alternate_port != 5901) {
3081                         if (vnc_preference_alternate_port_last != 0) {
3082                                 dissector_delete("tcp.port",
3083                                                  vnc_preference_alternate_port_last,
3084                                                  vnc_handle);
3085                         }
3086                         /* Save this setting to see if has changed later */
3087                         vnc_preference_alternate_port_last =
3088                                 vnc_preference_alternate_port;
3089
3090                         /* Register the new port setting */
3091                         if (vnc_preference_alternate_port != 0) {
3092                                 dissector_add("tcp.port", 
3093                                               vnc_preference_alternate_port,
3094                                               vnc_handle);
3095                         }
3096                 }
3097         }
3098 }