diff options
author | Bill Meier <wmeier@newsguy.com> | 2014-07-03 17:35:58 -0400 |
---|---|---|
committer | Bill Meier <wmeier@newsguy.com> | 2014-07-03 21:51:17 +0000 |
commit | df6bdcc07d4b2dc7877007cfa04830761acb0d0f (patch) | |
tree | 9d0ab0a603e33128aa44dd042d60696886c1fbe8 /epan/dissectors/packet-vnc.c | |
parent | 60a6f8582a229fe4c8028656f5fe5a1a319ca7f7 (diff) | |
download | wireshark-df6bdcc07d4b2dc7877007cfa04830761acb0d0f.tar.gz |
packet-vnc.c: Improve dissection
- Properly dissect multiple VNC PDUs in one (or more) TCP segment(s).
- Dissect additional message types ('Fence' and 'Enable Continuous Updates').
- Handle "num_rects" field = 0xFFFF (TightVNC).
- Add some more info as to sources of information about the VNC protocol.
- Add an XXX note as to the (incorrect) reassembly method being used.
- Add some notes as to possible ToDo's.
Change-Id: Id4942c50b3d1373bd2e72c0131614835dc39ba90
Reviewed-on: https://code.wireshark.org/review/2834
Reviewed-by: Bill Meier <wmeier@newsguy.com>
Diffstat (limited to 'epan/dissectors/packet-vnc.c')
-rw-r--r-- | epan/dissectors/packet-vnc.c | 320 |
1 files changed, 266 insertions, 54 deletions
diff --git a/epan/dissectors/packet-vnc.c b/epan/dissectors/packet-vnc.c index 4f1ef7743d..9d1903a58e 100644 --- a/epan/dissectors/packet-vnc.c +++ b/epan/dissectors/packet-vnc.c @@ -31,6 +31,7 @@ * 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. @@ -38,8 +39,44 @@ * 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 <glib.h> @@ -99,41 +136,71 @@ static const value_string yes_no_vs[] = { }; typedef enum { - VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT = 0, - VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING = 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, - VNC_CLIENT_MESSAGE_TYPE_MIRRORLINK = 128 + /* 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[] = { - { VNC_CLIENT_MESSAGE_TYPE_SET_PIXEL_FORMAT, "Set Pixel Format" }, - { VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING, "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" }, - { VNC_CLIENT_MESSAGE_TYPE_MIRRORLINK, "MirrorLink" }, - { 0, NULL } + /* 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_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" }, - { 0, NULL } + { 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 = { @@ -392,6 +459,13 @@ typedef enum { VNC_SESSION_STATE_NORMAL_TRAFFIC } vnc_session_state_e; +typedef enum { + VNC_FENCE_BLOCK_BEFORE = 0x00000001, + VNC_FENCE_BLOCK_AFTER = 0x00000002, + VNC_FENCE_SYNC_NEXT = 0x00000004, + VNC_FENCE_REQUEST = 0x80000000 +} vnc_fence_flags_e; + /* This structure will be tied to each conversation. */ typedef struct { gdouble server_proto_ver, client_proto_ver; @@ -481,6 +555,8 @@ static guint vnc_supported_encodings(tvbuff_t *tvb, gint *offset, 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, @@ -495,8 +571,8 @@ static guint vnc_h264_encoding(tvbuff_t *tvb, gint *offset, proto_tree *tree); pinfo->destport == vnc_preference_alternate_port #define VNC_BYTES_NEEDED(a) \ - if(a > (guint)tvb_length_remaining(tvb, *offset)) \ - return a; + if((a) > (guint)tvb_length_remaining(tvb, *offset)) \ + return (a); /* Variables for our preferences */ static guint vnc_preference_alternate_port = 0; @@ -765,6 +841,23 @@ 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; @@ -806,6 +899,7 @@ 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; @@ -870,11 +964,15 @@ dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) vnc_set_bytes_per_pixel(pinfo, vnc_bytes_per_pixel); vnc_set_depth(pinfo, vnc_depth); - if(!ret) { - if(DEST_PORT_VNC || 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); + if (ret) { + return; /* We're in a "startup" state; Cannot yet do "normal" processing */ + } + + if(DEST_PORT_VNC || 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); } } @@ -886,7 +984,7 @@ process_vendor(proto_tree *tree, gint hfindex, tvbuff_t *tvb, gint offset) proto_item *ti; if (tree) { - vendor = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 4, ENC_ASCII); + vendor = tvb_get_string(wmem_packet_scope(), tvb, offset, 4); ti = proto_tree_add_string(tree, hfindex, tvb, offset, 4, vendor); @@ -919,7 +1017,7 @@ process_tight_capabilities(proto_tree *tree, offset = process_vendor(tree, vendor_index, tvb, offset); - name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 8, ENC_ASCII); + name = tvb_get_string(wmem_packet_scope(), tvb, offset, 8); proto_tree_add_string(tree, name_index, tvb, offset, 8, name); offset += 8; } @@ -1025,7 +1123,7 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset, 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); + g_ascii_strtod((char *)tvb_get_string(wmem_packet_scope(), tvb, 4, 7), NULL); per_conversation_info->server_port = pinfo->srcport; col_add_fstr(pinfo->cinfo, COL_INFO, @@ -1042,7 +1140,7 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset, 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); + g_ascii_strtod((char *)tvb_get_string(wmem_packet_scope(), tvb, 4, 7), NULL); col_add_fstr(pinfo->cinfo, COL_INFO, "Client protocol version: %s", @@ -1194,10 +1292,10 @@ vnc_startup_messages(tvbuff_t *tvb, packet_info *pinfo, gint offset, 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); + vendor = tvb_get_string(wmem_packet_scope(), tvb, offset, 4); process_vendor(tree, hf_vnc_tight_server_vendor, tvb, offset); offset += 4; - signature = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 8, ENC_ASCII); + signature = tvb_get_string(wmem_packet_scope(), tvb, offset, 8); proto_tree_add_text(tree, tvb, offset, 8, "Signature: %s", signature); offset += 8; @@ -1522,7 +1620,7 @@ vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset, { guint8 message_type; - proto_item *ti = NULL; + proto_item *ti; proto_tree *vnc_client_message_type_tree; message_type = tvb_get_guint8(tvb, *offset); @@ -1542,7 +1640,7 @@ vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *offset, vnc_client_message_type_tree); break; - case VNC_CLIENT_MESSAGE_TYPE_SET_ENCODING : + case VNC_CLIENT_MESSAGE_TYPE_SET_ENCODINGS : vnc_client_set_encodings(tvb, pinfo, offset, vnc_client_message_type_tree); break; @@ -1572,8 +1670,18 @@ vnc_client_to_server(tvbuff_t *tvb, packet_info *pinfo, gint *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_fstr(pinfo->cinfo, COL_INFO, + col_append_sep_fstr(pinfo->cinfo, COL_INFO, "; ", "Unknown client message type (%u)", message_type); break; @@ -1588,9 +1696,10 @@ vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset, guint8 message_type; gint bytes_needed = 0; - proto_item *ti = NULL; + proto_item *ti; proto_tree *vnc_server_message_type_tree; +again: start_offset = *offset; message_type = tvb_get_guint8(tvb, *offset); @@ -1629,15 +1738,33 @@ vnc_server_to_client(tvbuff_t *tvb, packet_info *pinfo, gint *offset, vnc_server_message_type_tree); break; - default : - col_append_str(pinfo->cinfo, COL_INFO, + 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_text(vnc_server_message_type_tree, tvb, start_offset, -1, + "[See further on for dissection of the complete (reassembled) PDU]"); pinfo->desegment_offset = start_offset; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + return; + } + + if ((unsigned)*offset < tvb_reported_length(tvb)) { + goto again; } } @@ -1853,14 +1980,15 @@ static guint vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset, proto_tree *tree) { - gint ii; - guint16 num_rects, width, height; + 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_set_str(pinfo->cinfo, COL_INFO, "Server framebuffer update"); + 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; @@ -1868,7 +1996,15 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset, num_rects = tvb_get_ntohs(tvb, *offset); ti = proto_tree_add_item(tree, hf_vnc_rectangle_num, tvb, *offset, 2, ENC_BIG_ENDIAN); - if (num_rects > 5000) { + /* 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); @@ -1877,6 +2013,11 @@ vnc_server_framebuffer_update(tvbuff_t *tvb, packet_info *pinfo, gint *offset, *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); ti = proto_tree_add_text(tree, tvb, *offset, 12, @@ -2676,6 +2817,40 @@ vnc_mirrorlink(tvbuff_t *tvb, packet_info *pinfo, gint *offset, } 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_NA); + + *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); @@ -2798,7 +2973,7 @@ vnc_zrle_encoding(tvbuff_t *tvb, packet_info *pinfo _U_, gint *offset, gint uncomp_offset = 0; guint length; gint subencoding_type; - tvbuff_t *uncomp_tvb = NULL; + tvbuff_t *uncomp_tvb; proto_tree *zrle_subencoding_tree; proto_item *ti; #endif @@ -3163,7 +3338,7 @@ vnc_server_set_colormap_entries(tvbuff_t *tvb, packet_info *pinfo, gint *offset, proto_item *ti; proto_tree *vnc_colormap_num_groups, *vnc_colormap_color_group; - col_set_str(pinfo->cinfo, COL_INFO, "Server set colormap entries"); + col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server set colormap entries"); number_of_colors = tvb_get_ntohs(tvb, 4); @@ -3229,7 +3404,7 @@ static void vnc_server_ring_bell(tvbuff_t *tvb _U_, packet_info *pinfo, gint *offset _U_, proto_tree *tree _U_) { - col_set_str(pinfo->cinfo, COL_INFO, "Server ring bell on client"); + col_append_sep_str(pinfo->cinfo, COL_INFO, "; ", "Server ring bell on client"); /* This message type has no payload... */ } @@ -3241,7 +3416,7 @@ vnc_server_cut_text(tvbuff_t *tvb, packet_info *pinfo, gint *offset, guint32 text_len; proto_item *pi; - col_set_str(pinfo->cinfo, COL_INFO, "Server cut text"); + 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, @@ -4433,6 +4608,42 @@ proto_register_vnc(void) "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, BASE_NONE, NULL, VNC_FENCE_REQUEST, + NULL, HFILL } + }, + { &hf_vnc_fence_sync_next, + { "Fence_sync_next", "vnc.fence_sync_next", + FT_BOOLEAN, BASE_NONE, NULL, VNC_FENCE_SYNC_NEXT, + NULL, HFILL } + }, + { &hf_vnc_fence_block_after, + { "Fence_block_after", "vnc.fence_block_after", + FT_BOOLEAN, BASE_NONE, NULL, VNC_FENCE_BLOCK_AFTER, + NULL, HFILL } + }, + { &hf_vnc_fence_block_before, + { "Fence block_before", "vnc.fence_block_before", + FT_BOOLEAN, BASE_NONE, 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", @@ -4527,7 +4738,8 @@ proto_register_vnc(void) &ett_vnc_colormap_color_group, &ett_vnc_key_events, &ett_vnc_touch_events, - &ett_vnc_slrle_subline + &ett_vnc_slrle_subline, + &ett_vnc_fence_flags }; static ei_register_info ei[] = { |