![Anders Broman](/assets/img/avatar_default.png)
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
1233 lines
45 KiB
C
1233 lines
45 KiB
C
/* 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$
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/* Dissection of the VNC (Virtual Network Computing) network traffic.
|
|
*
|
|
* Several VNC implementations available, see:
|
|
* http://www.realvnc.com/
|
|
* http://www.tightvnc.com/
|
|
* http://ultravnc.sourceforge.net/
|
|
* ...
|
|
*
|
|
* The protocol itself is known as RFB - Remote Frame Buffer Protocol.
|
|
*
|
|
* 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
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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);
|
|
|
|
/* Variables for our preferences */
|
|
static guint vnc_preference_alternate_port = 0; /* An alternate port besides the default (5500, 5501, 5900, 5901) */
|
|
|
|
/* 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; /* 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;
|
|
|
|
/* 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 dissect the packets */
|
|
static void
|
|
dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
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;
|
|
|
|
conversation_t *conversation;
|
|
vnc_hash_entry_t *hash_info;
|
|
|
|
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");
|
|
|
|
/* 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);
|
|
}
|
|
|
|
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);
|
|
|
|
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");
|
|
|
|
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; /* To handle our preferences */
|
|
|
|
/* 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 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 */
|
|
proto_vnc = proto_register_protocol("Virtual Network Computing",
|
|
"VNC", "vnc");
|
|
|
|
/* 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 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);
|
|
|
|
}
|
|
|
|
void
|
|
proto_reg_handoff_vnc(void)
|
|
{
|
|
static gboolean inited = FALSE;
|
|
|
|
if(!inited) {
|
|
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 */
|
|
|
|
/* 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;
|
|
}
|
|
|
|
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 */
|
|
|
|
}
|
|
|
|
}
|