wireshark/epan/dissectors/packet-vnc.c
Michael Mann 268841f3e0 Combine Decode As and port preferences for tcp.port dissector table.
This patch introduces new APIs to allow dissectors to have a preference for
a (TCP) port, but the underlying data is actually part of Decode As functionality.
For now the APIs are intentionally separate from the regular APIs that register a
dissector within a dissector table.  It may be possible to eventually combine the
two so that all dissectors that register with a dissector table have an opportunity
to "automatically" have a preference to adjust the "table value" through the
preferences dialog.

The tcp.port dissector table was used as the guinea pig.  This will eventually be
expanded to other dissector tables as well (most notably UDP ports).  Some
dissectors that "shared" a TCP/UDP port preference were also converted. It also
removed the need for some preference callback functions (mostly when the callback
function was the proto_reg_handoff function) so there is cleanup around that.

Dissectors that has a port preference whose default was 0 were switched to using
the dissector_add_for_decode_as_with_preference API rather than dissector_add_uint_with_preference

Also added comments for TCP ports used that aren't IANA registered.

Change-Id: I99604f95d426ad345f4b494598d94178b886eb67
Reviewed-on: https://code.wireshark.org/review/17724
Reviewed-by: Michael Mann <mmann78@netscape.net>
2016-10-08 02:44:53 +00:00

4789 lines
159 KiB
C

/* packet-vnc.c
* Routines for VNC dissection (Virtual Network Computing)
* Copyright 2005, Ulf Lamping <ulf.lamping@web.de>
* Copyright 2006-2007, Stephen Fisher (see AUTHORS file)
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Dissection of the VNC (Virtual Network Computing) network traffic.
*
* All versions of RealVNC and TightVNC are supported.
* Note: The addition of TightVNC support is not yet complete.
*
* Several VNC implementations available, see:
* http://www.realvnc.com/
* http://www.tightvnc.com/
* http://ultravnc.sourceforge.net/
* [Fedora TigerVNC]
* ...
*
* 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 & TightVNC source code
* Note: rfbproto.rst [ https://github.com/svn2github/tigervnc/blob/master/rfbproto/rfbproto.rst ]
* seems to have additional information over rfbproto.pdf.
*/
/* XXX:
* This dissector adds items to the protocol tree before completing re-assembly
* of a VNC PDU which extends over more than one TCP segment.
* This is not correct. As noted in Bug #5366 (and elsewhere), the correct method
* is that:
* "one must walk over all the message first, to determine its exact length
* (one of the characteristics of the protocol, hard to determine prior to
* going over the message what its final size would be)".
*
* The original method of reassembly:
* When more data is needed to continue dissecting a PDU, repeatedly request
* a few additional bytes (for one or a few more fields of the PDU).
* This resulted in 'one-pass' tshark dissection redissecting
* the PDU repeatedly many, many times with each time dissecting
* the PDU with one or a few more additional fields.
* This generated *lots* of (repeated) output since a reassembled
* VNC PDU can contain many fields (each of short length).
* It also resulted in the fragment table containing many, many small fragments
* for VNC PDUS containing many small fields.
*
* The current reassembly method:
* Use DESEGMENT_ONE_MORE_SEGMENT when requesting additional data for a PDU.
* This significantly reduces the amount of repeated data in a dissection,
* but will still result in "partial" repeated dissection output in some cases.
*/
/* (Somewhat random notes while reviewing the code):
Check types, etc against IANA list
Optimize: Do col_set(..., COL_INFO) once (after fetching message type & before dispatching ?)
Dispatch via a message table (instead of using a switch(...)
Worry about globals (vnc_bytes_per_pixel & nc_depth): "Global so they keep their value between packets"
Msg type 150: client-server: enable/disable (1+9 bytes); server-client: endofContinousUpdates(1+0 bytes) ?
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/conversation.h>
#include <epan/prefs.h>
#include <epan/prefs-int.h>
#include <epan/expert.h>
#include <epan/proto_data.h>
#include "packet-x11.h" /* This contains the extern for the X11 value_string_ext
* "x11_keysym_vals_source_ext" that VNC uses. */
void proto_register_vnc(void);
typedef enum {
VNC_SECURITY_TYPE_INVALID = 0,
VNC_SECURITY_TYPE_NONE = 1,
VNC_SECURITY_TYPE_VNC = 2,
VNC_SECURITY_TYPE_RA2 = 5,
VNC_SECURITY_TYPE_RA2ne = 6,
VNC_SECURITY_TYPE_TIGHT = 16,
VNC_SECURITY_TYPE_ULTRA = 17,
VNC_SECURITY_TYPE_TLS = 18,
VNC_SECURITY_TYPE_VENCRYPT = 19,
VNC_SECURITY_TYPE_GTK_VNC_SASL = 20,
VNC_SECURITY_TYPE_MD5_HASH_AUTH = 21,
VNC_SECURITY_TYPE_XVP = 22,
VNC_SECURITY_TYPE_ARD = 30,
VNC_TIGHT_AUTH_TGHT_ULGNAUTH = 119,
VNC_TIGHT_AUTH_TGHT_XTRNAUTH = 130
} vnc_security_types_e;
static const value_string vnc_security_types_vs[] = {
{ VNC_SECURITY_TYPE_INVALID, "Invalid" },
{ VNC_SECURITY_TYPE_NONE, "None" },
{ VNC_SECURITY_TYPE_VNC, "VNC" },
{ VNC_SECURITY_TYPE_RA2, "RA2" },
{ VNC_SECURITY_TYPE_RA2ne, "RA2ne" },
{ VNC_SECURITY_TYPE_TIGHT, "Tight" },
{ VNC_SECURITY_TYPE_ULTRA, "Ultra" },
{ VNC_SECURITY_TYPE_TLS, "TLS" },
{ VNC_SECURITY_TYPE_VENCRYPT, "VeNCrypt" },
{ VNC_SECURITY_TYPE_GTK_VNC_SASL, "GTK-VNC SASL" },
{ VNC_SECURITY_TYPE_ARD, "Apple Remote Desktop" },
{ 0, NULL }
};
static const true_false_string auth_result_tfs = {
"Failed",
"OK"
};
static const value_string yes_no_vs[] = {
{ 0, "No" },
{ 1, "Yes" },
{ 0, NULL }
};
typedef enum {
/* Required */
VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT = 0,
VNC_CLIENT_MESSAGE_TYPE_SET_ENCODINGS = 2,
VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ = 3,
VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT = 4,
VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT = 5,
VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT = 6,
/* Optional */
VNC_CLIENT_MESSAGE_TYPE_MIRRORLINK = 128,
VNC_CLIENT_MESSAGE_TYPE_ENABLE_CONTINUOUS_UPDATES = 150, /* TightVNC */
VNC_CLIENT_MESSAGE_TYPE_FENCE = 248, /* TigerVNC */
VNC_CLIENT_MESSAGE_TYPE_XVP = 250,
VNC_CLIENT_MESSAGE_TYPE_SETR_DESKTOP_SIZE = 251,
VNC_CLIENT_MESSAGE_TYPE_TIGHT = 252,
VNC_CLIENT_MESSAGE_TYPE_GII = 253,
VNC_CLIENT_MESSAGE_TYPE_QEMU = 255
} vnc_client_message_types_e;
static const value_string vnc_client_message_types_vs[] = {
/* Required */
{ VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT, "Set Pixel Format" },
{ VNC_CLIENT_MESSAGE_TYPE_SET_ENCODINGS, "Set Encodings" },
{ VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ, "Framebuffer Update Request" },
{ VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT, "Key Event" },
{ VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT, "Pointer Event" },
{ VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT, "Cut Text" },
/* Optional */
{ VNC_CLIENT_MESSAGE_TYPE_MIRRORLINK, "MirrorLink" },
{ VNC_CLIENT_MESSAGE_TYPE_ENABLE_CONTINUOUS_UPDATES, "Enable Continuous Updates" },
{ VNC_CLIENT_MESSAGE_TYPE_FENCE, "Fence" },
{ VNC_CLIENT_MESSAGE_TYPE_XVP, "Xvp" },
{ VNC_CLIENT_MESSAGE_TYPE_SETR_DESKTOP_SIZE, "Setr Desktop Size" },
{ VNC_CLIENT_MESSAGE_TYPE_TIGHT, "Tight" },
{ VNC_CLIENT_MESSAGE_TYPE_GII, "Gii" },
{ VNC_CLIENT_MESSAGE_TYPE_QEMU, "Qemu" },
{ 0, NULL }
};
typedef enum {
VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE = 0,
VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES = 1,
VNC_SERVER_MESSAGE_TYPE_RING_BELL = 2,
VNC_SERVER_MESSAGE_TYPE_CUT_TEXT = 3,
VNC_SERVER_MESSAGE_TYPE_MIRRORLINK = 128,
VNC_SERVER_MESSAGE_TYPE_END_CONTINUOUS_UPDATES = 150, /* TightVNC */
VNC_SERVER_MESSAGE_TYPE_FENCE = 248, /* TigerVNC */
VNC_SERVER_MESSAGE_TYPE_XVP = 250,
VNC_SERVER_MESSAGE_TYPE_TIGHT = 252,
VNC_SERVER_MESSAGE_TYPE_GII = 253,
VNC_SERVER_MESSAGE_TYPE_QEMU = 255
} vnc_server_message_types_e;
static const value_string vnc_server_message_types_vs[] = {
{ VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE, "Framebuffer Update" },
{ VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES, "Set Colormap Entries" },
{ VNC_SERVER_MESSAGE_TYPE_RING_BELL, "Ring Bell" },
{ VNC_SERVER_MESSAGE_TYPE_CUT_TEXT, "Cut Text" },
{ VNC_SERVER_MESSAGE_TYPE_MIRRORLINK, "MirrorLink" },
{ VNC_SERVER_MESSAGE_TYPE_END_CONTINUOUS_UPDATES, "End Continuous Updates" },
{ VNC_SERVER_MESSAGE_TYPE_FENCE, "Fence" },
{ VNC_SERVER_MESSAGE_TYPE_XVP, "Xvp" },
{ VNC_SERVER_MESSAGE_TYPE_TIGHT, "Tight" },
{ VNC_SERVER_MESSAGE_TYPE_GII, "Gii" },
{ VNC_SERVER_MESSAGE_TYPE_QEMU, "Qemu" },
{ 0, NULL }
};
static const true_false_string button_mask_tfs = {
"Pressed",
"Not pressed"
};
#define VNC_ENCODING_TYPE_DESKTOP_SIZE 0xFFFFFF21
#define VNC_ENCODING_TYPE_LAST_RECT 0xFFFFFF20
#define VNC_ENCODING_TYPE_POINTER_POS 0xFFFFFF18
#define VNC_ENCODING_TYPE_RICH_CURSOR 0xFFFFFF11
#define VNC_ENCODING_TYPE_X_CURSOR 0xFFFFFF10
#define VNC_ENCODING_TYPE_RAW 0
#define VNC_ENCODING_TYPE_COPY_RECT 1
#define VNC_ENCODING_TYPE_RRE 2
#define VNC_ENCODING_TYPE_CORRE 4
#define VNC_ENCODING_TYPE_HEXTILE 5
#define VNC_ENCODING_TYPE_ZLIB 6
#define VNC_ENCODING_TYPE_TIGHT 7
#define VNC_ENCODING_TYPE_ZLIBHEX 8
#define VNC_ENCODING_TYPE_ULTRA 9
#define VNC_ENCODING_TYPE_TRLE 15
#define VNC_ENCODING_TYPE_RLE 16
#define VNC_ENCODING_TYPE_HITACHI_ZYWRLE 17
#define VNC_ENCODING_TYPE_JPEG_0 -32
#define VNC_ENCODING_TYPE_JPEG_1 -31
#define VNC_ENCODING_TYPE_JPEG_2 -30
#define VNC_ENCODING_TYPE_JPEG_3 -29
#define VNC_ENCODING_TYPE_JPEG_4 -28
#define VNC_ENCODING_TYPE_JPEG_5 -27
#define VNC_ENCODING_TYPE_JPEG_6 -26
#define VNC_ENCODING_TYPE_JPEG_7 -25
#define VNC_ENCODING_TYPE_JPEG_8 -24
#define VNC_ENCODING_TYPE_JPEG_9 -23
#define VNC_ENCODING_TYPE_COMPRESSION_0 0xFFFFFF00
#define VNC_ENCODING_TYPE_COMPRESSION_1 0xFFFFFF01
#define VNC_ENCODING_TYPE_COMPRESSION_2 0xFFFFFF02
#define VNC_ENCODING_TYPE_COMPRESSION_3 0xFFFFFF03
#define VNC_ENCODING_TYPE_COMPRESSION_4 0xFFFFFF04
#define VNC_ENCODING_TYPE_COMPRESSION_5 0xFFFFFF05
#define VNC_ENCODING_TYPE_COMPRESSION_6 0xFFFFFF06
#define VNC_ENCODING_TYPE_COMPRESSION_7 0xFFFFFF07
#define VNC_ENCODING_TYPE_COMPRESSION_8 0xFFFFFF08
#define VNC_ENCODING_TYPE_COMPRESSION_9 0xFFFFFF09
#define VNC_ENCODING_TYPE_WMVi 0x574D5669
#define VNC_ENCODING_TYPE_CACHE 0xFFFF0000
#define VNC_ENCODING_TYPE_CACHE_ENABLE 0xFFFF0001
#define VNC_ENCODING_TYPE_XOR_ZLIB 0xFFFF0002
#define VNC_ENCODING_TYPE_XOR_MONO_ZLIB 0xFFFF0003
#define VNC_ENCODING_TYPE_XOR_MULTI_ZLIB 0xFFFF0004
#define VNC_ENCODING_TYPE_SOLID_COLOR 0xFFFF0005
#define VNC_ENCODING_TYPE_XOR_ENABLE 0xFFFF0006
#define VNC_ENCODING_TYPE_CACHE_ZIP 0xFFFF0007
#define VNC_ENCODING_TYPE_SOL_MONO_ZIP 0xFFFF0008
#define VNC_ENCODING_TYPE_ULTRA_ZIP 0xFFFF0009
#define VNC_ENCODING_TYPE_SERVER_STATE 0xFFFF8000
#define VNC_ENCODING_TYPE_ENABLE_KEEP_ALIVE 0xFFFF8001
#define VNC_ENCODING_TYPE_FTP_PROTO_VER 0xFFFF8002
#define VNC_ENCODING_TYPE_POINTER_CHANGE -257
#define VNC_ENCODING_TYPE_EXT_KEY_EVENT -258
#define VNC_ENCODING_TYPE_AUDIO 259
#define VNC_ENCODING_TYPE_DESKTOP_NAME -307
#define VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE -308
#define VNC_ENCODING_TYPE_KEYBOARD_LED_STATE 0XFFFE0000
#define VNC_ENCODING_TYPE_SUPPORTED_MESSAGES 0XFFFE0001
#define VNC_ENCODING_TYPE_SUPPORTED_ENCODINGS 0XFFFE0002
#define VNC_ENCODING_TYPE_SERVER_IDENTITY 0XFFFE0003
#define VNC_ENCODING_TYPE_MIRRORLINK 0xFFFFFDF5
#define VNC_ENCODING_TYPE_CONTEXT_INFORMATION 0xFFFFFDF4
#define VNC_ENCODING_TYPE_SLRLE 0xFFFFFDF3
#define VNC_ENCODING_TYPE_TRANSFORM 0xFFFFFDF2
#define VNC_ENCODING_TYPE_HSML 0xFFFFFDF1
#define VNC_ENCODING_TYPE_H264 0X48323634
static const value_string encoding_types_vs[] = {
{ VNC_ENCODING_TYPE_DESKTOP_SIZE, "DesktopSize (pseudo)" },
{ VNC_ENCODING_TYPE_LAST_RECT, "LastRect (pseudo)" },
{ VNC_ENCODING_TYPE_POINTER_POS, "Pointer pos (pseudo)" },
{ VNC_ENCODING_TYPE_RICH_CURSOR, "Rich Cursor (pseudo)" },
{ VNC_ENCODING_TYPE_X_CURSOR, "X Cursor (pseudo)" },
{ VNC_ENCODING_TYPE_RAW, "Raw" },
{ VNC_ENCODING_TYPE_COPY_RECT, "CopyRect" },
{ VNC_ENCODING_TYPE_RRE, "RRE" },
{ VNC_ENCODING_TYPE_CORRE, "CoRRE" },
{ VNC_ENCODING_TYPE_HEXTILE, "Hextile" },
{ VNC_ENCODING_TYPE_ZLIB, "Zlib" },
{ VNC_ENCODING_TYPE_TIGHT, "Tight" },
{ VNC_ENCODING_TYPE_ZLIBHEX, "ZlibHex" },
{ VNC_ENCODING_TYPE_ULTRA, "Ultra" },
{ VNC_ENCODING_TYPE_RLE, "ZRLE" },
{ VNC_ENCODING_TYPE_HITACHI_ZYWRLE, "Hitachi ZYWRLE" },
{ VNC_ENCODING_TYPE_JPEG_0, "JPEG quality level 0" },
{ VNC_ENCODING_TYPE_JPEG_1, "JPEG quality level 1" },
{ VNC_ENCODING_TYPE_JPEG_2, "JPEG quality level 2" },
{ VNC_ENCODING_TYPE_JPEG_3, "JPEG quality level 3" },
{ VNC_ENCODING_TYPE_JPEG_4, "JPEG quality level 4" },
{ VNC_ENCODING_TYPE_JPEG_5, "JPEG quality level 5" },
{ VNC_ENCODING_TYPE_JPEG_6, "JPEG quality level 6" },
{ VNC_ENCODING_TYPE_JPEG_7, "JPEG quality level 7" },
{ VNC_ENCODING_TYPE_JPEG_8, "JPEG quality level 8" },
{ VNC_ENCODING_TYPE_JPEG_9, "JPEG quality level 9" },
{ VNC_ENCODING_TYPE_COMPRESSION_0, "Compression level 0" },
{ VNC_ENCODING_TYPE_COMPRESSION_1, "Compression level 1" },
{ VNC_ENCODING_TYPE_COMPRESSION_2, "Compression level 2" },
{ VNC_ENCODING_TYPE_COMPRESSION_3, "Compression level 3" },
{ VNC_ENCODING_TYPE_COMPRESSION_4, "Compression level 4" },
{ VNC_ENCODING_TYPE_COMPRESSION_5, "Compression level 5" },
{ VNC_ENCODING_TYPE_COMPRESSION_6, "Compression level 6" },
{ VNC_ENCODING_TYPE_COMPRESSION_7, "Compression level 7" },
{ VNC_ENCODING_TYPE_COMPRESSION_8, "Compression level 8" },
{ VNC_ENCODING_TYPE_COMPRESSION_9, "Compression level 9" },
/* FIXME understand for real what the below mean. Taken from Ultra VNC source code */
/* { VNC_ENCODING_TYPE_CACHE, */
{ VNC_ENCODING_TYPE_CACHE_ENABLE, "Enable Caching"},
/* { VNC_ENCODING_TYPE_XOR_ZLIB,
{ VNC_ENCODING_TYPE_XOR_MONO_ZLIB,
{ VNC_ENCODING_TYPE_XOR_MULTI_ZLIB,
{ VNC_ENCODING_TYPE_SOLID_COLOR,
{ VNC_ENCODING_TYPE_XOR_ENABLE,
{ VNC_ENCODING_TYPE_CACHE_ZIP,
{ VNC_ENCODING_TYPE_SOL_MONO_ZIP,
{ VNC_ENCODING_TYPE_ULTRA_ZIP,
*/ { VNC_ENCODING_TYPE_SERVER_STATE, "Server State" },
{ VNC_ENCODING_TYPE_ENABLE_KEEP_ALIVE, "Enable Keep Alive" },
{ VNC_ENCODING_TYPE_FTP_PROTO_VER, "FTP protocol version" },
{ VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE, "Extended Desktop Size"},
{ VNC_ENCODING_TYPE_DESKTOP_NAME, "Desktop Name" },
{ VNC_ENCODING_TYPE_KEYBOARD_LED_STATE, "Keyboard LED State" },
{ VNC_ENCODING_TYPE_SUPPORTED_MESSAGES, "Supported Messages" },
{ VNC_ENCODING_TYPE_SUPPORTED_ENCODINGS, "Supported Encodings" },
{ VNC_ENCODING_TYPE_SERVER_IDENTITY, "Server Identity" },
{ VNC_ENCODING_TYPE_MIRRORLINK, "MirrorLink" },
{ VNC_ENCODING_TYPE_CONTEXT_INFORMATION, "Context Information" },
{ VNC_ENCODING_TYPE_SLRLE, "SLRLE" },
{ VNC_ENCODING_TYPE_TRANSFORM, "Transform" },
{ VNC_ENCODING_TYPE_HSML, "HSML" },
{ VNC_ENCODING_TYPE_H264, "H264" },
{ 0, NULL }
};
/* Rectangle types for Tight encoding. These come in the "control byte" at the
* start of a rectangle's payload. Note that these are with respect to the most
* significant bits 4-7 of the control byte, so you must shift it to the right 4
* bits before comparing against these values.
*/
#define TIGHT_RECT_FILL 0x08
#define TIGHT_RECT_JPEG 0x09
#define TIGHT_RECT_MAX_VALUE 0x09
#define TIGHT_RECT_EXPLICIT_FILTER_FLAG 0x04
/* Filter types for Basic encoding of Tight rectangles */
#define TIGHT_RECT_FILTER_COPY 0x00
#define TIGHT_RECT_FILTER_PALETTE 0x01
#define TIGHT_RECT_FILTER_GRADIENT 0x02
/* Minimum number of bytes to compress for Tight encoding */
#define TIGHT_MIN_BYTES_TO_COMPRESS 12
static const value_string tight_filter_ids_vs[] = {
{ TIGHT_RECT_FILTER_COPY, "Copy" },
{ TIGHT_RECT_FILTER_PALETTE, "Palette" },
{ TIGHT_RECT_FILTER_GRADIENT, "Gradient" },
{ 0, NULL }
};
/* MirrorLink messages */
typedef enum {
VNC_ML_EXT_BYE_BYE = 0,
VNC_ML_EXT_SERVER_DISPLAY_CONFIGURATION = 1,
VNC_ML_EXT_CLIENT_DISPLAY_CONFIGURATION = 2,
VNC_ML_EXT_SERVER_EVENT_CONFIGURATION = 3,
VNC_ML_EXT_CLIENT_EVENT_CONFIGURATION = 4,
VNC_ML_EXT_EVENT_MAPPING = 5,
VNC_ML_EXT_EVENT_MAPPING_REQUEST = 6,
VNC_ML_EXT_KEY_EVENT_LISTING = 7,
VNC_ML_EXT_KEY_EVENT_LISTING_REQUEST = 8,
VNC_ML_EXT_VIRTUAL_KEYBOARD = 9,
VNC_ML_EXT_VIRTUAL_KEYBOARD_REQUEST = 10,
VNC_ML_EXT_DEVICE_STATUS = 11,
VNC_ML_EXT_DEVICE_STATUS_REQUEST = 12,
VNC_ML_EXT_CONTENT_ATTESTATION = 13,
VNC_ML_EXT_CONTENT_ATTESTATION_REQUEST = 14,
VNC_ML_EXT_FB_BLOCKING_NOTIFICATION = 16,
VNC_ML_EXT_AUDIO_BLOCKING_NOTIFICATION = 18,
VNC_ML_EXT_TOUCH_EVENT = 20,
VNC_ML_EXT_FB_ALTERNATIVE_TEXT = 21,
VNC_ML_EXT_FB_ALTERNATIVE_TEXT_REQUEST = 22
} vnc_mirrorlink_ext_types_e;
static const value_string vnc_mirrorlink_types_vs[] = {
{ VNC_ML_EXT_BYE_BYE, "ByeBye" },
{ VNC_ML_EXT_SERVER_DISPLAY_CONFIGURATION, "Server Display Configuration" },
{ VNC_ML_EXT_CLIENT_DISPLAY_CONFIGURATION, "Client Display Configuration" },
{ VNC_ML_EXT_SERVER_EVENT_CONFIGURATION, "Server Event Configuration" },
{ VNC_ML_EXT_CLIENT_EVENT_CONFIGURATION, "Client Event Configuration" },
{ VNC_ML_EXT_EVENT_MAPPING, "Event Mapping" },
{ VNC_ML_EXT_EVENT_MAPPING_REQUEST, "Event Mapping Request" },
{ VNC_ML_EXT_KEY_EVENT_LISTING, "Key Event Listing" },
{ VNC_ML_EXT_KEY_EVENT_LISTING_REQUEST, "Key Event Listing Request" },
{ VNC_ML_EXT_VIRTUAL_KEYBOARD, "Virtual Keyboard Trigger" },
{ VNC_ML_EXT_VIRTUAL_KEYBOARD_REQUEST, "Virtual Keyboard Trigger Request" },
{ VNC_ML_EXT_DEVICE_STATUS, "Device Status" },
{ VNC_ML_EXT_DEVICE_STATUS_REQUEST, "Device Status Request" },
{ VNC_ML_EXT_CONTENT_ATTESTATION, "Content Attestation" },
{ VNC_ML_EXT_CONTENT_ATTESTATION_REQUEST, "Content Attestation Request" },
{ VNC_ML_EXT_FB_BLOCKING_NOTIFICATION, "Framebuffer Blocking Notification" },
{ VNC_ML_EXT_AUDIO_BLOCKING_NOTIFICATION, "Audio Blocking Notification" },
{ VNC_ML_EXT_TOUCH_EVENT, "Touch Event" },
{ VNC_ML_EXT_FB_ALTERNATIVE_TEXT, "Framebuffer Alternative Text" },
{ VNC_ML_EXT_FB_ALTERNATIVE_TEXT_REQUEST, "Framebuffer Alternative Text Request" },
{ 0, NULL }
};
/* Slice types for H.264 encoding */
typedef enum {
VNC_H264_SLICE_TYPE_P = 0,
VNC_H264_SLICE_TYPE_B = 1,
VNC_H264_SLICE_TYPE_I = 2
} vnc_h264_slice_types_e;
static const value_string vnc_h264_slice_types_vs[] = {
{ VNC_H264_SLICE_TYPE_P, "Predicted" },
{ VNC_H264_SLICE_TYPE_B, "Bi-predicted" },
{ VNC_H264_SLICE_TYPE_I, "Intra coded" },
{ 0, NULL }
};
typedef enum {
VNC_SESSION_STATE_SERVER_VERSION,
VNC_SESSION_STATE_CLIENT_VERSION,
VNC_SESSION_STATE_SECURITY,
VNC_SESSION_STATE_SECURITY_TYPES,
VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES,
VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY,
VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES,
VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY,
VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3,
VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE,
VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE,
VNC_SESSION_STATE_ARD_AUTHENTICATION_CHALLENGE,
VNC_SESSION_STATE_ARD_AUTHENTICATION_RESPONSE,
VNC_SESSION_STATE_SECURITY_RESULT,
VNC_SESSION_STATE_CLIENT_INIT,
VNC_SESSION_STATE_SERVER_INIT,
VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS,
VNC_SESSION_STATE_NORMAL_TRAFFIC
} vnc_session_state_e;
#define VNC_FENCE_BLOCK_BEFORE 0x00000001
#define VNC_FENCE_BLOCK_AFTER 0x00000002
#define VNC_FENCE_SYNC_NEXT 0x00000004
#define VNC_FENCE_REQUEST 0x80000000
/* This structure will be tied to each conversation. */
typedef struct {
gdouble server_proto_ver, client_proto_ver;
vnc_session_state_e vnc_next_state;
guint32 server_port;
/* These are specific to TightVNC */
gint num_server_message_types;
gint num_client_message_types;
gint num_encoding_types;
guint8 security_type_selected;
gboolean tight_enabled;
/* This is specific to Apple Remote Desktop */
guint16 ard_key_length;
} vnc_conversation_t;
/* This structure will be tied to each packet */
typedef struct {
vnc_session_state_e state;
gint preferred_encoding;
guint8 bytes_per_pixel;
guint8 depth;
} vnc_packet_t;
void proto_reg_handoff_vnc(void);
static gboolean vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo,
gint offset, proto_tree *tree,
vnc_conversation_t *per_conversation_info);
static void vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_client_framebuffer_update_request(tvbuff_t *tvb,
packet_info *pinfo,
gint *offset,
proto_tree *tree);
static void vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree);
static guint vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static guint vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height);
static guint vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree,
const guint16 width, const guint16 height);
static guint vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height);
static guint vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree,
const guint16 width, const guint16 height);
static guint vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height);
static guint vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height);
static guint vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree, const guint16 width,
const guint16 height);
static guint vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree, const guint16 width,
const guint16 height);
static guint vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_server_ring_bell(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static guint vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree);
static void vnc_set_bytes_per_pixel(packet_info *pinfo, const guint8 bytes_per_pixel);
static void vnc_set_depth(packet_info *pinfo, const guint8 depth);
static guint8 vnc_get_bytes_per_pixel(packet_info *pinfo);
static guint8 vnc_get_depth(packet_info *pinfo);
static guint32 vnc_extended_desktop_size(tvbuff_t *tvb, gint *offset, proto_tree *tree);
static guint vnc_supported_messages(tvbuff_t *tvb, gint *offset,
proto_tree *tree, const guint16 width);
static guint vnc_supported_encodings(tvbuff_t *tvb, gint *offset,
proto_tree *tree, const guint16 width,
const guint16 height);
static guint vnc_server_identity(tvbuff_t *tvb, gint *offset,
proto_tree *tree, const guint16 width);
static guint vnc_fence(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree);
static guint vnc_mirrorlink(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree);
static guint vnc_context_information(tvbuff_t *tvb, gint *offset,
proto_tree *tree);
static guint vnc_slrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 height);
static guint vnc_h264_encoding(tvbuff_t *tvb, gint *offset, proto_tree *tree);
#define VNC_BYTES_NEEDED(a) \
if((a) > (guint)tvb_reported_length_remaining(tvb, *offset)) \
return (a);
/* 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_auth_error_length = -1;
static int hf_vnc_ard_auth_generator = -1;
static int hf_vnc_ard_auth_key_len = -1;
static int hf_vnc_ard_auth_modulus = -1;
static int hf_vnc_ard_auth_server_key = -1;
static int hf_vnc_ard_auth_credentials = -1;
static int hf_vnc_ard_auth_client_key = -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;
static int hf_vnc_desktop_screen_num = -1;
static int hf_vnc_desktop_screen_id = -1;
static int hf_vnc_desktop_screen_x = -1;
static int hf_vnc_desktop_screen_y = -1;
static int hf_vnc_desktop_screen_width = -1;
static int hf_vnc_desktop_screen_height = -1;
static int hf_vnc_desktop_screen_flags = -1;
static int hf_vnc_num_server_message_types = -1;
static int hf_vnc_num_client_message_types = -1;
static int hf_vnc_num_encoding_types = -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_encoding_num = -1;
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 */
/* Tunneling capabilities (TightVNC extension) */
static int hf_vnc_tight_num_tunnel_types = -1;
static int hf_vnc_tight_tunnel_type = -1;
/* Authentication capabilities (TightVNC extension) */
static int hf_vnc_tight_num_auth_types = -1;
static int hf_vnc_tight_auth_code = -1;
/* TightVNC capabilities */
static int hf_vnc_tight_server_message_type = -1;
static int hf_vnc_tight_server_vendor = -1;
static int hf_vnc_tight_signature = -1;
static int hf_vnc_tight_server_name = -1;
static int hf_vnc_tight_client_message_type = -1;
static int hf_vnc_tight_client_vendor = -1;
static int hf_vnc_tight_client_name = -1;
static int hf_vnc_tight_encoding_type = -1;
static int hf_vnc_tight_encoding_vendor = -1;
static int hf_vnc_tight_encoding_name = -1;
/* Tight compression parameters */
static int hf_vnc_tight_reset_stream0 = -1;
static int hf_vnc_tight_reset_stream1 = -1;
static int hf_vnc_tight_reset_stream2 = -1;
static int hf_vnc_tight_reset_stream3 = -1;
static int hf_vnc_tight_rect_type = -1;
static int hf_vnc_tight_image_len = -1;
static int hf_vnc_tight_image_data = -1;
static int hf_vnc_tight_fill_color = -1;
static int hf_vnc_tight_filter_flag = -1;
static int hf_vnc_tight_filter_id = -1;
static int hf_vnc_tight_palette_num_colors = -1;
static int hf_vnc_tight_palette_data = -1;
/* Server Framebuffer Update */
static int hf_vnc_rectangle_num = -1;
static int hf_vnc_fb_update_x_pos = -1;
static int hf_vnc_fb_update_y_pos = -1;
static int hf_vnc_fb_update_width = -1;
static int hf_vnc_fb_update_height = -1;
static int hf_vnc_fb_update_encoding_type = -1;
/* Raw Encoding */
static int hf_vnc_raw_pixel_data = -1;
/* CopyRect Encoding */
static int hf_vnc_copyrect_src_x_pos = -1;
static int hf_vnc_copyrect_src_y_pos = -1;
/* RRE Encoding */
static int hf_vnc_rre_num_subrects = -1;
static int hf_vnc_rre_bg_pixel = -1;
static int hf_vnc_rre_subrect_pixel = -1;
static int hf_vnc_rre_subrect_x_pos = -1;
static int hf_vnc_rre_subrect_y_pos = -1;
static int hf_vnc_rre_subrect_width = -1;
static int hf_vnc_rre_subrect_height = -1;
/* Hextile Encoding */
static int hf_vnc_hextile_subencoding_mask = -1;
static int hf_vnc_hextile_raw = -1;
static int hf_vnc_hextile_raw_value = -1;
static int hf_vnc_hextile_bg = -1;
static int hf_vnc_hextile_bg_value = -1;
static int hf_vnc_hextile_fg = -1;
static int hf_vnc_hextile_fg_value = -1;
static int hf_vnc_hextile_anysubrects = -1;
static int hf_vnc_hextile_num_subrects = -1;
static int hf_vnc_hextile_subrectscolored = -1;
static int hf_vnc_hextile_subrect_pixel_value = -1;
static int hf_vnc_hextile_subrect_x_pos = -1;
static int hf_vnc_hextile_subrect_y_pos = -1;
static int hf_vnc_hextile_subrect_width = -1;
static int hf_vnc_hextile_subrect_height = -1;
/* ZRLE Encoding */
static int hf_vnc_zrle_len = -1;
static int hf_vnc_zrle_subencoding = -1;
static int hf_vnc_zrle_rle = -1;
static int hf_vnc_zrle_palette_size = -1;
static int hf_vnc_zrle_data = -1;
static int hf_vnc_zrle_raw = -1;
static int hf_vnc_zrle_palette = -1;
/* Cursor Encoding */
static int hf_vnc_cursor_x_fore_back = -1;
static int hf_vnc_cursor_encoding_pixels = -1;
static int hf_vnc_cursor_encoding_bitmask = -1;
/* Server Set Colormap Entries */
static int hf_vnc_color_groups = -1;
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;
/* LibVNCServer additions */
static int hf_vnc_supported_messages_client2server = -1;
static int hf_vnc_supported_messages_server2client = -1;
static int hf_vnc_num_supported_encodings = -1;
static int hf_vnc_supported_encodings = -1;
static int hf_vnc_server_identity = -1;
/* MirrorLink */
static int hf_vnc_mirrorlink_type = -1;
static int hf_vnc_mirrorlink_length = -1;
static int hf_vnc_mirrorlink_version_major = -1;
static int hf_vnc_mirrorlink_version_minor = -1;
static int hf_vnc_mirrorlink_framebuffer_configuration = -1;
static int hf_vnc_mirrorlink_pixel_width = -1;
static int hf_vnc_mirrorlink_pixel_height = -1;
static int hf_vnc_mirrorlink_pixel_format = -1;
static int hf_vnc_mirrorlink_display_width = -1;
static int hf_vnc_mirrorlink_display_height = -1;
static int hf_vnc_mirrorlink_display_distance = -1;
static int hf_vnc_mirrorlink_keyboard_language = -1;
static int hf_vnc_mirrorlink_keyboard_country = -1;
static int hf_vnc_mirrorlink_ui_language = -1;
static int hf_vnc_mirrorlink_ui_country = -1;
static int hf_vnc_mirrorlink_knob_keys = -1;
static int hf_vnc_mirrorlink_device_keys = -1;
static int hf_vnc_mirrorlink_multimedia_keys = -1;
static int hf_vnc_mirrorlink_key_related = -1;
static int hf_vnc_mirrorlink_pointer_related = -1;
static int hf_vnc_mirrorlink_key_symbol_value_client = -1;
static int hf_vnc_mirrorlink_key_symbol_value_server = -1;
static int hf_vnc_mirrorlink_key_configuration = -1;
static int hf_vnc_mirrorlink_key_num_events = -1;
static int hf_vnc_mirrorlink_key_event_counter = -1;
static int hf_vnc_mirrorlink_key_symbol_value = -1;
static int hf_vnc_mirrorlink_key_request_configuration = -1;
static int hf_vnc_mirrorlink_keyboard_configuration = -1;
static int hf_vnc_mirrorlink_cursor_x = -1;
static int hf_vnc_mirrorlink_cursor_y = -1;
static int hf_vnc_mirrorlink_text_x = -1;
static int hf_vnc_mirrorlink_text_y = -1;
static int hf_vnc_mirrorlink_text_width = -1;
static int hf_vnc_mirrorlink_text_height = -1;
static int hf_vnc_mirrorlink_keyboard_request_configuration = -1;
static int hf_vnc_mirrorlink_device_status = -1;
static int hf_vnc_mirrorlink_app_id = -1;
static int hf_vnc_mirrorlink_fb_block_x = -1;
static int hf_vnc_mirrorlink_fb_block_y = -1;
static int hf_vnc_mirrorlink_fb_block_width = -1;
static int hf_vnc_mirrorlink_fb_block_height = -1;
static int hf_vnc_mirrorlink_fb_block_reason = -1;
static int hf_vnc_mirrorlink_audio_block_reason = -1;
static int hf_vnc_mirrorlink_touch_num_events = -1;
static int hf_vnc_mirrorlink_touch_x = -1;
static int hf_vnc_mirrorlink_touch_y = -1;
static int hf_vnc_mirrorlink_touch_id = -1;
static int hf_vnc_mirrorlink_touch_pressure = -1;
static int hf_vnc_mirrorlink_text = -1;
static int hf_vnc_mirrorlink_text_length = -1;
static int hf_vnc_mirrorlink_text_max_length = -1;
static int hf_vnc_mirrorlink_unknown = -1;
/* Fence */
static int hf_vnc_fence_flags = -1;
static int hf_vnc_fence_request = -1;
static int hf_vnc_fence_sync_next = -1;
static int hf_vnc_fence_block_after = -1;
static int hf_vnc_fence_block_before = -1;
static int hf_vnc_fence_payload_length = -1;
static int hf_vnc_fence_payload = -1;
static const int *vnc_fence_flags[] = {
&hf_vnc_fence_request,
&hf_vnc_fence_sync_next,
&hf_vnc_fence_block_after,
&hf_vnc_fence_block_before,
NULL
};
/* Context Information */
static int hf_vnc_context_information_app_id = -1;
static int hf_vnc_context_information_app_category = -1;
static int hf_vnc_context_information_app_trust_level = -1;
static int hf_vnc_context_information_content_category = -1;
static int hf_vnc_context_information_content_rules = -1;
static int hf_vnc_context_information_content_trust_level = -1;
/* Scan Line based Run-Length Encoding */
static int hf_vnc_slrle_run_num = -1;
static int hf_vnc_slrle_run_data = -1;
/* H.264 Encoding */
static int hf_vnc_h264_slice_type = -1;
static int hf_vnc_h264_nbytes = -1;
static int hf_vnc_h264_width = -1;
static int hf_vnc_h264_height = -1;
static int hf_vnc_h264_data = -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_rect = -1;
static gint ett_vnc_encoding_type = -1;
static gint ett_vnc_rre_subrect = -1;
static gint ett_vnc_hextile_subencoding_mask = -1;
static gint ett_vnc_hextile_num_subrects = -1;
static gint ett_vnc_hextile_subrect = -1;
static gint ett_vnc_hextile_tile = -1;
static gint ett_vnc_zrle_subencoding = -1;
static gint ett_vnc_colormap_num_groups = -1;
static gint ett_vnc_colormap_color_group = -1;
static gint ett_vnc_desktop_screen = -1;
static gint ett_vnc_key_events = -1;
static gint ett_vnc_touch_events = -1;
static gint ett_vnc_slrle_subline = -1;
static gint ett_vnc_fence_flags = -1;
static expert_field ei_vnc_possible_gtk_vnc_bug = EI_INIT;
static expert_field ei_vnc_auth_code_mismatch = EI_INIT;
static expert_field ei_vnc_unknown_tight_vnc_auth = EI_INIT;
static expert_field ei_vnc_too_many_rectangles = EI_INIT;
static expert_field ei_vnc_too_many_sub_rectangles = EI_INIT;
static expert_field ei_vnc_invalid_encoding = EI_INIT;
static expert_field ei_vnc_too_many_colors = EI_INIT;
static expert_field ei_vnc_too_many_cut_text = EI_INIT;
static expert_field ei_vnc_zrle_failed = EI_INIT;
static expert_field ei_vnc_unknown_tight = EI_INIT;
static expert_field ei_vnc_reassemble = EI_INIT;
/* Global so they keep their value between packets */
guint8 vnc_bytes_per_pixel;
guint8 vnc_depth;
#define VNC_PORT_RANGE "5500-5501,5900-5901" /* Not IANA registered */
static range_t *vnc_tcp_range = NULL;
static dissector_handle_t vnc_handle;
/* Code to dissect the packets */
static int
dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
gboolean ret;
gint offset = 0;
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *ti;
proto_tree *vnc_tree;
conversation_t *conversation;
vnc_conversation_t *per_conversation_info;
conversation = find_or_create_conversation(pinfo);
/* Retrieve information from conversation, or add it if it isn't
* there yet */
per_conversation_info = (vnc_conversation_t *)conversation_get_proto_data(conversation, proto_vnc);
if(!per_conversation_info) {
per_conversation_info = wmem_new(wmem_file_scope(), vnc_conversation_t);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SERVER_VERSION;
per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_INVALID;
per_conversation_info->tight_enabled = FALSE;
conversation_add_proto_data(conversation, proto_vnc, per_conversation_info);
}
/* Make entries in Protocol column and Info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "VNC");
/* First, clear the info column */
col_clear(pinfo->cinfo, COL_INFO);
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, ENC_NA);
vnc_tree = proto_item_add_subtree(ti, ett_vnc);
/* Dissect any remaining session startup messages */
ret = vnc_startup_messages(tvb, pinfo, offset, vnc_tree,
per_conversation_info);
vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
vnc_set_depth(pinfo, vnc_depth);
if (ret) {
return tvb_captured_length(tvb); /* We're in a "startup" state; Cannot yet do "normal" processing */
}
if(value_is_in_range(vnc_tcp_range, pinfo->destport) || per_conversation_info->server_port == pinfo->destport) {
vnc_client_to_server(tvb, pinfo, &offset, vnc_tree);
}
else {
vnc_server_to_client(tvb, pinfo, &offset, vnc_tree);
}
return tvb_captured_length(tvb);
}
/* Returns the new offset after processing the 4-byte vendor string */
static gint
process_vendor(proto_tree *tree, gint hfindex, tvbuff_t *tvb, gint offset)
{
const guint8 *vendor;
proto_item *ti;
if (tree) {
ti = proto_tree_add_item_ret_string(tree, hfindex, tvb, offset, 4, ENC_ASCII|ENC_NA, wmem_packet_scope(), &vendor);
if(g_ascii_strcasecmp(vendor, "STDV") == 0)
proto_item_append_text(ti, " (Standard VNC vendor)");
else if(g_ascii_strcasecmp(vendor, "TRDV") == 0)
proto_item_append_text(ti, " (Tridia VNC vendor)");
else if(g_ascii_strcasecmp(vendor, "TGHT") == 0)
proto_item_append_text(ti, " (Tight VNC vendor)");
}
offset += 4;
return offset;
}
/* Returns the new offset after processing the specified number of capabilities */
static gint
process_tight_capabilities(proto_tree *tree,
gint type_index, gint vendor_index, gint name_index,
tvbuff_t *tvb, gint offset, const gint num_capabilities)
{
gint i;
/* See vnc_unixsrc/include/rfbproto.h:rfbCapabilityInfo */
for (i = 0; i < num_capabilities; i++) {
proto_tree_add_item(tree, type_index, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
offset = process_vendor(tree, vendor_index, tvb, offset);
proto_tree_add_item(tree, name_index, tvb, offset, 8, ENC_ASCII|ENC_NA);
offset += 8;
}
return offset;
}
/* Returns true if this looks like a client or server version packet: 12 bytes, in the format "RFB xxx.yyy\n" .
* Will check for the 12 bytes exact length, the 'RFB ' string and that it ends with a '\n'.
* The exact 'xxx.yyy' is checked later, by trying to convert it to a double using g_ascii_strtod.
* pinfo and tree are NULL when using this function to check the heuristics for dissection. If we're
* checking the heuristics, we don't need to add expert_info, we just reject that packet as not
* being a VNC packet.
*/
static gboolean
vnc_is_client_or_server_version_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if(tvb_captured_length(tvb) != 12) {
return FALSE;
}
if(tvb_strncaseeql(tvb, 0, "RFB ", 4) != 0) {
return FALSE;
}
/* 0x2e = '.' 0xa = '\n' */
if (tvb_get_guint8(tvb, 7) != 0x2e) {
return FALSE;
}
if (tvb_get_guint8(tvb,11) != 0xa) {
if (tvb_get_guint8(tvb,11) == 0) {
/* Per bug 5469, It appears that any VNC clients using gtk-vnc before [1] was
* fixed will exhibit the described protocol violation that prevents wireshark
* from dissecting the session.
*
* [1] http://git.gnome.org/browse/gtk-vnc/commit/?id=bc9e2b19167686dd381a0508af1a5113675d08a2
*/
if ((pinfo != NULL) && (tree != NULL)) {
proto_tree_add_expert(tree, pinfo, &ei_vnc_possible_gtk_vnc_bug, tvb, -1, 0);
}
return TRUE;
}
return FALSE;
}
return TRUE;
}
static gboolean test_vnc_protocol(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
{
conversation_t *conversation;
if (vnc_is_client_or_server_version_message(tvb, NULL, NULL)) {
conversation = conversation_new(pinfo->num, &pinfo->src,
&pinfo->dst, pinfo->ptype,
pinfo->srcport,
pinfo->destport, 0);
conversation_set_dissector(conversation, vnc_handle);
dissect_vnc(tvb, pinfo, tree, data);
return TRUE;
}
return FALSE;
}
/* Returns true if additional session startup messages follow */
static gboolean
vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset,
proto_tree *tree, vnc_conversation_t
*per_conversation_info)
{
guint8 num_security_types;
guint32 desktop_name_len, auth_result, text_len, auth_code;
vnc_packet_t *per_packet_info;
gint num_tunnel_types;
gint num_auth_types;
proto_item* auth_item;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
if(!per_packet_info) {
per_packet_info = wmem_new(wmem_file_scope(), vnc_packet_t);
per_packet_info->state = per_conversation_info->vnc_next_state;
per_packet_info->preferred_encoding = -1;
p_add_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0, per_packet_info);
}
/* Packet dissection follows */
switch(per_packet_info->state) {
case VNC_SESSION_STATE_SERVER_VERSION :
if (!vnc_is_client_or_server_version_message(tvb, pinfo, tree))
return TRUE; /* we still hope to get a SERVER_VERSION message some day. Do not proceed yet */
proto_tree_add_item(tree, hf_vnc_server_proto_ver, tvb, 4,
7, ENC_ASCII|ENC_NA);
per_conversation_info->server_proto_ver =
g_ascii_strtod((char *)tvb_get_string_enc(wmem_packet_scope(), tvb, 4, 7, ENC_ASCII), NULL);
per_conversation_info->server_port = pinfo->srcport;
col_add_fstr(pinfo->cinfo, COL_INFO,
"Server protocol version: %s",
tvb_format_text(tvb, 4, 7));
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_VERSION;
break;
case VNC_SESSION_STATE_CLIENT_VERSION :
if (!vnc_is_client_or_server_version_message(tvb, pinfo, tree))
return TRUE; /* we still hope to get a CLIENT_VERSION message some day. Do not proceed yet */
proto_tree_add_item(tree, hf_vnc_client_proto_ver, tvb,
4, 7, ENC_ASCII|ENC_NA);
per_conversation_info->client_proto_ver =
g_ascii_strtod((char *)tvb_get_string_enc(wmem_packet_scope(), tvb, 4, 7, ENC_ASCII), NULL);
col_add_fstr(pinfo->cinfo, COL_INFO,
"Client protocol version: %s",
tvb_format_text(tvb, 4, 7));
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY;
break;
case VNC_SESSION_STATE_SECURITY :
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 highest version it supports. */
if(per_conversation_info->client_proto_ver >= 3.007) {
num_security_types = tvb_get_guint8(tvb, offset);
if (tree) {
proto_tree_add_item(tree,
hf_vnc_num_security_types,
tvb, offset, 1, ENC_BIG_ENDIAN);
for(offset = 1; offset <= num_security_types; offset++){
proto_tree_add_item(tree,
hf_vnc_security_type, tvb,
offset, 1, ENC_BIG_ENDIAN);
}
}
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_TYPES;
} else {
/* Version < 3.007: The server decides the
* authentication type for us to use */
proto_tree_add_item(tree, hf_vnc_server_security_type,
tvb, offset, 4, ENC_BIG_ENDIAN);
/* The cast below is possible since in older versions of the protocol the only possible values are 0,1,2 */
per_conversation_info->security_type_selected = (guint8)tvb_get_ntohl(tvb, offset);
switch(per_conversation_info->security_type_selected) {
case VNC_SECURITY_TYPE_INVALID:
/* TODO: In this case (INVALID) the connection has failed */
/* and there should be an error string describing the error */
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_TYPES;
break;
case VNC_SECURITY_TYPE_NONE:
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
break;
case VNC_SECURITY_TYPE_VNC:
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
break;
case VNC_SECURITY_TYPE_ARD:
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_ARD_AUTHENTICATION_CHALLENGE;
break;
default:
/* Security type not supported by this dissector */
break;
}
}
break;
case VNC_SESSION_STATE_SECURITY_TYPES :
col_set_str(pinfo->cinfo, COL_INFO, "Authentication type selected by client");
proto_tree_add_item(tree, hf_vnc_client_security_type, tvb, offset, 1, ENC_BIG_ENDIAN);
per_conversation_info->security_type_selected =
tvb_get_guint8(tvb, offset);
switch(per_conversation_info->security_type_selected) {
case VNC_SECURITY_TYPE_NONE :
if(per_conversation_info->client_proto_ver >= 3.008)
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_SECURITY_RESULT;
else
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_CLIENT_INIT;
break;
case VNC_SECURITY_TYPE_VNC :
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
break;
case VNC_SECURITY_TYPE_TIGHT :
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES;
per_conversation_info->tight_enabled = TRUE;
break;
case VNC_SECURITY_TYPE_ARD:
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_ARD_AUTHENTICATION_CHALLENGE;
break;
default :
/* Security type not supported by this dissector */
break;
}
break;
case VNC_SESSION_STATE_TIGHT_TUNNELING_CAPABILITIES :
{
gint i;
col_set_str(pinfo->cinfo, COL_INFO, "TightVNC tunneling capabilities supported");
proto_tree_add_item(tree, hf_vnc_tight_num_tunnel_types, tvb, offset, 4, ENC_BIG_ENDIAN);
num_tunnel_types = tvb_get_ntohl(tvb, offset);
offset += 4;
for(i = 0; i < num_tunnel_types; i++) {
/* TightVNC and Xvnc don't support any tunnel capabilities yet, but each capability
* is 16 bytes, so skip them.
*/
proto_tree_add_item(tree, hf_vnc_tight_tunnel_type, tvb, offset, 16, ENC_BIG_ENDIAN);
offset += 16;
}
if (num_tunnel_types == 0)
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES;
else
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY;
break;
}
case VNC_SESSION_STATE_TIGHT_TUNNEL_TYPE_REPLY:
/* Neither TightVNC nor Xvnc implement this; they just have a placeholder that emits an error
* message and closes the connection (xserver/hw/vnc/auth.c:rfbProcessClientTunnelingType).
* We should actually never get here...
*/
break;
case VNC_SESSION_STATE_TIGHT_AUTH_CAPABILITIES:
col_set_str(pinfo->cinfo, COL_INFO, "TightVNC authentication capabilities supported");
proto_tree_add_item(tree, hf_vnc_tight_num_auth_types, tvb, offset, 4, ENC_BIG_ENDIAN);
num_auth_types = tvb_get_ntohl(tvb, offset);
offset += 4;
{
int i;
const guint8 *vendor, *signature;
for (i = 0; i < 1; i++) {
auth_code = tvb_get_ntohl(tvb, offset);
auth_item = proto_tree_add_item(tree, hf_vnc_tight_auth_code, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
vendor = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 4, ENC_ASCII);
process_vendor(tree, hf_vnc_tight_server_vendor, tvb, offset);
offset += 4;
proto_tree_add_item_ret_string(tree, hf_vnc_tight_signature, tvb, offset, 8, ENC_ASCII|ENC_NA, wmem_packet_scope(), &signature);
offset += 8;
switch(auth_code) {
case VNC_SECURITY_TYPE_NONE:
if ((g_ascii_strcasecmp(vendor, "STDV") != 0) || (g_ascii_strcasecmp(signature, "NOAUTH__") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
case VNC_SECURITY_TYPE_VNC:
if ((g_ascii_strcasecmp(vendor, "STDV") != 0) || (g_ascii_strcasecmp(signature, "VNCAUTH_") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
case VNC_SECURITY_TYPE_VENCRYPT:
if ((g_ascii_strcasecmp(vendor, "VENC") != 0) || (g_ascii_strcasecmp(signature, "VENCRYPT") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
case VNC_SECURITY_TYPE_GTK_VNC_SASL:
if ((g_ascii_strcasecmp(vendor, "GTKV") != 0) || (g_ascii_strcasecmp(signature, "SASL____") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
case VNC_TIGHT_AUTH_TGHT_ULGNAUTH:
if ((g_ascii_strcasecmp(vendor, "TGHT") != 0) || (g_ascii_strcasecmp(signature, "ULGNAUTH") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
case VNC_TIGHT_AUTH_TGHT_XTRNAUTH:
if ((g_ascii_strcasecmp(vendor, "TGHT") != 0) || (g_ascii_strcasecmp(signature, "XTRNAUTH") != 0)) {
expert_add_info(pinfo, auth_item, &ei_vnc_auth_code_mismatch);
}
break;
default:
expert_add_info(pinfo, auth_item, &ei_vnc_unknown_tight_vnc_auth);
break;
}
}
}
if (num_auth_types == 0)
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
else
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY;
break;
case VNC_SESSION_STATE_TIGHT_AUTH_TYPE_REPLY:
col_set_str(pinfo->cinfo, COL_INFO, "TightVNC authentication type selected by client");
auth_code = tvb_get_ntohl(tvb, offset);
auth_item = proto_tree_add_item(tree, hf_vnc_tight_auth_code, tvb, offset, 4, ENC_BIG_ENDIAN);
switch(auth_code) {
case VNC_SECURITY_TYPE_NONE:
per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_NONE;
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
break;
case VNC_SECURITY_TYPE_VNC:
per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_VNC;
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
break;
case VNC_SECURITY_TYPE_GTK_VNC_SASL:
per_conversation_info->security_type_selected = VNC_SECURITY_TYPE_GTK_VNC_SASL;
/* TODO: dissection not implemented yet */
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
break;
case VNC_TIGHT_AUTH_TGHT_ULGNAUTH:
per_conversation_info->security_type_selected = VNC_TIGHT_AUTH_TGHT_ULGNAUTH;
/* TODO: dissection not implemented yet */
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
break;
case VNC_TIGHT_AUTH_TGHT_XTRNAUTH:
per_conversation_info->security_type_selected = VNC_TIGHT_AUTH_TGHT_XTRNAUTH;
/* TODO: dissection not implemented yet */
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
break;
default:
expert_add_info(pinfo, auth_item, &ei_vnc_unknown_tight_vnc_auth);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3;
break;
}
break;
case VNC_SESSION_STATE_TIGHT_UNKNOWN_PACKET3 :
col_set_str(pinfo->cinfo, COL_INFO, "Unknown packet (TightVNC)");
proto_tree_add_expert(tree, pinfo, &ei_vnc_unknown_tight, tvb, offset, -1);
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE;
break;
case VNC_SESSION_STATE_VNC_AUTHENTICATION_CHALLENGE :
col_set_str(pinfo->cinfo, COL_INFO, "Authentication challenge from server");
proto_tree_add_item(tree, hf_vnc_auth_challenge, tvb,
offset, 16, ENC_NA);
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE;
break;
case VNC_SESSION_STATE_VNC_AUTHENTICATION_RESPONSE :
col_set_str(pinfo->cinfo, COL_INFO, "Authentication response from client");
proto_tree_add_item(tree, hf_vnc_auth_response, tvb,
offset, 16, ENC_NA);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_RESULT;
break;
case VNC_SESSION_STATE_ARD_AUTHENTICATION_CHALLENGE :
{
gint key_len;
col_set_str(pinfo->cinfo, COL_INFO, "ARD authentication challenge");
proto_tree_add_item(tree, hf_vnc_ard_auth_generator, tvb,
offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_ard_auth_key_len, tvb,
offset + 2, 2, ENC_BIG_ENDIAN);
key_len = tvb_get_ntohs(tvb, offset + 2);
offset += 4;
proto_tree_add_item(tree, hf_vnc_ard_auth_modulus, tvb,
offset, key_len, ENC_NA);
proto_tree_add_item(tree, hf_vnc_ard_auth_server_key, tvb,
offset + key_len, key_len, ENC_NA);
per_conversation_info->ard_key_length = key_len;
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_ARD_AUTHENTICATION_RESPONSE;
}
break;
case VNC_SESSION_STATE_ARD_AUTHENTICATION_RESPONSE :
col_set_str(pinfo->cinfo, COL_INFO, "ARD authentication response");
proto_tree_add_item(tree, hf_vnc_ard_auth_credentials, tvb,
offset, 128, ENC_NA);
proto_tree_add_item(tree, hf_vnc_ard_auth_client_key, tvb,
offset + 128, per_conversation_info->ard_key_length, ENC_NA);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SECURITY_RESULT;
break;
case VNC_SESSION_STATE_SECURITY_RESULT :
col_set_str(pinfo->cinfo, COL_INFO, "Authentication result");
proto_tree_add_item(tree, hf_vnc_auth_result, tvb, offset,
4, ENC_BIG_ENDIAN);
auth_result = tvb_get_ntohl(tvb, offset);
offset += 4;
switch(auth_result) {
case 0 : /* OK */
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_CLIENT_INIT;
break;
case 1 : /* Failed */
if(per_conversation_info->client_proto_ver >= 3.008) {
text_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_vnc_auth_error_length, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(tree, hf_vnc_auth_error, tvb,
offset, text_len, ENC_ASCII|ENC_NA);
}
return TRUE; /* All versions: Do not continue
processing VNC packets as connection
will be closed after this packet. */
break;
}
break;
case VNC_SESSION_STATE_CLIENT_INIT :
col_set_str(pinfo->cinfo, COL_INFO, "Share desktop flag");
proto_tree_add_item(tree, hf_vnc_share_desktop_flag, tvb,
offset, 1, ENC_BIG_ENDIAN);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_SERVER_INIT;
break;
case VNC_SESSION_STATE_SERVER_INIT :
col_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer parameters");
proto_tree_add_item(tree, hf_vnc_width, tvb, offset, 2,
ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(tree, hf_vnc_height, tvb, offset, 2,
ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(tree, hf_vnc_server_bits_per_pixel,
tvb, offset, 1, ENC_BIG_ENDIAN);
vnc_bytes_per_pixel = tvb_get_guint8(tvb, offset)/8;
vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_depth, tvb, offset,
1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_big_endian_flag,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_true_color_flag,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_red_max,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(tree, hf_vnc_server_green_max,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(tree, hf_vnc_server_blue_max,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(tree, hf_vnc_server_red_shift,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_green_shift,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_server_blue_shift,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(tree, hf_vnc_padding,
tvb, offset, 3, ENC_NA);
offset += 3; /* Skip over 3 bytes of padding */
if(tvb_reported_length_remaining(tvb, offset) > 4) {
/* Sometimes the desktop name & length is skipped */
proto_tree_add_item(tree, hf_vnc_desktop_name_len,
tvb, offset, 4, ENC_BIG_ENDIAN);
desktop_name_len = tvb_get_ntohl(tvb, offset);
offset += 4;
proto_tree_add_item(tree, hf_vnc_desktop_name,
tvb, offset, desktop_name_len,
ENC_ASCII|ENC_NA);
}
if(per_conversation_info->tight_enabled == TRUE)
per_conversation_info->vnc_next_state =
VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS;
else
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_NORMAL_TRAFFIC;
break;
case VNC_SESSION_STATE_TIGHT_INTERACTION_CAPS :
col_set_str(pinfo->cinfo, COL_INFO, "TightVNC Interaction Capabilities");
proto_tree_add_item(tree, hf_vnc_num_server_message_types,
tvb, offset, 2, ENC_BIG_ENDIAN);
per_conversation_info->num_server_message_types = tvb_get_ntohs(tvb, offset);
offset += 2;
proto_tree_add_item(tree, hf_vnc_num_client_message_types,
tvb, offset, 2, ENC_BIG_ENDIAN);
per_conversation_info->num_client_message_types = tvb_get_ntohs(tvb, offset);
offset += 2;
proto_tree_add_item(tree, hf_vnc_num_encoding_types,
tvb, offset, 2, ENC_BIG_ENDIAN);
per_conversation_info->num_encoding_types = tvb_get_ntohs(tvb, offset);
offset += 2;
proto_tree_add_item(tree, hf_vnc_padding, tvb, offset, 2, ENC_NA);
offset += 2;
offset = process_tight_capabilities(tree,
hf_vnc_tight_server_message_type,
hf_vnc_tight_server_vendor,
hf_vnc_tight_server_name,
tvb, offset, per_conversation_info->num_server_message_types);
offset = process_tight_capabilities(tree,
hf_vnc_tight_client_message_type,
hf_vnc_tight_client_vendor,
hf_vnc_tight_client_name,
tvb, offset, per_conversation_info->num_client_message_types);
process_tight_capabilities(tree,
hf_vnc_tight_encoding_type,
hf_vnc_tight_encoding_vendor,
hf_vnc_tight_encoding_name,
tvb, offset, per_conversation_info->num_encoding_types);
per_conversation_info->vnc_next_state = VNC_SESSION_STATE_NORMAL_TRAFFIC;
break;
case VNC_SESSION_STATE_NORMAL_TRAFFIC :
return FALSE;
}
return TRUE;
}
static void
vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint8 message_type;
proto_item *ti;
proto_tree *vnc_client_message_type_tree;
message_type = tvb_get_guint8(tvb, *offset);
ti = proto_tree_add_item(tree, hf_vnc_client_message_type, tvb,
*offset, 1, ENC_BIG_ENDIAN);
vnc_client_message_type_tree =
proto_item_add_subtree(ti, ett_vnc_client_message_type);
*offset += 1;
switch(message_type) {
case VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT :
vnc_client_set_pixel_format(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_SET_ENCODINGS :
vnc_client_set_encodings(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_FRAMEBUF_UPDATE_REQ :
vnc_client_framebuffer_update_request(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_KEY_EVENT :
vnc_client_key_event(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_POINTER_EVENT:
vnc_client_pointer_event(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_CLIENT_CUT_TEXT :
vnc_client_cut_text(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_MIRRORLINK :
vnc_mirrorlink(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
case VNC_CLIENT_MESSAGE_TYPE_ENABLE_CONTINUOUS_UPDATES :
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Client Enable Continuous Updates");
*offset += 9;
break;
case VNC_CLIENT_MESSAGE_TYPE_FENCE :
vnc_fence(tvb, pinfo, offset,
vnc_client_message_type_tree);
break;
default :
col_append_sep_fstr(pinfo->cinfo, COL_INFO, "; ",
"Unknown client message type (%u)",
message_type);
break;
}
}
static void
vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
gint start_offset;
guint8 message_type;
gint bytes_needed = 0;
proto_item *ti;
proto_tree *vnc_server_message_type_tree;
again:
start_offset = *offset;
message_type = tvb_get_guint8(tvb, *offset);
ti = proto_tree_add_item(tree, hf_vnc_server_message_type, tvb,
*offset, 1, ENC_BIG_ENDIAN);
vnc_server_message_type_tree =
proto_item_add_subtree(ti, ett_vnc_server_message_type);
*offset += 1;
switch(message_type) {
case VNC_SERVER_MESSAGE_TYPE_FRAMEBUFFER_UPDATE :
bytes_needed =
vnc_server_framebuffer_update(tvb, pinfo, offset,
vnc_server_message_type_tree);
break;
case VNC_SERVER_MESSAGE_TYPE_SET_COLORMAP_ENTRIES :
bytes_needed = vnc_server_set_colormap_entries(tvb, pinfo, offset, vnc_server_message_type_tree);
break;
case VNC_SERVER_MESSAGE_TYPE_RING_BELL :
vnc_server_ring_bell(tvb, pinfo, offset,
vnc_server_message_type_tree);
break;
case VNC_SERVER_MESSAGE_TYPE_CUT_TEXT :
bytes_needed = vnc_server_cut_text(tvb, pinfo, offset,
vnc_server_message_type_tree);
break;
case VNC_SERVER_MESSAGE_TYPE_MIRRORLINK :
bytes_needed = vnc_mirrorlink(tvb, pinfo, offset,
vnc_server_message_type_tree);
break;
case VNC_SERVER_MESSAGE_TYPE_END_CONTINUOUS_UPDATES :
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server End Continuous Updates");
*offset += 1;
break;
case VNC_SERVER_MESSAGE_TYPE_FENCE :
bytes_needed = vnc_fence(tvb, pinfo, offset,
vnc_server_message_type_tree);
break;
default :
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ",
"Unknown server message type");
*offset = tvb_reported_length(tvb); /* Swallow the rest of the segment */
break;
}
if(bytes_needed > 0 && vnc_preference_desegment && pinfo->can_desegment) {
proto_tree_add_expert(vnc_server_message_type_tree, pinfo, &ei_vnc_reassemble, tvb, start_offset, -1);
pinfo->desegment_offset = start_offset;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return;
}
if ((unsigned)*offset < tvb_reported_length(tvb)) {
goto again;
}
}
static void
vnc_client_set_pixel_format(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_INFO, "Client set pixel format");
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, ENC_NA);
*offset += 3; /* Skip over 3 bytes of padding */
proto_tree_add_item(tree, hf_vnc_client_bits_per_pixel, tvb, *offset,
1, ENC_BIG_ENDIAN);
vnc_bytes_per_pixel = tvb_get_guint8(tvb, *offset)/8;
vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_depth, tvb, *offset,
1, ENC_BIG_ENDIAN);
vnc_depth = tvb_get_guint8(tvb, *offset);
vnc_set_depth(pinfo, vnc_depth);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_big_endian_flag, tvb, *offset,
1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_true_color_flag, tvb, *offset,
1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_red_max, tvb, *offset,
2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_client_green_max, tvb, *offset,
2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_client_blue_max, tvb, *offset,
2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_client_red_shift, tvb, *offset,
1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_green_shift, tvb, *offset,
1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_client_blue_shift, tvb, *offset,
1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, ENC_NA);
*offset += 3; /* Skip over 3 bytes of padding */
}
static void
vnc_client_set_encodings(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint16 number_of_encodings;
guint counter;
vnc_packet_t *per_packet_info;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
col_set_str(pinfo->cinfo, COL_INFO, "Client set encodings");
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, ENC_NA);
*offset += 1; /* Skip over 1 byte of padding */
number_of_encodings = tvb_get_ntohs(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_encoding_num, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
per_packet_info->preferred_encoding = -1;
for(counter = 0; counter < number_of_encodings; counter++) {
proto_tree_add_item(tree,
hf_vnc_client_set_encodings_encoding_type,
tvb, *offset, 4, ENC_BIG_ENDIAN);
/* Remember the first real encoding as the preferred encoding,
* per xserver/hw/vnc/rfbserver.c:rfbProcessClientNormalMessage().
* Otherwise, use RAW as the preferred encoding.
*/
if (per_packet_info->preferred_encoding == -1) {
int encoding;
encoding = tvb_get_ntohl(tvb, *offset);
switch(encoding) {
case VNC_ENCODING_TYPE_RAW:
case VNC_ENCODING_TYPE_RRE:
case VNC_ENCODING_TYPE_CORRE:
case VNC_ENCODING_TYPE_HEXTILE:
case VNC_ENCODING_TYPE_ZLIB:
case VNC_ENCODING_TYPE_TIGHT:
per_packet_info->preferred_encoding = encoding;
break;
}
}
*offset += 4;
}
if (per_packet_info->preferred_encoding == -1)
per_packet_info->preferred_encoding = VNC_ENCODING_TYPE_RAW;
}
static void
vnc_client_framebuffer_update_request(tvbuff_t *tvb, packet_info *pinfo,
gint *offset, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_INFO, "Client framebuffer update request");
proto_tree_add_item(tree, hf_vnc_update_req_incremental,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_update_req_x_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_update_req_y_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_update_req_width, tvb,
*offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_update_req_height, tvb,
*offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
}
static void
vnc_client_key_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_INFO, "Client key event");
proto_tree_add_item(tree, hf_vnc_key_down, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 2, ENC_NA);
*offset += 2; /* Skip over 2 bytes of padding */
proto_tree_add_item(tree, hf_vnc_key, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
}
static void
vnc_client_pointer_event(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_INFO, "Client pointer event");
proto_tree_add_item(tree, hf_vnc_button_1_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_2_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_3_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_4_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_5_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_6_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_7_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_vnc_button_8_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_pointer_x_pos, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_pointer_y_pos, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
}
static void
vnc_client_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint32 text_len;
col_set_str(pinfo->cinfo, COL_INFO, "Client cut text");
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, ENC_NA);
*offset += 3; /* Skip over 3 bytes of padding */
text_len = tvb_get_ntohl(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_client_cut_text_len, tvb, *offset, 4,
ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_client_cut_text, tvb, *offset,
text_len, ENC_ASCII|ENC_NA);
*offset += text_len;
}
static guint
vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint ii;
guint num_rects;
guint16 width, height;
guint bytes_needed = 0;
guint32 encoding_type;
proto_item *ti, *ti_x, *ti_y, *ti_width, *ti_height;
proto_tree *vnc_rect_tree, *vnc_encoding_type_tree;
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server framebuffer update");
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, ENC_NA);
*offset += 1;
num_rects = tvb_get_ntohs(tvb, *offset);
ti = proto_tree_add_item(tree, hf_vnc_rectangle_num, tvb, *offset, 2, ENC_BIG_ENDIAN);
/* In some cases, TIGHT encoding ignores the "number of rectangles" field; */
/* VNC_ENCODING_TYPE_LAST_RECT is used to indicate the end of the rectangle list. */
/* (It appears that TIGHT encoding uses 0xFFFF for the num_rects field when the */
/* field is not being used). For now: we'll assume that a value 0f 0xFFFF means */
/* that the field is not being used. */
if (num_rects == 0xFFFF) {
proto_item_append_text(ti, " [TIGHT encoding assumed (field is not used)]");
}
if ((num_rects != 0xFFFF) && (num_rects > 5000)) {
expert_add_info_format(pinfo, ti, &ei_vnc_too_many_rectangles,
"Too many rectangles (%d), aborting dissection", num_rects);
return(0);
}
*offset += 2;
for(ii = 0; ii < num_rects; ii++) {
if (ii > 5000) {
expert_add_info_format(pinfo, ti, &ei_vnc_too_many_rectangles,
"Too many rectangles (%d), aborting dissection", ii);
return(0);
}
VNC_BYTES_NEEDED(12);
vnc_rect_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 12,
ett_vnc_rect, NULL, "Rectangle #%d", ii+1);
ti_x = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_x_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
ti_y = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_y_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
ti_width = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
width = tvb_get_ntohs(tvb, *offset);
*offset += 2;
ti_height = proto_tree_add_item(vnc_rect_tree, hf_vnc_fb_update_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
height = tvb_get_ntohs(tvb, *offset);
*offset += 2;
ti = proto_tree_add_item(vnc_rect_tree,
hf_vnc_fb_update_encoding_type,
tvb, *offset, 4, ENC_BIG_ENDIAN);
encoding_type = tvb_get_ntohl(tvb, *offset);
*offset += 4;
if (encoding_type == VNC_ENCODING_TYPE_LAST_RECT)
break; /* exit the loop */
vnc_encoding_type_tree =
proto_item_add_subtree(ti, ett_vnc_encoding_type);
switch(encoding_type) {
case VNC_ENCODING_TYPE_RAW:
bytes_needed = vnc_raw_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_COPY_RECT:
bytes_needed =
vnc_copyrect_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_RRE:
bytes_needed =
vnc_rre_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_HEXTILE:
bytes_needed =
vnc_hextile_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_RLE:
bytes_needed =
vnc_zrle_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_TIGHT:
bytes_needed =
vnc_tight_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_RICH_CURSOR:
case VNC_ENCODING_TYPE_X_CURSOR:
proto_item_append_text (ti_x, " (hotspot X)");
proto_item_append_text (ti_y, " (hotspot Y)");
proto_item_append_text (ti_width, " (cursor width)");
proto_item_append_text (ti_height, " (cursor height)");
if (encoding_type == VNC_ENCODING_TYPE_RICH_CURSOR)
bytes_needed = vnc_rich_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
else
bytes_needed = vnc_x_cursor_encoding(tvb, pinfo, offset, vnc_encoding_type_tree, width, height);
break;
case VNC_ENCODING_TYPE_POINTER_POS:
proto_item_append_text (ti_x, " (pointer X)");
proto_item_append_text (ti_y, " (pointer Y)");
proto_item_append_text (ti_width, " (unused)");
proto_item_append_text (ti_height, " (unused)");
bytes_needed = 0;
break;
case VNC_ENCODING_TYPE_DESKTOP_SIZE:
/* There is no payload for this message type */
bytes_needed = 0;
break;
case VNC_ENCODING_TYPE_EXTENDED_DESK_SIZE :
bytes_needed = vnc_extended_desktop_size(tvb, offset, vnc_encoding_type_tree);
break;
case VNC_ENCODING_TYPE_KEYBOARD_LED_STATE :
/* There is no payload for this message type */
bytes_needed = 0;
break;
case VNC_ENCODING_TYPE_SUPPORTED_MESSAGES :
bytes_needed = vnc_supported_messages(tvb, offset,
vnc_encoding_type_tree,
width);
break;
case VNC_ENCODING_TYPE_SUPPORTED_ENCODINGS :
bytes_needed = vnc_supported_encodings(tvb, offset,
vnc_encoding_type_tree,
width, height);
break;
case VNC_ENCODING_TYPE_SERVER_IDENTITY :
bytes_needed = vnc_server_identity(tvb, offset,
vnc_encoding_type_tree,
width);
break;
case VNC_ENCODING_TYPE_CONTEXT_INFORMATION :
bytes_needed = vnc_context_information(tvb, offset,
vnc_encoding_type_tree);
break;
case VNC_ENCODING_TYPE_SLRLE :
bytes_needed = vnc_slrle_encoding(tvb, pinfo, offset,
vnc_encoding_type_tree,
height);
break;
case VNC_ENCODING_TYPE_H264 :
bytes_needed = vnc_h264_encoding(tvb, offset,
vnc_encoding_type_tree);
break;
}
/* Check if the routines above requested more bytes to
* be desegmented. */
if(bytes_needed > 0)
return bytes_needed;
}
return 0;
}
static guint32
vnc_extended_desktop_size(tvbuff_t *tvb, gint *offset, proto_tree *tree)
{
guint8 i, num_of_screens;
proto_tree *screen_tree;
num_of_screens = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_desktop_screen_num, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, ENC_NA);
VNC_BYTES_NEEDED((guint32)(3 + (num_of_screens * 16)));
*offset += 3;
for(i = 0; i < num_of_screens; i++) {
screen_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 16, ett_vnc_desktop_screen, NULL, "Screen #%u", i+1);
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_id, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_x, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_y, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_width, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_height, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(screen_tree, hf_vnc_desktop_screen_flags, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
}
return 0;
}
static guint
vnc_raw_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height)
{
guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
guint length;
length = width * height * bytes_per_pixel;
VNC_BYTES_NEEDED(length);
proto_tree_add_item(tree, hf_vnc_raw_pixel_data, tvb, *offset,
length, ENC_NA);
*offset += length;
return 0; /* bytes_needed */
}
static guint
vnc_copyrect_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
{
proto_tree_add_item(tree, hf_vnc_copyrect_src_x_pos, tvb, *offset,
2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_copyrect_src_y_pos, tvb, *offset,
2, ENC_BIG_ENDIAN);
*offset += 2;
return 0; /* bytes_needed */
}
static guint
vnc_rre_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
{
guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
guint32 num_subrects, i;
guint bytes_needed;
proto_item *ti;
proto_tree *subrect_tree;
VNC_BYTES_NEEDED(4);
ti = proto_tree_add_item(tree, hf_vnc_rre_num_subrects, tvb, *offset,
4, ENC_BIG_ENDIAN);
num_subrects = tvb_get_ntohl(tvb, *offset);
*offset += 4;
if (num_subrects > 10000) {
expert_add_info_format(pinfo, ti, &ei_vnc_too_many_sub_rectangles,
"Too many sub-rectangles (%d), aborting dissection", num_subrects);
return(0);
}
*offset += 2;
VNC_BYTES_NEEDED(bytes_per_pixel);
proto_tree_add_item(tree, hf_vnc_rre_bg_pixel, tvb, *offset,
bytes_per_pixel, ENC_NA);
*offset += bytes_per_pixel;
/* We know we need (at least) all these bytes, so ask for them now
* (instead of a few at a time...).
*/
bytes_needed = bytes_per_pixel + 8;
VNC_BYTES_NEEDED(bytes_needed * num_subrects);
for(i = 0; i < num_subrects; i++) {
subrect_tree = proto_tree_add_subtree_format(tree, tvb, *offset, bytes_per_pixel +
8, ett_vnc_rre_subrect, NULL, "Subrectangle #%d", i+1);
proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_pixel,
tvb, *offset, bytes_per_pixel, ENC_NA);
*offset += bytes_per_pixel;
proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_x_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_y_pos,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(subrect_tree, hf_vnc_rre_subrect_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
}
return 0; /* bytes_needed */
}
static guint
vnc_hextile_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height)
{
guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
guint8 i, subencoding_mask, num_subrects, subrect_len, tile_height, tile_width;
guint32 raw_length;
proto_tree *tile_tree, *subencoding_mask_tree, *subrect_tree, *num_subrects_tree;
proto_item *ti;
guint16 current_height = 0, current_width;
while(current_height != height) {
if (current_height + 16 > height)
tile_height = height - current_height;
else
tile_height = 16;
current_height += tile_height;
current_width = 0;
while(current_width != width) {
if (current_width + 16 > width)
tile_width = width - current_width;
else
tile_width = 16;
current_width += tile_width;
VNC_BYTES_NEEDED(1);
subencoding_mask = tvb_get_guint8(tvb, *offset);
tile_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 1, ett_vnc_hextile_tile, NULL,
"Tile {%d:%d}, sub encoding mask %u", current_width, current_height, subencoding_mask);
ti = proto_tree_add_item(tile_tree, hf_vnc_hextile_subencoding_mask, tvb,
*offset, 1, ENC_BIG_ENDIAN);
subencoding_mask_tree =
proto_item_add_subtree(ti, ett_vnc_hextile_subencoding_mask);
proto_tree_add_item(subencoding_mask_tree,
hf_vnc_hextile_raw, tvb, *offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(subencoding_mask_tree,
hf_vnc_hextile_bg, tvb, *offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(subencoding_mask_tree,
hf_vnc_hextile_fg, tvb, *offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(subencoding_mask_tree,
hf_vnc_hextile_anysubrects, tvb, *offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(subencoding_mask_tree,
hf_vnc_hextile_subrectscolored, tvb, *offset, 1,
ENC_BIG_ENDIAN);
*offset += 1;
if(subencoding_mask & 0x1) { /* Raw */
raw_length = tile_width * tile_height * bytes_per_pixel;
proto_tree_add_item(tile_tree, hf_vnc_hextile_raw_value, tvb,
*offset, raw_length, ENC_NA);
VNC_BYTES_NEEDED(raw_length);
*offset += raw_length;
} else {
if(subencoding_mask & 0x2) { /* Background Specified */
VNC_BYTES_NEEDED(bytes_per_pixel);
proto_tree_add_item(tile_tree, hf_vnc_hextile_bg_value,
tvb, *offset, bytes_per_pixel,
ENC_NA);
*offset += bytes_per_pixel;
}
if(subencoding_mask & 0x4) { /* Foreground Specified */
VNC_BYTES_NEEDED(bytes_per_pixel);
proto_tree_add_item(tile_tree, hf_vnc_hextile_fg_value,
tvb, *offset, bytes_per_pixel,
ENC_NA);
*offset += bytes_per_pixel;
}
if(subencoding_mask & 0x8) { /* Any Subrects */
VNC_BYTES_NEEDED(3); /* 1 byte for number of subrects field, +2 at least for 1 subrect */
ti = proto_tree_add_item(tile_tree,
hf_vnc_hextile_num_subrects,
tvb, *offset, 1,
ENC_BIG_ENDIAN);
num_subrects = tvb_get_guint8(tvb, *offset);
*offset += 1;
if(subencoding_mask & 0x10)
subrect_len = bytes_per_pixel + 2;
else
subrect_len = 2;
VNC_BYTES_NEEDED((guint)(subrect_len * num_subrects));
num_subrects_tree =
proto_item_add_subtree(ti, ett_vnc_hextile_num_subrects);
for(i = 0; i < num_subrects; i++) {
subrect_tree = proto_tree_add_subtree_format(num_subrects_tree, tvb,
*offset, subrect_len, ett_vnc_hextile_subrect, NULL,
"Subrectangle #%d", i+1);
if(subencoding_mask & 0x10) {
/* Subrects Colored */
proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_pixel_value, tvb, *offset, bytes_per_pixel, ENC_NA);
*offset += bytes_per_pixel;
}
proto_tree_add_item(subrect_tree,
hf_vnc_hextile_subrect_x_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_y_pos, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_width, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(subrect_tree, hf_vnc_hextile_subrect_height, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
}
}
}
}
}
return 0; /* bytes_needed */
}
static guint
vnc_supported_messages(tvbuff_t *tvb, gint *offset, proto_tree *tree,
const guint16 width)
{
VNC_BYTES_NEEDED(width);
if (width >= 64) {
proto_tree_add_item(tree,
hf_vnc_supported_messages_client2server,
tvb, *offset, 32, ENC_NA);
*offset += 32;
proto_tree_add_item(tree,
hf_vnc_supported_messages_server2client,
tvb, *offset, 32, ENC_NA);
*offset += 32;
*offset += width - 64;
} else {
*offset += width;
}
return 0; /* bytes_needed */
}
static guint
vnc_supported_encodings(tvbuff_t *tvb, gint *offset, proto_tree *tree,
const guint16 width, const guint16 height)
{
guint16 i = width;
proto_tree_add_uint(tree, hf_vnc_num_supported_encodings, tvb, *offset, 0, height);
VNC_BYTES_NEEDED(width);
for (; i >= 4; i -= 4) {
proto_tree_add_item(tree, hf_vnc_supported_encodings,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
}
*offset += i;
return 0; /* bytes_needed */
}
static guint
vnc_server_identity(tvbuff_t *tvb, gint *offset, proto_tree *tree,
const guint16 width)
{
VNC_BYTES_NEEDED(width);
proto_tree_add_item(tree, hf_vnc_server_identity,
tvb, *offset, width, ENC_ASCII|ENC_NA);
*offset += width;
return 0; /* bytes_needed */
}
static guint
vnc_mirrorlink(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint8 type;
guint16 length;
guint16 num, i;
gint end;
proto_tree *sub_tree;
/* Header */
VNC_BYTES_NEEDED(3);
type = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_mirrorlink_type,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
length = tvb_get_ntohs(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_mirrorlink_length,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
col_add_fstr(pinfo->cinfo, COL_INFO, "MirrorLink (%s)",
val_to_str_const(type, vnc_mirrorlink_types_vs,
"Unknown"));
/* Payload */
end = *offset + length;
switch(type) {
case VNC_ML_EXT_BYE_BYE :
break;
case VNC_ML_EXT_SERVER_DISPLAY_CONFIGURATION :
VNC_BYTES_NEEDED(12);
proto_tree_add_item(tree, hf_vnc_mirrorlink_version_major,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_mirrorlink_version_minor,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree,
hf_vnc_mirrorlink_framebuffer_configuration,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pixel_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pixel_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pixel_format,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case VNC_ML_EXT_CLIENT_DISPLAY_CONFIGURATION :
VNC_BYTES_NEEDED(14);
proto_tree_add_item(tree, hf_vnc_mirrorlink_version_major,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_mirrorlink_version_minor,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree,
hf_vnc_mirrorlink_framebuffer_configuration,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pixel_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pixel_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_display_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_display_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_display_distance,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
case VNC_ML_EXT_SERVER_EVENT_CONFIGURATION :
case VNC_ML_EXT_CLIENT_EVENT_CONFIGURATION :
VNC_BYTES_NEEDED(28);
proto_tree_add_item(tree, hf_vnc_mirrorlink_keyboard_language,
tvb, *offset, 2, ENC_ASCII|ENC_NA);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_keyboard_country,
tvb, *offset, 2, ENC_ASCII|ENC_NA);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_ui_language,
tvb, *offset, 2, ENC_ASCII|ENC_NA);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_ui_country,
tvb, *offset, 2, ENC_ASCII|ENC_NA);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_knob_keys,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_device_keys,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_multimedia_keys,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_key_related,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_pointer_related,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case VNC_ML_EXT_EVENT_MAPPING :
case VNC_ML_EXT_EVENT_MAPPING_REQUEST :
VNC_BYTES_NEEDED(8);
proto_tree_add_item(tree,
hf_vnc_mirrorlink_key_symbol_value_client,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree,
hf_vnc_mirrorlink_key_symbol_value_server,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case VNC_ML_EXT_KEY_EVENT_LISTING :
VNC_BYTES_NEEDED(4);
proto_tree_add_item(tree, hf_vnc_mirrorlink_key_configuration,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
num = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_mirrorlink_key_num_events,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(tree, hf_vnc_mirrorlink_key_event_counter,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
VNC_BYTES_NEEDED((guint)(4 * num));
sub_tree = proto_tree_add_subtree(tree, tvb, *offset, 4 * num,
ett_vnc_key_events, NULL, "Key Event List");
for (; num > 0; num--) {
proto_tree_add_item(sub_tree,
hf_vnc_mirrorlink_key_symbol_value,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4 ;
}
break;
case VNC_ML_EXT_KEY_EVENT_LISTING_REQUEST :
VNC_BYTES_NEEDED(4);
proto_tree_add_item(tree,
hf_vnc_mirrorlink_key_request_configuration,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case VNC_ML_EXT_VIRTUAL_KEYBOARD :
VNC_BYTES_NEEDED(16);
proto_tree_add_item(tree,
hf_vnc_mirrorlink_keyboard_configuration,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_cursor_x,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_cursor_y,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_x,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_y,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
case VNC_ML_EXT_VIRTUAL_KEYBOARD_REQUEST :
VNC_BYTES_NEEDED(4);
proto_tree_add_item(tree,
hf_vnc_mirrorlink_keyboard_request_configuration,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
case VNC_ML_EXT_DEVICE_STATUS :
case VNC_ML_EXT_DEVICE_STATUS_REQUEST :
VNC_BYTES_NEEDED(4);
proto_tree_add_item(tree, hf_vnc_mirrorlink_device_status,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
break;
/*
case VNC_ML_EXT_CONTENT_ATTESTATION :
break;
case VNC_ML_EXT_CONTENT_ATTESTATION_REQUEST :
break;
*/
case VNC_ML_EXT_FB_BLOCKING_NOTIFICATION :
VNC_BYTES_NEEDED(14);
proto_tree_add_item(tree, hf_vnc_mirrorlink_fb_block_x,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_fb_block_y,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_fb_block_width,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_fb_block_height,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_mirrorlink_app_id,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_fb_block_reason,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
case VNC_ML_EXT_AUDIO_BLOCKING_NOTIFICATION :
VNC_BYTES_NEEDED(6);
proto_tree_add_item(tree, hf_vnc_mirrorlink_app_id,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_mirrorlink_audio_block_reason,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
case VNC_ML_EXT_TOUCH_EVENT :
VNC_BYTES_NEEDED(1);
num = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_mirrorlink_touch_num_events,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
VNC_BYTES_NEEDED((guint)(6 * num));
/*sub_tree = proto_item_add_subtree(tree, ett_vnc_touch_events);*/
for (i = 0; i < num; i++) {
sub_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 6,
ett_vnc_touch_events, NULL, "Touch Event #%d", i + 1);
proto_tree_add_item(sub_tree, hf_vnc_mirrorlink_touch_x,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(sub_tree, hf_vnc_mirrorlink_touch_y,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(sub_tree,
hf_vnc_mirrorlink_touch_id,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
proto_tree_add_item(sub_tree,
hf_vnc_mirrorlink_touch_pressure,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
}
break;
case VNC_ML_EXT_FB_ALTERNATIVE_TEXT :
VNC_BYTES_NEEDED(6);
proto_tree_add_item(tree, hf_vnc_mirrorlink_app_id,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
num = tvb_get_ntohs(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_length,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
VNC_BYTES_NEEDED(num);
proto_tree_add_item(tree, hf_vnc_mirrorlink_text,
tvb, *offset, num, ENC_ASCII|ENC_NA);
*offset += num;
break;
case VNC_ML_EXT_FB_ALTERNATIVE_TEXT_REQUEST :
VNC_BYTES_NEEDED(2);
proto_tree_add_item(tree, hf_vnc_mirrorlink_text_max_length,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
break;
}
if (end > *offset) {
length = end - *offset;
VNC_BYTES_NEEDED(length);
proto_tree_add_item(tree, hf_vnc_mirrorlink_unknown,
tvb, *offset, length, ENC_NA);
*offset = end;
}
return 0; /* bytes_needed */
}
static guint
vnc_fence(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint payload_length;
VNC_BYTES_NEEDED(8);
payload_length = tvb_get_guint8(tvb, *offset+7);
VNC_BYTES_NEEDED((8+payload_length));
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Fence");
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 3, ENC_NA);
*offset += 3; /* skip padding */
proto_tree_add_bitmask(tree, tvb, *offset, hf_vnc_fence_flags,
ett_vnc_fence_flags, vnc_fence_flags, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_fence_payload_length,
tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
if (payload_length > 0) {
proto_tree_add_item(tree, hf_vnc_fence_payload,
tvb, *offset, payload_length, ENC_NA);
*offset += payload_length;
}
return 0;
}
static guint
vnc_context_information(tvbuff_t *tvb, gint *offset, proto_tree *tree)
{
VNC_BYTES_NEEDED(20);
proto_tree_add_item(tree, hf_vnc_context_information_app_id,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_context_information_app_trust_level,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree,
hf_vnc_context_information_content_trust_level,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(tree, hf_vnc_context_information_app_category,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_context_information_content_category,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_context_information_content_rules,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
return 0; /* bytes_needed */
}
static guint
vnc_slrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 height)
{
guint8 depth = vnc_get_depth(pinfo);
guint8 depth_mod = depth % 8;
guint8 bytes_per_run;
guint16 num_runs, i;
guint length;
proto_tree *sub_tree;
if (depth_mod <= 4)
bytes_per_run = ( 8 - depth_mod + depth) / 8;
else
bytes_per_run = (16 - depth_mod + depth) / 8;
for (i = 0; i < height; i++) {
VNC_BYTES_NEEDED(2);
num_runs = tvb_get_ntohs(tvb, *offset);
length = num_runs * bytes_per_run;
sub_tree = proto_tree_add_subtree_format(tree, tvb, *offset, 2 + length,
ett_vnc_slrle_subline, NULL, "Scanline #%d", i+1);
proto_tree_add_item(sub_tree, hf_vnc_slrle_run_num,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
VNC_BYTES_NEEDED(length);
proto_tree_add_item(sub_tree, hf_vnc_slrle_run_data,
tvb, *offset, length, ENC_NA);
*offset += length;
}
return 0; /* bytes_needed */
}
static guint
vnc_h264_encoding(tvbuff_t *tvb, gint *offset, proto_tree *tree)
{
guint32 nbytes;
VNC_BYTES_NEEDED(16);
/*0 == P-Frame; 1 == B-Frame; 2 == I-Frame*/
proto_tree_add_item(tree, hf_vnc_h264_slice_type,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
nbytes = tvb_get_ntohl(tvb, *offset);
proto_tree_add_item(tree, hf_vnc_h264_nbytes,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_h264_width,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
proto_tree_add_item(tree, hf_vnc_h264_height,
tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset += 4;
VNC_BYTES_NEEDED(nbytes);
proto_tree_add_item(tree, hf_vnc_h264_data,
tvb, *offset, nbytes, ENC_NA);
*offset += nbytes;
return 0; /* bytes_needed */
}
#ifdef HAVE_ZLIB
static guint
vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height)
#else
static guint
vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
#endif
{
guint32 data_len;
#ifdef HAVE_ZLIB
guint8 palette_size;
guint8 bytes_per_cpixel = vnc_get_bytes_per_pixel(pinfo);
gint uncomp_offset = 0;
guint length;
gint subencoding_type;
tvbuff_t *uncomp_tvb;
proto_tree *zrle_subencoding_tree;
proto_item *ti;
#endif
VNC_BYTES_NEEDED(4);
proto_tree_add_item(tree, hf_vnc_zrle_len, tvb, *offset,
4, ENC_BIG_ENDIAN);
data_len = tvb_get_ntohl(tvb, *offset);
*offset += 4;
VNC_BYTES_NEEDED(data_len);
proto_tree_add_item(tree, hf_vnc_zrle_data, tvb, *offset,
data_len, ENC_NA);
#ifdef HAVE_ZLIB
uncomp_tvb = tvb_child_uncompress(tvb, tvb, *offset, data_len);
if(uncomp_tvb != NULL) {
add_new_data_source(pinfo, uncomp_tvb,
"Uncompressed ZRLE data");
ti = proto_tree_add_item(tree, hf_vnc_zrle_subencoding,
uncomp_tvb, uncomp_offset, 1, ENC_BIG_ENDIAN);
zrle_subencoding_tree =
proto_item_add_subtree(ti, ett_vnc_zrle_subencoding);
proto_tree_add_item(zrle_subencoding_tree, hf_vnc_zrle_rle,
uncomp_tvb, uncomp_offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(zrle_subencoding_tree,
hf_vnc_zrle_palette_size, uncomp_tvb,
uncomp_offset, 1, ENC_BIG_ENDIAN);
subencoding_type = tvb_get_guint8(uncomp_tvb, uncomp_offset);
palette_size = subencoding_type & 0x7F;
uncomp_offset += 1;
if(subencoding_type == 0) { /* Raw */
length = width * height * bytes_per_cpixel;
VNC_BYTES_NEEDED(length);
/* XXX - not working yet! */
proto_tree_add_item(zrle_subencoding_tree,
hf_vnc_zrle_raw, uncomp_tvb,
uncomp_offset, length, ENC_NA);
} else if(subencoding_type >= 130 && subencoding_type <= 255) {
length = palette_size * bytes_per_cpixel;
VNC_BYTES_NEEDED(length);
proto_tree_add_item(zrle_subencoding_tree,
hf_vnc_zrle_palette, uncomp_tvb,
uncomp_offset, length, ENC_NA);
/* XXX - Not complete! */
}
} else {
proto_tree_add_expert(tree, pinfo, &ei_vnc_zrle_failed, tvb, *offset, data_len);
}
#endif /* HAVE_ZLIB */
*offset += data_len;
return 0; /* bytes_needed */
}
static guint
read_compact_len(tvbuff_t *tvb, gint *offset, gint *length, gint *value_length)
{
gint b;
VNC_BYTES_NEEDED(1);
*value_length = 0;
b = tvb_get_guint8(tvb, *offset);
*offset += 1;
*value_length += 1;
*length = b & 0x7f;
if ((b & 0x80) != 0) {
VNC_BYTES_NEEDED(1);
b = tvb_get_guint8(tvb, *offset);
*offset += 1;
*value_length += 1;
*length |= (b & 0x7f) << 7;
if ((b & 0x80) != 0) {
VNC_BYTES_NEEDED (1);
b = tvb_get_guint8(tvb, *offset);
*offset += 1;
*value_length += 1;
*length |= (b & 0xff) << 14;
}
}
return 0;
}
static guint
process_compact_length_and_image_data(tvbuff_t *tvb, gint *offset, proto_tree *tree)
{
guint bytes_needed;
guint length, value_length;
bytes_needed = read_compact_len (tvb, offset, &length, &value_length);
if (bytes_needed != 0)
return bytes_needed;
proto_tree_add_uint(tree, hf_vnc_tight_image_len, tvb, *offset - value_length, value_length, length);
VNC_BYTES_NEEDED(length);
proto_tree_add_item(tree, hf_vnc_tight_image_data, tvb, *offset, length, ENC_NA);
*offset += length;
return 0; /* bytes_needed */
}
static guint
process_tight_rect_filter_palette(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, gint *bits_per_pixel)
{
vnc_packet_t *per_packet_info;
gint num_colors;
guint palette_bytes;
/* See TightVNC's vnc_unixsrc/vncviewer/tight.c:InitFilterPaletteBPP() */
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
VNC_BYTES_NEEDED(1);
proto_tree_add_item(tree, hf_vnc_tight_palette_num_colors, tvb, *offset, 1, ENC_BIG_ENDIAN);
num_colors = tvb_get_guint8(tvb, *offset);
*offset += 1;
num_colors++;
if (num_colors < 2)
return 0;
if (per_packet_info->depth == 24)
palette_bytes = num_colors * 3;
else
palette_bytes = num_colors * per_packet_info->depth / 8;
VNC_BYTES_NEEDED(palette_bytes);
proto_tree_add_item(tree, hf_vnc_tight_palette_data, tvb, *offset, palette_bytes, ENC_NA);
*offset += palette_bytes;
/* This is the number of bits per pixel *in the image data*, not the actual client depth */
if (num_colors == 2)
*bits_per_pixel = 1;
else
*bits_per_pixel = 8;
return 0;
}
static guint
vnc_tight_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width _U_, const guint16 height _U_)
{
vnc_packet_t *per_packet_info;
guint8 comp_ctl;
proto_item *compression_type_ti;
gint bit_offset;
gint bytes_needed = -1;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
/* See xserver/hw/vnc/rfbproto.h and grep for "Tight Encoding." for the following layout */
VNC_BYTES_NEEDED(1);
/* least significant bits 0-3 are "reset compression stream N" */
bit_offset = *offset * 8;
proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream0, tvb, bit_offset + 7, 1, ENC_BIG_ENDIAN);
proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream1, tvb, bit_offset + 6, 1, ENC_BIG_ENDIAN);
proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream2, tvb, bit_offset + 5, 1, ENC_BIG_ENDIAN);
proto_tree_add_bits_item(tree, hf_vnc_tight_reset_stream3, tvb, bit_offset + 4, 1, ENC_BIG_ENDIAN);
/* most significant bits 4-7 are "compression type" */
compression_type_ti = proto_tree_add_bits_item(tree, hf_vnc_tight_rect_type, tvb, bit_offset + 0, 4, ENC_BIG_ENDIAN);
comp_ctl = tvb_get_guint8(tvb, *offset);
*offset += 1;
comp_ctl >>= 4; /* skip over the "reset compression" bits from above */
/* compression format */
if (comp_ctl == TIGHT_RECT_FILL) {
/* "fill" encoding (solid rectangle) */
proto_item_append_text(compression_type_ti, " (fill encoding - solid rectangle)");
if (per_packet_info->depth == 24) {
VNC_BYTES_NEEDED(3);
proto_tree_add_item(tree, hf_vnc_tight_fill_color, tvb, *offset, 3, ENC_NA);
*offset += 3;
} else {
VNC_BYTES_NEEDED(per_packet_info->bytes_per_pixel);
proto_tree_add_item(tree, hf_vnc_tight_fill_color, tvb, *offset, per_packet_info->bytes_per_pixel, ENC_NA);
*offset += per_packet_info->bytes_per_pixel;
}
bytes_needed = 0;
} else if (comp_ctl == TIGHT_RECT_JPEG) {
/* jpeg encoding */
proto_item_append_text(compression_type_ti, " (JPEG encoding)");
bytes_needed = process_compact_length_and_image_data(tvb, offset, tree);
if (bytes_needed != 0)
return bytes_needed;
} else if (comp_ctl > TIGHT_RECT_MAX_VALUE) {
/* invalid encoding */
expert_add_info(pinfo, compression_type_ti, &ei_vnc_invalid_encoding);
} else {
guint row_size;
gint bits_per_pixel;
/* basic encoding */
proto_item_append_text(compression_type_ti, " (basic encoding)");
proto_tree_add_bits_item(tree, hf_vnc_tight_filter_flag, tvb, bit_offset + 1, 1, ENC_BIG_ENDIAN);
bits_per_pixel = per_packet_info->depth;
if ((comp_ctl & TIGHT_RECT_EXPLICIT_FILTER_FLAG) != 0) {
guint8 filter_id;
/* explicit filter */
VNC_BYTES_NEEDED(1);
proto_tree_add_item(tree, hf_vnc_tight_filter_id, tvb, *offset, 1, ENC_BIG_ENDIAN);
filter_id = tvb_get_guint8(tvb, *offset);
*offset += 1;
switch (filter_id) {
case TIGHT_RECT_FILTER_COPY:
/* nothing to do */
break;
case TIGHT_RECT_FILTER_PALETTE:
bytes_needed = process_tight_rect_filter_palette(tvb, pinfo, offset, tree, &bits_per_pixel);
if (bytes_needed != 0)
return bytes_needed;
break;
case TIGHT_RECT_FILTER_GRADIENT:
/* nothing to do */
break;
}
} else {
/* this is the same case as TIGHT_RECT_FILTER_COPY, so there's nothing special to do */
}
row_size = ((guint) width * bits_per_pixel + 7) / 8;
if (row_size * height < TIGHT_MIN_BYTES_TO_COMPRESS) {
guint num_bytes;
/* The data is not compressed; just skip over it */
num_bytes = row_size * height;
VNC_BYTES_NEEDED(num_bytes);
proto_tree_add_item(tree, hf_vnc_tight_image_data, tvb, *offset, num_bytes, ENC_NA);
*offset += num_bytes;
bytes_needed = 0;
} else {
/* The data is compressed; read its length and data */
bytes_needed = process_compact_length_and_image_data(tvb, offset, tree);
if (bytes_needed != 0)
return bytes_needed;
}
}
DISSECTOR_ASSERT(bytes_needed != -1);
return bytes_needed;
}
static guint
decode_cursor(tvbuff_t *tvb, gint *offset, proto_tree *tree,
guint pixels_bytes, guint mask_bytes)
{
guint total_bytes;
total_bytes = pixels_bytes + mask_bytes;
VNC_BYTES_NEEDED (total_bytes);
proto_tree_add_item(tree, hf_vnc_cursor_encoding_pixels, tvb, *offset,
pixels_bytes, ENC_NA);
*offset += pixels_bytes;
proto_tree_add_item(tree, hf_vnc_cursor_encoding_bitmask, tvb, *offset,
mask_bytes, ENC_NA);
*offset += mask_bytes;
return 0; /* bytes_needed */
}
static guint
vnc_rich_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height)
{
guint8 bytes_per_pixel = vnc_get_bytes_per_pixel(pinfo);
guint pixels_bytes, mask_bytes;
pixels_bytes = width * height * bytes_per_pixel;
mask_bytes = ((width + 7) / 8) * height;
return decode_cursor(tvb, offset, tree,
pixels_bytes, mask_bytes);
}
static guint
vnc_x_cursor_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset,
proto_tree *tree, const guint16 width, const guint16 height)
{
gint bitmap_row_bytes = (width + 7) / 8;
gint mask_bytes = bitmap_row_bytes * height;
VNC_BYTES_NEEDED (6);
proto_tree_add_item(tree, hf_vnc_cursor_x_fore_back, tvb, *offset, 6, ENC_NA);
*offset += 6;
/* The length of the pixel data is the same as the length of the mask data (X cursors are strictly black/white) */
return decode_cursor(tvb, offset, tree,
mask_bytes, mask_bytes);
}
static guint
vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint16 number_of_colors;
guint counter, bytes_needed;
proto_item *ti;
proto_tree *vnc_colormap_num_groups, *vnc_colormap_color_group;
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server set colormap entries");
number_of_colors = tvb_get_ntohs(tvb, 4);
VNC_BYTES_NEEDED(3);
proto_tree_add_item(tree, hf_vnc_padding, tvb, *offset, 1, ENC_NA);
*offset += 1; /* Skip over 1 byte of padding */
proto_tree_add_item(tree, hf_vnc_colormap_first_color,
tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
/* XXX - this is 3 bytes into the tvb, but number_of_colors is set off
* of 4 bytes in... Bug???
*/
ti = proto_tree_add_item(tree, hf_vnc_colormap_num_colors, tvb,
*offset, 2, ENC_BIG_ENDIAN);
if (number_of_colors > 10000) {
expert_add_info_format(pinfo, ti, &ei_vnc_too_many_colors,"Too many colors (%d), aborting dissection",
number_of_colors);
return(0);
}
bytes_needed = (number_of_colors * 6) + 5;
VNC_BYTES_NEEDED(bytes_needed);
*offset += 2;
ti = proto_tree_add_item(tree, hf_vnc_color_groups, tvb,
*offset, number_of_colors * 6, ENC_NA);
vnc_colormap_num_groups =
proto_item_add_subtree(ti, ett_vnc_colormap_num_groups);
for(counter = 0; counter < number_of_colors; counter++) {
vnc_colormap_color_group = proto_tree_add_subtree_format(vnc_colormap_num_groups, tvb,
*offset, 6, ett_vnc_colormap_color_group, NULL,
"Color group #%d", counter+1);
proto_tree_add_item(vnc_colormap_color_group,
hf_vnc_colormap_red, tvb,
*offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(vnc_colormap_color_group,
hf_vnc_colormap_green, tvb,
*offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
proto_tree_add_item(vnc_colormap_color_group,
hf_vnc_colormap_blue, tvb,
*offset, 2, ENC_BIG_ENDIAN);
*offset += 2;
}
return 0;
}
static void
vnc_server_ring_bell(tvbuff_t *tvb _U_, packet_info *pinfo, gint *offset _U_,
proto_tree *tree _U_)
{
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server ring bell on client");
/* This message type has no payload... */
}
static guint
vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset,
proto_tree *tree)
{
guint32 text_len;
proto_item *pi;
col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server cut text");
text_len = tvb_get_ntohl(tvb, *offset);
pi = proto_tree_add_item(tree, hf_vnc_server_cut_text_len, tvb, *offset, 4,
ENC_BIG_ENDIAN);
*offset += 4;
if (text_len > 100000) {
expert_add_info_format(pinfo, pi, &ei_vnc_too_many_cut_text,
"Too much cut text (%d), aborting dissection", text_len);
return(0);
}
VNC_BYTES_NEEDED(text_len);
proto_tree_add_item(tree, hf_vnc_server_cut_text, tvb, *offset,
text_len, ENC_ASCII|ENC_NA);
*offset += text_len;
return *offset;
}
static void
vnc_set_bytes_per_pixel(packet_info *pinfo, const guint8 bytes_per_pixel)
{
vnc_packet_t *per_packet_info;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
per_packet_info->bytes_per_pixel = bytes_per_pixel;
}
static void
vnc_set_depth(packet_info *pinfo, const guint8 depth)
{
vnc_packet_t *per_packet_info;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
per_packet_info->depth = depth;
}
static guint8
vnc_get_bytes_per_pixel(packet_info *pinfo)
{
vnc_packet_t *per_packet_info;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
return per_packet_info->bytes_per_pixel;
}
static guint8
vnc_get_depth(packet_info *pinfo)
{
vnc_packet_t *per_packet_info;
per_packet_info = (vnc_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_vnc, 0);
/* Our calling function should have set the packet's proto data already */
DISSECTOR_ASSERT(per_packet_info != NULL);
return per_packet_info->depth;
}
/* Preference callbacks */
static void
apply_vnc_prefs(void) {
pref_t *vnc_ports = prefs_find_preference(prefs_find_module("vnc"), "tcp.port");
vnc_tcp_range = range_copy(*vnc_ports->varp.range);
}
/* Register the protocol with Wireshark */
void
proto_register_vnc(void)
{
module_t *vnc_module; /* To handle our preferences */
expert_module_t* expert_vnc;
/* 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(vnc_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(vnc_security_types_vs), 0x0,
"Security type mandated by the server", HFILL }
},
{ &hf_vnc_client_security_type,
{ "Security type selected", "vnc.client_security_type",
FT_UINT8, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
"Security type selected by the client", HFILL }
},
{ &hf_vnc_tight_num_tunnel_types,
{ "Number of supported tunnel types", "vnc.num_tunnel_types",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of tunnel types for TightVNC", HFILL }
},
{ &hf_vnc_tight_tunnel_type,
{ "Tunnel type", "vnc.tunnel_type",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Tunnel type specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_num_auth_types,
{ "Number of supported authentication types", "vnc.num_auth_types",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Authentication types specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_auth_code,
{ "Authentication code", "vnc.tight_auth_code",
FT_UINT32, BASE_DEC, VALS(vnc_security_types_vs), 0x0,
"Authentication code specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_server_message_type,
{ "Server message type (TightVNC)", "vnc.tight_server_message_type",
FT_INT32, BASE_DEC, NULL, 0x0,
"Server message type specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_server_vendor,
{ "Server vendor code", "vnc.server_vendor",
FT_STRING, BASE_NONE, NULL, 0x0,
"Server vendor code specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_signature,
{ "Signature", "vnc.signature",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_vnc_tight_server_name,
{ "Server name", "vnc.server_name",
FT_STRING, BASE_NONE, NULL, 0x0,
"Server name specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_client_message_type,
{ "Client message type (TightVNC)", "vnc.tight_client_message_type",
FT_INT32, BASE_DEC, NULL, 0x0,
"Client message type specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_client_vendor,
{ "Client vendor code", "vnc.client_vendor",
FT_STRING, BASE_NONE, NULL, 0x0,
"Client vendor code specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_client_name,
{ "Client name", "vnc.client_name",
FT_STRING, BASE_NONE, NULL, 0x0,
"Client name specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_encoding_type,
{ "Encoding type", "vnc.encoding_type",
FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
"Encoding type specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_encoding_vendor,
{ "Encoding vendor code", "vnc.encoding_vendor",
FT_STRING, BASE_NONE, NULL, 0x0,
"Encoding vendor code specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_encoding_name,
{ "Encoding name", "vnc.encoding_name",
FT_STRING, BASE_NONE, NULL, 0x0,
"Encoding name specific to TightVNC", HFILL }
},
{ &hf_vnc_tight_reset_stream0,
{ "Reset compression stream 0", "vnc.tight_reset_stream0",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Tight compression, reset compression stream 0", HFILL }
},
{ &hf_vnc_tight_reset_stream1,
{ "Reset compression stream 1", "vnc.tight_reset_stream1",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Tight compression, reset compression stream 1", HFILL }
},
{ &hf_vnc_tight_reset_stream2,
{ "Reset compression stream 2", "vnc.tight_reset_stream2",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Tight compression, reset compression stream 2", HFILL }
},
{ &hf_vnc_tight_reset_stream3,
{ "Reset compression stream 3", "vnc.tight_reset_stream3",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Tight compression, reset compression stream 3", HFILL }
},
{ &hf_vnc_tight_rect_type,
{ "Rectangle type", "vnc.tight_rect_type",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Tight compression, rectangle type", HFILL }
},
{ &hf_vnc_tight_image_len,
{ "Image data length", "vnc.tight_image_len",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Tight compression, length of image data", HFILL }
},
{ &hf_vnc_tight_image_data,
{ "Image data", "vnc.tight_image_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Tight compression, image data", HFILL }
},
{ &hf_vnc_tight_fill_color,
{ "Fill color (RGB)", "vnc.tight_fill_color",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Tight compression, fill color for solid rectangle", HFILL }
},
{ &hf_vnc_tight_filter_flag,
{ "Explicit filter flag", "vnc.tight_filter_flag",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Tight compression, explicit filter flag", HFILL }
},
{ &hf_vnc_tight_filter_id,
{ "Filter ID", "vnc.tight_filter_id",
FT_UINT8, BASE_DEC, VALS(tight_filter_ids_vs), 0x0,
"Tight compression, filter ID", HFILL }
},
{ &hf_vnc_tight_palette_num_colors,
{ "Number of colors in palette", "vnc.tight_palette_num_colors",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Tight compression, number of colors in rectangle's palette", HFILL }
},
{ &hf_vnc_tight_palette_data,
{ "Palette data", "vnc.tight_palette_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Tight compression, palette data for a rectangle", HFILL }
},
{ &hf_vnc_auth_challenge,
{ "Authentication challenge", "vnc.auth_challenge",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Random authentication challenge from server to client", HFILL }
},
{ &hf_vnc_auth_response,
{ "Authentication response", "vnc.auth_response",
FT_BYTES, 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_BOOLEAN, 32, TFS(&auth_result_tfs), 0x1,
NULL, HFILL }
},
{ &hf_vnc_auth_error_length,
{ "Length of authentication error", "vnc.auth_error_len",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Authentication error length (present only if the authentication result is fail", 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_ard_auth_generator,
{ "Generator", "vnc.ard_auth_generator",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Generator for Diffie-Hellman key exchange", HFILL }
},
{ &hf_vnc_ard_auth_key_len,
{ "Key length", "vnc.ard_auth_key_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Diffie-Hellman key length", HFILL }
},
{ &hf_vnc_ard_auth_modulus,
{ "Prime modulus", "vnc.ard_auth_modulus",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Prime modulus for Diffie-Hellman key exchange", HFILL }
},
{ &hf_vnc_ard_auth_server_key,
{ "Server public key", "vnc.ard_auth_server_key",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Server's public Diffie-Hellman key", HFILL }
},
{ &hf_vnc_ard_auth_credentials,
{ "Encrypted credentials", "vnc.ard_auth_credentials",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Encrypted client username and password", HFILL }
},
{ &hf_vnc_ard_auth_client_key,
{ "Client public key", "vnc.ard_auth_client_key",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Client's public Diffie-Hellman key", HFILL }
},
{ &hf_vnc_share_desktop_flag,
{ "Share desktop flag", "vnc.share_desktop_flag",
FT_BOOLEAN, BASE_NONE, NULL, 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.height",
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_screen_num,
{ "Number of screens", "vnc.screen_num",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_vnc_desktop_screen_id,
{ "Screen ID", "vnc.screen_id",
FT_UINT32, BASE_DEC, NULL, 0x0,
"ID of screen", HFILL }
},
{ &hf_vnc_desktop_screen_x,
{ "Screen X position", "vnc.screen_x",
FT_UINT16, BASE_DEC, NULL, 0x0,
"X coordinate of screen", HFILL }
},
{ &hf_vnc_desktop_screen_y,
{ "Screen Y position", "vnc.screen_y",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Y coordinate of screen", HFILL }
},
{ &hf_vnc_desktop_screen_width,
{ "Screen width", "vnc.screen_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Width of screen", HFILL }
},
{ &hf_vnc_desktop_screen_height,
{ "Screen height", "vnc.screen_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Height of screen", HFILL }
},
{ &hf_vnc_desktop_screen_flags,
{ "Screen flags", "vnc.screen_flags",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Flags of screen", 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_num_server_message_types,
{ "Server message types", "vnc.num_server_message_types",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Unknown", HFILL } /* XXX - Needs description */
},
{ &hf_vnc_num_client_message_types,
{ "Client message types", "vnc.num_client_message_types",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Unknown", HFILL } /* XXX - Needs description */
},
{ &hf_vnc_num_encoding_types,
{ "Encoding types", "vnc.num_encoding_types",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Unknown", HFILL } /* XXX - Needs description */
},
{ &hf_vnc_client_message_type,
{ "Client Message Type", "vnc.client_message_type",
FT_UINT8, BASE_DEC, VALS(vnc_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_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
"Specifies whether the key is being pressed or not", HFILL }
},
{ &hf_vnc_key,
{ "Key", "vnc.key",
FT_UINT32, BASE_HEX | BASE_EXT_STRING, &x11_keysym_vals_source_ext, 0x0, /* keysym_vals_source_exr is from packet-x11.c */
"Key being pressed/depressed", HFILL }
},
/* Client Pointer Event */
{ &hf_vnc_button_1_pos,
{ "Mouse button #1 position", "vnc.button_1_pos",
FT_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_BOOLEAN, 8, TFS(&button_mask_tfs), 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_encoding_num,
{ "Number of encodings", "vnc.client_set_encodings_num",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Number of encodings used to send pixel data from server to client", 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_NONE, 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(vnc_server_message_types_vs), 0x0,
"Message type from server", HFILL }
},
{ &hf_vnc_rectangle_num,
{ "Number of rectangles", "vnc.fb_update_num_rects",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Number of rectangles of this server framebuffer update", HFILL }
},
{ &hf_vnc_fb_update_x_pos,
{ "X position", "vnc.fb_update_x_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"X position of this server framebuffer update", HFILL }
},
{ &hf_vnc_fb_update_y_pos,
{ "Y position", "vnc.fb_update_y_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Y position of this server framebuffer update", HFILL }
},
{ &hf_vnc_fb_update_width,
{ "Width", "vnc.fb_update_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Width of this server framebuffer update", HFILL }
},
{ &hf_vnc_fb_update_height,
{ "Height", "vnc.fb_update_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Height of this server framebuffer update", HFILL }
},
{ &hf_vnc_fb_update_encoding_type,
{ "Encoding type", "vnc.fb_update_encoding_type",
FT_INT32, BASE_DEC, VALS(encoding_types_vs), 0x0,
"Encoding type of this server framebuffer update", HFILL }
},
/* Cursor encoding */
{ &hf_vnc_cursor_x_fore_back,
{ "X Cursor foreground RGB / background RGB", "vnc.cursor_x_fore_back",
FT_BYTES, BASE_NONE, NULL, 0x0,
"RGB values for the X cursor's foreground and background", HFILL }
},
{ &hf_vnc_cursor_encoding_pixels,
{ "Cursor encoding pixels", "vnc.cursor_encoding_pixels",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Cursor encoding pixel data", HFILL }
},
{ &hf_vnc_cursor_encoding_bitmask,
{ "Cursor encoding bitmask", "vnc.cursor_encoding_bitmask",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Cursor encoding pixel bitmask", HFILL }
},
/* Raw Encoding */
{ &hf_vnc_raw_pixel_data,
{ "Pixel data", "vnc.raw_pixel_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Raw pixel data.", HFILL }
},
/* CopyRect Encoding*/
{ &hf_vnc_copyrect_src_x_pos,
{ "Source x position", "vnc.copyrect_src_x_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"X position of the rectangle to copy from", HFILL }
},
{ &hf_vnc_copyrect_src_y_pos,
{ "Source y position", "vnc.copyrect_src_y_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Y position of the rectangle to copy from", HFILL }
},
/* RRE Encoding */
{ &hf_vnc_rre_num_subrects,
{ "Number of subrectangles", "vnc.rre_num_subrects",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of subrectangles contained in this encoding type", HFILL }
},
{ &hf_vnc_rre_bg_pixel,
{ "Background pixel value", "vnc.rre_bg_pixel",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
{ &hf_vnc_rre_subrect_pixel,
{ "Pixel value", "vnc.rre_subrect_pixel",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Subrectangle pixel value", HFILL }
},
{ &hf_vnc_rre_subrect_x_pos,
{ "X position", "vnc.rre_subrect_x_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Position of this subrectangle on the x axis", HFILL }
},
{ &hf_vnc_rre_subrect_y_pos,
{ "Y position", "vnc.rre_subrect_y_pos",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Position of this subrectangle on the y axis", HFILL }
},
{ &hf_vnc_rre_subrect_width,
{ "Width", "vnc.rre_subrect_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Width of this subrectangle", HFILL }
},
{ &hf_vnc_rre_subrect_height,
{ "Height", "vnc.rre_subrect_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Height of this subrectangle", HFILL }
},
/* Hextile Encoding */
{ &hf_vnc_hextile_subencoding_mask,
{ "Subencoding type", "vnc.hextile_subencoding",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Hextile subencoding type.", HFILL }
},
{ &hf_vnc_hextile_raw,
{ "Raw", "vnc.hextile_raw",
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x1,
"Raw subencoding is used in this tile", HFILL }
},
{ &hf_vnc_hextile_raw_value,
{ "Raw pixel values", "vnc.hextile_raw_value",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Raw subencoding pixel values", HFILL }
},
{ &hf_vnc_hextile_bg,
{ "Background Specified", "vnc.hextile_bg",
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x2,
"Background Specified subencoding is used in this tile", HFILL }
},
{ &hf_vnc_hextile_bg_value,
{ "Background pixel value", "vnc.hextile_bg_value",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Background color for this tile", HFILL }
},
{ &hf_vnc_hextile_fg,
{ "Foreground Specified", "vnc.hextile_fg",
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x4,
"Foreground Specified subencoding is used in this tile", HFILL }
},
{ &hf_vnc_hextile_fg_value,
{ "Foreground pixel value", "vnc.hextile_fg_value",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Foreground color for this tile", HFILL }
},
{ &hf_vnc_hextile_anysubrects,
{ "Any Subrects", "vnc.hextile_anysubrects",
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x8,
"Any subrects subencoding is used in this tile", HFILL }
},
{ &hf_vnc_hextile_num_subrects,
{ "Number of subrectangles", "vnc.hextile_num_subrects",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Number of subrectangles that follow", HFILL }
},
{ &hf_vnc_hextile_subrectscolored,
{ "Subrects Colored", "vnc.hextile_subrectscolored",
FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
"Subrects colored subencoding is used in this tile", HFILL }
},
{ &hf_vnc_hextile_subrect_pixel_value,
{ "Pixel value", "vnc.hextile_subrect_pixel_value",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Pixel value of this subrectangle", HFILL }
},
{ &hf_vnc_hextile_subrect_x_pos,
{ "X position", "vnc.hextile_subrect_x_pos",
FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
"X position of this subrectangle", HFILL }
},
{ &hf_vnc_hextile_subrect_y_pos,
{ "Y position", "vnc.hextile_subrect_y_pos",
FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
"Y position of this subrectangle", HFILL }
},
{ &hf_vnc_hextile_subrect_width,
{ "Width", "vnc.hextile_subrect_width",
FT_UINT8, BASE_DEC, NULL, 0xF0, /* Top 4 bits */
"Subrectangle width minus one", HFILL }
},
{ &hf_vnc_hextile_subrect_height,
{ "Height", "vnc.hextile_subrect_height",
FT_UINT8, BASE_DEC, NULL, 0xF, /* Bottom 4 bits */
"Subrectangle height minus one", HFILL }
},
/* ZRLE Encoding */
{ &hf_vnc_zrle_len,
{ "ZRLE compressed length", "vnc.zrle_len",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Length of compressed ZRLE data that follows", HFILL }
},
{ &hf_vnc_zrle_subencoding,
{ "Subencoding type", "vnc.zrle_subencoding",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Subencoding type byte", HFILL }
},
{ &hf_vnc_zrle_rle,
{ "RLE", "vnc.zrle_rle",
FT_UINT8, BASE_DEC, VALS(yes_no_vs), 0x80, /* Upper bit */
"Specifies that data is run-length encoded", HFILL }
},
{ &hf_vnc_zrle_palette_size,
{ "Palette size", "vnc.zrle_palette_size",
FT_UINT8, BASE_DEC, NULL, 0x7F, /* Lower 7 bits */
NULL, HFILL }
},
{ &hf_vnc_zrle_data,
{ "ZRLE compressed data", "vnc.zrle_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Compressed ZRLE data. Compiling with zlib support will uncompress and dissect this data", HFILL }
},
{ &hf_vnc_zrle_raw,
{ "Pixel values", "vnc.zrle_raw",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Raw pixel values for this tile", HFILL }
},
{ &hf_vnc_zrle_palette,
{ "Palette", "vnc.zrle_palette",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Palette pixel values", 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_color_groups,
{ "Color groups", "vnc.color_groups",
FT_NONE, BASE_NONE, NULL, 0x0,
NULL, 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 }
},
/* LibVNCServer additions */
{ &hf_vnc_supported_messages_client2server,
{ "Client2server", "vnc.supported_messages_client2server",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Supported client to server messages (bit flags)", HFILL }
},
{ &hf_vnc_supported_messages_server2client,
{ "Server2client", "vnc.supported_messages_server2client",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Supported server to client messages (bit flags)", HFILL }
},
{ &hf_vnc_num_supported_encodings,
{ "Number of supported encodings", "vnc.num_supported_encodings",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_vnc_supported_encodings,
{ "Encoding", "vnc.supported_encodings",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Supported encoding", HFILL }
},
{ &hf_vnc_server_identity,
{ "Server Identity", "vnc.server_identity",
FT_STRING, BASE_NONE, NULL, 0x0,
"Server identity string", HFILL }
},
/* MirrorLink */
{ &hf_vnc_mirrorlink_type,
{ "Type", "vnc.mirrorlink_type",
FT_UINT8, BASE_DEC, VALS(vnc_mirrorlink_types_vs), 0x0,
"MirrorLink extension message type", HFILL }
},
{ &hf_vnc_mirrorlink_length,
{ "Length", "vnc.mirrorlink_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Payload length", HFILL }
},
{ &hf_vnc_mirrorlink_version_major,
{ "Major Version", "vnc.mirrorlink_version_major",
FT_UINT8, BASE_DEC, NULL, 0x0,
"MirrorLink major version", HFILL }
},
{ &hf_vnc_mirrorlink_version_minor,
{ "Minor Version", "vnc.mirrorlink_version_minor",
FT_UINT8, BASE_DEC, NULL, 0x0,
"MirrorLink minor version", HFILL }
},
{ &hf_vnc_mirrorlink_framebuffer_configuration,
{ "Configuration",
"vnc.mirrorlink_framebuffer_configuration",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Framebuffer configuration", HFILL }
},
{ &hf_vnc_mirrorlink_pixel_width,
{ "Pixel Width", "vnc.mirrorlink_pixel_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Display width [pixel]", HFILL }
},
{ &hf_vnc_mirrorlink_pixel_height,
{ "Pixel Height", "vnc.mirrorlink_pixel_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Display height [pixel]", HFILL }
},
{ &hf_vnc_mirrorlink_pixel_format,
{ "Pixel Format", "vnc.mirrorlink_pixel_format",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Pixel format support", HFILL }
},
{ &hf_vnc_mirrorlink_display_width,
{ "Display Width", "vnc.mirrorlink_display_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Display width [mm]", HFILL }
},
{ &hf_vnc_mirrorlink_display_height,
{ "Display Height", "vnc.mirrorlink_display_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Display height [mm]", HFILL }
},
{ &hf_vnc_mirrorlink_display_distance,
{ "Display Distance", "vnc.mirrorlink_display_distance",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Display distance [mm]", HFILL }
},
{ &hf_vnc_mirrorlink_keyboard_language,
{ "Keyboard Language", "vnc.mirrorlink_keyboard_language",
FT_STRING, BASE_NONE, NULL, 0x0,
"Keyboard layout - Language code (according ISO 639-1)",
HFILL }
},
{ &hf_vnc_mirrorlink_keyboard_country,
{ "Keyboard Country", "vnc.mirrorlink_keyboard_country",
FT_STRING, BASE_NONE, NULL, 0x0,
"Keyboard layout - Country code (according ISO 3166-1 alpha-2)",
HFILL }
},
{ &hf_vnc_mirrorlink_ui_language,
{ "UI Language", "vnc.mirrorlink_ui_language",
FT_STRING, BASE_NONE, NULL, 0x0,
"UI language - Language code (according ISO 639-1)", HFILL }
},
{ &hf_vnc_mirrorlink_ui_country,
{ "UI Country", "vnc.mirrorlink_ui_country",
FT_STRING, BASE_NONE, NULL, 0x0,
"UI language - Country code (according ISO 3166-1 alpha 2)",
HFILL }
},
{ &hf_vnc_mirrorlink_knob_keys,
{ "Knob Keys", "vnc.mirrorlink_knob_keys",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Supported knob keys", HFILL }
},
{ &hf_vnc_mirrorlink_device_keys,
{ "Device Keys", "vnc.mirrorlink_device_keys",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Supported device keys", HFILL }
},
{ &hf_vnc_mirrorlink_multimedia_keys,
{ "Multimedia Keys", "vnc.mirrorlink_multimedia_keys",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Supported multimedia keys", HFILL }
},
{ &hf_vnc_mirrorlink_key_related,
{ "Keyboard", "vnc.mirrorlink_key_related",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Keyboard related", HFILL }
},
{ &hf_vnc_mirrorlink_pointer_related,
{ "Pointer", "vnc.mirrorlink_pointer_related",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Pointer related", HFILL }
},
{ &hf_vnc_mirrorlink_key_symbol_value_client,
{ "Client KeySymValue",
"vnc.mirrorlink_key_symbol_value_client",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Client key symbol value", HFILL }
},
{ &hf_vnc_mirrorlink_key_symbol_value_server,
{ "Server KeySymValue",
"vnc.mirrorlink_key_symbol_value_server",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Server key symbol value", HFILL }
},
{ &hf_vnc_mirrorlink_key_configuration,
{ "Configuration", "vnc.mirrorlink_key_configuration",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Key event listing configuration", HFILL }
},
{ &hf_vnc_mirrorlink_key_num_events,
{ "Number of Key Events", "vnc.mirrorlink_key_num_events",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Number of key events in list", HFILL }
},
{ &hf_vnc_mirrorlink_key_event_counter,
{ "Key Event Counter", "vnc.mirrorlink_key_event_counter",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Key event listing counter", HFILL }
},
{ &hf_vnc_mirrorlink_key_symbol_value,
{ "KeySymValue",
"vnc.mirrorlink_key_symbol_value",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Key symbol value", HFILL }
},
{ &hf_vnc_mirrorlink_key_request_configuration,
{ "Configuration", "vnc.mirrorlink_key_request_configuration",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Key event listing request configuration", HFILL }
},
{ &hf_vnc_mirrorlink_keyboard_configuration,
{ "Configuration", "vnc.mirrorlink_keyboard_configuration",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Virtual keyboard configuration", HFILL }
},
{ &hf_vnc_mirrorlink_cursor_x,
{ "Cursor X", "vnc.mirrorlink_cursor_x",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Cursor - X position", HFILL }
},
{ &hf_vnc_mirrorlink_cursor_y,
{ "Cursor Y", "vnc.mirrorlink_cursor_y",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Cursor - Y position", HFILL }
},
{ &hf_vnc_mirrorlink_text_x,
{ "Text X", "vnc.mirrorlink_text_x",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Text input area - X position", HFILL }
},
{ &hf_vnc_mirrorlink_text_y,
{ "Text Y", "vnc.mirrorlink_text_y",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Text input area - Y position", HFILL }
},
{ &hf_vnc_mirrorlink_text_width,
{ "Text Width", "vnc.mirrorlink_text_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Text input area - Width", HFILL }
},
{ &hf_vnc_mirrorlink_text_height,
{ "Text Height", "vnc.mirrorlink_text_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Text input area - Height", HFILL }
},
{ &hf_vnc_mirrorlink_keyboard_request_configuration,
{ "Configuration",
"vnc.mirrorlink_keyboard_request_configuration",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Virtual keyboard request configuration", HFILL }
},
{ &hf_vnc_mirrorlink_device_status,
{ "Device Status", "vnc.mirrorlink_device_status",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Status of Device Features", HFILL }
},
{ &hf_vnc_mirrorlink_app_id,
{ "App Id", "vnc.mirrorlink_app_id",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Unique application id", HFILL }
},
{ &hf_vnc_mirrorlink_fb_block_x,
{ "Frambuffer X", "vnc.mirrorlink_fb_block_x",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Frambuffer blocking - X position", HFILL }
},
{ &hf_vnc_mirrorlink_fb_block_y,
{ "Frambuffer Y", "vnc.mirrorlink_fb_block_y",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Frambuffer blocking - Y position", HFILL }
},
{ &hf_vnc_mirrorlink_fb_block_width,
{ "Frambuffer Width", "vnc.mirrorlink_fb_block_width",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Frambuffer blocking - Width", HFILL }
},
{ &hf_vnc_mirrorlink_fb_block_height,
{ "Frambuffer Height", "vnc.mirrorlink_fb_block_height",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Frambuffer blocking - Height", HFILL }
},
{ &hf_vnc_mirrorlink_fb_block_reason,
{ "Reason", "vnc.mirrorlink_fb_block_reason",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Reason for blocking", HFILL }
},
{ &hf_vnc_mirrorlink_audio_block_reason,
{ "Reason", "vnc.mirrorlink_audio_block_reason",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Reason for blocking", HFILL }
},
{ &hf_vnc_mirrorlink_touch_num_events,
{ "Number of Touch Events", "vnc.mirrorlink_touch_num_events",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Number of touch events in list", HFILL }
},
{ &hf_vnc_mirrorlink_touch_x,
{ "Touch X", "vnc.mirrorlink_touch_x",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Touch event - X position", HFILL }
},
{ &hf_vnc_mirrorlink_touch_y,
{ "Touch Y", "vnc.mirrorlink_touch_y",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Touch event - Y position", HFILL }
},
{ &hf_vnc_mirrorlink_touch_id,
{ "Touch Id", "vnc.mirrorlink_touch_id",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Touch event - identifier", HFILL }
},
{ &hf_vnc_mirrorlink_touch_pressure,
{ "Touch Pressure", "vnc.mirrorlink_touch_pressure",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Touch event - pressure value", HFILL }
},
{ &hf_vnc_mirrorlink_text,
{ "Text", "vnc.mirrorlink_text",
FT_STRING, BASE_NONE, NULL, 0x0,
"Textual information", HFILL }
},
{ &hf_vnc_mirrorlink_text_length,
{ "Length", "vnc.mirrorlink_text_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of textual information", HFILL }
},
{ &hf_vnc_mirrorlink_text_max_length,
{ "Max Length", "vnc.mirrorlink_text_max_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Maximum length of textual information", HFILL }
},
{ &hf_vnc_mirrorlink_unknown,
{ "Unknown", "vnc.mirrorlink_unknown",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Unknown data", HFILL }
},
/* Fence */
{ &hf_vnc_fence_flags,
{"Fence flags", "vnc.fence_flags", FT_UINT32, BASE_HEX,
NULL, 0, NULL, HFILL}},
{ &hf_vnc_fence_request,
{ "Fence_request", "vnc.fence_request",
FT_BOOLEAN, 32, NULL, VNC_FENCE_REQUEST,
NULL, HFILL }
},
{ &hf_vnc_fence_sync_next,
{ "Fence_sync_next", "vnc.fence_sync_next",
FT_BOOLEAN, 32, NULL, VNC_FENCE_SYNC_NEXT,
NULL, HFILL }
},
{ &hf_vnc_fence_block_after,
{ "Fence_block_after", "vnc.fence_block_after",
FT_BOOLEAN, 32, NULL, VNC_FENCE_BLOCK_AFTER,
NULL, HFILL }
},
{ &hf_vnc_fence_block_before,
{ "Fence block_before", "vnc.fence_block_before",
FT_BOOLEAN, 32, NULL, VNC_FENCE_BLOCK_BEFORE,
NULL, HFILL }
},
{ &hf_vnc_fence_payload_length,
{ "Fence payload length", "vnc.fence_payload_length",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_vnc_fence_payload,
{ "Fence payload", "vnc.fence_payload",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
/* Context Information */
{ &hf_vnc_context_information_app_id,
{ "App Id", "vnc.context_information_app_id",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Unique application id", HFILL }
},
{ &hf_vnc_context_information_app_trust_level,
{ "App Trust Level",
"vnc.context_information_app_trust_level",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Trust Level for Application Category", HFILL }
},
{ &hf_vnc_context_information_content_trust_level,
{ "Content Trust Level",
"vnc.context_information_content_trust_level",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Trust Level for Content Category", HFILL }
},
{ &hf_vnc_context_information_app_category,
{ "App Category", "vnc.context_information_app_category",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Application Category", HFILL }
},
{ &hf_vnc_context_information_content_category,
{ "Content Category",
"vnc.context_information_content_category",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Visual content category", HFILL }
},
{ &hf_vnc_context_information_content_rules,
{ "Content Rules", "vnc.context_information_content_rules",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Visual content rules", HFILL }
},
/* Scan Line based Run-Length Encoding */
{ &hf_vnc_slrle_run_num,
{ "Number of Runs", "vnc.slrle_run_num",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Number of Runs within Line", HFILL }
},
{ &hf_vnc_slrle_run_data,
{ "Raw RLE data", "vnc.slrle_run_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Raw Run-Length encoded data within Line", HFILL }
},
/* H.264 Encoding */
{ &hf_vnc_h264_slice_type,
{ "Slice Type", "vnc.h264_slice_type",
FT_UINT32, BASE_DEC, VALS(vnc_h264_slice_types_vs), 0x0,
"Frame slice type", HFILL }
},
{ &hf_vnc_h264_nbytes,
{ "Number of Bytes", "vnc.h264_nbytes",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Number of bytes within frame", HFILL }
},
{ &hf_vnc_h264_width,
{ "Width", "vnc.h264_width",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Frame Width", HFILL }
},
{ &hf_vnc_h264_height,
{ "Height", "vnc.h264_height",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Frame Height", HFILL }
},
{ &hf_vnc_h264_data,
{ "Data", "vnc.h264_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Frame H.264 data", HFILL }
},
};
/* Setup protocol subtree arrays */
static gint *ett[] = {
&ett_vnc,
&ett_vnc_client_message_type,
&ett_vnc_server_message_type,
&ett_vnc_rect,
&ett_vnc_encoding_type,
&ett_vnc_rre_subrect,
&ett_vnc_hextile_subencoding_mask,
&ett_vnc_hextile_num_subrects,
&ett_vnc_hextile_subrect,
&ett_vnc_hextile_tile,
&ett_vnc_zrle_subencoding,
&ett_vnc_colormap_num_groups,
&ett_vnc_desktop_screen,
&ett_vnc_colormap_color_group,
&ett_vnc_key_events,
&ett_vnc_touch_events,
&ett_vnc_slrle_subline,
&ett_vnc_fence_flags
};
static ei_register_info ei[] = {
{ &ei_vnc_possible_gtk_vnc_bug, { "vnc.possible_gtk_vnc_bug", PI_MALFORMED, PI_ERROR, "NULL found in greeting. client -> server greeting must be 12 bytes (possible gtk-vnc bug)", EXPFILL }},
{ &ei_vnc_auth_code_mismatch, { "vnc.auth_code_mismatch", PI_PROTOCOL, PI_WARN, "Authentication code does not match vendor or signature", EXPFILL }},
{ &ei_vnc_unknown_tight_vnc_auth, { "vnc.unknown_tight_vnc_auth", PI_PROTOCOL, PI_ERROR, "Unknown TIGHT VNC authentication", EXPFILL }},
{ &ei_vnc_too_many_rectangles, { "vnc.too_many_rectangles", PI_MALFORMED, PI_ERROR, "Too many rectangles, aborting dissection", EXPFILL }},
{ &ei_vnc_too_many_sub_rectangles, { "vnc.too_many_sub_rectangles", PI_MALFORMED, PI_ERROR, "Too many sub-rectangles, aborting dissection", EXPFILL }},
{ &ei_vnc_invalid_encoding, { "vnc.invalid_encoding", PI_MALFORMED, PI_ERROR, "Invalid encoding", EXPFILL }},
{ &ei_vnc_too_many_colors, { "vnc.too_many_colors", PI_MALFORMED, PI_ERROR, "Too many colors, aborting dissection", EXPFILL }},
{ &ei_vnc_too_many_cut_text, { "vnc.too_many_cut_text", PI_MALFORMED, PI_ERROR, "Too much cut text, aborting dissection", EXPFILL }},
{ &ei_vnc_zrle_failed, { "vnc.zrle_failed", PI_UNDECODED, PI_ERROR, "Decompression of ZRLE data failed", EXPFILL }},
{ &ei_vnc_unknown_tight, { "vnc.unknown_tight_packet", PI_UNDECODED, PI_WARN, "Unknown packet (TightVNC)", EXPFILL }},
{ &ei_vnc_reassemble, { "vnc.reassemble", PI_REASSEMBLE, PI_CHAT, "See further on for dissection of the complete (reassembled) PDU", EXPFILL }},
};
/* 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 */
proto_register_field_array(proto_vnc, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_vnc = expert_register_protocol(proto_vnc);
expert_register_field_array(expert_vnc, ei, array_length(ei));
/* Register our preferences module */
vnc_module = prefs_register_protocol(proto_vnc, apply_vnc_prefs);
prefs_register_bool_preference(vnc_module, "desegment",
"Reassemble VNC messages spanning multiple TCP segments.",
"Whether the VNC dissector should reassemble messages spanning "
"multiple TCP segments. To use this option, you must also enable "
"\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
&vnc_preference_desegment);
}
void
proto_reg_handoff_vnc(void)
{
vnc_handle = create_dissector_handle(dissect_vnc, proto_vnc);
dissector_add_uint_range_with_preference("tcp.port", VNC_PORT_RANGE, vnc_handle);
heur_dissector_add("tcp", test_vnc_protocol, "VNC over TCP", "vnc_tcp", proto_vnc, HEURISTIC_ENABLE);
/* We don't register a port for the VNC HTTP server because
* that simply provides a java program for download via the
* HTTP protocol. The java program then connects to a standard
* VNC port. */
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/