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