Major overhaul of VNC dissector: split everything into its own function and
[obnox/wireshark/wip.git] / epan / dissectors / packet-vnc.c
1 /* packet-vnc.c
2  * Routines for VNC dissection (Virtual Network Computing)
3  * Copyright 2005, Ulf Lamping <ulf.lamping@web.de>
4  * Copyright 2006-2007, Stephen Fisher <stephentfisher@yahoo.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /* Dissection of the VNC (Virtual Network Computing) network traffic.
28  *
29  * Both versions of RealVNC (3.3 and 3.8) are supported.
30  *
31  * Several VNC implementations available, see:
32  * http://www.realvnc.com/
33  * http://www.tightvnc.com/
34  * http://ultravnc.sourceforge.net/
35  * ...
36  *
37  * The protocol itself is known as RFB - Remote Frame Buffer Protocol.
38  *
39  * This code is based on the protocol specification:
40  *   http://www.realvnc.com/docs/rfbproto.pdf
41  *  and the RealVNC free edition source code
42  */
43
44
45 /* XXX - We can delete entries in the tree, can't we? for when desegmenting */
46
47 #ifdef HAVE_CONFIG_H
48 # include "config.h"
49 #endif
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <math.h>
55 #include <glib.h>
56
57 #include <epan/conversation.h>
58 #include <epan/emem.h>
59 #include <epan/packet.h>
60 #include <epan/prefs.h>
61 #include "packet-x11-keysym.h" /* This contains the X11 value_string
62                                 * "keysym_vals_source" that VNC also uses. */
63
64 static const value_string security_types_vs[] = {
65         { 0,  "Invalid" },
66         { 1,  "None"    },
67         { 2,  "VNC"     },
68         { 5,  "RA2"     },
69         { 6,  "RA2ne"   },
70         { 16, "Tight"   },
71         { 17, "Ultra"   },
72         { 18, "TLS"     },
73         { 0,  NULL      }
74 };
75
76 static const value_string auth_result_vs[] = {
77         { 0, "OK"     },
78         { 1, "Failed" },
79         { 0,  NULL    }
80 };
81
82 static const value_string yes_no_vs[] = {
83         { 0, "No"  },
84         { 1, "Yes" },
85         { 0,  NULL }
86 };
87
88 static const value_string client_message_types_vs[] = {
89         { 0, "Set Pixel Format"           },
90         { 2, "Set Encodings"              },
91         { 3, "Framebuffer Update Request" },
92         { 4, "Key Event"                  },
93         { 5, "Pointer Event"              },
94         { 6, "Cut Text"                   },
95         { 0,  NULL                        }
96 };
97
98 static const value_string server_message_types_vs[] = {
99         { 0, "Framebuffer Update"   },
100         { 1, "Set Colormap Entries" },
101         { 2, "Ring Bell"            },
102         { 3, "Cut Text"             },
103         { 0,  NULL                  }
104 };
105
106 static const value_string button_mask_vs[] = {
107         { 0, "Not pressed" },
108         { 1, "Pressed"     },
109         { 0,  NULL         }
110 };
111
112 static const value_string encoding_types_vs[] = {
113         { -239, "Cursor (pseudo)"      },
114         { -223, "DesktopSize (pseudo)" },
115         { 0,  "Raw"                    },
116         { 1,  "CopyRect"               },
117         { 2,  "RRE"                    },
118         { 4,  "CoRRE"                  },
119         { 5,  "Hextile"                },
120         { 16, "ZRLE"                   },
121         { 0,  NULL                     }
122 };
123
124
125 void proto_reg_handoff_vnc(void);
126
127 static void vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo,
128                                  gint *offset, proto_tree *tree);
129 static void vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo,
130                                  gint *offset, proto_tree *tree);
131 static void vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo,
132                                         gint *offset, proto_tree *tree);
133 static void vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo,
134                                      gint *offset, proto_tree *tree);
135 static void vnc_client_framebuffer_update_request(tvbuff_t *tvb,
136                                                   packet_info *pinfo,
137                                                   gint *offset,
138                                                   proto_tree *tree);
139 static void vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo,
140                                  gint *offset, proto_tree *tree);
141 static void vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo,
142                                      gint *offset, proto_tree *tree);
143 static void vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
144                                 proto_tree *tree);
145
146 static guint vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo,
147                                            gint *offset, proto_tree *tree);
148 static guint vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
149                               proto_tree *tree, guint16 width, guint16 height);
150 static guint vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo,
151                                    gint *offset, proto_tree *tree,
152                                    guint16 width, guint16 height);
153 static guint vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
154                               proto_tree *tree, guint16 width, guint16 height);
155 static guint vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo,
156                                   gint *offset, proto_tree *tree,
157                                   guint16 width, guint16 height);
158 static guint vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
159                                proto_tree *tree, guint16 width, guint16 height);
160 static guint vnc_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
161                                  gint *offset, proto_tree *tree, guint16 width,
162                                  guint16 height);
163 static guint vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo,
164                                              gint *offset, proto_tree *tree);
165 static void vnc_server_ring_bell(tvbuff_t *tvb, packet_info *pinfo,
166                                  gint *offset, proto_tree *tree);
167 static guint vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo,
168                                  gint *offset, proto_tree *tree);
169 static void vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel);
170 static guint8 vnc_get_bytes_per_pixel(packet_info *pinfo);
171
172
173 #define DEST_PORT_VNC pinfo->destport == 5500 || pinfo->destport == 5501 || \
174                 pinfo->destport == 5900 || pinfo->destport == 5901 ||   \
175                 pinfo->destport == vnc_preference_alternate_port
176
177 #define VNC_BYTES_NEEDED(a)                                     \
178         if(a > (guint)tvb_length_remaining(tvb, *offset))       \
179                 return a;
180
181
182 /* Variables for our preferences */
183 static guint vnc_preference_alternate_port = 0;
184
185 /* This is a behind the scenes variable that is not changed by the user.
186  * This stores last setting of the vnc_preference_alternate_port.  Used to keep
187  * track of when the user has changed the setting so that we can delete
188  * and re-register with the new port number. */
189 static guint vnc_preference_alternate_port_last = 0;
190
191 /* Initialize the protocol and registered fields */
192 static int proto_vnc = -1; /* Protocol subtree */
193 static int hf_vnc_padding = -1;
194 static int hf_vnc_server_proto_ver = -1;
195 static int hf_vnc_client_proto_ver = -1;
196 static int hf_vnc_num_security_types = -1;
197 static int hf_vnc_security_type = -1;
198 static int hf_vnc_server_security_type = -1;
199 static int hf_vnc_client_security_type = -1;
200 static int hf_vnc_auth_challenge = -1;
201 static int hf_vnc_auth_response = -1;
202 static int hf_vnc_auth_result = -1;
203 static int hf_vnc_auth_error = -1;
204
205 static int hf_vnc_share_desktop_flag = -1;
206 static int hf_vnc_width = -1;
207 static int hf_vnc_height = -1;
208 static int hf_vnc_server_bits_per_pixel = -1;
209 static int hf_vnc_server_depth = -1;
210 static int hf_vnc_server_big_endian_flag = -1;
211 static int hf_vnc_server_true_color_flag = -1;
212 static int hf_vnc_server_red_max = -1;
213 static int hf_vnc_server_green_max = -1;
214 static int hf_vnc_server_blue_max = -1;
215 static int hf_vnc_server_red_shift = -1;
216 static int hf_vnc_server_green_shift = -1;
217 static int hf_vnc_server_blue_shift = -1;
218 static int hf_vnc_desktop_name = -1;
219 static int hf_vnc_desktop_name_len = -1;
220
221
222 /********** Client Message Types **********/
223
224 static int hf_vnc_client_message_type = -1; /* A subtree under VNC */
225 static int hf_vnc_client_bits_per_pixel = -1;
226 static int hf_vnc_client_depth = -1;
227 static int hf_vnc_client_big_endian_flag = -1;
228 static int hf_vnc_client_true_color_flag = -1;
229 static int hf_vnc_client_red_max = -1;
230 static int hf_vnc_client_green_max = -1;
231 static int hf_vnc_client_blue_max = -1;
232 static int hf_vnc_client_red_shift = -1;
233 static int hf_vnc_client_green_shift = -1;
234 static int hf_vnc_client_blue_shift = -1;
235
236 /* Client Key Event */
237 static int hf_vnc_key_down = -1;
238 static int hf_vnc_key = -1;
239
240 /* Client Pointer Event */
241 static int hf_vnc_button_1_pos = -1;
242 static int hf_vnc_button_2_pos = -1;
243 static int hf_vnc_button_3_pos = -1;
244 static int hf_vnc_button_4_pos = -1;
245 static int hf_vnc_button_5_pos = -1;
246 static int hf_vnc_button_6_pos = -1;
247 static int hf_vnc_button_7_pos = -1;
248 static int hf_vnc_button_8_pos = -1;
249 static int hf_vnc_pointer_x_pos = -1;
250 static int hf_vnc_pointer_y_pos = -1;
251
252 /* Client Framebuffer Update Request */
253 static int hf_vnc_update_req_incremental = -1;
254 static int hf_vnc_update_req_x_pos = -1;
255 static int hf_vnc_update_req_y_pos = -1;
256 static int hf_vnc_update_req_width = -1;
257 static int hf_vnc_update_req_height = -1;
258
259 /* Client Set Encodings */
260 static int hf_vnc_client_set_encodings_encoding_type = -1;
261
262 /* Client Cut Text */
263 static int hf_vnc_client_cut_text_len = -1;
264 static int hf_vnc_client_cut_text = -1;
265
266 /********** Server Message Types **********/
267
268 static int hf_vnc_server_message_type = -1; /* Subtree */
269
270 /* Server Framebuffer Update */
271 static int hf_vnc_fb_update_x_pos = -1;
272 static int hf_vnc_fb_update_y_pos = -1;
273 static int hf_vnc_fb_update_width = -1;
274 static int hf_vnc_fb_update_height = -1;
275 static int hf_vnc_fb_update_encoding_type = -1;
276
277 /* Raw Encoding */
278 static int hf_vnc_raw_pixel_data = -1;
279
280 /* CopyRect Encoding */
281 static int hf_vnc_copyrect_src_x_pos = -1;
282 static int hf_vnc_copyrect_src_y_pos = -1;
283
284 /* RRE Encoding */
285 static int hf_vnc_rre_num_subrects = -1;
286 static int hf_vnc_rre_bg_pixel = -1;
287
288 static int hf_vnc_rre_subrect_pixel = -1;
289 static int hf_vnc_rre_subrect_x_pos = -1;
290 static int hf_vnc_rre_subrect_y_pos = -1;
291 static int hf_vnc_rre_subrect_width = -1;
292 static int hf_vnc_rre_subrect_height = -1;
293
294 /* Hextile Encoding */
295 static int hf_vnc_hextile_subencoding_mask = -1;
296 static int hf_vnc_hextile_raw = -1;
297 static int hf_vnc_hextile_raw_value = -1;
298 static int hf_vnc_hextile_bg = -1;
299 static int hf_vnc_hextile_bg_value = -1;
300 static int hf_vnc_hextile_fg = -1;
301 static int hf_vnc_hextile_fg_value = -1;
302 static int hf_vnc_hextile_anysubrects = -1;
303 static int hf_vnc_hextile_num_subrects = -1;
304 static int hf_vnc_hextile_subrectscolored = -1;
305 static int hf_vnc_hextile_subrect_pixel_value = -1;
306 static int hf_vnc_hextile_subrect_x_pos = -1;
307 static int hf_vnc_hextile_subrect_y_pos = -1;
308 static int hf_vnc_hextile_subrect_width = -1;
309 static int hf_vnc_hextile_subrect_height = -1;
310
311 /* ZRLE Encoding */
312 static int hf_vnc_zrle_len = -1;
313 static int hf_vnc_zrle_subencoding = -1;
314 static int hf_vnc_zrle_rle = -1;
315 static int hf_vnc_zrle_palette_size = -1;
316 static int hf_vnc_zrle_data = -1;
317 static int hf_vnc_zrle_raw = -1;
318 static int hf_vnc_zrle_palette = -1;
319
320 /* Cursor Encoding */
321 static int hf_vnc_cursor_encoding_pixels = -1;
322 static int hf_vnc_cursor_encoding_bitmask = -1;
323
324 /* Server Set Colormap Entries */
325 static int hf_vnc_colormap_first_color = -1;
326 static int hf_vnc_colormap_num_colors = -1;
327 static int hf_vnc_colormap_red = -1;
328 static int hf_vnc_colormap_green = -1;
329 static int hf_vnc_colormap_blue = -1;
330
331 /* Server Cut Text */
332 static int hf_vnc_server_cut_text_len = -1;
333 static int hf_vnc_server_cut_text = -1;
334
335 /********** End of Server Message Types **********/
336
337 static gboolean vnc_preference_desegment = TRUE;
338
339 /* Initialize the subtree pointers */
340 static gint ett_vnc = -1;
341 static gint ett_vnc_client_message_type = -1;
342 static gint ett_vnc_server_message_type = -1;
343 static gint ett_vnc_rect = -1;
344 static gint ett_vnc_encoding_type = -1;
345 static gint ett_vnc_rre_subrect = -1;
346 static gint ett_vnc_hextile_subencoding_mask = -1;
347 static gint ett_vnc_hextile_num_subrects = -1;
348 static gint ett_vnc_hextile_subrect = -1;
349 static gint ett_vnc_zrle_subencoding = -1;
350 static gint ett_vnc_colormap_num_groups = -1;
351 static gint ett_vnc_colormap_color_group = -1;
352
353 static dissector_handle_t vnc_handle;
354
355
356 /* Initialize the structure that will be tied to each conversation. */
357 typedef struct {
358         /* Packet numbers for the first 9 packets of each conversation. */
359         guint32 first_packet_number, second_packet_number, third_packet_number,
360                 forth_packet_number, fifth_packet_number, sixth_packet_number,
361                 seventh_packet_number, eighth_packet_number,
362                 ninth_packet_number;
363         gdouble server_proto_ver, client_proto_ver;
364 } vnc_conversation_t;
365
366 /* Initialize the structure that will be tied to each packet */
367 typedef struct {
368         guint8 bytes_per_pixel;
369 } vnc_packet_t;
370
371
372 guint8 vnc_bytes_per_pixel; /* Global so it keeps its value between packets */
373
374
375 /* Code to dissect the packets */
376 static void
377 dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
378 {
379         guint8 num_security_types;
380         guint32 text_len; /* Part of: Client Cut Text & Server Cut Text */
381         guint32 auth_result, desktop_name_len;
382         guint offset = 0;
383
384         /* Set up structures needed to add the protocol subtree and manage it */
385         proto_item *ti=NULL;
386         proto_tree *vnc_tree=NULL;
387
388         conversation_t *conversation;
389         vnc_conversation_t *per_conversation_info;
390
391         conversation = find_conversation(pinfo->fd->num, &pinfo->src,
392                                          &pinfo->dst, pinfo->ptype,
393                                          pinfo->srcport, pinfo->destport, 0);
394
395         if(!conversation) {  /* Conversation does not exist yet - create it */
396                 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
397                                                 &pinfo->dst, pinfo->ptype,
398                                                 pinfo->srcport,
399                                                 pinfo->destport, 0);
400         }
401
402         /* Retrieve information from conversation, or add it if it isn't
403          * there yet */
404         per_conversation_info = conversation_get_proto_data(conversation,
405                                                             proto_vnc);
406         if(!per_conversation_info) {
407                 per_conversation_info = se_alloc(sizeof(vnc_conversation_t));
408
409                 /* We must be on the first packet now */
410                 per_conversation_info->first_packet_number   = pinfo->fd->num;
411
412                 /* The rest of these values will be set as we come across each
413                  * packet */
414                 per_conversation_info->second_packet_number  = 0;
415                 per_conversation_info->third_packet_number   = 0;
416                 per_conversation_info->forth_packet_number   = 0;
417                 per_conversation_info->fifth_packet_number   = 0;
418                 per_conversation_info->sixth_packet_number   = 0;
419                 per_conversation_info->seventh_packet_number = 0;
420                 per_conversation_info->eighth_packet_number  = 0;
421                 per_conversation_info->ninth_packet_number   = 0;
422
423                 per_conversation_info->server_proto_ver = 0.0;
424                 per_conversation_info->client_proto_ver = 0.0;
425
426                 conversation_add_proto_data(conversation, proto_vnc,
427                                             per_conversation_info);
428         }
429
430         /* Store the number of the first nine packets of this conversation as
431          * we reach them for the first time.  These are the packets that
432          * contain connection setup data and do not have a message type
433          * identifier.  The packets after the ninth one do contain message
434          * type identifiers. */
435
436         if(!per_conversation_info->second_packet_number && pinfo->fd->num >
437            per_conversation_info->first_packet_number) {
438                 /* We're on the second packet of the conversation */
439                 per_conversation_info->second_packet_number = pinfo->fd->num;
440
441         } else if(per_conversation_info->second_packet_number &&
442                   !per_conversation_info->third_packet_number &&
443                   pinfo->fd->num >
444                   per_conversation_info->second_packet_number) {
445                 /* We're on the third packet of the conversation */
446                 per_conversation_info->third_packet_number = pinfo->fd->num;
447
448         } else if(per_conversation_info->third_packet_number &&
449                   !per_conversation_info->forth_packet_number &&
450                   pinfo->fd->num > per_conversation_info->third_packet_number) {
451                 /* We're on the forth packet of the conversation */
452                 per_conversation_info->forth_packet_number = pinfo->fd->num;
453
454         } else if(per_conversation_info->forth_packet_number &&
455                   !per_conversation_info->fifth_packet_number &&
456                   pinfo->fd->num > per_conversation_info->forth_packet_number) {
457                 /* We're on the fifth packet of the conversation */
458                 per_conversation_info->fifth_packet_number = pinfo->fd->num;
459
460         } else if(per_conversation_info->fifth_packet_number &&
461                   !per_conversation_info->sixth_packet_number &&
462                   pinfo->fd->num > per_conversation_info->fifth_packet_number) {
463                 /* We're on the sixth packet of the conversation */
464                 per_conversation_info->sixth_packet_number = pinfo->fd->num;
465
466         } else if(per_conversation_info->sixth_packet_number &&
467                   !per_conversation_info->seventh_packet_number &&
468                   pinfo->fd->num > per_conversation_info->sixth_packet_number) {
469                 /* We're on the seventh packet of the conversation */
470                 per_conversation_info->seventh_packet_number = pinfo->fd->num;
471
472         } else if(per_conversation_info->seventh_packet_number &&
473                   !per_conversation_info->eighth_packet_number && 
474                   pinfo->fd->num >
475                   per_conversation_info->seventh_packet_number){
476                 /* We're on the eighth packet of the conversation */
477                 per_conversation_info->eighth_packet_number = pinfo->fd->num;
478
479         } else if(per_conversation_info->eighth_packet_number &&
480                   !per_conversation_info->ninth_packet_number &&
481                   pinfo->fd->num > per_conversation_info->eighth_packet_number){
482                 /* We're on the ninth packet of the conversation */
483                 per_conversation_info->ninth_packet_number = pinfo->fd->num;
484         }
485
486
487         /* Make entries in Protocol column and Info column on summary display */
488         if (check_col(pinfo->cinfo, COL_PROTOCOL))
489                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "VNC");
490
491         /* First, clear the info column */
492         if(check_col(pinfo->cinfo, COL_INFO))
493                 col_clear(pinfo->cinfo, COL_INFO);
494
495         /* create display subtree for the protocol */
496         if(tree) {
497                 ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, FALSE);
498                 vnc_tree = proto_item_add_subtree(ti, ett_vnc);
499         }
500
501         offset = 0; /* Start at the beginning of the VNC protocol data */
502
503         /* Server Protocol Version */
504
505         if(pinfo->fd->num == per_conversation_info->first_packet_number) {
506                 proto_tree_add_item(vnc_tree, hf_vnc_server_proto_ver, tvb, 4,
507                                     7, FALSE);
508                 per_conversation_info->server_proto_ver =
509                         g_strtod(tvb_get_ephemeral_string(tvb, 4, 7), NULL);
510
511                 if (check_col(pinfo->cinfo, COL_INFO))
512                         col_add_fstr(pinfo->cinfo, COL_INFO,
513                                      "Server protocol version: %s",
514                                      tvb_format_text(tvb, 4, 7));
515         }
516
517         /* Second Packet = Client Protocol Version */
518         else if(pinfo->fd->num == per_conversation_info->second_packet_number) {
519                 proto_tree_add_item(vnc_tree, hf_vnc_client_proto_ver, tvb, 4,
520                                     7, FALSE);
521                 per_conversation_info->client_proto_ver =
522                         g_strtod(tvb_get_ephemeral_string(tvb, 4, 7), NULL);
523
524                 if (check_col(pinfo->cinfo, COL_INFO))
525                         col_add_fstr(pinfo->cinfo, COL_INFO,
526                                      "Client protocol version: %s",
527                                      tvb_format_text(tvb, 4, 7));
528         }
529
530         /* Security Types Supported */
531         else if(pinfo->fd->num == per_conversation_info->third_packet_number) {
532
533                 if (check_col(pinfo->cinfo, COL_INFO))
534                         col_set_str(pinfo->cinfo, COL_INFO,
535                                     "Security types supported");
536
537                 /* We're checking against the client protocol version because
538                  * the client is the final decider on which version to use
539                  * after the server offers the version it supports. */
540
541                 if(per_conversation_info->client_proto_ver >= 3.007) {
542                         proto_tree_add_item(vnc_tree,
543                                             hf_vnc_num_security_types, tvb,
544                                             offset, 1, FALSE);
545                         num_security_types = tvb_get_guint8(tvb, offset);
546
547                         for(offset = 1; offset <= num_security_types; offset++){
548                                 proto_tree_add_item(vnc_tree,
549                                                     hf_vnc_security_type, tvb,
550                                                     offset, 1, FALSE);
551                         }
552                 } else {
553                         /* Version < 3.007: The server decides the
554                          * authentication time for us to use */
555                         proto_tree_add_item(vnc_tree,
556                                             hf_vnc_server_security_type, tvb,
557                                             offset, 4, FALSE);
558
559                 }
560
561         }
562
563         /* Authentication type selected by client.
564          * This field is skipped by versions < 3.007 so the packet number is
565          * off on each if statement below */
566         else if(per_conversation_info->client_proto_ver >= 3.007 &&
567                 pinfo->fd->num == per_conversation_info->forth_packet_number) {
568                 if (check_col(pinfo->cinfo, COL_INFO))
569                         col_set_str(pinfo->cinfo, COL_INFO,
570                                     "Authentication type selected by client");
571
572                 proto_tree_add_item(vnc_tree, hf_vnc_client_security_type, tvb,
573                                     offset, 1, FALSE);
574         }
575
576         /* Authentication challenge from server */
577         else if((per_conversation_info->client_proto_ver >= 3.007 &&
578                  pinfo->fd->num == per_conversation_info->fifth_packet_number)||
579                 (per_conversation_info->client_proto_ver  < 3.007 &&
580                  pinfo->fd->num == per_conversation_info->forth_packet_number)){
581                 if (check_col(pinfo->cinfo, COL_INFO))
582                         col_set_str(pinfo->cinfo, COL_INFO,
583                                     "Authentication challenge from server");
584                 
585                 proto_tree_add_item(vnc_tree, hf_vnc_auth_challenge, tvb,
586                                     offset, 16, FALSE);
587         }
588
589         /* Authentication response from client */
590         else if((per_conversation_info->client_proto_ver >= 3.007 &&
591                  pinfo->fd->num == per_conversation_info->sixth_packet_number)||
592                 (per_conversation_info->client_proto_ver  < 3.007 &&
593                  pinfo->fd->num == per_conversation_info->fifth_packet_number)){
594                 if (check_col(pinfo->cinfo, COL_INFO))
595                         col_set_str(pinfo->cinfo, COL_INFO,
596                                     "Authentication response from client");
597
598                 proto_tree_add_item(vnc_tree, hf_vnc_auth_response, tvb,
599                                     offset, 16, FALSE);
600         }
601
602         /* Authentication result */
603         else if((per_conversation_info->client_proto_ver >= 3.007 &&
604                  pinfo->fd->num == per_conversation_info->seventh_packet_number)
605                 || (per_conversation_info->client_proto_ver < 3.007 &&
606                     pinfo->fd->num ==
607                     per_conversation_info->sixth_packet_number)) {
608
609                 if (check_col(pinfo->cinfo, COL_INFO))
610                         col_set_str(pinfo->cinfo, COL_INFO,
611                                     "Authentication result");
612
613                 proto_tree_add_item(vnc_tree, hf_vnc_auth_result, tvb, offset,
614                                     4, FALSE);
615                 auth_result = tvb_get_ntohl(tvb, offset);
616                 offset += 4;
617
618                 if(per_conversation_info->client_proto_ver >= 3.007 &&
619                    auth_result == 1) { /* 1 = failed */
620                         text_len = tvb_get_ntohl(tvb, offset);
621                         proto_tree_add_text(vnc_tree, tvb, offset, 4,
622                                             "Length of authentication error: %d", text_len);
623                         offset += 4;
624
625                         proto_tree_add_item(vnc_tree, hf_vnc_auth_error, tvb,
626                                             offset, text_len, FALSE);
627                         offset += text_len;
628
629                 }
630         }
631
632         /* Share desktop */
633         else if((per_conversation_info->client_proto_ver >= 3.007 &&
634                  pinfo->fd->num == per_conversation_info->eighth_packet_number)
635                 || (per_conversation_info->client_proto_ver  < 3.007 &&
636                  pinfo->fd->num == per_conversation_info->seventh_packet_number)) {
637                 if (check_col(pinfo->cinfo, COL_INFO))
638                         col_set_str(pinfo->cinfo, COL_INFO,
639                                     "Share desktop flag");
640
641                 proto_tree_add_item(vnc_tree, hf_vnc_share_desktop_flag, tvb,
642                                     offset, 1, FALSE);
643         }
644
645         /* Various parameters for the frame buffer (screen) from the server */
646         else if((per_conversation_info->client_proto_ver >= 3.007 &&
647                  pinfo->fd->num == per_conversation_info->ninth_packet_number)||
648                 (per_conversation_info->client_proto_ver  < 3.007 &&
649                  pinfo->fd->num == per_conversation_info->eighth_packet_number)) {
650
651                 if (check_col(pinfo->cinfo, COL_INFO))
652                         col_set_str(pinfo->cinfo, COL_INFO,
653                                     "Server framebuffer parameters");
654
655                 proto_tree_add_item(vnc_tree, hf_vnc_width, tvb, offset, 2,
656                                     FALSE);
657                 offset += 2;
658
659                 proto_tree_add_item(vnc_tree, hf_vnc_height, tvb, offset, 2,
660                                     FALSE);
661                 offset += 2;
662
663                 proto_tree_add_item(vnc_tree, hf_vnc_server_bits_per_pixel,
664                                     tvb, offset, 1, FALSE);
665                 vnc_bytes_per_pixel = tvb_get_guint8(tvb, offset)/8;
666                 vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
667                 offset += 1;
668
669                 proto_tree_add_item(vnc_tree, hf_vnc_server_depth, tvb, offset,
670                                     1, FALSE);
671                 offset += 1;
672
673                 proto_tree_add_item(vnc_tree, hf_vnc_server_big_endian_flag,
674                                     tvb, offset, 1, FALSE);
675                 offset += 1;
676
677                 proto_tree_add_item(vnc_tree, hf_vnc_server_true_color_flag,
678                                     tvb, offset, 1, FALSE);
679                 offset += 1;
680
681                 proto_tree_add_item(vnc_tree, hf_vnc_server_red_max,
682                                     tvb, offset, 2, FALSE);
683                 offset += 2;
684
685                 proto_tree_add_item(vnc_tree, hf_vnc_server_green_max,
686                                     tvb, offset, 2, FALSE);
687                 offset += 2;
688
689                 proto_tree_add_item(vnc_tree, hf_vnc_server_blue_max,
690                                     tvb, offset, 2, FALSE);
691                 offset += 2;
692
693                 proto_tree_add_item(vnc_tree, hf_vnc_server_red_shift,
694                                     tvb, offset, 1, FALSE);
695                 offset += 1;
696
697                 proto_tree_add_item(vnc_tree, hf_vnc_server_green_shift,
698                                     tvb, offset, 1, FALSE);
699                 offset += 1;
700
701                 proto_tree_add_item(vnc_tree, hf_vnc_server_blue_shift,
702                                     tvb, offset, 1, FALSE);
703                 offset += 1;
704
705                 proto_tree_add_item(vnc_tree, hf_vnc_padding,
706                                     tvb, offset, 3, FALSE);
707                 offset += 3; /* Skip over 3 bytes of padding */
708                 
709                 if(tvb_length_remaining(tvb, offset) > 0) {
710                         /* Sometimes the desktop name & length is skipped */
711                         proto_tree_add_item(vnc_tree, hf_vnc_desktop_name_len,
712                                             tvb, offset, 4, FALSE);
713                         desktop_name_len = tvb_get_ntohl(tvb, offset);
714                         offset += 4;
715
716                         proto_tree_add_item(vnc_tree, hf_vnc_desktop_name,
717                                             tvb, offset, desktop_name_len,
718                                             FALSE);
719                 }
720
721         } else {        /* All packets beyond #9 */
722
723                 vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
724
725                 if(DEST_PORT_VNC)
726                         vnc_client_to_server(tvb, pinfo, &offset, vnc_tree);
727                 else
728                         vnc_server_to_client(tvb, pinfo, &offset, vnc_tree);
729         }
730 }
731
732
733 static void
734 vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
735                      proto_tree *tree)
736 {
737         guint8 message_type;
738
739         proto_item *ti=NULL;
740         proto_tree *vnc_client_message_type_tree;
741
742         message_type = tvb_get_guint8(tvb, *offset);
743
744         ti = proto_tree_add_item(tree, hf_vnc_client_message_type, tvb,
745                                  *offset, 1, FALSE);
746
747         vnc_client_message_type_tree =
748                 proto_item_add_subtree(ti, ett_vnc_client_message_type);
749
750         *offset += 1;
751
752         switch(message_type) {
753                 
754         case 0 :
755                 vnc_client_set_pixel_format(tvb, pinfo, offset,
756                                             vnc_client_message_type_tree);
757                 break;
758
759         case 2 :
760                 vnc_client_set_encodings(tvb, pinfo, offset,
761                                          vnc_client_message_type_tree);
762                 break;
763
764         case 3 :
765                 vnc_client_framebuffer_update_request(tvb, pinfo, offset,
766                                                       vnc_client_message_type_tree);
767                 break;
768
769         case 4 :
770                 vnc_client_key_event(tvb, pinfo, offset,
771                                      vnc_client_message_type_tree);
772                 break;
773
774         case 5:
775                 vnc_client_pointer_event(tvb, pinfo, offset,
776                                          vnc_client_message_type_tree);
777                 break;
778
779         case 6 :
780                 vnc_client_cut_text(tvb, pinfo, offset,
781                                     vnc_client_message_type_tree);
782                 break;
783
784         default :
785                 if (check_col(pinfo->cinfo, COL_INFO))
786                         col_append_str(pinfo->cinfo, COL_INFO,
787                                        "Unknown client message type");
788                 break;
789         }
790 }
791
792 static void
793 vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
794                      proto_tree *tree)
795 {
796         guint8 message_type;
797         gint bytes_needed = 0, length_remaining;
798         
799         proto_item *ti=NULL;
800         proto_tree *vnc_server_message_type_tree;
801
802         message_type = tvb_get_guint8(tvb, *offset);
803
804         ti = proto_tree_add_item(tree, hf_vnc_server_message_type, tvb,
805                                  *offset, 1, FALSE);
806         vnc_server_message_type_tree =
807                 proto_item_add_subtree(ti, ett_vnc_server_message_type);
808
809         *offset += 1;
810
811         switch(message_type) {
812
813         case 0 :
814                 bytes_needed =
815                         vnc_server_framebuffer_update(tvb, pinfo, offset,
816                                                       vnc_server_message_type_tree);
817                 break;
818
819         case 1 :
820                 bytes_needed = vnc_server_set_colormap_entries(tvb, pinfo, offset, vnc_server_message_type_tree);
821                 break;
822
823         case 2 :
824                 vnc_server_ring_bell(tvb, pinfo, offset,
825                                      vnc_server_message_type_tree);
826                 break;
827
828         case 3 :
829                 bytes_needed = vnc_server_cut_text(tvb, pinfo, offset,
830                                                    vnc_server_message_type_tree);
831                 break;
832
833         default :
834                 if (check_col(pinfo->cinfo, COL_INFO))
835                         col_append_str(pinfo->cinfo, COL_INFO,
836                                        "Unknown server message type");
837                 break;
838         }
839
840         if(bytes_needed > 0 && vnc_preference_desegment &&
841            pinfo->can_desegment) {
842                 length_remaining = tvb_length_remaining(tvb, *offset);
843
844                 pinfo->desegment_offset = 0;
845                 pinfo->desegment_len = tvb_length(tvb) + bytes_needed -
846                         length_remaining;
847                 return;
848         }
849 }
850
851
852 static void
853 vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
854                             proto_tree *tree)
855 {
856         if (check_col(pinfo->cinfo, COL_INFO))
857                 col_set_str(pinfo->cinfo, COL_INFO, "Client set pixel format");
858         
859         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
860                             3, FALSE);
861         *offset += 3; /* Skip over 3 bytes of padding */
862                 
863         proto_tree_add_item(tree, hf_vnc_client_bits_per_pixel, tvb, *offset,
864                             1, FALSE);
865         vnc_bytes_per_pixel = tvb_get_guint8(tvb, *offset)/8;
866         vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
867         *offset += 1;
868
869         proto_tree_add_item(tree, hf_vnc_client_depth, tvb, *offset,
870                             1, FALSE);
871         *offset += 1;
872
873         proto_tree_add_item(tree, hf_vnc_client_big_endian_flag, tvb, *offset,
874                             1, FALSE);
875         *offset += 1;
876
877         proto_tree_add_item(tree, hf_vnc_client_true_color_flag, tvb, *offset,
878                             1, FALSE);
879         *offset += 1;
880
881         proto_tree_add_item(tree, hf_vnc_client_red_max, tvb, *offset,
882                             2, FALSE);
883         *offset += 2;
884
885         proto_tree_add_item(tree, hf_vnc_client_green_max, tvb, *offset,
886                             2, FALSE);
887         *offset += 2;
888
889         proto_tree_add_item(tree, hf_vnc_client_blue_max, tvb, *offset,
890                             2, FALSE);
891         *offset += 2;
892
893         proto_tree_add_item(tree, hf_vnc_client_red_shift, tvb, *offset,
894                             1, FALSE);
895         *offset += 1;
896
897         proto_tree_add_item(tree, hf_vnc_client_green_shift, tvb, *offset,
898                             1, FALSE);
899         *offset += 1;
900
901         proto_tree_add_item(tree, hf_vnc_client_blue_shift, tvb, *offset,
902                             1, FALSE);
903         *offset += 1;
904
905         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset,
906                             3, FALSE);
907         *offset += 3; /* Skip over 3 bytes of padding */
908 }
909
910
911 static void
912 vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
913                          proto_tree *tree)
914 {
915         guint16 number_of_encodings;
916         guint counter;
917
918         if (check_col(pinfo->cinfo, COL_INFO))
919                 col_set_str(pinfo->cinfo, COL_INFO, "Client set encodings");
920
921         proto_tree_add_item(tree, hf_vnc_padding,
922                             tvb, *offset, 1, FALSE);
923         *offset += 1; /* Skip over 1 byte of padding */
924
925         number_of_encodings = tvb_get_ntohs(tvb, *offset);
926
927         proto_tree_add_text(tree, tvb, *offset, 2,
928                             "Number of encodings: %d", number_of_encodings);
929         *offset += 2;
930
931         for(counter = 1; counter <= number_of_encodings; counter++) {
932                 proto_tree_add_item(tree,
933                                     hf_vnc_client_set_encodings_encoding_type,
934                                     tvb, *offset, 4, FALSE);
935                 *offset += 4;
936         }
937 }
938
939
940 static void
941 vnc_client_framebuffer_update_request(tvbuff_t *tvb, packet_info *pinfo,
942                                       gint *offset, proto_tree *tree)
943 {
944         if (check_col(pinfo->cinfo, COL_INFO))
945                 col_set_str(pinfo->cinfo, COL_INFO,
946                             "Client framebuffer update request");
947
948         proto_tree_add_item(tree, hf_vnc_update_req_incremental,
949                             tvb, *offset, 1, FALSE);
950         *offset += 1;
951
952         proto_tree_add_item(tree, hf_vnc_update_req_x_pos,
953                             tvb, *offset, 2, FALSE);
954         *offset += 2;
955
956         proto_tree_add_item(tree, hf_vnc_update_req_y_pos,
957                             tvb, *offset, 2, FALSE);
958         *offset += 2;
959
960         proto_tree_add_item(tree, hf_vnc_update_req_width, tvb,
961                             *offset, 2, FALSE);
962         *offset += 2;
963
964         proto_tree_add_item(tree, hf_vnc_update_req_height, tvb,
965                             *offset, 2, FALSE);
966         *offset += 2;
967 }
968
969
970 static void
971 vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
972                      proto_tree *tree)
973 {
974         if (check_col(pinfo->cinfo, COL_INFO))
975                 col_set_str(pinfo->cinfo, COL_INFO, "Client key event");
976         
977         proto_tree_add_item(tree, hf_vnc_key_down, tvb, *offset, 1, FALSE);
978         *offset += 1;
979         
980         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 2, FALSE);
981         *offset += 2; /* Skip over 2 bytes of padding */
982         
983         proto_tree_add_item(tree, hf_vnc_key, tvb, *offset, 4, FALSE);
984         *offset += 4;
985 }
986
987
988 static void
989 vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
990                          proto_tree *tree)
991 {
992         if (check_col(pinfo->cinfo, COL_INFO))
993                 col_set_str(pinfo->cinfo, COL_INFO, "Client pointer event");
994         
995         proto_tree_add_item(tree, hf_vnc_button_1_pos, tvb, *offset, 1, FALSE);
996         proto_tree_add_item(tree, hf_vnc_button_2_pos, tvb, *offset, 1, FALSE);
997         proto_tree_add_item(tree, hf_vnc_button_3_pos, tvb, *offset, 1, FALSE);
998         proto_tree_add_item(tree, hf_vnc_button_4_pos, tvb, *offset, 1, FALSE);
999         proto_tree_add_item(tree, hf_vnc_button_5_pos, tvb, *offset, 1, FALSE);
1000         proto_tree_add_item(tree, hf_vnc_button_6_pos, tvb, *offset, 1, FALSE);
1001         proto_tree_add_item(tree, hf_vnc_button_7_pos, tvb, *offset, 1, FALSE);
1002         proto_tree_add_item(tree, hf_vnc_button_8_pos, tvb, *offset, 1, FALSE);
1003         *offset += 1;
1004         
1005         proto_tree_add_item(tree, hf_vnc_pointer_x_pos, tvb, *offset, 2, FALSE);
1006         *offset += 2;
1007         
1008         proto_tree_add_item(tree, hf_vnc_pointer_y_pos, tvb, *offset, 2, FALSE);
1009         *offset += 2;
1010 }
1011
1012
1013 static void
1014 vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1015                     proto_tree *tree)
1016 {
1017         guint32 text_len;
1018
1019         if (check_col(pinfo->cinfo, COL_INFO))
1020                 col_set_str(pinfo->cinfo, COL_INFO, "Client cut text");
1021
1022         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, FALSE);
1023         *offset += 3; /* Skip over 3 bytes of padding */
1024
1025         text_len = tvb_get_ntohl(tvb, *offset);
1026         proto_tree_add_item(tree, hf_vnc_client_cut_text_len, tvb, *offset, 4,
1027                             FALSE);
1028         *offset += 4;
1029
1030         proto_tree_add_item(tree, hf_vnc_client_cut_text, tvb, *offset,
1031                             text_len, FALSE);
1032         *offset += text_len;
1033
1034 }
1035
1036
1037 static guint
1038 vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1039                               proto_tree *tree)
1040 {
1041         guint16 num_rects, i, width, height;
1042         guint bytes_needed = 0;
1043         gint32 encoding_type;
1044         proto_item *ti;
1045         proto_tree *vnc_rect_tree, *vnc_encoding_type_tree;
1046         
1047         if (check_col(pinfo->cinfo, COL_INFO))
1048                 col_set_str(pinfo->cinfo, COL_INFO,
1049                             "Server framebuffer update");       
1050
1051         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
1052         *offset += 1;
1053         
1054         num_rects = tvb_get_ntohs(tvb, *offset);
1055         proto_tree_add_text(tree, tvb, *offset, 2, "Number of rectangles: %d",
1056                             num_rects);
1057         *offset += 2;
1058         
1059         for(i = 1; i <= num_rects; i++) {
1060
1061                 VNC_BYTES_NEEDED(12);
1062
1063                 ti = proto_tree_add_text(tree, tvb, *offset, 12,
1064                                          "Rectangle #%d", i);
1065
1066                 vnc_rect_tree =
1067                         proto_item_add_subtree(ti, ett_vnc_rect);
1068
1069                 proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_x_pos,
1070                                     tvb, *offset, 2, FALSE);
1071                 *offset += 2;
1072                 
1073                 proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_y_pos,
1074                                     tvb, *offset, 2, FALSE);
1075                 *offset += 2;
1076                 
1077                 proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_width,
1078                                     tvb, *offset, 2, FALSE);
1079                 width = tvb_get_ntohs(tvb, *offset);
1080                 *offset += 2;
1081                 
1082                 proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_height,
1083                                     tvb, *offset, 2, FALSE);
1084                 height = tvb_get_ntohs(tvb, *offset);
1085                 *offset += 2;
1086
1087                 ti = proto_tree_add_item(vnc_rect_tree,
1088                                          hf_vnc_fb_update_encoding_type,
1089                                          tvb, *offset, 4, FALSE);
1090                 
1091                 vnc_encoding_type_tree =
1092                         proto_item_add_subtree(ti, ett_vnc_encoding_type);
1093
1094                 encoding_type = tvb_get_ntohl(tvb, *offset);
1095                 *offset += 4;
1096
1097                 switch(encoding_type) {
1098                         
1099                 case 0 :
1100                         bytes_needed = vnc_raw_encoding(tvb, pinfo, offset,
1101                                                         vnc_encoding_type_tree,
1102                                                         width, height);
1103                         break;
1104                         
1105                 case 1 :
1106                         bytes_needed =
1107                                 vnc_copyrect_encoding(tvb, pinfo, offset,
1108                                                       vnc_encoding_type_tree,
1109                                                       width, height);
1110                         break;
1111                         
1112                 case 2 :
1113                         bytes_needed = 
1114                                 vnc_rre_encoding(tvb, pinfo, offset,
1115                                                  vnc_encoding_type_tree,
1116                                                  width, height);
1117                         break;
1118                         
1119                 case 5 :
1120                         bytes_needed =
1121                                 vnc_hextile_encoding(tvb, pinfo, offset,
1122                                                      vnc_encoding_type_tree,
1123                                                      width, height);
1124                         break;
1125                         
1126                 case 16 :
1127                         bytes_needed =
1128                                 vnc_zrle_encoding(tvb, pinfo, offset,
1129                                                   vnc_encoding_type_tree,
1130                                                   width, height);
1131                         break;
1132                         
1133                 case -239 :
1134                         bytes_needed =
1135                                 vnc_cursor_encoding(tvb, pinfo, offset,
1136                                                     vnc_encoding_type_tree,
1137                                                     width, height);
1138                         break;
1139                         
1140                 case -223 : /* DesktopSize */
1141
1142                         /* There is no payload for this message type */
1143
1144                         bytes_needed = 0;
1145                         break;
1146
1147                 }
1148
1149                 /* Check if the routines above requested more bytes to
1150                  * be desegmented. */
1151                 if(bytes_needed > 0)
1152                         return bytes_needed;
1153         }
1154
1155         return 0;
1156 }
1157
1158
1159 static guint
1160 vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1161                  proto_tree *tree, guint16 width, guint16 height)
1162 {
1163         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1164         guint length;
1165
1166         length = width * height * bytes_per_pixel;
1167         VNC_BYTES_NEEDED(length);
1168
1169         proto_tree_add_item(tree, hf_vnc_raw_pixel_data, tvb, *offset, 
1170                             length, FALSE);
1171         *offset += length;
1172
1173         return 0; /* bytes_needed */
1174 }
1175
1176
1177 static guint
1178 vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
1179                       proto_tree *tree, guint16 width _U_, guint16 height _U_)
1180 {
1181         proto_tree_add_item(tree, hf_vnc_copyrect_src_x_pos, tvb, *offset, 
1182                             2, FALSE);
1183         *offset += 2;
1184
1185         proto_tree_add_item(tree, hf_vnc_copyrect_src_y_pos, tvb, *offset, 
1186                             2, FALSE);
1187         *offset += 2;
1188
1189         return 0; /* bytes_needed */
1190 }
1191
1192
1193 static guint
1194 vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1195                  proto_tree *tree, guint16 width _U_, guint16 height _U_)
1196 {
1197         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1198         guint32 num_subrects, i;
1199         guint bytes_needed;
1200         proto_item *ti;
1201         proto_tree *subrect_tree;
1202
1203         VNC_BYTES_NEEDED(4);
1204         proto_tree_add_item(tree, hf_vnc_rre_num_subrects, tvb, *offset, 
1205                             4, FALSE);
1206         num_subrects = tvb_get_ntohl(tvb, *offset);
1207         *offset += 4;
1208
1209         VNC_BYTES_NEEDED(bytes_per_pixel);
1210         proto_tree_add_item(tree, hf_vnc_rre_bg_pixel, tvb, *offset, 
1211                             bytes_per_pixel, FALSE);
1212         *offset += bytes_per_pixel;
1213
1214         for(i = 1; i <= num_subrects; i++) {
1215                 bytes_needed = bytes_per_pixel + 8;
1216                 VNC_BYTES_NEEDED(bytes_needed);
1217
1218                 ti = proto_tree_add_text(tree, tvb, *offset, bytes_per_pixel +
1219                                          8, "Subrectangle #%d", i);
1220                 subrect_tree =
1221                         proto_item_add_subtree(ti, ett_vnc_rre_subrect);
1222
1223                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_pixel,
1224                                     tvb, *offset, bytes_per_pixel, FALSE);
1225                 *offset += bytes_per_pixel;
1226
1227                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_x_pos,
1228                                     tvb, *offset, 2, FALSE);
1229                 *offset += 2;
1230
1231                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_y_pos,
1232                                     tvb, *offset, 2, FALSE);
1233                 *offset += 2;
1234
1235                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_width,
1236                                     tvb, *offset, 2, FALSE);
1237                 *offset += 2;
1238
1239                 proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_height,
1240                                     tvb, *offset, 2, FALSE);
1241                 *offset += 2;
1242         }
1243
1244         return 0; /* bytes_needed */
1245 }
1246
1247
1248 static guint
1249 vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1250                      proto_tree *tree, guint16 width, guint16 height)
1251 {
1252         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1253         guint8 i, subencoding_mask, num_subrects, subrect_len;
1254         guint length;
1255         proto_tree *subencoding_mask_tree, *subrect_tree, *num_subrects_tree;
1256         proto_item *ti;
1257
1258         VNC_BYTES_NEEDED(1);
1259         ti = proto_tree_add_item(tree, hf_vnc_hextile_subencoding_mask, tvb,
1260                                  *offset, 1, FALSE);
1261         subencoding_mask = tvb_get_guint8(tvb, *offset);
1262
1263         subencoding_mask_tree =
1264                 proto_item_add_subtree(ti, ett_vnc_hextile_subencoding_mask);
1265
1266         proto_tree_add_item(subencoding_mask_tree,
1267                             hf_vnc_hextile_raw, tvb, *offset, 1,
1268                             FALSE);
1269         proto_tree_add_item(subencoding_mask_tree,
1270                             hf_vnc_hextile_bg, tvb, *offset, 1,
1271                             FALSE);
1272         proto_tree_add_item(subencoding_mask_tree,
1273                             hf_vnc_hextile_fg, tvb, *offset, 1,
1274                             FALSE);
1275         proto_tree_add_item(subencoding_mask_tree,
1276                             hf_vnc_hextile_anysubrects, tvb, *offset, 1,
1277                             FALSE);
1278         proto_tree_add_item(subencoding_mask_tree,
1279                             hf_vnc_hextile_subrectscolored, tvb, *offset, 1,
1280                             FALSE);
1281         *offset += 1;
1282         
1283         if(subencoding_mask & 0x1) { /* Raw */
1284                 length = width * height * bytes_per_pixel;
1285
1286                 VNC_BYTES_NEEDED(length);
1287
1288                 proto_tree_add_item(tree, hf_vnc_hextile_raw_value, tvb,
1289                                     *offset, length, FALSE);
1290                 *offset += length;
1291         } else { 
1292                 if(subencoding_mask & 0x2) { /* Background Specified */
1293                         proto_tree_add_item(tree, hf_vnc_hextile_bg_value,
1294                                             tvb, *offset, bytes_per_pixel,
1295                                             FALSE);
1296                         *offset += bytes_per_pixel;
1297                 }
1298
1299                 if(subencoding_mask & 0x4) { /* Foreground Specified */
1300                         proto_tree_add_item(tree, hf_vnc_hextile_fg_value,
1301                                             tvb, *offset, bytes_per_pixel,
1302                                             FALSE);
1303                         *offset += bytes_per_pixel;
1304                 }
1305
1306                 if(subencoding_mask & 0x8) { /* Any Subrects */
1307                         ti = proto_tree_add_item(tree,
1308                                                  hf_vnc_hextile_num_subrects,
1309                                                  tvb, *offset, 1,
1310                                                  FALSE);
1311                         num_subrects = tvb_get_guint8(tvb, *offset);
1312                         *offset += 1;
1313                         
1314                         num_subrects_tree =
1315                                 proto_item_add_subtree(ti, ett_vnc_hextile_num_subrects);
1316
1317                         for(i = 1; i <= num_subrects; i++) {
1318
1319                                 if(subencoding_mask & 0x16) 
1320                                         subrect_len = bytes_per_pixel + 2;
1321                                 else
1322                                         subrect_len = 2;
1323
1324                                 ti = proto_tree_add_text(num_subrects_tree, tvb,
1325                                                          *offset, subrect_len,
1326                                                          "Subrectangle #%d", i);
1327
1328                                 subrect_tree = 
1329                                         proto_item_add_subtree(ti, ett_vnc_hextile_subrect);
1330
1331                                 if(subencoding_mask & 0x16) {
1332                                         /* Subrects Colored */
1333                                         proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_pixel_value, tvb, *offset, bytes_per_pixel, FALSE);
1334                                         
1335                                         *offset += bytes_per_pixel;
1336                                 }
1337
1338                                 proto_tree_add_item(subrect_tree,
1339                                                     hf_vnc_hextile_subrect_x_pos, tvb, *offset, 1, FALSE);
1340
1341                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_y_pos, tvb, *offset, 1, FALSE);
1342
1343                                 *offset += 1;
1344
1345                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_width, tvb, *offset, 1, FALSE);
1346
1347                                 proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_height, tvb, *offset, 1, FALSE);
1348
1349                                 *offset += 1;
1350                         }
1351                 }
1352         }
1353
1354         return 0; /* bytes_needed */
1355 }
1356
1357
1358 static guint
1359 vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1360                   proto_tree *tree, guint16 width, guint16 height)
1361 {
1362         guint32 data_len;
1363 #ifdef HAVE_LIBZ
1364         guint8 palette_size;
1365         guint8 bytes_per_cpixel = vnc_get_bytes_per_pixel(pinfo);
1366         gint uncomp_offset = 0;
1367         guint length;
1368         gint subencoding_type;
1369         tvbuff_t *uncomp_tvb = NULL;
1370         proto_tree *zrle_subencoding_tree;
1371         proto_item *ti;
1372 #endif
1373
1374         VNC_BYTES_NEEDED(4);
1375         proto_tree_add_item(tree, hf_vnc_zrle_len, tvb, *offset, 
1376                             4, FALSE);
1377         data_len = tvb_get_ntohl(tvb, *offset);
1378
1379         *offset += 4;
1380
1381         VNC_BYTES_NEEDED(data_len);
1382
1383         proto_tree_add_item(tree, hf_vnc_zrle_data, tvb, *offset,
1384                             data_len, FALSE);
1385
1386 #ifdef HAVE_LIBZ
1387         uncomp_tvb = tvb_uncompress(tvb, *offset, data_len);
1388
1389         if(uncomp_tvb != NULL) {
1390                 tvb_set_child_real_data_tvbuff(tvb, uncomp_tvb);
1391                 add_new_data_source(pinfo, uncomp_tvb,
1392                                     "Uncompressed ZRLE data");
1393
1394                 ti = proto_tree_add_item(tree, hf_vnc_zrle_subencoding,
1395                                          uncomp_tvb, uncomp_offset, 1, FALSE);
1396                 zrle_subencoding_tree =
1397                         proto_item_add_subtree(ti, ett_vnc_zrle_subencoding);
1398
1399                 proto_tree_add_item(zrle_subencoding_tree, hf_vnc_zrle_rle,
1400                                     uncomp_tvb, uncomp_offset, 1, FALSE);
1401
1402                 proto_tree_add_item(zrle_subencoding_tree,
1403                                     hf_vnc_zrle_palette_size, uncomp_tvb,
1404                                     uncomp_offset, 1, FALSE);
1405
1406                 subencoding_type = tvb_get_guint8(uncomp_tvb, uncomp_offset);
1407                 palette_size = subencoding_type & 0x7F;
1408
1409                 uncomp_offset += 1;
1410
1411                 if(subencoding_type == 0) { /* Raw */
1412                         length = width * height * bytes_per_cpixel;
1413                         VNC_BYTES_NEEDED(length);
1414
1415                         /* XXX - not working yet! */
1416
1417                         proto_tree_add_item(zrle_subencoding_tree,
1418                                             hf_vnc_zrle_raw, uncomp_tvb,
1419                                             uncomp_offset, length, FALSE);
1420
1421                 } else if(subencoding_type >= 130 && subencoding_type <= 255) {
1422                         length = palette_size * bytes_per_cpixel;
1423                         VNC_BYTES_NEEDED(length);
1424
1425                         proto_tree_add_item(zrle_subencoding_tree,
1426                                             hf_vnc_zrle_palette, uncomp_tvb,
1427                                             uncomp_offset, length, FALSE);
1428                 
1429                         /* XXX - Not complete! */
1430                 }
1431                         
1432         } else {
1433                 proto_tree_add_text(tree, tvb, *offset, data_len,
1434                                     "Decompression of ZRLE data failed");
1435         }
1436 #endif /* HAVE_LIBZ */
1437         
1438         *offset += data_len;
1439
1440         return 0; /* bytes_needed */
1441 }
1442
1443
1444 static guint
1445 vnc_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1446                     proto_tree *tree, guint16 width, guint16 height)
1447 {
1448         guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
1449         guint length;
1450
1451         length = width * height * bytes_per_pixel;
1452         proto_tree_add_item(tree, hf_vnc_cursor_encoding_pixels, tvb, *offset, 
1453                             length, FALSE);
1454         *offset += length;
1455
1456         length = floor((width + 7)/8) * height;
1457         proto_tree_add_item(tree, hf_vnc_cursor_encoding_bitmask, tvb, *offset,
1458                             length, FALSE);
1459         *offset += length;
1460
1461         return 0; /* bytes_needed */
1462 }
1463
1464
1465 static guint
1466 vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1467                                 proto_tree *tree)
1468 {
1469         guint16 number_of_colors;
1470         guint counter, bytes_needed;
1471         proto_item *ti;
1472         proto_tree *vnc_colormap_num_groups, *vnc_colormap_color_group;
1473
1474         if (check_col(pinfo->cinfo, COL_INFO))
1475                 col_set_str(pinfo->cinfo, COL_INFO,
1476                             "Server set colormap entries");
1477
1478         number_of_colors = tvb_get_ntohs(tvb, 4);
1479
1480         bytes_needed = (number_of_colors * 6) + 6;
1481         VNC_BYTES_NEEDED(bytes_needed);
1482
1483         ti = proto_tree_add_item(tree, hf_vnc_server_message_type, tvb,
1484                                  *offset, 1, FALSE);
1485         tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
1486         *offset += 1;
1487
1488         proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, FALSE);
1489         *offset += 1; /* Skip over 1 byte of padding */
1490
1491         proto_tree_add_item(tree,
1492                             hf_vnc_colormap_first_color,
1493                             tvb, *offset, 2, FALSE);
1494         *offset += 2;
1495
1496         ti = proto_tree_add_item(tree, hf_vnc_colormap_num_colors, tvb,
1497                                  *offset, 2, FALSE);
1498         vnc_colormap_num_groups =
1499                 proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
1500
1501         *offset += 2;
1502
1503         for(counter = 1; counter <= number_of_colors; counter++) {
1504                 ti = proto_tree_add_text(vnc_colormap_num_groups, tvb,
1505                                          *offset, 6,
1506                                          "Color group #%d", counter);
1507
1508                 vnc_colormap_color_group =
1509                         proto_item_add_subtree(ti,
1510                                                ett_vnc_colormap_color_group);
1511
1512                 proto_tree_add_item(vnc_colormap_color_group,
1513                                     hf_vnc_colormap_red, tvb,
1514                                     *offset, 2, FALSE);
1515                 *offset += 2;
1516
1517                 proto_tree_add_item(vnc_colormap_color_group,
1518                                     hf_vnc_colormap_green, tvb,
1519                                     *offset, 2, FALSE);
1520                 *offset += 2;
1521
1522                 proto_tree_add_item(vnc_colormap_color_group,
1523                                     hf_vnc_colormap_blue, tvb,
1524                                     *offset, 2, FALSE);
1525                 *offset += 2;
1526         }
1527 }
1528
1529
1530 static void
1531 vnc_server_ring_bell(tvbuff_t *tvb _U_, packet_info *pinfo, gint *offset _U_,
1532                      proto_tree *tree _U_)
1533 {
1534         if (check_col(pinfo->cinfo, COL_INFO))
1535                 col_set_str(pinfo->cinfo, COL_INFO, "Server ring bell on client");
1536         /* This message type has no payload... */
1537 }
1538
1539
1540 static guint
1541 vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
1542                     proto_tree *tree)
1543 {
1544         guint32 text_len;
1545
1546         if (check_col(pinfo->cinfo, COL_INFO))
1547                 col_set_str(pinfo->cinfo, COL_INFO,
1548                             "Server cut text");
1549
1550         text_len = tvb_get_ntohl(tvb, *offset);
1551         proto_tree_add_item(tree,
1552                             hf_vnc_server_cut_text_len, tvb, *offset, 4,
1553                             FALSE);
1554         *offset += 4;
1555         
1556         VNC_BYTES_NEEDED(text_len);
1557
1558         proto_tree_add_item(tree, hf_vnc_server_cut_text, tvb, *offset,
1559                             text_len, FALSE);
1560         *offset += text_len;
1561 }
1562
1563
1564 static void
1565 vnc_set_bytes_per_pixel(packet_info *pinfo, guint8 bytes_per_pixel)
1566 {
1567         vnc_packet_t *per_packet_info;
1568
1569         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
1570
1571         if(!per_packet_info) {
1572                 per_packet_info = se_alloc(sizeof(per_packet_info));
1573
1574                 per_packet_info->bytes_per_pixel = bytes_per_pixel;
1575
1576                 p_add_proto_data(pinfo->fd, proto_vnc, per_packet_info);
1577         }
1578 }
1579
1580
1581 static guint8
1582 vnc_get_bytes_per_pixel(packet_info *pinfo)
1583 {
1584         vnc_packet_t *per_packet_info;
1585
1586         per_packet_info = p_get_proto_data(pinfo->fd, proto_vnc);
1587
1588         if(per_packet_info) {
1589                 return per_packet_info->bytes_per_pixel;
1590         } else {
1591                 return 0;
1592         }
1593 }
1594
1595
1596 /* Register the protocol with Wireshark */
1597 void
1598 proto_register_vnc(void)
1599 {
1600         module_t *vnc_module; /* To handle our preferences */
1601
1602         /* Setup list of header fields */
1603         static hf_register_info hf[] = {
1604                 { &hf_vnc_padding,
1605                   { "Padding", "vnc.padding",
1606                     FT_NONE, BASE_NONE, NULL, 0x0,
1607                     "Unused space", HFILL }
1608                 },
1609
1610                 { &hf_vnc_server_proto_ver,
1611                   { "Server protocol version", "vnc.server_proto_ver",
1612                     FT_STRING, BASE_NONE, NULL, 0x0,
1613                     "VNC protocol version on server", HFILL }
1614                 },
1615                 { &hf_vnc_client_proto_ver,
1616                   { "Client protocol version", "vnc.client_proto_ver",
1617                     FT_STRING, BASE_NONE, NULL, 0x0,
1618                     "VNC protocol version on client", HFILL }
1619                 },
1620                 { &hf_vnc_num_security_types,
1621                   { "Number of security types", "vnc.num_security_types",
1622                     FT_UINT8, BASE_DEC, NULL, 0x0,
1623                     "Number of security (authentication) types supported by the server", HFILL }
1624                 },
1625                 { &hf_vnc_security_type,
1626                   { "Security type", "vnc.security_type",
1627                     FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
1628                     "Security types offered by the server (VNC versions => 3.007", HFILL }
1629                 },
1630                 { &hf_vnc_server_security_type,
1631                   { "Security type", "vnc.server_security_type",
1632                     FT_UINT32, BASE_DEC, VALS(security_types_vs), 0x0,
1633                     "Security type mandated by the server (VNC versions < 3.007)", HFILL }
1634                 },
1635                 { &hf_vnc_client_security_type,
1636                   { "Security type selected", "vnc.security_type",
1637                     FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
1638                     "Security type selected by the client", HFILL }
1639                 },
1640                 { &hf_vnc_auth_challenge,
1641                   { "Authentication challenge", "vnc.auth_challenge",
1642                     FT_STRING, BASE_NONE, NULL, 0x0,
1643                     "Random authentication challenge from server to client", HFILL }
1644                 },
1645                 { &hf_vnc_auth_response,
1646                   { "Authentication response", "vnc.auth_response",
1647                     FT_STRING, BASE_NONE, NULL, 0x0,
1648                     "Client's encrypted response to the server's authentication challenge", HFILL }
1649                 },
1650                 { &hf_vnc_auth_result,
1651                   { "Authentication result", "vnc.auth_result",
1652                     FT_UINT32, BASE_DEC, VALS(auth_result_vs), 0x0,
1653                     "Authentication result", HFILL }
1654                 },
1655                 { &hf_vnc_auth_error,
1656                   { "Authentication error", "vnc.auth_error",
1657                     FT_STRING, BASE_NONE, NULL, 0x0,
1658                     "Authentication error (present only if the authentication result is fail", HFILL }
1659                 },
1660                 { &hf_vnc_share_desktop_flag,
1661                   { "Share desktop flag", "vnc.share_desktop_flag",
1662                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
1663                     "Client's desire to share the server's desktop with other clients", HFILL }
1664                 },
1665                 { &hf_vnc_width,
1666                   { "Framebuffer width", "vnc.width",
1667                     FT_UINT16, BASE_DEC, NULL, 0x0,
1668                     "Width of the framebuffer (screen) in pixels", HFILL }
1669                 },
1670                 { &hf_vnc_height,
1671                   { "Framebuffer height", "vnc.width",
1672                     FT_UINT16, BASE_DEC, NULL, 0x0,
1673                     "Height of the framebuffer (screen) in pixels", HFILL }
1674                 },
1675                 { &hf_vnc_server_bits_per_pixel,
1676                   { "Bits per pixel", "vnc.server_bits_per_pixel",
1677                     FT_UINT8, BASE_DEC, NULL, 0x0,
1678                     "Number of bits used by server for each pixel value on the wire from the server", HFILL }
1679                 },
1680                 { &hf_vnc_server_depth,
1681                   { "Depth", "vnc.server_depth",
1682                     FT_UINT8, BASE_DEC, NULL, 0x0,
1683                     "Number of useful bits in the pixel value on server", HFILL }
1684                 },
1685                 { &hf_vnc_server_big_endian_flag,
1686                   { "Big endian flag", "vnc.server_big_endian_flag",
1687                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1688                     "True if multi-byte pixels are interpreted as big endian by server", HFILL }
1689                 },
1690                 { &hf_vnc_server_true_color_flag,
1691                   { "True color flag", "vnc.server_true_color_flag",
1692                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1693                     "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 }
1694                 },
1695                 { &hf_vnc_server_red_max,
1696                   { "Red maximum", "vnc.server_red_max",
1697                     FT_UINT16, BASE_DEC, NULL, 0x0,
1698                     "Maximum red value on server as n: 2^n - 1", HFILL }
1699                 },
1700                 { &hf_vnc_server_green_max,
1701                   { "Green maximum", "vnc.server_green_max",
1702                     FT_UINT16, BASE_DEC, NULL, 0x0,
1703                     "Maximum green value on server as n: 2^n - 1", HFILL }
1704                 },
1705                 { &hf_vnc_server_blue_max,
1706                   { "Blue maximum", "vnc.server_blue_max",
1707                     FT_UINT16, BASE_DEC, NULL, 0x0,
1708                     "Maximum blue value on server as n: 2^n - 1", HFILL }
1709                 },
1710                 { &hf_vnc_server_red_shift,
1711                   { "Red shift", "vnc.server_red_shift",
1712                     FT_UINT8, BASE_DEC, NULL, 0x0,
1713                     "Number of shifts needed to get the red value in a pixel to the least significant bit on the server", HFILL }
1714                 },
1715                 { &hf_vnc_server_green_shift,
1716                   { "Green shift", "vnc.server_green_shift",
1717                     FT_UINT8, BASE_DEC, NULL, 0x0,
1718                     "Number of shifts needed to get the green value in a pixel to the least significant bit on the server", HFILL }
1719                 },
1720                 { &hf_vnc_server_blue_shift,
1721                   { "Blue shift", "vnc.server_blue_shift",
1722                     FT_UINT8, BASE_DEC, NULL, 0x0,
1723                     "Number of shifts needed to get the blue value in a pixel to the least significant bit on the server", HFILL }
1724                 },
1725                 { &hf_vnc_desktop_name_len,
1726                   { "Desktop name length", "vnc.desktop_name_len",
1727                     FT_UINT32, BASE_DEC, NULL, 0x0,
1728                     "Length of desktop name in bytes", HFILL }
1729                 },
1730                 { &hf_vnc_desktop_name,
1731                   { "Desktop name", "vnc.desktop_name",
1732                     FT_STRING, BASE_NONE, NULL, 0x0,
1733                     "Name of the VNC desktop on the server", HFILL }
1734                 },
1735                 { &hf_vnc_client_message_type,
1736                   { "Client Message Type", "vnc.client_message_type",
1737                     FT_UINT8, BASE_DEC, VALS(client_message_types_vs), 0x0,
1738                     "Message type from client", HFILL }
1739                 },
1740                 { &hf_vnc_client_bits_per_pixel,
1741                   { "Bits per pixel", "vnc.client_bits_per_pixel",
1742                     FT_UINT8, BASE_DEC, NULL, 0x0,
1743                     "Number of bits used by server for each pixel value on the wire from the client", HFILL }
1744                 },
1745                 { &hf_vnc_client_depth,
1746                   { "Depth", "vnc.client_depth",
1747                     FT_UINT8, BASE_DEC, NULL, 0x0,
1748                     "Number of useful bits in the pixel value on client", HFILL }
1749                 },
1750                 { &hf_vnc_client_big_endian_flag,
1751                   { "Big endian flag", "vnc.client_big_endian_flag",
1752                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1753                     "True if multi-byte pixels are interpreted as big endian by client", HFILL }
1754                 },
1755                 { &hf_vnc_client_true_color_flag,
1756                   { "True color flag", "vnc.client_true_color_flag",
1757                     FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1758                     "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 }
1759                 },
1760                 { &hf_vnc_client_red_max,
1761                   { "Red maximum", "vnc.client_red_max",
1762                     FT_UINT16, BASE_DEC, NULL, 0x0,
1763                     "Maximum red value on client as n: 2^n - 1", HFILL }
1764                 },
1765                 { &hf_vnc_client_green_max,
1766                   { "Green maximum", "vnc.client_green_max",
1767                     FT_UINT16, BASE_DEC, NULL, 0x0,
1768                     "Maximum green value on client as n: 2^n - 1", HFILL }
1769                 },
1770                 { &hf_vnc_client_blue_max,
1771                   { "Blue maximum", "vnc.client_blue_max",
1772                     FT_UINT16, BASE_DEC, NULL, 0x0,
1773                     "Maximum blue value on client as n: 2^n - 1", HFILL }
1774                 },
1775                 { &hf_vnc_client_red_shift,
1776                   { "Red shift", "vnc.client_red_shift",
1777                     FT_UINT8, BASE_DEC, NULL, 0x0,
1778                     "Number of shifts needed to get the red value in a pixel to the least significant bit on the client", HFILL }
1779                 },
1780                 { &hf_vnc_client_green_shift,
1781                   { "Green shift", "vnc.client_green_shift",
1782                     FT_UINT8, BASE_DEC, NULL, 0x0,
1783                     "Number of shifts needed to get the green value in a pixel to the least significant bit on the client", HFILL }
1784                 },
1785                 { &hf_vnc_client_blue_shift,
1786                   { "Blue shift", "vnc.client_blue_shift",
1787                     FT_UINT8, BASE_DEC, NULL, 0x0,
1788                     "Number of shifts needed to get the blue value in a pixel to the least significant bit on the client", HFILL }
1789                 },
1790
1791                 /* Client Key Event */
1792                 { &hf_vnc_key_down,
1793                   { "Key down", "vnc.key_down",
1794                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
1795                     "Specifies whether the key is being pressed or not", HFILL }
1796                 },
1797                 { &hf_vnc_key,
1798                   { "Key", "vnc.key",
1799                     FT_UINT32, BASE_HEX, VALS(keysym_vals_source), 0x0, /* keysym_vals_source is from packet-x11-keysym.h */
1800                     "Key being pressed/depressed", HFILL }
1801                 },
1802
1803                 /* Client Pointer Event */
1804                 { &hf_vnc_button_1_pos,
1805                   { "Mouse button #1 position", "vnc.button_1_pos",
1806                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x1,
1807                     "Whether mouse button #1 is being pressed or not", HFILL }
1808                 },
1809                 { &hf_vnc_button_2_pos,
1810                   { "Mouse button #2 position", "vnc.button_2_pos",
1811                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x2,
1812                     "Whether mouse button #2 is being pressed or not", HFILL }
1813                 },
1814                 { &hf_vnc_button_3_pos,
1815                   { "Mouse button #3 position", "vnc.button_3_pos",
1816                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x4,
1817                     "Whether mouse button #3 is being pressed or not", HFILL }
1818                 },
1819                 { &hf_vnc_button_4_pos,
1820                   { "Mouse button #4 position", "vnc.button_4_pos",
1821                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x8,
1822                     "Whether mouse button #4 is being pressed or not", HFILL }
1823                 },
1824                 { &hf_vnc_button_5_pos,
1825                   { "Mouse button #5 position", "vnc.button_5_pos",
1826                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x10,
1827                     "Whether mouse button #5 is being pressed or not", HFILL }
1828                 },
1829                 { &hf_vnc_button_6_pos,
1830                   { "Mouse button #6 position", "vnc.button_6_pos",
1831                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x20,
1832                     "Whether mouse button #6 is being pressed or not", HFILL }
1833                 },
1834                 { &hf_vnc_button_7_pos,
1835                   { "Mouse button #7 position", "vnc.button_7_pos",
1836                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x40,
1837                     "Whether mouse button #7 is being pressed or not", HFILL }
1838                 },
1839                 { &hf_vnc_button_8_pos,
1840                   { "Mouse button #8 position", "vnc.button_8_pos",
1841                     FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x80,
1842                     "Whether mouse button #8 is being pressed or not", HFILL }
1843                 },
1844                 { &hf_vnc_pointer_x_pos,
1845                   { "X position", "vnc.pointer_x_pos",
1846                     FT_UINT16, BASE_DEC, NULL, 0x0,
1847                     "Position of mouse cursor on the x-axis", HFILL }
1848                 },
1849                 { &hf_vnc_pointer_y_pos,
1850                   { "Y position", "vnc.pointer_y_pos",
1851                     FT_UINT16, BASE_DEC, NULL, 0x0,
1852                     "Position of mouse cursor on the y-axis", HFILL }
1853                 },
1854                 { &hf_vnc_client_set_encodings_encoding_type,
1855                   { "Encoding type", "vnc.client_set_encodings_encoding_type",
1856                     FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
1857                     "Type of encoding used to send pixel data from server to client", HFILL }
1858                 },
1859
1860                 /* Client Framebuffer Update Request */
1861                 { &hf_vnc_update_req_incremental,
1862                   { "Incremental update", "vnc.update_req_incremental",
1863                     FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1864                     "Specifies if the client wants an incremental update instead of a full one", HFILL }
1865                 },
1866                 { &hf_vnc_update_req_x_pos,
1867                   { "X position", "vnc.update_req_x_pos",
1868                     FT_UINT16, BASE_DEC, NULL, 0x0,
1869                     "X position of framebuffer (screen) update requested", HFILL }
1870                 },
1871                 { &hf_vnc_update_req_y_pos,
1872                   { "Y position", "vnc.update_req_y_pos",
1873                     FT_UINT16, BASE_DEC, NULL, 0x0,
1874                     "Y position of framebuffer (screen) update request", HFILL }
1875                 },
1876                 { &hf_vnc_update_req_width,
1877                   { "Width", "vnc.update_req_width",
1878                     FT_UINT16, BASE_DEC, NULL, 0x0,
1879                     "Width of framebuffer (screen) update request", HFILL }
1880                 },
1881                 { &hf_vnc_update_req_height,
1882                   { "Height", "vnc.update_req_height",
1883                     FT_UINT16, BASE_DEC, NULL, 0x0,
1884                     "Height of framebuffer (screen) update request", HFILL }
1885                 },
1886                 { &hf_vnc_client_cut_text_len,
1887                   { "Length", "vnc.client_cut_text_len",
1888                     FT_UINT32, BASE_DEC, NULL, 0x0,
1889                     "Length of client's copy/cut text (clipboard) string in bytes", HFILL }
1890                 },
1891                 { &hf_vnc_client_cut_text,
1892                   { "Text", "vnc.client_cut_text",
1893                     FT_STRING, BASE_NONE, NULL, 0x0,
1894                     "Text string in the client's copy/cut text (clipboard)", HFILL }
1895                 },
1896
1897
1898                 /********** Server Message Types **********/
1899                 { &hf_vnc_server_message_type,
1900                   { "Server Message Type", "vnc.server_message_type",
1901                     FT_UINT8, BASE_DEC, VALS(server_message_types_vs), 0x0,
1902                     "Message type from server", HFILL }
1903                 },
1904
1905                 { &hf_vnc_fb_update_x_pos,
1906                   { "X position", "vnc.fb_update_x_pos",
1907                     FT_UINT16, BASE_DEC, NULL, 0x0,
1908                     "X position of this server framebuffer update", HFILL }
1909                 },
1910
1911                 { &hf_vnc_fb_update_y_pos,
1912                   { "Y position", "vnc.fb_update_x_pos",
1913                     FT_UINT16, BASE_DEC, NULL, 0x0,
1914                     "Y position of this server framebuffer update", HFILL }
1915                 },
1916
1917                 { &hf_vnc_fb_update_width,
1918                   { "Width", "vnc.fb_update_width",
1919                     FT_UINT16, BASE_DEC, NULL, 0x0,
1920                     "Width of this server framebuffer update", HFILL }
1921                 },
1922
1923                 { &hf_vnc_fb_update_height,
1924                   { "Height", "vnc.fb_update_width",
1925                     FT_UINT16, BASE_DEC, NULL, 0x0,
1926                     "Height of this server framebuffer update", HFILL }
1927                 },
1928
1929                 { &hf_vnc_fb_update_encoding_type,
1930                   { "Encoding type", "vnc.fb_update_encoding_type",
1931                     FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
1932                     "Encoding type of this server framebuffer update", HFILL }
1933                 },
1934
1935                 /* Cursor encoding */
1936                 { &hf_vnc_cursor_encoding_pixels,
1937                   { "Cursor encoding pixels", "vnc.cursor_encoding_pixels",
1938                     FT_BYTES, BASE_NONE, NULL, 0x0,
1939                     "Cursor encoding pixel data", HFILL }
1940                 },              
1941
1942                 { &hf_vnc_cursor_encoding_bitmask,
1943                   { "Cursor encoding bitmask", "vnc.cursor_encoding_bitmask",
1944                     FT_BYTES, BASE_NONE, NULL, 0x0,
1945                     "Cursor encoding pixel bitmask", HFILL }
1946                 },              
1947
1948                 /* Raw Encoding */
1949                 { &hf_vnc_raw_pixel_data,
1950                   { "Pixel data", "vnc.raw_pixel_data",
1951                     FT_BYTES, BASE_NONE, NULL, 0x0,
1952                     "Raw pixel data.", HFILL }
1953                 },              
1954
1955                 /* CopyRect Encoding*/
1956                 { &hf_vnc_copyrect_src_x_pos,
1957                   { "Source x position", "vnc.copyrect_src_x_pos",
1958                     FT_UINT16, BASE_DEC, NULL, 0x0,
1959                     "X position of the rectangle to copy from", HFILL }
1960                 },              
1961
1962                 { &hf_vnc_copyrect_src_y_pos,
1963                   { "Source y position", "vnc.copyrect_src_y_pos",
1964                     FT_UINT16, BASE_DEC, NULL, 0x0,
1965                     "Y position of the rectangle to copy from", HFILL }
1966                 },              
1967
1968                 /* RRE Encoding */
1969                 { &hf_vnc_rre_num_subrects,
1970                   { "Number of subrectangles", "vnc.rre_num_subrects",
1971                     FT_UINT32, BASE_DEC, NULL, 0x0,
1972                     "Number of subrectangles contained in this encoding type", HFILL }
1973                 },
1974
1975                 { &hf_vnc_rre_bg_pixel,
1976                   { "Background pixel value", "vnc.rre_bg_pixel",
1977                     FT_BYTES, BASE_NONE, NULL, 0x0,
1978                     "Background pixel value", HFILL }
1979                 },
1980
1981                 { &hf_vnc_rre_subrect_pixel,
1982                   { "Pixel value", "vnc.rre_subrect_pixel",
1983                     FT_BYTES, BASE_NONE, NULL, 0x0,
1984                     "Subrectangle pixel value", HFILL }
1985                 },
1986
1987                 { &hf_vnc_rre_subrect_x_pos,
1988                   { "X position", "vnc.rre_subrect_x_pos",
1989                     FT_UINT16, BASE_DEC, NULL, 0x0,
1990                     "Position of this subrectangle on the x axis", HFILL }
1991                 },
1992
1993                 { &hf_vnc_rre_subrect_y_pos,
1994                   { "Y position", "vnc.rre_subrect_y_pos",
1995                     FT_UINT16, BASE_DEC, NULL, 0x0,
1996                     "Position of this subrectangle on the y axis", HFILL }
1997                 },
1998
1999                 { &hf_vnc_rre_subrect_width,
2000                   { "Width", "vnc.rre_subrect_width",
2001                     FT_UINT16, BASE_DEC, NULL, 0x0,
2002                     "Width of this subrectangle", HFILL }
2003                 },
2004
2005                 { &hf_vnc_rre_subrect_height,
2006                   { "Height", "vnc.rre_subrect_height",
2007                     FT_UINT16, BASE_DEC, NULL, 0x0,
2008                     "Height of this subrectangle", HFILL }
2009                 },
2010
2011
2012                 /* Hextile Encoding */
2013                 { &hf_vnc_hextile_subencoding_mask,
2014                   { "Subencoding type", "vnc.hextile_subencoding",
2015                     FT_UINT8, BASE_DEC, NULL, 0x0,
2016                     "Hextile subencoding type.", HFILL }
2017                 },              
2018
2019                 { &hf_vnc_hextile_raw,
2020                   { "Raw", "vnc.hextile_raw",
2021                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x1,
2022                     "Raw subencoding is used in this tile", HFILL }
2023                 },              
2024
2025                 { &hf_vnc_hextile_raw_value,
2026                   { "Raw pixel values", "vnc.hextile_raw_value",
2027                     FT_BYTES, BASE_NONE, NULL, 0x0,
2028                     "Raw subencoding pixel values", HFILL }
2029                 },              
2030
2031                 { &hf_vnc_hextile_bg,
2032                   { "Background Specified", "vnc.hextile_bg",
2033                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x2,
2034                     "Background Specified subencoding is used in this tile", HFILL }
2035                 },
2036
2037                 { &hf_vnc_hextile_bg_value,
2038                   { "Background pixel value", "vnc.hextile_bg_value",
2039                     FT_BYTES, BASE_NONE, NULL, 0x0,
2040                     "Background color for this tile", HFILL }
2041                 },
2042
2043                 { &hf_vnc_hextile_fg,
2044                   { "Foreground Specified", "vnc.hextile_fg",
2045                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x4,
2046                     "Foreground Specified subencoding is used in this tile", HFILL }
2047                 },              
2048
2049                 { &hf_vnc_hextile_fg_value,
2050                   { "Foreground pixel value", "vnc.hextile_fg_value",
2051                     FT_BYTES, BASE_NONE, NULL, 0x0,
2052                     "Foreground color for this tile", HFILL }
2053                 },
2054
2055                 { &hf_vnc_hextile_anysubrects,
2056                   { "Any Subrects", "vnc.hextile_anysubrects",
2057                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x8,
2058                     "Any subrects subencoding is used in this tile", HFILL }
2059                 },              
2060
2061                 { &hf_vnc_hextile_num_subrects,
2062                   { "Number of subrectangles", "vnc.hextile_num_subrects",
2063                     FT_UINT8, BASE_DEC, NULL, 0x0,
2064                     "Number of subrectangles that follow", HFILL }
2065                 },              
2066
2067                 { &hf_vnc_hextile_subrectscolored,
2068                   { "Subrects Colored", "vnc.hextile_subrectscolored",
2069                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x10,
2070                     "Subrects colored subencoding is used in this tile", HFILL }
2071                 },              
2072
2073                 { &hf_vnc_hextile_subrect_pixel_value,
2074                   { "Pixel value", "vnc.hextile_subrect_pixel_value",
2075                     FT_BYTES, BASE_NONE, NULL, 0x0,
2076                     "Pixel value of this subrectangle", HFILL }
2077                 },              
2078
2079                 { &hf_vnc_hextile_subrect_x_pos,
2080                   { "X position", "vnc.hextile_subrect_x_pos",
2081                     FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
2082                     "X position of this subrectangle", HFILL }
2083                 },              
2084
2085                 { &hf_vnc_hextile_subrect_y_pos,
2086                   { "Y position", "vnc.hextile_subrect_y_pos",
2087                     FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
2088                     "Y position of this subrectangle", HFILL }
2089                 },              
2090
2091                 { &hf_vnc_hextile_subrect_width,
2092                   { "Width", "vnc.hextile_subrect_width",
2093                     FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
2094                     "Subrectangle width minus one", HFILL }
2095                 },              
2096
2097                 { &hf_vnc_hextile_subrect_height,
2098                   { "Height", "vnc.hextile_subrect_height",
2099                     FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
2100                     "Subrectangle height minus one", HFILL }
2101                 },              
2102
2103
2104                 /* ZRLE Encoding */
2105                 { &hf_vnc_zrle_len,
2106                   { "ZRLE compressed length", "vnc.zrle_len",
2107                     FT_UINT32, BASE_DEC, NULL, 0x0,
2108                     "Length of compressed ZRLE data that follows", HFILL }
2109                 },
2110
2111                 { &hf_vnc_zrle_subencoding,
2112                   { "Subencoding type", "vnc.zrle_subencoding",
2113                     FT_UINT8, BASE_DEC, NULL, 0x0,
2114                     "Subencoding type byte", HFILL }
2115                 },
2116
2117                 { &hf_vnc_zrle_rle,
2118                   { "RLE", "vnc.zrle_rle",
2119                     FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x80, /* Upper bit */
2120                     "Specifies that data is run-length encoded", HFILL }
2121                 },
2122
2123                 { &hf_vnc_zrle_palette_size,
2124                   { "Palette size", "vnc.zrle_palette_size",
2125                     FT_UINT8, BASE_DEC, NULL, 0x7F, /* Lower 7 bits */
2126                     "Palette size", HFILL }
2127                 },
2128
2129                 { &hf_vnc_zrle_data,
2130                   { "ZRLE compressed data", "vnc.zrle_data",
2131                     FT_BYTES, BASE_NONE, NULL, 0x0,
2132                     "Compressed ZRLE data.  Compiling with zlib support will uncompress and dissect this data", HFILL }
2133                 },
2134
2135                 { &hf_vnc_zrle_raw,
2136                   { "Pixel values", "vnc.zrle_raw",
2137                     FT_BYTES, BASE_NONE, NULL, 0x0,
2138                     "Raw pixel values for this tile", HFILL }
2139                 },
2140
2141                 { &hf_vnc_zrle_palette,
2142                   { "Palette", "vnc.zrle_palette",
2143                     FT_BYTES, BASE_NONE, NULL, 0x0,
2144                     "Palette pixel values", HFILL }
2145                 },
2146
2147                 /* Server Set Colormap Entries */
2148                 { &hf_vnc_colormap_first_color,
2149                   { "First color", "vnc.colormap_first_color",
2150                     FT_UINT16, BASE_DEC, NULL, 0x0,
2151                     "First color that should be mapped to given RGB intensities", HFILL }
2152                 },
2153                 { &hf_vnc_colormap_num_colors,
2154                   { "Number of color groups", "vnc.colormap_groups",
2155                     FT_UINT16, BASE_DEC, NULL, 0x0,
2156                     "Number of red/green/blue color groups", HFILL }
2157                 },
2158                 { &hf_vnc_colormap_red,
2159                   { "Red", "vnc.colormap_red",
2160                     FT_UINT16, BASE_DEC, NULL, 0x0,
2161                     "Red intensity", HFILL }
2162                 },
2163                 { &hf_vnc_colormap_green,
2164                   { "Green", "vnc.colormap_green",
2165                     FT_UINT16, BASE_DEC, NULL, 0x0,
2166                     "Green intensity", HFILL }
2167                 },
2168                 { &hf_vnc_colormap_blue,
2169                   { "Blue", "vnc.colormap_blue",
2170                     FT_UINT16, BASE_DEC, NULL, 0x0,
2171                     "Blue intensity", HFILL }
2172                 },
2173
2174                 /* Server Cut Text */
2175                 { &hf_vnc_server_cut_text_len,
2176                   { "Length", "vnc.server_cut_text_len",
2177                     FT_UINT32, BASE_DEC, NULL, 0x0,
2178                     "Length of server's copy/cut text (clipboard) string in bytes", HFILL }
2179                 },
2180                 { &hf_vnc_server_cut_text,
2181                   { "Text", "vnc.server_cut_text",
2182                     FT_STRING, BASE_NONE, NULL, 0x0,
2183                     "Text string in the server's copy/cut text (clipboard)", HFILL }
2184                 },
2185         };
2186
2187         /* Setup protocol subtree arrays */
2188         static gint *ett[] = {
2189                 &ett_vnc,
2190                 &ett_vnc_client_message_type,
2191                 &ett_vnc_server_message_type,
2192                 &ett_vnc_rect,
2193                 &ett_vnc_encoding_type,
2194                 &ett_vnc_rre_subrect,
2195                 &ett_vnc_hextile_subencoding_mask,
2196                 &ett_vnc_hextile_num_subrects,
2197                 &ett_vnc_hextile_subrect,
2198                 &ett_vnc_zrle_subencoding,
2199                 &ett_vnc_colormap_num_groups,
2200                 &ett_vnc_colormap_color_group
2201         };
2202
2203         /* Register the protocol name and description */
2204         proto_vnc = proto_register_protocol("Virtual Network Computing",
2205                                             "VNC", "vnc");
2206
2207         /* Required function calls to register the header fields and subtrees */
2208         proto_register_field_array(proto_vnc, hf, array_length(hf));
2209         proto_register_subtree_array(ett, array_length(ett));
2210
2211         /* Register our preferences module */
2212         vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);
2213
2214         prefs_register_bool_preference(vnc_module, "desegment", "Reassemble VNC messages spanning multiple TCP segments.", "Whether the VNC dissector should reasss emble messages spanning multiple TCP segments.  To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &vnc_preference_desegment);
2215
2216         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);
2217
2218 }
2219
2220 void
2221 proto_reg_handoff_vnc(void)
2222 {
2223         static gboolean inited = FALSE;
2224
2225         if(!inited) {
2226                 vnc_handle = create_dissector_handle(dissect_vnc,
2227                                                      proto_vnc);
2228
2229                 dissector_add("tcp.port", 5500, vnc_handle);
2230                 dissector_add("tcp.port", 5501, vnc_handle);
2231                 dissector_add("tcp.port", 5900, vnc_handle);
2232                 dissector_add("tcp.port", 5901, vnc_handle);
2233
2234                 /* We don't register a port for the VNC HTTP server because
2235                  * that simply provides a java program for download via the
2236                  * HTTP protocol.  The java program then connects to a standard
2237                  * VNC port. */
2238
2239                 inited = TRUE;
2240         }
2241
2242         if(vnc_preference_alternate_port != 5500 &&
2243            vnc_preference_alternate_port != 5501 &&
2244            vnc_preference_alternate_port != 5900 &&
2245            vnc_preference_alternate_port != 5901 &&
2246            vnc_preference_alternate_port != 0) {
2247
2248                 dissector_delete("tcp.port",
2249                                  vnc_preference_alternate_port_last,
2250                                  vnc_handle);
2251
2252                 /* Save this setting to see if has changed later */
2253                 vnc_preference_alternate_port_last =
2254                         vnc_preference_alternate_port;
2255
2256                 /* Register the new port setting */
2257                 dissector_add("tcp.port", vnc_preference_alternate_port,
2258                               vnc_handle);
2259                 
2260         }
2261
2262 }