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