epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-x11.c
blobeca43a1d6a16f243e1fcddf7ddd15172ecd2444e
1 /* packet-x11.c
2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
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
13 /* TODO (in no particular order):
15 * - keep track of Atom creation by server to be able to display
16 * non-predefined atoms
17 * - Idem for keysym <-> keycode ???
18 * - Idem for fonts
19 * - Subtree the request ids (that is x11.create-window.window and
20 * x11.change-window.window should be distinct), and add hidden fields
21 * (so we still have x11.window).
22 * - add hidden fields so we can have x11.circulate-window in addition to
23 * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
24 * now)
25 * - add hidden fields so we have x11.listOfStuff.length
26 * - use a faster scheme that linear list searching for the opcode.
27 * - correct display of Unicode chars.
28 * - Not everything is homogeneous, in particular the handling of items in
29 * list is a total mess.
32 /* By the way, I wrote a program to generate every request and test
33 * that stuff. If you're interested, you can get it at
34 * http://tronche.com/gui/x/
37 #include "config.h"
40 #include <epan/packet.h>
41 #include <epan/exceptions.h>
42 #include <epan/conversation.h>
43 #include <epan/expert.h>
44 #include <epan/show_exception.h>
45 #include <epan/prefs.h>
47 #include "packet-x11-keysymdef.h"
48 #include "packet-x11.h"
50 #include <wsutil/array.h>
51 #include <wsutil/bits_count_ones.h>
53 void proto_register_x11(void);
54 void proto_reg_handoff_x11(void);
56 static dissector_handle_t x11_handle;
58 #define cVALS(x) (const value_string*)(x)
62 * Data structure associated with a conversation; keeps track of the
63 * request for which we're expecting a reply, the frame number of
64 * the initial connection request, and the byte order of the connection.
66 * An opcode of -3 means we haven't yet seen any requests yet.
67 * An opcode of -2 means we're not expecting a reply (unused).
68 * An opcode of -1 means we're waiting for a reply to the initial
69 * connection request.
70 * An opcode of 0 means the request was not seen (or unknown).
71 * Other values are the opcode of the request for which we're expecting
72 * a reply.
75 #define NOTHING_SEEN -3
76 #define NOTHING_EXPECTED -2
77 #define INITIAL_CONN -1
78 #define UNKNOWN_OPCODE 0
80 #define MAX_OPCODES (255 + 1) /* 255 + INITIAL_CONN */
81 #define LastExtensionError 255
82 #define LastExtensionEvent 127
84 #define BYTE_ORDER_UNKNOWN 0xFFFFFFFF
86 static const char *modifiers[] = {
87 "Shift",
88 "Lock",
89 "Control",
90 "Mod1",
91 "Mod2",
92 "Mod3",
93 "Mod4",
94 "Mod5"
97 /* Keymasks. From <X11/X.h>. */
98 #define ShiftMask (1<<0)
99 #define LockMask (1<<1)
100 #define ControlMask (1<<2)
101 #define Mod1Mask (1<<3)
102 #define Mod2Mask (1<<4)
103 #define Mod3Mask (1<<5)
104 #define Mod4Mask (1<<6)
105 #define Mod5Mask (1<<7)
107 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
108 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
110 /* from <X11/X.h> */
111 #define NoSymbol 0L /* special KeySym */
113 typedef struct _x11_conv_data {
114 wmem_map_t *seqtable; /* hashtable of sequencenumber <-> opcode. */
115 wmem_map_t *valtable; /* hashtable of sequencenumber <-> &opcode_vals */
116 /* major opcodes including extensions (NULL terminated) */
117 value_string opcode_vals[MAX_OPCODES+1];
118 /* error codes including extensions (NULL terminated) */
119 value_string errorcode_vals[LastExtensionError + 2];
120 /* event codes including extensions (NULL terminated) */
121 value_string eventcode_vals[LastExtensionEvent + 2];
122 wmem_map_t *eventcode_funcs; /* hashtable of eventcode <-> dissect_event() */
123 wmem_map_t *reply_funcs; /* hashtable of opcode <-> dissect_reply() */
125 int sequencenumber; /* sequencenumber of current packet. */
126 uint32_t iconn_frame; /* frame # of initial connection request */
127 uint32_t iconn_reply; /* frame # of initial connection reply */
128 unsigned byte_order; /* byte order of connection */
129 bool resync; /* resynchronization of sequence number performed */
131 int *keycodemap[256]; /* keycode to keysymvalue map. */
132 int keysyms_per_keycode;
133 int first_keycode;
134 int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
135 int keycodes_per_modifier;
137 union {
138 struct {
139 int first_keycode;
140 } GetKeyboardMapping;
141 } request;
142 } x11_conv_data_t;
144 static wmem_map_t *extension_table; /* hashtable of extension name <-> dispatch function */
145 static wmem_map_t *event_table; /* hashtable of extension name <-> event info list */
146 static wmem_map_t *genevent_table; /* hashtable of extension name <-> generic event info list */
147 static wmem_map_t *error_table; /* hashtable of extension name <-> error list */
148 static wmem_map_t *reply_table; /* hashtable of extension name <-> reply list */
150 /* Initialize the protocol and registered fields */
151 static int proto_x11;
153 #include "x11-declarations.h"
155 /* Initialize the subtree pointers */
156 static int ett_x11;
157 static int ett_x11_color_flags;
158 static int ett_x11_list_of_arc;
159 static int ett_x11_arc;
160 static int ett_x11_list_of_atom;
161 static int ett_x11_list_of_card32;
162 static int ett_x11_list_of_float;
163 static int ett_x11_list_of_double;
164 static int ett_x11_list_of_color_item;
165 static int ett_x11_color_item;
166 static int ett_x11_list_of_keycode;
167 static int ett_x11_list_of_keysyms;
168 static int ett_x11_keysym;
169 static int ett_x11_list_of_point;
170 static int ett_x11_point;
171 static int ett_x11_list_of_rectangle;
172 static int ett_x11_rectangle;
173 static int ett_x11_list_of_segment;
174 static int ett_x11_segment;
175 static int ett_x11_list_of_string8;
176 static int ett_x11_list_of_text_item;
177 static int ett_x11_text_item;
178 static int ett_x11_gc_value_mask; /* XXX - unused */
179 static int ett_x11_event_mask; /* XXX - unused */
180 static int ett_x11_do_not_propagate_mask; /* XXX - unused */
181 static int ett_x11_set_of_key_mask;
182 static int ett_x11_pointer_event_mask; /* XXX - unused */
183 static int ett_x11_window_value_mask; /* XXX - unused */
184 static int ett_x11_configure_window_mask; /* XXX - unused */
185 static int ett_x11_keyboard_value_mask; /* XXX - unused */
186 static int ett_x11_same_screen_focus;
187 static int ett_x11_event;
188 static int ett_x11_list_of_pixmap_format;
189 static int ett_x11_pixmap_format;
190 static int ett_x11_list_of_screen;
191 static int ett_x11_screen;
192 static int ett_x11_list_of_depth_detail;
193 static int ett_x11_depth_detail;
194 static int ett_x11_list_of_visualtype;
195 static int ett_x11_visualtype;
197 static expert_field ei_x11_invalid_format;
198 static expert_field ei_x11_request_length;
199 static expert_field ei_x11_keycode_value_out_of_range;
201 /* desegmentation of X11 messages */
202 static bool x11_desegment = true;
204 #define DEFAULT_X11_PORT_RANGE "6000-6063"
207 * Round a length to a multiple of 4 bytes.
209 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
211 /************************************************************************
212 *** ***
213 *** E N U M T A B L E S D E F I N I T I O N S ***
214 *** ***
215 ************************************************************************/
217 static const value_string byte_order_vals[] = {
218 { 'B', "Big-endian" },
219 { 'l', "Little-endian" },
220 { 0, NULL }
223 static const value_string image_byte_order_vals[] = {
224 { 0, "LSBFirst" },
225 { 1, "MSBFirst" },
226 { 0, NULL }
229 static const value_string access_mode_vals[] = {
230 { 0, "Disable" },
231 { 1, "Enable" },
232 { 0, NULL }
235 static const value_string all_temporary_vals[] = {
236 { 0, "AllTemporary" },
237 { 0, NULL }
240 static const value_string alloc_vals[] = {
241 { 0, "None" },
242 { 1, "All" },
243 { 0, NULL }
246 static const value_string allow_events_mode_vals[] = {
247 { 0, "AsyncPointer" },
248 { 1, "SyncPointer" },
249 { 2, "ReplayPointer" },
250 { 3, "AsyncKeyboard" },
251 { 4, "SyncKeyboard" },
252 { 5, "ReplayKeyboard" },
253 { 6, "AsyncBoth" },
254 { 7, "SyncBoth" },
255 { 0, NULL }
258 static const value_string arc_mode_vals[] = {
259 { 0, "Chord" },
260 { 1, "PieSlice" },
261 { 0, NULL }
264 static const char *atom_predefined_interpretation[] = {
265 "<error>",
266 "PRIMARY",
267 "SECONDARY",
268 "ARC",
269 "ATOM",
270 "BITMAP",
271 "CARDINAL",
272 "COLORMAP",
273 "CURSOR",
274 "CUT_BUFFER0",
275 "CUT_BUFFER1",
276 "CUT_BUFFER2",
277 "CUT_BUFFER3",
278 "CUT_BUFFER4",
279 "CUT_BUFFER5",
280 "CUT_BUFFER6",
281 "CUT_BUFFER7",
282 "DRAWABLE",
283 "FONT",
284 "INTEGER",
285 "PIXMAP",
286 "POINT",
287 "RECTANGLE",
288 "RESOURCE_MANAGER",
289 "RGB_COLOR_MAP",
290 "RGB_BEST_MAP",
291 "RGB_BLUE_MAP",
292 "RGB_DEFAULT_MAP",
293 "RGB_GRAY_MAP",
294 "RGB_GREEN_MAP",
295 "RGB_RED_MAP",
296 "STRING",
297 "VISUALID",
298 "WINDOW",
299 "WM_COMMAND",
300 "WM_HINTS",
301 "WM_CLIENT_MACHINE",
302 "WM_ICON_NAME",
303 "WM_ICON_SIZE",
304 "WM_NAME",
305 "WM_NORMAL_HINTS",
306 "WM_SIZE_HINTS",
307 "WM_ZOOM_HINTS",
308 "MIN_SPACE",
309 "NORM_SPACE",
310 "MAX_SPACE",
311 "END_SPACE",
312 "SUPERSCRIPT_X",
313 "SUPERSCRIPT_Y",
314 "SUBSCRIPT_X",
315 "SUBSCRIPT_Y",
316 "UNDERLINE_POSITION",
317 "UNDERLINE_THICKNESS",
318 "STRIKEOUT_ASCENT",
319 "STRIKEOUT_DESCENT",
320 "ITALIC_ANGLE",
321 "X_HEIGHT",
322 "QUAD_WIDTH",
323 "WEIGHT",
324 "POINT_SIZE",
325 "RESOLUTION",
326 "COPYRIGHT",
327 "NOTICE",
328 "FONT_NAME",
329 "FAMILY_NAME",
330 "FULL_NAME",
331 "CAP_HEIGHT",
332 "WM_CLASS",
333 "WM_TRANSIENT_FOR",
336 static const value_string auto_repeat_mode_vals[] = {
337 { 0, "Off" },
338 { 1, "On" },
339 { 2, "Default" },
340 { 0, NULL }
343 static const value_string background_pixmap_vals[] = {
344 { 0, "None" },
345 { 1, "ParentRelative" },
346 { 0, NULL }
349 static const value_string backing_store_vals[] = {
350 { 0, "NotUseful" },
351 { 1, "WhenMapped" },
352 { 2, "Always" },
353 { 0, NULL }
356 static const value_string border_pixmap_vals[] = {
357 { 0, "CopyFromParent" },
358 { 0, NULL }
361 static const value_string button_vals[] = {
362 { 0x8000, "AnyButton" },
363 { 0, NULL }
366 static const value_string cap_style_vals[] = {
367 { 0, "NotLast" },
368 { 1, "Butt" },
369 { 2, "Round" },
370 { 3, "Projecting" },
371 { 0, NULL }
374 static const value_string class_vals[] = {
375 { 0, "Cursor" },
376 { 1, "Tile" },
377 { 2, "Stipple" },
378 { 0, NULL }
381 static const value_string close_down_mode_vals[] = {
382 { 0, "Destroy" },
383 { 1, "RetainPermanent" },
384 { 2, "RetainTemporary" },
385 { 0, NULL }
388 static const value_string colormap_state_vals[] = {
389 { 0, "Uninstalled" },
390 { 1, "Installed" },
391 { 0, NULL }
394 static const value_string coordinate_mode_vals[] = {
395 { 0, "Origin" },
396 { 1, "Previous" },
397 { 0, NULL }
400 static const value_string destination_vals[] = {
401 { 0, "PointerWindow" },
402 { 1, "InputFocus" },
403 { 0, NULL }
406 static const value_string direction_vals[] = {
407 { 0, "RaiseLowest" },
408 { 1, "LowerHighest" },
409 { 0, NULL }
412 static const value_string event_detail_vals[] = {
413 { 0, "Ancestor" },
414 { 1, "Virtual" },
415 { 2, "Inferior" },
416 { 3, "Nonlinear" },
417 { 4, "NonlinearVirtual" },
418 { 0, NULL }
421 #define FAMILY_INTERNET 0
422 #define FAMILY_DECNET 1
423 #define FAMILY_CHAOS 2
425 static const value_string family_vals[] = {
426 { FAMILY_INTERNET, "Internet" },
427 { FAMILY_DECNET, "DECnet" },
428 { FAMILY_CHAOS, "Chaos" },
429 { 0, NULL }
432 static const value_string fill_rule_vals[] = {
433 { 0, "EvenOdd" },
434 { 1, "Winding" },
435 { 0, NULL }
438 static const value_string fill_style_vals[] = {
439 { 0, "Solid" },
440 { 1, "Tiled" },
441 { 2, "Stippled" },
442 { 3, "OpaqueStippled" },
443 { 0, NULL }
446 static const value_string focus_detail_vals[] = {
447 { 0, "Ancestor" },
448 { 1, "Virtual" },
449 { 2, "Inferior" },
450 { 3, "Nonlinear" },
451 { 4, "NonlinearVirtual" },
452 { 5, "Pointer" },
453 { 6, "PointerRoot" },
454 { 7, "None" },
455 { 0, NULL }
458 static const value_string focus_mode_vals[] = {
459 { 0, "Normal" },
460 { 1, "Grab" },
461 { 2, "Ungrab" },
462 { 3, "WhileGrabbed" },
463 { 0, NULL }
466 static const value_string focus_vals[] = {
467 { 0, "None" },
468 { 1, "PointerRoot" },
469 { 0, NULL }
472 static const value_string function_vals[] = {
473 { 0, "Clear" },
474 { 1, "And" },
475 { 2, "AndReverse" },
476 { 3, "Copy" },
477 { 4, "AndInverted" },
478 { 5, "NoOp" },
479 { 6, "Xor" },
480 { 7, "Or" },
481 { 8, "Nor" },
482 { 9, "Equiv" },
483 { 10, "Invert" },
484 { 11, "OrReverse" },
485 { 12, "CopyInverted" },
486 { 13, "OrInverted" },
487 { 14, "Nand" },
488 { 15, "Set" },
489 { 0, NULL }
492 static const value_string grab_mode_vals[] = {
493 { 0, "Normal" },
494 { 1, "Grab" },
495 { 2, "Ungrab" },
496 { 0, NULL }
499 static const value_string grab_status_vals[] = {
500 { 0, "Success" },
501 { 1, "AlreadyGrabbed" },
502 { 2, "InvalidTime" },
503 { 3, "NotViewable" },
504 { 4, "Frozen" },
505 { 0, NULL }
508 static const value_string bit_gravity_vals[] = {
509 { 0, "Forget" },
510 { 1, "NorthWest" },
511 { 2, "North" },
512 { 3, "NorthEast" },
513 { 4, "West" },
514 { 5, "Center" },
515 { 6, "East" },
516 { 7, "SouthWest" },
517 { 8, "South" },
518 { 9, "SouthEast" },
519 { 10, "Static" },
520 { 0, NULL }
523 static const value_string win_gravity_vals[] = {
524 { 0, "Unmap" },
525 { 1, "NorthWest" },
526 { 2, "North" },
527 { 3, "NorthEast" },
528 { 4, "West" },
529 { 5, "Center" },
530 { 6, "East" },
531 { 7, "SouthWest" },
532 { 8, "South" },
533 { 9, "SouthEast" },
534 { 10, "Static" },
535 { 0, NULL }
538 static const value_string image_format_vals[] = {
539 { 0, "Bitmap" },
540 { 1, "XYPixmap" },
541 { 2, "ZPixmap" },
542 { 0, NULL }
545 static const value_string image_pixmap_format_vals[] = {
546 { 1, "XYPixmap" },
547 { 2, "ZPixmap" },
548 { 0, NULL }
551 static const value_string join_style_vals[] = {
552 { 0, "Miter" },
553 { 1, "Round" },
554 { 2, "Bevel" },
555 { 0, NULL }
558 static const value_string key_vals[] = {
559 { 0, "AnyKey" },
560 { 0, NULL }
563 #include "x11-keysym.h"
565 static const value_string line_style_vals[] = {
566 { 0, "Solid" },
567 { 1, "OnOffDash" },
568 { 2, "DoubleDash" },
569 { 0, NULL }
572 static const value_string mode_vals[] = {
573 { 0, "Replace" },
574 { 1, "Prepend" },
575 { 2, "Append" },
576 { 0, NULL }
579 static const value_string on_off_vals[] = {
580 { 0, "Off" },
581 { 1, "On" },
582 { 0, NULL }
585 static const value_string place_vals[] = {
586 { 0, "Top" },
587 { 1, "Bottom" },
588 { 0, NULL }
591 static const value_string property_state_vals[] = {
592 { 0, "NewValue" },
593 { 1, "Deleted" },
594 { 0, NULL }
597 static const value_string visibility_state_vals[] = {
598 { 0, "Unobscured" },
599 { 1, "PartiallyObscured" },
600 { 2, "FullyObscured" },
601 { 0, NULL }
604 static const value_string mapping_request_vals[] = {
605 { 0, "MappingModifier" },
606 { 1, "MappingKeyboard" },
607 { 2, "MappingPointer" },
608 { 0, NULL }
611 /* Requestcodes. From <X11/Xproto.h>. */
612 #define X_CreateWindow 1
613 #define X_ChangeWindowAttributes 2
614 #define X_GetWindowAttributes 3
615 #define X_DestroyWindow 4
616 #define X_DestroySubwindows 5
617 #define X_ChangeSaveSet 6
618 #define X_ReparentWindow 7
619 #define X_MapWindow 8
620 #define X_MapSubwindows 9
621 #define X_UnmapWindow 10
622 #define X_UnmapSubwindows 11
623 #define X_ConfigureWindow 12
624 #define X_CirculateWindow 13
625 #define X_GetGeometry 14
626 #define X_QueryTree 15
627 #define X_InternAtom 16
628 #define X_GetAtomName 17
629 #define X_ChangeProperty 18
630 #define X_DeleteProperty 19
631 #define X_GetProperty 20
632 #define X_ListProperties 21
633 #define X_SetSelectionOwner 22
634 #define X_GetSelectionOwner 23
635 #define X_ConvertSelection 24
636 #define X_SendEvent 25
637 #define X_GrabPointer 26
638 #define X_UngrabPointer 27
639 #define X_GrabButton 28
640 #define X_UngrabButton 29
641 #define X_ChangeActivePointerGrab 30
642 #define X_GrabKeyboard 31
643 #define X_UngrabKeyboard 32
644 #define X_GrabKey 33
645 #define X_UngrabKey 34
646 #define X_AllowEvents 35
647 #define X_GrabServer 36
648 #define X_UngrabServer 37
649 #define X_QueryPointer 38
650 #define X_GetMotionEvents 39
651 #define X_TranslateCoords 40
652 #define X_WarpPointer 41
653 #define X_SetInputFocus 42
654 #define X_GetInputFocus 43
655 #define X_QueryKeymap 44
656 #define X_OpenFont 45
657 #define X_CloseFont 46
658 #define X_QueryFont 47
659 #define X_QueryTextExtents 48
660 #define X_ListFonts 49
661 #define X_ListFontsWithInfo 50
662 #define X_SetFontPath 51
663 #define X_GetFontPath 52
664 #define X_CreatePixmap 53
665 #define X_FreePixmap 54
666 #define X_CreateGC 55
667 #define X_ChangeGC 56
668 #define X_CopyGC 57
669 #define X_SetDashes 58
670 #define X_SetClipRectangles 59
671 #define X_FreeGC 60
672 #define X_ClearArea 61
673 #define X_CopyArea 62
674 #define X_CopyPlane 63
675 #define X_PolyPoint 64
676 #define X_PolyLine 65
677 #define X_PolySegment 66
678 #define X_PolyRectangle 67
679 #define X_PolyArc 68
680 #define X_FillPoly 69
681 #define X_PolyFillRectangle 70
682 #define X_PolyFillArc 71
683 #define X_PutImage 72
684 #define X_GetImage 73
685 #define X_PolyText8 74
686 #define X_PolyText16 75
687 #define X_ImageText8 76
688 #define X_ImageText16 77
689 #define X_CreateColormap 78
690 #define X_FreeColormap 79
691 #define X_CopyColormapAndFree 80
692 #define X_InstallColormap 81
693 #define X_UninstallColormap 82
694 #define X_ListInstalledColormaps 83
695 #define X_AllocColor 84
696 #define X_AllocNamedColor 85
697 #define X_AllocColorCells 86
698 #define X_AllocColorPlanes 87
699 #define X_FreeColors 88
700 #define X_StoreColors 89
701 #define X_StoreNamedColor 90
702 #define X_QueryColors 91
703 #define X_LookupColor 92
704 #define X_CreateCursor 93
705 #define X_CreateGlyphCursor 94
706 #define X_FreeCursor 95
707 #define X_RecolorCursor 96
708 #define X_QueryBestSize 97
709 #define X_QueryExtension 98
710 #define X_ListExtensions 99
711 #define X_ChangeKeyboardMapping 100
712 #define X_GetKeyboardMapping 101
713 #define X_ChangeKeyboardControl 102
714 #define X_GetKeyboardControl 103
715 #define X_Bell 104
716 #define X_ChangePointerControl 105
717 #define X_GetPointerControl 106
718 #define X_SetScreenSaver 107
719 #define X_GetScreenSaver 108
720 #define X_ChangeHosts 109
721 #define X_ListHosts 110
722 #define X_SetAccessControl 111
723 #define X_SetCloseDownMode 112
724 #define X_KillClient 113
725 #define X_RotateProperties 114
726 #define X_ForceScreenSaver 115
727 #define X_SetPointerMapping 116
728 #define X_GetPointerMapping 117
729 #define X_SetModifierMapping 118
730 #define X_GetModifierMapping 119
731 #define X_NoOperation 127
732 #define X_FirstExtension 128
733 #define X_LastExtension 255
735 static const value_string opcode_vals[] = {
736 { INITIAL_CONN, "Initial connection request" },
737 { X_CreateWindow, "CreateWindow" },
738 { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
739 { X_GetWindowAttributes, "GetWindowAttributes" },
740 { X_DestroyWindow, "DestroyWindow" },
741 { X_DestroySubwindows, "DestroySubwindows" },
742 { X_ChangeSaveSet, "ChangeSaveSet" },
743 { X_ReparentWindow, "ReparentWindow" },
744 { X_MapWindow, "MapWindow" },
745 { X_MapSubwindows, "MapSubwindows" },
746 { X_UnmapWindow, "UnmapWindow" },
747 { X_UnmapSubwindows, "UnmapSubwindows" },
748 { X_ConfigureWindow, "ConfigureWindow" },
749 { X_CirculateWindow, "CirculateWindow" },
750 { X_GetGeometry, "GetGeometry" },
751 { X_QueryTree, "QueryTree" },
752 { X_InternAtom, "InternAtom" },
753 { X_GetAtomName, "GetAtomName" },
754 { X_ChangeProperty, "ChangeProperty" },
755 { X_DeleteProperty, "DeleteProperty" },
756 { X_GetProperty, "GetProperty" },
757 { X_ListProperties, "ListProperties" },
758 { X_SetSelectionOwner, "SetSelectionOwner" },
759 { X_GetSelectionOwner, "GetSelectionOwner" },
760 { X_ConvertSelection, "ConvertSelection" },
761 { X_SendEvent, "SendEvent" },
762 { X_GrabPointer, "GrabPointer" },
763 { X_UngrabPointer, "UngrabPointer" },
764 { X_GrabButton, "GrabButton" },
765 { X_UngrabButton, "UngrabButton" },
766 { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
767 { X_GrabKeyboard, "GrabKeyboard" },
768 { X_UngrabKeyboard, "UngrabKeyboard" },
769 { X_GrabKey, "GrabKey" },
770 { X_UngrabKey, "UngrabKey" },
771 { X_AllowEvents, "AllowEvents" },
772 { X_GrabServer, "GrabServer" },
773 { X_UngrabServer, "UngrabServer" },
774 { X_QueryPointer, "QueryPointer" },
775 { X_GetMotionEvents, "GetMotionEvents" },
776 { X_TranslateCoords, "TranslateCoordinates" },
777 { X_WarpPointer, "WarpPointer" },
778 { X_SetInputFocus, "SetInputFocus" },
779 { X_GetInputFocus, "GetInputFocus" },
780 { X_QueryKeymap, "QueryKeymap" },
781 { X_OpenFont, "OpenFont" },
782 { X_CloseFont, "CloseFont" },
783 { X_QueryFont, "QueryFont" },
784 { X_QueryTextExtents, "QueryTextExtents" },
785 { X_ListFonts, "ListFonts" },
786 { X_ListFontsWithInfo, "ListFontsWithInfo" },
787 { X_SetFontPath, "SetFontPath" },
788 { X_GetFontPath, "GetFontPath" },
789 { X_CreatePixmap, "CreatePixmap" },
790 { X_FreePixmap, "FreePixmap" },
791 { X_CreateGC, "CreateGC" },
792 { X_ChangeGC, "ChangeGC" },
793 { X_CopyGC, "CopyGC" },
794 { X_SetDashes, "SetDashes" },
795 { X_SetClipRectangles, "SetClipRectangles" },
796 { X_FreeGC, "FreeGC" },
797 { X_ClearArea, "ClearArea" },
798 { X_CopyArea, "CopyArea" },
799 { X_CopyPlane, "CopyPlane" },
800 { X_PolyPoint, "PolyPoint" },
801 { X_PolyLine, "PolyLine" },
802 { X_PolySegment, "PolySegment" },
803 { X_PolyRectangle, "PolyRectangle" },
804 { X_PolyArc, "PolyArc" },
805 { X_FillPoly, "FillPoly" },
806 { X_PolyFillRectangle, "PolyFillRectangle" },
807 { X_PolyFillArc, "PolyFillArc" },
808 { X_PutImage, "PutImage" },
809 { X_GetImage, "GetImage" },
810 { X_PolyText8, "PolyText8" },
811 { X_PolyText16, "PolyText16" },
812 { X_ImageText8, "ImageText8" },
813 { X_ImageText16, "ImageText16" },
814 { X_CreateColormap, "CreateColormap" },
815 { X_FreeColormap, "FreeColormap" },
816 { X_CopyColormapAndFree, "CopyColormapAndFree" },
817 { X_InstallColormap, "InstallColormap" },
818 { X_UninstallColormap, "UninstallColormap" },
819 { X_ListInstalledColormaps, "ListInstalledColormaps" },
820 { X_AllocColor, "AllocColor" },
821 { X_AllocNamedColor, "AllocNamedColor" },
822 { X_AllocColorCells, "AllocColorCells" },
823 { X_AllocColorPlanes, "AllocColorPlanes" },
824 { X_FreeColors, "FreeColors" },
825 { X_StoreColors, "StoreColors" },
826 { X_StoreNamedColor, "StoreNamedColor" },
827 { X_QueryColors, "QueryColors" },
828 { X_LookupColor, "LookupColor" },
829 { X_CreateCursor, "CreateCursor" },
830 { X_CreateGlyphCursor, "CreateGlyphCursor" },
831 { X_FreeCursor, "FreeCursor" },
832 { X_RecolorCursor, "RecolorCursor" },
833 { X_QueryBestSize, "QueryBestSize" },
834 { X_QueryExtension, "QueryExtension" },
835 { X_ListExtensions, "ListExtensions" },
836 { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
837 { X_GetKeyboardMapping, "GetKeyboardMapping" },
838 { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
839 { X_GetKeyboardControl, "GetKeyboardControl" },
840 { X_Bell, "Bell" },
841 { X_ChangePointerControl, "ChangePointerControl" },
842 { X_GetPointerControl, "GetPointerControl" },
843 { X_SetScreenSaver, "SetScreenSaver" },
844 { X_GetScreenSaver, "GetScreenSaver" },
845 { X_ChangeHosts, "ChangeHosts" },
846 { X_ListHosts, "ListHosts" },
847 { X_SetAccessControl, "SetAccessControl" },
848 { X_SetCloseDownMode, "SetCloseDownMode" },
849 { X_KillClient, "KillClient" },
850 { X_RotateProperties, "RotateProperties" },
851 { X_ForceScreenSaver, "ForceScreenSaver" },
852 { X_SetPointerMapping, "SetPointerMapping" },
853 { X_GetPointerMapping, "GetPointerMapping" },
854 { X_SetModifierMapping, "SetModifierMapping" },
855 { X_GetModifierMapping, "GetModifierMapping" },
856 { X_NoOperation, "NoOperation" },
857 { 0, NULL }
860 /* Eventscodes. From <X11/X.h>. */
861 #define KeyPress 2
862 #define KeyRelease 3
863 #define ButtonPress 4
864 #define ButtonRelease 5
865 #define MotionNotify 6
866 #define EnterNotify 7
867 #define LeaveNotify 8
868 #define FocusIn 9
869 #define FocusOut 10
870 #define KeymapNotify 11
871 #define Expose 12
872 #define GraphicsExpose 13
873 #define NoExpose 14
874 #define VisibilityNotify 15
875 #define CreateNotify 16
876 #define DestroyNotify 17
877 #define UnmapNotify 18
878 #define MapNotify 19
879 #define MapRequest 20
880 #define ReparentNotify 21
881 #define ConfigureNotify 22
882 #define ConfigureRequest 23
883 #define GravityNotify 24
884 #define ResizeRequest 25
885 #define CirculateNotify 26
886 #define CirculateRequest 27
887 #define PropertyNotify 28
888 #define SelectionClear 29
889 #define SelectionRequest 30
890 #define SelectionNotify 31
891 #define ColormapNotify 32
892 #define ClientMessage 33
893 #define MappingNotify 34
894 #define GenericEvent 35
896 static const value_string eventcode_vals[] = {
897 { KeyPress, "KeyPress" },
898 { KeyRelease, "KeyRelease" },
899 { ButtonPress, "ButtonPress" },
900 { ButtonRelease, "ButtonRelease" },
901 { MotionNotify, "MotionNotify" },
902 { EnterNotify, "EnterNotify" },
903 { LeaveNotify, "LeaveNotify" },
904 { FocusIn, "FocusIn" },
905 { FocusOut, "FocusOut" },
906 { KeymapNotify, "KeymapNotify" },
907 { Expose, "Expose" },
908 { GraphicsExpose, "GraphicsExpose" },
909 { NoExpose, "NoExpose" },
910 { VisibilityNotify, "VisibilityNotify" },
911 { CreateNotify, "CreateNotify" },
912 { DestroyNotify, "DestroyNotify" },
913 { UnmapNotify, "UnmapNotify" },
914 { MapNotify, "MapNotify" },
915 { MapRequest, "MapRequest" },
916 { ReparentNotify, "ReparentNotify" },
917 { ConfigureNotify, "ConfigureNotify" },
918 { ConfigureRequest, "ConfigureRequest" },
919 { GravityNotify, "GravityNotify" },
920 { ResizeRequest, "ResizeRequest" },
921 { CirculateNotify, "CirculateNotify" },
922 { CirculateRequest, "CirculateRequest" },
923 { PropertyNotify, "PropertyNotify" },
924 { SelectionClear, "SelectionClear" },
925 { SelectionRequest, "SelectionRequest" },
926 { SelectionNotify, "SelectionNotify" },
927 { ColormapNotify, "ColormapNotify" },
928 { ClientMessage, "ClientMessage" },
929 { MappingNotify, "MappingNotify" },
930 { GenericEvent, "GenericEvent" },
931 { 0, NULL }
934 /* Errorcodes. From <X11/X.h> */
935 #define Success 0 /* everything's okay */
936 #define BadRequest 1 /* bad request code */
937 #define BadValue 2 /* int parameter out of range */
938 #define BadWindow 3 /* parameter not a Window */
939 #define BadPixmap 4 /* parameter not a Pixmap */
940 #define BadAtom 5 /* parameter not an Atom */
941 #define BadCursor 6 /* parameter not a Cursor */
942 #define BadFont 7 /* parameter not a Font */
943 #define BadMatch 8 /* parameter mismatch */
944 #define BadDrawable 9 /* parameter not a Pixmap or Window */
945 #define BadAccess 10 /* depending on context:
946 - key/button already grabbed
947 - attempt to free an illegal
948 cmap entry
949 - attempt to store into a read-only
950 color map entry.
951 - attempt to modify the access control
952 list from other than the local host.
954 #define BadAlloc 11 /* insufficient resources */
955 #define BadColormap 12 /* no such colormap */
956 #define BadGC 13 /* parameter not a GC */
957 #define BadIDChoice 14 /* choice not in range or already used */
958 #define BadName 15 /* font or color name doesn't exist */
959 #define BadLength 16 /* Request length incorrect */
960 #define BadImplementation 17 /* server is defective */
962 static const value_string errorcode_vals[] = {
963 { Success, "Success" },
964 { BadRequest, "BadRequest" },
965 { BadValue, "BadValue" },
966 { BadWindow, "BadWindow" },
967 { BadPixmap, "BadPixmap" },
968 { BadAtom, "BadAtom" },
969 { BadCursor, "BadCursor" },
970 { BadFont, "BadFont" },
971 { BadMatch, "BadMatch" },
972 { BadDrawable, "BadDrawable" },
973 { BadAccess, "BadAccess" },
974 { BadAlloc, "BadAlloc" },
975 { BadColormap, "BadColormap" },
976 { BadGC, "BadGC" },
977 { BadIDChoice, "BadIDChoice" },
978 { BadName, "BadName" },
979 { BadLength, "BadLength" },
980 { BadImplementation, "BadImplementation" },
981 { 0, NULL }
984 static const value_string ordering_vals[] = {
985 { 0, "UnSorted" },
986 { 1, "YSorted" },
987 { 2, "YXSorted" },
988 { 3, "YXBanded" },
989 { 0, NULL }
992 static const value_string plane_mask_vals[] = {
993 { 0xFFFFFFFF, "AllPlanes" },
994 { 0, NULL }
997 static const value_string pointer_keyboard_mode_vals[] = {
998 { 0, "Synchronous" },
999 { 1, "Asynchronous" },
1000 { 0, NULL }
1003 static const value_string revert_to_vals[] = {
1004 { 0, "None" },
1005 { 1, "PointerRoot" },
1006 { 2, "Parent" },
1007 { 0, NULL }
1010 static const value_string insert_delete_vals[] = {
1011 { 0, "Insert" },
1012 { 1, "Delete" },
1013 { 0, NULL }
1016 static const value_string screen_saver_mode_vals[] = {
1017 { 0, "Reset" },
1018 { 1, "Activate" },
1019 { 0, NULL }
1022 static const value_string shape_vals[] = {
1023 { 0, "Complex" },
1024 { 1, "Nonconvex" },
1025 { 2, "Convex" },
1026 { 0, NULL }
1029 static const value_string stack_mode_vals[] = {
1030 { 0, "Above" },
1031 { 1, "Below" },
1032 { 2, "TopIf" },
1033 { 3, "BottomIf" },
1034 { 4, "Opposite" },
1035 { 0, NULL }
1038 static const value_string subwindow_mode_vals[] = {
1039 { 0, "ClipByChildren" },
1040 { 1, "IncludeInferiors" },
1041 { 0, NULL }
1044 static const value_string window_class_vals[] = {
1045 { 0, "CopyFromParent" },
1046 { 1, "InputOutput" },
1047 { 2, "InputOnly" },
1048 { 0, NULL }
1051 static const value_string yes_no_default_vals[] = {
1052 { 0, "No" },
1053 { 1, "Yes" },
1054 { 2, "Default" },
1055 { 0, NULL }
1058 static const value_string zero_is_any_property_type_vals[] = {
1059 { 0, "AnyPropertyType" },
1060 { 0, NULL }
1063 static const value_string zero_is_none_vals[] = {
1064 { 0, "None" },
1065 { 0, NULL }
1068 /************************************************************************
1069 *** ***
1070 *** F I E L D D E C O D I N G M A C R O S ***
1071 *** ***
1072 ************************************************************************/
1073 #define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, byte_order))
1074 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, byte_order))
1075 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, byte_order))
1077 #define FLAG(position, name) {\
1078 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
1080 #define FLAG_IF_NONZERO(position, name) do {\
1081 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask) \
1082 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
1084 #define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, byte_order); }
1085 #define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
1086 #define BUTTON(name) FIELD8(name)
1087 #define CARD8(name) FIELD8(name)
1088 #define CARD16(name) (FIELD16(name))
1089 #define CARD32(name) (FIELD32(name))
1090 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1091 #define COLORMAP(name) FIELD32(name)
1092 #define CURSOR(name) FIELD32(name)
1093 #define DRAWABLE(name) FIELD32(name)
1094 #define ENUM8(name) (FIELD8(name))
1095 #define ENUM16(name) (FIELD16(name))
1096 #define FONT(name) FIELD32(name)
1097 #define FONTABLE(name) FIELD32(name)
1098 #define GCONTEXT(name) FIELD32(name)
1099 #define INT8(name) FIELD8(name)
1100 #define INT16(name) FIELD16(name)
1101 #define INT32(name) FIELD32(name)
1102 #define KEYCODE(name) FIELD8(name)
1103 #define KEYCODE_DECODED(name, keycode, mask) do { \
1104 proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
1105 keycode, "keycode: %d (%s)", \
1106 keycode, keycode2keysymString(state->keycodemap, \
1107 state->first_keycode, state->keysyms_per_keycode, \
1108 state->modifiermap, state->keycodes_per_modifier, \
1109 keycode, mask)); \
1110 ++offset; \
1111 } while (0)
1112 #define EVENT() do { \
1113 tvbuff_t *next_tvb; \
1114 unsigned char eventcode; \
1115 const char *sent; \
1116 proto_tree *event_proto_tree; \
1117 next_tvb = tvb_new_subset_length_caplen(tvb, offset, next_offset - offset, \
1118 next_offset - offset); \
1119 eventcode = tvb_get_uint8(next_tvb, 0); \
1120 sent = (eventcode & 0x80) ? "Sent-" : ""; \
1121 event_proto_tree = proto_tree_add_subtree_format(t, next_tvb, \
1122 0, -1, ett_x11_event, NULL, \
1123 "event: %d (%s)", \
1124 eventcode, \
1125 val_to_str(eventcode & 0x7F, \
1126 state->eventcode_vals, \
1127 "<Unknown eventcode %u>")); \
1128 decode_x11_event(next_tvb, eventcode, sent, event_proto_tree, \
1129 state, byte_order); \
1130 offset = next_offset; \
1131 } while (0)
1133 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, byte_order); }
1134 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, byte_order); }
1135 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), byte_order); }
1136 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), byte_order); }
1137 #define LISTofIPADDRESS(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), false); }
1138 #define LISTofCARD16(name, length) { listOfCard16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 2, byte_order); }
1139 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, byte_order); }
1140 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, byte_order); }
1141 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), byte_order); }
1142 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1143 keysyms_per_keycode) {\
1144 listOfKeysyms(tvb, pinfo, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), byte_order); }
1145 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, byte_order); }
1146 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, byte_order); }
1147 #define LISTofPIXMAPFORMAT(name, length) { listOfPixmapFormat(tvb, offsetp, t, hf_x11_##name, (length), byte_order); }
1148 #define LISTofSCREEN(name, length) { listOfScreen(tvb, offsetp, t, hf_x11_##name, (length), byte_order); }
1149 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, byte_order); }
1150 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), byte_order); }
1151 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, false, next_offset, byte_order); }
1152 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, true, next_offset, byte_order); }
1153 #define OPCODE() { \
1154 opcode = tvb_get_uint8(tvb, *offsetp); \
1155 proto_tree_add_uint(t, hf_x11_opcode, tvb, *offsetp, \
1156 1, opcode); \
1157 *offsetp += 1; \
1160 #define PIXMAP(name) { FIELD32(name); }
1161 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, byte_order))
1162 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, byte_order); }
1163 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, byte_order);}
1164 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, byte_order, 0); }
1165 #define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, byte_order, 1); }
1166 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, byte_order); }
1167 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1168 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, byte_order); }
1169 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, byte_order); }
1170 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, ENC_NA); *offsetp += x; }
1171 #define PAD() { if (next_offset - *offsetp > 0) proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, next_offset - *offsetp, ENC_NA); *offsetp = next_offset; }
1172 #define WINDOW(name) { FIELD32(name); }
1174 #define VISUALID(name) { int32_t v = tvb_get_uint32(tvb, *offsetp, byte_order); \
1175 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1176 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1177 #define REPLY(name) FIELD8(name);
1178 #define REPLYLENGTH(name) FIELD32(name);
1180 #define EVENTCONTENTS_COMMON() do { \
1181 TIMESTAMP(time); \
1182 WINDOW(rootwindow); \
1183 WINDOW(eventwindow); \
1184 WINDOW(childwindow); \
1185 INT16(root_x); \
1186 INT16(root_y); \
1187 INT16(event_x); \
1188 INT16(event_y); \
1189 setOfKeyButMask(tvb, offsetp, t, byte_order, 1); \
1190 } while (0)
1192 #define SEQUENCENUMBER_REPLY(name) do { \
1193 uint16_t seqno; \
1195 seqno = tvb_get_uint16(tvb, *offsetp, byte_order); \
1196 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1197 *offsetp, 2, seqno, \
1198 "sequencenumber: %d (%s)", \
1199 (int)seqno, \
1200 val_to_str(opcode & 0xFF, state->opcode_vals, "<Unknown opcode %d>")); \
1201 *offsetp += 2; \
1202 } while (0)
1204 #define REPLYCONTENTS_COMMON() do { \
1205 REPLY(reply); \
1206 proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, \
1207 1, ENC_NA); \
1208 ++(*offsetp); \
1209 SEQUENCENUMBER_REPLY(sequencenumber); \
1210 REPLYLENGTH(replylength); \
1211 proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, \
1212 tvb_reported_length_remaining(tvb, *offsetp), ENC_NA); \
1213 *offsetp += tvb_reported_length_remaining(tvb, *offsetp); \
1214 } while (0)
1217 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1218 if (length_remaining < plen) { \
1219 if (x11_desegment && pinfo->can_desegment) { \
1220 pinfo->desegment_offset = offset; \
1221 pinfo->desegment_len = plen - length_remaining; \
1222 return; \
1223 } else { \
1224 ; /* XXX yes, what then? Need to skip/join. */ \
1227 if (length_remaining > plen) \
1228 length_remaining = plen; \
1229 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length_remaining, plen); \
1231 if (sep == NULL) { \
1232 col_set_str(pinfo->cinfo, COL_INFO, str); \
1233 sep = ":"; \
1236 TRY { \
1237 func(next_tvb, pinfo, tree, sep, state, byte_order); \
1240 CATCH_NONFATAL_ERRORS { \
1241 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); \
1243 ENDTRY; \
1245 sep = ","; \
1246 } while (0)
1248 static void
1249 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1250 const char *sep, x11_conv_data_t *state,
1251 unsigned byte_order);
1253 static void
1254 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1255 const char *sep, x11_conv_data_t *state,
1256 unsigned byte_order);
1258 static void
1259 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1260 const char *sep, x11_conv_data_t *state,
1261 unsigned byte_order);
1263 static void
1264 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1265 const char *sep, x11_conv_data_t *state,
1266 unsigned byte_order);
1268 static void
1269 decode_x11_event(tvbuff_t *tvb, unsigned char eventcode, const char *sent,
1270 proto_tree *t, x11_conv_data_t *state,
1271 unsigned byte_order);
1273 static x11_conv_data_t *
1274 x11_stateinit(conversation_t *conversation);
1276 static const char *
1277 keysymString(uint32_t v);
1280 /************************************************************************
1281 *** ***
1282 *** D E C O D I N G F I E L D S ***
1283 *** ***
1284 ************************************************************************/
1286 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1287 unsigned byte_order)
1289 const char *interpretation = NULL;
1291 uint32_t v = tvb_get_uint32(tvb, *offsetp, byte_order);
1292 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1293 interpretation = atom_predefined_interpretation[v];
1294 else if (v)
1295 interpretation = "Not a predefined atom";
1296 else {
1297 header_field_info *hfi = proto_registrar_get_nth(hf);
1298 if (hfi -> strings)
1299 interpretation = try_val_to_str(v, cVALS(hfi -> strings));
1301 if (!interpretation) interpretation = "error in Xlib client program ?";
1302 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1303 proto_registrar_get_nth(hf) -> name, v, interpretation);
1304 *offsetp += 4;
1307 static uint32_t add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1309 uint32_t v = tvb_get_uint8(tvb, *offsetp);
1310 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1311 *offsetp += 1;
1312 return v;
1315 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1317 unsigned do_red_green_blue = tvb_get_uint8(tvb, *offsetp);
1318 proto_item *ti;
1319 proto_tree *tt;
1321 if (do_red_green_blue) {
1322 bool sep = false;
1323 wmem_strbuf_t *buffer = wmem_strbuf_create(wmem_packet_scope());
1324 wmem_strbuf_append(buffer, "flags: ");
1326 if (do_red_green_blue & 0x1) {
1327 wmem_strbuf_append(buffer, "DoRed");
1328 sep = true;
1331 if (do_red_green_blue & 0x2) {
1332 if (sep) wmem_strbuf_append(buffer, " | ");
1333 wmem_strbuf_append(buffer, "DoGreen");
1334 sep = true;
1337 if (do_red_green_blue & 0x4) {
1338 if (sep) wmem_strbuf_append(buffer, " | ");
1339 wmem_strbuf_append(buffer, "DoBlue");
1340 sep = true;
1343 if (do_red_green_blue & 0xf8) {
1344 if (sep) wmem_strbuf_append(buffer, " + trash");
1347 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1348 "%s", wmem_strbuf_get_str(buffer));
1349 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1350 if (do_red_green_blue & 0x1)
1351 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1352 do_red_green_blue & 0x1);
1353 if (do_red_green_blue & 0x2)
1354 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1355 do_red_green_blue & 0x2);
1356 if (do_red_green_blue & 0x4)
1357 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1358 do_red_green_blue & 0x4);
1359 if (do_red_green_blue & 0xf8)
1360 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1361 do_red_green_blue & 0xf8);
1362 } else
1363 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1364 "flags: none");
1365 *offsetp += 1;
1368 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1369 int length, unsigned byte_order)
1371 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1372 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1373 while(length--) {
1374 int16_t x = tvb_get_uint16(tvb, *offsetp, byte_order);
1375 int16_t y = tvb_get_uint16(tvb, *offsetp + 2, byte_order);
1376 uint16_t width = tvb_get_uint16(tvb, *offsetp + 4, byte_order);
1377 uint16_t height = tvb_get_uint16(tvb, *offsetp + 6, byte_order);
1378 int16_t angle1 = tvb_get_uint16(tvb, *offsetp + 8, byte_order);
1379 int16_t angle2 = tvb_get_uint16(tvb, *offsetp + 10, byte_order);
1381 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1382 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1383 width, height, x, y, angle1, angle2,
1384 angle1 / 64.0, angle2 / 64.0);
1385 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1386 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1387 *offsetp += 2;
1388 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1389 *offsetp += 2;
1390 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1391 *offsetp += 2;
1392 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1393 *offsetp += 2;
1394 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1395 *offsetp += 2;
1396 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1397 *offsetp += 2;
1401 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1402 int length, unsigned byte_order)
1404 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, byte_order);
1405 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1406 while(length--)
1407 atom(tvb, offsetp, tt, hf_x11_properties_item, byte_order);
1410 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1411 int length, unsigned byte_order)
1413 if (length <= 0) length = 1;
1414 proto_tree_add_item(t, hf, tvb, *offsetp, length, byte_order);
1415 *offsetp += length;
1418 static void listOfCard16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1419 int hf_item, int length, unsigned byte_order)
1421 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 2, byte_order);
1422 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1423 while(length--) {
1424 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 2, byte_order);
1425 *offsetp += 2;
1429 static void listOfInt16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1430 int hf_item, int length, unsigned byte_order)
1432 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 2, byte_order);
1433 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1434 while(length--) {
1435 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 2, byte_order);
1436 *offsetp += 2;
1440 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1441 int hf_item, int length, unsigned byte_order)
1443 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, byte_order);
1444 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1445 while(length--) {
1446 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 4, byte_order);
1447 *offsetp += 4;
1451 static void listOfInt32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1452 int hf_item, int length, unsigned byte_order)
1454 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, byte_order);
1455 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1456 while(length--) {
1457 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 4, byte_order);
1458 *offsetp += 4;
1462 static void listOfCard64(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1463 int hf_item, int length, unsigned byte_order)
1465 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1466 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1467 while(length--) {
1468 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 8, byte_order);
1469 *offsetp += 8;
1473 #if 0 /* Not yet used by any extension */
1474 static void listOfInt64(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1475 int hf_item, int length, unsigned byte_order)
1477 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1478 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1479 while(length--) {
1480 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 8, byte_order);
1481 *offsetp += 8;
1484 #endif
1486 static void listOfFloat(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1487 int hf_item, int length, unsigned byte_order)
1489 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, byte_order);
1490 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_float);
1491 while(length--) {
1492 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 4, byte_order);
1493 *offsetp += 4;
1497 static void listOfDouble(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1498 int hf_item, int length, unsigned byte_order)
1500 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1501 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_double);
1502 while(length--) {
1503 proto_tree_add_item(tt, hf_item, tvb, *offsetp, 8, byte_order);
1504 *offsetp += 8;
1508 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1509 int length, unsigned byte_order)
1511 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1512 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1513 while(length--) {
1514 proto_item *tti;
1515 proto_tree *ttt;
1516 unsigned do_red_green_blue;
1517 uint16_t red, green, blue;
1518 wmem_strbuf_t *buffer;
1519 const char *sep;
1521 buffer=wmem_strbuf_create(wmem_packet_scope());
1522 wmem_strbuf_append(buffer, "colorItem ");
1523 red = tvb_get_uint16(tvb, *offsetp + 4, byte_order);
1524 green = tvb_get_uint16(tvb, *offsetp + 6, byte_order);
1525 blue = tvb_get_uint16(tvb, *offsetp + 8, byte_order);
1526 do_red_green_blue = tvb_get_uint8(tvb, *offsetp + 10);
1528 sep = "";
1529 if (do_red_green_blue & 0x1) {
1530 wmem_strbuf_append_printf(buffer, "red = %d", red);
1531 sep = ", ";
1533 if (do_red_green_blue & 0x2) {
1534 wmem_strbuf_append_printf(buffer, "%sgreen = %d", sep, green);
1535 sep = ", ";
1537 if (do_red_green_blue & 0x4)
1538 wmem_strbuf_append_printf(buffer, "%sblue = %d", sep, blue);
1540 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", wmem_strbuf_get_str(buffer));
1541 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1542 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, byte_order);
1543 *offsetp += 4;
1544 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, byte_order);
1545 *offsetp += 2;
1546 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, byte_order);
1547 *offsetp += 2;
1548 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, byte_order);
1549 *offsetp += 2;
1550 colorFlags(tvb, offsetp, ttt);
1551 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, byte_order);
1552 *offsetp += 1;
1556 #if 0 /* XXX: Use of GTree no longer needed; use value_string_ext */
1557 static int compareGuint32(const void *a, const void *b)
1559 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1561 #endif
1563 static void
1564 XConvertCase(register int sym, int *lower, int *upper)
1566 *lower = sym;
1567 *upper = sym;
1568 switch(sym >> 8) {
1569 case 0: /* Latin 1 */
1570 if ((sym >= XK_A) && (sym <= XK_Z))
1571 *lower += (XK_a - XK_A);
1572 else if ((sym >= XK_a) && (sym <= XK_z))
1573 *upper -= (XK_a - XK_A);
1574 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1575 *lower += (XK_agrave - XK_Agrave);
1576 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1577 *upper -= (XK_agrave - XK_Agrave);
1578 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1579 *lower += (XK_oslash - XK_Ooblique);
1580 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1581 *upper -= (XK_oslash - XK_Ooblique);
1582 break;
1583 case 1: /* Latin 2 */
1584 /* Assume the KeySym is a legal value (ignore discontinuities) */
1585 if (sym == XK_Aogonek)
1586 *lower = XK_aogonek;
1587 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1588 *lower += (XK_lstroke - XK_Lstroke);
1589 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1590 *lower += (XK_scaron - XK_Scaron);
1591 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1592 *lower += (XK_zcaron - XK_Zcaron);
1593 else if (sym == XK_aogonek)
1594 *upper = XK_Aogonek;
1595 else if (sym >= XK_lstroke && sym <= XK_sacute)
1596 *upper -= (XK_lstroke - XK_Lstroke);
1597 else if (sym >= XK_scaron && sym <= XK_zacute)
1598 *upper -= (XK_scaron - XK_Scaron);
1599 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1600 *upper -= (XK_zcaron - XK_Zcaron);
1601 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1602 *lower += (XK_racute - XK_Racute);
1603 else if (sym >= XK_racute && sym <= XK_tcedilla)
1604 *upper -= (XK_racute - XK_Racute);
1605 break;
1606 case 2: /* Latin 3 */
1607 /* Assume the KeySym is a legal value (ignore discontinuities) */
1608 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1609 *lower += (XK_hstroke - XK_Hstroke);
1610 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1611 *lower += (XK_gbreve - XK_Gbreve);
1612 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1613 *upper -= (XK_hstroke - XK_Hstroke);
1614 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1615 *upper -= (XK_gbreve - XK_Gbreve);
1616 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1617 *lower += (XK_cabovedot - XK_Cabovedot);
1618 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1619 *upper -= (XK_cabovedot - XK_Cabovedot);
1620 break;
1621 case 3: /* Latin 4 */
1622 /* Assume the KeySym is a legal value (ignore discontinuities) */
1623 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1624 *lower += (XK_rcedilla - XK_Rcedilla);
1625 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1626 *upper -= (XK_rcedilla - XK_Rcedilla);
1627 else if (sym == XK_ENG)
1628 *lower = XK_eng;
1629 else if (sym == XK_eng)
1630 *upper = XK_ENG;
1631 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1632 *lower += (XK_amacron - XK_Amacron);
1633 else if (sym >= XK_amacron && sym <= XK_umacron)
1634 *upper -= (XK_amacron - XK_Amacron);
1635 break;
1636 case 6: /* Cyrillic */
1637 /* Assume the KeySym is a legal value (ignore discontinuities) */
1638 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1639 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1640 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1641 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1642 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1643 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1644 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1645 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1646 break;
1647 case 7: /* Greek */
1648 /* Assume the KeySym is a legal value (ignore discontinuities) */
1649 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1650 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1651 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1652 sym != XK_Greek_iotaaccentdieresis &&
1653 sym != XK_Greek_upsilonaccentdieresis)
1654 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1655 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1656 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1657 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1658 sym != XK_Greek_finalsmallsigma)
1659 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1660 break;
1664 static const char *
1665 keycode2keysymString(int *keycodemap[256], int first_keycode,
1666 int keysyms_per_keycode,
1667 int *modifiermap[array_length(modifiers)],
1668 int keycodes_per_modifier,
1669 uint32_t keycode, uint32_t bitmask)
1671 int *syms;
1672 int groupmodkc, numlockkc, numlockmod, groupmod;
1673 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1674 int lockmod_is_nosymbol = 1;
1675 int modifier, kc, keysym;
1677 if ((syms = keycodemap[keycode]) == NULL)
1678 return "<Unknown>";
1680 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1681 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1682 if (keycodemap[kc] == NULL)
1683 return "<Unknown>";
1684 switch (keycodemap[kc][keysym]) {
1685 case 0xff7e:
1686 groupmodkc = kc;
1687 break;
1689 case 0xff7f:
1690 numlockkc = kc;
1691 break;
1693 case 0xffe5:
1694 lockmod_is_capslock = kc;
1695 break;
1697 case 0xffe6:
1698 lockmod_is_shiftlock = kc;
1699 break;
1705 * If we have not seen the modifiermap we don't know what the
1706 * keycode translates to, but we do know it's one of the keys
1707 * in syms (give or take a case-conversion), so we could in
1708 * theory list them all.
1710 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1711 return "<Unknown>";
1713 /* find out what the numlockmodifer and groupmodifier is. */
1714 for (modifier = 0, numlockmod = groupmod = -1;
1715 modifier < (int)array_length(modifiers) && numlockmod == -1;
1716 ++modifier)
1717 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1718 if (modifiermap[modifier][kc] == numlockkc)
1719 numlockmod = modifier;
1720 else if (modifiermap[modifier][kc] == groupmodkc)
1721 groupmod = modifier;
1724 * ... and what the lockmodifier is interpreted as.
1725 * (X11v4r6 ref, keyboard and pointers section.)
1727 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1728 if (modifiermap[1][kc] == lockmod_is_capslock) {
1729 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1730 break;
1732 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1733 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1734 break;
1737 #if 0
1739 * This is (how I understand) the X11v4R6 protocol description given
1740 * in A. Nye's book. It is quite different from the
1741 * code in _XTranslateKey() in the file
1742 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1743 * as shipped with XFree, and doesn't work correctly, nor do I see
1744 * how it could (e.g. the case of lower/uppercase-letters).
1745 * -- Michael Shuldman
1748 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1749 && ((syms[1] >= 0xff80
1750 && syms[1] <= 0xffbd)
1751 || (syms[1] >= 0x11000000
1752 && syms[1] <= 0x1100ffff))) {
1753 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1754 return keysymString(syms[groupmod + 0]);
1755 else
1756 if (syms[groupmod + 1] == NoSymbol)
1757 return keysymString(syms[groupmod + 0]);
1758 else
1759 return keysymString(syms[groupmod + 1]);
1761 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1762 return keysymString(syms[groupmod + 0]);
1763 else if (!(bitmask & ShiftMask)
1764 && ((bitmask & LockMask) && lockmod_is_capslock))
1765 if (islower(syms[groupmod + 0]))
1766 /* return toupper(keysymString(syms[groupmod + 0])); */
1767 return "Uppercase"; /* XXX */
1768 else
1769 return keysymString(syms[groupmod + 0]);
1771 else if ((bitmask & ShiftMask)
1772 && ((bitmask & LockMask) && lockmod_is_capslock))
1773 if (islower(syms[groupmod + 1]))
1774 /* return toupper(keysymString(syms[groupmod + 1])); */
1775 return "Uppercase"; /* XXX */
1776 else
1777 return keysymString(syms[groupmod + 1]);
1779 else if ((bitmask & ShiftMask)
1780 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1781 return keysymString(syms[groupmod + 1]);
1782 #else /* _XTranslateKey() based code. */
1784 while (keysyms_per_keycode > 2
1785 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1786 --keysyms_per_keycode;
1787 if (keysyms_per_keycode > 2
1788 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1789 syms += 2;
1790 keysyms_per_keycode -= 2;
1793 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1794 && keysyms_per_keycode > 1
1795 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1796 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1797 if ((bitmask & ShiftMask)
1798 || (bitmask & LockMask && lockmod_is_shiftlock))
1799 keysym = syms[0];
1800 else
1801 keysym = syms[1];
1803 else if (!(bitmask & ShiftMask)
1804 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1805 if (keysyms_per_keycode == 1
1806 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1807 int usym;
1809 XConvertCase(syms[0], &keysym, &usym);
1811 else
1812 keysym = syms[0];
1814 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1815 int lsym, usym = 0;
1817 if (keysyms_per_keycode == 1
1818 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1819 XConvertCase(syms[0], &lsym, &usym);
1820 keysym = usym;
1822 else {
1823 int lsym, usym = 0;
1825 if (keysyms_per_keycode == 1
1826 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1827 keysym = syms[0];
1829 XConvertCase(keysym, &lsym, &usym);
1831 if (!(bitmask & ShiftMask) && keysym != syms[0]
1832 && ((keysym != usym) || (lsym == usym)))
1833 XConvertCase(syms[0], &lsym, &usym);
1834 keysym = usym;
1837 if (keysym == XK_VoidSymbol)
1838 keysym = NoSymbol;
1840 return wmem_strdup_printf(wmem_packet_scope(), "%d, \"%s\"", keysym, keysymString(keysym));
1841 #endif
1844 static const char *keysymString(uint32_t v)
1846 #if 0 /* XXX: Use of GTree no longer needed; use value_string_ext */
1847 static GTree *keysymTable = NULL;
1849 void *res;
1850 if (!keysymTable) {
1852 /* This table is so big that we built it only if necessary */
1853 const value_string *p = x11_keysym_vals_source;
1854 keysymTable = g_tree_new(compareGuint32);
1855 for(; p -> strptr; p++)
1856 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), (void *) (p -> strptr) );
1858 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1859 return res ? res : "<Unknown>";
1860 #endif
1862 return val_to_str_ext_const(v, &x11_keysym_vals_source_ext, "<Unknown>");
1866 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1867 int *modifiermap[], int keycodes_per_modifier,
1868 unsigned byte_order _U_)
1870 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1871 (int)array_length(modifiers) * keycodes_per_modifier, ENC_NA);
1872 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1873 size_t m;
1875 for (m = 0; m < array_length(modifiers);
1876 ++m, *offsetp += keycodes_per_modifier) {
1877 proto_item *tikc;
1878 int i;
1880 tikc = proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1881 *offsetp, keycodes_per_modifier, NULL, "item: ");
1882 modifiermap[m] = (int *)
1883 wmem_alloc(wmem_file_scope(), sizeof(*modifiermap[m]) * keycodes_per_modifier);
1884 for(i = 0; i < keycodes_per_modifier; ++i) {
1885 unsigned char c = tvb_get_uint8(tvb, (*offsetp) + i);
1887 if (c)
1888 proto_item_append_text(tikc, " %s=%d", modifiers[m], c);
1890 modifiermap[m][i] = c;
1895 static void listOfKeysyms(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, int hf,
1896 int hf_item, int *keycodemap[256],
1897 int keycode_first, int keycode_count,
1898 int keysyms_per_keycode, unsigned byte_order)
1900 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, byte_order);
1901 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1902 proto_item *tti;
1903 proto_tree *ttt;
1904 int i, keycode;
1906 DISSECTOR_ASSERT(keycode_first >= 0);
1907 DISSECTOR_ASSERT(keycode_count >= 0);
1909 for (keycode = keycode_first; keycode_count > 0;
1910 ++keycode, --keycode_count) {
1911 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1912 4 * keysyms_per_keycode, "keysyms (keycode %d):", keycode);
1913 if (keycode >= 256) {
1914 expert_add_info_format(pinfo, tti, &ei_x11_keycode_value_out_of_range,
1915 "keycode value %d is out of range", keycode);
1916 *offsetp += 4 * keysyms_per_keycode;
1917 continue;
1920 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1922 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1923 keycodemap[keycode]
1924 = (int *)wmem_alloc(wmem_file_scope(), sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1926 for(i = 0; i < keysyms_per_keycode; ++i) {
1927 /* keysymvalue = byte3 * 256 + byte4. */
1928 uint32_t v = tvb_get_uint32(tvb, *offsetp, byte_order);
1930 proto_item_append_text(tti, " %s", keysymString(v));
1931 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1932 tvb, *offsetp, 4, v,
1933 "keysym (keycode %d): 0x%08x (%s)",
1934 keycode, v, keysymString(v));
1936 keycodemap[keycode][i] = v;
1937 *offsetp += 4;
1940 for (i = 1; i < keysyms_per_keycode; ++i)
1941 if (keycodemap[keycode][i] != NoSymbol)
1942 break;
1944 if (i == keysyms_per_keycode) {
1945 /* all but (possibly) first were NoSymbol. */
1946 if (keysyms_per_keycode == 4) {
1947 keycodemap[keycode][1] = NoSymbol;
1948 keycodemap[keycode][2] = keycodemap[keycode][0];
1949 keycodemap[keycode][3] = NoSymbol;
1952 continue;
1955 for (i = 2; i < keysyms_per_keycode; ++i)
1956 if (keycodemap[keycode][i] != NoSymbol)
1957 break;
1958 if (i == keysyms_per_keycode) {
1959 /* all but (possibly) first two were NoSymbol. */
1960 if (keysyms_per_keycode == 4) {
1961 keycodemap[keycode][2] = keycodemap[keycode][0];
1962 keycodemap[keycode][3] = keycodemap[keycode][1];
1965 continue;
1970 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1971 int length, unsigned byte_order)
1973 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, byte_order);
1974 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1975 while(length--) {
1976 int16_t x, y;
1977 proto_item *tti;
1978 proto_tree *ttt;
1980 x = tvb_get_uint16(tvb, *offsetp, byte_order);
1981 y = tvb_get_uint16(tvb, *offsetp + 2, byte_order);
1983 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1984 ttt = proto_item_add_subtree(tti, ett_x11_point);
1985 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1986 *offsetp += 2;
1987 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1988 *offsetp += 2;
1992 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1993 int length, unsigned byte_order)
1995 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
1996 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1997 while(length--) {
1998 int16_t x, y;
1999 unsigned width, height;
2000 proto_item *tti;
2001 proto_tree *ttt;
2003 x = tvb_get_uint16(tvb, *offsetp, byte_order);
2004 y = tvb_get_uint16(tvb, *offsetp + 2, byte_order);
2005 width = tvb_get_uint16(tvb, *offsetp + 4, byte_order);
2006 height = tvb_get_uint16(tvb, *offsetp + 6, byte_order);
2008 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
2009 "rectangle: %dx%d+%d+%d", width, height, x, y);
2010 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
2011 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
2012 *offsetp += 2;
2013 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
2014 *offsetp += 2;
2015 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
2016 *offsetp += 2;
2017 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
2018 *offsetp += 2;
2022 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2023 int length, unsigned byte_order)
2025 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
2026 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
2027 while(length--) {
2028 int16_t x1, y1, x2, y2;
2029 proto_item *tti;
2030 proto_tree *ttt;
2032 x1 = tvb_get_uint16(tvb, *offsetp, byte_order);
2033 y1 = tvb_get_uint16(tvb, *offsetp + 2, byte_order);
2034 x2 = tvb_get_uint16(tvb, *offsetp + 4, byte_order);
2035 y2 = tvb_get_uint16(tvb, *offsetp + 6, byte_order);
2037 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
2038 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
2039 ttt = proto_item_add_subtree(tti, ett_x11_segment);
2040 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, byte_order);
2041 *offsetp += 2;
2042 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, byte_order);
2043 *offsetp += 2;
2044 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, byte_order);
2045 *offsetp += 2;
2046 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, byte_order);
2047 *offsetp += 2;
2051 static void listOfVisualTypes(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2052 int length, unsigned byte_order)
2054 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 24, byte_order);
2055 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_visualtype);
2056 while(length--) {
2057 proto_item *tti;
2058 proto_tree *ttt;
2060 tti = proto_tree_add_none_format(tt, hf_x11_visualtype, tvb, *offsetp, 24,
2061 "visualtype");
2062 ttt = proto_item_add_subtree(tti, ett_x11_visualtype);
2063 proto_tree_add_item(ttt, hf_x11_visualtype_visualid, tvb, *offsetp, 4, byte_order);
2064 *offsetp += 4;
2065 proto_tree_add_item(ttt, hf_x11_visualtype_class, tvb, *offsetp, 1, byte_order);
2066 *offsetp += 1;
2067 proto_tree_add_item(ttt, hf_x11_visualtype_bits_per_rgb_value, tvb, *offsetp, 1, byte_order);
2068 *offsetp += 1;
2069 proto_tree_add_item(ttt, hf_x11_visualtype_colormap_entries, tvb, *offsetp, 2, byte_order);
2070 *offsetp += 2;
2071 proto_tree_add_item(ttt, hf_x11_visualtype_red_mask, tvb, *offsetp, 4, byte_order);
2072 *offsetp += 4;
2073 proto_tree_add_item(ttt, hf_x11_visualtype_green_mask, tvb, *offsetp, 4, byte_order);
2074 *offsetp += 4;
2075 proto_tree_add_item(ttt, hf_x11_visualtype_blue_mask, tvb, *offsetp, 4, byte_order);
2076 *offsetp += 4;
2077 proto_tree_add_item(ttt, hf_x11_unused, tvb, *offsetp, 4, byte_order);
2078 *offsetp += 4;
2081 static void listOfDepth(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2082 int length, unsigned byte_order)
2084 uint16_t number_of_visualtypes;
2085 proto_item *ti;
2086 proto_tree *tt;
2088 ti = proto_tree_add_item(t, hf, tvb, *offsetp, -1, byte_order);
2089 tt = proto_item_add_subtree(ti, ett_x11_list_of_depth_detail);
2090 while(length--) {
2091 proto_item *tti;
2092 proto_tree *ttt;
2093 number_of_visualtypes = tvb_get_uint16(tvb, *offsetp + 2, byte_order);
2095 tti = proto_tree_add_none_format(tt, hf_x11_depth_detail, tvb, *offsetp, 8 + 24 * number_of_visualtypes,
2096 "depth-detail");
2097 ttt = proto_item_add_subtree(tti, ett_x11_screen);
2098 proto_tree_add_item(ttt, hf_x11_depth_detail_depth, tvb, *offsetp, 1, byte_order);
2099 *offsetp += 1;
2100 proto_tree_add_item(ttt, hf_x11_unused, tvb, *offsetp, 1, byte_order);
2101 *offsetp += 1;
2102 proto_tree_add_item(ttt, hf_x11_depth_detail_visualtypes_numbers, tvb, *offsetp, 2, byte_order);
2103 *offsetp += 2;
2104 proto_tree_add_item(ttt, hf_x11_unused, tvb, *offsetp, 4, byte_order);
2105 *offsetp += 4;
2106 if (number_of_visualtypes > 0)
2107 listOfVisualTypes(tvb, offsetp, ttt, hf_x11_visualtype, number_of_visualtypes, byte_order);
2111 static void listOfScreen(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2112 int length, unsigned byte_order)
2114 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, -1, byte_order);
2115 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_screen);
2116 while(length--) {
2117 uint8_t number_of_depths, root_depth;
2118 uint16_t width_in_pixels, height_in_pixels;
2119 uint32_t screen_root;
2120 proto_item *tti;
2121 proto_tree *ttt;
2123 screen_root = tvb_get_uint32(tvb, *offsetp, byte_order);
2124 width_in_pixels = tvb_get_uint16(tvb, *offsetp + 20, byte_order);
2125 height_in_pixels = tvb_get_uint16(tvb, *offsetp + 22, byte_order);
2126 root_depth = tvb_get_uint8(tvb, *offsetp + 38);
2127 tti = proto_tree_add_none_format(tt, hf_x11_screen, tvb, *offsetp, 0,
2128 "screen (%08x: %d x %d x %d)", screen_root,
2129 width_in_pixels, height_in_pixels, root_depth);
2130 ttt = proto_item_add_subtree(tti, ett_x11_screen);
2131 proto_tree_add_item(ttt, hf_x11_screen_root, tvb, *offsetp, 4, byte_order);
2132 *offsetp += 4;
2133 proto_tree_add_item(ttt, hf_x11_screen_default_colormap, tvb, *offsetp, 4, byte_order);
2134 *offsetp += 4;
2135 proto_tree_add_item(ttt, hf_x11_screen_white_pixel, tvb, *offsetp, 4, byte_order);
2136 *offsetp += 4;
2137 proto_tree_add_item(ttt, hf_x11_screen_black_pixel, tvb, *offsetp, 4, byte_order);
2138 *offsetp += 4;
2139 proto_tree_add_item(ttt, hf_x11_screen_current_input_masks, tvb, *offsetp, 4, byte_order);
2140 *offsetp += 4;
2141 proto_tree_add_item(ttt, hf_x11_screen_width_in_pixels, tvb, *offsetp, 2, byte_order);
2142 *offsetp += 2;
2143 proto_tree_add_item(ttt, hf_x11_screen_height_in_pixels, tvb, *offsetp, 2, byte_order);
2144 *offsetp += 2;
2145 proto_tree_add_item(ttt, hf_x11_screen_width_in_millimeters, tvb, *offsetp, 2, byte_order);
2146 *offsetp += 2;
2147 proto_tree_add_item(ttt, hf_x11_screen_height_in_millimeters, tvb, *offsetp, 2, byte_order);
2148 *offsetp += 2;
2149 proto_tree_add_item(ttt, hf_x11_screen_min_installed_maps, tvb, *offsetp, 2, byte_order);
2150 *offsetp += 2;
2151 proto_tree_add_item(ttt, hf_x11_screen_max_installed_maps, tvb, *offsetp, 2, byte_order);
2152 *offsetp += 2;
2153 proto_tree_add_item(ttt, hf_x11_screen_root_visual, tvb, *offsetp, 4, byte_order);
2154 *offsetp += 4;
2155 proto_tree_add_item(ttt, hf_x11_screen_backing_stores, tvb, *offsetp, 1, byte_order);
2156 *offsetp += 1;
2157 proto_tree_add_item(ttt, hf_x11_screen_save_unders, tvb, *offsetp, 1, byte_order);
2158 *offsetp += 1;
2159 proto_tree_add_item(ttt, hf_x11_screen_root_depth, tvb, *offsetp, 1, byte_order);
2160 *offsetp += 1;
2161 number_of_depths = tvb_get_uint8(tvb, *offsetp);
2162 proto_tree_add_item(ttt, hf_x11_screen_allowed_depths_len, tvb, *offsetp, 1, byte_order);
2163 *offsetp += 1;
2164 listOfDepth(tvb, offsetp, ttt, hf_x11_depth_detail, number_of_depths, byte_order);
2167 static void listOfPixmapFormat(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2168 int length, unsigned byte_order)
2170 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, byte_order);
2171 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_pixmap_format);
2172 while(length--) {
2173 proto_item *tti;
2174 proto_tree *ttt;
2176 tti = proto_tree_add_none_format(tt, hf_x11_pixmap_format, tvb, *offsetp, 8,
2177 "pixmap-format");
2178 ttt = proto_item_add_subtree(tti, ett_x11_pixmap_format);
2179 proto_tree_add_item(ttt, hf_x11_pixmap_format_depth, tvb, *offsetp, 1, byte_order);
2180 *offsetp += 1;
2181 proto_tree_add_item(ttt, hf_x11_pixmap_format_bits_per_pixel, tvb, *offsetp, 1, byte_order);
2182 *offsetp += 1;
2183 proto_tree_add_item(ttt, hf_x11_pixmap_format_scanline_pad, tvb, *offsetp, 1, byte_order);
2184 *offsetp += 1;
2185 proto_tree_add_item(ttt, hf_x11_unused, tvb, *offsetp, 5, byte_order);
2186 *offsetp += 5;
2190 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2191 int hf_item, int length, unsigned byte_order)
2193 char *s = NULL;
2194 proto_item *ti;
2195 proto_tree *tt;
2196 int i;
2198 /* Compute total length */
2200 int scanning_offset = *offsetp; /* Scanning pointer */
2201 for(i = length; i; i--) {
2202 int l;
2203 l = tvb_get_uint8(tvb, scanning_offset);
2204 scanning_offset += 1 + l;
2207 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, byte_order);
2208 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2210 while(length--) {
2211 unsigned l = tvb_get_uint8(tvb, *offsetp);
2212 s = tvb_get_string_enc(wmem_packet_scope(), tvb, *offsetp + 1, l, ENC_ASCII);
2213 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2214 *offsetp += l + 1;
2218 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2220 for(; length > 0; offset += 2, length--) {
2221 if (tvb_get_uint8(tvb, offset))
2222 return false;
2224 return true;
2227 /* XXX - assumes that the string encoding is ASCII; even if 0x00 through
2228 0x7F are ASCII, 0x80 through 0xFF might not be, and even 0x00 through
2229 0x7F aren't necessarily ASCII. */
2230 static char *tvb_get_ascii_string16(tvbuff_t *tvb, int offset, unsigned length)
2232 wmem_strbuf_t *str;
2233 uint8_t ch;
2235 str = wmem_strbuf_new_sized(wmem_packet_scope(), length + 1);
2237 while(length--) {
2238 offset++;
2239 ch = tvb_get_uint8(tvb, offset);
2240 if (ch < 0x80)
2241 wmem_strbuf_append_c(str, ch);
2242 else
2243 wmem_strbuf_append_unichar_repl(str);
2244 offset++;
2246 return wmem_strbuf_finalize(str);
2249 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2250 int sizeIs16, int next_offset, unsigned byte_order)
2252 char *s = NULL;
2253 proto_item *ti;
2254 proto_tree *tt;
2255 uint32_t fid;
2257 /* Compute total length */
2259 int scanning_offset = *offsetp; /* Scanning pointer */
2260 int n = 0; /* Number of items */
2262 while(scanning_offset < next_offset) {
2263 int l; /* Length of an individual item */
2264 l = tvb_get_uint8(tvb, scanning_offset);
2265 scanning_offset++;
2266 if (!l) break;
2267 n++;
2268 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2271 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, byte_order);
2272 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2274 while(n--) {
2275 unsigned l = tvb_get_uint8(tvb, *offsetp);
2276 if (l == 255) { /* Item is a font */
2277 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2278 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2279 *offsetp += 5;
2280 } else { /* Item is a string */
2281 proto_item *tti;
2282 proto_tree *ttt;
2283 int8_t delta = tvb_get_uint8(tvb, *offsetp + 1);
2284 if (sizeIs16) {
2285 if (stringIsActuallyAn8BitString(tvb, *offsetp + 2, l)) {
2286 s = tvb_get_ascii_string16(tvb, *offsetp + 2, l);
2287 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l*2 + 2,
2288 "textitem (string): delta = %d, \"%s\"",
2289 delta, s);
2290 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2291 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, byte_order);
2292 proto_tree_add_string_format_value(ttt, hf_x11_textitem_string_string16, tvb,
2293 *offsetp + 2, l, s, "\"%s\"", s);
2294 } else {
2295 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l*2 + 2,
2296 "textitem (string): delta = %d, %s",
2297 delta,
2298 tvb_bytes_to_str(wmem_packet_scope(), tvb, *offsetp + 2, l*2));
2299 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2300 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, byte_order);
2301 proto_tree_add_item(ttt, hf_x11_textitem_string_string16_bytes, tvb, *offsetp + 2, l*2, byte_order);
2303 *offsetp += l*2 + 2;
2304 } else {
2305 s = tvb_get_string_enc(wmem_packet_scope(), tvb, *offsetp + 2, l, ENC_ASCII);
2306 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2307 "textitem (string): delta = %d, \"%s\"",
2308 delta, s);
2309 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2310 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, byte_order);
2311 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2312 *offsetp + 2, l, s, "\"%s\"", s);
2313 *offsetp += l + 2;
2319 static uint32_t field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2320 unsigned byte_order)
2322 uint32_t v = tvb_get_uint8(tvb, *offsetp);
2323 header_field_info *hfi = proto_registrar_get_nth(hf);
2324 const char *enumValue = NULL;
2326 if (hfi -> strings)
2327 enumValue = try_val_to_str(v, cVALS(hfi -> strings));
2328 if (enumValue)
2329 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2330 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2331 hfi -> name, v, enumValue);
2332 else
2333 proto_tree_add_item(t, hf, tvb, *offsetp, 1, byte_order);
2334 *offsetp += 1;
2335 return v;
2338 static uint32_t field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2339 unsigned byte_order)
2341 uint32_t v = tvb_get_uint16(tvb, *offsetp, byte_order);
2342 header_field_info *hfi = proto_registrar_get_nth(hf);
2343 const char *enumValue = NULL;
2345 if (hfi -> strings)
2346 enumValue = try_val_to_str(v, cVALS(hfi -> strings));
2347 if (enumValue)
2348 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2349 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2350 hfi -> name, v, enumValue);
2351 else
2352 proto_tree_add_item(t, hf, tvb, *offsetp, 2, byte_order);
2353 *offsetp += 2;
2354 return v;
2357 static uint32_t field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2358 unsigned byte_order)
2360 uint32_t v = tvb_get_uint32(tvb, *offsetp, byte_order);
2361 header_field_info *hfi = proto_registrar_get_nth(hf);
2362 const char *enumValue = NULL;
2363 const char *nameAsChar = hfi -> name;
2365 if (hfi -> strings)
2366 enumValue = try_val_to_str(v, cVALS(hfi -> strings));
2367 if (enumValue)
2368 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2369 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2370 nameAsChar, v, enumValue);
2371 else
2372 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2373 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2374 nameAsChar, v);
2375 *offsetp += 4;
2376 return v;
2379 static int * const gc_mask_attributes[] = {
2380 &hf_x11_gc_value_mask_function,
2381 &hf_x11_gc_value_mask_plane_mask,
2382 &hf_x11_gc_value_mask_foreground,
2383 &hf_x11_gc_value_mask_background,
2384 &hf_x11_gc_value_mask_line_width,
2385 &hf_x11_gc_value_mask_line_style,
2386 &hf_x11_gc_value_mask_cap_style,
2387 &hf_x11_gc_value_mask_join_style,
2388 &hf_x11_gc_value_mask_fill_style,
2389 &hf_x11_gc_value_mask_fill_rule,
2390 &hf_x11_gc_value_mask_tile,
2391 &hf_x11_gc_value_mask_stipple,
2392 &hf_x11_gc_value_mask_tile_stipple_x_origin,
2393 &hf_x11_gc_value_mask_tile_stipple_y_origin,
2394 &hf_x11_gc_value_mask_font,
2395 &hf_x11_gc_value_mask_subwindow_mode,
2396 &hf_x11_gc_value_mask_graphics_exposures,
2397 &hf_x11_gc_value_mask_clip_x_origin,
2398 &hf_x11_gc_value_mask_clip_y_origin,
2399 &hf_x11_gc_value_mask_clip_mask,
2400 &hf_x11_gc_value_mask_dash_offset,
2401 &hf_x11_gc_value_mask_gc_dashes,
2402 &hf_x11_gc_value_mask_arc_mode,
2403 NULL
2406 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2407 unsigned byte_order)
2409 uint32_t bitmask;
2410 bitmask = tvb_get_uint32(tvb, *offsetp, byte_order);
2411 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_gc_value_mask, ett_x11_gc_value_mask, gc_mask_attributes, byte_order);
2412 *offsetp += 4;
2414 if (bitmask & 0x00000001) {
2415 proto_tree_add_item(t, hf_x11_function, tvb, *offsetp, 1, byte_order);
2416 *offsetp += 1;
2417 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2418 *offsetp += 3;
2420 if (bitmask & 0x00000002) {
2421 proto_tree_add_item(t, hf_x11_plane_mask, tvb, *offsetp, 4, byte_order);
2422 *offsetp += 4;
2424 if (bitmask & 0x00000004) {
2425 proto_tree_add_item(t, hf_x11_foreground, tvb, *offsetp, 4, byte_order);
2426 *offsetp += 4;
2428 if (bitmask & 0x00000008) {
2429 proto_tree_add_item(t, hf_x11_background, tvb, *offsetp, 4, byte_order);
2430 *offsetp += 4;
2432 if (bitmask & 0x00000010) {
2433 proto_tree_add_item(t, hf_x11_line_width, tvb, *offsetp, 2, byte_order);
2434 *offsetp += 2;
2435 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2436 *offsetp += 2;
2438 if (bitmask & 0x00000020) {
2439 proto_tree_add_item(t, hf_x11_line_style, tvb, *offsetp, 1, byte_order);
2440 *offsetp += 1;
2441 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2442 *offsetp += 3;
2444 if (bitmask & 0x00000040) {
2445 proto_tree_add_item(t, hf_x11_cap_style, tvb, *offsetp, 1, byte_order);
2446 *offsetp += 1;
2447 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2448 *offsetp += 3;
2450 if (bitmask & 0x00000080) {
2451 proto_tree_add_item(t, hf_x11_join_style, tvb, *offsetp, 1, byte_order);
2452 *offsetp += 1;
2453 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2454 *offsetp += 3;
2456 if (bitmask & 0x00000100) {
2457 proto_tree_add_item(t, hf_x11_fill_style, tvb, *offsetp, 1, byte_order);
2458 *offsetp += 1;
2459 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2460 *offsetp += 3;
2462 if (bitmask & 0x00000200) {
2463 proto_tree_add_item(t, hf_x11_fill_rule, tvb, *offsetp, 1, byte_order);
2464 *offsetp += 1;
2465 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2466 *offsetp += 3;
2468 if (bitmask & 0x00000400) {
2469 proto_tree_add_item(t, hf_x11_tile, tvb, *offsetp, 4, byte_order);
2470 *offsetp += 4;
2472 if (bitmask & 0x00000800) {
2473 proto_tree_add_item(t, hf_x11_stipple, tvb, *offsetp, 4, byte_order);
2474 *offsetp += 4;
2476 if (bitmask & 0x00001000) {
2477 proto_tree_add_item(t, hf_x11_tile_stipple_x_origin, tvb, *offsetp, 2, byte_order);
2478 *offsetp += 2;
2479 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2480 *offsetp += 2;
2482 if (bitmask & 0x00002000) {
2483 proto_tree_add_item(t, hf_x11_tile_stipple_y_origin, tvb, *offsetp, 2, byte_order);
2484 *offsetp += 2;
2485 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2486 *offsetp += 2;
2488 if (bitmask & 0x00004000) {
2489 proto_tree_add_item(t, hf_x11_font, tvb, *offsetp, 4, byte_order);
2490 *offsetp += 4;
2492 if (bitmask & 0x00008000) {
2493 proto_tree_add_item(t, hf_x11_subwindow_mode, tvb, *offsetp, 1, byte_order);
2494 *offsetp += 1;
2495 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2496 *offsetp += 3;
2498 if (bitmask & 0x00010000) {
2499 proto_tree_add_item(t, hf_x11_graphics_exposures, tvb, *offsetp, 1, byte_order);
2500 *offsetp += 1;
2501 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2502 *offsetp += 3;
2504 if (bitmask & 0x00020000) {
2505 proto_tree_add_item(t, hf_x11_clip_x_origin, tvb, *offsetp, 2, byte_order);
2506 *offsetp += 2;
2507 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2508 *offsetp += 2;
2510 if (bitmask & 0x00040000) {
2511 proto_tree_add_item(t, hf_x11_clip_y_origin, tvb, *offsetp, 2, byte_order);
2512 *offsetp += 2;
2513 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2514 *offsetp += 2;
2516 if (bitmask & 0x00080000) {
2517 proto_tree_add_item(t, hf_x11_clip_mask, tvb, *offsetp, 4, byte_order);
2518 *offsetp += 4;
2520 if (bitmask & 0x00100000) {
2521 proto_tree_add_item(t, hf_x11_dash_offset, tvb, *offsetp, 2, byte_order);
2522 *offsetp += 2;
2523 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
2524 *offsetp += 2;
2526 if (bitmask & 0x00200000) {
2527 proto_tree_add_item(t, hf_x11_gc_dashes, tvb, *offsetp, 1, byte_order);
2528 *offsetp += 1;
2529 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2530 *offsetp += 3;
2532 if (bitmask & 0x00400000) {
2533 proto_tree_add_item(t, hf_x11_arc_mode, tvb, *offsetp, 1, byte_order);
2534 *offsetp += 1;
2535 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2536 *offsetp += 3;
2540 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2541 unsigned byte_order)
2543 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_gc_value_mask, ett_x11_gc_value_mask, gc_mask_attributes, byte_order);
2544 *offsetp += 4;
2547 static uint32_t requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2548 unsigned byte_order)
2550 uint32_t res;
2551 proto_item *ti = proto_tree_add_item_ret_uint(t, hf_x11_request_length, tvb, *offsetp, 2, byte_order, &res);
2552 *offsetp += 2;
2553 if (res == 0) {
2554 proto_item_append_text(ti, " (extended length flag)");
2555 proto_tree_add_item_ret_uint(t, hf_x11_request_length, tvb, *offsetp, 4, byte_order, &res);
2556 *offsetp += 4;
2558 return res * 4;
2561 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2562 unsigned byte_order)
2564 static int * const events[] = {
2565 &hf_x11_event_mask_KeyPress,
2566 &hf_x11_event_mask_KeyRelease,
2567 &hf_x11_event_mask_ButtonPress,
2568 &hf_x11_event_mask_ButtonRelease,
2569 &hf_x11_event_mask_EnterWindow,
2570 &hf_x11_event_mask_LeaveWindow,
2571 &hf_x11_event_mask_PointerMotion,
2572 &hf_x11_event_mask_PointerMotionHint,
2573 &hf_x11_event_mask_Button1Motion,
2574 &hf_x11_event_mask_Button2Motion,
2575 &hf_x11_event_mask_Button3Motion,
2576 &hf_x11_event_mask_Button4Motion,
2577 &hf_x11_event_mask_Button5Motion,
2578 &hf_x11_event_mask_ButtonMotion,
2579 &hf_x11_event_mask_KeymapState,
2580 &hf_x11_event_mask_Exposure,
2581 &hf_x11_event_mask_VisibilityChange,
2582 &hf_x11_event_mask_StructureNotify,
2583 &hf_x11_event_mask_ResizeRedirect,
2584 &hf_x11_event_mask_SubstructureNotify,
2585 &hf_x11_event_mask_SubstructureRedirect,
2586 &hf_x11_event_mask_FocusChange,
2587 &hf_x11_event_mask_PropertyChange,
2588 &hf_x11_event_mask_ColormapChange,
2589 &hf_x11_event_mask_OwnerGrabButton,
2590 NULL
2593 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_event_mask, ett_x11_event_mask, events, byte_order);
2594 *offsetp += 4;
2597 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2598 unsigned byte_order)
2600 static int * const do_not_propagate_events[] = {
2601 &hf_x11_do_not_propagate_mask_KeyPress,
2602 &hf_x11_do_not_propagate_mask_KeyRelease,
2603 &hf_x11_do_not_propagate_mask_ButtonPress,
2604 &hf_x11_do_not_propagate_mask_ButtonRelease,
2605 &hf_x11_do_not_propagate_mask_PointerMotion,
2606 &hf_x11_do_not_propagate_mask_Button1Motion,
2607 &hf_x11_do_not_propagate_mask_Button2Motion,
2608 &hf_x11_do_not_propagate_mask_Button3Motion,
2609 &hf_x11_do_not_propagate_mask_Button4Motion,
2610 &hf_x11_do_not_propagate_mask_Button5Motion,
2611 &hf_x11_do_not_propagate_mask_ButtonMotion,
2612 NULL
2615 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_do_not_propagate_mask, ett_x11_do_not_propagate_mask, do_not_propagate_events, byte_order);
2616 *offsetp += 4;
2620 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2621 unsigned byte_order, bool butmask)
2623 proto_item *ti;
2624 uint32_t bitmask_value;
2625 int bitmask_offset;
2626 int bitmask_size;
2627 proto_tree *bitmask_tree;
2629 bitmask_value = tvb_get_uint16(tvb, *offsetp, byte_order);
2630 bitmask_offset = *offsetp;
2631 bitmask_size = 2;
2633 if (!butmask && bitmask_value == 0x8000)
2634 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2635 "modifiers-masks: 0x8000 (AnyModifier)");
2636 else {
2637 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2638 bitmask_value);
2639 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2640 FLAG(modifiers, Shift);
2641 FLAG(modifiers, Lock);
2642 FLAG(modifiers, Control);
2643 FLAG(modifiers, Mod1);
2644 FLAG(modifiers, Mod2);
2645 FLAG(modifiers, Mod3);
2646 FLAG(modifiers, Mod4);
2647 FLAG(modifiers, Mod5);
2649 if (butmask) {
2650 FLAG(modifiers, Button1);
2651 FLAG(modifiers, Button2);
2652 FLAG(modifiers, Button3);
2653 FLAG(modifiers, Button4);
2654 FLAG(modifiers, Button5);
2657 if (butmask)
2658 FLAG_IF_NONZERO(keybut, erroneous_bits);
2659 else
2660 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2662 *offsetp += 2;
2665 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2666 unsigned byte_order)
2668 static int * const pointer_events[] = {
2669 &hf_x11_pointer_event_mask_ButtonRelease,
2670 &hf_x11_pointer_event_mask_EnterWindow,
2671 &hf_x11_pointer_event_mask_LeaveWindow,
2672 &hf_x11_pointer_event_mask_PointerMotion,
2673 &hf_x11_pointer_event_mask_PointerMotionHint,
2674 &hf_x11_pointer_event_mask_Button1Motion,
2675 &hf_x11_pointer_event_mask_Button2Motion,
2676 &hf_x11_pointer_event_mask_Button3Motion,
2677 &hf_x11_pointer_event_mask_Button4Motion,
2678 &hf_x11_pointer_event_mask_Button5Motion,
2679 &hf_x11_pointer_event_mask_ButtonMotion,
2680 &hf_x11_pointer_event_mask_KeymapState,
2681 NULL
2684 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_pointer_event_mask, ett_x11_pointer_event_mask, pointer_events, byte_order);
2685 *offsetp += 2;
2688 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2689 int hf, unsigned length)
2691 proto_tree_add_item(t, hf, tvb, *offsetp, length, ENC_NA|ENC_ASCII);
2692 *offsetp += length;
2695 /* The length supplied is the length of the string in CHAR2Bs (half the number of bytes) */
2697 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2698 int hf_bytes, unsigned length, unsigned byte_order)
2700 unsigned l = length*2; /* byte count */
2701 char *s;
2703 if (stringIsActuallyAn8BitString(tvb, *offsetp, length)) {
2704 s = tvb_get_ascii_string16(tvb, *offsetp, length);
2705 proto_tree_add_string_format_value(t, hf, tvb, *offsetp, l, s, "\"%s\"", s);
2706 } else
2707 proto_tree_add_item(t, hf_bytes, tvb, *offsetp, l, byte_order);
2709 *offsetp += l;
2712 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2713 unsigned byte_order)
2715 uint32_t v = tvb_get_uint32(tvb, *offsetp, byte_order);
2717 if (!v)
2718 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2719 proto_registrar_get_nth(hf) -> name);
2720 else
2721 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2722 *offsetp += 4;
2725 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2726 unsigned byte_order)
2728 uint32_t bitmask;
2729 static int * const window_attributes_flags[] = {
2730 &hf_x11_window_value_mask_background_pixmap,
2731 &hf_x11_window_value_mask_background_pixel,
2732 &hf_x11_window_value_mask_border_pixmap,
2733 &hf_x11_window_value_mask_border_pixel,
2734 &hf_x11_window_value_mask_bit_gravity,
2735 &hf_x11_window_value_mask_win_gravity,
2736 &hf_x11_window_value_mask_backing_store,
2737 &hf_x11_window_value_mask_backing_planes,
2738 &hf_x11_window_value_mask_backing_pixel,
2739 &hf_x11_window_value_mask_override_redirect,
2740 &hf_x11_window_value_mask_save_under,
2741 &hf_x11_window_value_mask_event_mask,
2742 &hf_x11_window_value_mask_do_not_propagate_mask,
2743 &hf_x11_window_value_mask_colormap,
2744 &hf_x11_window_value_mask_cursor,
2745 NULL
2748 bitmask = tvb_get_uint32(tvb, *offsetp, byte_order);
2749 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_window_value_mask, ett_x11_window_value_mask, window_attributes_flags, byte_order);
2750 *offsetp += 4;
2752 if (bitmask & 0x00000001) {
2753 proto_tree_add_item(t, hf_x11_background_pixmap, tvb, *offsetp, 4, byte_order);
2754 *offsetp += 4;
2756 if (bitmask & 0x00000002) {
2757 proto_tree_add_item(t, hf_x11_background_pixel, tvb, *offsetp, 4, byte_order);
2758 *offsetp += 4;
2760 if (bitmask & 0x00000004) {
2761 proto_tree_add_item(t, hf_x11_border_pixmap, tvb, *offsetp, 4, byte_order);
2762 *offsetp += 4;
2764 if (bitmask & 0x00000008) {
2765 proto_tree_add_item(t, hf_x11_border_pixel, tvb, *offsetp, 4, byte_order);
2766 *offsetp += 4;
2768 if (bitmask & 0x00000010) {
2769 proto_tree_add_item(t, hf_x11_bit_gravity, tvb, *offsetp, 1, byte_order);
2770 *offsetp += 1;
2771 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2772 *offsetp += 3;
2774 if (bitmask & 0x00000020) {
2775 proto_tree_add_item(t, hf_x11_win_gravity, tvb, *offsetp, 1, byte_order);
2776 *offsetp += 1;
2777 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2778 *offsetp += 3;
2780 if (bitmask & 0x00000040) {
2781 proto_tree_add_item(t, hf_x11_backing_store, tvb, *offsetp, 1, byte_order);
2782 *offsetp += 1;
2783 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2784 *offsetp += 3;
2786 if (bitmask & 0x00000080) {
2787 proto_tree_add_item(t, hf_x11_backing_planes, tvb, *offsetp, 4, byte_order);
2788 *offsetp += 4;
2790 if (bitmask & 0x00000100) {
2791 proto_tree_add_item(t, hf_x11_backing_pixel, tvb, *offsetp, 4, byte_order);
2792 *offsetp += 4;
2794 if (bitmask & 0x00000200) {
2795 proto_tree_add_item(t, hf_x11_override_redirect, tvb, *offsetp, 1, byte_order);
2796 *offsetp += 1;
2797 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2798 *offsetp += 3;
2800 if (bitmask & 0x00000400) {
2801 proto_tree_add_item(t, hf_x11_save_under, tvb, *offsetp, 1, byte_order);
2802 *offsetp += 1;
2803 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
2804 *offsetp += 3;
2806 if (bitmask & 0x00000800) {
2807 setOfEvent(tvb, offsetp, t, byte_order);
2809 if (bitmask & 0x00001000) {
2810 setOfDeviceEvent(tvb, offsetp, t, byte_order);
2812 if (bitmask & 0x00002000) {
2813 proto_tree_add_item(t, hf_x11_colormap, tvb, *offsetp, 4, byte_order);
2814 *offsetp += 4;
2816 if (bitmask & 0x00004000) {
2817 proto_tree_add_item(t, hf_x11_cursor, tvb, *offsetp, 4, byte_order);
2818 *offsetp += 4;
2822 /************************************************************************
2823 *** ***
2824 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2825 *** ***
2826 ************************************************************************/
2828 /* If we can't guess, we return ENC_LITTLE_ENDIAN, cause
2829 I'm developing on a Linux box :-). The (non-)guess isn't cached
2830 however, so we may have more luck next time. I'm quite conservative
2831 in my assertions, cause once it's cached, it stays in cache, and
2832 we may be fooled up by a packet starting with the end of a request
2833 started in a previous packet...
2836 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2838 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2840 int res = 0;
2841 while(maskLength--) {
2842 int c = tvb_get_uint8(tvb, offset);
2843 offset++;
2844 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2846 return res;
2849 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2851 if (listLength > length) return false;
2852 while(listLength--) {
2853 int l;
2854 if (!tvb_bytes_exist(tvb, offset, 1)) return true;
2855 l = tvb_get_uint8(tvb, offset);
2856 if (!l) break;
2857 l++;
2858 if (l > length) return false;
2859 if (!tvb_bytes_exist(tvb, offset, l)) return true;
2860 offset += l;
2861 length -= l;
2863 if (length > 3) return false;
2864 return true;
2867 static int rounded4(int n)
2869 int remainder = n % 4;
2870 int res = n / 4;
2871 if (remainder) res++;
2872 return res;
2875 /* We assume the order to be consistent, until proven wrong. */
2877 static bool consistentWithOrder(int length, tvbuff_t *tvb, int offset, int encoding)
2879 switch(tvb_get_uint8(tvb, offset)) {
2880 case X_CreateWindow:
2881 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2883 case X_ChangeWindowAttributes:
2884 case X_ChangeGC:
2885 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2887 case X_GetWindowAttributes:
2888 case X_DestroyWindow:
2889 case X_DestroySubwindows:
2890 case X_ChangeSaveSet:
2891 case X_MapWindow:
2892 case X_MapSubwindows:
2893 case X_UnmapWindow:
2894 case X_UnmapSubwindows:
2895 case X_CirculateWindow:
2896 case X_GetGeometry:
2897 case X_QueryTree:
2898 case X_GetAtomName:
2899 case X_ListProperties:
2900 case X_GetSelectionOwner:
2901 case X_UngrabPointer:
2902 case X_UngrabKeyboard:
2903 case X_AllowEvents:
2904 case X_QueryPointer:
2905 case X_CloseFont:
2906 case X_QueryFont:
2907 case X_FreePixmap:
2908 case X_FreeGC:
2909 case X_FreeColormap:
2910 case X_InstallColormap:
2911 case X_UninstallColormap:
2912 case X_ListInstalledColormaps:
2913 case X_FreeCursor:
2914 case X_GetKeyboardMapping:
2915 case X_KillClient:
2916 return length == 2;
2918 case X_ReparentWindow:
2919 case X_SetSelectionOwner:
2920 case X_ChangeActivePointerGrab:
2921 case X_GrabKeyboard:
2922 case X_GrabKey:
2923 case X_GetMotionEvents:
2924 case X_TranslateCoords:
2925 case X_CreatePixmap:
2926 case X_CopyGC:
2927 case X_ClearArea:
2928 case X_CreateColormap:
2929 case X_AllocColor:
2930 case X_AllocColorPlanes:
2931 return length == 4;
2933 case X_ConfigureWindow:
2934 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2936 case X_InternAtom:
2937 case X_QueryExtension:
2938 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(tvb_get_uint16(tvb, offset + 4, encoding));
2940 case X_ChangeProperty:
2942 int multiplier, type;
2943 if (!tvb_bytes_exist(tvb, offset, 17)) return true;
2944 type = tvb_get_uint8(tvb, 16);
2945 if (type != 8 && type != 16 && type != 32) return false;
2946 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2947 if (!tvb_bytes_exist(tvb, offset, 24)) return true;
2948 return length == 6 + rounded4(tvb_get_uint32(tvb, offset + 20, encoding) * multiplier);
2951 case X_DeleteProperty:
2952 case X_UngrabButton:
2953 case X_UngrabKey:
2954 case X_SetInputFocus:
2955 case X_CopyColormapAndFree:
2956 case X_AllocColorCells:
2957 case X_QueryBestSize:
2958 case X_ChangePointerControl:
2959 case X_SetScreenSaver:
2960 return length == 3;
2962 case X_GetProperty:
2963 case X_ConvertSelection:
2964 case X_GrabPointer:
2965 case X_GrabButton:
2966 case X_WarpPointer:
2967 return length == 6;
2969 case X_SendEvent:
2970 return length == 11;
2972 case X_GrabServer:
2973 case X_UngrabServer:
2974 case X_GetInputFocus:
2975 case X_QueryKeymap:
2976 case X_GetFontPath:
2977 case X_ListExtensions:
2978 case X_GetKeyboardControl:
2979 case X_Bell:
2980 case X_GetPointerControl:
2981 case X_GetScreenSaver:
2982 case X_ListHosts:
2983 case X_SetAccessControl:
2984 case X_SetCloseDownMode:
2985 case X_ForceScreenSaver:
2986 case X_GetPointerMapping:
2987 case X_GetModifierMapping:
2988 return length == 1;
2990 case X_OpenFont:
2991 case X_AllocNamedColor:
2992 case X_LookupColor:
2993 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(tvb_get_uint16(tvb, offset + 8, encoding));
2995 case X_QueryTextExtents:
2996 return length >= 2;
2998 case X_ListFonts:
2999 case X_ListFontsWithInfo:
3000 case X_ChangeHosts:
3001 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(tvb_get_uint16(tvb, offset + 6, encoding));
3003 case X_SetFontPath:
3004 if (length < 2) return false;
3005 if (!tvb_bytes_exist(tvb, offset, 8)) return true;
3006 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, tvb_get_uint16(tvb, offset + 4, encoding));
3008 case X_CreateGC:
3009 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
3011 case X_SetDashes:
3012 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(tvb_get_uint16(tvb, offset + 10, encoding));
3014 case X_SetClipRectangles:
3015 case X_PolySegment:
3016 case X_PolyRectangle:
3017 case X_PolyFillRectangle:
3018 return length >= 3 && (length - 3) % 2 == 0;
3020 case X_CopyArea:
3021 return length == 7;
3023 case X_CopyPlane:
3024 case X_CreateCursor:
3025 case X_CreateGlyphCursor:
3026 return length == 8;
3028 case X_PolyPoint:
3029 case X_PolyLine:
3030 case X_FreeColors:
3031 return length >= 3;
3033 case X_PolyArc:
3034 case X_PolyFillArc:
3035 return length >= 3 && (length - 3) % 3 == 0;
3037 case X_FillPoly:
3038 case X_ImageText8:
3039 return length >= 4;
3041 case X_PutImage:
3042 return length >= 6;
3044 case X_GetImage:
3045 case X_RecolorCursor:
3046 return length == 5;
3048 case X_PolyText8:
3049 if (length < 4) return false;
3050 return true; /* We don't perform many controls on this one */
3052 case X_PolyText16:
3053 if (length < 4) return false;
3054 return true; /* We don't perform many controls on this one */
3056 case X_ImageText16:
3057 return length >= 4;
3059 case X_StoreColors:
3060 return length > 2 && (length - 2) % 3 == 0;
3062 case X_StoreNamedColor:
3063 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(tvb_get_uint16(tvb, offset + 12, encoding));
3065 case X_QueryColors:
3066 return length >= 2;
3068 case X_ChangeKeyboardMapping:
3069 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_uint8(tvb, 1) * tvb_get_uint8(tvb, 5);
3071 case X_ChangeKeyboardControl:
3072 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
3074 case X_RotateProperties:
3075 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + tvb_get_uint16(tvb, offset + 8, encoding);
3077 case X_SetPointerMapping:
3078 return length == 1 + rounded4(tvb_get_uint8(tvb, 1));
3080 case X_SetModifierMapping:
3081 return length == 1 + tvb_get_uint8(tvb, 1) * 2;
3083 case X_NoOperation:
3084 return length >= 1;
3086 default:
3087 return true;
3091 /* -1 means doesn't match, +1 means match, 0 means don't know */
3093 static int x_endian_match(tvbuff_t *tvb, int encoding)
3095 int offset, nextoffset;
3096 int atLeastOne = 0;
3098 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
3099 int length;
3100 length = tvb_get_uint16(tvb, offset + 2, encoding);
3101 if (!length)
3102 return -1;
3103 nextoffset = offset + length * 4;
3104 if (!consistentWithOrder(length, tvb, offset, encoding))
3105 return -1;
3106 atLeastOne = 1;
3108 return atLeastOne;
3111 static unsigned
3112 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
3113 x11_conv_data_t *state)
3115 /* With X the client gives the byte ordering for the protocol,
3116 and the port on the server tells us we're speaking X. */
3118 int le, be;
3119 unsigned decision;
3121 if (state->byte_order == ENC_BIG_ENDIAN)
3122 return ENC_BIG_ENDIAN; /* known to be big-endian */
3123 else if (state->byte_order == ENC_LITTLE_ENDIAN)
3124 return ENC_LITTLE_ENDIAN; /* known to be little-endian */
3126 if (pinfo->srcport == pinfo->match_uint) {
3128 * This is a reply or event; we don't try to guess the
3129 * byte order on it for now.
3131 return ENC_LITTLE_ENDIAN;
3134 le = x_endian_match(tvb, ENC_LITTLE_ENDIAN);
3135 be = x_endian_match(tvb, ENC_BIG_ENDIAN);
3137 if (le == be) {
3138 /* We have no reason to believe it's little- rather than
3139 big-endian, so we guess the shortest length is the
3140 right one.
3142 if (!tvb_bytes_exist(tvb, 0, 4))
3143 /* Not even a way to get the length. We're biased
3144 toward little endianness here (essentially the
3145 x86 world right now). Decoding won't go very far
3146 anyway.
3148 decision = ENC_LITTLE_ENDIAN;
3149 else {
3150 if (tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2))
3151 decision = ENC_LITTLE_ENDIAN;
3152 else
3153 decision = ENC_BIG_ENDIAN;
3155 } else {
3156 if (le >= be)
3157 decision = ENC_LITTLE_ENDIAN;
3158 else
3159 decision = ENC_BIG_ENDIAN;
3162 if ((le < 0 && be > 0) || (le > 0 && be < 0)) {
3164 * Remember the decision.
3166 state->byte_order = decision;
3169 return decision;
3172 /************************************************************************
3173 *** ***
3174 *** D E C O D I N G O N E P A C K E T ***
3175 *** ***
3176 ************************************************************************/
3179 * Decode an initial connection request.
3181 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
3182 proto_tree *tree, x11_conv_data_t *state, unsigned byte_order)
3184 int offset = 0;
3185 int *offsetp = &offset;
3186 proto_item *ti;
3187 proto_tree *t;
3188 uint16_t auth_proto_name_length, auth_proto_data_length;
3189 int left;
3191 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
3192 proto_item_append_text(ti, ", Request, Initial connection request");
3193 t = proto_item_add_subtree(ti, ett_x11);
3195 CARD8(byte_order);
3196 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3197 *offsetp += 1;
3198 CARD16(protocol_major_version);
3199 CARD16(protocol_minor_version);
3200 auth_proto_name_length = CARD16(authorization_protocol_name_length);
3201 auth_proto_data_length = CARD16(authorization_protocol_data_length);
3202 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3203 *offsetp += 2;
3205 if (auth_proto_name_length != 0) {
3206 STRING8(authorization_protocol_name, auth_proto_name_length);
3207 offset = ROUND_LENGTH(offset);
3210 if (auth_proto_data_length != 0) {
3211 STRING8(authorization_protocol_data, auth_proto_data_length);
3212 offset = ROUND_LENGTH(offset);
3215 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3216 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
3217 ENC_NA);
3220 * This is the initial connection request...
3222 state->iconn_frame = pinfo->num;
3225 * ...and we're expecting a reply to it.
3227 state->sequencenumber = 0;
3228 wmem_map_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
3229 (int *)INITIAL_CONN);
3232 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
3233 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *state,
3234 unsigned byte_order)
3236 int offset = 0, *offsetp = &offset, left;
3237 unsigned char success;
3238 int length_of_vendor;
3239 int length_of_reason;
3240 int number_of_formats_in_pixmap_formats;
3241 int number_of_screens_in_roots;
3242 int unused;
3243 proto_item *ti;
3244 proto_tree *t;
3246 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
3247 proto_item_append_text(ti, ", Reply, Initial connection reply");
3248 t = proto_item_add_subtree(ti, ett_x11);
3250 state->iconn_reply = pinfo->num;
3251 success = INT8(success);
3252 if (success) {
3253 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3254 *offsetp += 1;
3255 length_of_reason = 0;
3257 else {
3258 length_of_reason = INT8(length_of_reason);
3261 INT16(protocol_major_version);
3262 INT16(protocol_minor_version);
3263 INT16(replylength);
3264 if (success) {
3265 INT32(release_number);
3266 INT32(resource_id_base);
3267 INT32(resource_id_mask);
3268 INT32(motion_buffer_size);
3269 length_of_vendor = INT16(length_of_vendor);
3270 INT16(maximum_request_length);
3271 number_of_screens_in_roots = INT8(number_of_screens_in_roots);
3272 number_of_formats_in_pixmap_formats = INT8(number_of_formats_in_pixmap_formats);
3273 INT8(image_byte_order);
3274 INT8(bitmap_format_bit_order);
3275 INT8(bitmap_format_scanline_unit);
3276 INT8(bitmap_format_scanline_pad);
3277 INT8(min_keycode);
3278 INT8(max_keycode);
3279 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 4, ENC_NA);
3280 *offsetp += 4;
3281 STRING8(vendor, length_of_vendor);
3282 unused = (4 - (length_of_vendor % 4)) % 4;
3283 if (unused > 0) {
3284 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, ENC_NA);
3285 *offsetp += unused;
3287 LISTofPIXMAPFORMAT(pixmap_format, number_of_formats_in_pixmap_formats);
3288 LISTofSCREEN(screen, number_of_screens_in_roots);
3289 } else {
3290 STRING8(reason, length_of_reason);
3293 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3294 UNDECODED(left);
3298 typedef struct x11_reply_info {
3299 const uint8_t minor;
3300 void (*dissect)(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, unsigned byte_order);
3301 } x11_reply_info;
3303 typedef struct event_info {
3304 const char *name;
3305 void (*dissect)(tvbuff_t *tvb, int *offsetp, proto_tree *t, unsigned byte_order);
3306 } x11_event_info;
3308 typedef struct x11_generic_event_info {
3309 const uint16_t minor;
3310 void (*dissect)(tvbuff_t *tvb, int length, int *offsetp, proto_tree *t, unsigned byte_order);
3311 } x11_generic_event_info;
3313 static void set_handler(const char *name, void (*func)(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, unsigned byte_order),
3314 const char * const *errors,
3315 const x11_event_info *event_info,
3316 const x11_generic_event_info *genevent_info,
3317 const x11_reply_info *reply_info)
3319 wmem_map_insert(extension_table, (void *)name, (void *)func);
3320 wmem_map_insert(error_table, (void *)name, (void *)errors);
3321 wmem_map_insert(event_table, (void *)name, (void *)event_info);
3322 if (genevent_info)
3323 wmem_map_insert(genevent_table, (void *)name, (void *)genevent_info);
3324 wmem_map_insert(reply_table, (void *)name, (void *)reply_info);
3327 #include "x11-extension-errors.h"
3328 #include "x11-extension-implementation.h"
3330 static void tryExtension(int opcode, tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t,
3331 x11_conv_data_t *state, unsigned byte_order)
3333 const char *extension;
3334 void (*func)(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, unsigned byte_order);
3336 extension = try_val_to_str(opcode, state->opcode_vals);
3337 if (!extension)
3338 return;
3340 func = (void (*)(tvbuff_t *, packet_info *, int *, proto_tree *, unsigned))wmem_map_lookup(extension_table, extension);
3341 if (func)
3342 func(tvb, pinfo, offsetp, t, byte_order);
3345 static void tryExtensionReply(int opcode, tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t,
3346 x11_conv_data_t *state, unsigned byte_order)
3348 void (*func)(tvbuff_t *tvb, packet_info *pinfo, int *offsetp, proto_tree *t, unsigned byte_order);
3350 func = (void (*)(tvbuff_t *, packet_info *, int *, proto_tree *, unsigned))wmem_map_lookup(state->reply_funcs, GINT_TO_POINTER(opcode));
3351 if (func)
3352 func(tvb, pinfo, offsetp, t, byte_order);
3353 else
3354 REPLYCONTENTS_COMMON();
3357 static void tryExtensionEvent(int event, tvbuff_t *tvb, int *offsetp, proto_tree *t,
3358 x11_conv_data_t *state, unsigned byte_order)
3360 void (*func)(tvbuff_t *tvb, int *offsetp, proto_tree *t, unsigned byte_order);
3362 func = (void (*)(tvbuff_t *, int *, proto_tree *, unsigned))wmem_map_lookup(state->eventcode_funcs, GINT_TO_POINTER(event));
3363 if (func)
3364 func(tvb, offsetp, t, byte_order);
3367 static void tryGenericExtensionEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
3368 x11_conv_data_t *state, unsigned byte_order)
3370 const char *extname;
3371 int extension, length;
3373 extension = tvb_get_uint8(tvb, *offsetp);
3374 (*offsetp)++;
3375 extname = try_val_to_str(extension, state->opcode_vals);
3377 if (extname) {
3378 proto_tree_add_uint_format(t, hf_x11_extension, tvb, *offsetp, 1, extension, "extension: %d (%s)", extension, extname);
3379 } else {
3380 proto_tree_add_uint(t, hf_x11_extension, tvb, *offsetp, 1, extension);
3383 CARD16(event_sequencenumber);
3385 length = REPLYLENGTH(eventlength);
3386 length = length * 4 + 32;
3387 *offsetp += 4;
3389 if (extname) {
3390 x11_generic_event_info *info;
3391 info = (x11_generic_event_info *)wmem_map_lookup(genevent_table, extname);
3393 if (info) {
3394 int i;
3396 int opcode = tvb_get_uint16(tvb, *offsetp, byte_order);
3398 for (i = 0; info[i].dissect != NULL; i++) {
3399 if (info[i].minor == opcode) {
3400 *offsetp += 2;
3401 info[i].dissect(tvb, length, offsetp, t, byte_order);
3402 return;
3407 CARD16(minor_opcode);
3410 static void register_extension(x11_conv_data_t *state, value_string *vals_p,
3411 int major_opcode, unsigned int first_event, unsigned int first_error)
3413 const char * const *error_string;
3414 x11_event_info *event_info;
3415 x11_reply_info *reply_info;
3416 int i;
3418 vals_p->value = major_opcode;
3420 error_string = (const char * const *)wmem_map_lookup(error_table, vals_p->strptr);
3421 while (error_string && *error_string && first_error <= LastExtensionError) {
3422 /* store string of extension error */
3423 for (i = 0; i <= LastExtensionError; i++) {
3424 if (state->errorcode_vals[i].strptr == NULL) {
3425 state->errorcode_vals[i].value = first_error;
3426 state->errorcode_vals[i].strptr = *error_string;
3427 break;
3428 } else if (state->errorcode_vals[i].value == first_error) {
3429 /* TODO: Warn about extensions stepping on each other */
3430 state->errorcode_vals[i].strptr = *error_string;
3431 break;
3434 first_error++;
3435 error_string++;
3438 event_info = (x11_event_info *)wmem_map_lookup(event_table, vals_p->strptr);
3439 while (event_info && event_info->name && first_event <= LastExtensionEvent) {
3440 /* store string of extension event */
3441 for (i = 0; i <= LastExtensionEvent; i++) {
3442 if (state->eventcode_vals[i].strptr == NULL) {
3443 state->eventcode_vals[i].value = first_event;
3444 state->eventcode_vals[i].strptr = event_info->name;
3445 break;
3446 } else if (state->eventcode_vals[i].value == first_event) {
3447 /* TODO: Warn about extensions stepping on each other */
3448 state->eventcode_vals[i].strptr = event_info->name;
3449 break;
3453 /* store event decode function */
3454 wmem_map_insert(state->eventcode_funcs, GINT_TO_POINTER(first_event), (void *)event_info->dissect);
3456 first_event++;
3457 event_info++;
3460 reply_info = (x11_reply_info *)wmem_map_lookup(reply_table, vals_p->strptr);
3461 if (reply_info)
3462 for (i = 0; reply_info[i].dissect; i++)
3463 wmem_map_insert(state->reply_funcs,
3464 GINT_TO_POINTER(major_opcode | (reply_info[i].minor << 8)),
3465 (void *)reply_info[i].dissect);
3469 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
3470 proto_tree *tree, const char *sep, x11_conv_data_t *state,
3471 unsigned byte_order)
3473 int offset = 0;
3474 int *offsetp = &offset;
3475 int query_ext_offset;
3476 int next_offset;
3477 proto_item *ti;
3478 proto_tree *t;
3479 int length, opcode, i;
3480 uint8_t v8, v8_2, v8_3;
3481 uint16_t v16;
3482 uint32_t v32;
3483 int left;
3484 char *name;
3486 query_ext_offset = 2; /* "opcode" and "unused" */
3488 length = tvb_get_uint16(tvb, query_ext_offset, byte_order) * 4;
3489 query_ext_offset += 2;
3491 if (length == 0) {
3492 /* BIG-REQUESTS extension */
3493 length = tvb_get_uint32(tvb, query_ext_offset, byte_order);
3494 if ((int64_t)length * 4 > INT32_MAX)
3495 return;
3496 length *= 4;
3497 query_ext_offset += 4;
3500 if (length < 4) {
3501 /* Bogus message length? */
3502 return;
3505 next_offset = offset + length;
3507 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
3508 t = proto_item_add_subtree(ti, ett_x11);
3510 if (!pinfo->fd->visited)
3511 ++state->sequencenumber;
3513 OPCODE();
3515 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
3516 val_to_str(opcode, state->opcode_vals,
3517 "<Unknown opcode %d>"));
3519 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
3520 opcode, val_to_str(opcode, state->opcode_vals,
3521 "<Unknown opcode %d>"));
3524 * Does this request expect a reply?
3526 switch(opcode) {
3528 case X_QueryExtension:
3530 /* necessary processing even if tree == NULL */
3532 v16 = tvb_get_uint16(tvb, query_ext_offset, byte_order);
3533 query_ext_offset += 2;
3534 /* Some unused bytes */
3535 query_ext_offset += 2;
3536 name = tvb_get_string_enc(wmem_file_scope(), tvb, query_ext_offset, v16, ENC_ASCII);
3538 /* store string of extension, opcode will be set at reply */
3539 i = 0;
3540 while(i < MAX_OPCODES) {
3541 if (state->opcode_vals[i].strptr == NULL) {
3542 state->opcode_vals[i].strptr = name;
3543 state->opcode_vals[i].value = -1;
3544 wmem_map_insert(state->valtable,
3545 GINT_TO_POINTER(state->sequencenumber),
3546 (int *)&state->opcode_vals[i]);
3547 break;
3548 } else if (strcmp(state->opcode_vals[i].strptr,
3549 name) == 0) {
3550 wmem_map_insert(state->valtable,
3551 GINT_TO_POINTER(state->sequencenumber),
3552 (int *)&state->opcode_vals[i]);
3553 break;
3555 i++;
3558 /* QueryExtension expects a reply, fall through */
3559 /* FALLTHROUGH */
3560 case X_AllocColor:
3561 case X_AllocColorCells:
3562 case X_AllocColorPlanes:
3563 case X_AllocNamedColor:
3564 case X_GetAtomName:
3565 case X_GetFontPath:
3566 case X_GetGeometry:
3567 case X_GetImage:
3568 case X_GetInputFocus:
3569 case X_GetKeyboardControl:
3570 case X_GetKeyboardMapping:
3571 case X_GetModifierMapping:
3572 case X_GetMotionEvents:
3573 case X_GetPointerControl:
3574 case X_GetPointerMapping:
3575 case X_GetProperty:
3576 case X_GetScreenSaver:
3577 case X_GetSelectionOwner:
3578 case X_GetWindowAttributes:
3579 case X_GrabKeyboard:
3580 case X_GrabPointer:
3581 case X_InternAtom:
3582 case X_ListExtensions:
3583 case X_ListFonts:
3584 case X_ListFontsWithInfo:
3585 case X_ListHosts:
3586 case X_ListInstalledColormaps:
3587 case X_ListProperties:
3588 case X_LookupColor:
3589 case X_QueryBestSize:
3590 case X_QueryColors:
3591 case X_QueryFont:
3592 case X_QueryKeymap:
3593 case X_QueryPointer:
3594 case X_QueryTextExtents:
3595 case X_QueryTree:
3596 case X_SetModifierMapping:
3597 case X_SetPointerMapping:
3598 case X_TranslateCoords:
3600 * Those requests expect a reply.
3602 wmem_map_insert(state->seqtable,
3603 GINT_TO_POINTER(state->sequencenumber),
3604 GINT_TO_POINTER(opcode));
3606 break;
3608 default:
3610 * With Extension, we don't know, so assume there could be one
3612 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3613 uint32_t minor;
3614 minor = tvb_get_uint8(tvb, 1);
3616 wmem_map_insert(state->seqtable,
3617 GINT_TO_POINTER(state->sequencenumber),
3618 GINT_TO_POINTER(opcode | (minor << 8)));
3622 * No reply is expected from any other request.
3624 break;
3627 if (tree == NULL)
3628 return;
3630 switch(opcode) {
3632 case X_CreateWindow:
3633 CARD8(depth);
3634 requestLength(tvb, offsetp, t, byte_order);
3635 WINDOW(wid);
3636 WINDOW(parent);
3637 INT16(x);
3638 INT16(y);
3639 CARD16(width);
3640 CARD16(height);
3641 CARD16(border_width);
3642 ENUM16(window_class);
3643 VISUALID(visual);
3644 windowAttributes(tvb, offsetp, t, byte_order);
3645 break;
3647 case X_ChangeWindowAttributes:
3648 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3649 *offsetp += 1;
3650 requestLength(tvb, offsetp, t, byte_order);
3651 WINDOW(window);
3652 windowAttributes(tvb, offsetp, t, byte_order);
3653 break;
3655 case X_GetWindowAttributes:
3656 case X_DestroyWindow:
3657 case X_DestroySubwindows:
3658 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3659 *offsetp += 1;
3660 requestLength(tvb, offsetp, t, byte_order);
3661 WINDOW(window);
3662 break;
3664 case X_ChangeSaveSet:
3665 ENUM8(save_set_mode);
3666 requestLength(tvb, offsetp, t, byte_order);
3667 WINDOW(window);
3668 break;
3670 case X_ReparentWindow:
3671 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3672 *offsetp += 1;
3673 requestLength(tvb, offsetp, t, byte_order);
3674 WINDOW(window);
3675 WINDOW(parent);
3676 INT16(x);
3677 INT16(y);
3678 break;
3680 case X_MapWindow:
3681 case X_MapSubwindows:
3682 case X_UnmapWindow:
3683 case X_UnmapSubwindows:
3684 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3685 *offsetp += 1;
3686 requestLength(tvb, offsetp, t, byte_order);
3687 WINDOW(window);
3688 break;
3690 case X_ConfigureWindow:
3692 uint16_t bitmask16;
3693 static int * const configure_window_mask_flags[] = {
3694 &hf_x11_configure_window_mask_x,
3695 &hf_x11_configure_window_mask_y,
3696 &hf_x11_configure_window_mask_width,
3697 &hf_x11_configure_window_mask_height,
3698 &hf_x11_configure_window_mask_border_width,
3699 &hf_x11_configure_window_mask_sibling,
3700 &hf_x11_configure_window_mask_stack_mode,
3701 NULL
3704 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3705 *offsetp += 1;
3706 requestLength(tvb, offsetp, t, byte_order);
3707 proto_tree_add_item(t, hf_x11_window, tvb, *offsetp, 4, byte_order);
3708 *offsetp += 4;
3709 bitmask16 = tvb_get_uint16(tvb, *offsetp, byte_order);
3710 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_configure_window_mask, ett_x11_configure_window_mask, configure_window_mask_flags, byte_order);
3711 *offsetp += 2;
3712 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3713 *offsetp += 2;
3714 if (bitmask16 & 0x0001) {
3715 proto_tree_add_item(t, hf_x11_x, tvb, *offsetp, 2, byte_order);
3716 *offsetp += 2;
3717 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3718 *offsetp += 2;
3720 if (bitmask16 & 0x0002) {
3721 proto_tree_add_item(t, hf_x11_y, tvb, *offsetp, 2, byte_order);
3722 *offsetp += 2;
3723 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3724 *offsetp += 2;
3726 if (bitmask16 & 0x0004) {
3727 proto_tree_add_item(t, hf_x11_width, tvb, *offsetp, 2, byte_order);
3728 *offsetp += 2;
3729 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3730 *offsetp += 2;
3732 if (bitmask16 & 0x0008) {
3733 proto_tree_add_item(t, hf_x11_height, tvb, *offsetp, 2, byte_order);
3734 *offsetp += 2;
3735 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3736 *offsetp += 2;
3738 if (bitmask16 & 0x0010) {
3739 proto_tree_add_item(t, hf_x11_border_width, tvb, *offsetp, 2, byte_order);
3740 *offsetp += 2;
3741 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3742 *offsetp += 2;
3744 if (bitmask16 & 0x0020) {
3745 proto_tree_add_item(t, hf_x11_sibling, tvb, *offsetp, 4, byte_order);
3746 *offsetp += 4;
3748 if (bitmask16 & 0x0040) {
3749 proto_tree_add_item(t, hf_x11_stack_mode, tvb, *offsetp, 1, byte_order);
3750 *offsetp += 1;
3751 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
3752 *offsetp += 3;
3754 if (next_offset - *offsetp > 0) {
3755 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, next_offset - *offsetp, ENC_NA);
3756 *offsetp = next_offset;
3759 break;
3761 case X_CirculateWindow:
3762 ENUM8(direction);
3763 requestLength(tvb, offsetp, t, byte_order);
3764 WINDOW(window);
3765 break;
3767 case X_GetGeometry:
3768 case X_QueryTree:
3769 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3770 *offsetp += 1;
3771 requestLength(tvb, offsetp, t, byte_order);
3772 DRAWABLE(drawable);
3773 break;
3775 case X_InternAtom:
3776 BOOL(only_if_exists);
3777 requestLength(tvb, offsetp, t, byte_order);
3778 v16 = FIELD16(name_length);
3779 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3780 *offsetp += 2;
3781 STRING8(name, v16);
3782 PAD();
3783 break;
3785 case X_GetAtomName:
3786 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3787 *offsetp += 1;
3788 requestLength(tvb, offsetp, t, byte_order);
3789 ATOM(atom);
3790 break;
3792 case X_ChangeProperty:
3793 ENUM8(mode);
3794 requestLength(tvb, offsetp, t, byte_order);
3795 WINDOW(window);
3796 ATOM(property);
3797 ATOM(type);
3798 v8 = CARD8(format);
3799 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
3800 *offsetp += 3;
3801 v32 = CARD32(data_length);
3802 switch (v8) {
3803 case 8:
3804 if (v32)
3805 LISTofBYTE(data, v32);
3806 break;
3807 case 16:
3808 if (v32)
3809 LISTofCARD16(data16, v32 * 2);
3810 break;
3811 case 32:
3812 if (v32)
3813 LISTofCARD32(data32, v32 * 4);
3814 break;
3815 default:
3816 expert_add_info(pinfo, ti, &ei_x11_invalid_format);
3817 break;
3819 PAD();
3820 break;
3822 case X_DeleteProperty:
3823 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3824 *offsetp += 1;
3825 requestLength(tvb, offsetp, t, byte_order);
3826 WINDOW(window);
3827 ATOM(property);
3828 break;
3830 case X_GetProperty:
3831 BOOL(delete);
3832 requestLength(tvb, offsetp, t, byte_order);
3833 WINDOW(window);
3834 ATOM(property);
3835 ATOM(get_property_type);
3836 CARD32(long_offset);
3837 CARD32(long_length);
3838 break;
3840 case X_ListProperties:
3841 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3842 *offsetp += 1;
3843 requestLength(tvb, offsetp, t, byte_order);
3844 WINDOW(window);
3845 break;
3847 case X_SetSelectionOwner:
3848 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3849 *offsetp += 1;
3850 requestLength(tvb, offsetp, t, byte_order);
3851 WINDOW(owner);
3852 ATOM(selection);
3853 TIMESTAMP(time);
3854 break;
3856 case X_GetSelectionOwner:
3857 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3858 *offsetp += 1;
3859 requestLength(tvb, offsetp, t, byte_order);
3860 ATOM(selection);
3861 break;
3863 case X_ConvertSelection:
3864 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3865 *offsetp += 1;
3866 requestLength(tvb, offsetp, t, byte_order);
3867 WINDOW(requestor);
3868 ATOM(selection);
3869 ATOM(target);
3870 ATOM(property);
3871 TIMESTAMP(time);
3872 break;
3874 case X_SendEvent:
3875 BOOL(propagate);
3876 requestLength(tvb, offsetp, t, byte_order);
3877 WINDOW(destination);
3878 SETofEVENT(event_mask);
3879 EVENT();
3880 break;
3882 case X_GrabPointer:
3883 BOOL(owner_events);
3884 requestLength(tvb, offsetp, t, byte_order);
3885 WINDOW(grab_window);
3886 SETofPOINTEREVENT(pointer_event_mask);
3887 ENUM8(pointer_mode);
3888 ENUM8(keyboard_mode);
3889 WINDOW(confine_to);
3890 CURSOR(cursor);
3891 TIMESTAMP(time);
3892 break;
3894 case X_UngrabPointer:
3895 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3896 *offsetp += 1;
3897 requestLength(tvb, offsetp, t, byte_order);
3898 TIMESTAMP(time);
3899 break;
3901 case X_GrabButton:
3902 BOOL(owner_events);
3903 requestLength(tvb, offsetp, t, byte_order);
3904 WINDOW(grab_window);
3905 SETofPOINTEREVENT(event_mask);
3906 ENUM8(pointer_mode);
3907 ENUM8(keyboard_mode);
3908 WINDOW(confine_to);
3909 CURSOR(cursor);
3910 BUTTON(button);
3911 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3912 *offsetp += 1;
3913 SETofKEYMASK(modifiers);
3914 break;
3916 case X_UngrabButton:
3917 BUTTON(button);
3918 requestLength(tvb, offsetp, t, byte_order);
3919 WINDOW(grab_window);
3920 SETofKEYMASK(modifiers);
3921 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3922 *offsetp += 2;
3923 break;
3925 case X_ChangeActivePointerGrab:
3926 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3927 *offsetp += 1;
3928 requestLength(tvb, offsetp, t, byte_order);
3929 CURSOR(cursor);
3930 TIMESTAMP(time);
3931 SETofPOINTEREVENT(event_mask);
3932 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3933 *offsetp += 2;
3934 break;
3936 case X_GrabKeyboard:
3937 BOOL(owner_events);
3938 requestLength(tvb, offsetp, t, byte_order);
3939 WINDOW(grab_window);
3940 TIMESTAMP(time);
3941 ENUM8(pointer_mode);
3942 ENUM8(keyboard_mode);
3943 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3944 *offsetp += 2;
3945 break;
3947 case X_UngrabKeyboard:
3948 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3949 *offsetp += 1;
3950 requestLength(tvb, offsetp, t, byte_order);
3951 TIMESTAMP(time);
3952 break;
3954 case X_GrabKey:
3955 BOOL(owner_events);
3956 requestLength(tvb, offsetp, t, byte_order);
3957 WINDOW(grab_window);
3958 SETofKEYMASK(modifiers);
3959 KEYCODE(key);
3960 ENUM8(pointer_mode);
3961 ENUM8(keyboard_mode);
3962 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
3963 *offsetp += 3;
3964 break;
3966 case X_UngrabKey:
3967 KEYCODE(key);
3968 requestLength(tvb, offsetp, t, byte_order);
3969 WINDOW(grab_window);
3970 SETofKEYMASK(modifiers);
3971 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
3972 *offsetp += 2;
3973 break;
3975 case X_AllowEvents:
3976 ENUM8(allow_events_mode);
3977 requestLength(tvb, offsetp, t, byte_order);
3978 TIMESTAMP(time);
3979 break;
3981 case X_GrabServer:
3982 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3983 *offsetp += 1;
3984 requestLength(tvb, offsetp, t, byte_order);
3985 break;
3987 case X_UngrabServer:
3988 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3989 *offsetp += 1;
3990 requestLength(tvb, offsetp, t, byte_order);
3991 break;
3993 case X_QueryPointer:
3994 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
3995 *offsetp += 1;
3996 requestLength(tvb, offsetp, t, byte_order);
3997 WINDOW(window);
3998 break;
4000 case X_GetMotionEvents:
4001 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4002 *offsetp += 1;
4003 requestLength(tvb, offsetp, t, byte_order);
4004 WINDOW(window);
4005 TIMESTAMP(start);
4006 TIMESTAMP(stop);
4007 break;
4009 case X_TranslateCoords:
4010 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4011 *offsetp += 1;
4012 requestLength(tvb, offsetp, t, byte_order);
4013 WINDOW(src_window);
4014 WINDOW(dst_window);
4015 INT16(src_x);
4016 INT16(src_y);
4017 break;
4019 case X_WarpPointer:
4020 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4021 *offsetp += 1;
4022 requestLength(tvb, offsetp, t, byte_order);
4023 WINDOW(warp_pointer_src_window);
4024 WINDOW(warp_pointer_dst_window);
4025 INT16(src_x);
4026 INT16(src_y);
4027 CARD16(src_width);
4028 CARD16(src_height);
4029 INT16(dst_x);
4030 INT16(dst_y);
4031 break;
4033 case X_SetInputFocus:
4034 ENUM8(revert_to);
4035 requestLength(tvb, offsetp, t, byte_order);
4036 WINDOW(focus);
4037 TIMESTAMP(time);
4038 break;
4040 case X_GetInputFocus:
4041 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4042 *offsetp += 1;
4043 requestLength(tvb, offsetp, t, byte_order);
4044 break;
4046 case X_QueryKeymap:
4047 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4048 *offsetp += 1;
4049 requestLength(tvb, offsetp, t, byte_order);
4050 break;
4052 case X_OpenFont:
4053 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4054 *offsetp += 1;
4055 requestLength(tvb, offsetp, t, byte_order);
4056 FONT(fid);
4057 v16 = FIELD16(name_length);
4058 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4059 *offsetp += 2;
4060 STRING8(name, v16);
4061 PAD();
4062 break;
4064 case X_CloseFont:
4065 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4066 *offsetp += 1;
4067 requestLength(tvb, offsetp, t, byte_order);
4068 FONT(font);
4069 break;
4071 case X_QueryFont:
4072 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4073 *offsetp += 1;
4074 requestLength(tvb, offsetp, t, byte_order);
4075 FONTABLE(font);
4076 break;
4078 case X_QueryTextExtents:
4079 v8 = BOOL(odd_length);
4080 requestLength(tvb, offsetp, t, byte_order);
4081 FONTABLE(font);
4082 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
4083 PAD();
4084 break;
4086 case X_ListFonts:
4087 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4088 *offsetp += 1;
4089 requestLength(tvb, offsetp, t, byte_order);
4090 CARD16(max_names);
4091 v16 = FIELD16(pattern_length);
4092 STRING8(pattern, v16);
4093 PAD();
4094 break;
4096 case X_ListFontsWithInfo:
4097 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4098 *offsetp += 1;
4099 requestLength(tvb, offsetp, t, byte_order);
4100 CARD16(max_names);
4101 v16 = FIELD16(pattern_length);
4102 STRING8(pattern, v16);
4103 PAD();
4104 break;
4106 case X_SetFontPath:
4107 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4108 *offsetp += 1;
4109 requestLength(tvb, offsetp, t, byte_order);
4110 v16 = CARD16(str_number_in_path);
4111 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4112 *offsetp += 2;
4113 LISTofSTRING8(path, v16);
4114 PAD();
4115 break;
4117 case X_GetFontPath:
4118 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4119 *offsetp += 1;
4120 requestLength(tvb, offsetp, t, byte_order);
4121 break;
4123 case X_CreatePixmap:
4124 CARD8(depth);
4125 requestLength(tvb, offsetp, t, byte_order);
4126 PIXMAP(pid);
4127 DRAWABLE(drawable);
4128 CARD16(width);
4129 CARD16(height);
4130 break;
4132 case X_FreePixmap:
4133 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4134 *offsetp += 1;
4135 requestLength(tvb, offsetp, t, byte_order);
4136 PIXMAP(pixmap);
4137 break;
4139 case X_CreateGC:
4140 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4141 *offsetp += 1;
4142 requestLength(tvb, offsetp, t, byte_order);
4143 GCONTEXT(cid);
4144 DRAWABLE(drawable);
4145 gcAttributes(tvb, offsetp, t, byte_order);
4146 break;
4148 case X_ChangeGC:
4149 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4150 *offsetp += 1;
4151 requestLength(tvb, offsetp, t, byte_order);
4152 GCONTEXT(gc);
4153 gcAttributes(tvb, offsetp, t, byte_order);
4154 break;
4156 case X_CopyGC:
4157 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4158 *offsetp += 1;
4159 requestLength(tvb, offsetp, t, byte_order);
4160 GCONTEXT(src_gc);
4161 GCONTEXT(dst_gc);
4162 gcMask(tvb, offsetp, t, byte_order);
4163 break;
4165 case X_SetDashes:
4166 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4167 *offsetp += 1;
4168 requestLength(tvb, offsetp, t, byte_order);
4169 GCONTEXT(gc);
4170 CARD16(dash_offset);
4171 v16 = FIELD16(dashes_length);
4172 LISTofCARD8(dashes, v16);
4173 PAD();
4174 break;
4176 case X_SetClipRectangles:
4177 ENUM8(ordering);
4178 requestLength(tvb, offsetp, t, byte_order);
4179 GCONTEXT(gc);
4180 INT16(clip_x_origin);
4181 INT16(clip_y_origin);
4182 LISTofRECTANGLE(rectangles);
4183 break;
4185 case X_FreeGC:
4186 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4187 *offsetp += 1;
4188 requestLength(tvb, offsetp, t, byte_order);
4189 GCONTEXT(gc);
4190 break;
4192 case X_ClearArea:
4193 BOOL(exposures);
4194 requestLength(tvb, offsetp, t, byte_order);
4195 WINDOW(window);
4196 INT16(x);
4197 INT16(y);
4198 CARD16(width);
4199 CARD16(height);
4200 break;
4202 case X_CopyArea:
4203 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4204 *offsetp += 1;
4205 requestLength(tvb, offsetp, t, byte_order);
4206 DRAWABLE(src_drawable);
4207 DRAWABLE(dst_drawable);
4208 GCONTEXT(gc);
4209 INT16(src_x);
4210 INT16(src_y);
4211 INT16(dst_x);
4212 INT16(dst_y);
4213 CARD16(width);
4214 CARD16(height);
4215 break;
4217 case X_CopyPlane:
4218 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4219 *offsetp += 1;
4220 requestLength(tvb, offsetp, t, byte_order);
4221 DRAWABLE(src_drawable);
4222 DRAWABLE(dst_drawable);
4223 GCONTEXT(gc);
4224 INT16(src_x);
4225 INT16(src_y);
4226 INT16(dst_x);
4227 INT16(dst_y);
4228 CARD16(width);
4229 CARD16(height);
4230 CARD32(bit_plane);
4231 break;
4233 case X_PolyPoint:
4234 ENUM8(coordinate_mode);
4235 v16 = requestLength(tvb, offsetp, t, byte_order);
4236 DRAWABLE(drawable);
4237 GCONTEXT(gc);
4238 LISTofPOINT(points, v16 - 12);
4239 break;
4241 case X_PolyLine:
4242 ENUM8(coordinate_mode);
4243 v16 = requestLength(tvb, offsetp, t, byte_order);
4244 DRAWABLE(drawable);
4245 GCONTEXT(gc);
4246 LISTofPOINT(points, v16 - 12);
4247 break;
4249 case X_PolySegment:
4250 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4251 *offsetp += 1;
4252 requestLength(tvb, offsetp, t, byte_order);
4253 DRAWABLE(drawable);
4254 GCONTEXT(gc);
4255 LISTofSEGMENT(segments);
4256 break;
4258 case X_PolyRectangle:
4259 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4260 *offsetp += 1;
4261 requestLength(tvb, offsetp, t, byte_order);
4262 DRAWABLE(drawable);
4263 GCONTEXT(gc);
4264 LISTofRECTANGLE(rectangles);
4265 break;
4267 case X_PolyArc:
4268 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4269 *offsetp += 1;
4270 requestLength(tvb, offsetp, t, byte_order);
4271 DRAWABLE(drawable);
4272 GCONTEXT(gc);
4273 LISTofARC(arcs);
4274 break;
4276 case X_FillPoly:
4277 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4278 *offsetp += 1;
4279 v16 = requestLength(tvb, offsetp, t, byte_order);
4280 DRAWABLE(drawable);
4281 GCONTEXT(gc);
4282 ENUM8(shape);
4283 ENUM8(coordinate_mode);
4284 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4285 *offsetp += 2;
4286 LISTofPOINT(points, v16 - 16);
4287 break;
4289 case X_PolyFillRectangle:
4290 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4291 *offsetp += 1;
4292 requestLength(tvb, offsetp, t, byte_order);
4293 DRAWABLE(drawable);
4294 GCONTEXT(gc);
4295 LISTofRECTANGLE(rectangles);
4296 break;
4298 case X_PolyFillArc:
4299 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4300 *offsetp += 1;
4301 requestLength(tvb, offsetp, t, byte_order);
4302 DRAWABLE(drawable);
4303 GCONTEXT(gc);
4304 LISTofARC(arcs);
4305 break;
4307 case X_PutImage:
4308 ENUM8(image_format);
4309 v16 = requestLength(tvb, offsetp, t, byte_order);
4310 DRAWABLE(drawable);
4311 GCONTEXT(gc);
4312 CARD16(width);
4313 CARD16(height);
4314 INT16(dst_x);
4315 INT16(dst_y);
4316 CARD8(left_pad);
4317 CARD8(depth);
4318 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4319 *offsetp += 2;
4320 LISTofBYTE(data, v16 - 24);
4321 PAD();
4322 break;
4324 case X_GetImage:
4325 ENUM8(image_pixmap_format);
4326 requestLength(tvb, offsetp, t, byte_order);
4327 DRAWABLE(drawable);
4328 INT16(x);
4329 INT16(y);
4330 CARD16(width);
4331 CARD16(height);
4332 CARD32(plane_mask);
4333 break;
4335 case X_PolyText8:
4336 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4337 *offsetp += 1;
4338 requestLength(tvb, offsetp, t, byte_order);
4339 DRAWABLE(drawable);
4340 GCONTEXT(gc);
4341 INT16(x);
4342 INT16(y);
4343 LISTofTEXTITEM8(items);
4344 PAD();
4345 break;
4347 case X_PolyText16:
4348 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4349 *offsetp += 1;
4350 requestLength(tvb, offsetp, t, byte_order);
4351 DRAWABLE(drawable);
4352 GCONTEXT(gc);
4353 INT16(x);
4354 INT16(y);
4355 LISTofTEXTITEM16(items);
4356 PAD();
4357 break;
4359 case X_ImageText8:
4360 v8 = FIELD8(string_length);
4361 requestLength(tvb, offsetp, t, byte_order);
4362 DRAWABLE(drawable);
4363 GCONTEXT(gc);
4364 INT16(x);
4365 INT16(y);
4366 STRING8(string, v8);
4367 PAD();
4368 break;
4370 case X_ImageText16:
4371 v8 = FIELD8(string_length);
4372 requestLength(tvb, offsetp, t, byte_order);
4373 DRAWABLE(drawable);
4374 GCONTEXT(gc);
4375 INT16(x);
4376 INT16(y);
4377 STRING16(string16, v8);
4378 PAD();
4379 break;
4381 case X_CreateColormap:
4382 ENUM8(alloc);
4383 requestLength(tvb, offsetp, t, byte_order);
4384 COLORMAP(mid);
4385 WINDOW(window);
4386 VISUALID(visual);
4387 break;
4389 case X_FreeColormap:
4390 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4391 *offsetp += 1;
4392 requestLength(tvb, offsetp, t, byte_order);
4393 COLORMAP(cmap);
4394 break;
4396 case X_CopyColormapAndFree:
4397 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4398 *offsetp += 1;
4399 requestLength(tvb, offsetp, t, byte_order);
4400 COLORMAP(mid);
4401 COLORMAP(src_cmap);
4402 break;
4404 case X_InstallColormap:
4405 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4406 *offsetp += 1;
4407 requestLength(tvb, offsetp, t, byte_order);
4408 COLORMAP(cmap);
4409 break;
4411 case X_UninstallColormap:
4412 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4413 *offsetp += 1;
4414 requestLength(tvb, offsetp, t, byte_order);
4415 COLORMAP(cmap);
4416 break;
4418 case X_ListInstalledColormaps:
4419 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4420 *offsetp += 1;
4421 requestLength(tvb, offsetp, t, byte_order);
4422 WINDOW(window);
4423 break;
4425 case X_AllocColor:
4426 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4427 *offsetp += 1;
4428 requestLength(tvb, offsetp, t, byte_order);
4429 COLORMAP(cmap);
4430 CARD16(red);
4431 CARD16(green);
4432 CARD16(blue);
4433 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4434 *offsetp += 2;
4435 break;
4437 case X_AllocNamedColor:
4438 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4439 *offsetp += 1;
4440 requestLength(tvb, offsetp, t, byte_order);
4441 COLORMAP(cmap);
4442 v16 = FIELD16(name_length);
4443 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4444 *offsetp += 2;
4445 STRING8(name, v16);
4446 PAD();
4447 break;
4449 case X_AllocColorCells:
4450 BOOL(contiguous);
4451 requestLength(tvb, offsetp, t, byte_order);
4452 COLORMAP(cmap);
4453 CARD16(colors);
4454 CARD16(planes);
4455 break;
4457 case X_AllocColorPlanes:
4458 BOOL(contiguous);
4459 requestLength(tvb, offsetp, t, byte_order);
4460 COLORMAP(cmap);
4461 CARD16(colors);
4462 CARD16(reds);
4463 CARD16(greens);
4464 CARD16(blues);
4465 break;
4467 case X_FreeColors:
4468 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4469 *offsetp += 1;
4470 v16 = requestLength(tvb, offsetp, t, byte_order);
4471 COLORMAP(cmap);
4472 CARD32(plane_mask);
4473 LISTofCARD32(pixels, v16 - 12);
4474 break;
4476 case X_StoreColors:
4477 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4478 *offsetp += 1;
4479 v16 = requestLength(tvb, offsetp, t, byte_order);
4480 COLORMAP(cmap);
4481 LISTofCOLORITEM(color_items, v16 - 8);
4482 break;
4484 case X_StoreNamedColor:
4485 COLOR_FLAGS(color);
4486 requestLength(tvb, offsetp, t, byte_order);
4487 COLORMAP(cmap);
4488 CARD32(pixel);
4489 v16 = FIELD16(name_length);
4490 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4491 *offsetp += 2;
4492 STRING8(name, v16);
4493 PAD();
4494 break;
4496 case X_QueryColors:
4497 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4498 *offsetp += 1;
4499 v16 = requestLength(tvb, offsetp, t, byte_order);
4500 COLORMAP(cmap);
4501 LISTofCARD32(pixels, v16 - 8);
4502 break;
4504 case X_LookupColor:
4505 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4506 *offsetp += 1;
4507 requestLength(tvb, offsetp, t, byte_order);
4508 COLORMAP(cmap);
4509 v16 = FIELD16(name_length);
4510 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4511 *offsetp += 2;
4512 STRING8(name, v16);
4513 PAD();
4514 break;
4516 case X_CreateCursor:
4517 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4518 *offsetp += 1;
4519 requestLength(tvb, offsetp, t, byte_order);
4520 CURSOR(cid);
4521 PIXMAP(source_pixmap);
4522 PIXMAP(mask);
4523 CARD16(fore_red);
4524 CARD16(fore_green);
4525 CARD16(fore_blue);
4526 CARD16(back_red);
4527 CARD16(back_green);
4528 CARD16(back_blue);
4529 CARD16(x);
4530 CARD16(y);
4531 break;
4533 case X_CreateGlyphCursor:
4534 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4535 *offsetp += 1;
4536 requestLength(tvb, offsetp, t, byte_order);
4537 CURSOR(cid);
4538 FONT(source_font);
4539 FONT(mask_font);
4540 CARD16(source_char);
4541 CARD16(mask_char);
4542 CARD16(fore_red);
4543 CARD16(fore_green);
4544 CARD16(fore_blue);
4545 CARD16(back_red);
4546 CARD16(back_green);
4547 CARD16(back_blue);
4548 break;
4550 case X_FreeCursor:
4551 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4552 *offsetp += 1;
4553 requestLength(tvb, offsetp, t, byte_order);
4554 CURSOR(cursor);
4555 break;
4557 case X_RecolorCursor:
4558 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4559 *offsetp += 1;
4560 requestLength(tvb, offsetp, t, byte_order);
4561 CURSOR(cursor);
4562 CARD16(fore_red);
4563 CARD16(fore_green);
4564 CARD16(fore_blue);
4565 CARD16(back_red);
4566 CARD16(back_green);
4567 CARD16(back_blue);
4568 break;
4570 case X_QueryBestSize:
4571 ENUM8(class);
4572 requestLength(tvb, offsetp, t, byte_order);
4573 DRAWABLE(drawable);
4574 CARD16(width);
4575 CARD16(height);
4576 break;
4578 case X_QueryExtension:
4579 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4580 *offsetp += 1;
4581 requestLength(tvb, offsetp, t, byte_order);
4582 v16 = FIELD16(name_length);
4583 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4584 *offsetp += 2;
4585 STRING8(name, v16);
4586 PAD();
4587 break;
4589 case X_ListExtensions:
4590 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4591 *offsetp += 1;
4592 requestLength(tvb, offsetp, t, byte_order);
4593 break;
4595 case X_ChangeKeyboardMapping:
4596 v8 = FIELD8(keycode_count);
4597 requestLength(tvb, offsetp, t, byte_order);
4598 v8_2 = KEYCODE(first_keycode);
4599 v8_3 = FIELD8(keysyms_per_keycode);
4600 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4601 *offsetp += 2;
4602 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
4603 break;
4605 case X_GetKeyboardMapping:
4606 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4607 *offsetp += 1;
4608 requestLength(tvb, offsetp, t, byte_order);
4609 state->request.GetKeyboardMapping.first_keycode
4610 = KEYCODE(first_keycode);
4611 FIELD8(count);
4612 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4613 *offsetp += 2;
4614 break;
4616 case X_ChangeKeyboardControl:
4618 uint32_t bitmask32;
4619 static int * const keyboard_value_flags[] = {
4620 &hf_x11_keyboard_value_mask_key_click_percent,
4621 &hf_x11_keyboard_value_mask_bell_percent,
4622 &hf_x11_keyboard_value_mask_bell_pitch,
4623 &hf_x11_keyboard_value_mask_bell_duration,
4624 &hf_x11_keyboard_value_mask_led,
4625 &hf_x11_keyboard_value_mask_led_mode,
4626 &hf_x11_keyboard_value_mask_keyboard_key,
4627 &hf_x11_keyboard_value_mask_auto_repeat_mode,
4628 NULL
4631 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4632 *offsetp += 1;
4633 requestLength(tvb, offsetp, t, byte_order);
4634 bitmask32 = tvb_get_uint32(tvb, *offsetp, byte_order);
4635 proto_tree_add_bitmask(t, tvb, *offsetp, hf_x11_keyboard_value_mask, ett_x11_keyboard_value_mask, keyboard_value_flags, byte_order);
4636 *offsetp += 4;
4637 if (bitmask32 & 0x00000001) {
4638 proto_tree_add_item(t, hf_x11_key_click_percent, tvb, *offsetp, 1, byte_order);
4639 *offsetp += 1;
4640 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
4641 *offsetp += 3;
4643 if (bitmask32 & 0x00000002) {
4644 proto_tree_add_item(t, hf_x11_bell_percent, tvb, *offsetp, 1, byte_order);
4645 *offsetp += 1;
4646 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
4647 *offsetp += 3;
4649 if (bitmask32 & 0x00000004) {
4650 proto_tree_add_item(t, hf_x11_bell_pitch, tvb, *offsetp, 2, byte_order);
4651 *offsetp += 2;
4652 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4653 *offsetp += 2;
4655 if (bitmask32 & 0x00000008) {
4656 proto_tree_add_item(t, hf_x11_bell_duration, tvb, *offsetp, 2, byte_order);
4657 *offsetp += 2;
4658 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4659 *offsetp += 2;
4661 if (bitmask32 & 0x00000010) {
4662 proto_tree_add_item(t, hf_x11_led, tvb, *offsetp, 2, byte_order);
4663 *offsetp += 2;
4664 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4665 *offsetp += 2;
4667 if (bitmask32 & 0x00000020) {
4668 proto_tree_add_item(t, hf_x11_led_mode, tvb, *offsetp, 1, byte_order);
4669 *offsetp += 1;
4670 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
4671 *offsetp += 3;
4673 if (bitmask32 & 0x00000040) {
4674 proto_tree_add_item(t, hf_x11_keyboard_key, tvb, *offsetp, 1, byte_order);
4675 *offsetp += 1;
4676 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
4677 *offsetp += 3;
4679 if (bitmask32 & 0x00000080) {
4680 proto_tree_add_item(t, hf_x11_auto_repeat_mode, tvb, *offsetp, 1, byte_order);
4681 *offsetp += 1;
4682 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 3, ENC_NA);
4683 *offsetp += 3;
4686 break;
4688 case X_GetKeyboardControl:
4689 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4690 *offsetp += 1;
4691 requestLength(tvb, offsetp, t, byte_order);
4692 break;
4694 case X_Bell:
4695 INT8(percent);
4696 requestLength(tvb, offsetp, t, byte_order);
4697 break;
4699 case X_ChangePointerControl:
4700 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4701 *offsetp += 1;
4702 requestLength(tvb, offsetp, t, byte_order);
4703 INT16(acceleration_numerator);
4704 INT16(acceleration_denominator);
4705 INT16(threshold);
4706 BOOL(do_acceleration);
4707 BOOL(do_threshold);
4708 break;
4710 case X_GetPointerControl:
4711 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4712 *offsetp += 1;
4713 requestLength(tvb, offsetp, t, byte_order);
4714 break;
4716 case X_SetScreenSaver:
4717 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4718 *offsetp += 1;
4719 requestLength(tvb, offsetp, t, byte_order);
4720 INT16(timeout);
4721 INT16(interval);
4722 ENUM8(prefer_blanking);
4723 ENUM8(allow_exposures);
4724 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
4725 *offsetp += 2;
4726 break;
4728 case X_GetScreenSaver:
4729 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4730 *offsetp += 1;
4731 requestLength(tvb, offsetp, t, byte_order);
4732 break;
4734 case X_ChangeHosts:
4735 ENUM8(change_host_mode);
4736 requestLength(tvb, offsetp, t, byte_order);
4737 v8 = ENUM8(family);
4738 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4739 *offsetp += 1;
4740 v16 = CARD16(address_length);
4741 if (v8 == FAMILY_INTERNET && v16 == 4) {
4743 * IPv4 addresses.
4744 * XXX - what about IPv6? Is that a family of
4745 * FAMILY_INTERNET (0) with a length of 16?
4747 LISTofIPADDRESS(ip_address, v16);
4748 } else
4749 LISTofCARD8(address, v16);
4750 break;
4752 case X_ListHosts:
4753 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4754 *offsetp += 1;
4755 requestLength(tvb, offsetp, t, byte_order);
4756 break;
4758 case X_SetAccessControl:
4759 ENUM8(access_mode);
4760 requestLength(tvb, offsetp, t, byte_order);
4761 break;
4763 case X_SetCloseDownMode:
4764 ENUM8(close_down_mode);
4765 requestLength(tvb, offsetp, t, byte_order);
4766 break;
4768 case X_KillClient:
4769 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4770 *offsetp += 1;
4771 requestLength(tvb, offsetp, t, byte_order);
4772 CARD32(resource);
4773 break;
4775 case X_RotateProperties:
4776 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4777 *offsetp += 1;
4778 v16 = requestLength(tvb, offsetp, t, byte_order);
4779 WINDOW(window);
4780 CARD16(property_number);
4781 INT16(delta);
4782 LISTofATOM(properties, (v16 - 12));
4783 break;
4785 case X_ForceScreenSaver:
4786 ENUM8(screen_saver_mode);
4787 requestLength(tvb, offsetp, t, byte_order);
4788 break;
4790 case X_SetPointerMapping:
4791 v8 = FIELD8(map_length);
4792 requestLength(tvb, offsetp, t, byte_order);
4793 LISTofCARD8(map, v8);
4794 PAD();
4795 break;
4797 case X_GetPointerMapping:
4798 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4799 *offsetp += 1;
4800 requestLength(tvb, offsetp, t, byte_order);
4801 break;
4803 case X_SetModifierMapping:
4804 v8 = FIELD8(keycodes_per_modifier);
4805 requestLength(tvb, offsetp, t, byte_order);
4806 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4807 break;
4809 case X_GetModifierMapping:
4810 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4811 *offsetp += 1;
4812 requestLength(tvb, offsetp, t, byte_order);
4813 break;
4815 case X_NoOperation:
4816 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
4817 *offsetp += 1;
4818 requestLength(tvb, offsetp, t, byte_order);
4819 break;
4820 default:
4821 tryExtension(opcode, tvb, pinfo, offsetp, t, state, byte_order);
4822 break;
4825 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4826 UNDECODED(left);
4829 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4830 proto_tree *tree)
4832 volatile int offset = 0;
4833 int length_remaining;
4834 volatile unsigned byte_order;
4835 uint8_t opcode;
4836 volatile int plen;
4837 proto_item *ti;
4838 volatile bool is_initial_creq;
4839 uint16_t auth_proto_len, auth_data_len;
4840 const char *volatile sep = NULL;
4841 conversation_t *conversation;
4842 x11_conv_data_t *volatile state;
4843 int length;
4844 tvbuff_t *volatile next_tvb;
4846 while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) {
4849 * Can we do reassembly?
4851 if (x11_desegment && pinfo->can_desegment) {
4853 * Yes - is the X11 request header split across
4854 * segment boundaries?
4856 if (length_remaining < 4) {
4858 * Yes. Tell the TCP dissector where the data
4859 * for this message starts in the data it handed
4860 * us and that we need "some more data." Don't tell
4861 * it exactly how many bytes we need because if/when
4862 * we ask for even more (after the header) that will
4863 * break reassembly.
4865 pinfo->desegment_offset = offset;
4866 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4867 return;
4872 * Get the state for this conversation; create the conversation
4873 * if we don't have one, and create the state if we don't have
4874 * any.
4876 conversation = find_or_create_conversation(pinfo);
4879 * Is there state attached to this conversation?
4881 if ((state = (x11_conv_data_t *)conversation_get_proto_data(conversation, proto_x11))
4882 == NULL)
4883 state = x11_stateinit(conversation);
4886 * Guess the byte order if we don't already know it.
4888 byte_order = guess_byte_ordering(tvb, pinfo, state);
4891 * Get the opcode and length of the putative X11 request.
4893 opcode = tvb_get_uint8(tvb, 0);
4894 plen = tvb_get_uint16(tvb, offset + 2, byte_order);
4896 if (plen == 0) {
4898 * A length field of 0 indicates that the BIG-REQUESTS
4899 * extension is used: The next four bytes are the real length.
4901 plen = tvb_get_uint32(tvb, offset + 4, byte_order);
4904 if (plen <= 0) {
4906 * This can't be less then 0, as it includes the header length.
4907 * A different choice of byte order wouldn't have
4908 * helped.
4909 * Give up.
4911 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1, ENC_NA);
4912 expert_add_info_format(pinfo, ti, &ei_x11_request_length, "Bogus request length (%d)", plen);
4913 return;
4916 if (state->iconn_frame == pinfo->num ||
4917 (wmem_map_lookup(state->seqtable,
4918 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4919 (opcode == 'B' || opcode == 'l') &&
4920 (plen == 11 || plen == 2816))) {
4922 * Either
4924 * we saw this on the first pass and this is
4925 * it again
4927 * or
4928 * we haven't already seen any requests, the first
4929 * byte of the message is 'B' or 'l', and the 16-bit
4930 * integer 2 bytes into the data stream is either 11
4931 * or a byte-swapped 11.
4933 * This means it's probably an initial connection
4934 * request, not a message.
4936 * 'B' is decimal 66, which is the opcode for a
4937 * PolySegment request; unfortunately, 11 is a valid
4938 * length for a PolySegment request request, so we
4939 * might mis-identify that request. (Are there any
4940 * other checks we can do?)
4942 * 'l' is decimal 108, which is the opcode for a
4943 * GetScreenSaver request; the only valid length
4944 * for that request is 1.
4946 is_initial_creq = true;
4949 * We now know the byte order. Override the guess.
4951 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4952 if (opcode == 'B') {
4954 * Big-endian.
4956 byte_order = state->byte_order = ENC_BIG_ENDIAN;
4957 } else {
4959 * Little-endian.
4961 byte_order = state->byte_order = ENC_LITTLE_ENDIAN;
4966 * Can we do reassembly?
4968 if (x11_desegment && pinfo->can_desegment) {
4970 * Yes - is the fixed-length portion of the
4971 * initial connection header split across
4972 * segment boundaries?
4974 if (length_remaining < 10) {
4976 * Yes. Tell the TCP dissector where the
4977 * data for this message starts in the data
4978 * it handed us and that we need "some more
4979 * data." Don't tell it exactly how many bytes
4980 * we need because if/when we ask for even more
4981 * (after the header) that will break reassembly.
4983 pinfo->desegment_offset = offset;
4984 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4985 return;
4990 * Get the lengths of the authorization protocol and
4991 * the authorization data.
4993 auth_proto_len = tvb_get_uint16(tvb, offset + 6, byte_order);
4994 auth_data_len = tvb_get_uint16(tvb, offset + 8, byte_order);
4995 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4996 ROUND_LENGTH(auth_data_len);
4997 } else {
4998 volatile int64_t tmp = (int64_t)plen * 4;
5000 * This is probably an ordinary request.
5002 is_initial_creq = false;
5005 * The length of a request is in 4-byte words.
5007 if (tmp > INT32_MAX) {
5008 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1, ENC_NA);
5009 expert_add_info_format(pinfo, ti, &ei_x11_request_length, "Bogus request length (%"PRId64")", tmp);
5010 return;
5012 plen = (int)tmp;
5016 * Can we do reassembly?
5018 if (x11_desegment && pinfo->can_desegment) {
5020 * Yes - is the X11 request split across segment
5021 * boundaries?
5023 if (length_remaining < plen) {
5025 * Yes. Tell the TCP dissector where the data
5026 * for this message starts in the data it handed
5027 * us, and how many more bytes we need, and return.
5029 pinfo->desegment_offset = offset;
5030 pinfo->desegment_len = plen - length_remaining;
5031 return;
5036 * Construct a tvbuff containing the amount of the payload
5037 * we have available. Make its reported length the
5038 * amount of data in the X11 request.
5040 * XXX - if reassembly isn't enabled. the subdissector
5041 * will throw a BoundsError exception, rather than a
5042 * ReportedBoundsError exception. We really want a tvbuff
5043 * where the length is "length", the reported length is "plen",
5044 * and the "if the snapshot length were infinite" length is the
5045 * minimum of the reported length of the tvbuff handed to us
5046 * and "plen", with a new type of exception thrown if the offset
5047 * is within the reported length but beyond that third length,
5048 * with that exception getting the "Unreassembled Packet" error.
5050 length = length_remaining;
5051 if (length > plen)
5052 length = plen;
5053 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen);
5056 * Set the column appropriately.
5058 if (is_initial_creq) {
5059 col_set_str(pinfo->cinfo, COL_INFO, "Initial connection request");
5060 } else {
5061 if (sep == NULL) {
5063 * We haven't set the column yet; set it.
5065 col_set_str(pinfo->cinfo, COL_INFO, "Requests");
5068 * Initialize the separator.
5070 sep = ":";
5075 * Dissect the X11 request.
5077 * Catch the ReportedBoundsError exception; if this
5078 * particular message happens to get a ReportedBoundsError
5079 * exception, that doesn't mean that we should stop
5080 * dissecting X11 requests within this frame or chunk of
5081 * reassembled data.
5083 * If it gets a BoundsError, we can stop, as there's nothing
5084 * more to see, so we just re-throw it.
5086 TRY {
5087 if (is_initial_creq) {
5088 dissect_x11_initial_conn(next_tvb, pinfo, tree,
5089 state, byte_order);
5090 } else {
5091 dissect_x11_request(next_tvb, pinfo, tree, sep,
5092 state, byte_order);
5095 CATCH_NONFATAL_ERRORS {
5096 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
5098 ENDTRY;
5101 * Skip the X11 message.
5103 offset += plen;
5105 sep = ",";
5109 static x11_conv_data_t *
5110 x11_stateinit(conversation_t *conversation)
5112 x11_conv_data_t *state;
5113 static x11_conv_data_t stateinit;
5114 int i;
5116 state = wmem_new(wmem_file_scope(), x11_conv_data_t);
5117 *state = stateinit;
5119 /* initialise opcodes */
5120 for (i = 0; opcode_vals[i].strptr != NULL; i++) {
5121 state->opcode_vals[i].value = opcode_vals[i].value;
5122 state->opcode_vals[i].strptr = opcode_vals[i].strptr;
5124 for (; i <= MAX_OPCODES; i++) {
5125 state->opcode_vals[i].value = 0;
5126 state->opcode_vals[i].strptr = NULL;
5129 /* initialise errorcodes */
5130 for (i = 0; errorcode_vals[i].strptr != NULL; i++) {
5131 state->errorcode_vals[i].value = errorcode_vals[i].value;
5132 state->errorcode_vals[i].strptr = errorcode_vals[i].strptr;
5134 for (; i <= LastExtensionError + 1; i++) {
5135 state->errorcode_vals[i].value = 0;
5136 state->errorcode_vals[i].strptr = NULL;
5139 /* initialise eventcodes */
5140 for (i = 0; eventcode_vals[i].strptr != NULL; i++) {
5141 state->eventcode_vals[i].value = eventcode_vals[i].value;
5142 state->eventcode_vals[i].strptr = eventcode_vals[i].strptr;
5144 for (; i <= LastExtensionEvent + 1; i++) {
5145 state->eventcode_vals[i].value = 0;
5146 state->eventcode_vals[i].strptr = NULL;
5148 state->eventcode_funcs = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5149 state->reply_funcs = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5151 state->seqtable = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5152 state->valtable = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5153 wmem_map_insert(state->seqtable, (int *)0, (int *)NOTHING_SEEN);
5154 state->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
5155 conversation_add_proto_data(conversation, proto_x11, state);
5156 return state;
5160 static void
5161 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5163 /* Set up structures we will need to add the protocol subtree and manage it */
5164 volatile int offset, plen;
5165 tvbuff_t *volatile next_tvb;
5166 conversation_t *conversation;
5167 x11_conv_data_t *volatile state;
5168 volatile unsigned byte_order;
5169 int length_remaining;
5170 const char *volatile sep = NULL;
5174 * Get the state for this conversation; create the conversation
5175 * if we don't have one, and create the state if we don't have
5176 * any.
5178 conversation = find_or_create_conversation(pinfo);
5181 * Is there state attached to this conversation?
5183 if ((state = (x11_conv_data_t *)conversation_get_proto_data(conversation, proto_x11))
5184 == NULL) {
5186 * No - create a state structure and attach it.
5188 state = x11_stateinit(conversation);
5192 * Guess the byte order if we don't already know it.
5194 byte_order = guess_byte_ordering(tvb, pinfo, state);
5196 offset = 0;
5197 while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) {
5199 * Can we do reassembly?
5201 if (x11_desegment && pinfo->can_desegment) {
5203 * Yes - is the X11 Reply or GenericEvent header split across
5204 * segment boundaries?
5206 if (length_remaining < 8) {
5208 * Yes. Tell the TCP dissector where the data
5209 * for this message starts in the data it handed
5210 * us and that we need "some more data." Don't tell
5211 * it exactly how many bytes we need because if/when
5212 * we ask for even more (after the header) that will
5213 * break reassembly.
5215 pinfo->desegment_offset = offset;
5216 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
5217 return;
5222 * Find out what kind of a reply it is.
5223 * There are four possible:
5224 * - reply to initial connection
5225 * - errorreply (a request generated an error)
5226 * - requestreply (reply to a request)
5227 * - event (some event occurred)
5229 if (wmem_map_lookup(state->seqtable,
5230 GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN
5231 || (state->iconn_reply == pinfo->num)) {
5233 * Either the connection is in the "initial
5234 * connection" state, or this frame is known
5235 * to have the initial connection reply.
5236 * That means this is the initial connection
5237 * reply.
5239 plen = 8 + tvb_get_uint16(tvb, offset + 6, byte_order) * 4;
5241 HANDLE_REPLY(plen, length_remaining,
5242 "Initial connection reply",
5243 dissect_x11_initial_reply);
5244 } else {
5246 * This isn't an initial connection reply
5247 * (XXX - unless we missed the initial
5248 * connection request). Look at the first
5249 * byte to determine what it is; errors
5250 * start with a byte of 0, replies start
5251 * with a byte of 1, events start with
5252 * a byte with of 2 or greater.
5254 switch (tvb_get_uint8(tvb, offset)) {
5256 case 0:
5257 plen = 32;
5258 HANDLE_REPLY(plen, length_remaining,
5259 "Error", dissect_x11_error);
5260 break;
5262 case 1:
5264 /* To avoid an "assert w/side-effect" warning,
5265 * use a non-volatile temp variable instead. */
5266 int tmp_plen;
5268 /* replylength is in units of four. */
5269 tmp_plen = plen = 32 + tvb_get_uint32(tvb, offset + 4, byte_order) * 4;
5270 /* If tmp_plen < 32, we got an overflow;
5271 * the reply length is too long. */
5272 THROW_ON(tmp_plen < 32, ReportedBoundsError);
5273 HANDLE_REPLY(plen, length_remaining,
5274 "Reply", dissect_x11_reply);
5275 break;
5278 case GenericEvent:
5280 /* An Event, but with a length field like a Reply. */
5282 /* To avoid an "assert w/side-effect" warning,
5283 * use a non-volatile temp variable instead. */
5284 int tmp_plen;
5286 /* GenericEvent's length is also in units of four. */
5287 tmp_plen = plen = 32 + tvb_get_uint32(tvb, offset + 4, byte_order) * 4;
5288 /* If tmp_plen < 32, we got an overflow;
5289 * the event length is too long. */
5290 THROW_ON(tmp_plen < 32, ReportedBoundsError);
5291 HANDLE_REPLY(plen, length_remaining,
5292 "Event", dissect_x11_event);
5293 break;
5296 default:
5297 /* Event */
5298 plen = 32;
5299 HANDLE_REPLY(plen, length_remaining,
5300 "Event", dissect_x11_event);
5301 break;
5305 offset += plen;
5308 return;
5311 static void
5312 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5313 const char *sep, x11_conv_data_t *state,
5314 unsigned byte_order)
5316 int offset = 0, *offsetp = &offset, length, left, opcode;
5317 int major_opcode, sequence_number, first_error, first_event;
5318 value_string *vals_p;
5319 proto_item *ti;
5320 proto_tree *t;
5322 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
5323 t = proto_item_add_subtree(ti, ett_x11);
5327 * XXX - this doesn't work correctly if either
5329 * 1) the request sequence number wraps in the lower 16
5330 * bits;
5332 * 2) we don't see the initial connection request and the
5333 * resynchronization of sequence number fails and thus
5334 * don't have the right sequence numbers
5336 * 3) we don't have all the packets in the capture and
5337 * get out of sequence.
5339 * We might, instead, want to assume that a reply is a reply to
5340 * the most recent not-already-replied-to request in the same
5341 * connection. That also might mismatch replies to requests if
5342 * packets are lost, but there's nothing you can do to fix that.
5345 sequence_number = tvb_get_uint16(tvb, offset + 2, byte_order);
5346 opcode = GPOINTER_TO_INT(wmem_map_lookup(state->seqtable,
5347 GINT_TO_POINTER(sequence_number)));
5349 if (state->iconn_frame == 0 && state->resync == false) {
5352 * We don't see the initial connection request and no
5353 * resynchronization has been performed yet (first reply),
5354 * set the current sequence number to the one of the
5355 * current reply (this is only performed once).
5357 state->sequencenumber = sequence_number;
5358 state->resync = true;
5361 if (opcode == UNKNOWN_OPCODE) {
5362 col_append_fstr(pinfo->cinfo, COL_INFO,
5363 "%s to unknown request", sep);
5364 proto_item_append_text(ti, ", Reply to unknown request");
5365 } else {
5366 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5367 sep,
5368 val_to_str(opcode & 0xFF, state->opcode_vals,
5369 "<Unknown opcode %d>"));
5371 if (opcode > 0xFF)
5372 proto_item_append_text(ti, ", Reply, opcode: %d.%d (%s)",
5373 opcode & 0xFF, opcode >> 8, val_to_str(opcode & 0xFF,
5374 state->opcode_vals,
5375 "<Unknown opcode %d>"));
5376 else
5377 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
5378 opcode, val_to_str(opcode,
5379 state->opcode_vals,
5380 "<Unknown opcode %d>"));
5383 switch (opcode) {
5386 * Replies that need special processing outside tree
5389 case X_QueryExtension:
5392 * if extension is present and request is known:
5393 * store opcode of extension in value_string of
5394 * opcodes
5396 if (!tvb_get_uint8(tvb, offset + 8)) {
5397 /* not present */
5398 break;
5401 vals_p = (value_string *)wmem_map_lookup(state->valtable,
5402 GINT_TO_POINTER(sequence_number));
5403 if (vals_p != NULL) {
5404 major_opcode = tvb_get_uint8(tvb, offset + 9);
5405 first_event = tvb_get_uint8(tvb, offset + 10);
5406 first_error = tvb_get_uint8(tvb, offset + 11);
5408 register_extension(state, vals_p, major_opcode, first_event, first_error);
5409 wmem_map_remove(state->valtable,
5410 GINT_TO_POINTER(sequence_number));
5412 break;
5414 default:
5415 break;
5418 if (tree == NULL)
5419 return;
5421 switch (opcode) {
5423 * Requests that expect a reply.
5426 case X_GetWindowAttributes:
5427 REPLYCONTENTS_COMMON();
5428 break;
5430 case X_GetGeometry:
5431 REPLY(reply);
5432 CARD8(depth);
5433 SEQUENCENUMBER_REPLY(sequencenumber);
5434 REPLYLENGTH(replylength);
5435 WINDOW(rootwindow);
5436 INT16(x);
5437 INT16(y);
5438 CARD16(width);
5439 CARD16(height);
5440 CARD16(border_width);
5441 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 10, ENC_NA);
5442 *offsetp += 10;
5443 break;
5445 case X_QueryTree:
5446 REPLYCONTENTS_COMMON();
5447 break;
5449 case X_InternAtom:
5450 REPLY(reply);
5451 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5452 *offsetp += 1;
5453 SEQUENCENUMBER_REPLY(sequencenumber);
5454 REPLYLENGTH(replylength);
5455 ATOM(atom);
5456 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5457 *offsetp += 20;
5458 break;
5460 case X_GetAtomName:
5461 REPLYCONTENTS_COMMON();
5462 break;
5464 case X_GetProperty:
5465 REPLY(reply);
5466 CARD8(format);
5467 SEQUENCENUMBER_REPLY(sequencenumber);
5468 REPLYLENGTH(replylength);
5469 ATOM(get_property_type);
5470 CARD32(bytes_after);
5471 CARD32(valuelength);
5472 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 12, ENC_NA);
5473 *offsetp += 12;
5474 break;
5476 case X_ListProperties:
5477 REPLY(reply);
5478 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5479 *offsetp += 1;
5480 SEQUENCENUMBER_REPLY(sequencenumber);
5481 REPLYLENGTH(replylength);
5482 length = CARD16(property_number);
5483 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 22, ENC_NA);
5484 *offsetp += 22;
5485 LISTofATOM(properties, length*4);
5486 break;
5488 case X_GetSelectionOwner:
5489 REPLY(reply);
5490 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5491 *offsetp += 1;
5492 SEQUENCENUMBER_REPLY(sequencenumber);
5493 REPLYLENGTH(replylength);
5494 WINDOW(owner);
5495 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5496 *offsetp += 20;
5497 break;
5499 case X_GrabPointer:
5500 case X_GrabKeyboard:
5501 REPLY(reply);
5502 ENUM8(grab_status);
5503 SEQUENCENUMBER_REPLY(sequencenumber);
5504 REPLYLENGTH(replylength);
5505 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 24, ENC_NA);
5506 *offsetp += 24;
5507 break;
5509 case X_QueryPointer:
5510 REPLY(reply);
5511 BOOL(same_screen);
5512 SEQUENCENUMBER_REPLY(sequencenumber);
5513 REPLYLENGTH(replylength);
5514 WINDOW(rootwindow);
5515 WINDOW(childwindow);
5516 INT16(root_x);
5517 INT16(root_y);
5518 INT16(win_x);
5519 INT16(win_y);
5520 SETofKEYBUTMASK(mask);
5521 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 6, ENC_NA);
5522 *offsetp += 6;
5523 break;
5525 case X_GetMotionEvents:
5526 REPLYCONTENTS_COMMON();
5527 break;
5529 case X_TranslateCoords:
5530 REPLY(reply);
5531 BOOL(same_screen);
5532 SEQUENCENUMBER_REPLY(sequencenumber);
5533 REPLYLENGTH(replylength);
5534 WINDOW(childwindow);
5535 INT16(dst_x);
5536 INT16(dst_y);
5537 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 16, ENC_NA);
5538 *offsetp += 16;
5539 break;
5541 case X_GetInputFocus:
5542 REPLY(reply);
5543 ENUM8(revert_to);
5544 SEQUENCENUMBER_REPLY(sequencenumber);
5545 REPLYLENGTH(replylength);
5546 WINDOW(focus);
5547 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5548 *offsetp += 20;
5549 break;
5551 case X_QueryKeymap:
5552 REPLY(reply);
5553 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5554 *offsetp += 1;
5555 SEQUENCENUMBER_REPLY(sequencenumber);
5556 REPLYLENGTH(replylength);
5557 LISTofCARD8(keys, 32);
5558 break;
5560 case X_QueryFont:
5561 case X_QueryTextExtents:
5562 case X_ListFonts:
5563 case X_GetImage:
5564 case X_ListInstalledColormaps:
5565 REPLYCONTENTS_COMMON();
5566 break;
5568 case X_AllocColor:
5569 REPLY(reply);
5570 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5571 *offsetp += 1;
5572 SEQUENCENUMBER_REPLY(sequencenumber);
5573 REPLYLENGTH(replylength);
5574 CARD16(red);
5575 CARD16(green);
5576 CARD16(blue);
5577 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 2, ENC_NA);
5578 *offsetp += 2;
5579 CARD32(pixel);
5580 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 12, ENC_NA);
5581 *offsetp += 12;
5582 break;
5584 case X_QueryColors:
5585 REPLYCONTENTS_COMMON();
5586 break;
5588 case X_LookupColor:
5589 REPLY(reply);
5590 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5591 *offsetp += 1;
5592 SEQUENCENUMBER_REPLY(sequencenumber);
5593 REPLYLENGTH(replylength);
5594 CARD16(exact_red);
5595 CARD16(exact_green);
5596 CARD16(exact_blue);
5597 CARD16(visual_red);
5598 CARD16(visual_green);
5599 CARD16(visual_blue);
5600 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 12, ENC_NA);
5601 *offsetp += 12;
5602 break;
5604 case X_QueryBestSize:
5605 REPLY(reply);
5606 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5607 *offsetp += 1;
5608 SEQUENCENUMBER_REPLY(sequencenumber);
5609 REPLYLENGTH(replylength);
5610 CARD16(width);
5611 CARD16(height);
5612 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5613 *offsetp += 20;
5614 break;
5616 case X_QueryExtension:
5617 REPLY(reply);
5618 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5619 *offsetp += 1;
5620 SEQUENCENUMBER_REPLY(sequencenumber);
5621 REPLYLENGTH(replylength);
5622 BOOL(present);
5623 CARD8(major_opcode);
5624 CARD8(first_event);
5625 CARD8(first_error);
5626 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5627 *offsetp += 20;
5628 break;
5630 case X_ListExtensions:
5631 REPLYCONTENTS_COMMON();
5632 break;
5634 case X_GetKeyboardMapping:
5635 state->first_keycode =
5636 state->request.GetKeyboardMapping.first_keycode;
5637 REPLY(reply);
5638 state->keysyms_per_keycode =
5639 FIELD8(keysyms_per_keycode);
5640 SEQUENCENUMBER_REPLY(sequencenumber);
5641 length = REPLYLENGTH(replylength);
5642 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 24, ENC_NA);
5643 *offsetp += 24;
5644 LISTofKEYSYM(keysyms, state->keycodemap,
5645 state->request.GetKeyboardMapping.first_keycode,
5646 /* XXX - length / state->keysyms_per_keycode can raise a division by zero,
5647 * don't know if this is the *right* way to fix it ... */
5648 state->keysyms_per_keycode ? length / state->keysyms_per_keycode : 0,
5649 state->keysyms_per_keycode);
5650 break;
5652 case X_GetKeyboardControl:
5653 REPLYCONTENTS_COMMON();
5654 break;
5656 case X_GetPointerControl:
5657 REPLY(reply);
5658 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5659 *offsetp += 1;
5660 SEQUENCENUMBER_REPLY(sequencenumber);
5661 REPLYLENGTH(replylength);
5662 CARD16(acceleration_numerator);
5663 CARD16(acceleration_denominator);
5664 CARD16(threshold);
5665 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 18, ENC_NA);
5666 *offsetp += 18;
5667 break;
5669 case X_GetScreenSaver:
5670 REPLY(reply);
5671 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5672 *offsetp += 1;
5673 SEQUENCENUMBER_REPLY(sequencenumber);
5674 REPLYLENGTH(replylength);
5675 CARD16(timeout);
5676 CARD16(interval);
5677 ENUM8(prefer_blanking);
5678 ENUM8(allow_exposures);
5679 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 18, ENC_NA);
5680 *offsetp += 18;
5681 break;
5683 case X_ListHosts:
5684 case X_SetPointerMapping:
5685 case X_GetPointerMapping:
5686 case X_SetModifierMapping:
5687 REPLYCONTENTS_COMMON();
5688 break;
5690 case X_GetModifierMapping:
5691 REPLY(reply);
5692 state->keycodes_per_modifier =
5693 FIELD8(keycodes_per_modifier);
5694 SEQUENCENUMBER_REPLY(sequencenumber);
5695 REPLYLENGTH(replylength);
5696 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 24, ENC_NA);
5697 *offsetp += 24;
5698 LISTofKEYCODE(state->modifiermap, keycodes,
5699 state->keycodes_per_modifier);
5700 break;
5702 case UNKNOWN_OPCODE:
5703 REPLYCONTENTS_COMMON();
5704 break;
5706 default:
5707 tryExtensionReply(opcode, tvb, pinfo, offsetp, t, state, byte_order);
5710 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5711 UNDECODED(left);
5714 static void
5715 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
5717 proto_item *ti;
5718 uint32_t bitmask_value;
5719 int bitmask_offset;
5720 int bitmask_size;
5721 proto_tree *bitmask_tree;
5723 bitmask_value = tvb_get_uint8(tvb, *offsetp);
5724 bitmask_offset = *offsetp;
5725 bitmask_size = 1;
5727 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
5728 bitmask_value);
5729 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
5730 FLAG(same_screen_focus, focus);
5731 FLAG(same_screen_focus, same_screen);
5733 *offsetp += 1;
5736 static void
5737 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5738 const char *sep, x11_conv_data_t *state,
5739 unsigned byte_order)
5741 unsigned char eventcode;
5742 const char *sent;
5743 proto_item *ti;
5744 proto_tree *t;
5746 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
5747 t = proto_item_add_subtree(ti, ett_x11);
5749 eventcode = tvb_get_uint8(tvb, 0);
5750 sent = (eventcode & 0x80) ? "Sent-" : "";
5752 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s%s",
5753 sep, sent,
5754 val_to_str(eventcode & 0x7F, state->eventcode_vals,
5755 "<Unknown eventcode %u>"));
5757 proto_item_append_text(ti, ", Event, eventcode: %d (%s%s)",
5758 eventcode, sent,
5759 val_to_str(eventcode & 0x7F, state->eventcode_vals,
5760 "<Unknown eventcode %u>"));
5762 if (tree == NULL)
5763 return;
5765 decode_x11_event(tvb, eventcode, sent, t, state, byte_order);
5767 return;
5770 static void
5771 decode_x11_event(tvbuff_t *tvb, unsigned char eventcode, const char *sent,
5772 proto_tree *t, x11_conv_data_t *state,
5773 unsigned byte_order)
5775 int offset = 0, *offsetp = &offset, left;
5777 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
5778 eventcode,
5779 "eventcode: %d (%s%s)",
5780 eventcode, sent,
5781 val_to_str(eventcode & 0x7F, state->eventcode_vals,
5782 "<Unknown eventcode %u>"));
5783 ++offset;
5785 switch (eventcode & 0x7F) {
5786 case KeyPress:
5787 case KeyRelease: {
5788 int code, mask;
5790 /* need to do some prefetching here ... */
5791 code = tvb_get_uint8(tvb, offset);
5792 mask = tvb_get_uint16(tvb, 28, byte_order);
5794 KEYCODE_DECODED(keycode, code, mask);
5795 CARD16(event_sequencenumber);
5796 EVENTCONTENTS_COMMON();
5797 BOOL(same_screen);
5798 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5799 *offsetp += 1;
5800 break;
5803 case ButtonPress:
5804 case ButtonRelease:
5805 BUTTON(eventbutton);
5806 CARD16(event_sequencenumber);
5807 EVENTCONTENTS_COMMON();
5808 BOOL(same_screen);
5809 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5810 *offsetp += 1;
5811 break;
5813 case MotionNotify:
5814 CARD8(detail);
5815 CARD16(event_sequencenumber);
5816 EVENTCONTENTS_COMMON();
5817 BOOL(same_screen);
5818 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5819 *offsetp += 1;
5820 break;
5822 case EnterNotify:
5823 case LeaveNotify:
5824 ENUM8(event_detail);
5825 CARD16(event_sequencenumber);
5826 EVENTCONTENTS_COMMON();
5827 ENUM8(grab_mode);
5828 same_screen_focus(tvb, offsetp, t);
5829 break;
5831 case FocusIn:
5832 case FocusOut:
5833 ENUM8(focus_detail);
5834 CARD16(event_sequencenumber);
5835 WINDOW(eventwindow);
5836 ENUM8(focus_mode);
5837 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 23, ENC_NA);
5838 *offsetp += 23;
5839 break;
5841 case KeymapNotify:
5842 break;
5844 case Expose:
5845 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5846 *offsetp += 1;
5847 CARD16(event_sequencenumber);
5848 WINDOW(eventwindow);
5849 INT16(x);
5850 INT16(y);
5851 CARD16(width);
5852 CARD16(height);
5853 CARD16(count);
5854 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 14, ENC_NA);
5855 *offsetp += 14;
5856 break;
5858 case GraphicsExpose:
5859 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5860 *offsetp += 1;
5861 CARD16(event_sequencenumber);
5862 DRAWABLE(drawable);
5863 CARD16(x);
5864 CARD16(y);
5865 CARD16(width);
5866 CARD16(height);
5867 CARD16(minor_opcode);
5868 CARD16(count);
5869 CARD8(major_opcode);
5870 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 11, ENC_NA);
5871 *offsetp += 11;
5872 break;
5874 case NoExpose:
5875 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5876 *offsetp += 1;
5877 CARD16(event_sequencenumber);
5878 DRAWABLE(drawable);
5879 CARD16(minor_opcode);
5880 CARD8(major_opcode);
5881 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 21, ENC_NA);
5882 *offsetp += 21;
5883 break;
5885 case VisibilityNotify:
5886 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5887 *offsetp += 1;
5888 CARD16(event_sequencenumber);
5889 WINDOW(eventwindow);
5890 ENUM8(visibility_state);
5891 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 23, ENC_NA);
5892 *offsetp += 23;
5893 break;
5895 case CreateNotify:
5896 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5897 *offsetp += 1;
5898 CARD16(event_sequencenumber);
5899 WINDOW(parent);
5900 WINDOW(eventwindow);
5901 INT16(x);
5902 INT16(y);
5903 CARD16(width);
5904 CARD16(height);
5905 CARD16(border_width);
5906 BOOL(override_redirect);
5907 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 9, ENC_NA);
5908 *offsetp += 9;
5909 break;
5911 case DestroyNotify:
5912 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5913 *offsetp += 1;
5914 CARD16(event_sequencenumber);
5915 WINDOW(eventwindow);
5916 WINDOW(window);
5917 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5918 *offsetp += 20;
5919 break;
5921 case UnmapNotify:
5922 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5923 *offsetp += 1;
5924 CARD16(event_sequencenumber);
5925 WINDOW(eventwindow);
5926 WINDOW(window);
5927 BOOL(from_configure);
5928 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 19, ENC_NA);
5929 *offsetp += 19;
5930 break;
5932 case MapNotify:
5933 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5934 *offsetp += 1;
5935 CARD16(event_sequencenumber);
5936 WINDOW(eventwindow);
5937 WINDOW(window);
5938 BOOL(override_redirect);
5939 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 19, ENC_NA);
5940 *offsetp += 19;
5941 break;
5943 case MapRequest:
5944 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5945 *offsetp += 1;
5946 CARD16(event_sequencenumber);
5947 WINDOW(parent);
5948 WINDOW(eventwindow);
5949 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
5950 *offsetp += 20;
5951 break;
5953 case ReparentNotify:
5954 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5955 *offsetp += 1;
5956 CARD16(event_sequencenumber);
5957 WINDOW(eventwindow);
5958 WINDOW(window);
5959 WINDOW(parent);
5960 INT16(x);
5961 INT16(y);
5962 BOOL(override_redirect);
5963 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 11, ENC_NA);
5964 *offsetp += 11;
5965 break;
5967 case ConfigureNotify:
5968 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5969 *offsetp += 1;
5970 CARD16(event_sequencenumber);
5971 WINDOW(eventwindow);
5972 WINDOW(window);
5973 WINDOW(above_sibling);
5974 INT16(x);
5975 INT16(y);
5976 CARD16(width);
5977 CARD16(height);
5978 CARD16(border_width);
5979 BOOL(override_redirect);
5980 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 5, ENC_NA);
5981 *offsetp += 5;
5982 break;
5984 case ConfigureRequest:
5985 break;
5987 case GravityNotify:
5988 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
5989 *offsetp += 1;
5990 CARD16(event_sequencenumber);
5991 WINDOW(eventwindow);
5992 WINDOW(window);
5993 INT16(x);
5994 INT16(y);
5995 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 16, ENC_NA);
5996 *offsetp += 16;
5997 break;
5999 case ResizeRequest:
6000 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6001 *offsetp += 1;
6002 CARD16(event_sequencenumber);
6003 WINDOW(eventwindow);
6004 CARD16(width);
6005 CARD16(height);
6006 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 20, ENC_NA);
6007 *offsetp += 20;
6008 break;
6010 case CirculateNotify:
6011 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6012 *offsetp += 1;
6013 CARD16(event_sequencenumber);
6014 WINDOW(eventwindow);
6015 WINDOW(window);
6016 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 4, ENC_NA);
6017 *offsetp += 4;
6018 ENUM8(place);
6019 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 15, ENC_NA);
6020 *offsetp += 15;
6021 break;
6023 case CirculateRequest:
6024 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6025 *offsetp += 1;
6026 CARD16(event_sequencenumber);
6027 WINDOW(parent);
6028 WINDOW(eventwindow);
6029 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 4, ENC_NA);
6030 *offsetp += 4;
6031 ENUM8(place);
6032 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 15, ENC_NA);
6033 *offsetp += 15;
6034 break;
6036 case PropertyNotify:
6037 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6038 *offsetp += 1;
6039 CARD16(event_sequencenumber);
6040 WINDOW(eventwindow);
6041 ATOM(atom);
6042 TIMESTAMP(time);
6043 ENUM8(property_state);
6044 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 15, ENC_NA);
6045 *offsetp += 15;
6046 break;
6048 case SelectionClear:
6049 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6050 *offsetp += 1;
6051 CARD16(event_sequencenumber);
6052 TIMESTAMP(time);
6053 WINDOW(owner);
6054 ATOM(selection);
6055 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 16, ENC_NA);
6056 *offsetp += 16;
6057 break;
6059 case SelectionRequest:
6060 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6061 *offsetp += 1;
6062 CARD16(event_sequencenumber);
6063 TIMESTAMP(time);
6064 WINDOW(owner);
6065 WINDOW(requestor);
6066 ATOM(selection);
6067 ATOM(target);
6068 ATOM(property);
6069 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 4, ENC_NA);
6070 *offsetp += 4;
6071 break;
6073 case SelectionNotify:
6074 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6075 *offsetp += 1;
6076 CARD16(event_sequencenumber);
6077 TIMESTAMP(time);
6078 WINDOW(requestor);
6079 ATOM(selection);
6080 ATOM(target);
6081 ATOM(property);
6082 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 8, ENC_NA);
6083 *offsetp += 8;
6084 break;
6086 case ColormapNotify:
6087 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6088 *offsetp += 1;
6089 CARD16(event_sequencenumber);
6090 WINDOW(eventwindow);
6091 COLORMAP(cmap);
6092 BOOL(new);
6093 ENUM8(colormap_state);
6094 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 18, ENC_NA);
6095 *offsetp += 18;
6096 break;
6098 case ClientMessage:
6099 CARD8(format);
6100 CARD16(event_sequencenumber);
6101 WINDOW(eventwindow);
6102 ATOM(type);
6103 LISTofBYTE(data, 20);
6104 break;
6106 case MappingNotify:
6107 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 1, ENC_NA);
6108 *offsetp += 1;
6109 CARD16(event_sequencenumber);
6110 ENUM8(mapping_request);
6111 CARD8(first_keycode);
6112 CARD8(count);
6113 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, 25, ENC_NA);
6114 *offsetp += 25;
6115 break;
6117 case GenericEvent:
6118 tryGenericExtensionEvent(tvb, offsetp, t, state, byte_order);
6119 break;
6121 default:
6122 tryExtensionEvent(eventcode & 0x7F, tvb, offsetp, t, state, byte_order);
6123 break;
6126 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
6127 UNDECODED(left);
6130 static void
6131 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6132 const char *sep, x11_conv_data_t *state _U_,
6133 unsigned byte_order)
6135 int offset = 0, *offsetp = &offset, left;
6136 unsigned char errorcode;
6137 proto_item *ti;
6138 proto_tree *t;
6140 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, ENC_NA);
6141 t = proto_item_add_subtree(ti, ett_x11);
6143 CARD8(error);
6145 errorcode = tvb_get_uint8(tvb, offset);
6146 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
6147 sep, val_to_str(errorcode, state->errorcode_vals, "<Unknown errorcode %u>"));
6149 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
6150 errorcode,
6151 "errorcode: %d (%s)",
6152 errorcode,
6153 val_to_str(errorcode, state->errorcode_vals,
6154 "<Unknown errorcode %u>"));
6155 ++offset;
6157 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
6158 errorcode, val_to_str(errorcode, state->errorcode_vals,
6159 "<Unknown errorcode %u>"));
6161 if (tree == NULL)
6162 return;
6164 CARD16(error_sequencenumber);
6166 switch (errorcode) {
6167 case BadValue:
6168 CARD32(error_badvalue);
6169 break;
6170 case BadWindow:
6171 case BadPixmap:
6172 case BadCursor:
6173 case BadFont:
6174 case BadDrawable:
6175 case BadColormap:
6176 case BadGC:
6177 case BadIDChoice:
6178 CARD32(error_badresourceid);
6179 break;
6181 default:
6182 UNDECODED(4);
6185 CARD16(minor_opcode);
6186 CARD8(major_opcode);
6188 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
6189 UNDECODED(left);
6194 /************************************************************************
6195 *** ***
6196 *** I N I T I A L I Z A T I O N A N D M A I N ***
6197 *** ***
6198 ************************************************************************/
6200 static int
6201 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6203 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
6205 if (pinfo->match_uint == pinfo->srcport)
6206 dissect_x11_replies(tvb, pinfo, tree);
6207 else
6208 dissect_x11_requests(tvb, pinfo, tree);
6210 return tvb_captured_length(tvb);
6213 /* Register the protocol with Wireshark */
6214 void proto_register_x11(void)
6217 /* Setup list of header fields */
6218 static hf_register_info hf[] = {
6219 #include "x11-register-info.h"
6222 /* Setup protocol subtree array */
6223 static int *ett[] = {
6224 &ett_x11,
6225 &ett_x11_color_flags,
6226 &ett_x11_list_of_arc,
6227 &ett_x11_arc,
6228 &ett_x11_list_of_atom,
6229 &ett_x11_list_of_card32,
6230 &ett_x11_list_of_float,
6231 &ett_x11_list_of_double,
6232 &ett_x11_list_of_color_item,
6233 &ett_x11_color_item,
6234 &ett_x11_list_of_keycode,
6235 &ett_x11_list_of_keysyms,
6236 &ett_x11_keysym,
6237 &ett_x11_list_of_point,
6238 &ett_x11_point,
6239 &ett_x11_list_of_rectangle,
6240 &ett_x11_rectangle,
6241 &ett_x11_list_of_segment,
6242 &ett_x11_segment,
6243 &ett_x11_list_of_string8,
6244 &ett_x11_list_of_text_item,
6245 &ett_x11_text_item,
6246 &ett_x11_gc_value_mask,
6247 &ett_x11_event_mask,
6248 &ett_x11_do_not_propagate_mask,
6249 &ett_x11_set_of_key_mask,
6250 &ett_x11_pointer_event_mask,
6251 &ett_x11_window_value_mask,
6252 &ett_x11_configure_window_mask,
6253 &ett_x11_keyboard_value_mask,
6254 &ett_x11_same_screen_focus,
6255 &ett_x11_event,
6256 &ett_x11_list_of_pixmap_format,
6257 &ett_x11_pixmap_format,
6258 &ett_x11_list_of_screen,
6259 &ett_x11_screen,
6260 &ett_x11_list_of_depth_detail,
6261 &ett_x11_depth_detail,
6262 &ett_x11_list_of_visualtype,
6263 &ett_x11_visualtype,
6266 static ei_register_info ei[] = {
6267 { &ei_x11_invalid_format, { "x11.invalid_format", PI_PROTOCOL, PI_WARN, "Invalid Format", EXPFILL }},
6268 { &ei_x11_request_length, { "x11.request-length.invalid", PI_PROTOCOL, PI_WARN, "Invalid Length", EXPFILL }},
6269 { &ei_x11_keycode_value_out_of_range, { "x11.keycode_value_out_of_range", PI_PROTOCOL, PI_WARN, "keycode value is out of range", EXPFILL }},
6272 module_t *x11_module;
6273 expert_module_t* expert_x11;
6275 /* Register the protocol name and description */
6276 proto_x11 = proto_register_protocol("X11", "X11", "x11");
6277 x11_handle = register_dissector("x11", dissect_x11, proto_x11);
6279 /* Required function calls to register the header fields and subtrees used */
6280 proto_register_field_array(proto_x11, hf, array_length(hf));
6281 proto_register_subtree_array(ett, array_length(ett));
6282 expert_x11 = expert_register_protocol(proto_x11);
6283 expert_register_field_array(expert_x11, ei, array_length(ei));
6285 extension_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
6286 error_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
6287 event_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
6288 genevent_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
6289 reply_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
6290 register_x11_extensions();
6292 x11_module = prefs_register_protocol(proto_x11, NULL);
6293 prefs_register_bool_preference(x11_module, "desegment",
6294 "Reassemble X11 messages spanning multiple TCP segments",
6295 "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
6296 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
6297 &x11_desegment);
6300 void
6301 proto_reg_handoff_x11(void)
6303 dissector_add_uint_range_with_preference("tcp.port", DEFAULT_X11_PORT_RANGE, x11_handle);
6307 * Editor modelines
6309 * Local Variables:
6310 * c-basic-offset: 6
6311 * tab-width: 8
6312 * indent-tabs-mode: nil
6313 * End:
6315 * ex: set shiftwidth=6 tabstop=8 expandtab:
6316 * :indentSize=6:tabSize=8:noTabs=true: