diff options
author | Anders Broman <anders.broman@ericsson.com> | 2006-09-05 05:38:11 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2006-09-05 05:38:11 +0000 |
commit | 5c682dd6ee5682454a269aa2316fb7d36709e30d (patch) | |
tree | b7d399e40e018a34a0d9ad2ca1a13e975c85a4f8 | |
parent | bec84221026d70b6efc88f05d04eb7332f123592 (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.c | 1288 | ||||
-rw-r--r-- | epan/dissectors/packet-x11-keysym.h | 3 |
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__ |