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