2 * Routines for Spice protocol dissection
3 * Copyright 2011, Yaniv Kaul <ykaul@redhat.com>
4 * Copyright 2013, Jonathon Jongsma <jjongsma@redhat.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * This code is based on the protocol specification:
13 * https://www.spice-space.org/spice-protocol.html
14 * and the source - git://cgit.freedesktop.org/spice/spice-protocol
19 #include <epan/packet.h>
20 #include <epan/conversation.h>
21 #include <epan/expert.h>
22 #include <epan/proto_data.h>
24 #include <epan/unit_strings.h>
26 #include <wsutil/array.h>
29 * packet-spice.h is auto-generated from a Spice protocol definition by a tool
30 * included in the spice-common repository
31 * (https://gitlab.freedesktop.org/spice/spice-common)
32 * To re-generate this file, run the following command from the root of the
34 * python ./spice_codegen.py --generate-wireshark-dissector \
35 * spice.proto packet-spice.h
37 #if WS_IS_AT_LEAST_GNUC_VERSION(6,0)
38 DIAG_OFF(unused
-const-variable
)
40 #include "packet-spice.h"
41 #if WS_IS_AT_LEAST_GNUC_VERSION(6,0)
42 DIAG_ON(unused
-const-variable
)
45 void proto_register_spice(void);
46 void proto_reg_handoff_spice(void);
48 #define SPICE_MAGIC 0x52454451 /* = "REDQ" */
50 #define SPICE_VERSION_MAJOR_1 1
51 #define SPICE_VERSION_MINOR_0 0
52 #define SPICE_VERSION_MAJOR_UNSTABLE 0xfffe
53 #define SPICE_VERSION_MINOR_UNSTABLE 0xffff
55 #define SPICE_TICKET_PUBKEY_BYTES 162
57 #define SPICE_ALIGN(a, size) (((a) + ((size) - 1)) & ~((size) - 1))
66 SPICE_CLIENT_AUTH_SELECT
,
67 SPICE_SASL_INIT_FROM_SERVER
,
68 SPICE_SASL_START_TO_SERVER
,
69 SPICE_SASL_START_FROM_SERVER
,
70 SPICE_SASL_START_FROM_SERVER_CONT
,
71 SPICE_SASL_STEP_TO_SERVER
,
72 SPICE_SASL_STEP_FROM_SERVER
,
73 SPICE_SASL_STEP_FROM_SERVER_CONT
,
76 } spice_session_state_e
;
78 static const value_string state_name_vs
[] = {
79 { SPICE_LINK_CLIENT
, "Client link message" },
80 { SPICE_LINK_SERVER
, "Server link message" },
81 { SPICE_TICKET_CLIENT
, "Client ticket" },
82 { SPICE_TICKET_SERVER
, "Server ticket" },
83 { SPICE_CLIENT_AUTH_SELECT
, "Client authentication method selection" },
84 { SPICE_SASL_INIT_FROM_SERVER
, "SASL supported authentication mechanisms (init from server)" },
85 { SPICE_SASL_START_TO_SERVER
, "SASL authentication (start to server)" },
86 { SPICE_SASL_START_FROM_SERVER
, "SASL authentication (start from server)" },
87 { SPICE_SASL_START_FROM_SERVER_CONT
, "SASL authentication - result from server" },
88 { SPICE_SASL_STEP_TO_SERVER
, "SASL authentication from client (step to server)" },
89 { SPICE_SASL_STEP_FROM_SERVER
, "SASL authentication (step from server)" },
90 { SPICE_SASL_STEP_FROM_SERVER_CONT
, "SASL authentication - result from server" },
91 { SPICE_SASL_DATA
, "SASL wrapped Spice message" },
92 { SPICE_DATA
, "" }, /* Intentionally "blank" to help col_append_sep_str() logic */
96 static dissector_handle_t spice_handle
;
98 #define SPICE_CHANNEL_NONE 0
100 #define SPICE_FIRST_AVAIL_MESSAGE 101
102 #define sizeof_SpiceLinkHeader 16
103 #define sizeof_SpiceDataHeader 18
104 #define sizeof_SpiceMiniDataHeader 6
106 static const value_string playback_mode_vals
[] = {
107 { SPICE_AUDIO_DATA_MODE_INVALID
, "INVALID" },
108 { SPICE_AUDIO_DATA_MODE_RAW
, "RAW" },
109 { SPICE_AUDIO_DATA_MODE_CELT_0_5_1
, "CELT_0_5_1" },
116 SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE
,
117 SPICE_MAIN_CAP_VM_NAME_UUID
,
118 SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS
,
119 SPICE_MAIN_CAP_SEAMLESS_MIGRATE
124 SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE_MASK
= (1 << SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE
),
125 SPICE_MAIN_CAP_VM_NAME_UUID_MASK
= (1 << SPICE_MAIN_CAP_VM_NAME_UUID
),
126 SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS_MASK
= (1 << SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS
),
127 SPICE_MAIN_CAP_SEAMLESS_MIGRATE_MASK
= (1 << SPICE_MAIN_CAP_SEAMLESS_MIGRATE
)
131 VD_AGENT_MOUSE_STATE
= 1,
132 VD_AGENT_MONITORS_CONFIG
,
135 VD_AGENT_DISPLAY_CONFIG
,
136 VD_AGENT_ANNOUNCE_CAPABILITIES
,
137 VD_AGENT_CLIPBOARD_GRAB
,
138 VD_AGENT_CLIPBOARD_REQUEST
,
139 VD_AGENT_CLIPBOARD_RELEASE
,
140 VD_AGENT_FILE_XFER_START
,
141 VD_AGENT_FILE_XFER_STATUS
,
142 VD_AGENT_FILE_XFER_DATA
,
143 VD_AGENT_CLIENT_DISCONNECTED
,
147 static const value_string agent_message_type_vs
[] = {
148 { VD_AGENT_MOUSE_STATE
, "VD_AGENT_MOUSE_STATE" },
149 { VD_AGENT_MONITORS_CONFIG
, "VD_AGENT_MONITORS_CONFIG" },
150 { VD_AGENT_REPLY
, "VD_AGENT_REPLY" },
151 { VD_AGENT_CLIPBOARD
, "VD_AGENT_CLIPBOARD" },
152 { VD_AGENT_DISPLAY_CONFIG
, "VD_AGENT_DISPLAY_CONFIG" },
153 { VD_AGENT_ANNOUNCE_CAPABILITIES
, "VD_AGENT_ANNOUNCE_CAPABILITIES" },
154 { VD_AGENT_CLIPBOARD_GRAB
, "VD_AGENT_CLIPBOARD_GRAB" },
155 { VD_AGENT_CLIPBOARD_REQUEST
, "VD_AGENT_CLIPBOARD_REQUEST" },
156 { VD_AGENT_CLIPBOARD_RELEASE
, "VD_AGENT_CLIPBOARD_RELEASE" },
157 { VD_AGENT_FILE_XFER_START
, "VD_AGENT_FILE_XFER_START" },
158 { VD_AGENT_FILE_XFER_STATUS
, "VD_AGENT_FILE_XFER_STATUS" },
159 { VD_AGENT_FILE_XFER_DATA
, "VD_AGENT_FILE_XFER_DATA" },
160 { VD_AGENT_CLIENT_DISCONNECTED
, "VD_AGENT_CLIENT_DISCONNECTED" },
161 { VD_AGENT_END_MESSAGE
, "VD_AGENT_END_MESSAGE" },
166 VD_AGENT_CLIPBOARD_NONE
,
167 VD_AGENT_CLIPBOARD_UTF8_TEXT
,
168 VD_AGENT_CLIPBOARD_IMAGE_PNG
,
169 VD_AGENT_CLIPBOARD_IMAGE_BMP
,
170 VD_AGENT_CLIPBOARD_IMAGE_TIFF
,
171 VD_AGENT_CLIPBOARD_IMAGE_JPG
174 static const value_string agent_clipboard_type
[] = {
175 { VD_AGENT_CLIPBOARD_NONE
, "NONE" },
176 { VD_AGENT_CLIPBOARD_UTF8_TEXT
, "UTF8_TEXT" },
177 { VD_AGENT_CLIPBOARD_IMAGE_PNG
, "IMAGE_PNG" },
178 { VD_AGENT_CLIPBOARD_IMAGE_BMP
, "IMAGE_BMP" },
179 { VD_AGENT_CLIPBOARD_IMAGE_TIFF
,"IMAGE_TIFF" },
180 { VD_AGENT_CLIPBOARD_IMAGE_JPG
, "IMAGE_JPG" },
185 VD_AGENT_CAP_MOUSE_STATE
= (1 << 0),
186 VD_AGENT_CAP_MONITORS_CONFIG
= (1 << 1),
187 VD_AGENT_CAP_REPLY
= (1 << 2),
188 VD_AGENT_CAP_CLIPBOARD
= (1 << 3),
189 VD_AGENT_CAP_DISPLAY_CONFIG
= (1 << 4),
190 VD_AGENT_CAP_CLIPBOARD_BY_DEMAND
= (1 << 5),
191 VD_AGENT_CAP_CLIPBOARD_SELECTION
= (1 << 6),
192 VD_AGENT_CAP_SPARSE_MONITORS_CONFIG
= (1 << 7),
193 VD_AGENT_CAP_GUEST_LINEEND_LF
= (1 << 8),
194 VD_AGENT_CAP_GUEST_LINEEND_CRLF
= (1 << 9)
198 static const value_string vd_agent_cap_vs
[] = {
199 { VD_AGENT_CAP_MOUSE_STATE
, "VD_AGENT_CAP_MOUSE_STATE" },
200 { VD_AGENT_CAP_MONITORS_CONFIG
, "VD_AGENT_CAP_MONITORS_CONFIG" },
201 { VD_AGENT_CAP_REPLY
, "VD_AGENT_CAP_REPLY" },
202 { VD_AGENT_CAP_CLIPBOARD
, "VD_AGENT_CAP_CLIPBOARD" },
203 { VD_AGENT_CAP_DISPLAY_CONFIG
, "VD_AGENT_CAP_DISPLAY_CONFIG" },
204 { VD_AGENT_CAP_CLIPBOARD_BY_DEMAND
, "VD_AGENT_CAP_CLIPBOARD_BY_DEMAND" },
205 { VD_AGENT_CAP_CLIPBOARD_SELECTION
, "VD_AGENT_CAP_CLIPBOARD_SELECTION" },
206 { VD_AGENT_CAP_SPARSE_MONITORS_CONFIG
, "VD_AGENT_CAP_SPARSE_MONITORS_CONFIG" },
207 { VD_AGENT_CAP_GUEST_LINEEND_LF
, "VD_AGENT_CAP_GUEST_LINEEND_LF" },
208 { VD_AGENT_CAP_GUEST_LINEEND_CRLF
, "VD_AGENT_CAP_GUEST_LINEEND_CRLF" },
214 VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS
= (1 << 0)
218 static const value_string vd_agent_monitors_config_flag_vs
[] = {
219 { VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS
, "VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS"},
225 VD_AGENT_SUCCESS
= 1,
229 static const value_string vd_agent_reply_error_vs
[] = {
230 { VD_AGENT_SUCCESS
, "SUCCESS"},
231 { VD_AGENT_ERROR
, "ERROR"},
235 /* playback channel capabilities */
237 SPICE_PLAYBACK_CAP_CELT_0_5_1
,
238 SPICE_PLAYBACK_CAP_VOLUME
,
239 SPICE_PLAYBACK_CAP_LATENCY
,
240 SPICE_PLAYBACK_CAP_OPUS
,
241 /* Number of bits to display for capabilities of the playback channel. */
246 SPICE_PLAYBACK_CAP_CELT_0_5_1_MASK
= (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1
),
247 SPICE_PLAYBACK_CAP_VOLUME_MASK
= (1 << SPICE_PLAYBACK_CAP_VOLUME
),
248 SPICE_PLAYBACK_CAP_LATENCY_MASK
= (1 << SPICE_PLAYBACK_CAP_LATENCY
),
249 SPICE_PLAYBACK_CAP_OPUS_MASK
= (1 << SPICE_PLAYBACK_CAP_OPUS
),
252 /* record channel capabilities */
254 SPICE_RECORD_CAP_CELT_0_5_1
,
255 SPICE_RECORD_CAP_VOLUME
,
256 SPICE_RECORD_CAP_OPUS
,
257 /* Number of bits to display for capabilities of the record channel. */
262 SPICE_RECORD_CAP_CELT_0_5_1_MASK
= (1 << SPICE_RECORD_CAP_CELT_0_5_1
),
263 SPICE_RECORD_CAP_VOLUME_MASK
= (1 << SPICE_RECORD_CAP_VOLUME
),
264 SPICE_RECORD_CAP_OPUS_MASK
= (1 << SPICE_RECORD_CAP_OPUS
),
267 /* display channel */
269 SPICE_DISPLAY_CAP_SIZED_STREAM
,
270 SPICE_DISPLAY_CAP_MONITORS_CONFIG
,
271 SPICE_DISPLAY_CAP_COMPOSITE
,
272 SPICE_DISPLAY_CAP_A8_SURFACE
,
273 SPICE_DISPLAY_CAP_STREAM_REPORT
,
274 SPICE_DISPLAY_CAP_LZ4_COMPRESSION
,
275 SPICE_DISPLAY_CAP_PREF_COMPRESSION
,
276 SPICE_DISPLAY_CAP_GL_SCANOUT
,
277 SPICE_DISPLAY_CAP_MULTI_CODEC
,
278 SPICE_DISPLAY_CAP_CODEC_MJPEG
,
279 SPICE_DISPLAY_CAP_CODEC_VP8
,
280 SPICE_DISPLAY_CAP_CODEC_H264
,
281 SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE
,
282 SPICE_DISPLAY_CAP_CODEC_VP9
,
283 SPICE_DISPLAY_CAP_CODEC_H265
,
284 /* Number of bits to display for capabilities of the display channel. */
289 SPICE_DISPLAY_CAP_SIZED_STREAM_MASK
= (1 << SPICE_DISPLAY_CAP_SIZED_STREAM
),
290 SPICE_DISPLAY_CAP_MONITORS_CONFIG_MASK
= (1 << SPICE_DISPLAY_CAP_MONITORS_CONFIG
),
291 SPICE_DISPLAY_CAP_COMPOSITE_MASK
= (1 << SPICE_DISPLAY_CAP_COMPOSITE
),
292 SPICE_DISPLAY_CAP_A8_SURFACE_MASK
= (1 << SPICE_DISPLAY_CAP_A8_SURFACE
),
293 SPICE_DISPLAY_CAP_STREAM_REPORT_MASK
= (1 << SPICE_DISPLAY_CAP_STREAM_REPORT
),
294 SPICE_DISPLAY_CAP_LZ4_COMPRESSION_MASK
= (1 << SPICE_DISPLAY_CAP_LZ4_COMPRESSION
),
295 SPICE_DISPLAY_CAP_PREF_COMPRESSION_MASK
= (1 << SPICE_DISPLAY_CAP_PREF_COMPRESSION
),
296 SPICE_DISPLAY_CAP_GL_SCANOUT_MASK
= (1 << SPICE_DISPLAY_CAP_GL_SCANOUT
),
297 SPICE_DISPLAY_CAP_MULTI_CODEC_MASK
= (1 << SPICE_DISPLAY_CAP_MULTI_CODEC
),
298 SPICE_DISPLAY_CAP_CODEC_MJPEG_MASK
= (1 << SPICE_DISPLAY_CAP_CODEC_MJPEG
),
299 SPICE_DISPLAY_CAP_CODEC_VP8_MASK
= (1 << SPICE_DISPLAY_CAP_CODEC_VP8
),
300 SPICE_DISPLAY_CAP_CODEC_H264_MASK
= (1 << SPICE_DISPLAY_CAP_CODEC_H264
),
301 SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE_MASK
= (1 << SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE
),
302 SPICE_DISPLAY_CAP_CODEC_VP9_MASK
= (1 << SPICE_DISPLAY_CAP_CODEC_VP9
),
303 SPICE_DISPLAY_CAP_CODEC_H265_MASK
= (1 << SPICE_DISPLAY_CAP_CODEC_H265
)
307 /* display channel */
309 #define sizeof_RedcDisplayInit 14
312 static const value_string cursor_visible_vs
[] = {
327 #define sizeof_CursorHeader 17
329 static const value_string spice_agent_vs
[] = {
330 { 0, "Disconnected" },
335 /* This structure will be tied to each conversation. */
337 uint32_t connection_id
;
338 uint32_t num_channel_caps
;
340 uint32_t client_auth
;
341 uint32_t server_auth
;
342 uint32_t auth_selected
;
343 spice_session_state_e next_state
;
344 uint16_t playback_mode
;
345 uint8_t channel_type
;
347 bool client_mini_header
;
348 bool server_mini_header
;
349 } spice_conversation_t
;
352 spice_session_state_e state
;
362 #define sizeof_SpiceRect 16
367 #define sizeof_Clip 1 /* This is correct only if the type is none. If it is RECTS, this is followed by: */
370 uint32_t num_rects
; /* this is followed by RECT rects[num_rects] */
376 SpiceRect bounding_box
;
380 #define sizeof_DisplayBase 21 /* size without a rect list in the Clip */
392 #define sizeof_Mask 13
394 #define sizeof_ImageDescriptor 18
397 QUIC_IMAGE_TYPE_INVALID
,
398 QUIC_IMAGE_TYPE_GRAY
,
399 QUIC_IMAGE_TYPE_RGB16
,
400 QUIC_IMAGE_TYPE_RGB24
,
401 QUIC_IMAGE_TYPE_RGB32
,
405 static const value_string quic_type_vs
[] = {
406 { QUIC_IMAGE_TYPE_INVALID
, "INVALID" },
407 { QUIC_IMAGE_TYPE_GRAY
, "GRAY" },
408 { QUIC_IMAGE_TYPE_RGB16
, "RGB16" },
409 { QUIC_IMAGE_TYPE_RGB24
, "RGB24" },
410 { QUIC_IMAGE_TYPE_RGB32
, "RGB32" },
411 { QUIC_IMAGE_TYPE_RGBA
, "RGBA" },
416 LZ_IMAGE_TYPE_INVALID
,
417 LZ_IMAGE_TYPE_PLT1_LE
,
418 LZ_IMAGE_TYPE_PLT1_BE
,
419 LZ_IMAGE_TYPE_PLT4_LE
,
420 LZ_IMAGE_TYPE_PLT4_BE
,
429 static const value_string LzImage_type_vs
[] = {
430 { LZ_IMAGE_TYPE_INVALID
, "INVALID" },
431 { LZ_IMAGE_TYPE_PLT1_LE
, "PLT1_LE" },
432 { LZ_IMAGE_TYPE_PLT1_BE
, "PLT1_BE" },
433 { LZ_IMAGE_TYPE_PLT4_LE
, "PLT4_LE" },
434 { LZ_IMAGE_TYPE_PLT4_BE
, "PLT4_BE" },
435 { LZ_IMAGE_TYPE_PLT8
, "PLT8" },
436 { LZ_IMAGE_TYPE_RGB16
, "RGB16" },
437 { LZ_IMAGE_TYPE_RGB24
, "RGB24" },
438 { LZ_IMAGE_TYPE_RGB32
, "RGB32" },
439 { LZ_IMAGE_TYPE_RGBA
, "RGBA" },
440 { LZ_IMAGE_TYPE_XXXA
, "RGB JPEG (w/ Alpha LZ)" },
444 #define sizeof_SpiceHead 28
447 SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION
,
448 SPICE_COMMON_CAP_AUTH_SPICE
,
449 SPICE_COMMON_CAP_AUTH_SASL
,
450 SPICE_COMMON_CAP_MINI_HEADER
454 SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION_MASK
= (1 << SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION
),
455 SPICE_COMMON_CAP_AUTH_SPICE_MASK
= (1 << SPICE_COMMON_CAP_AUTH_SPICE
),
456 SPICE_COMMON_CAP_AUTH_SASL_MASK
= (1 << SPICE_COMMON_CAP_AUTH_SASL
),
457 SPICE_COMMON_CAP_MINI_HEADER_MASK
= (1 << SPICE_COMMON_CAP_MINI_HEADER
)
460 static const value_string spice_auth_select_vs
[] = {
461 { SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION
, "Auth Selection" },
462 { SPICE_COMMON_CAP_AUTH_SPICE
, "Spice" },
463 { SPICE_COMMON_CAP_AUTH_SASL
, "SASL" },
464 { SPICE_COMMON_CAP_MINI_HEADER
, "Mini header" },
468 static const value_string spice_sasl_auth_result_vs
[] = {
474 #define GET_PDU_FROM_OFFSET(OFFSET) if (avail < pdu_len) { \
475 pinfo->desegment_offset = OFFSET; \
476 pinfo->desegment_len = pdu_len - avail; \
480 static int ett_spice
;
481 static int ett_link_client
;
482 static int ett_link_server
;
483 static int ett_link_caps
;
485 static int ett_message
;
486 static int ett_ticket_client
;
487 static int ett_auth_select_client
;
488 static int ett_ticket_server
;
489 static int ett_playback
;
490 static int ett_display_client
;
491 static int ett_display_server
;
492 static int ett_common_server_message
;
493 static int ett_common_client_message
;
494 static int ett_point
;
495 static int ett_point16
;
496 static int ett_cursor
;
497 static int ett_spice_main
;
499 static int ett_DisplayBase
;
502 static int ett_imagedesc
;
503 static int ett_imageQuic
;
504 static int ett_GLZ_RGB
;
505 static int ett_LZ_RGB
;
506 static int ett_LZ_PLT
;
507 static int ett_ZLIB_GLZ
;
508 static int ett_Uncomp_tree
;
509 static int ett_LZ_JPEG
;
511 static int ett_cursor_header
;
512 static int ett_RedCursor
;
513 static int ett_pattern
;
514 static int ett_brush
;
515 static int ett_Pixmap
;
516 static int ett_SpiceHead
;
517 static int ett_inputs_client
;
518 static int ett_rectlist
;
519 static int ett_inputs_server
;
520 static int ett_record_client
;
521 static int ett_record_server
;
522 static int ett_main_client
;
523 static int ett_spice_agent
;
524 static int ett_cap_tree
;
525 static int proto_spice
;
526 static int hf_spice_magic
;
527 static int hf_major_version
;
528 static int hf_minor_version
;
529 static int hf_message_size
;
530 static int hf_message_type
;
531 static int hf_conn_id
;
532 static int hf_channel_type
;
533 static int hf_channel_id
;
534 static int hf_num_common_caps
;
535 static int hf_num_channel_caps
;
536 static int hf_caps_offset
;
537 static int hf_error_code
;
539 static int hf_serial
;
540 static int hf_data_size
;
541 static int hf_data_sublist
;
542 static int hf_link_client
;
543 static int hf_link_server
;
544 static int hf_ticket_client
;
545 static int hf_auth_select_client
;
546 static int hf_ticket_server
;
547 static int hf_main_num_channels
;
548 static int hf_main_cap_semi_migrate
;
549 static int hf_main_cap_vm_name_uuid
;
550 static int hf_main_cap_agent_connected_tokens
;
551 static int hf_main_cap_seamless_migrate
;
552 static int hf_inputs_cap
;
553 static int hf_cursor_cap
;
554 static int hf_common_cap_auth_select
;
555 static int hf_common_cap_auth_spice
;
556 static int hf_common_cap_auth_sasl
;
557 static int hf_common_cap_mini_header
;
558 static int hf_audio_timestamp
;
559 static int hf_audio_mode
;
560 static int hf_audio_channels
;
561 static int hf_audio_format
;
562 static int hf_audio_frequency
;
563 static int hf_audio_volume
;
564 static int hf_audio_mute
;
565 static int hf_audio_latency
;
566 static int hf_red_set_ack_generation
;
567 static int hf_red_set_ack_window
;
568 static int hf_Clip_type
;
569 static int hf_Mask_flag
;
570 static int hf_display_rop_descriptor
;
571 static int hf_display_scale_mode
;
572 static int hf_display_stream_id
;
573 static int hf_display_stream_report_unique_id
;
574 static int hf_display_stream_report_max_window_size
;
575 static int hf_display_stream_report_timeout
;
576 static int hf_display_stream_width
;
577 static int hf_display_stream_height
;
578 static int hf_display_stream_src_width
;
579 static int hf_display_stream_src_height
;
580 static int hf_display_stream_data_size
;
581 static int hf_display_stream_codec_type
;
582 static int hf_display_stream_stamp
;
583 static int hf_display_stream_flags
;
584 static int hf_red_ping_id
;
585 static int hf_red_timestamp
;
586 static int hf_spice_display_mode_width
;
587 static int hf_spice_display_mode_height
;
588 static int hf_spice_display_mode_depth
;
589 static int hf_image_desc_id
;
590 static int hf_image_desc_type
;
591 static int hf_image_desc_flags
;
592 static int hf_image_desc_width
;
593 static int hf_image_desc_height
;
594 static int hf_quic_width
;
595 static int hf_quic_height
;
596 static int hf_quic_major_version
;
597 static int hf_quic_minor_version
;
598 static int hf_quic_type
;
599 static int hf_LZ_width
;
600 static int hf_LZ_height
;
601 static int hf_LZ_major_version
;
602 static int hf_LZ_minor_version
;
603 static int hf_LZ_PLT_type
;
604 static int hf_LZ_RGB_type
;
605 static int hf_LZ_stride
;
606 static int hf_LZ_RGB_dict_id
;
607 static int hf_cursor_trail_len
;
608 static int hf_cursor_trail_freq
;
609 static int hf_cursor_trail_visible
;
610 static int hf_cursor_unique
;
611 static int hf_cursor_type
;
612 static int hf_cursor_width
;
613 static int hf_cursor_height
;
614 static int hf_cursor_hotspot_x
;
615 static int hf_cursor_hotspot_y
;
616 static int hf_cursor_flags
;
617 static int hf_cursor_id
;
618 static int hf_spice_display_init_cache_id
;
619 static int hf_spice_display_init_cache_size
;
620 static int hf_spice_display_init_glz_dict_id
;
621 static int hf_spice_display_init_dict_window_size
;
622 static int hf_brush_type
;
623 static int hf_brush_rgb
;
624 static int hf_pixmap_width
;
625 static int hf_pixmap_height
;
626 static int hf_pixmap_stride
;
627 static int hf_pixmap_address
;
628 static int hf_pixmap_format
;
629 static int hf_pixmap_flags
;
630 static int hf_keyboard_modifiers
;
631 static int hf_keyboard_modifier_scroll_lock
;
632 static int hf_keyboard_modifier_num_lock
;
633 static int hf_keyboard_modifier_caps_lock
;
634 static int hf_keyboard_code
;
635 static int hf_rectlist_size
;
636 static int hf_migrate_dest_port
;
637 static int hf_migrate_dest_sport
;
638 static int hf_migrate_src_mig_version
;
639 static int hf_session_id
;
640 static int hf_display_channels_hint
;
641 static int hf_supported_mouse_modes
;
642 static int hf_current_mouse_mode
;
643 static int hf_supported_mouse_modes_flags
;
644 static int hf_supported_mouse_modes_flag_client
;
645 static int hf_supported_mouse_modes_flag_server
;
646 static int hf_current_mouse_mode_flags
;
647 static int hf_agent_connected
;
648 static int hf_agent_tokens
;
649 static int hf_agent_protocol
;
650 static int hf_agent_type
;
651 static int hf_agent_opaque
;
652 static int hf_agent_size
;
653 static int hf_agent_token
;
654 static int hf_agent_clipboard_selection
;
655 static int hf_agent_clipboard_type
;
656 static int hf_agent_num_monitors
;
657 static int hf_agent_monitor_height
;
658 static int hf_agent_monitor_width
;
659 static int hf_agent_monitor_depth
;
660 static int hf_agent_monitor_x
;
661 static int hf_agent_monitor_y
;
662 static int hf_multi_media_time
;
663 static int hf_ram_hint
;
664 static int hf_button
;
665 static int hf_buttons_state
;
666 static int hf_button_mask_left
;
667 static int hf_button_mask_middle
;
668 static int hf_button_mask_right
;
669 static int hf_button_mask_reserved_bits
;
670 static int hf_mouse_display_id
;
671 static int hf_display_text_fore_mode
;
672 static int hf_display_text_back_mode
;
673 static int hf_display_surface_id
;
674 static int hf_display_surface_width
;
675 static int hf_display_surface_height
;
676 static int hf_display_surface_format
;
677 static int hf_display_surface_flags
;
678 static int hf_main_client_agent_tokens
;
679 static int hf_tranparent_src_color
;
680 static int hf_tranparent_true_color
;
681 static int hf_spice_sasl_auth_result
;
682 static int hf_playback_cap_celt_0_5_1
;
683 static int hf_playback_cap_volume
;
684 static int hf_playback_cap_latency
;
685 static int hf_playback_cap_opus
;
686 static int hf_record_cap_celt
;
687 static int hf_record_cap_volume
;
688 static int hf_record_cap_opus
;
689 static int hf_display_cap_sized_stream
;
690 static int hf_display_cap_monitors_config
;
691 static int hf_display_cap_composite
;
692 static int hf_display_cap_a8_surface
;
693 static int hf_display_cap_stream_report
;
694 static int hf_display_cap_lz4_compression
;
695 static int hf_display_cap_pref_compression
;
696 static int hf_display_cap_gl_scanout
;
697 static int hf_display_cap_multi_codec
;
698 static int hf_display_cap_codec_mjpeg
;
699 static int hf_display_cap_codec_vp8
;
700 static int hf_display_cap_codec_h264
;
701 static int hf_display_cap_pref_video_codec_type
;
702 static int hf_display_cap_codec_vp9
;
703 static int hf_display_cap_codec_h265
;
704 static int hf_main_uuid
;
705 static int hf_main_name
;
706 static int hf_main_name_len
;
707 static int hf_display_monitor_config_count
;
708 static int hf_display_monitor_config_max_allowed
;
709 static int hf_display_head_id
;
710 static int hf_display_head_surface_id
;
711 static int hf_display_head_width
;
712 static int hf_display_head_height
;
713 static int hf_display_head_x
;
714 static int hf_display_head_y
;
715 static int hf_display_head_flags
;
716 static int hf_zlib_uncompress_size
;
717 static int hf_zlib_compress_size
;
718 static int hf_rect_left
;
719 static int hf_rect_top
;
720 static int hf_rect_right
;
721 static int hf_rect_bottom
;
722 static int hf_point32_x
;
723 static int hf_point32_y
;
724 static int hf_point16_x
;
725 static int hf_point16_y
;
726 static int hf_severity
;
727 static int hf_visibility
;
728 static int hf_notify_code
;
729 static int hf_notify_message_len
;
730 static int hf_notify_message
;
731 static int hf_num_glyphs
;
732 static int hf_port_opened
;
733 static int hf_port_event
;
734 static int hf_raw_data
;
735 static int hf_display_inval_list_count
;
736 static int hf_resource_type
;
737 static int hf_resource_id
;
738 static int hf_ref_image
;
739 static int hf_ref_string
;
740 static int hf_vd_agent_buttons
;
741 static int hf_vd_agent_caps_request
;
742 static int hf_vd_agent_cap_mouse_state
;
743 static int hf_vd_agent_cap_monitors_config
;
744 static int hf_vd_agent_cap_reply
;
745 static int hf_vd_agent_cap_clipboard
;
746 static int hf_vd_agent_cap_display_config
;
747 static int hf_vd_agent_cap_clipboard_by_demand
;
748 static int hf_vd_agent_cap_clipboard_selection
;
749 static int hf_vd_agent_cap_sparse_monitors_config
;
750 static int hf_vd_agent_cap_guest_lineend_lf
;
751 static int hf_vd_agent_cap_guest_lineend_crlf
;
752 static int hf_vd_agent_monitors_config_flag_use_pos
;
753 static int hf_vd_agent_reply_type
;
754 static int hf_vd_agent_reply_error
;
755 /* Generated from convert_proto_tree_add_text.pl */
756 static int hf_spice_supported_authentication_mechanisms_list
;
757 static int hf_spice_selected_client_out_mechanism
;
758 static int hf_spice_scale_mode
;
759 static int hf_spice_supported_authentication_mechanisms_list_length
;
760 static int hf_spice_rop3
;
761 static int hf_spice_x509_subjectpublickeyinfo
;
762 static int hf_spice_glz_rgb_image_size
;
763 static int hf_spice_vd_agent_display_config_message
;
764 static int hf_spice_stream_data
;
765 static int hf_spice_client_out_mechanism_length
;
766 static int hf_spice_vd_agent_clipboard_message
;
767 static int hf_spice_image_from_cache
;
768 static int hf_spice_lz_rgb_compressed_image_data
;
769 static int hf_spice_unknown_bytes
;
770 static int hf_spice_sasl_data
;
771 static int hf_spice_name_length
;
772 static int hf_spice_zlib_stream
;
773 static int hf_spice_lz_plt_image_size
;
774 static int hf_spice_reserved
;
775 static int hf_spice_sasl_authentication_data
;
776 static int hf_spice_image_from_cache_lossless
;
777 static int hf_spice_quic_magic
;
778 static int hf_spice_surface_id
;
779 static int hf_spice_ping_data
;
780 static int hf_spice_display_mark_message
;
781 static int hf_spice_pixmap_pixels
;
782 static int hf_spice_vd_agent_clipboard_release_message
;
783 static int hf_spice_clientout_list
;
784 static int hf_spice_server_inputs_mouse_motion_ack_message
;
785 static int hf_spice_cursor_data
;
786 static int hf_spice_clientout_length
;
787 static int hf_spice_lz_magic
;
788 static int hf_spice_lz_rgb_image_size
;
789 static int hf_spice_lz_plt_data
;
790 static int hf_spice_glyph_flags
;
791 static int hf_spice_palette_offset
;
793 static int hf_spice_lz_jpeg_image_size
;
795 static int hf_spice_palette
;
796 static int hf_spice_selected_authentication_mechanism_length
;
797 static int hf_spice_display_reset_message
;
798 static int hf_spice_topdown_flag
;
799 static int hf_spice_quic_image_size
;
800 static int hf_spice_sasl_message_length
;
801 static int hf_spice_selected_authentication_mechanism
;
802 static int hf_spice_lz_plt_flag
;
803 static int hf_spice_quic_compressed_image_data
;
805 static expert_field ei_spice_decompress_error
;
806 static expert_field ei_spice_unknown_message
;
807 static expert_field ei_spice_not_dissected
;
808 static expert_field ei_spice_auth_unknown
;
809 static expert_field ei_spice_sasl_auth_result
;
810 static expert_field ei_spice_expected_from_client
;
811 /* Generated from convert_proto_tree_add_text.pl */
812 static expert_field ei_spice_brush_type
;
813 static expert_field ei_spice_unknown_image_type
;
814 static expert_field ei_spice_Mask_flag
;
815 static expert_field ei_spice_Mask_point
;
816 static expert_field ei_spice_common_cap_unknown
;
817 static expert_field ei_spice_unknown_channel
;
820 static dissector_handle_t jpeg_handle
;
823 dissect_SpiceHead(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, const uint16_t num
)
825 proto_tree
*SpiceHead_tree
;
827 SpiceHead_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof_SpiceHead
,
828 ett_SpiceHead
, NULL
, "Display Head #%u", num
);
829 proto_tree_add_item(SpiceHead_tree
, hf_display_head_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
831 proto_tree_add_item(SpiceHead_tree
, hf_display_head_surface_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
833 proto_tree_add_item(SpiceHead_tree
, hf_display_head_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
835 proto_tree_add_item(SpiceHead_tree
, hf_display_head_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
837 proto_tree_add_item(SpiceHead_tree
, hf_display_head_x
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
839 proto_tree_add_item(SpiceHead_tree
, hf_display_head_y
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
841 proto_tree_add_item(SpiceHead_tree
, hf_display_head_flags
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
847 #define sizeof_AgentMonitorConfig 20
849 dissect_AgentMonitorConfig(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, const uint16_t num
)
853 subtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof_AgentMonitorConfig
,
854 ett_SpiceHead
, NULL
, "Monitor Config #%u", num
);
855 proto_tree_add_item(subtree
, hf_agent_monitor_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
857 proto_tree_add_item(subtree
, hf_agent_monitor_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
859 proto_tree_add_item(subtree
, hf_agent_monitor_depth
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
861 proto_tree_add_item(subtree
, hf_agent_monitor_x
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
863 proto_tree_add_item(subtree
, hf_agent_monitor_y
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
869 /* returns the pixmap size in bytes */
871 dissect_Pixmap(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
874 proto_tree
*Pixmap_tree
;
876 uint32_t strides
, height
, palette_ptr
;
878 Pixmap_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 0, ett_Pixmap
, &ti
, "Pixmap"); /* size is fixed later */
879 proto_tree_add_item(Pixmap_tree
, hf_pixmap_format
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
881 proto_tree_add_item(Pixmap_tree
, hf_pixmap_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
883 proto_tree_add_item(Pixmap_tree
, hf_pixmap_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
885 height
= tvb_get_letohl(tvb
, offset
);
886 proto_tree_add_item(Pixmap_tree
, hf_pixmap_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
888 strides
= tvb_get_letohl(tvb
, offset
);
889 proto_tree_add_item(Pixmap_tree
, hf_pixmap_stride
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
891 palette_ptr
= tvb_get_letohl(tvb
, offset
);
892 proto_tree_add_item(Pixmap_tree
, hf_pixmap_address
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
894 PixmapSize
= height
* strides
;
895 proto_item_set_len(ti
, 18 + PixmapSize
);
896 proto_tree_add_bytes_format(Pixmap_tree
, hf_spice_pixmap_pixels
, tvb
, offset
, PixmapSize
, NULL
,
897 "Pixmap pixels (%d bytes)", PixmapSize
);
898 offset
+= PixmapSize
;
899 /* FIXME: compute palette size */
900 proto_tree_add_bytes_format(Pixmap_tree
, hf_spice_palette
, tvb
, offset
, 0, NULL
, "Palette (offset from message start - %u)", palette_ptr
);
901 /*TODO: complete pixmap dissection */
903 return PixmapSize
+ 18;
906 /* returns the type of cursor */
908 dissect_CursorHeader(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, uint16_t *width
, uint16_t *height
)
910 const uint8_t type
= tvb_get_uint8(tvb
, offset
+ 8);
912 *width
= tvb_get_letohs(tvb
, offset
+ 8 + 1);
913 *height
= tvb_get_letohs(tvb
, offset
+ 8 + 1 + 2);
916 proto_tree
*CursorHeader_tree
;
918 CursorHeader_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof_CursorHeader
, ett_cursor_header
, NULL
, "Cursor Header");
919 proto_tree_add_item(CursorHeader_tree
, hf_cursor_unique
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
921 proto_tree_add_item(CursorHeader_tree
, hf_cursor_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
923 proto_tree_add_item(CursorHeader_tree
, hf_cursor_width
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
925 proto_tree_add_item(CursorHeader_tree
, hf_cursor_height
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
927 proto_tree_add_item(CursorHeader_tree
, hf_cursor_hotspot_x
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
929 proto_tree_add_item(CursorHeader_tree
, hf_cursor_hotspot_y
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
935 /* returns the size of RedCursor */
937 dissect_RedCursor(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
940 proto_tree
*RedCursor_tree
;
942 uint16_t height
, width
;
943 uint32_t init_offset
= offset
;
944 const uint16_t flags
= tvb_get_letohs(tvb
, offset
);
945 uint32_t data_size
= 0;
947 RedCursor_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 2, ett_RedCursor
, &ti
, "RedCursor"); /* FIXME - fix size if flag is not NONE */
949 proto_tree_add_item(RedCursor_tree
, hf_cursor_flags
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
950 if (flags
== SPICE_CURSOR_FLAGS_NONE
) {
956 type
= dissect_CursorHeader(tvb
, RedCursor_tree
, offset
, &width
, &height
);
957 offset
+= (int)sizeof_CursorHeader
;
960 if (((width
== 0) || (height
== 0)) || (flags
== SPICE_CURSOR_FLAGS_FROM_CACHE
)) {
961 proto_item_set_len(ti
, offset
- init_offset
);
962 return (offset
- init_offset
);
966 case SPICE_CURSOR_TYPE_ALPHA
:
967 data_size
= (width
<< 2) * height
;
969 case SPICE_CURSOR_TYPE_MONO
:
970 data_size
= (SPICE_ALIGN(width
, 8) >> 2) * height
;
972 /* TODO: fix all size calculations for below cursor types, using SPICE_ALIGN */
973 case SPICE_CURSOR_TYPE_COLOR4
:
974 case SPICE_CURSOR_TYPE_COLOR8
:
975 case SPICE_CURSOR_TYPE_COLOR16
:
976 case SPICE_CURSOR_TYPE_COLOR24
:
977 case SPICE_CURSOR_TYPE_COLOR32
:
983 if (data_size
!= 0) {
984 proto_tree_add_item(RedCursor_tree
, hf_spice_cursor_data
, tvb
, offset
, data_size
, ENC_NA
);
986 proto_tree_add_item(RedCursor_tree
, hf_spice_cursor_data
, tvb
, offset
, -1, ENC_NA
);
991 return (offset
- init_offset
);
994 /* returns the image type, needed for later */
996 dissect_ImageDescriptor(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
998 const uint8_t type
= tvb_get_uint8(tvb
, offset
+ 8);
1001 proto_tree
*ImageDescriptor_tree
;
1003 ImageDescriptor_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof_ImageDescriptor
, ett_imagedesc
, NULL
, "Image Descriptor");
1005 proto_tree_add_item(ImageDescriptor_tree
, hf_image_desc_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1007 proto_tree_add_item(ImageDescriptor_tree
, hf_image_desc_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1009 proto_tree_add_item(ImageDescriptor_tree
, hf_image_desc_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1011 proto_tree_add_item(ImageDescriptor_tree
, hf_image_desc_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1013 proto_tree_add_item(ImageDescriptor_tree
, hf_image_desc_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1020 dissect_ImageQuic(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1022 const uint32_t QuicSize
= tvb_get_letohl(tvb
, offset
);
1025 proto_tree
*ImageQuic_tree
;
1027 ImageQuic_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, QuicSize
+ 4, ett_imageQuic
, NULL
, "QUIC Image");
1029 proto_tree_add_uint(ImageQuic_tree
, hf_spice_quic_image_size
, tvb
, offset
, 4, QuicSize
);
1031 proto_tree_add_item(ImageQuic_tree
, hf_spice_quic_magic
, tvb
, offset
, 4, ENC_ASCII
);
1033 proto_tree_add_item(ImageQuic_tree
, hf_quic_major_version
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1035 proto_tree_add_item(ImageQuic_tree
, hf_quic_minor_version
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1037 proto_tree_add_item(ImageQuic_tree
, hf_quic_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1039 proto_tree_add_item(ImageQuic_tree
, hf_quic_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1041 proto_tree_add_item(ImageQuic_tree
, hf_quic_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1043 proto_tree_add_bytes_format(ImageQuic_tree
, hf_spice_quic_compressed_image_data
, tvb
, offset
, QuicSize
- 20, NULL
, "QUIC compressed image data (%u bytes)", QuicSize
);
1046 return QuicSize
+ 4;
1050 dissect_ImageLZ_common_header(tvbuff_t
*tvb
, proto_tree
*tree
, const uint32_t offset
)
1053 proto_tree_add_item(tree
, hf_spice_lz_magic
, tvb
, offset
, 4, ENC_ASCII
);
1054 proto_tree_add_item(tree
, hf_LZ_major_version
, tvb
, offset
+ 4, 2, ENC_BIG_ENDIAN
);
1055 proto_tree_add_item(tree
, hf_LZ_minor_version
, tvb
, offset
+ 6, 2, ENC_BIG_ENDIAN
);
1061 dissect_ImageLZ_common(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, const bool IsLZ
, const uint32_t size
)
1065 uint32_t end_offset
= offset
+ size
;
1067 offset
+= dissect_ImageLZ_common_header(tvb
, tree
, offset
);
1070 offset
+=3; /* alignment in LZ? Does not exist in GLZ?*/
1072 proto_tree_add_item(tree
, hf_LZ_RGB_type
, tvb
, offset
, 1, ENC_NA
);
1073 type
= tvb_get_uint8(tvb
, offset
);
1075 switch (type
& 0xf) { /* 0xf is the MASK */
1076 case LZ_IMAGE_TYPE_RGB16
:
1077 case LZ_IMAGE_TYPE_RGB24
:
1078 case LZ_IMAGE_TYPE_RGB32
:
1079 proto_tree_add_item(tree
, hf_LZ_width
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1081 proto_tree_add_item(tree
, hf_LZ_height
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1083 proto_tree_add_item(tree
, hf_LZ_stride
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1085 proto_tree_add_item(tree
, hf_LZ_RGB_dict_id
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
1087 proto_tree_add_bytes_format(tree
, hf_spice_lz_rgb_compressed_image_data
, tvb
, offset
, end_offset
- offset
, NULL
, "LZ_RGB compressed image data (%u bytes)", end_offset
- offset
);
1089 case LZ_IMAGE_TYPE_RGBA
:
1092 case LZ_IMAGE_TYPE_XXXA
:
1093 proto_tree_add_item(tree
, hf_LZ_width
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1095 proto_tree_add_item(tree
, hf_LZ_height
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1097 proto_tree_add_item(tree
, hf_LZ_stride
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1099 proto_tree_add_item(tree
, hf_spice_topdown_flag
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1101 proto_tree_add_item(tree
, hf_spice_unknown_bytes
, tvb
, offset
, 12, ENC_NA
);
1105 proto_tree_add_item(tree
, hf_LZ_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1107 proto_tree_add_item(tree
, hf_LZ_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1109 proto_tree_add_item(tree
, hf_LZ_stride
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1111 proto_tree_add_item(tree
, hf_LZ_RGB_dict_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1113 proto_tree_add_bytes_format(tree
, hf_spice_lz_rgb_compressed_image_data
, tvb
, offset
, end_offset
- offset
, NULL
, "LZ_RGB compressed image data (%u bytes)", end_offset
- offset
);
1121 dissect_ImageLZ_JPEG(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1123 proto_tree
*LZ_JPEG_tree
;
1124 const uint32_t LZ_JPEGSize
= tvb_get_letohl(tvb
, offset
);
1126 LZ_JPEG_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, LZ_JPEGSize
+ 4, ett_LZ_JPEG
, NULL
, "LZ_JPEG Image");
1127 proto_tree_add_uint(LZ_JPEG_tree
, hf_spice_lz_jpeg_image_size
, tvb
, offset
, 4, LZ_JPEGSize
);
1129 offset
+= dissect_ImageLZ_common_header(tvb
, LZ_JPEG_tree
, offset
);
1136 dissect_ImageGLZ_RGB(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, const uint32_t size
)
1138 proto_tree
*GLZ_RGB_tree
;
1139 uint32_t GLZ_RGBSize
;
1141 if (size
== 0) { /* if no size was passed to us, need to fetch it. Otherwise, we already have it from the callee */
1142 GLZ_RGBSize
= tvb_get_letohl(tvb
, offset
);
1143 GLZ_RGB_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, GLZ_RGBSize
+ 4, ett_GLZ_RGB
, NULL
, "GLZ_RGB Image");
1144 proto_tree_add_uint(GLZ_RGB_tree
, hf_spice_glz_rgb_image_size
, tvb
, offset
, 4, GLZ_RGBSize
);
1148 GLZ_RGB_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, GLZ_RGBSize
, ett_GLZ_RGB
, NULL
, "GLZ_RGB Image");
1151 dissect_ImageLZ_common(tvb
, GLZ_RGB_tree
, offset
, false, GLZ_RGBSize
);
1153 return GLZ_RGBSize
+ 4;
1157 dissect_ImageLZ_RGB(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1159 proto_tree
*LZ_RGB_tree
;
1160 const uint32_t LZ_RGBSize
= tvb_get_letohl(tvb
, offset
);
1162 LZ_RGB_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, LZ_RGBSize
+ 4, ett_LZ_RGB
, NULL
, "LZ_RGB Image");
1163 proto_tree_add_uint(LZ_RGB_tree
, hf_spice_lz_rgb_image_size
, tvb
, offset
, 4, LZ_RGBSize
);
1166 dissect_ImageLZ_common(tvb
, LZ_RGB_tree
, offset
, true, LZ_RGBSize
);
1168 return LZ_RGBSize
+ 4;
1172 dissect_ImageLZ_PLT(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1174 proto_tree
*LZ_PLT_tree
;
1175 uint32_t LZ_PLTSize
, pal_size
;
1177 const uint32_t current_offset
= offset
;
1179 LZ_PLTSize
= tvb_get_letohl(tvb
, offset
+ 1); /* for some reason, it reports two extra bytes */
1180 LZ_PLT_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, (LZ_PLTSize
- 2)+ 1 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 4, ett_LZ_PLT
, NULL
, "LZ_PLT Image");
1182 proto_tree_add_item(LZ_PLT_tree
, hf_spice_lz_plt_flag
, tvb
, offset
, 1, ENC_NA
); /* TODO: dissect */
1184 proto_tree_add_uint_format_value(LZ_PLT_tree
, hf_spice_lz_plt_image_size
, tvb
, offset
, 4, LZ_PLTSize
, "%u bytes (2 extra bytes?)", LZ_PLTSize
);
1187 proto_tree_add_item_ret_uint(LZ_PLT_tree
, hf_spice_palette_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &pal_size
); /* TODO: not sure it's correct */
1190 dissect_ImageLZ_common_header(tvb
, LZ_PLT_tree
, offset
);
1193 proto_tree_add_item(LZ_PLT_tree
, hf_LZ_PLT_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1195 proto_tree_add_item(LZ_PLT_tree
, hf_LZ_width
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1197 proto_tree_add_item(LZ_PLT_tree
, hf_LZ_height
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1199 proto_tree_add_item(LZ_PLT_tree
, hf_LZ_stride
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1201 proto_tree_add_item(LZ_PLT_tree
, hf_spice_topdown_flag
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1203 proto_tree_add_bytes_format(LZ_PLT_tree
, hf_spice_lz_plt_data
, tvb
, offset
, (LZ_PLTSize
- 2), NULL
, "LZ_PLT data (%u bytes)", (LZ_PLTSize
- 2));
1204 offset
+= (LZ_PLTSize
- 2);
1206 * proto_tree_add_bytes_format(LZ_PLT_tree, tvb, offset, pal_size, "palette (%u bytes)" , pal_size);
1207 * offset += pal_size;
1209 return offset
- current_offset
;
1215 dissect_ImageJPEG_Alpha(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, uint32_t offset
)
1217 proto_tree
*JPEG_tree
;
1219 uint32_t JPEG_Size
, Data_Size
;
1221 /*TODO: const uint8_t flags = tvb_get_uint8(tvb, offset); dissect and present */
1224 JPEG_Size
= tvb_get_letohl(tvb
, offset
);
1227 Data_Size
= tvb_get_letohl(tvb
, offset
);
1230 JPEG_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
- 9, Data_Size
+ 9,
1231 ett_JPEG
, NULL
, "RGB JPEG Image, Alpha channel (%u bytes)", Data_Size
);
1233 jpeg_tvb
= tvb_new_subset_length(tvb
, offset
, JPEG_Size
);
1234 call_dissector(jpeg_handle
, jpeg_tvb
, pinfo
, JPEG_tree
);
1235 offset
+= JPEG_Size
;
1237 dissect_ImageLZ_common(tvb
, tree
, offset
, true, JPEG_Size
);
1239 return Data_Size
+ 9;
1243 dissect_ImageJPEG(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, const uint32_t offset
)
1245 proto_tree
*JPEG_tree
;
1248 const uint32_t JPEG_Size
= tvb_get_letohl(tvb
, offset
);
1249 JPEG_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, JPEG_Size
+ 4, ett_JPEG
, NULL
, "JPEG Image (%u bytes)", JPEG_Size
);
1251 jpeg_tvb
= tvb_new_subset_length(tvb
, offset
+ 4, JPEG_Size
);
1252 call_dissector(jpeg_handle
, jpeg_tvb
, pinfo
, JPEG_tree
);
1254 return JPEG_Size
+ 4;
1257 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
1259 dissect_ImageZLIB_GLZ_stream(tvbuff_t
*tvb
, proto_tree
*ZLIB_GLZ_tree
, packet_info
*pinfo
,
1260 uint32_t offset
, uint32_t ZLIB_GLZSize
, uint32_t ZLIB_uncompSize
)
1263 proto_tree
*Uncomp_tree
;
1264 tvbuff_t
*uncompressed_tvb
;
1266 Uncomp_tree
= proto_tree_add_subtree_format(ZLIB_GLZ_tree
, tvb
, offset
, ZLIB_GLZSize
, ett_Uncomp_tree
, &ti
, "ZLIB stream (%u bytes)", ZLIB_GLZSize
);
1267 uncompressed_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, ZLIB_GLZSize
);
1268 if (uncompressed_tvb
!= NULL
) {
1269 add_new_data_source(pinfo
, uncompressed_tvb
, "Uncompressed GLZ stream");
1270 dissect_ImageGLZ_RGB(uncompressed_tvb
, Uncomp_tree
, 0, ZLIB_uncompSize
);
1272 expert_add_info(pinfo
, ti
, &ei_spice_decompress_error
);
1277 dissect_ImageZLIB_GLZ_stream(tvbuff_t
*tvb
, proto_tree
*ZLIB_GLZ_tree
, packet_info
*pinfo _U_
,
1278 uint32_t offset
, uint32_t ZLIB_GLZSize
, uint32_t ZLIB_uncompSize _U_
)
1280 proto_tree_add_bytes_format(ZLIB_GLZ_tree
, hf_spice_zlib_stream
, tvb
, offset
, ZLIB_GLZSize
, NULL
, "ZLIB stream (%u bytes)", ZLIB_GLZSize
);
1285 dissect_ImageZLIB_GLZ(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, uint32_t offset
)
1287 proto_tree
*ZLIB_GLZ_tree
;
1288 uint32_t ZLIB_GLZSize
, ZLIB_uncompSize
;
1290 ZLIB_uncompSize
= tvb_get_letohl(tvb
, offset
);
1291 ZLIB_GLZSize
= tvb_get_letohl(tvb
, offset
+ 4); /* compressed size */
1293 ZLIB_GLZ_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, ZLIB_GLZSize
+ 8, ett_ZLIB_GLZ
, NULL
, "ZLIB over GLZ Image");
1295 proto_tree_add_item(ZLIB_GLZ_tree
, hf_zlib_uncompress_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1297 proto_tree_add_item(ZLIB_GLZ_tree
, hf_zlib_compress_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1299 dissect_ImageZLIB_GLZ_stream(tvb
, ZLIB_GLZ_tree
, pinfo
, offset
, ZLIB_GLZSize
, ZLIB_uncompSize
);
1302 return ZLIB_GLZSize
+ 8;
1305 /* returns the size of an image, not offset */
1307 dissect_Image(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, uint32_t offset
)
1309 uint32_t ImageSize
= 0;
1310 const uint8_t type
= dissect_ImageDescriptor(tvb
, tree
, offset
);
1312 offset
+= (int)sizeof_ImageDescriptor
;
1315 case SPICE_IMAGE_TYPE_BITMAP
:
1316 ImageSize
= dissect_Pixmap(tvb
, tree
, offset
);
1318 case SPICE_IMAGE_TYPE_QUIC
:
1319 ImageSize
= dissect_ImageQuic(tvb
, tree
, offset
);
1321 case SPICE_IMAGE_TYPE_LZ_PLT
:
1322 ImageSize
= dissect_ImageLZ_PLT(tvb
, tree
, offset
);
1324 case SPICE_IMAGE_TYPE_LZ_RGB
:
1325 ImageSize
= dissect_ImageLZ_RGB(tvb
, tree
, offset
);
1327 case SPICE_IMAGE_TYPE_GLZ_RGB
:
1328 ImageSize
= dissect_ImageGLZ_RGB(tvb
, tree
, offset
, 0);
1330 case SPICE_IMAGE_TYPE_FROM_CACHE
:
1331 proto_tree_add_item(tree
, hf_spice_image_from_cache
, tvb
, offset
, 0, ENC_NA
);
1333 case SPICE_IMAGE_TYPE_SURFACE
:
1334 ImageSize
= 4; /* surface ID */
1335 proto_tree_add_item(tree
, hf_spice_surface_id
, tvb
, offset
, ImageSize
, ENC_LITTLE_ENDIAN
);
1337 case SPICE_IMAGE_TYPE_JPEG
:
1338 ImageSize
= dissect_ImageJPEG(tvb
, tree
, pinfo
, offset
);
1340 case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS
:
1341 proto_tree_add_item(tree
, hf_spice_image_from_cache_lossless
, tvb
, offset
, 0, ENC_NA
);
1343 case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB
:
1344 ImageSize
= dissect_ImageZLIB_GLZ(tvb
, tree
, pinfo
, offset
);
1346 case SPICE_IMAGE_TYPE_JPEG_ALPHA
:
1347 ImageSize
= dissect_ImageJPEG_Alpha(tvb
, tree
, pinfo
, offset
);
1350 proto_tree_add_expert(tree
, pinfo
, &ei_spice_unknown_image_type
, tvb
, offset
, -1);
1353 return sizeof_ImageDescriptor
+ ImageSize
;
1357 dissect_SpiceRect(tvbuff_t
*tvb
, proto_tree
*tree
, const uint32_t offset
, const int32_t id
)
1359 proto_tree
*rect_tree
;
1362 rect
.left
= tvb_get_letohl(tvb
, offset
);
1363 rect
.top
= tvb_get_letohl(tvb
, offset
+ 4);
1364 rect
.right
= tvb_get_letohl(tvb
, offset
+ 8);
1365 rect
.bottom
= tvb_get_letohl(tvb
, offset
+ 12);
1369 rect_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof_SpiceRect
, ett_rect
, NULL
,
1370 "RECT %u: (%u-%u, %u-%u)", id
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1371 } else { /* single rectangle */
1372 rect_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof_SpiceRect
, ett_rect
, NULL
,
1373 "RECT: (%u-%u, %u-%u)", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1376 proto_tree_add_item(rect_tree
, hf_rect_left
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1377 proto_tree_add_item(rect_tree
, hf_rect_top
, tvb
, offset
+ 4, 4, ENC_LITTLE_ENDIAN
);
1378 proto_tree_add_item(rect_tree
, hf_rect_right
, tvb
, offset
+ 8, 4, ENC_LITTLE_ENDIAN
);
1379 proto_tree_add_item(rect_tree
, hf_rect_bottom
, tvb
, offset
+ 12, 4, ENC_LITTLE_ENDIAN
);
1386 rect_is_empty(const SpiceRect r
)
1388 return r
.top
== r
.bottom
|| r
.left
== r
.right
;
1392 dissect_RectList(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1394 proto_tree
*rectlist_tree
;
1396 const uint32_t rectlist_size
= tvb_get_letohl(tvb
, offset
);
1399 rectlist_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 4 + (rectlist_size
* sizeof_SpiceRect
),
1400 ett_rectlist
, NULL
, "RectList (%d rects)", rectlist_size
);
1402 proto_tree_add_item(rectlist_tree
, hf_rectlist_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1404 for (i
= 0; i
< rectlist_size
; i
++ ) {
1405 dissect_SpiceRect(tvb
, rectlist_tree
, offset
, i
);
1406 offset
+= (int)sizeof_SpiceRect
;
1410 return (4 + (rectlist_size
* sizeof_SpiceRect
));
1413 /* returns clip type */
1415 dissect_Clip(tvbuff_t
*tvb
, proto_tree
*tree
, const uint32_t offset
)
1417 proto_tree
*Clip_tree
;
1418 const uint8_t type
= tvb_get_uint8(tvb
, offset
);
1421 Clip_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 1, ett_Clip
, NULL
, "SpiceClip");
1422 proto_tree_add_item(Clip_tree
, hf_Clip_type
, tvb
, offset
, sizeof_Clip
, ENC_LITTLE_ENDIAN
);
1429 dissect_POINT32(tvbuff_t
*tvb
, proto_tree
*tree
, const uint32_t offset
)
1431 proto_tree
*point_tree
;
1432 proto_item
*ret_item
;
1435 point
.x
= tvb_get_letohil(tvb
, offset
);
1436 point
.y
= tvb_get_letohil(tvb
, offset
+ 4);
1438 point_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof(point32_t
), ett_point
, &ret_item
, "POINT (%d, %d)", point
.x
, point
.y
);
1440 proto_tree_add_item(point_tree
, hf_point32_x
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1441 proto_tree_add_item(point_tree
, hf_point32_y
, tvb
, offset
+ 4, 4, ENC_LITTLE_ENDIAN
);
1447 dissect_POINT16(tvbuff_t
*tvb
, proto_tree
*tree
, const uint32_t offset
)
1449 proto_tree
*point16_tree
;
1452 point16
.x
= tvb_get_letohis(tvb
, offset
);
1453 point16
.y
= tvb_get_letohis(tvb
, offset
+ 2);
1456 point16_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof(point16_t
), ett_point16
, NULL
, "POINT16 (%d, %d)", point16
.x
, point16
.y
);
1458 proto_tree_add_item(point16_tree
, hf_point16_x
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1459 proto_tree_add_item(point16_tree
, hf_point16_y
, tvb
, offset
+ 2, 2, ENC_LITTLE_ENDIAN
);
1466 dissect_Mask(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, uint32_t offset
)
1468 proto_item
*ti
, *mask_item
, *point_item
;
1469 proto_tree
*Mask_tree
;
1472 Mask_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof_Mask
, ett_Mask
, &ti
, "Mask");
1473 mask_item
= proto_tree_add_item(Mask_tree
, hf_Mask_flag
, tvb
, offset
, 1, ENC_NA
);
1475 point_item
= dissect_POINT32(tvb
, Mask_tree
, offset
);
1476 offset
+= (int)sizeof(point32_t
);
1477 bitmap
= tvb_get_letohl(tvb
, offset
);
1478 proto_tree_add_item(Mask_tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1482 proto_item_set_len(ti
, sizeof_Mask
+ sizeof_ImageDescriptor
);
1483 dissect_ImageDescriptor(tvb
, Mask_tree
, offset
);
1484 return sizeof_Mask
+ sizeof_ImageDescriptor
;
1487 expert_add_info(pinfo
, mask_item
, &ei_spice_Mask_flag
);
1488 expert_add_info(pinfo
, point_item
, &ei_spice_Mask_point
);
1492 /* returns brush size */
1494 dissect_Brush(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, uint32_t offset
)
1496 proto_tree
*brush_tree
;
1498 const uint8_t type
= tvb_get_uint8(tvb
, offset
);
1499 ti
= proto_tree_add_item(tree
, hf_brush_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1502 case SPICE_BRUSH_TYPE_SOLID
:
1503 proto_item_set_len(ti
, 5);
1504 brush_tree
= proto_item_add_subtree(ti
, ett_brush
);
1506 proto_tree_add_item(brush_tree
, hf_brush_rgb
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1508 case SPICE_BRUSH_TYPE_PATTERN
:
1509 proto_item_set_len(ti
, 17);
1510 brush_tree
= proto_item_add_subtree(ti
, ett_brush
);
1511 proto_tree_add_item(brush_tree
, hf_brush_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1513 /* FIXME: this is supposed to be the offset to the image to be used as the pattern. */
1514 /* For now the hack is that callers check if the returned size was not 5 (therefore SOLID, */
1515 /* it's a pattern and later on dissect the image. That's bad. Really. */
1516 proto_tree_add_item(brush_tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1518 dissect_POINT32(tvb
, brush_tree
, offset
);
1520 case SPICE_BRUSH_TYPE_NONE
:
1523 expert_add_info(pinfo
, ti
, &ei_spice_brush_type
);
1531 dissect_DisplayBase(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
1534 proto_tree
*DisplayBase_tree
;
1537 uint32_t clip_size
= 0;
1539 DisplayBase_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof_DisplayBase
, ett_DisplayBase
, &ti
, "SpiceMsgDisplayBase");
1540 proto_tree_add_item(DisplayBase_tree
, hf_display_surface_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1542 rect
= dissect_SpiceRect(tvb
, DisplayBase_tree
, offset
, -1);
1543 proto_item_append_text(ti
, " - SpiceRect box (%u-%u, %u-%u)",rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1544 offset
+= (int)sizeof_SpiceRect
;
1545 clip_type
= dissect_Clip(tvb
, DisplayBase_tree
, offset
);
1546 offset
+= (int)sizeof_Clip
;
1547 if (clip_type
== SPICE_CLIP_TYPE_RECTS
) {
1548 clip_size
= dissect_RectList(tvb
, DisplayBase_tree
, offset
);
1549 proto_item_set_len(ti
, sizeof_DisplayBase
+ clip_size
);
1550 return sizeof_DisplayBase
+ clip_size
;
1552 return sizeof_DisplayBase
;
1556 #define sizeof_ResourceId 9
1558 dissect_SpiceResourceId(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, uint16_t count
)
1560 proto_tree
*resource_tree
;
1562 resource_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, sizeof_ResourceId
,
1563 ett_cursor_header
, NULL
, "Resource #%d", count
);
1564 proto_tree_add_item(resource_tree
, hf_resource_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1565 proto_tree_add_item(resource_tree
, hf_resource_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1567 return sizeof_ResourceId
;
1571 static const char* get_message_type_string(const uint16_t message_type
, const spice_conversation_t
*spice_info
,
1572 const bool client_message
)
1575 if (message_type
< SPICE_FIRST_AVAIL_MESSAGE
) { /* this is a common message */
1576 if (client_message
) {
1577 return val_to_str_const(message_type
, spice_msgc_vs
, "Unknown client message");
1579 return val_to_str_const(message_type
, spice_msg_vs
, "Unknown server message");
1583 switch (spice_info
->channel_type
) {
1584 case SPICE_CHANNEL_MAIN
:
1585 if (client_message
) {
1586 return val_to_str_const(message_type
, spice_msgc_main_vs
, "Unknown main channel client message");
1588 return val_to_str_const(message_type
, spice_msg_main_vs
, "Unknown main channel server message");
1591 case SPICE_CHANNEL_DISPLAY
:
1592 if (client_message
) {
1593 return val_to_str_const(message_type
, spice_msgc_display_vs
, "Unknown display channel client message");
1595 return val_to_str_const(message_type
, spice_msg_display_vs
, "Unknown display channel server message");
1598 case SPICE_CHANNEL_INPUTS
:
1599 if (client_message
) {
1600 return val_to_str_const(message_type
, spice_msgc_inputs_vs
, "Unknown inputs channel client message");
1602 return val_to_str_const(message_type
, spice_msg_inputs_vs
, "Unknown inputs channel server message");
1605 case SPICE_CHANNEL_CURSOR
:
1606 if (client_message
) {
1607 return val_to_str_const(message_type
, NULL
, "Unknown cursor channel client message");
1609 return val_to_str_const(message_type
, spice_msg_cursor_vs
, "Unknown cursor channel server message");
1612 case SPICE_CHANNEL_PLAYBACK
:
1613 return val_to_str_const(message_type
, spice_msg_playback_vs
, "Unknown playback channel server message");
1614 case SPICE_CHANNEL_RECORD
:
1615 if (client_message
) {
1616 return val_to_str_const(message_type
, spice_msgc_record_vs
, "Unknown record channel client message");
1618 return val_to_str_const(message_type
, spice_msg_record_vs
, "Unknown record channel server message");
1621 case SPICE_CHANNEL_TUNNEL
:
1622 if (client_message
) {
1623 return val_to_str_const(message_type
, spice_msgc_tunnel_vs
, "Unknown tunnel channel client message");
1625 return val_to_str_const(message_type
, spice_msg_tunnel_vs
, "Unknown tunnel channel server message");
1628 case SPICE_CHANNEL_SMARTCARD
:
1629 if (client_message
) {
1630 return val_to_str_const(message_type
, spice_msgc_smartcard_vs
, "Unknown smartcard channel client message");
1632 return val_to_str_const(message_type
, spice_msg_smartcard_vs
, "Unknown smartcard channel server message");
1635 case SPICE_CHANNEL_USBREDIR
:
1636 if (client_message
) {
1637 const value_string
*values
= NULL
;
1638 if (message_type
< SPICE_MSG_END_SPICEVMC
)
1639 values
= spice_msg_spicevmc_vs
;
1640 return val_to_str_const(message_type
, values
, "Unknown usbredir channel client message");
1642 const value_string
*values
= NULL
;
1643 if (message_type
< SPICE_MSGC_END_SPICEVMC
)
1644 values
= spice_msgc_spicevmc_vs
;
1645 return val_to_str_const(message_type
, values
, "Unknown usbredir channel server message");
1651 return "Unknown message";
1654 dissect_spice_mini_data_header(tvbuff_t
*tvb
, proto_tree
*tree
, const spice_conversation_t
*spice_info
,
1655 const bool client_message
, const uint16_t message_type
, uint32_t offset
)
1657 proto_tree
* subtree
;
1660 subtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 2, ett_common_client_message
, NULL
,
1661 "Message type: %s (%d)", get_message_type_string(message_type
, spice_info
, client_message
), message_type
);
1662 proto_tree_add_item(subtree
, hf_message_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1664 proto_tree_add_item(tree
, hf_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1669 dissect_spice_data_header(tvbuff_t
*tvb
, proto_tree
*tree
, const spice_conversation_t
*spice_info
,
1670 const bool client_message
, const uint16_t message_type
, proto_item
** msgtype_item
, uint32_t *sublist_size
, uint32_t offset
)
1672 proto_tree
* subtree
;
1673 *sublist_size
= tvb_get_letohl(tvb
, offset
+ 14);
1676 proto_tree_add_item(tree
, hf_serial
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1678 subtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 2, ett_common_client_message
, NULL
,
1679 "Message type: %s (%d)", get_message_type_string(message_type
, spice_info
, client_message
), message_type
);
1680 *msgtype_item
= proto_tree_add_item(subtree
, hf_message_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1682 proto_tree_add_item(tree
, hf_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1684 proto_tree_add_item(tree
, hf_data_sublist
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1690 dissect_spice_common_client_messages(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
1692 switch (message_type
) {
1693 case SPICE_MSGC_ACK_SYNC
:
1694 proto_tree_add_item(tree
, hf_red_set_ack_generation
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1697 case SPICE_MSGC_ACK
:
1699 case SPICE_MSGC_PONG
:
1700 proto_tree_add_item(tree
, hf_red_ping_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1702 proto_tree_add_item(tree
, hf_red_timestamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1706 case SPICE_MSGC_MIGRATE_FLUSH_MARK:
1707 case SPICE_MSGC_MIGRATE_DATA:
1708 case SPICE_MSGC_DISCONNECTING:
1711 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown common client message - cannot dissect");
1719 dissect_spice_common_server_messages(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
,
1720 uint32_t offset
, const uint32_t total_message_size
)
1722 uint32_t message_len
;
1724 switch (message_type
) {
1726 case SPICE_MSG_MIGRATE:
1727 case SPICE_MSG_MIGRATE_DATA:
1728 case SPICE_MSG_WAIT_FOR_CHANNELS:
1729 case SPICE_MSG_DISCONNECTING:
1731 case SPICE_MSG_SET_ACK
:
1732 proto_tree_add_item(tree
, hf_red_set_ack_generation
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1734 proto_tree_add_item(tree
, hf_red_set_ack_window
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1737 case SPICE_MSG_PING
:
1738 proto_tree_add_item(tree
, hf_red_ping_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1740 proto_tree_add_item(tree
, hf_red_timestamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1742 if (total_message_size
> 12) {
1743 proto_tree_add_bytes_format(tree
, hf_spice_ping_data
, tvb
, offset
, total_message_size
- 12,
1744 NULL
, "PING DATA (%d bytes)", total_message_size
- 12);
1745 offset
+= (total_message_size
- 12);
1748 case SPICE_MSG_NOTIFY
:
1749 proto_tree_add_item(tree
, hf_red_timestamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1751 proto_tree_add_item(tree
, hf_severity
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1753 proto_tree_add_item(tree
, hf_visibility
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1755 /*TODO: based on severity, dissect the error code */
1756 proto_tree_add_item(tree
, hf_notify_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1758 message_len
= tvb_get_letohl(tvb
, offset
);
1759 proto_tree_add_item(tree
, hf_notify_message_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1761 proto_tree_add_item(tree
, hf_notify_message
, tvb
, offset
, message_len
+ 1, ENC_ASCII
);
1762 offset
+= (message_len
+ 1);
1765 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown common server message - cannot dissect");
1772 dissect_spice_record_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
1774 proto_tree
*record_tree
;
1776 switch (message_type
) {
1777 case SPICE_MSGC_RECORD_MODE
:
1778 record_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 8, ett_record_client
, NULL
, "Client RECORD_MODE message"); /* size is incorrect, fixed later */
1779 proto_tree_add_item(record_tree
, hf_audio_timestamp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1781 proto_tree_add_item(record_tree
, hf_audio_mode
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1783 /* TODO - mode dependent, there may be more data here */
1786 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown record client message - cannot dissect");
1794 dissect_spice_display_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
1796 switch (message_type
) {
1797 case SPICE_MSGC_DISPLAY_INIT
:
1798 proto_tree_add_item(tree
, hf_spice_display_init_cache_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1800 proto_tree_add_item(tree
, hf_spice_display_init_cache_size
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1802 proto_tree_add_item(tree
, hf_spice_display_init_glz_dict_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1804 proto_tree_add_item(tree
, hf_spice_display_init_dict_window_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1808 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown display client message - cannot dissect");
1816 dissect_spice_display_server(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
1818 uint32_t data_size
, displayBaseLen
;
1824 switch (message_type
) {
1825 case SPICE_MSG_DISPLAY_MODE
:
1826 proto_tree_add_item(tree
, hf_spice_display_mode_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1828 proto_tree_add_item(tree
, hf_spice_display_mode_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1830 proto_tree_add_item(tree
, hf_spice_display_mode_depth
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1833 case SPICE_MSG_DISPLAY_MARK
:
1834 proto_tree_add_item(tree
, hf_spice_display_mark_message
, tvb
, offset
, 0, ENC_NA
);
1836 case SPICE_MSG_DISPLAY_RESET
:
1837 proto_tree_add_item(tree
, hf_spice_display_reset_message
, tvb
, offset
, 0, ENC_NA
);
1839 case SPICE_MSG_DISPLAY_INVAL_LIST
:
1840 proto_tree_add_item(tree
, hf_display_inval_list_count
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1841 count
= tvb_get_letohs(tvb
, offset
);
1843 for (i
= 0; i
< count
; i
++) {
1844 offset
+= dissect_SpiceResourceId(tvb
, tree
, offset
, i
+ 1);
1847 case SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND
:
1848 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1849 offset
+= displayBaseLen
;
1850 /* TODO: Flag 1 byte, Alpha 1 byte dissection*/
1852 proto_tree_add_item(tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1854 dissect_SpiceRect(tvb
, tree
, offset
, -1);
1855 offset
+= (int)sizeof_SpiceRect
;
1856 data_size
= dissect_Image(tvb
, tree
, pinfo
, offset
);
1857 offset
+= data_size
;
1859 case SPICE_MSG_DISPLAY_DRAW_BLACKNESS
:
1860 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1861 offset
+= displayBaseLen
;
1862 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1864 case SPICE_MSG_DISPLAY_COPY_BITS
:
1865 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1866 offset
+= displayBaseLen
;
1867 dissect_POINT32(tvb
, tree
, offset
);
1868 offset
+= (int)sizeof(point32_t
);
1870 case SPICE_MSG_DISPLAY_DRAW_WHITENESS
:
1871 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1872 offset
+= displayBaseLen
;
1873 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1875 case SPICE_MSG_DISPLAY_DRAW_INVERS
:
1876 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1877 offset
+= displayBaseLen
;
1878 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1880 case SPICE_MSG_DISPLAY_DRAW_FILL
:
1881 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1882 offset
+= displayBaseLen
;
1883 data_size
= dissect_Brush(tvb
, pinfo
, tree
, offset
);
1884 offset
+= data_size
;
1886 proto_tree_add_item(tree
, hf_display_rop_descriptor
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1889 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1891 if (data_size
!= 5) { /* if it's not a SOLID brush, it's a PATTERN, dissect its image descriptor */
1892 offset
+= dissect_Image(tvb
, tree
, pinfo
, offset
);
1895 case SPICE_MSG_DISPLAY_DRAW_TRANSPARENT
:
1896 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1897 offset
+= displayBaseLen
;
1898 proto_tree_add_item(tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1901 dissect_SpiceRect(tvb
, tree
, offset
, -1);
1902 offset
+= (int)sizeof_SpiceRect
;
1903 proto_tree_add_item(tree
, hf_tranparent_src_color
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1905 proto_tree_add_item(tree
, hf_tranparent_true_color
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1907 data_size
= dissect_Image(tvb
, tree
, pinfo
, offset
);
1908 offset
+= data_size
;
1910 case SPICE_MSG_DISPLAY_DRAW_BLEND
:
1911 case SPICE_MSG_DISPLAY_DRAW_COPY
:
1912 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1913 offset
+= displayBaseLen
;
1914 /* SpiceImage *src_bitmap */
1915 proto_tree_add_item(tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1919 dissect_SpiceRect(tvb
, tree
, offset
, -1);
1920 offset
+= (int)sizeof_SpiceRect
;
1922 proto_tree_add_item(tree
, hf_display_rop_descriptor
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1925 proto_tree_add_item(tree
, hf_display_scale_mode
, tvb
, offset
, 1, ENC_NA
);
1928 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1930 data_size
= dissect_Image(tvb
, tree
, pinfo
, offset
);
1931 offset
+= data_size
;
1933 case SPICE_MSG_DISPLAY_DRAW_ROP3
:
1934 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1935 offset
+= displayBaseLen
;
1936 /* SpiceImage *src_bitmap */
1937 proto_tree_add_item(tree
, hf_ref_image
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1941 dissect_SpiceRect(tvb
, tree
, offset
, -1);
1942 offset
+= (int)sizeof_SpiceRect
;
1944 data_size
= dissect_Brush(tvb
, pinfo
, tree
, offset
);
1945 offset
+= data_size
;
1947 proto_tree_add_item(tree
, hf_spice_rop3
, tvb
, offset
, 1, ENC_NA
);
1949 proto_tree_add_item(tree
, hf_spice_scale_mode
, tvb
, offset
, 1, ENC_NA
);
1952 offset
+= dissect_Mask(tvb
, pinfo
, tree
, offset
);
1953 /*FIXME - need to understand what the rest of the message contains. */
1954 data_size
= dissect_Image(tvb
, tree
, pinfo
, offset
);
1955 offset
+= data_size
;
1957 case SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES
:
1959 case SPICE_MSG_DISPLAY_DRAW_TEXT
:
1960 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1961 offset
+= displayBaseLen
;
1962 proto_tree_add_item(tree
, hf_ref_string
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1965 r
= dissect_SpiceRect(tvb
, tree
, offset
, -1);
1966 offset
+= (int)sizeof_SpiceRect
;
1967 if (!rect_is_empty(r
)) {
1968 data_size
= dissect_Brush(tvb
, pinfo
, tree
, offset
);
1969 offset
+= data_size
;
1971 proto_tree_add_item(tree
, hf_display_text_fore_mode
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1973 proto_tree_add_item(tree
, hf_display_text_back_mode
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1976 proto_tree_add_item(tree
, hf_num_glyphs
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
1978 proto_tree_add_item(tree
, hf_spice_glyph_flags
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1979 /*TODO finish dissecting glyph list */
1981 case SPICE_MSG_DISPLAY_DRAW_STROKE
:
1982 displayBaseLen
= dissect_DisplayBase(tvb
, tree
, offset
);
1983 offset
+= displayBaseLen
;
1984 /*TODO: complete and correct dissection */
1987 case SPICE_MSG_DISPLAY_STREAM_CLIP
:
1988 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1990 clip_type
= dissect_Clip(tvb
, tree
, offset
);
1991 offset
+= (int)sizeof_Clip
;
1992 if (clip_type
== SPICE_CLIP_TYPE_RECTS
) {
1993 offset
+= dissect_RectList(tvb
, tree
, offset
);
1996 case SPICE_MSG_DISPLAY_STREAM_CREATE
:
1997 proto_tree_add_item(tree
, hf_display_surface_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1999 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2001 proto_tree_add_item(tree
, hf_display_stream_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2003 proto_tree_add_item(tree
, hf_display_stream_codec_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2005 proto_tree_add_item(tree
, hf_display_stream_stamp
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
2007 proto_tree_add_item(tree
, hf_display_stream_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2009 proto_tree_add_item(tree
, hf_display_stream_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2011 proto_tree_add_item(tree
, hf_display_stream_src_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2013 proto_tree_add_item(tree
, hf_display_stream_src_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2015 dissect_SpiceRect(tvb
, tree
, offset
, -1);
2016 offset
+= (int)sizeof_SpiceRect
;
2017 clip_type
= dissect_Clip(tvb
, tree
, offset
);
2018 offset
+= (int)sizeof_Clip
;
2019 if (clip_type
== SPICE_CLIP_TYPE_RECTS
) {
2020 offset
+= dissect_RectList(tvb
, tree
, offset
);
2023 case SPICE_MSG_DISPLAY_STREAM_DATA
:
2024 data_size
= tvb_get_letohl(tvb
, offset
+ 8);
2025 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2027 proto_tree_add_item(tree
, hf_multi_media_time
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2029 proto_tree_add_item(tree
, hf_display_stream_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2031 proto_tree_add_bytes_format(tree
, hf_spice_stream_data
, tvb
, offset
, data_size
, NULL
, "Stream data");
2032 jpeg_tvb
= tvb_new_subset_length(tvb
, offset
, data_size
);
2033 call_dissector(jpeg_handle
, jpeg_tvb
, pinfo
, tree
);
2034 offset
+= data_size
;
2036 case SPICE_MSG_DISPLAY_STREAM_DESTROY
:
2037 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2040 case SPICE_MSG_DISPLAY_STREAM_DATA_SIZED
:
2041 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2043 proto_tree_add_item(tree
, hf_multi_media_time
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2045 proto_tree_add_item(tree
, hf_display_stream_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2047 proto_tree_add_item(tree
, hf_display_stream_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2049 dissect_SpiceRect(tvb
, tree
, offset
, -1);
2050 offset
+= (int)sizeof_SpiceRect
;
2051 proto_tree_add_item(tree
, hf_display_stream_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2054 case SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL
:
2056 case SPICE_MSG_DISPLAY_SURFACE_CREATE
:
2057 proto_tree_add_item(tree
, hf_display_surface_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2059 proto_tree_add_item(tree
, hf_display_surface_width
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2061 proto_tree_add_item(tree
, hf_display_surface_height
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2063 proto_tree_add_item(tree
, hf_display_surface_format
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2065 proto_tree_add_item(tree
, hf_display_surface_flags
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2068 case SPICE_MSG_DISPLAY_SURFACE_DESTROY
:
2069 proto_tree_add_item(tree
, hf_display_surface_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2072 case SPICE_MSG_DISPLAY_MONITORS_CONFIG
:
2073 proto_tree_add_item(tree
, hf_display_monitor_config_count
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2074 count
= tvb_get_letohs(tvb
, offset
);
2076 proto_tree_add_item(tree
, hf_display_monitor_config_max_allowed
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2078 for (i
= 0; i
< count
; i
++) {
2079 offset
= dissect_SpiceHead(tvb
, tree
, offset
, i
);
2082 case SPICE_MSG_DISPLAY_DRAW_COMPOSITE
:
2084 case SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT
:
2085 proto_tree_add_item(tree
, hf_display_stream_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2087 proto_tree_add_item(tree
, hf_display_stream_report_unique_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2089 proto_tree_add_item(tree
, hf_display_stream_report_max_window_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2091 proto_tree_add_item(tree
, hf_display_stream_report_timeout
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2095 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown display server message - cannot dissect");
2102 dissect_spice_playback_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
,
2103 uint32_t message_size
, spice_conversation_t
*spice_info
, uint32_t offset
)
2105 uint8_t num_channels
, i
;
2106 proto_tree
* subtree
;
2108 switch (message_type
) {
2109 case SPICE_MSG_PLAYBACK_DATA
:
2110 proto_tree_add_item(tree
, hf_audio_timestamp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2112 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, message_size
- 4, ENC_NA
);
2113 offset
+= (message_size
- 4);
2115 case SPICE_MSG_PLAYBACK_MODE
:
2116 proto_tree_add_item(tree
, hf_audio_timestamp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2118 spice_info
->playback_mode
= tvb_get_letohs(tvb
, offset
);
2119 proto_tree_add_item(tree
, hf_audio_mode
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2121 /* TODO - mode dependent, there may be more data here */
2123 case SPICE_MSG_PLAYBACK_START
:
2124 proto_tree_add_item(tree
, hf_audio_channels
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2126 proto_tree_add_item(tree
, hf_audio_format
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2128 proto_tree_add_item(tree
, hf_audio_frequency
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2130 proto_tree_add_item(tree
, hf_audio_timestamp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2133 case SPICE_MSG_PLAYBACK_STOP
:
2135 case SPICE_MSG_PLAYBACK_VOLUME
:
2136 num_channels
= tvb_get_uint8(tvb
, offset
);
2137 proto_tree_add_item(tree
, hf_audio_channels
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2139 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, 2 * num_channels
, ett_record_server
, NULL
, "Channel volume array");
2140 for (i
= 0; i
< num_channels
; i
++) {
2141 proto_tree_add_item(subtree
, hf_audio_volume
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2145 case SPICE_MSG_PLAYBACK_MUTE
:
2146 proto_tree_add_item(tree
, hf_audio_mute
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2149 case SPICE_MSG_PLAYBACK_LATENCY
:
2150 proto_tree_add_item(tree
, hf_audio_latency
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2154 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown playback server message - cannot dissect");
2161 dissect_spice_cursor_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2163 uint32_t RedCursorSize
;
2165 switch (message_type
) {
2166 case SPICE_MSG_CURSOR_INIT
:
2167 dissect_POINT16(tvb
, tree
, offset
);
2168 offset
+= (int)sizeof(point16_t
);
2169 proto_tree_add_item(tree
, hf_cursor_trail_len
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2171 proto_tree_add_item(tree
, hf_cursor_trail_freq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2173 proto_tree_add_item(tree
, hf_cursor_trail_visible
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2175 RedCursorSize
= dissect_RedCursor(tvb
, tree
, offset
);
2176 offset
+= RedCursorSize
;
2178 case SPICE_MSG_CURSOR_RESET
:
2180 case SPICE_MSG_CURSOR_SET
:
2181 dissect_POINT16(tvb
, tree
, offset
);
2182 offset
+= (int)sizeof(point16_t
);
2183 offset
+=1; /*TODO flags */
2184 RedCursorSize
= dissect_RedCursor(tvb
, tree
, offset
);
2185 offset
+= RedCursorSize
;
2187 case SPICE_MSG_CURSOR_MOVE
:
2188 dissect_POINT16(tvb
, tree
, offset
);
2189 offset
+= (int)sizeof(point16_t
);
2191 case SPICE_MSG_CURSOR_HIDE
:
2193 case SPICE_MSG_CURSOR_TRAIL
:
2194 proto_tree_add_item(tree
, hf_cursor_trail_len
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2196 proto_tree_add_item(tree
, hf_cursor_trail_freq
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2199 case SPICE_MSG_CURSOR_INVAL_ONE
:
2200 proto_tree_add_item(tree
, hf_cursor_id
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
2203 case SPICE_MSG_CURSOR_INVAL_ALL
:
2206 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown cursor server message - cannot dissect");
2213 dissect_spice_record_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2215 uint8_t num_channels
, i
;
2216 proto_tree
* subtree
;
2218 switch (message_type
) {
2219 case SPICE_MSG_RECORD_STOP
:
2221 case SPICE_MSG_RECORD_VOLUME
:
2222 num_channels
= tvb_get_uint8(tvb
, offset
);
2223 proto_tree_add_item(tree
, hf_audio_channels
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2225 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, 2 * num_channels
, ett_record_server
, NULL
, "Volume Array");
2226 for (i
= 0; i
< num_channels
; i
++) {
2227 proto_tree_add_item(subtree
, hf_audio_volume
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2231 case SPICE_MSG_RECORD_MUTE
:
2232 proto_tree_add_item(tree
, hf_audio_mute
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2236 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown record server message - cannot dissect");
2243 dissect_spice_agent_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint32_t message_type
, proto_item
* msgtype_item
, uint32_t message_len
, uint32_t offset
)
2245 proto_tree
*agent_tree
;
2246 uint32_t n_monitors
= 0, i
;
2248 switch (message_type
) {
2249 case VD_AGENT_MOUSE_STATE
:
2250 dissect_POINT32(tvb
, tree
, offset
);
2251 offset
+= (int)sizeof(point32_t
);
2252 proto_tree_add_item(tree
, hf_vd_agent_buttons
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2254 proto_tree_add_item(tree
, hf_mouse_display_id
, tvb
, offset
, 1, ENC_NA
);
2257 case VD_AGENT_MONITORS_CONFIG
:
2258 n_monitors
= tvb_get_letohl(tvb
, offset
);
2259 proto_tree_add_item(tree
, hf_agent_num_monitors
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2261 proto_tree_add_item(tree
, hf_vd_agent_monitors_config_flag_use_pos
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2263 for (i
= 0; i
< n_monitors
; i
++) {
2264 offset
= dissect_AgentMonitorConfig(tvb
, tree
, offset
, i
);
2267 case VD_AGENT_REPLY
:
2268 proto_tree_add_item(tree
, hf_vd_agent_reply_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2270 proto_tree_add_item(tree
, hf_vd_agent_reply_error
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2273 case VD_AGENT_CLIPBOARD
:
2274 /*ti = */proto_tree_add_item(tree
, hf_spice_vd_agent_clipboard_message
, tvb
, offset
, message_len
, ENC_NA
);
2275 /* TODO: display string
2276 agent_tree = proto_item_add_subtree(ti, ett_spice_agent);
2278 offset
+= message_len
;
2280 case VD_AGENT_DISPLAY_CONFIG
:
2281 proto_tree_add_item(tree
, hf_spice_vd_agent_display_config_message
, tvb
, offset
, 4, ENC_NA
);
2284 case VD_AGENT_ANNOUNCE_CAPABILITIES
:
2285 proto_tree_add_item(tree
, hf_vd_agent_caps_request
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2287 proto_tree_add_item(tree
, hf_vd_agent_cap_mouse_state
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2288 proto_tree_add_item(tree
, hf_vd_agent_cap_monitors_config
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2289 proto_tree_add_item(tree
, hf_vd_agent_cap_reply
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2290 proto_tree_add_item(tree
, hf_vd_agent_cap_clipboard
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2291 proto_tree_add_item(tree
, hf_vd_agent_cap_display_config
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2292 proto_tree_add_item(tree
, hf_vd_agent_cap_clipboard_by_demand
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2293 proto_tree_add_item(tree
, hf_vd_agent_cap_clipboard_selection
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2294 proto_tree_add_item(tree
, hf_vd_agent_cap_sparse_monitors_config
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2295 proto_tree_add_item(tree
, hf_vd_agent_cap_guest_lineend_lf
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2296 proto_tree_add_item(tree
, hf_vd_agent_cap_guest_lineend_crlf
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2299 case VD_AGENT_CLIPBOARD_GRAB
:
2300 agent_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 4, ett_spice_agent
, NULL
, "VD_AGENT_CLIPBOARD_GRAB message");
2301 proto_tree_add_item(agent_tree
, hf_agent_clipboard_selection
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2303 proto_tree_add_item(agent_tree
, hf_spice_reserved
, tvb
, offset
, 3, ENC_NA
);
2306 case VD_AGENT_CLIPBOARD_REQUEST
:
2307 agent_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 8, ett_spice_agent
, NULL
, "VD_AGENT_CLIPBOARD_REQUEST message");
2308 proto_tree_add_item(agent_tree
, hf_agent_clipboard_selection
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2310 proto_tree_add_item(agent_tree
, hf_spice_reserved
, tvb
, offset
, 3, ENC_NA
);
2312 proto_tree_add_item(agent_tree
, hf_agent_clipboard_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2315 case VD_AGENT_CLIPBOARD_RELEASE
:
2316 proto_tree_add_item(tree
, hf_spice_vd_agent_clipboard_release_message
, tvb
, offset
, 0, ENC_NA
);
2319 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown agent message (%u) - cannot dissect", message_type
);
2325 /* note that the size property is necessary here because the protocol uses
2326 * uint32 in the INIT message, and flags16 in the MOUSE_MODE message
2329 dissect_supported_mouse_modes(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
, uint32_t size
)
2332 proto_tree
*sub_tree
;
2333 int hf
= hf_supported_mouse_modes
;
2336 hf
= hf_supported_mouse_modes_flags
;
2338 ti
= proto_tree_add_item(tree
, hf
, tvb
, offset
, size
, ENC_LITTLE_ENDIAN
);
2339 sub_tree
= proto_item_add_subtree(ti
, ett_main_client
);
2341 proto_tree_add_item(sub_tree
, hf_supported_mouse_modes_flag_client
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2342 proto_tree_add_item(sub_tree
, hf_supported_mouse_modes_flag_server
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2344 return offset
+ size
;
2348 dissect_spice_main_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2350 uint32_t num_channels
, i
, agent_msg_type
, agent_msg_len
, name_len
, data_size
;
2351 proto_tree
*subtree
= NULL
;
2353 switch (message_type
) {
2354 case SPICE_MSG_MAIN_MIGRATE_BEGIN
:
2355 case SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST
:
2356 case SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS
:
2357 proto_tree_add_item(tree
, hf_migrate_dest_port
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2359 proto_tree_add_item(tree
, hf_migrate_dest_sport
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2361 data_size
= tvb_get_letohl(tvb
, offset
);
2363 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, data_size
, ENC_NA
);
2364 offset
+= data_size
;
2365 data_size
= tvb_get_letohl(tvb
, offset
);
2367 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, data_size
, ENC_NA
);
2368 offset
+= data_size
;
2369 if (message_type
== SPICE_MSG_MAIN_MIGRATE_BEGIN_SEAMLESS
) {
2370 proto_tree_add_item(tree
, hf_migrate_src_mig_version
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2374 case SPICE_MSG_MAIN_MIGRATE_CANCEL
:
2376 case SPICE_MSG_MAIN_INIT
:
2377 proto_tree_add_item(tree
, hf_session_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2379 proto_tree_add_item(tree
, hf_display_channels_hint
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2381 dissect_supported_mouse_modes(tvb
, tree
, offset
, 4);
2383 proto_tree_add_item(tree
, hf_current_mouse_mode
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2385 proto_tree_add_item(tree
, hf_agent_connected
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2387 proto_tree_add_item(tree
, hf_agent_tokens
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2389 proto_tree_add_item(tree
, hf_multi_media_time
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2391 proto_tree_add_item(tree
, hf_ram_hint
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2394 case SPICE_MSG_MAIN_CHANNELS_LIST
:
2395 num_channels
= tvb_get_letohl(tvb
, offset
);
2396 proto_tree_add_item(tree
, hf_main_num_channels
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2398 subtree
= proto_tree_add_subtree(tree
, tvb
, offset
, 2 * num_channels
, ett_main_client
, NULL
, "Channel Array");
2399 for (i
= 0; i
< num_channels
; i
++ ) {
2400 proto_tree
*subsubtree
;
2402 subsubtree
= proto_tree_add_subtree_format(subtree
, tvb
, offset
, 2, ett_main_client
, NULL
, "channels[%u]: %s", i
,
2403 val_to_str_const(tvb_get_uint8(tvb
, offset
), channel_types_vs
, "Unknown"));
2405 proto_tree_add_item(subsubtree
, hf_channel_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2407 proto_tree_add_item(subsubtree
, hf_channel_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2411 case SPICE_MSG_MAIN_MOUSE_MODE
:
2412 dissect_supported_mouse_modes(tvb
, tree
, offset
, 2);
2414 proto_tree_add_item(tree
, hf_current_mouse_mode_flags
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2417 case SPICE_MSG_MAIN_MULTI_MEDIA_TIME
:
2418 proto_tree_add_item(tree
, hf_multi_media_time
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2421 case SPICE_MSG_MAIN_AGENT_DISCONNECTED
:
2422 proto_tree_add_item(tree
, hf_error_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2425 case SPICE_MSG_MAIN_AGENT_DATA
:
2426 proto_tree_add_item(tree
, hf_agent_protocol
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2428 proto_tree_add_item(tree
, hf_agent_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2429 agent_msg_type
= tvb_get_letohl(tvb
, offset
);
2431 proto_tree_add_item(tree
, hf_agent_opaque
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
2433 proto_tree_add_item(tree
, hf_agent_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2434 agent_msg_len
= tvb_get_letohl(tvb
, offset
);
2436 offset
= dissect_spice_agent_message(tvb
, pinfo
, tree
, agent_msg_type
, msgtype_item
, agent_msg_len
, offset
);
2438 case SPICE_MSG_MAIN_AGENT_TOKEN
:
2439 case SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS
:
2440 proto_tree_add_item(tree
, hf_agent_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2443 case SPICE_MSG_MAIN_NAME
:
2444 name_len
= tvb_get_letohl(tvb
, offset
);
2445 proto_tree_add_item(tree
, hf_main_name_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2447 proto_tree_add_item(tree
, hf_main_name
, tvb
, offset
, name_len
, ENC_ASCII
);
2450 case SPICE_MSG_MAIN_UUID
:
2451 proto_tree_add_item(tree
, hf_main_uuid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
);
2454 case SPICE_MSG_MAIN_MIGRATE_END
:
2456 case SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK
:
2458 case SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_NACK
:
2461 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown main server message - cannot dissect");
2468 dissect_spice_main_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2470 proto_tree
*main_tree
;
2471 uint32_t agent_msg_type
, agent_msg_len
;
2473 switch (message_type
) {
2474 case SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST
:
2475 proto_tree_add_item(tree
, hf_current_mouse_mode_flags
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2478 case SPICE_MSGC_MAIN_ATTACH_CHANNELS
:
2480 case SPICE_MSGC_MAIN_AGENT_START
:
2481 main_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 4, ett_main_client
, NULL
, "Client AGENT_START message");
2482 proto_tree_add_item(main_tree
, hf_main_client_agent_tokens
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2485 case SPICE_MSGC_MAIN_AGENT_DATA
:
2486 main_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 24, ett_main_client
, NULL
, "Client AGENT_DATA message");
2487 proto_tree_add_item(main_tree
, hf_agent_protocol
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2489 proto_tree_add_item(main_tree
, hf_agent_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2490 agent_msg_type
= tvb_get_letohl(tvb
, offset
);
2492 proto_tree_add_item(main_tree
, hf_agent_opaque
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
2494 proto_tree_add_item(main_tree
, hf_agent_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2495 agent_msg_len
= tvb_get_letohl(tvb
, offset
);
2497 offset
= dissect_spice_agent_message(tvb
, pinfo
, main_tree
, agent_msg_type
, msgtype_item
, agent_msg_len
, offset
);
2500 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown main client message - cannot dissect");
2507 dissect_spice_keyboard_modifiers(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
2510 proto_tree
*subtree
;
2512 ti
= proto_tree_add_item(tree
, hf_keyboard_modifiers
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2513 subtree
= proto_item_add_subtree(ti
, ett_link_caps
);
2515 proto_tree_add_item(subtree
, hf_keyboard_modifier_scroll_lock
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2516 proto_tree_add_item(subtree
, hf_keyboard_modifier_num_lock
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2517 proto_tree_add_item(subtree
, hf_keyboard_modifier_caps_lock
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2522 dissect_buttons_state(tvbuff_t
*tvb
, proto_tree
*tree
, uint32_t offset
)
2525 proto_tree
*subtree
;
2527 ti
= proto_tree_add_item(tree
, hf_buttons_state
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
2528 subtree
= proto_item_add_subtree(ti
, ett_inputs_client
);
2530 static int *const hf_buttons_mask
[] = {
2531 &hf_button_mask_left
,
2532 &hf_button_mask_middle
,
2533 &hf_button_mask_right
,
2534 &hf_button_mask_reserved_bits
,
2538 proto_tree_add_bitmask_list(subtree
, tvb
, offset
, 2, hf_buttons_mask
, ENC_LITTLE_ENDIAN
);
2544 dissect_spice_inputs_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2546 proto_tree
*inputs_tree
;
2548 switch (message_type
) {
2549 case SPICE_MSGC_INPUTS_KEY_DOWN
:
2550 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 4, ett_inputs_client
, NULL
, "Client KEY_DOWN message");
2551 proto_tree_add_item(inputs_tree
, hf_keyboard_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2554 case SPICE_MSGC_INPUTS_KEY_UP
:
2555 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 4, ett_inputs_client
, NULL
, "Client KEY_UP message");
2556 proto_tree_add_item(inputs_tree
, hf_keyboard_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2559 case SPICE_MSGC_INPUTS_KEY_MODIFIERS
:
2560 offset
+= dissect_spice_keyboard_modifiers(tvb
, tree
, offset
);
2562 case SPICE_MSGC_INPUTS_MOUSE_POSITION
:
2563 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof(point32_t
) + 3, ett_inputs_client
, NULL
, "Client MOUSE_POSITION message");
2564 dissect_POINT32(tvb
, inputs_tree
, offset
);
2565 offset
+= (int)sizeof(point32_t
);
2566 offset
+= dissect_buttons_state(tvb
, inputs_tree
, offset
);
2567 proto_tree_add_item(inputs_tree
, hf_mouse_display_id
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2570 case SPICE_MSGC_INPUTS_MOUSE_MOTION
:
2571 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, sizeof(point32_t
) + 2, ett_inputs_client
, NULL
, "Client MOUSE_MOTION message");
2572 dissect_POINT32(tvb
, inputs_tree
, offset
);
2573 offset
+= (int)sizeof(point32_t
);
2574 offset
+= dissect_buttons_state(tvb
, inputs_tree
, offset
);
2576 case SPICE_MSGC_INPUTS_MOUSE_PRESS
:
2577 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 3, ett_inputs_client
, NULL
, "Client MOUSE_PRESS message");
2578 proto_tree_add_item(inputs_tree
, hf_button
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2580 offset
+= dissect_buttons_state(tvb
, inputs_tree
, offset
);
2582 case SPICE_MSGC_INPUTS_MOUSE_RELEASE
:
2583 inputs_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 3, ett_inputs_client
, NULL
, "Client MOUSE_RELEASE message");
2584 proto_tree_add_item(inputs_tree
, hf_button
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2586 offset
+= dissect_buttons_state(tvb
, inputs_tree
, offset
);
2589 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown inputs client message - cannot dissect");
2596 dissect_spice_inputs_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2598 switch (message_type
) {
2599 case SPICE_MSG_INPUTS_INIT
:
2600 offset
+= dissect_spice_keyboard_modifiers(tvb
, tree
, offset
);
2602 case SPICE_MSG_INPUTS_KEY_MODIFIERS
:
2603 offset
+= dissect_spice_keyboard_modifiers(tvb
, tree
, offset
);
2605 case SPICE_MSG_INPUTS_MOUSE_MOTION_ACK
:
2606 proto_tree_add_item(tree
, hf_spice_server_inputs_mouse_motion_ack_message
, tvb
, offset
, 0, ENC_NA
);
2609 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown inputs server message - cannot dissect");
2616 dissect_spice_tunnel_client(packet_info
*pinfo
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2618 /* TODO: Not implemented yet */
2619 switch (message_type
) {
2621 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2628 dissect_spice_tunnel_server(packet_info
*pinfo
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2630 /* TODO: Not implemented yet */
2631 switch (message_type
) {
2633 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2640 dissect_spice_smartcard_client(packet_info
*pinfo
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2642 /* TODO: Not implemented yet */
2643 switch (message_type
) {
2645 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2652 dissect_spice_smartcard_server(packet_info
*pinfo
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t offset
)
2654 /* TODO: Not implemented yet */
2655 switch (message_type
) {
2657 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2664 dissect_spice_usbredir_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t message_size
, uint32_t offset
)
2666 switch (message_type
) {
2667 case SPICE_MSGC_SPICEVMC_DATA
:
2668 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, message_size
, ENC_NA
);
2669 offset
+= message_size
;
2672 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2679 dissect_spice_usbredir_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t message_size
, uint32_t offset
)
2681 switch (message_type
) {
2682 case SPICE_MSG_SPICEVMC_DATA
:
2683 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, message_size
, ENC_NA
);
2684 offset
+= message_size
;
2687 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2694 dissect_spice_port_client(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t message_size
, uint32_t offset
)
2696 switch (message_type
) {
2697 case SPICE_MSGC_SPICEVMC_DATA
:
2698 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, message_size
, ENC_NA
);
2699 offset
+= message_size
;
2701 case SPICE_MSGC_PORT_EVENT
:
2702 proto_tree_add_item(tree
, hf_port_event
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2706 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2713 dissect_spice_port_server(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, const uint16_t message_type
, proto_item
* msgtype_item
, uint32_t message_size
, uint32_t offset
)
2715 switch (message_type
) {
2716 case SPICE_MSG_SPICEVMC_DATA
:
2717 proto_tree_add_item(tree
, hf_raw_data
, tvb
, offset
, message_size
, ENC_NA
);
2718 offset
+= message_size
;
2720 case SPICE_MSG_PORT_INIT
:
2722 uint32_t size
= tvb_get_letohl(tvb
, offset
);
2723 proto_tree_add_item(tree
, hf_spice_name_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2725 proto_tree_add_item(tree
, hf_main_name
, tvb
, offset
, size
, ENC_ASCII
);
2727 proto_tree_add_item(tree
, hf_port_opened
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2731 case SPICE_MSG_PORT_EVENT
:
2732 proto_tree_add_item(tree
, hf_port_event
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
2736 expert_add_info_format(pinfo
, msgtype_item
, &ei_spice_unknown_message
, "Unknown message - cannot dissect");
2744 dissect_spice_data_server_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, spice_conversation_t
*spice_info
, uint32_t offset
, const uint32_t total_message_size
)
2746 proto_item
*ti
= NULL
, *msg_ti
=NULL
, *msgtype_ti
=NULL
;
2747 proto_tree
*data_header_tree
, *message_tree
;
2748 uint16_t message_type
;
2749 uint32_t message_size
, sublist_size
, old_offset
;
2750 uint32_t header_size
;
2752 if (spice_info
->client_mini_header
&& spice_info
->server_mini_header
) {
2753 header_size
= sizeof_SpiceMiniDataHeader
;
2754 message_type
= tvb_get_letohs(tvb
, offset
);
2755 message_size
= tvb_get_letohl(tvb
, offset
+2);
2756 message_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 0,
2757 ett_message
, &msg_ti
, "%s (%d bytes)",
2758 get_message_type_string(message_type
, spice_info
, false),
2759 message_size
+ header_size
);
2760 ti
= proto_tree_add_item(message_tree
, hf_data
, tvb
, offset
, header_size
, ENC_NA
);
2761 data_header_tree
= proto_item_add_subtree(ti
, ett_data
);
2762 dissect_spice_mini_data_header(tvb
, data_header_tree
, spice_info
, false, message_type
, offset
);
2763 proto_item_set_len(msg_ti
, message_size
+ header_size
);
2765 header_size
= sizeof_SpiceDataHeader
;
2766 message_type
= tvb_get_letohs(tvb
, offset
+ 8);
2767 message_size
= tvb_get_letohl(tvb
, offset
+ 10);
2768 message_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 0,
2769 ett_message
, &msg_ti
, "%s (%d bytes)",
2770 get_message_type_string(message_type
, spice_info
, false),
2771 message_size
+ header_size
);
2772 ti
= proto_tree_add_item(message_tree
, hf_data
, tvb
, offset
, header_size
, ENC_NA
);
2773 data_header_tree
= proto_item_add_subtree(ti
, ett_data
);
2774 dissect_spice_data_header(tvb
, data_header_tree
, spice_info
, false, message_type
, &msgtype_ti
, &sublist_size
, offset
);
2776 proto_item_set_len(msg_ti
, message_size
+ header_size
);
2777 offset
+= header_size
;
2778 old_offset
= offset
;
2780 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, ", ", get_message_type_string(message_type
, spice_info
, false));
2781 if (message_type
< SPICE_FIRST_AVAIL_MESSAGE
) { /* this is a common message */
2782 offset
= dissect_spice_common_server_messages(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, offset
, total_message_size
- header_size
);
2786 switch (spice_info
->channel_type
) {
2787 case SPICE_CHANNEL_PLAYBACK
:
2788 offset
= dissect_spice_playback_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, message_size
, spice_info
, offset
);
2790 case SPICE_CHANNEL_RECORD
:
2791 offset
= dissect_spice_record_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, offset
);
2793 case SPICE_CHANNEL_MAIN
:
2794 offset
= dissect_spice_main_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, offset
);
2796 case SPICE_CHANNEL_CURSOR
:
2797 offset
= dissect_spice_cursor_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, offset
);
2799 case SPICE_CHANNEL_DISPLAY
:
2800 offset
= dissect_spice_display_server(tvb
, message_tree
, pinfo
, message_type
, msgtype_ti
, offset
);
2802 case SPICE_CHANNEL_INPUTS
:
2803 offset
= dissect_spice_inputs_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, offset
);
2805 case SPICE_CHANNEL_TUNNEL
:
2806 offset
= dissect_spice_tunnel_server(pinfo
, message_type
, msgtype_ti
, offset
);
2808 case SPICE_CHANNEL_SMARTCARD
:
2809 offset
= dissect_spice_smartcard_server(pinfo
, message_type
, msgtype_ti
, offset
);
2811 case SPICE_CHANNEL_USBREDIR
:
2812 offset
= dissect_spice_usbredir_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, message_size
, offset
);
2814 case SPICE_CHANNEL_PORT
:
2815 offset
= dissect_spice_port_server(tvb
, pinfo
, message_tree
, message_type
, msgtype_ti
, message_size
, offset
);
2818 expert_add_info_format(pinfo
, msgtype_ti
, &ei_spice_unknown_message
, "Unknown server PDU - cannot dissect");
2821 if ((offset
- old_offset
) != message_size
) {
2822 proto_tree_add_expert_format(tree
, pinfo
, &ei_spice_not_dissected
, tvb
, offset
, -1,
2823 "message type %s (%u) not fully dissected", get_message_type_string(message_type
, spice_info
, false), message_type
);
2824 offset
= old_offset
+ message_size
;
2831 dissect_spice_data_client_pdu(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, spice_conversation_t
*spice_info
, uint32_t offset
)
2833 proto_item
*ti
= NULL
, *msgtype_ti
= NULL
;
2834 proto_tree
*data_header_tree
;
2835 uint16_t message_type
;
2836 uint32_t message_size
= 0, sublist_size
;
2837 uint32_t header_size
;
2839 if (spice_info
->client_mini_header
&& spice_info
->server_mini_header
) {
2840 header_size
= sizeof_SpiceMiniDataHeader
;
2841 ti
= proto_tree_add_item(tree
, hf_data
, tvb
, offset
, header_size
, ENC_NA
);
2842 data_header_tree
= proto_item_add_subtree(ti
, ett_data
);
2843 message_type
= tvb_get_letohs(tvb
, offset
);
2844 message_size
= tvb_get_letohl(tvb
, offset
+ 2);
2845 dissect_spice_mini_data_header(tvb
, data_header_tree
, spice_info
, true, message_type
, offset
);
2847 header_size
= sizeof_SpiceDataHeader
;
2848 ti
= proto_tree_add_item(tree
, hf_data
, tvb
, offset
, header_size
, ENC_NA
);
2849 data_header_tree
= proto_item_add_subtree(ti
, ett_data
);
2850 message_type
= tvb_get_letohs(tvb
, offset
+ 8);
2851 message_size
= tvb_get_letohl(tvb
, offset
+ 10);
2852 dissect_spice_data_header(tvb
, data_header_tree
, spice_info
, true, message_type
, &msgtype_ti
, &sublist_size
, offset
);
2854 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, ", ", get_message_type_string(message_type
, spice_info
, true));
2855 offset
+= header_size
;
2856 /* TODO: deal with sub-messages list first. As implementation does not uses sub-messages list yet, */
2857 /* it cannot be implemented in the dissector yet. */
2859 if (message_type
< SPICE_FIRST_AVAIL_MESSAGE
) { /* this is a common message */
2860 return dissect_spice_common_client_messages(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, offset
);
2863 switch (spice_info
->channel_type
) {
2864 case SPICE_CHANNEL_PLAYBACK
:
2866 case SPICE_CHANNEL_RECORD
:
2867 offset
= dissect_spice_record_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, offset
);
2869 case SPICE_CHANNEL_MAIN
:
2870 offset
= dissect_spice_main_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, offset
);
2872 case SPICE_CHANNEL_DISPLAY
:
2873 offset
= dissect_spice_display_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, offset
);
2875 case SPICE_CHANNEL_INPUTS
:
2876 offset
= dissect_spice_inputs_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, offset
);
2878 case SPICE_CHANNEL_TUNNEL
:
2879 offset
= dissect_spice_tunnel_client(pinfo
, message_type
, msgtype_ti
, offset
);
2881 case SPICE_CHANNEL_SMARTCARD
:
2882 offset
= dissect_spice_smartcard_client(pinfo
, message_type
, msgtype_ti
, offset
);
2884 case SPICE_CHANNEL_USBREDIR
:
2885 offset
= dissect_spice_usbredir_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, message_size
, offset
);
2887 case SPICE_CHANNEL_PORT
:
2888 offset
= dissect_spice_port_client(tvb
, pinfo
, tree
, message_type
, msgtype_ti
, message_size
, offset
);
2891 expert_add_info_format(pinfo
, msgtype_ti
, &ei_spice_unknown_message
, "Unknown client PDU - cannot dissect");
2899 dissect_spice_link_common_header(tvbuff_t
*tvb
, proto_tree
*tree
)
2902 /* dissect common header */
2903 proto_tree_add_item(tree
, hf_spice_magic
, tvb
, 0, 4, ENC_ASCII
);
2904 proto_tree_add_item(tree
, hf_major_version
, tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
2905 proto_tree_add_item(tree
, hf_minor_version
, tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
2906 proto_tree_add_item(tree
, hf_message_size
, tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
2911 dissect_spice_common_capabilities(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, uint32_t offset
, const unsigned caps_len
, spice_conversation_t
*spice_info
, bool is_client
)
2913 /* TODO: save common and per-channel capabilities in spice_info ? */
2916 static int * const caps
[] = {
2917 &hf_common_cap_auth_select
,
2918 &hf_common_cap_auth_spice
,
2919 &hf_common_cap_auth_sasl
,
2920 &hf_common_cap_mini_header
,
2924 for(i
= 0; i
< caps_len
; i
++) {
2925 val
= tvb_get_letohl(tvb
, offset
);
2929 spice_info
->client_auth
= val
;
2931 spice_info
->server_auth
= val
;
2934 proto_tree_add_bitmask_list(tree
, tvb
, offset
, 4, caps
, ENC_LITTLE_ENDIAN
);
2935 if (val
& SPICE_COMMON_CAP_MINI_HEADER_MASK
) {
2937 spice_info
->client_mini_header
= true;
2939 spice_info
->server_mini_header
= true;
2945 proto_tree_add_expert(tree
, pinfo
, &ei_spice_common_cap_unknown
, tvb
, offset
, 4);
2953 dissect_spice_link_capabilities(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, uint32_t offset
, const unsigned caps_len
, const spice_conversation_t
*spice_info
)
2955 /* TODO: save common and per-channel capabilities in spice_info ? */
2958 for(i
= 0; i
< caps_len
; i
++) {
2959 switch (spice_info
->channel_type
) {
2960 case SPICE_CHANNEL_PLAYBACK
:
2962 static int * const playback_cap
[] = {
2963 &hf_playback_cap_celt_0_5_1
,
2964 &hf_playback_cap_volume
,
2965 &hf_playback_cap_latency
,
2966 &hf_playback_cap_opus
,
2973 proto_tree_add_bitmask_list(tree
, tvb
, offset
, 4, playback_cap
, ENC_LITTLE_ENDIAN
);
2976 case SPICE_CHANNEL_MAIN
:
2978 static int * const main_cap
[] = {
2979 &hf_main_cap_semi_migrate
,
2980 &hf_main_cap_vm_name_uuid
, /*Note: only relevant for client. TODO: dissect only for client */
2981 &hf_main_cap_agent_connected_tokens
,
2982 &hf_main_cap_seamless_migrate
,
2989 proto_tree_add_bitmask_list(tree
, tvb
, offset
, 4, main_cap
, ENC_LITTLE_ENDIAN
);
2992 case SPICE_CHANNEL_DISPLAY
:
2994 static int * const display_cap
[] = {
2995 &hf_display_cap_sized_stream
,
2996 &hf_display_cap_monitors_config
,
2997 &hf_display_cap_composite
,
2998 &hf_display_cap_a8_surface
,
2999 &hf_display_cap_stream_report
,
3000 &hf_display_cap_lz4_compression
,
3001 &hf_display_cap_pref_compression
,
3002 &hf_display_cap_gl_scanout
,
3003 &hf_display_cap_multi_codec
,
3004 &hf_display_cap_codec_mjpeg
,
3005 &hf_display_cap_codec_vp8
,
3006 &hf_display_cap_codec_h264
,
3007 &hf_display_cap_pref_video_codec_type
,
3008 &hf_display_cap_codec_vp9
,
3009 &hf_display_cap_codec_h265
,
3016 proto_tree_add_bitmask_list(tree
, tvb
, offset
, 4, display_cap
, ENC_LITTLE_ENDIAN
);
3019 case SPICE_CHANNEL_INPUTS
:
3020 proto_tree_add_item(tree
, hf_inputs_cap
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3022 case SPICE_CHANNEL_CURSOR
:
3023 proto_tree_add_item(tree
, hf_cursor_cap
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3025 case SPICE_CHANNEL_RECORD
:
3027 static int * const record_cap
[] = {
3028 &hf_record_cap_celt
,
3029 &hf_record_cap_volume
,
3030 &hf_record_cap_opus
,
3037 proto_tree_add_bitmask_list(tree
, tvb
, offset
, 4, record_cap
, ENC_LITTLE_ENDIAN
);
3041 proto_tree_add_expert(tree
, pinfo
, &ei_spice_unknown_channel
, tvb
, offset
, -1);
3049 dissect_spice_link_client_pdu(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, spice_conversation_t
*spice_info
)
3052 uint32_t common_caps_len
, channel_caps_len
;
3053 proto_item
*ti
= NULL
;
3054 proto_tree
*link_header_tree
= NULL
;
3055 proto_tree
*caps_tree
= NULL
;
3058 ti
= proto_tree_add_item(tree
, hf_link_client
, tvb
, 0, sizeof_SpiceLinkHeader
, ENC_NA
);
3059 link_header_tree
= proto_item_add_subtree(ti
, ett_link_client
);
3061 dissect_spice_link_common_header(tvb
, link_header_tree
);
3063 offset
= sizeof_SpiceLinkHeader
;
3065 if (spice_info
->channel_type
== SPICE_CHANNEL_NONE
) {
3066 spice_info
->channel_type
= tvb_get_uint8(tvb
, offset
+ 4);
3068 common_caps_len
= tvb_get_letohl(tvb
, offset
+ 6);
3069 channel_caps_len
= tvb_get_letohl(tvb
, offset
+ 10);
3070 proto_tree_add_item(tree
, hf_conn_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3072 proto_tree_add_item(tree
, hf_channel_type
, tvb
, offset
, 1, ENC_NA
);
3074 proto_tree_add_item(tree
, hf_channel_id
, tvb
, offset
, 1, ENC_NA
);
3076 proto_tree_add_item(tree
, hf_num_common_caps
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3078 proto_tree_add_item(tree
, hf_num_channel_caps
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3080 proto_tree_add_item(tree
, hf_caps_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3083 if (common_caps_len
> 0) {
3084 caps_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, common_caps_len
* 4,
3085 ett_link_caps
, NULL
, "Client Common Capabilities (%d bytes)",
3086 common_caps_len
* 4); /* caps_len multiplied by 4 as length is in UINT32 units */
3087 dissect_spice_common_capabilities(tvb
, pinfo
, caps_tree
, offset
, common_caps_len
, spice_info
, true);
3088 offset
+= (common_caps_len
* 4);
3090 if (channel_caps_len
> 0) {
3091 caps_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, channel_caps_len
* 4,
3092 ett_link_caps
, NULL
, "Client Channel-specific Capabilities (%d bytes)",
3093 channel_caps_len
* 4); /* caps_len multiplied by 4 as length is in UINT32 units */
3094 dissect_spice_link_capabilities(tvb
, pinfo
, caps_tree
, offset
, channel_caps_len
, spice_info
);
3099 dissect_spice_link_server_pdu(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, spice_conversation_t
*spice_info
)
3102 uint32_t common_caps_len
, channel_caps_len
;
3103 proto_item
*ti
= NULL
;
3104 proto_tree
*link_tree
= NULL
;
3105 proto_tree
*caps_tree
= NULL
;
3108 ti
= proto_tree_add_item(tree
, hf_link_server
, tvb
, 0, sizeof_SpiceLinkHeader
, ENC_NA
);
3109 link_tree
= proto_item_add_subtree(ti
, ett_link_server
);
3111 dissect_spice_link_common_header(tvb
, link_tree
);
3114 offset
= sizeof_SpiceLinkHeader
;
3117 proto_tree_add_item(tree
, hf_error_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3118 proto_tree_add_bytes_format(tree
, hf_spice_x509_subjectpublickeyinfo
, tvb
, offset
+ 4, SPICE_TICKET_PUBKEY_BYTES
, NULL
, "X.509 SubjectPublicKeyInfo (ASN.1)");
3119 proto_tree_add_item(tree
, hf_num_common_caps
, tvb
, offset
+ 4 + SPICE_TICKET_PUBKEY_BYTES
, 4, ENC_LITTLE_ENDIAN
);
3120 proto_tree_add_item(tree
, hf_num_channel_caps
, tvb
, offset
+ 8 + SPICE_TICKET_PUBKEY_BYTES
, 4, ENC_LITTLE_ENDIAN
);
3122 proto_tree_add_item(tree
, hf_caps_offset
, tvb
, offset
+ 12 + SPICE_TICKET_PUBKEY_BYTES
, 4, ENC_LITTLE_ENDIAN
);
3125 common_caps_len
= tvb_get_letohl(tvb
, offset
+ 4 + SPICE_TICKET_PUBKEY_BYTES
);
3126 channel_caps_len
= tvb_get_letohl(tvb
, offset
+ 8 + SPICE_TICKET_PUBKEY_BYTES
);
3127 offset
+= (int)sizeof_SpiceLinkHeader
+ SPICE_TICKET_PUBKEY_BYTES
;
3129 if (common_caps_len
> 0) {
3130 caps_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, common_caps_len
* 4,
3131 ett_link_caps
, NULL
, "Common Capabilities (%d bytes)",
3132 common_caps_len
* 4); /* caps_len multiplied by 4 as length is in UINT32 units */
3133 dissect_spice_common_capabilities(tvb
, pinfo
, caps_tree
, offset
, common_caps_len
, spice_info
, false);
3134 offset
+= (common_caps_len
* 4);
3136 if (channel_caps_len
> 0) {
3137 caps_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, channel_caps_len
* 4,
3138 ett_link_caps
, NULL
, "Channel Capabilities (%d bytes)",
3139 channel_caps_len
* 4); /* caps_len multiplied by 4 as length is in UINT32 units */
3140 dissect_spice_link_capabilities(tvb
, pinfo
, caps_tree
, offset
, channel_caps_len
, spice_info
);
3145 dissect_spice(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3148 conversation_t
*conversation
;
3149 spice_conversation_t
*spice_info
;
3150 spice_packet_t
*per_packet_info
;
3152 uint32_t pdu_len
= 0;
3154 proto_item
*ti
, *auth_item
;
3155 proto_tree
*spice_tree
;
3156 bool client_sasl_list
= false;
3157 uint8_t sasl_auth_result
;
3159 conversation
= find_or_create_conversation(pinfo
);
3161 spice_info
= (spice_conversation_t
*)conversation_get_proto_data(conversation
, proto_spice
);
3163 spice_info
= wmem_new0(wmem_file_scope(), spice_conversation_t
);
3164 spice_info
->destport
= pinfo
->destport
;
3165 spice_info
->channel_type
= SPICE_CHANNEL_NONE
;
3166 spice_info
->next_state
= SPICE_LINK_CLIENT
;
3167 spice_info
->client_auth
= 0;
3168 spice_info
->server_auth
= 0;
3169 spice_info
->playback_mode
= SPICE_AUDIO_DATA_MODE_INVALID
;
3170 spice_info
->client_mini_header
= false;
3171 spice_info
->server_mini_header
= false;
3172 conversation_add_proto_data(conversation
, proto_spice
, spice_info
);
3173 conversation_set_dissector(conversation
, spice_handle
);
3176 per_packet_info
= (spice_packet_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_spice
, 0);
3177 if (!per_packet_info
) {
3178 per_packet_info
= wmem_new(wmem_file_scope(), spice_packet_t
);
3179 per_packet_info
->state
= spice_info
->next_state
;
3180 p_add_proto_data(wmem_file_scope(), pinfo
, proto_spice
, 0, per_packet_info
);
3183 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "Spice %s", val_to_str_const(spice_info
->channel_type
,channel_types_vs
, "Unknown"));
3184 col_clear(pinfo
->cinfo
, COL_INFO
);
3185 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(per_packet_info
->state
, state_name_vs
, ""));
3187 ti
= proto_tree_add_item(tree
, proto_spice
, tvb
, 0, -1, ENC_NA
);
3188 spice_tree
= proto_item_add_subtree(ti
, ett_spice
);
3190 switch (per_packet_info
->state
) {
3191 case SPICE_LINK_CLIENT
:
3192 avail
= tvb_reported_length(tvb
);
3193 pdu_len
= sizeof_SpiceLinkHeader
;
3194 GET_PDU_FROM_OFFSET(0)
3195 pdu_len
= tvb_get_letohl(tvb
, 12) + sizeof_SpiceLinkHeader
;
3196 GET_PDU_FROM_OFFSET(0)
3197 proto_item_set_len(ti
, pdu_len
);
3198 dissect_spice_link_client_pdu(tvb
, pinfo
, spice_tree
, spice_info
);
3199 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
,
3200 "Spice %s", val_to_str_const(spice_info
->channel_type
,channel_types_vs
, "Unknown"));
3201 spice_info
->next_state
= SPICE_LINK_SERVER
;
3203 case SPICE_LINK_SERVER
:
3204 avail
= tvb_reported_length(tvb
);
3205 pdu_len
= sizeof_SpiceLinkHeader
;
3206 GET_PDU_FROM_OFFSET(0)
3207 pdu_len
= tvb_get_letohl(tvb
, 12) + sizeof_SpiceLinkHeader
;
3208 GET_PDU_FROM_OFFSET(0)
3209 proto_item_set_len(ti
, pdu_len
);
3210 dissect_spice_link_server_pdu(tvb
, pinfo
, spice_tree
, spice_info
);
3211 if (!(spice_info
->server_auth
& SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION_MASK
) ||
3212 !(spice_info
->client_auth
& SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION_MASK
)) {
3213 /* Server or clients support spice ticket auth only */
3214 spice_info
->next_state
= SPICE_TICKET_CLIENT
;
3215 } else { /* Protocol selection between client and server */
3216 spice_info
->next_state
= SPICE_CLIENT_AUTH_SELECT
;
3219 case SPICE_CLIENT_AUTH_SELECT
:
3220 if (spice_info
->destport
!= pinfo
->destport
) { /* ignore anything from the server, wait for data from client */
3221 expert_add_info(pinfo
, ti
, &ei_spice_expected_from_client
);
3225 avail
= tvb_reported_length(tvb
);
3227 GET_PDU_FROM_OFFSET(0)
3228 proto_item_set_len(ti
, 4);
3230 auth_item
= proto_tree_add_item(spice_tree
, hf_auth_select_client
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
3231 spice_info
->auth_selected
= tvb_get_letohl(tvb
, 0);
3232 switch (spice_info
->auth_selected
) {
3233 case SPICE_COMMON_CAP_AUTH_SPICE
:
3234 spice_info
->next_state
= SPICE_TICKET_CLIENT
;
3236 case SPICE_COMMON_CAP_AUTH_SASL
:
3237 spice_info
->next_state
= SPICE_SASL_INIT_FROM_SERVER
;
3240 expert_add_info(pinfo
, auth_item
, &ei_spice_auth_unknown
);
3244 case SPICE_SASL_INIT_FROM_SERVER
:
3246 avail
= tvb_reported_length_remaining(tvb
, offset
);
3248 GET_PDU_FROM_OFFSET(offset
)
3249 pdu_len
= tvb_get_letohl(tvb
, offset
); /* the length of the following messages */
3250 proto_item_set_len(ti
, 4);
3251 proto_tree_add_item(spice_tree
, hf_spice_sasl_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3253 GET_PDU_FROM_OFFSET(offset
)
3254 proto_item_set_len(ti
, pdu_len
);
3255 proto_tree_add_uint(spice_tree
, hf_spice_supported_authentication_mechanisms_list_length
, tvb
, offset
, 4, pdu_len
- 4);
3257 proto_tree_add_item(spice_tree
, hf_spice_supported_authentication_mechanisms_list
, tvb
, offset
, pdu_len
- 4, ENC_NA
|ENC_ASCII
);
3258 offset
+= (pdu_len
- 4);
3259 spice_info
->next_state
= SPICE_SASL_START_TO_SERVER
;
3261 case SPICE_SASL_START_TO_SERVER
:
3263 while (offset
< tvb_reported_length(tvb
)) {
3264 avail
= tvb_reported_length_remaining(tvb
, offset
);
3266 GET_PDU_FROM_OFFSET(offset
)
3267 pdu_len
= tvb_get_letohl(tvb
, offset
); /* the length of the following messages */
3268 proto_item_set_len(ti
, 4);
3269 proto_tree_add_item(spice_tree
, hf_spice_sasl_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3271 /* meaning, empty PDU - assuming the client_out_list, which may be empty*/
3272 spice_info
->next_state
= SPICE_SASL_START_FROM_SERVER
;
3273 pdu_len
= 4; /* only the size field.*/
3277 GET_PDU_FROM_OFFSET(offset
)
3278 proto_item_set_len(ti
, pdu_len
);
3279 if (client_sasl_list
== false) {
3280 client_sasl_list
= true;
3281 col_set_str(pinfo
->cinfo
, COL_INFO
, "Client selected SASL authentication mechanism (start to server)");
3282 proto_tree_add_uint(spice_tree
, hf_spice_selected_authentication_mechanism_length
, tvb
, offset
, 4, pdu_len
- 4);
3284 proto_tree_add_item(spice_tree
, hf_spice_selected_authentication_mechanism
, tvb
, offset
, pdu_len
- 4, ENC_NA
|ENC_ASCII
);
3286 /* this is the client out list, ending the start from client message */
3287 col_set_str(pinfo
->cinfo
, COL_INFO
, "Client out mechanism (start to server)");
3288 proto_tree_add_uint(spice_tree
, hf_spice_client_out_mechanism_length
, tvb
, offset
, 4, pdu_len
- 4);
3290 proto_tree_add_item(spice_tree
, hf_spice_selected_client_out_mechanism
, tvb
, offset
, pdu_len
- 4, ENC_NA
|ENC_ASCII
);
3291 spice_info
->next_state
= SPICE_SASL_START_FROM_SERVER
;
3293 offset
+= (pdu_len
- 4);
3297 case SPICE_SASL_START_FROM_SERVER
:
3298 case SPICE_SASL_STEP_FROM_SERVER
:
3300 while (offset
< tvb_reported_length(tvb
)) {
3301 avail
= tvb_reported_length_remaining(tvb
, offset
);
3303 GET_PDU_FROM_OFFSET(offset
)
3304 pdu_len
= tvb_get_letohl(tvb
, offset
); /* the length of the following messages */
3305 proto_item_set_len(ti
, 4 + pdu_len
);
3306 proto_tree_add_item(spice_tree
, hf_spice_sasl_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3307 if (pdu_len
== 0) { /* meaning, empty PDU */
3308 offset
+= 4; /* only the size field.*/
3311 GET_PDU_FROM_OFFSET(offset
)
3313 proto_tree_add_item(spice_tree
, hf_spice_sasl_authentication_data
, tvb
, offset
, pdu_len
- 4, ENC_ASCII
);
3314 offset
+= (pdu_len
- 4);
3317 if (per_packet_info
->state
== SPICE_SASL_START_FROM_SERVER
) {
3318 spice_info
->next_state
= SPICE_SASL_START_FROM_SERVER_CONT
;
3320 spice_info
->next_state
= SPICE_SASL_STEP_FROM_SERVER_CONT
;
3323 case SPICE_SASL_START_FROM_SERVER_CONT
:
3324 case SPICE_SASL_STEP_FROM_SERVER_CONT
:
3326 avail
= tvb_reported_length_remaining(tvb
, offset
);
3328 proto_item_set_len(ti
, 1);
3329 sasl_auth_result
= tvb_get_uint8(tvb
, offset
);
3330 proto_tree_add_item(spice_tree
, hf_spice_sasl_auth_result
, tvb
, offset
, 1, ENC_NA
);
3332 if (per_packet_info
->state
== SPICE_SASL_START_FROM_SERVER_CONT
) {
3333 /* if we are in the sasl start, and can continue */
3334 if (sasl_auth_result
== 0) { /* 0 = continue */
3335 spice_info
->next_state
= SPICE_SASL_STEP_TO_SERVER
;
3337 expert_add_info_format(pinfo
, ti
, &ei_spice_sasl_auth_result
, "SPICE_SASL_START_FROM_SERVER_CONT and sasl_auth_result is %d",
3340 } else { /* SPICE_SASL_STEP_FROM_SERVER_CONT state. */
3341 spice_info
->next_state
= SPICE_TICKET_SERVER
;
3345 case SPICE_SASL_STEP_TO_SERVER
:
3347 while (offset
< tvb_reported_length(tvb
)) {
3348 avail
= tvb_reported_length_remaining(tvb
, offset
);
3350 GET_PDU_FROM_OFFSET(offset
)
3351 pdu_len
= tvb_get_letohl(tvb
, offset
); /* the length of the following messages */
3352 proto_item_set_len(ti
, 4);
3353 proto_tree_add_item(spice_tree
, hf_spice_sasl_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3355 /* meaning, empty PDU - assuming the client_out_list, which may be empty*/
3356 col_set_str(pinfo
->cinfo
, COL_INFO
, "SASL authentication from client (step to server)");
3357 spice_info
->next_state
= SPICE_SASL_STEP_FROM_SERVER
;
3358 pdu_len
= 4; /* only the size field.*/
3362 GET_PDU_FROM_OFFSET(offset
)
3363 proto_item_set_len(ti
, pdu_len
);
3364 col_set_str(pinfo
->cinfo
, COL_INFO
, "Clientout (step to server)");
3365 proto_tree_add_uint(spice_tree
, hf_spice_clientout_length
, tvb
, offset
, 4, pdu_len
- 4);
3367 proto_tree_add_item(spice_tree
, hf_spice_clientout_list
, tvb
, offset
, pdu_len
- 4, ENC_NA
|ENC_ASCII
);
3368 spice_info
->next_state
= SPICE_SASL_STEP_FROM_SERVER
;
3369 offset
+= (pdu_len
- 4);
3373 case SPICE_SASL_DATA
:
3375 while (offset
< tvb_reported_length(tvb
)) {
3376 avail
= tvb_reported_length_remaining(tvb
, offset
);
3378 GET_PDU_FROM_OFFSET(offset
)
3379 pdu_len
= tvb_get_ntohl(tvb
, offset
); /* the length of the following messages */
3380 proto_item_set_len(ti
, pdu_len
);
3381 proto_tree_add_item(spice_tree
, hf_spice_sasl_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
3382 if (pdu_len
== 0) { /* meaning, empty PDU */
3383 return 4; /* only the size field.*/
3387 GET_PDU_FROM_OFFSET(offset
)
3388 proto_item_set_len(ti
, pdu_len
);
3389 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
,
3390 "Spice %s (SASL wrapped)", val_to_str_const(spice_info
->channel_type
,channel_types_vs
, "Unknown"));
3393 proto_tree_add_bytes_format(spice_tree
, hf_spice_sasl_data
, tvb
, offset
, pdu_len
- 4, NULL
, "SASL data (%u bytes)", pdu_len
- 4);
3394 offset
+= (pdu_len
- 4);
3399 while (offset
< tvb_reported_length(tvb
)) {
3400 avail
= tvb_reported_length_remaining(tvb
, offset
);
3401 if (spice_info
->client_mini_header
&& spice_info
->server_mini_header
) {
3402 pdu_len
= sizeof_SpiceMiniDataHeader
;
3403 GET_PDU_FROM_OFFSET(offset
)
3404 pdu_len
= tvb_get_letohl(tvb
, offset
+ 2);
3405 pdu_len
+= sizeof_SpiceMiniDataHeader
;
3407 pdu_len
= sizeof_SpiceDataHeader
;
3408 GET_PDU_FROM_OFFSET(offset
)
3409 /* if there are no sub-messages, get the usual message body size. */
3410 /* Note that we do not dissect properly yet sub-messages - but they */
3411 /* are not used in the protocol either */
3412 pdu_len
= tvb_get_letohl(tvb
, offset
+ 10);
3413 pdu_len
+= sizeof_SpiceDataHeader
; /* +sizeof_SpiceDataHeader since you need to exclude the SPICE */
3414 /* data header, which is sizeof_SpiceDataHeader (18) bytes long) */
3416 GET_PDU_FROM_OFFSET(offset
)
3417 proto_item_set_len(ti
, pdu_len
);
3419 if (spice_info
->destport
== pinfo
->destport
) { /* client to server traffic */
3420 offset
= dissect_spice_data_client_pdu(tvb
, spice_tree
, pinfo
, spice_info
, offset
);
3421 } else { /* server to client traffic */
3422 offset
= dissect_spice_data_server_pdu(tvb
, spice_tree
, pinfo
, spice_info
, offset
, pdu_len
);
3427 case SPICE_TICKET_CLIENT
:
3428 if (spice_info
->destport
!= pinfo
->destport
) /* ignore anything from the server, wait for ticket from client */
3430 avail
= tvb_reported_length(tvb
);
3432 GET_PDU_FROM_OFFSET(0)
3433 proto_item_set_len(ti
, 128);
3434 proto_tree_add_item(spice_tree
, hf_ticket_client
, tvb
, 0, 128, ENC_NA
);
3435 spice_info
->next_state
= SPICE_TICKET_SERVER
;
3437 case SPICE_TICKET_SERVER
:
3438 if (spice_info
->destport
!= pinfo
->srcport
) /* ignore anything from the client, wait for ticket from server */
3440 avail
= tvb_reported_length(tvb
);
3442 GET_PDU_FROM_OFFSET(0)
3443 proto_item_set_len(ti
, 4);
3444 proto_tree_add_item(spice_tree
, hf_ticket_server
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
3445 if (spice_info
->auth_selected
== SPICE_COMMON_CAP_AUTH_SASL
) {
3446 spice_info
->next_state
= SPICE_SASL_DATA
;
3448 spice_info
->next_state
= SPICE_DATA
;
3458 test_spice_protocol(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
3461 if ((tvb_reported_length(tvb
) >= 4) && (tvb_get_ntohl(tvb
, 0) == SPICE_MAGIC
)) {
3462 dissect_spice(tvb
, pinfo
, tree
, data
);
3468 /* Register the protocol with Wireshark */
3470 proto_register_spice(void)
3472 /* Setup list of header fields */
3473 static hf_register_info hf
[] = {
3475 { "Link client header", "spice.link_client",
3476 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3480 { "Link server header", "spice.link_server",
3481 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3485 { "SPICE MAGIC", "spice.magic",
3486 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3489 { &hf_major_version
,
3490 { "Protocol major version", "spice.major_version",
3491 FT_INT32
, BASE_DEC
, NULL
, 0x0,
3494 { &hf_minor_version
,
3495 { "Protocol minor version", "spice.minor_version",
3496 FT_INT32
, BASE_DEC
, NULL
, 0x0,
3500 { "Message size", "spice.message_size",
3501 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3505 { "Message type", "spice.message_type",
3506 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3510 { "Session ID", "spice.conn_id",
3511 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
3515 { "Channel type", "spice.channel_type",
3516 FT_UINT8
, BASE_DEC
, VALS(channel_types_vs
), 0x0,
3520 { "Channel ID", "spice.channel_id",
3521 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3524 { &hf_num_common_caps
,
3525 { "Number of common capabilities", "spice.num_common_caps",
3526 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3529 { &hf_num_channel_caps
,
3530 { "Number of channel capabilities", "spice.num_channel_caps",
3531 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3535 { "Capabilities offset (bytes)", "spice.caps_offset",
3536 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3540 { "spice ERROR", "spice.error_code",
3541 FT_UINT32
, BASE_DEC
, VALS(spice_link_err_vs
), 0x0,
3545 { "Message serial number", "spice.serial",
3546 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
3550 { "Message header", "spice.message_header",
3551 FT_NONE
, BASE_NONE
, NULL
, 0x0,
3555 { "Message body size (bytes)", "spice.message_size",
3556 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3560 { "Sub-list offset (bytes)", "spice.message_sublist",
3561 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3564 { &hf_ticket_client
,
3565 { "Ticket - client", "spice.ticket_client",
3566 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3569 { &hf_ticket_server
,
3570 { "Link result", "spice.ticket_server",
3571 FT_UINT32
, BASE_DEC
, VALS(spice_link_err_vs
), 0x0,
3574 { &hf_auth_select_client
,
3575 { "Authentication selected by client", "spice.auth_select_client",
3576 FT_UINT32
, BASE_DEC
, VALS(spice_auth_select_vs
), 0x0,
3579 { &hf_common_cap_auth_select
,
3580 { "Auth Selection", "spice.common_cap_auth_select",
3581 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION_MASK
,
3584 { &hf_common_cap_auth_spice
,
3585 { "Auth Spice", "spice.common_cap_auth_spice",
3586 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_COMMON_CAP_AUTH_SPICE_MASK
,
3589 { &hf_common_cap_auth_sasl
,
3590 { "Auth SASL", "spice.common_cap_auth_sasl",
3591 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_COMMON_CAP_AUTH_SASL_MASK
,
3594 { &hf_common_cap_mini_header
,
3595 { "Mini Header", "spice.common_cap_mini_header",
3596 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_COMMON_CAP_MINI_HEADER_MASK
,
3599 { &hf_playback_cap_celt_0_5_1
,
3600 { "CELT 0.5.1 playback channel support", "spice.playback_cap_celt_0_5_1",
3601 FT_BOOLEAN
, PLAYBACK_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_PLAYBACK_CAP_CELT_0_5_1_MASK
,
3604 { &hf_playback_cap_volume
,
3605 { "Volume playback channel support", "spice.playback_cap_volume",
3606 FT_BOOLEAN
, PLAYBACK_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_PLAYBACK_CAP_VOLUME_MASK
,
3609 { &hf_playback_cap_latency
,
3610 { "Latency playback channel support", "spice.playback_cap_latency",
3611 FT_BOOLEAN
, PLAYBACK_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_PLAYBACK_CAP_LATENCY_MASK
,
3614 { &hf_playback_cap_opus
,
3615 { "OPUS playback channel support", "spice.playback_cap_opus",
3616 FT_BOOLEAN
, PLAYBACK_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_PLAYBACK_CAP_OPUS_MASK
,
3619 { &hf_record_cap_celt
,
3620 { "CELT 0.5.1 record channel support", "spice.record_cap_celt",
3621 FT_BOOLEAN
, RECORD_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_RECORD_CAP_CELT_0_5_1_MASK
,
3624 { &hf_record_cap_volume
,
3625 { "Volume record channel support", "spice.record_cap_volume",
3626 FT_BOOLEAN
, RECORD_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_RECORD_CAP_VOLUME_MASK
,
3629 { &hf_record_cap_opus
,
3630 { "Opus record channel support", "spice.record_cap_opus",
3631 FT_BOOLEAN
, RECORD_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_RECORD_CAP_OPUS_MASK
,
3634 { &hf_display_cap_sized_stream
,
3635 { "Sized stream display channel support", "spice.display_cap_sized_stream",
3636 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_SIZED_STREAM_MASK
,
3639 { &hf_display_cap_monitors_config
,
3640 { "Monitors configuration display channel support", "spice.display_cap_monitors_config",
3641 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_MONITORS_CONFIG_MASK
,
3644 { &hf_display_cap_composite
,
3645 { "Composite capability display channel support", "spice.display_cap_composite",
3646 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_COMPOSITE_MASK
,
3649 { &hf_display_cap_a8_surface
,
3650 { "A8 bitmap display channel support", "spice.display_cap_a8_surface",
3651 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_A8_SURFACE_MASK
,
3654 { &hf_display_cap_stream_report
,
3655 { "Stream Report display channel support", "spice.display_cap_stream_report",
3656 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_STREAM_REPORT_MASK
,
3659 { &hf_display_cap_lz4_compression
,
3660 { "LZ4 Compression display channel support", "spice.display_cap_lz4_compression",
3661 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_LZ4_COMPRESSION_MASK
,
3664 { &hf_display_cap_pref_compression
,
3665 { "Pref Compression display channel support", "spice.display_cap_pref_compression",
3666 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_PREF_COMPRESSION_MASK
,
3669 { &hf_display_cap_gl_scanout
,
3670 { "GL Scanout display channel support", "spice.display_cap_gl_scanout",
3671 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_GL_SCANOUT_MASK
,
3674 { &hf_display_cap_multi_codec
,
3675 { "Multi-codec display channel support", "spice.display_cap_multi_codec",
3676 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_MULTI_CODEC_MASK
,
3679 { &hf_display_cap_codec_mjpeg
,
3680 { "MJPEG codec display channel support", "spice.display_cap_codec_mjpeg",
3681 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_CODEC_MJPEG_MASK
,
3684 { &hf_display_cap_codec_vp8
,
3685 { "VP8 codec display channel support", "spice.display_cap_codec_vp8",
3686 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_CODEC_VP8_MASK
,
3689 { &hf_display_cap_codec_h264
,
3690 { "H264 codec display channel support", "spice.display_cap_codec_h264",
3691 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_CODEC_H264_MASK
,
3694 { &hf_display_cap_pref_video_codec_type
,
3695 { "Preferred Video Codec Type display channel support", "spice.display_cap_pref_video_codec_type",
3696 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE_MASK
,
3699 { &hf_display_cap_codec_vp9
,
3700 { "VP9 codec display channel support", "spice.display_cap_codec_vp9",
3701 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_CODEC_VP9_MASK
,
3704 { &hf_display_cap_codec_h265
,
3705 { "H265 codec display channel support", "spice.display_cap_codec_h265",
3706 FT_BOOLEAN
, DISPLAY_CAP_NBITS
, TFS(&tfs_set_notset
), SPICE_DISPLAY_CAP_CODEC_H265_MASK
,
3710 { "Cursor channel capability", "spice.cursor_cap",
3711 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3715 { "Inputs channel capability", "spice.inputs_cap",
3716 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3719 { &hf_main_num_channels
,
3720 { "Number of Channels", "spice.main_num_channels",
3721 FT_UINT32
, 4, NULL
, 0x0,
3724 { &hf_main_cap_semi_migrate
,
3725 { "Semi-seamless migration capability", "spice.main_cap_semi_migrate",
3726 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE_MASK
,
3729 { &hf_main_cap_vm_name_uuid
,
3730 { "VM name and UUID messages capability", "spice.main_cap_vm_name_uuid",
3731 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_MAIN_CAP_VM_NAME_UUID_MASK
,
3734 { &hf_main_cap_agent_connected_tokens
,
3735 { "Agent connected tokens capability", "spice.main_cap_agent_connected_tokens",
3736 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS_MASK
,
3739 { &hf_main_cap_seamless_migrate
,
3740 { "Seamless migration capability", "spice.main_cap_seamless_migrate",
3741 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), SPICE_MAIN_CAP_SEAMLESS_MIGRATE_MASK
,
3744 { &hf_audio_timestamp
,
3745 { "Timestamp", "spice.audio_timestamp",
3746 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3750 { "Mode", "spice.audio_mode",
3751 FT_UINT16
, BASE_DEC
, VALS(playback_mode_vals
), 0x0,
3754 { &hf_audio_channels
,
3755 { "Channels", "spice.audio_channels",
3756 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3760 { "Format", "spice.audio_format",
3761 FT_UINT16
, BASE_DEC
, VALS(spice_audio_fmt_vs
), 0x0,
3764 { &hf_audio_frequency
,
3765 { "Frequency", "spice.audio_frequency",
3766 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3770 { "Volume", "spice.audio_volume",
3771 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3775 { "Mute", "spice.audio_mute",
3776 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3779 { &hf_audio_latency
,
3780 { "Latency (ms)", "spice.audio_latency",
3781 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3784 { &hf_red_set_ack_generation
,
3785 { "Set ACK generation", "spice.red_set_ack_generation",
3786 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3789 { &hf_red_set_ack_window
,
3790 { "Set ACK window (messages)", "spice.red_set_ack_window",
3791 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3795 { "Clip type", "spice.clip_type",
3796 FT_UINT8
, BASE_DEC
, VALS(spice_clip_type_vs
), 0x0,
3800 { "Mask flag", "spice.mask_flag",
3801 FT_UINT8
, BASE_DEC
, VALS(spice_mask_flags_vs
), 0x0,
3804 { &hf_display_rop_descriptor
,
3805 { "ROP descriptor", "spice.display_rop_descriptor",
3806 FT_UINT16
, BASE_HEX
, VALS(spice_ropd_vs
), 0x0,
3809 { &hf_display_scale_mode
,
3810 { "Scale mode", "spice.scale_mode",
3811 FT_UINT8
, BASE_DEC
, VALS(spice_image_scale_mode_vs
), 0x0,
3815 { "Ping ID", "spice.ping_id",
3816 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3819 { &hf_red_timestamp
,
3820 { "timestamp", "spice.timestamp",
3821 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
3824 { &hf_spice_display_mode_width
,
3825 { "Display Width", "spice.display_width",
3826 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3829 { &hf_spice_display_mode_height
,
3830 { "Display Height", "spice.display_height",
3831 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3834 { &hf_spice_display_mode_depth
,
3835 { "Color depth", "spice.display_depth",
3836 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3839 { &hf_image_desc_id
,
3840 { "Image ID", "spice.image_id",
3841 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
3844 { &hf_image_desc_type
,
3845 { "Image type", "spice.image_type",
3846 FT_UINT8
, BASE_DEC
, VALS(spice_image_type_vs
), 0x0,
3849 { &hf_image_desc_flags
,
3850 { "Flags", "spice.image_flags",
3851 FT_UINT8
, BASE_HEX
, VALS(spice_image_flags_vs
), 0x0,
3854 { &hf_image_desc_width
,
3855 { "Width", "spice.image_width",
3856 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3859 { &hf_image_desc_height
,
3860 { "Height", "spice.image_height",
3861 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3865 { "Width", "spice.quic_width",
3866 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3870 { "QUIC image type", "spice.quic_type",
3871 FT_UINT32
, BASE_DEC
, VALS(quic_type_vs
), 0x0,
3875 { "Height", "spice.quic_height",
3876 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3879 { &hf_quic_major_version
,
3880 { "QUIC major version", "spice.quic_major_version",
3881 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3884 { &hf_quic_minor_version
,
3885 { "QUIC minor version", "spice.quic_minor_version",
3886 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3890 { "Width", "spice.LZ_width",
3891 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3895 { "Height", "spice.LZ_height",
3896 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3900 { "Image type", "spice.LZ_RGB_type",
3901 FT_UINT8
, BASE_DEC
, VALS(LzImage_type_vs
), 0xf,
3904 { &hf_LZ_major_version
,
3905 { "LZ major version", "spice.LZ_major_version",
3906 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3909 { &hf_LZ_minor_version
,
3910 { "LZ minor version", "spice.LZ_minor_version",
3911 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3915 { "Stride", "spice.LZ_stride",
3916 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3919 { &hf_LZ_RGB_dict_id
,
3920 { "LZ RGB Dictionary ID", "spice.LZ_RGB_dict_id",
3921 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
3924 { &hf_cursor_trail_len
,
3925 { "Cursor trail length", "spice.cursor_trail_len",
3926 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3929 { &hf_cursor_trail_freq
,
3930 { "Cursor trail frequency", "spice.cursor_trail_freq",
3931 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3934 { &hf_cursor_trail_visible
,
3935 { "Cursor trail visibility", "spice.cursor_trail_visible",
3936 FT_UINT8
, BASE_DEC
, VALS(cursor_visible_vs
), 0x0,
3939 { &hf_cursor_unique
,
3940 { "Cursor unique ID", "spice.cursor_unique",
3941 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
3945 { "Cursor type", "spice.cursor_type",
3946 FT_UINT8
, BASE_HEX
, VALS(spice_cursor_type_vs
), 0x0,
3950 { "Cursor width", "spice.cursor_width",
3951 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3954 { &hf_cursor_height
,
3955 { "Cursor height", "spice.cursor_height",
3956 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3959 { &hf_cursor_hotspot_x
,
3960 { "Cursor hotspot X", "spice.cursor_hotspot_x",
3961 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3964 { &hf_cursor_hotspot_y
,
3965 { "Cursor hotspot Y", "spice.cursor_hotspot_y",
3966 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3969 { &hf_cursor_flags
, /*FIXME - those are flags */
3970 { "Cursor flags", "spice.cursor_flags",
3971 FT_UINT16
, BASE_HEX
, VALS(spice_cursor_flags_vs
), 0x0,
3975 { "Cursor ID", "spice.cursor_id",
3976 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
3979 { &hf_spice_display_init_cache_id
,
3980 { "Cache ID", "spice.display_init_cache_id",
3981 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3984 { &hf_spice_display_init_cache_size
,
3985 { "Cache size (pixels)", "spice.display_init_cache_size",
3986 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
3989 { &hf_spice_display_init_glz_dict_id
,
3990 { "GLZ Dictionary ID", "spice.display_init_glz_dict_id",
3991 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3994 { &hf_spice_display_init_dict_window_size
,
3995 { "Dictionary window size", "spice.display_init_dict_window_size",
3996 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4000 { "Brush type", "spice.brush_type",
4001 FT_UINT8
, BASE_DEC
, VALS(spice_brush_type_vs
), 0x0,
4005 { "Brush color", "spice.brush_rgb",
4006 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
4010 { "Pixmap width", "spice.pixmap_width",
4011 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4014 { &hf_pixmap_height
,
4015 { "Pixmap height", "spice.pixmap_height",
4016 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4019 { &hf_pixmap_stride
,
4020 { "Pixmap stride", "spice.pixmap_stride",
4021 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4024 { &hf_pixmap_address
,
4025 { "Pixmap palette pointer", "spice.pixmap_palette_address",
4026 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
4029 { &hf_pixmap_format
,
4030 { "Pixmap format", "spice.pixmap_format",
4031 FT_UINT8
, BASE_DEC
, VALS(spice_bitmap_fmt_vs
), 0x0,
4035 { "Pixmap flags", "spice.pixmap_flags",
4036 FT_UINT8
, BASE_HEX
, VALS(spice_bitmap_flags_vs
), 0x0,
4039 { &hf_keyboard_modifiers
,
4040 { "Keyboard modifiers", "spice.keyboard_modifiers",
4041 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
4044 { &hf_keyboard_modifier_scroll_lock
,
4045 { "Scroll Lock", "spice.keyboard_modifier_scroll_lock",
4046 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK
,
4049 { &hf_keyboard_modifier_num_lock
,
4050 { "Num Lock", "spice.keyboard_modifier_num_lock",
4051 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK
,
4054 { &hf_keyboard_modifier_caps_lock
,
4055 { "Caps Lock", "spice.keyboard_modifier_caps_lock",
4056 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK
,
4059 { &hf_keyboard_code
,
4060 { "Key scan code", "spice.keyboard_key_code",
4061 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
4064 { &hf_rectlist_size
,
4065 { "RectList size", "spice.rectlist_size",
4066 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4069 { &hf_migrate_dest_port
,
4070 { "Migrate Dest Port", "spice.migrate_dest_port",
4071 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4074 { &hf_migrate_dest_sport
,
4075 { "Migrate Dest Secure Port", "spice.migrate_dest_sport",
4076 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4079 { &hf_migrate_src_mig_version
,
4080 { "Migrate Source Migration Version", "spice.migrate_src_version",
4081 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4085 { "Session ID", "spice.main_session_id",
4086 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4089 { &hf_display_channels_hint
,
4090 { "Number of display channels", "spice.display_channels_hint",
4091 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4094 { &hf_supported_mouse_modes
,
4095 { "Supported mouse modes", "spice.supported_mouse_modes",
4096 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
4099 { &hf_supported_mouse_modes_flags
,
4100 { "Supported mouse modes", "spice.supported_mouse_modes_flags",
4101 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
4104 { &hf_current_mouse_mode
,
4105 { "Current mouse mode", "spice.current_mouse_mode",
4106 FT_UINT32
, BASE_HEX
, VALS(spice_mouse_mode_vs
), 0x0,
4109 { &hf_supported_mouse_modes_flag_client
,
4110 { "Client mode", "spice.supported_mouse_modes_flag_client",
4111 FT_BOOLEAN
, 2, TFS(&tfs_set_notset
), SPICE_MOUSE_MODE_CLIENT
,
4114 { &hf_supported_mouse_modes_flag_server
,
4115 { "Server mode", "spice.supported_mouse_modes_flags_server",
4116 FT_BOOLEAN
, 2, TFS(&tfs_set_notset
), SPICE_MOUSE_MODE_SERVER
,
4119 { &hf_current_mouse_mode_flags
,
4120 { "Current mouse mode", "spice.current_mouse_mode_flags",
4121 FT_UINT16
, BASE_HEX
, VALS(spice_mouse_mode_vs
), 0x0,
4124 { &hf_agent_connected
,
4125 { "Agent", "spice.agent",
4126 FT_UINT32
, BASE_DEC
, VALS(spice_agent_vs
), 0x0,
4130 { "Agent tokens", "spice.agent_tokens",
4131 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4134 { &hf_multi_media_time
,
4135 { "Current server multimedia time", "spice.multimedia_time",
4136 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4140 { "RAM hint", "spice.ram_hint",
4141 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4145 { "Mouse button ID", "spice.button",
4146 FT_UINT8
, BASE_DEC
, VALS(spice_mouse_button_vs
), 0x0,
4149 { &hf_buttons_state
,
4150 { "Mouse buttons state mask", "spice.buttons_state",
4151 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
4154 { &hf_button_mask_left
,
4155 { "Left", "spice.button_mask_left",
4156 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_MOUSE_BUTTON_MASK_LEFT
,
4159 { &hf_button_mask_middle
,
4160 { "Middle", "spice.button_mask_middle",
4161 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_MOUSE_BUTTON_MASK_MIDDLE
,
4164 { &hf_button_mask_right
,
4165 { "Right", "spice.button_mask_right",
4166 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
), SPICE_MOUSE_BUTTON_MASK_RIGHT
,
4169 { &hf_button_mask_reserved_bits
,
4170 { "Reserved bits", "spice.button_mask_reserved_bits",
4171 FT_UINT16
, BASE_HEX
, NULL
, 0xFFF8,
4172 "Must be zero", HFILL
}
4174 { &hf_mouse_display_id
,
4175 { "Mouse display ID", "spice.mouse_display_id",
4176 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4179 { &hf_display_text_fore_mode
,
4180 { "Text foreground mode", "spice.draw_text_fore_mode",
4181 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4184 { &hf_display_text_back_mode
,
4185 { "Text background mode", "spice.draw_text_back_mode",
4186 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4189 { &hf_display_monitor_config_count
,
4190 { "Monitor count", "spice.monitor_config_count",
4191 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4194 { &hf_display_monitor_config_max_allowed
,
4195 { "Max.allowed monitors", "spice.monitor_config_max_allowed",
4196 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4199 { &hf_display_stream_id
,
4200 { "Stream ID", "spice.display_stream_id",
4201 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4204 { &hf_display_stream_report_unique_id
,
4205 { "Unique ID", "spice.display_stream_report_unique_id",
4206 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4209 { &hf_display_stream_report_max_window_size
,
4210 { "Max window size", "spice.display_stream_report_max_window_size",
4211 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4214 { &hf_display_stream_report_timeout
,
4215 { "Timeout (ms)", "spice.display_stream_report_timeout",
4216 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4219 { &hf_display_stream_flags
,
4220 { "Stream flags", "spice.display_stream_flags",
4221 FT_UINT8
, BASE_DEC
, VALS(spice_stream_flags_vs
), 0x0,
4224 { &hf_display_stream_codec_type
,
4225 { "Stream codec type", "spice.display_stream_codec_type",
4226 FT_UINT32
, BASE_DEC
, VALS(spice_video_codec_type_vs
), 0x0,
4229 { &hf_display_stream_stamp
,
4230 { "Stream stamp", "spice.display_stream_stamp",
4231 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
4234 { &hf_display_stream_data_size
,
4235 { "Stream data size", "spice.display_stream_data_size",
4236 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4239 { &hf_display_stream_width
,
4240 { "Stream width", "spice.stream_width",
4241 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4244 { &hf_display_stream_height
,
4245 { "Stream height", "spice.stream_height",
4246 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4249 { &hf_display_stream_src_width
,
4250 { "Stream source width", "spice.stream_src_width",
4251 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4254 { &hf_display_stream_src_height
,
4255 { "Stream source height", "spice.stream_src_height",
4256 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4259 { &hf_display_surface_id
,
4260 { "Surface ID", "spice.surface_id",
4261 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4264 { &hf_display_surface_width
,
4265 { "Surface width", "spice.surface_width",
4266 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4269 { &hf_display_surface_height
,
4270 { "Surface height", "spice.surface_height",
4271 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4274 { &hf_display_surface_format
,
4275 { "Surface format", "spice.surface_format",
4276 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4279 { &hf_display_surface_flags
,
4280 { "Surface flags", "spice.surface_flags",
4281 FT_UINT32
, BASE_DEC
, VALS(spice_surface_flags_vs
), 0x0,
4284 { &hf_tranparent_src_color
,
4285 { "Transparent source color", "spice.display_transparent_src_color",
4286 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
4289 { &hf_tranparent_true_color
,
4290 { "Transparent true color", "spice.display_transparent_true_color",
4291 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
4294 { &hf_main_client_agent_tokens
,
4295 { "Agent tokens", "spice.main_agent_tokens",
4296 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4299 { &hf_agent_protocol
,
4300 { "Agent Protocol version", "spice.main_agent_protocol",
4301 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4305 { "Agent message type", "spice.agent_message_type",
4306 FT_UINT32
, BASE_DEC
, VALS(agent_message_type_vs
), 0x0,
4310 { "Agent Opaque", "spice.main_agent_opaque",
4311 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
4315 { "Agent message size", "spice.main_agent_size",
4316 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4320 { "Agent token", "spice.main_agent_token",
4321 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4324 { &hf_agent_clipboard_selection
,
4325 { "Agent clipboard selection", "spice.main_agent_clipboard_selection",
4326 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4329 { &hf_agent_clipboard_type
,
4330 { "Agent clipboard type", "spice.main_agent_clipboard_type",
4331 FT_UINT32
, BASE_DEC
, VALS(agent_clipboard_type
), 0x0,
4335 { "LZ_PLT image type", "spice.LZ_PLT_type",
4336 FT_UINT32
, BASE_DEC
, VALS(LzImage_type_vs
), 0x0,
4339 { &hf_spice_sasl_auth_result
,
4340 { "Authentication result", "spice.sasl_auth_result",
4341 FT_UINT8
, BASE_DEC
, VALS(spice_sasl_auth_result_vs
), 0x0,
4345 { "UUID", "spice.main_uuid",
4346 FT_GUID
, BASE_NONE
, NULL
, 0x0,
4349 { &hf_main_name_len
,
4350 { "Name length", "spice.main_name_length",
4351 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4355 { "Name", "spice.main_name",
4356 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
4359 { &hf_display_head_id
,
4360 { "Head ID", "spice.display_head_id",
4361 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4364 { &hf_display_head_surface_id
,
4365 { "Head surface ID", "spice.display_head_surface_id",
4366 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4369 { &hf_display_head_width
,
4370 { "Head width", "spice.display_head_width",
4371 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4374 { &hf_display_head_height
,
4375 { "Head height", "spice.display_head_height",
4376 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4379 { &hf_display_head_x
,
4380 { "Head X coordinate", "spice.display_head_x",
4381 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4384 { &hf_display_head_y
,
4385 { "Head Y coordinate", "spice.display_head_y",
4386 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4389 { &hf_display_head_flags
,
4390 { "Head flags", "spice.display_head_flags",
4391 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4394 { &hf_zlib_uncompress_size
,
4395 { "ZLIB stream uncompressed size", "spice.zlib_uncompress_size",
4396 FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0,
4399 { &hf_zlib_compress_size
,
4400 { "ZLIB stream compressed size", "spice.zlib_compress_size",
4401 FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0,
4405 { "left", "spice.rect.left",
4406 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4410 { "top", "spice.rect.top",
4411 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4415 { "right", "spice.rect.right",
4416 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4420 { "bottom", "spice.rect.bottom",
4421 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4425 { "x", "spice.point32.x",
4426 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4430 { "y", "spice.point32.y",
4431 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4435 { "x", "spice.point16.x",
4436 FT_INT16
, BASE_DEC
, NULL
, 0x0,
4440 { "y", "spice.point16.y",
4441 FT_INT16
, BASE_DEC
, NULL
, 0x0,
4445 { "Severity", "spice.notify_severity",
4446 FT_UINT32
, BASE_DEC
, VALS(spice_notify_severity_vs
), 0x0,
4450 { "Visibility", "spice.notify_visibility",
4451 FT_UINT32
, BASE_DEC
, VALS(spice_notify_visibility_vs
), 0x0,
4455 { "error/warn/info code", "spice.notify_code",
4456 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4459 { &hf_notify_message_len
,
4460 { "Message length", "spice.notify_message_length",
4461 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4464 { &hf_notify_message
,
4465 { "Message", "spice.notify_message",
4466 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4470 { "Number of glyphs", "spice.num_glyphs",
4471 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4475 { "Opened", "spice.port_opened",
4476 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4480 { "Event", "spice.port_event",
4481 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4485 { "data", "spice.data",
4486 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4489 { &hf_display_inval_list_count
,
4490 { "count", "spice.display_inval_list_count",
4491 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4494 { &hf_resource_type
,
4495 { "Type", "spice.resource_type",
4496 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4500 { "id", "spice.resource_id",
4501 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
4505 { "Image address", "spice.ref_image",
4506 FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0,
4510 { "String address", "spice.ref_string",
4511 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
4514 { &hf_agent_num_monitors
,
4515 { "Number of monitors", "spice.agent_num_monitors",
4516 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4519 { &hf_agent_monitor_height
,
4520 { "Height", "spice.agent_monitor_height",
4521 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4524 { &hf_agent_monitor_width
,
4525 { "Width", "spice.agent_monitor_width",
4526 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4529 { &hf_agent_monitor_depth
,
4530 { "Depth", "spice.agent_monitor_depth",
4531 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4534 { &hf_agent_monitor_x
,
4535 { "x", "spice.agent_monitor_x",
4536 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4539 { &hf_agent_monitor_y
,
4540 { "y", "spice.agent_monitor_y",
4541 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4544 { &hf_vd_agent_buttons
,
4545 { "Buttons", "spice.vd_agent_buttons",
4546 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4549 { &hf_vd_agent_caps_request
,
4550 { "Request", "spice.vd_agent_caps_request",
4551 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4554 { &hf_vd_agent_cap_mouse_state
,
4555 { "Mouse State", "spice.vd_agent_cap_mouse_state",
4556 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_MOUSE_STATE
,
4559 { &hf_vd_agent_cap_monitors_config
,
4560 { "Monitors config", "spice.vd_agent_cap_monitors_config",
4561 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_MONITORS_CONFIG
,
4564 { &hf_vd_agent_cap_reply
,
4565 { "Reply", "spice.vd_agent_cap_reply",
4566 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_REPLY
,
4569 { &hf_vd_agent_cap_clipboard
,
4570 { "Clipboard", "spice.vd_agent_cap_clipboard",
4571 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_CLIPBOARD
,
4574 { &hf_vd_agent_cap_display_config
,
4575 { "Display config", "spice.vd_agent_cap_display_config",
4576 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_DISPLAY_CONFIG
,
4579 { &hf_vd_agent_cap_clipboard_by_demand
,
4580 { "Clipboard by demand", "spice.vd_agent_cap_clipboard_by_demand",
4581 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND
,
4584 { &hf_vd_agent_cap_clipboard_selection
,
4585 { "Clipboard selection", "spice.vd_agent_cap_clipboard_selection",
4586 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_CLIPBOARD_SELECTION
,
4589 { &hf_vd_agent_cap_sparse_monitors_config
,
4590 { "Sparse monitors config", "spice.vd_agent_cap_sparse_monitors_config",
4591 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_SPARSE_MONITORS_CONFIG
,
4594 { &hf_vd_agent_cap_guest_lineend_lf
,
4595 { "Guest line-end LF", "spice.vd_agent_cap_guest_lineend_lf",
4596 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_GUEST_LINEEND_LF
,
4599 { &hf_vd_agent_cap_guest_lineend_crlf
,
4600 { "Guest line-end CRLF", "spice.vd_agent_cap_guest_lineend_crlf",
4601 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CAP_GUEST_LINEEND_CRLF
,
4604 { &hf_vd_agent_monitors_config_flag_use_pos
,
4605 { "Use position", "spice.vd_agent_monitors_config_flag_use_pos",
4606 FT_BOOLEAN
, 32, TFS(&tfs_set_notset
), VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS
,
4609 { &hf_vd_agent_reply_type
,
4610 { "Type", "spice.vd_agent_reply_type",
4611 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4614 { &hf_vd_agent_reply_error
,
4615 { "Error", "spice.vd_agent_reply_error",
4616 FT_UINT32
, BASE_DEC
, VALS(vd_agent_reply_error_vs
), 0x0,
4619 /* Generated from convert_proto_tree_add_text.pl */
4620 { &hf_spice_pixmap_pixels
, { "Pixmap pixels", "spice.pixmap_pixels", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4621 { &hf_spice_palette
, { "Palette", "spice.palette", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4622 { &hf_spice_cursor_data
, { "Cursor data", "spice.cursor_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4623 { &hf_spice_quic_image_size
, { "QUIC image size", "spice.quic_image_size", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
4624 { &hf_spice_quic_magic
, { "QUIC magic", "spice.quic_magic", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4625 { &hf_spice_quic_compressed_image_data
, { "QUIC compressed image data", "spice.quic_compressed_image_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4626 { &hf_spice_lz_magic
, { "LZ magic", "spice.lz_magic", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4627 { &hf_spice_lz_rgb_compressed_image_data
, { "LZ_RGB compressed image data", "spice.lz_rgb_compressed_image_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4628 { &hf_spice_topdown_flag
, { "Topdown flag", "spice.topdown_flag", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4629 { &hf_spice_unknown_bytes
, { "Unknown bytes", "spice.unknown_bytes", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4631 { &hf_spice_lz_jpeg_image_size
, { "LZ JPEG image size", "spice.lz_jpeg_image_size", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
4633 { &hf_spice_glz_rgb_image_size
, { "GLZ RGB image size", "spice.glz_rgb_image_size", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
4634 { &hf_spice_lz_rgb_image_size
, { "LZ RGB image size", "spice.lz_rgb_image_size", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
4635 { &hf_spice_lz_plt_flag
, { "LZ_PLT Flag", "spice.lz_plt_flag", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
4636 { &hf_spice_lz_plt_image_size
, { "LZ PLT image size", "spice.lz_plt_image_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4637 { &hf_spice_palette_offset
, { "palette offset", "spice.palette_offset", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
4638 { &hf_spice_lz_plt_data
, { "LZ_PLT data", "spice.lz_plt_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4639 { &hf_spice_zlib_stream
, { "ZLIB stream", "spice.zlib_stream", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4640 { &hf_spice_image_from_cache
, { "Image from Cache", "spice.image_from_cache", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4641 { &hf_spice_surface_id
, { "Surface ID", "spice.surface_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4642 { &hf_spice_image_from_cache_lossless
, { "Image from Cache - lossless", "spice.image_from_cache_lossless", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4643 { &hf_spice_ping_data
, { "PING DATA", "spice.ping_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4644 { &hf_spice_display_mark_message
, { "DISPLAY_MARK message", "spice.display_mark_message", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4645 { &hf_spice_display_reset_message
, { "DISPLAY_RESET message", "spice.display_reset_message", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4646 { &hf_spice_rop3
, { "ROP3", "spice.rop3", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4647 { &hf_spice_scale_mode
, { "scale mode", "spice.scale_mode", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4648 { &hf_spice_glyph_flags
, { "Glyph flags", "spice.glyph_flags", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
4649 { &hf_spice_stream_data
, { "Stream data", "spice.stream_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4650 { &hf_spice_vd_agent_clipboard_message
, { "VD_AGENT_CLIPBOARD message", "spice.vd_agent_clipboard_message", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4651 { &hf_spice_vd_agent_display_config_message
, { "VD_AGENT_DISPLAY_CONFIG message", "spice.vd_agent_display_config_message", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4652 { &hf_spice_reserved
, { "Reserved", "spice.reserved", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4653 { &hf_spice_vd_agent_clipboard_release_message
, { "VD_AGENT_CLIPBOARD_RELEASE message", "spice.vd_agent_clipboard_release_message", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4654 { &hf_spice_server_inputs_mouse_motion_ack_message
, { "Server INPUTS_MOUSE_MOTION_ACK message", "spice.server_inputs_mouse_motion_ack_message", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4655 { &hf_spice_name_length
, { "Name length (bytes)", "spice.name_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4656 { &hf_spice_x509_subjectpublickeyinfo
, { "X.509 SubjectPublicKeyInfo (ASN.1)", "spice.x509_subjectpublickeyinfo", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4657 { &hf_spice_sasl_message_length
, { "SASL message length", "spice.sasl_message_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4658 { &hf_spice_supported_authentication_mechanisms_list_length
, { "Supported authentication mechanisms list length", "spice.supported_authentication_mechanisms_list_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4659 { &hf_spice_supported_authentication_mechanisms_list
, { "Supported authentication mechanisms list", "spice.supported_authentication_mechanisms_list", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4660 { &hf_spice_selected_authentication_mechanism_length
, { "Selected authentication mechanism length", "spice.selected_authentication_mechanism_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4661 { &hf_spice_selected_authentication_mechanism
, { "Selected authentication mechanism", "spice.selected_authentication_mechanism", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4662 { &hf_spice_client_out_mechanism_length
, { "Client out mechanism length", "spice.client_out_mechanism_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4663 { &hf_spice_selected_client_out_mechanism
, { "Selected client out mechanism", "spice.selected_client_out_mechanism", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4664 { &hf_spice_sasl_authentication_data
, { "SASL authentication data", "spice.sasl_authentication_data", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4665 { &hf_spice_clientout_length
, { "clientout length", "spice.clientout_length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
4666 { &hf_spice_clientout_list
, { "clientout list", "spice.clientout_list", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4667 { &hf_spice_sasl_data
, { "SASL data", "spice.sasl_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
4670 /* Setup protocol subtree arrays */
4671 static int *ett
[] = {
4677 &ett_auth_select_client
,
4682 &ett_common_server_message
,
4683 &ett_common_client_message
,
4684 &ett_display_client
,
4685 &ett_display_server
,
4719 static ei_register_info ei
[] = {
4720 { &ei_spice_decompress_error
, { "spice.decompress_error", PI_PROTOCOL
, PI_WARN
, "Error: Unable to decompress content", EXPFILL
}},
4721 { &ei_spice_unknown_message
, { "spice.unknown_message", PI_UNDECODED
, PI_WARN
, "Unknown message - cannot dissect", EXPFILL
}},
4722 { &ei_spice_not_dissected
, { "spice.not_dissected", PI_UNDECODED
, PI_WARN
, "Message not dissected", EXPFILL
}},
4723 { &ei_spice_auth_unknown
, { "spice.auth_unknown", PI_PROTOCOL
, PI_WARN
, "Unknown authentication selected", EXPFILL
}},
4724 { &ei_spice_sasl_auth_result
, { "spice.sasl_auth_result.expert", PI_PROTOCOL
, PI_WARN
, "Bad sasl_auth_result", EXPFILL
}},
4725 { &ei_spice_expected_from_client
, { "spice.expected_from_client", PI_PROTOCOL
, PI_WARN
, "SPICE_CLIENT_AUTH_SELECT: packet from server - expected from client", EXPFILL
}},
4726 /* Generated from convert_proto_tree_add_text.pl */
4727 { &ei_spice_unknown_image_type
, { "spice.unknown_image_type", PI_UNDECODED
, PI_WARN
, "Unknown image type - cannot dissect", EXPFILL
}},
4728 { &ei_spice_brush_type
, { "spice.brush_type.invalid", PI_PROTOCOL
, PI_WARN
, "Invalid Brush type", EXPFILL
}},
4729 { &ei_spice_Mask_flag
, { "spice.mask_flag.irrelevant", PI_PROTOCOL
, PI_NOTE
, "value irrelevant as bitmap address is 0", EXPFILL
}},
4730 { &ei_spice_Mask_point
, { "spice.mask_point.irrelevant", PI_PROTOCOL
, PI_NOTE
, "value irrelevant as bitmap address is 0", EXPFILL
}},
4731 { &ei_spice_unknown_channel
, { "spice.unknown_channel", PI_UNDECODED
, PI_WARN
, "Unknown channel - cannot dissect", EXPFILL
}},
4732 { &ei_spice_common_cap_unknown
, { "spice.common_cap.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown common capability", EXPFILL
}},
4735 expert_module_t
* expert_spice
;
4737 /* Register the protocol name and description */
4738 proto_spice
= proto_register_protocol("Spice protocol", "Spice", "spice");
4740 /* Register the dissector handle */
4741 spice_handle
= register_dissector("spice", dissect_spice
, proto_spice
);
4743 /* Required function calls to register the header fields and subtrees */
4744 proto_register_field_array(proto_spice
, hf
, array_length(hf
));
4745 proto_register_subtree_array(ett
, array_length(ett
));
4746 expert_spice
= expert_register_protocol(proto_spice
);
4747 expert_register_field_array(expert_spice
, ei
, array_length(ei
));
4752 proto_reg_handoff_spice(void)
4754 dissector_add_for_decode_as_with_preference("tcp.port", spice_handle
);
4755 heur_dissector_add("tcp", test_spice_protocol
, "Spice over TCP", "spice_tcp", proto_spice
, HEURISTIC_ENABLE
);
4756 jpeg_handle
= find_dissector_add_dependency("image-jfif", proto_spice
);
4760 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4765 * indent-tabs-mode: nil
4768 * vi: set shiftwidth=4 tabstop=8 expandtab:
4769 * :indentSize=4:tabSize=8:noTabs=true: