aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2006-09-05 05:38:11 +0000
committerAnders Broman <anders.broman@ericsson.com>2006-09-05 05:38:11 +0000
commit5c682dd6ee5682454a269aa2316fb7d36709e30d (patch)
treeb7d399e40e018a34a0d9ad2ca1a13e975c85a4f8
parentbec84221026d70b6efc88f05d04eb7332f123592 (diff)
From Stephen Fisher:
A patch to bring the VNC dissector almost to completion. I have not had a chance to finish the server message type "frame buffer update," which are the pixel values for screen rectangle updates. Everything else is there - tracking the keys the user is pushing, ringing a bell on the client, mouse button pushes/pointer movements, etc. svn path=/trunk/; revision=19145
-rw-r--r--epan/dissectors/packet-vnc.c1288
-rw-r--r--epan/dissectors/packet-x11-keysym.h3
2 files changed, 1132 insertions, 159 deletions
diff --git a/epan/dissectors/packet-vnc.c b/epan/dissectors/packet-vnc.c
index ae01b4b43a..993bb5b29b 100644
--- a/epan/dissectors/packet-vnc.c
+++ b/epan/dissectors/packet-vnc.c
@@ -1,6 +1,7 @@
/* packet-vnc.c
* Routines for VNC dissection (Virtual Network Computing)
* Copyright 2005, Ulf Lamping <ulf.lamping@web.de>
+ * Copyright 2006, Stephen Fisher <stephentfisher@yahoo.com>
*
* $Id$
*
@@ -33,8 +34,9 @@
*
* The protocol itself is known as RFB - Remote Frame Buffer Protocol.
*
- * Protocol specification:
- * http://www.realvnc.com/docs/rfbproto.pdf
+ * This code is based on the protocol specification:
+ * http://www.realvnc.com/docs/rfbproto.pdf
+ * and the RealVNC free edition source code
*/
#ifdef HAVE_CONFIG_H
@@ -47,216 +49,1184 @@
#include <glib.h>
+#include <epan/conversation.h>
+#include <epan/emem.h>
#include <epan/packet.h>
#include <epan/prefs.h>
+#include "packet-x11-keysym.h" /* This contains the X11 value_string "keysym_vals_source" that VNC uses */
+
+static const value_string security_types_vs[] = {
+ { 0, "Invalid" },
+ { 1, "None" },
+ { 2, "VNC" },
+ { 5, "RA2" },
+ { 6, "RA2ne" },
+ { 16, "Tight" },
+ { 17, "Ultra" },
+ { 18, "TLS" },
+ { 0, NULL }
+};
+
+static const value_string auth_result_vs[] = {
+ { 0, "OK" },
+ { 1, "Failed" },
+ { 0, NULL }
+};
+
+static const value_string yes_no_vs[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 0, NULL }
+};
+
+static const value_string client_message_types_vs[] = {
+ { 0, "Set Pixel Format" },
+ { 2, "Set Encodings" },
+ { 3, "Framebuffer Update Request" },
+ { 4, "Key Event" },
+ { 5, "Pointer Event" },
+ { 6, "Cut Text" },
+ { 0, NULL }
+};
+
+static const value_string server_message_types_vs[] = {
+ { 0, "Framebuffer Update" },
+ { 1, "Set Colormap Entries" },
+ { 2, "Ring Bell" },
+ { 3, "Cut Text" },
+ { 0, NULL }
+};
+
+static const value_string button_mask_vs[] = {
+ { 0, "Not pressed" },
+ { 1, "Pressed" },
+ { 0, NULL }
+};
+
+static const value_string encoding_types_vs[] = {
+ { -239, "Cursor (pseudo)" },
+ { -223, "DesktopSize (pseudo)" },
+ { 0, "Raw" },
+ { 1, "CopyRect" },
+ { 2, "RRE" },
+ { 4, "CoRRE" },
+ { 5, "Hextile" },
+ { 16, "ZRLE" },
+ { 0, NULL }
+};
+
void proto_reg_handoff_vnc(void);
-/* IF PROTO exposes code to other dissectors, then it must be exported
- in a header file. If not, a header file is not needed at all. */
-/*#include "packet-PROTOABBREV.h"*/
+/* Variables for our preferences */
+static guint vnc_preference_alternate_port = 0; /* An alternate port besides the default (5500, 5501, 5900, 5901) */
-static dissector_handle_t data_handle;
+/* This is a behind the scenes variable that is not changed by the user.
+ * This stores last setting of the vnc_preference_alternate_port. Used to keep
+ * track of when the user has changed the setting so that we can delete
+ * and re-register with the new port number. */
+static guint vnc_preference_alternate_port_last = 0;
/* Initialize the protocol and registered fields */
-static int proto_vnc = -1;
-static int hf_vnc = -1;
-static int hf_vnc_protocol_version = -1;
+static int proto_vnc = -1; /* Protocol subtree */
+static int hf_vnc_padding = -1;
+static int hf_vnc_server_proto_ver = -1;
+static int hf_vnc_client_proto_ver = -1;
+static int hf_vnc_num_security_types = -1;
+static int hf_vnc_security_type = -1;
+static int hf_vnc_server_security_type = -1;
+static int hf_vnc_client_security_type = -1;
+static int hf_vnc_auth_challenge = -1;
+static int hf_vnc_auth_response = -1;
+static int hf_vnc_auth_result = -1;
+static int hf_vnc_auth_error = -1;
+
+static int hf_vnc_share_desktop_flag = -1;
+static int hf_vnc_width = -1;
+static int hf_vnc_height = -1;
+static int hf_vnc_server_bits_per_pixel = -1;
+static int hf_vnc_server_depth = -1;
+static int hf_vnc_server_big_endian_flag = -1;
+static int hf_vnc_server_true_color_flag = -1;
+static int hf_vnc_server_red_max = -1;
+static int hf_vnc_server_green_max = -1;
+static int hf_vnc_server_blue_max = -1;
+static int hf_vnc_server_red_shift = -1;
+static int hf_vnc_server_green_shift = -1;
+static int hf_vnc_server_blue_shift = -1;
+static int hf_vnc_desktop_name = -1;
+static int hf_vnc_desktop_name_len = -1;
+
+
+/********** Client Message Types **********/
+
+static int hf_vnc_client_message_type = -1; /* A subtree under VNC */
+static int hf_vnc_client_bits_per_pixel = -1;
+static int hf_vnc_client_depth = -1;
+static int hf_vnc_client_big_endian_flag = -1;
+static int hf_vnc_client_true_color_flag = -1;
+static int hf_vnc_client_red_max = -1;
+static int hf_vnc_client_green_max = -1;
+static int hf_vnc_client_blue_max = -1;
+static int hf_vnc_client_red_shift = -1;
+static int hf_vnc_client_green_shift = -1;
+static int hf_vnc_client_blue_shift = -1;
+
+/* Client Key Event */
+static int hf_vnc_key_down = -1;
+static int hf_vnc_key = -1;
+
+/* Client Pointer Event */
+static int hf_vnc_button_1_pos = -1;
+static int hf_vnc_button_2_pos = -1;
+static int hf_vnc_button_3_pos = -1;
+static int hf_vnc_button_4_pos = -1;
+static int hf_vnc_button_5_pos = -1;
+static int hf_vnc_button_6_pos = -1;
+static int hf_vnc_button_7_pos = -1;
+static int hf_vnc_button_8_pos = -1;
+static int hf_vnc_pointer_x_pos = -1;
+static int hf_vnc_pointer_y_pos = -1;
+
+/* Client Framebuffer Update Request */
+static int hf_vnc_update_req_incremental = -1;
+static int hf_vnc_update_req_x_pos = -1;
+static int hf_vnc_update_req_y_pos = -1;
+static int hf_vnc_update_req_width = -1;
+static int hf_vnc_update_req_height = -1;
+
+/* Client Set Encodings */
+static int hf_vnc_client_set_encodings_encoding_type = -1;
-/* Global sample preference ("controls" display of numbers) */
-/*static gboolean gPREF_HEX = FALSE;*/
+/* Client Cut Text */
+static int hf_vnc_client_cut_text_len = -1;
+static int hf_vnc_client_cut_text = -1;
+
+/********** Server Message Types **********/
+
+static int hf_vnc_server_message_type = -1; /* Subtree */
+
+/* Server Set Colormap Entries */
+static int hf_vnc_colormap_first_color = -1;
+static int hf_vnc_colormap_num_colors = -1;
+static int hf_vnc_colormap_red = -1;
+static int hf_vnc_colormap_green = -1;
+static int hf_vnc_colormap_blue = -1;
+
+/* Server Cut Text */
+static int hf_vnc_server_cut_text_len = -1;
+static int hf_vnc_server_cut_text = -1;
+
+/********** End of Server Message Types **********/
+
+static gboolean vnc_preference_desegment = TRUE;
/* Initialize the subtree pointers */
static gint ett_vnc = -1;
+static gint ett_vnc_client_message_type = -1;
+static gint ett_vnc_server_message_type = -1;
+static gint ett_vnc_colormap_num_groups = -1;
+static gint ett_vnc_colormap_color_group = -1;
+
+static dissector_handle_t vnc_handle;
+
+/* Initialize the structure that will be tied to each conversation. */
+typedef struct {
+ /* Packet numbers for the first 9 packets of each conversation. */
+ guint32 first_packet_number, second_packet_number, third_packet_number, forth_packet_number, fifth_packet_number,
+ sixth_packet_number, seventh_packet_number, eighth_packet_number, ninth_packet_number;
+ gdouble server_proto_ver, client_proto_ver;
+} vnc_hash_entry_t;
-/* Code to actually dissect the packets */
+/* Code to dissect the packets */
static void
dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- gint offset = 0;
- gint length;
- guint8 *version;
+ guint8 num_security_types, message_type;
+ guint16 number_of_encodings = 0; /* Part of: Client Set Encodings */
+ guint16 number_of_colors; /* Part of: Server Set Colormap Entries */
+ guint32 text_len; /* Part of: Client Cut Text & Server Cut Text */
+ guint32 auth_result, desktop_name_len;
+ guint offset = 0, counter;
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti=NULL;
+ proto_tree *vnc_tree=NULL, *vnc_client_message_type_tree, *vnc_server_message_type_tree, *vnc_colormap_num_groups,
+ *vnc_colormap_color_group;
-/* Set up structures needed to add the protocol subtree and manage it */
- proto_item *ti;
- proto_tree *vnc_tree;
+ conversation_t *conversation;
+ vnc_hash_entry_t *hash_info;
-/* Make entries in Protocol column and Info column on summary display */
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+ if(!conversation) { /* Conversation does not exist yet - create it */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ /* Retrieve information from conversation
+ * or add it if it isn't there yet */
+ hash_info = conversation_get_proto_data(conversation, proto_vnc);
+ if(!hash_info) {
+ hash_info = se_alloc(sizeof(vnc_hash_entry_t));
+
+ /* We must be on the first packet now */
+ hash_info->first_packet_number = pinfo->fd->num;
+
+ /* The rest of these values will be set as we come across each packet */
+ hash_info->second_packet_number = 0;
+ hash_info->third_packet_number = 0;
+ hash_info->forth_packet_number = 0;
+ hash_info->fifth_packet_number = 0;
+ hash_info->sixth_packet_number = 0;
+ hash_info->seventh_packet_number = 0;
+ hash_info->eighth_packet_number = 0;
+ hash_info->ninth_packet_number = 0;
+
+ hash_info->server_proto_ver = 0.0;
+ hash_info->client_proto_ver = 0.0;
+
+ conversation_add_proto_data(conversation, proto_vnc, hash_info);
+ }
+
+ /* Store the number of the first nine packets of this conversation as we reach them for the first time.
+ * These are the packets that contain connection setup data and do not have a message type identifier.
+ * The packets after the ninth one do contain message type identifiers. */
+
+ if(!hash_info->second_packet_number && pinfo->fd->num > hash_info->first_packet_number) {
+ /* We're on the second packet of the conversation */
+ hash_info->second_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->second_packet_number && !hash_info->third_packet_number && pinfo->fd->num > hash_info->second_packet_number) {
+ /* We're on the third packet of the conversation */
+ hash_info->third_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->third_packet_number && !hash_info->forth_packet_number && pinfo->fd->num > hash_info->third_packet_number) {
+ /* We're on the forth packet of the conversation */
+ hash_info->forth_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->forth_packet_number && !hash_info->fifth_packet_number && pinfo->fd->num > hash_info->forth_packet_number) {
+ /* We're on the fifth packet of the conversation */
+ hash_info->fifth_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->fifth_packet_number && !hash_info->sixth_packet_number && pinfo->fd->num > hash_info->fifth_packet_number) {
+ /* We're on the sixth packet of the conversation */
+ hash_info->sixth_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->sixth_packet_number && !hash_info->seventh_packet_number && pinfo->fd->num > hash_info->sixth_packet_number) {
+ /* We're on the seventh packet of the conversation */
+ hash_info->seventh_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->seventh_packet_number && !hash_info->eighth_packet_number && pinfo->fd->num > hash_info->seventh_packet_number)
+ {
+ /* We're on the eighth packet of the conversation */
+ hash_info->eighth_packet_number = pinfo->fd->num;
+
+ } else if(hash_info->eighth_packet_number && !hash_info->ninth_packet_number && pinfo->fd->num > hash_info->eighth_packet_number) {
+ /* We're on the ninth packet of the conversation */
+ hash_info->ninth_packet_number = pinfo->fd->num;
+ }
+
+
+ /* Make entries in Protocol column and Info column on summary display */
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "VNC");
-
- if (check_col(pinfo->cinfo, COL_INFO))
- col_set_str(pinfo->cinfo, COL_INFO, "VNC");
-
-/* A protocol dissector can be called in 2 different ways:
-
- (a) Operational dissection
-
- In this mode, Wireshark is only interested in the way protocols
- interact, protocol conversations are created, packets are reassembled
- and handed over to higher-level protocol dissectors.
- In this mode Wireshark does not build a so-called "protocol tree".
-
- (b) Detailed dissection
-
- In this mode, Wireshark is also interested in all details of a given
- protocol, so a "protocol tree" is created.
-
- Wireshark distinguishes between the 2 modes with the proto_tree pointer:
- (a) <=> tree == NULL
- (b) <=> tree != NULL
-
- In the interest of speed, if "tree" is NULL, avoid building a
- protocol tree and adding stuff to it, or even looking at any packet
- data needed only if you're building the protocol tree, if possible.
-
- Note, however, that you must fill in column information, create
- conversations, reassemble packets, build any other persistent state
- needed for dissection, and call subdissectors regardless of whether
- "tree" is NULL or not. This might be inconvenient to do without
- doing most of the dissection work; the routines for adding items to
- the protocol tree can be passed a null protocol tree pointer, in
- which case they'll return a null item pointer, and
- "proto_item_add_subtree()" returns a null tree pointer if passed a
- null item pointer, so, if you're careful not to dereference any null
- tree or item pointers, you can accomplish this by doing all the
- dissection work. This might not be as efficient as skipping that
- work if you're not building a protocol tree, but if the code would
- have a lot of tests whether "tree" is null if you skipped that work,
- you might still be better off just doing all that work regardless of
- whether "tree" is null or not. */
- if (tree) {
-
-/* NOTE: The offset and length values in the call to
- "proto_tree_add_item()" define what data bytes to highlight in the hex
- display window when the line in the protocol tree display
- corresponding to that item is selected.
-
- Supplying a length of -1 is the way to highlight all data from the
- offset to the end of the packet. */
-
-/* create display subtree for the protocol */
- ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, FALSE);
- vnc_tree = proto_item_add_subtree(ti, ett_vnc);
-
- /* this is a hideous first hack!!! */
- if(tvb_length_remaining(tvb, offset) == 12) {
- length = 12;
- version = tvb_get_ephemeral_string(tvb, offset, length);
- if(version[0] == 'R' && version[1] == 'F' && version[2] == 'B') {
- /* remove trailing \n */
- version[11] = '\0';
- proto_tree_add_string(vnc_tree, hf_vnc_protocol_version, tvb, offset,
- length, version);
- if (check_col(pinfo->cinfo, COL_INFO))
- col_add_str(pinfo->cinfo, COL_INFO, version);
- offset += length;
- }
- }
-
-
-/* Continue adding tree items to process the packet here */
-
- call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
- pinfo, vnc_tree);
+ /* First, clear the info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* create display subtree for the protocol */
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, FALSE);
+ vnc_tree = proto_item_add_subtree(ti, ett_vnc);
}
-/* If this protocol has a sub-dissector call it here, see section 1.8 */
-}
+ offset = 0; /* Start at the beginning of the VNC protocol data */
+
+ /* Server Protocol Version */
+ if(pinfo->fd->num == hash_info->first_packet_number) {
+ proto_tree_add_item(vnc_tree, hf_vnc_server_proto_ver, tvb, 4, 7, FALSE);
+ hash_info->server_proto_ver = g_strtod(tvb_get_ephemeral_string(tvb, 4, 7), NULL);
-/* Register the protocol with Wireshark */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Server protocol version: %s", tvb_get_ephemeral_string(tvb, 4, 7));
+ }
+
+ /* Second Packet = Client Protocol Version */
+ else if(pinfo->fd->num == hash_info->second_packet_number) {
+ proto_tree_add_item(vnc_tree, hf_vnc_client_proto_ver, tvb, 4, 7, FALSE);
+ hash_info->client_proto_ver = g_strtod(tvb_get_ephemeral_string(tvb, 4, 7), NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Client protocol version: %s", tvb_get_ephemeral_string(tvb, 4, 7));
+
+ }
+
+ /* Security Types Supported */
+ else if(pinfo->fd->num == hash_info->third_packet_number) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Security types supported");
+
+ /* We're checking against the client protocol version because the client is the final decider
+ * on which version to use after the server offers the version it supports. */
+
+ if(hash_info->client_proto_ver >= 3.007) {
+ proto_tree_add_item(vnc_tree, hf_vnc_num_security_types, tvb, offset, 1, FALSE);
+ num_security_types = tvb_get_guint8(tvb, offset);
+
+ for(offset = 1; offset <= num_security_types; offset++) {
+ proto_tree_add_item(vnc_tree, hf_vnc_security_type, tvb, offset, 1, FALSE);
+ }
+ } else {
+ /* Version < 3.007: The server decides the authentication time for us to use */
+ proto_tree_add_item(vnc_tree, hf_vnc_server_security_type, tvb, offset, 4, FALSE);
+
+ }
+
+ }
+
+ /* Authentication type selected by client */
+ /* This field is skipped by versions < 3.007 so the packet number is off on each if statement below */
+ else if(hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->forth_packet_number) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Authentication type selected by client");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_client_security_type, tvb, offset, 1, FALSE);
+ }
+
+ /* Authentication challenge from server */
+ else if((hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->fifth_packet_number) ||
+ (hash_info->client_proto_ver < 3.007 && pinfo->fd->num == hash_info->forth_packet_number)) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Authentication challenge from server");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_auth_challenge, tvb, offset, 16, FALSE);
+ }
+
+ /* Authentication response from client */
+ else if((hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->sixth_packet_number) ||
+ (hash_info->client_proto_ver < 3.007 && pinfo->fd->num == hash_info->fifth_packet_number)) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Authentication response from client");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_auth_response, tvb, offset, 16, FALSE);
+ }
+
+ /* Authentication result */
+ else if((hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->seventh_packet_number) ||
+ (hash_info->client_proto_ver < 3.007 && pinfo->fd->num == hash_info->sixth_packet_number)) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Authentication result");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_auth_result, tvb, offset, 4, FALSE);
+ auth_result = tvb_get_ntohl(tvb, offset); /* 32-bit big endian accessor */
+ offset += 4;
+
+ if(hash_info->client_proto_ver >= 3.007 && auth_result == 1) { /* 1 = failed */
+ text_len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(vnc_tree, tvb, offset, 4, "Length of authentication error: %d", text_len);
+ offset += 4;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_auth_error, tvb, offset, text_len, FALSE);
+ offset += text_len;
+
+ }
+ }
+
+ /* Share desktop */
+ else if((hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->eighth_packet_number) ||
+ (hash_info->client_proto_ver < 3.007 && pinfo->fd->num == hash_info->seventh_packet_number)) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Share desktop flag");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_share_desktop_flag, tvb, offset, 1, FALSE);
+ }
+
+ /* Various parameters for the frame buffer (screen) from the server */
+ else if((hash_info->client_proto_ver >= 3.007 && pinfo->fd->num == hash_info->ninth_packet_number) ||
+ (hash_info->client_proto_ver < 3.007 && pinfo->fd->num == hash_info->eighth_packet_number)) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer parameters");
+
+ proto_tree_add_item(vnc_tree, hf_vnc_width, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_height, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_bits_per_pixel, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_depth, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_big_endian_flag, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_true_color_flag, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_red_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_green_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_blue_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_red_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_green_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_server_blue_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_padding, tvb, offset, 3, FALSE);
+ offset += 3; /* Skip over 3 bytes of padding */
+
+ if(tvb_length_remaining(tvb, offset) > 0) { /* Sometimes the desktop name & length is skipped */
+ proto_tree_add_item(vnc_tree, hf_vnc_desktop_name_len, tvb, offset, 4, FALSE);
+ desktop_name_len = tvb_get_ntohl(tvb, offset); /* 32-bit big endian accessor */
+ offset += 4;
+
+ proto_tree_add_item(vnc_tree, hf_vnc_desktop_name, tvb, offset, desktop_name_len, FALSE);
+ }
+
+ }
+
+ /* All packets beyond #9 */
+ else {
+ if(pinfo->destport == 5500 || pinfo->destport == 5501 || pinfo->destport == 5900 ||
+ pinfo->destport == 5901 || pinfo->destport == vnc_preference_alternate_port) { /* From client to server */
+
+ message_type = tvb_get_guint8(tvb, offset);
+
+ switch(message_type) {
+
+ case 0 : /* Client Set Pixel Format */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client set pixel format");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_padding, tvb, offset, 3, FALSE);
+ offset += 3; /* Skip over 3 bytes of padding */
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_bits_per_pixel, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_depth, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_big_endian_flag, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_true_color_flag, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_red_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_green_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_blue_max, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_red_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_green_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_blue_shift, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_padding, tvb, offset, 3, FALSE);
+ offset += 3; /* Skip over 3 bytes of padding */
+
+ break;
+
+ case 2 : /* Client Set Encodings */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client set encodings");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_padding, tvb, offset, 1, FALSE);
+ offset += 1; /* Skip over 1 byte of padding */
+
+ number_of_encodings = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_text(vnc_client_message_type_tree, tvb, offset, 2,
+ "Number of encodings: %d", number_of_encodings);
+ offset += 2;
+
+
+ for(counter = 1; counter <= number_of_encodings; counter++) {
+ proto_tree_add_item(vnc_client_message_type_tree,
+ hf_vnc_client_set_encodings_encoding_type, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ break;
+
+ case 3 : /* Client Framebuffer Update Request */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client framebuffer update request");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_update_req_incremental,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_update_req_x_pos,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_update_req_y_pos,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_update_req_width, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_update_req_height, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ break;
+
+ case 4 : /* Client Key Event */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client key event");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_key_down, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_padding, tvb, offset, 2, FALSE);
+ offset += 2; /* Skip over 2 bytes of padding */
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_key, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ break;
+
+ case 5: /* Client Pointer Event */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client pointer event");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_1_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_2_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_3_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_4_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_5_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_6_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_7_pos, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_button_8_pos, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_pointer_x_pos, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_pointer_y_pos, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ break;
+
+ case 6 : /* Client Cut Text */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Client cut text");
-/* this format is require because a script is used to build the C function
- that calls all the protocol registration.
-*/
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_client_message_type, tvb, offset, 1, FALSE);
+ vnc_client_message_type_tree = proto_item_add_subtree(ti, ett_vnc_client_message_type);
+ offset += 1;
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_padding, tvb, offset, 3, FALSE);
+ offset += 3; /* Skip over 3 bytes of padding */
+
+ text_len = tvb_get_ntohl(tvb, offset); /* 32-bit big endian accessor */
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_cut_text_len, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ proto_tree_add_item(vnc_client_message_type_tree, hf_vnc_client_cut_text, tvb, offset, text_len,
+ FALSE);
+ offset += text_len;
+
+ break;
+
+ default :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Unknown client message type");
+
+ proto_tree_add_text(vnc_tree, tvb, 0, -1, "Unknown client message type");
+
+ break;
+ }
+
+ } else { /* Packet is going from server to client */
+
+ message_type = tvb_get_guint8(tvb, offset);
+
+ switch(message_type) {
+
+ case 0 : /* Server Framebuffer Update */
+
+ /* XXX - This message type is not fully dissected yet */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer update");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_server_message_type, tvb, offset, 1, FALSE);
+ vnc_server_message_type_tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
+ offset += 1;
+
+ proto_tree_add_text(vnc_server_message_type_tree, tvb, offset, -1,
+ "Data");
+
+ break;
+
+ case 1 : /* Server Set Colormap Entries */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Server set colormap entries");
+
+ number_of_colors = tvb_get_ntohs(tvb, 4);
+ if(vnc_preference_desegment && pinfo->can_desegment &&
+ tvb_length_remaining(tvb, offset) < (number_of_colors * 6) + 6) {
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = (number_of_colors * 6) + 6 - tvb_length_remaining(tvb, offset);
+ return;
+ }
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_server_message_type, tvb, offset, 1, FALSE);
+ vnc_server_message_type_tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_server_message_type_tree, hf_vnc_padding, tvb, offset, 1, FALSE);
+ offset += 1; /* Skip over 1 byte of padding */
+
+ proto_tree_add_item(vnc_server_message_type_tree,
+ hf_vnc_colormap_first_color, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ ti = proto_tree_add_item(vnc_server_message_type_tree, hf_vnc_colormap_num_colors, tvb,
+ offset, 2, FALSE);
+ vnc_colormap_num_groups = proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
+
+ offset += 2;
+
+ for(counter = 1; counter <= number_of_colors; counter++) {
+ ti = proto_tree_add_text(vnc_colormap_num_groups, tvb, offset, 6,
+ "Color group #%d", counter);
+ vnc_colormap_color_group = proto_item_add_subtree(ti, ett_vnc_colormap_color_group);
+
+ proto_tree_add_item(vnc_colormap_color_group,
+ hf_vnc_colormap_red, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_colormap_color_group,
+ hf_vnc_colormap_green, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(vnc_colormap_color_group,
+ hf_vnc_colormap_blue, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ break;
+
+ case 2 : /* Server Ring Bell (on client) */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Server ring bell on client");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_server_message_type, tvb, offset, 1, FALSE);
+ vnc_server_message_type_tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
+ offset += 1;
+
+ /* This message type has no payload... */
+
+ break;
+
+ case 3 : /* Server Cut Text */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Server cut text");
+
+ ti = proto_tree_add_item(vnc_tree, hf_vnc_server_message_type, tvb, offset, 1, FALSE);
+ vnc_server_message_type_tree = proto_item_add_subtree(ti, ett_vnc_server_message_type);
+ offset += 1;
+
+ proto_tree_add_item(vnc_server_message_type_tree, hf_vnc_padding, tvb, offset, 3, FALSE);
+ offset += 3; /* Skip over 3 bytes of padding */
+
+ text_len = tvb_get_ntohl(tvb, offset); /* 32-bit big endian accessor */
+ proto_tree_add_item(vnc_server_message_type_tree, hf_vnc_server_cut_text_len, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ proto_tree_add_item(vnc_server_message_type_tree, hf_vnc_server_cut_text, tvb, offset, text_len,
+ FALSE);
+ offset += text_len;
+
+ break;
+
+ default :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Server framebuffer update (continuation)");
+
+ proto_tree_add_text(vnc_tree, tvb, 0, -1, "Server framebuffer update data (continuation)");
+
+ break;
+ }
+
+ }
+ }
+}
+
+
+/* Register the protocol with Wireshark */
void
proto_register_vnc(void)
{
-/* module_t *vnc_module;*/
+ module_t *vnc_module; /* To handle our preferences */
-/* Setup list of header fields See Section 1.6.1 for details*/
- static hf_register_info hf[] = {
- { &hf_vnc,
- { "VNC", "vnc", FT_NONE, BASE_NONE, NULL, 0x0, "Virtual Network Computing", HFILL }},
- { &hf_vnc_protocol_version,
- { "ProtocolVersion", "vnc.protocol_version", FT_STRING, BASE_NONE, NULL, 0x0, "Protocol Version", HFILL }
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_vnc_padding,
+ { "Padding", "vnc.padding",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Unused space", HFILL }
+ },
+
+ { &hf_vnc_server_proto_ver,
+ { "Server protocol version", "vnc.server_proto_ver",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "VNC protocol version on server", HFILL }
+ },
+ { &hf_vnc_client_proto_ver,
+ { "Client protocol version", "vnc.client_proto_ver",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "VNC protocol version on client", HFILL }
+ },
+ { &hf_vnc_num_security_types,
+ { "Number of security types", "vnc.num_security_types",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of security (authentication) types supported by the server", HFILL }
+ },
+ { &hf_vnc_security_type,
+ { "Security type", "vnc.security_type",
+ FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
+ "Security types offered by the server (VNC versions => 3.007", HFILL }
+ },
+ { &hf_vnc_server_security_type,
+ { "Security type", "vnc.server_security_type",
+ FT_UINT32, BASE_DEC, VALS(security_types_vs), 0x0,
+ "Security type mandated by the server (VNC versions < 3.007)", HFILL }
+ },
+ { &hf_vnc_client_security_type,
+ { "Security type selected", "vnc.security_type",
+ FT_UINT8, BASE_DEC, VALS(security_types_vs), 0x0,
+ "Security type selected by the client", HFILL }
+ },
+ { &hf_vnc_auth_challenge,
+ { "Authentication challenge", "vnc.auth_challenge",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Random authentication challenge from server to client", HFILL }
+ },
+ { &hf_vnc_auth_response,
+ { "Authentication response", "vnc.auth_response",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Client's encrypted response to the server's authentication challenge", HFILL }
+ },
+ { &hf_vnc_auth_result,
+ { "Authentication result", "vnc.auth_result",
+ FT_UINT32, BASE_DEC, VALS(auth_result_vs), 0x0,
+ "Authentication result", HFILL }
+ },
+ { &hf_vnc_auth_error,
+ { "Authentication error", "vnc.auth_error",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Authentication error (present only if the authentication result is fail", HFILL }
+ },
+ { &hf_vnc_share_desktop_flag,
+ { "Share desktop flag", "vnc.share_desktop_flag",
+ FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
+ "Client's desire to share the server's desktop with other clients", HFILL }
+ },
+ { &hf_vnc_width,
+ { "Framebuffer width", "vnc.width",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Width of the framebuffer (screen) in pixels", HFILL }
+ },
+ { &hf_vnc_height,
+ { "Framebuffer height", "vnc.width",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Height of the framebuffer (screen) in pixels", HFILL }
+ },
+ { &hf_vnc_server_bits_per_pixel,
+ { "Bits per pixel", "vnc.server_bits_per_pixel",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of bits used by server for each pixel value on the wire from the server", HFILL }
+ },
+ { &hf_vnc_server_depth,
+ { "Depth", "vnc.server_depth",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of useful bits in the pixel value on server", HFILL }
+ },
+ { &hf_vnc_server_big_endian_flag,
+ { "Big endian flag", "vnc.server_big_endian_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True if multi-byte pixels are interpreted as big endian by server", HFILL }
+ },
+ { &hf_vnc_server_true_color_flag,
+ { "True color flag", "vnc.server_true_color_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "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 }
+ },
+ { &hf_vnc_server_red_max,
+ { "Red maximum", "vnc.server_red_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum red value on server as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_server_green_max,
+ { "Green maximum", "vnc.server_green_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum green value on server as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_server_blue_max,
+ { "Blue maximum", "vnc.server_blue_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum blue value on server as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_server_red_shift,
+ { "Red shift", "vnc.server_red_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the red value in a pixel to the least significant bit on the server", HFILL }
+ },
+ { &hf_vnc_server_green_shift,
+ { "Green shift", "vnc.server_green_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the green value in a pixel to the least significant bit on the server", HFILL }
+ },
+ { &hf_vnc_server_blue_shift,
+ { "Blue shift", "vnc.server_blue_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the blue value in a pixel to the least significant bit on the server", HFILL }
+ },
+ { &hf_vnc_desktop_name_len,
+ { "Desktop name length", "vnc.desktop_name_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Length of desktop name in bytes", HFILL }
+ },
+ { &hf_vnc_desktop_name,
+ { "Desktop name", "vnc.desktop_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Name of the VNC desktop on the server", HFILL }
+ },
+ { &hf_vnc_client_message_type,
+ { "Client Message Type", "vnc.client_message_type",
+ FT_UINT8, BASE_DEC, VALS(client_message_types_vs), 0x0,
+ "Message type from client", HFILL }
+ },
+ { &hf_vnc_client_bits_per_pixel,
+ { "Bits per pixel", "vnc.client_bits_per_pixel",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of bits used by server for each pixel value on the wire from the client", HFILL }
+ },
+ { &hf_vnc_client_depth,
+ { "Depth", "vnc.client_depth",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of useful bits in the pixel value on client", HFILL }
+ },
+ { &hf_vnc_client_big_endian_flag,
+ { "Big endian flag", "vnc.client_big_endian_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True if multi-byte pixels are interpreted as big endian by client", HFILL }
+ },
+ { &hf_vnc_client_true_color_flag,
+ { "True color flag", "vnc.client_true_color_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "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 }
+ },
+ { &hf_vnc_client_red_max,
+ { "Red maximum", "vnc.client_red_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum red value on client as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_client_green_max,
+ { "Green maximum", "vnc.client_green_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum green value on client as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_client_blue_max,
+ { "Blue maximum", "vnc.client_blue_max",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum blue value on client as n: 2^n - 1", HFILL }
+ },
+ { &hf_vnc_client_red_shift,
+ { "Red shift", "vnc.client_red_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the red value in a pixel to the least significant bit on the client", HFILL }
+ },
+ { &hf_vnc_client_green_shift,
+ { "Green shift", "vnc.client_green_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the green value in a pixel to the least significant bit on the client", HFILL }
+ },
+ { &hf_vnc_client_blue_shift,
+ { "Blue shift", "vnc.client_blue_shift",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of shifts needed to get the blue value in a pixel to the least significant bit on the client", HFILL }
+ },
+
+ /* Client Key Event */
+ { &hf_vnc_key_down,
+ { "Key down", "vnc.key_down",
+ FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x0,
+ "Specifies whether the key is being pressed or not", HFILL }
+ },
+ { &hf_vnc_key,
+ { "Key", "vnc.key",
+ FT_UINT32, BASE_HEX, VALS(keysym_vals_source), 0x0, /* keysym_vals_source is from packet-x11-keysym.h */
+ "Key being pressed/depressed", HFILL }
+ },
+
+ /* Client Pointer Event */
+ { &hf_vnc_button_1_pos,
+ { "Mouse button #1 position", "vnc.button_1_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x1,
+ "Whether mouse button #1 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_2_pos,
+ { "Mouse button #2 position", "vnc.button_2_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x2,
+ "Whether mouse button #2 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_3_pos,
+ { "Mouse button #3 position", "vnc.button_3_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x4,
+ "Whether mouse button #3 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_4_pos,
+ { "Mouse button #4 position", "vnc.button_4_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x8,
+ "Whether mouse button #4 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_5_pos,
+ { "Mouse button #5 position", "vnc.button_5_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x10,
+ "Whether mouse button #5 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_6_pos,
+ { "Mouse button #6 position", "vnc.button_6_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x20,
+ "Whether mouse button #6 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_7_pos,
+ { "Mouse button #7 position", "vnc.button_7_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x40,
+ "Whether mouse button #7 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_button_8_pos,
+ { "Mouse button #8 position", "vnc.button_8_pos",
+ FT_UINT8, BASE_DEC, VALS(&button_mask_vs), 0x80,
+ "Whether mouse button #8 is being pressed or not", HFILL }
+ },
+ { &hf_vnc_pointer_x_pos,
+ { "X position", "vnc.pointer_x_pos",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Position of mouse cursor on the x-axis", HFILL }
+ },
+ { &hf_vnc_pointer_y_pos,
+ { "Y position", "vnc.pointer_y_pos",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Position of mouse cursor on the y-axis", HFILL }
+ },
+ { &hf_vnc_client_set_encodings_encoding_type,
+ { "Encoding type", "vnc.client_set_encodings_encoding_type",
+ FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
+ "Type of encoding used to send pixel data from server to client", HFILL }
+ },
+
+ /* Client Framebuffer Update Request */
+ { &hf_vnc_update_req_incremental,
+ { "Incremental update", "vnc.update_req_incremental",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Specifies if the client wants an incremental update instead of a full one", HFILL }
+ },
+ { &hf_vnc_update_req_x_pos,
+ { "X position", "vnc.update_req_x_pos",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "X position of framebuffer (screen) update requested", HFILL }
+ },
+ { &hf_vnc_update_req_y_pos,
+ { "Y position", "vnc.update_req_y_pos",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Y position of framebuffer (screen) update request", HFILL }
+ },
+ { &hf_vnc_update_req_width,
+ { "Width", "vnc.update_req_width",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Width of framebuffer (screen) update request", HFILL }
+ },
+ { &hf_vnc_update_req_height,
+ { "Height", "vnc.update_req_height",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Height of framebuffer (screen) update request", HFILL }
+ },
+ { &hf_vnc_client_cut_text_len,
+ { "Length", "vnc.client_cut_text_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Length of client's copy/cut text (clipboard) string in bytes", HFILL }
+ },
+ { &hf_vnc_client_cut_text,
+ { "Text", "vnc.client_cut_text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Text string in the client's copy/cut text (clipboard)", HFILL }
+ },
+
+
+ /********** Server Message Types **********/
+ { &hf_vnc_server_message_type,
+ { "Server Message Type", "vnc.server_message_type",
+ FT_UINT8, BASE_DEC, VALS(server_message_types_vs), 0x0,
+ "Message type from server", HFILL }
+ },
+
+ /* Server Set Colormap Entries */
+ { &hf_vnc_colormap_first_color,
+ { "First color", "vnc.colormap_first_color",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "First color that should be mapped to given RGB intensities", HFILL }
+ },
+ { &hf_vnc_colormap_num_colors,
+ { "Number of color groups", "vnc.colormap_groups",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of red/green/blue color groups", HFILL }
+ },
+ { &hf_vnc_colormap_red,
+ { "Red", "vnc.colormap_red",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Red intensity", HFILL }
+ },
+ { &hf_vnc_colormap_green,
+ { "Green", "vnc.colormap_green",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Green intensity", HFILL }
+ },
+ { &hf_vnc_colormap_blue,
+ { "Blue", "vnc.colormap_blue",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Blue intensity", HFILL }
+ },
+
+ /* Server Cut Text */
+ { &hf_vnc_server_cut_text_len,
+ { "Length", "vnc.server_cut_text_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Length of server's copy/cut text (clipboard) string in bytes", HFILL }
+ },
+ { &hf_vnc_server_cut_text,
+ { "Text", "vnc.server_cut_text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Text string in the server's copy/cut text (clipboard)", HFILL }
},
};
-/* Setup protocol subtree array */
+ /* Setup protocol subtree arrays */
static gint *ett[] = {
&ett_vnc,
+ &ett_vnc_client_message_type,
+ &ett_vnc_server_message_type,
+ &ett_vnc_colormap_num_groups,
+ &ett_vnc_colormap_color_group
};
-/* Register the protocol name and description */
+ /* Register the protocol name and description */
proto_vnc = proto_register_protocol("Virtual Network Computing",
- "VNC", "vnc");
+ "VNC", "vnc");
-/* Required function calls to register the header fields and subtrees used */
+ /* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_vnc, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
-/* Register preferences module (See Section 2.6 for more on preferences) */
-/* vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);*/
-
-/* Register a sample preference */
-/* prefs_register_bool_preference(vnc_module, "showHex",
- "Display numbers in Hex",
- "Enable to display numerical values in hexadecimal.",
- &gPREF_HEX ); */
-}
+ /* Register our preferences module */
+ vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);
+
+ prefs_register_bool_preference(vnc_module, "desegment", "Reassemble VNC 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);
+ 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);
+
+}
-/* If this dissector uses sub-dissector registration add a registration routine.
- This exact format is required because a script is used to find these routines
- and create the code that calls these routines.
-
- This function is also called by preferences whenever "Apply" is pressed
- (see prefs_register_protocol above) so it should accommodate being called
- more than once.
-*/
void
proto_reg_handoff_vnc(void)
{
static gboolean inited = FALSE;
-
- if( !inited ) {
-
- dissector_handle_t vnc_handle;
- data_handle = find_dissector("data");
+ if(!inited) {
+ vnc_handle = create_dissector_handle(dissect_vnc,
+ proto_vnc);
- vnc_handle = create_dissector_handle(dissect_vnc,
- proto_vnc);
+ dissector_add("tcp.port", 5500, vnc_handle); /* First screen on listening vnc viewer */
+ dissector_add("tcp.port", 5501, vnc_handle); /* Second screen on listening vnc viewer */
+ dissector_add("tcp.port", 5900, vnc_handle); /* First screen on server */
+ dissector_add("tcp.port", 5901, vnc_handle); /* Second screen on server */
- /* XXX - we need a heuristic or at least a preference setting for this port */
- dissector_add("tcp.port", 5901, vnc_handle);
-
- inited = TRUE;
- }
-
- /*
- If you perform registration functions which are dependant upon
- prefs the you should de-register everything which was associated
- with the previous settings and re-register using the new prefs settings
- here. In general this means you need to keep track of what value the
- preference had at the time you registered using a local static in this
- function. ie.
-
- static int currentPort = -1;
-
- if( -1 != currentPort ) {
- dissector_delete( "tcp.port", currentPort, PROTOABBREV_handle);
- }
+ /* We don't register a port for the VNC HTTP server because that simply provides a java program
+ * for download via the normal HTTP protocol. The java program then connects to a standard VNC port (above). */
+
+ inited = TRUE;
+ }
- currentPort = gPortPref;
+ if(vnc_preference_alternate_port != 5500 && vnc_preference_alternate_port != 5501 &&
+ vnc_preference_alternate_port != 5900 && vnc_preference_alternate_port != 5901 &&
+ vnc_preference_alternate_port != 0) {
+
+ dissector_delete("tcp.port", vnc_preference_alternate_port_last, vnc_handle);
+ vnc_preference_alternate_port_last = vnc_preference_alternate_port; /* Save this setting to see if has changed later */
+ dissector_add("tcp.port", vnc_preference_alternate_port, vnc_handle); /* Register the new port setting */
+
+ }
- dissector_add("tcp.port", currentPort, PROTOABBREV_handle);
-
- */
}
-
diff --git a/epan/dissectors/packet-x11-keysym.h b/epan/dissectors/packet-x11-keysym.h
index 9afbfd5e93..6bc53a78ed 100644
--- a/epan/dissectors/packet-x11-keysym.h
+++ b/epan/dissectors/packet-x11-keysym.h
@@ -3,6 +3,9 @@
* $Id$
*
* Put there so as to make packet-x11.c lighter. See packet-x11.c
+ *
+ * This file is also used by packet-vnc.c
+ *
*/
#ifndef __PACKET_X11_KEYSYM_H__