Properly escape the '#' character in the HAVE_GNU_ADNS definition.
[metze/wireshark/wip.git] / packet-x11.c
1 /* packet-x11.c
2  * Routines for X11 dissection
3  * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4  *
5  * $Id: packet-x11.c,v 1.46 2002/08/28 21:00:40 jmayer Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 /* TODO (in no particular order):
29  *
30  * - keep track of Atom creation by server to be able to display
31  *   non-predefined atoms
32  * - Idem for keysym <-> keycode ???
33  * - Idem for fonts
34  * - Subtree the request ids (that is x11.create-window.window and
35  *   x11.change-window.window should be  distinct), and add hidden fields
36  *   (so we still have x11.window).
37  * - add hidden fields so we can have x11.circulate-window in addition to
38  *   x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
39  *   now)
40  * - add hidden fields so we have x11.listOfStuff.length
41  * - use a faster scheme that linear list searching for the opcode.
42  * - correct display of Unicode chars.
43  * - Not everything is homogeneous, in particular the handling of items in
44  *   list is a total mess.
45  */
46
47 /* By the way, I wrote a program to generate every request and test
48  * that stuff. If you're interested, you can get it at
49  * http://tronche.com/gui/x/
50  */
51
52 #ifdef HAVE_CONFIG_H
53 # include "config.h"
54 #endif
55
56 #include <assert.h>
57 #include <ctype.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60
61 #include <string.h>
62 #include <glib.h>
63 #include <epan/packet.h>
64 #include <epan/conversation.h>
65
66 #include "prefs.h"
67 #include "packet-frame.h"
68
69 #define cVALS(x) (const value_string*)(x)
70
71 /* Initialize the protocol and registered fields */
72 static int proto_x11 = -1;
73
74 #include "x11-declarations.h"
75
76 /* Initialize the subtree pointers */
77 static gint ett_x11 = -1;
78 static gint ett_x11_color_flags = -1;
79 static gint ett_x11_list_of_arc = -1;
80 static gint ett_x11_arc = -1;
81 static gint ett_x11_list_of_atom = -1;
82 static gint ett_x11_list_of_card32 = -1;
83 static gint ett_x11_list_of_color_item = -1;
84 static gint ett_x11_color_item = -1;
85 static gint ett_x11_list_of_keycode = -1;
86 static gint ett_x11_list_of_keysyms = -1;
87 static gint ett_x11_keysym = -1;
88 static gint ett_x11_list_of_point = -1;
89 static gint ett_x11_point = -1;
90 static gint ett_x11_list_of_rectangle = -1;
91 static gint ett_x11_rectangle = -1;
92 static gint ett_x11_list_of_segment = -1;
93 static gint ett_x11_segment = -1;
94 static gint ett_x11_list_of_string8 = -1;
95 static gint ett_x11_list_of_text_item = -1;
96 static gint ett_x11_text_item = -1;
97 static gint ett_x11_gc_value_mask = -1;
98 static gint ett_x11_event_mask = -1;
99 static gint ett_x11_do_not_propagate_mask = -1;
100 static gint ett_x11_set_of_key_mask = -1;
101 static gint ett_x11_pointer_event_mask = -1;
102 static gint ett_x11_window_value_mask = -1;
103 static gint ett_x11_configure_window_mask = -1;
104 static gint ett_x11_keyboard_value_mask = -1;
105
106 /* desegmentation of X11 messages */
107 static gboolean x11_desegment = TRUE;
108
109 static dissector_handle_t data_handle;
110
111 #define TCP_PORT_X11                    6000
112 #define TCP_PORT_X11_2                  6001
113 #define TCP_PORT_X11_3                  6002
114
115 /*
116  * Round a length to a multiple of 4 bytes.
117  */
118 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
119
120 /************************************************************************
121  ***                                                                  ***
122  ***         E N U M   T A B L E S   D E F I N I T I O N S            ***
123  ***                                                                  ***
124  ************************************************************************/
125
126 static const value_string byte_order_vals[] = {
127      { 'B', "Big-endian" },
128      { 'l', "Little-endian" },
129      { 0,   NULL }
130 };
131
132 static const value_string access_mode_vals[] = {
133       { 0, "Disable" },
134       { 1, "Enable" },
135       { 0, NULL }
136 };
137
138 static const value_string all_temporary_vals[] = {
139       { 0, "AllTemporary" },
140       { 0, NULL }
141 };
142
143 static const value_string alloc_vals[] = {
144       { 0, "None" },
145       { 1, "All" },
146       { 0, NULL }
147 };
148
149 static const value_string allow_events_mode_vals[] = {
150       { 0, "AsyncPointer" },
151       { 1, "SyncPointer" },
152       { 2, "ReplayPointer" },
153       { 3, "AsyncKeyboard" },
154       { 4, "SyncKeyboard" },
155       { 5, "ReplayKeyboard" },
156       { 6, "AsyncBoth" },
157       { 7, "SyncBoth" },
158       { 0, NULL }
159 };
160
161 static const value_string arc_mode_vals[] = {
162       { 0, "Chord" },
163       { 1, "PieSlice" },
164       { 0, NULL }
165 };
166
167 static const char *atom_predefined_interpretation[] = {
168       "<error>",
169       "PRIMARY",
170       "SECONDARY",
171       "ARC",
172       "ATOM",
173       "BITMAP",
174       "CARDINAL",
175       "COLORMAP",
176       "CURSOR",
177       "CUT_BUFFER0",
178       "CUT_BUFFER1",
179       "CUT_BUFFER2",
180       "CUT_BUFFER3",
181       "CUT_BUFFER4",
182       "CUT_BUFFER5",
183       "CUT_BUFFER6",
184       "CUT_BUFFER7",
185       "DRAWABLE",
186       "FONT",
187       "INTEGER",
188       "PIXMAP",
189       "POINT",
190       "RECTANGLE",
191       "RESOURCE_MANAGER",
192       "RGB_COLOR_MAP",
193       "RGB_BEST_MAP",
194       "RGB_BLUE_MAP",
195       "RGB_DEFAULT_MAP",
196       "RGB_GRAY_MAP",
197       "RGB_GREEN_MAP",
198       "RGB_RED_MAP",
199       "STRING",
200       "VISUALID",
201       "WINDOW",
202       "WM_COMMAND",
203       "WM_HINTS",
204       "WM_CLIENT_MACHINE",
205       "WM_ICON_NAME",
206       "WM_ICON_SIZE",
207       "WM_NAME",
208       "WM_NORMAL_HINTS",
209       "WM_SIZE_HINTS",
210       "WM_ZOOM_HINTS",
211       "MIN_SPACE",
212       "NORM_SPACE",
213       "MAX_SPACE",
214       "END_SPACE",
215       "SUPERSCRIPT_X",
216       "SUPERSCRIPT_Y",
217       "SUBSCRIPT_X",
218       "SUBSCRIPT_Y",
219       "UNDERLINE_POSITION",
220       "UNDERLINE_THICKNESS",
221       "STRIKEOUT_ASCENT",
222       "STRIKEOUT_DESCENT",
223       "ITALIC_ANGLE",
224       "X_HEIGHT",
225       "QUAD_WIDTH",
226       "WEIGHT",
227       "POINT_SIZE",
228       "RESOLUTION",
229       "COPYRIGHT",
230       "NOTICE",
231       "FONT_NAME",
232       "FAMILY_NAME",
233       "FULL_NAME",
234       "CAP_HEIGHT",
235       "WM_CLASS",
236       "WM_TRANSIENT_FOR",
237 };
238
239 static const value_string auto_repeat_mode_vals[] = {
240       { 0, "Off" },
241       { 1, "On" },
242       { 2, "Default" },
243       { 0, NULL }
244 };
245
246 static const value_string background_pixmap_vals[] = {
247       { 0, "None" },
248       { 1, "ParentRelative" },
249       { 0, NULL }
250 };
251
252 static const value_string backing_store_vals[] = {
253       { 0, "NotUseful" },
254       { 1, "WhenMapped" },
255       { 2, "Always" },
256       { 0, NULL }
257 };
258
259 static const value_string border_pixmap_vals[] = {
260       { 0, "CopyFromParent" },
261       { 0, NULL }
262 };
263
264 static const value_string button_vals[] = {
265       { 0x8000, "AnyButton" },
266       { 0, NULL }
267 };
268
269 static const value_string cap_style_vals[] = {
270       { 0, "NotLast" },
271       { 1, "Butt" },
272       { 2, "Round" },
273       { 3, "Projecting" },
274       { 0, NULL }
275 };
276
277 static const value_string class_vals[] = {
278       { 0, "Cursor" },
279       { 1, "Tile" },
280       { 2, "Stipple" },
281       { 0, NULL }
282 };
283
284 static const value_string close_down_mode_vals[] = {
285       { 0, "Destroy" },
286       { 1, "RetainPermanent" },
287       { 2, "RetainTemporary" },
288       { 0, NULL }
289 };
290
291 static const value_string coordinate_mode_vals[] = {
292       { 0, "Origin" },
293       { 1, "Previous" },
294       { 0, NULL }
295 };
296
297 static const value_string direction_vals[] = {
298       { 0, "RaiseLowest" },
299       { 1, "LowerHighest" },
300       { 0, NULL }
301 };
302
303 #define FAMILY_INTERNET 0
304 #define FAMILY_DECNET   1
305 #define FAMILY_CHAOS    2
306
307 static const value_string family_vals[] = {
308       { FAMILY_INTERNET, "Internet" },
309       { FAMILY_DECNET,   "DECnet" },
310       { FAMILY_CHAOS,    "Chaos" },
311       { 0, NULL }
312 };
313
314 static const value_string fill_rule_vals[] = {
315       { 0, "EvenOdd" },
316       { 1, "Winding" },
317       { 0, NULL }
318 };
319
320 static const value_string fill_style_vals[] = {
321       { 0, "Solid" },
322       { 1, "Tiled" },
323       { 2, "Stippled" },
324       { 3, "OpaqueStippled" },
325       { 0, NULL }
326 };
327
328 static const value_string focus_vals[] = {
329       { 0, "None" },
330       { 1, "PointerRoot" },
331       { 0, NULL }
332 };
333
334 static const value_string function_vals[] = {
335       {  0, "Clear" },
336       {  1, "And" },
337       {  2, "AndReverse" },
338       {  3, "Copy" },
339       {  4, "AndInverted" },
340       {  5, "NoOp" },
341       {  6, "Xor" },
342       {  7, "Or" },
343       {  8, "Nor" },
344       {  9, "Equiv" },
345       { 10, "Invert" },
346       { 11, "OrReverse" },
347       { 12, "CopyInverted" },
348       { 13, "OrInverted" },
349       { 14, "Nand" },
350       { 15, "Set" },
351       {  0, NULL }
352 };
353
354 static const value_string gravity_vals[] = {
355       {  1, "NorthWest" },
356       {  2, "North" },
357       {  3, "NorthEast" },
358       {  4, "West" },
359       {  5, "Center" },
360       {  6, "East" },
361       {  7, "SouthWest" },
362       {  8, "South" },
363       {  9, "SouthEast" },
364       { 10, "Static" },
365       {  0, NULL }
366 };
367
368 static const value_string image_format_vals[] = {
369       { 0, "Bitmap" },
370       { 1, "XYPixmap" },
371       { 2, "ZPixmap" },
372       { 0, NULL }
373 };
374
375 static const value_string image_pixmap_format_vals[] = {
376       { 1, "XYPixmap" },
377       { 2, "ZPixmap" },
378       { 0, NULL }
379 };
380
381 static const value_string join_style_vals[] = {
382       { 0, "Miter" },
383       { 1, "Round" },
384       { 2, "Bevel" },
385       { 0, NULL }
386 };
387
388 static const value_string key_vals[] = {
389       { 0, "AnyKey" },
390       { 0, NULL }
391 };
392
393 #include "packet-x11-keysym.h"
394
395 static const value_string line_style_vals[] = {
396       { 0, "Solid" },
397       { 1, "OnOffDash" },
398       { 2, "DoubleDash" },
399       { 0, NULL }
400 };
401
402 static const value_string mode_vals[] = {
403       { 0, "Replace" },
404       { 1, "Prepend" },
405       { 2, "Append" },
406       { 0, NULL }
407 };
408
409 static const value_string on_off_vals[] = {
410       { 0, "Off" },
411       { 1, "On" },
412       { 0, NULL }
413 };
414
415 static const value_string opcode_vals[] = {
416       {   1, "CreateWindow" },
417       {   2, "ChangeWindowAttributes" },
418       {   3, "GetWindowAttributes" },
419       {   4, "DestroyWindow" },
420       {   5, "DestroySubwindows" },
421       {   6, "ChangeSaveSet" },
422       {   7, "ReparentWindow" },
423       {   8, "MapWindow" },
424       {   9, "MapSubwindows" },
425       {  10, "UnmapWindow" },
426       {  11, "UnmapSubwindows" },
427       {  12, "ConfigureWindow" },
428       {  13, "CirculateWindow" },
429       {  14, "GetGeometry" },
430       {  15, "QueryTree" },
431       {  16, "InternAtom" },
432       {  17, "GetAtomName" },
433       {  18, "ChangeProperty" },
434       {  19, "DeleteProperty" },
435       {  20, "GetProperty" },
436       {  21, "ListProperties" },
437       {  22, "SetSelectionOwner" },
438       {  23, "GetSelectionOwner" },
439       {  24, "ConvertSelection" },
440
441       {  26, "GrabPointer" },
442       {  27, "UngrabPointer" },
443       {  28, "GrabButton" },
444       {  29, "UngrabButton" },
445       {  30, "ChangeActivePointerGrab" },
446       {  31, "GrabKeyboard" },
447       {  32, "UngrabKeyboard" },
448       {  33, "GrabKey" },
449       {  34, "UngrabKey" },
450       {  35, "AllowEvents" },
451       {  36, "GrabServer" },
452       {  37, "UngrabServer" },
453       {  38, "QueryPointer" },
454       {  39, "GetMotionEvents" },
455       {  40, "TranslateCoordinates" },
456       {  41, "WarpPointer" },
457       {  42, "SetInputFocus" },
458       {  43, "GetInputFocus" },
459       {  44, "QueryKeymap" },
460       {  45, "OpenFont" },
461       {  46, "CloseFont" },
462       {  47, "QueryFont" },
463       {  48, "QueryTextExtents" },
464       {  49, "ListFonts" },
465       {  50, "ListFontsWithInfo" },
466       {  51, "SetFontPath" },
467       {  52, "GetFontPath" },
468       {  53, "CreatePixmap" },
469       {  54, "FreePixmap" },
470       {  55, "CreateGC" },
471       {  56, "ChangeGC" },
472       {  57, "CopyGC" },
473       {  58, "SetDashes" },
474       {  59, "SetClipRectangles" },
475       {  60, "FreeGC" },
476       {  61, "ClearArea" },
477       {  62, "CopyArea" },
478       {  63, "CopyPlane" },
479       {  64, "PolyPoint" },
480       {  65, "PolyLine" },
481       {  66, "PolySegment" },
482       {  67, "PolyRectangle" },
483       {  68, "PolyArc" },
484       {  69, "FillPoly" },
485       {  70, "PolyFillRectangle" },
486       {  71, "PolyFillArc" },
487       {  72, "PutImage" },
488       {  73, "GetImage" },
489       {  74, "PolyText8" },
490       {  75, "PolyText16" },
491       {  76, "ImageText8" },
492       {  77, "ImageText16" },
493       {  78, "CreateColormap" },
494       {  79, "FreeColormap" },
495       {  80, "CopyColormapAndFree" },
496       {  81, "InstallColormap" },
497       {  82, "UninstallColormap" },
498       {  83, "ListInstalledColormaps" },
499       {  84, "AllocColor" },
500       {  85, "AllocNamedColor" },
501       {  86, "AllocColorCells" },
502       {  87, "AllocColorPlanes" },
503       {  88, "FreeColors" },
504       {  89, "StoreColors" },
505       {  90, "StoreNamedColor" },
506       {  91, "QueryColors" },
507       {  92, "LookupColor" },
508       {  93, "CreateCursor" },
509       {  94, "CreateGlyphCursor" },
510       {  95, "FreeCursor" },
511       {  96, "RecolorCursor" },
512       {  97, "QueryBestSize" },
513       {  98, "QueryExtension" },
514       {  99, "ListExtensions" },
515       { 100, "ChangeKeyboardMapping" },
516       { 101, "GetKeyboardMapping" },
517       { 102, "ChangeKeyboardControl" },
518       { 103, "GetKeyboardControl" },
519       { 104, "Bell" },
520       { 105, "ChangePointerControl" },
521       { 106, "GetPointerControl" },
522       { 107, "SetScreenSaver" },
523       { 108, "GetScreenSaver" },
524       { 109, "ChangeHosts" },
525       { 110, "ListHosts" },
526       { 111, "SetAccessControl" },
527       { 112, "SetCloseDownMode" },
528       { 113, "KillClient" },
529       { 114, "RotateProperties" },
530       { 115, "ForceScreenSaver" },
531       { 116, "SetPointerMapping" },
532       { 117, "GetPointerMapping" },
533       { 118, "SetModifierMapping" },
534       { 119, "GetModifierMapping" },
535       { 127, "NoOperation" },
536       { 0, NULL }
537 };
538
539 static const value_string ordering_vals[] = {
540       { 0, "UnSorted" },
541       { 1, "YSorted" },
542       { 2, "YXSorted" },
543       { 3, "YXBanded" },
544       { 0, NULL }
545 };
546
547 static const value_string plane_mask_vals[] = {
548       { 0xFFFFFFFF, "AllPlanes" },
549       { 0, NULL }
550 };
551
552 static const value_string pointer_keyboard_mode_vals[] = {
553       { 0, "Synchronous" },
554       { 1, "Asynchronous" },
555       { 0, NULL }
556 };
557
558 static const value_string revert_to_vals[] = {
559       { 0, "None" },
560       { 1, "PointerRoot" },
561       { 2, "Parent" },
562       { 0, NULL }
563 };
564
565 static const value_string insert_delete_vals[] = {
566       { 0, "Insert" },
567       { 1, "Delete" },
568       { 0, NULL }
569 };
570
571 static const value_string screen_saver_mode_vals[] = {
572       { 0, "Reset" },
573       { 1, "Activate" },
574       { 0, NULL }
575 };
576
577 static const value_string shape_vals[] = {
578       { 0, "Complex" },
579       { 1, "Nonconvex" },
580       { 2, "Convex" },
581       { 0, NULL }
582 };
583
584 static const value_string stack_mode_vals[] = {
585       { 0, "Above" },
586       { 1, "Below" },
587       { 2, "TopIf" },
588       { 3, "BottomIf" },
589       { 4, "Opposite" },
590       { 0, NULL }
591 };
592
593 static const value_string subwindow_mode_vals[] = {
594       { 0, "ClipByChildren" },
595       { 1, "IncludeInferiors" },
596       { 0, NULL }
597 };
598
599 static const value_string window_class_vals[] = {
600       { 0, "CopyFromParent" },
601       { 1, "InputOutput" },
602       { 2, "InputOnly" },
603       { 0, NULL }
604 };
605
606 static const value_string yes_no_default_vals[] = {
607       { 0, "No" },
608       { 1, "Yes" },
609       { 2, "Default" },
610       { 0, NULL }
611 };
612
613 static const value_string zero_is_any_property_type_vals[] = {
614       { 0, "AnyPropertyType" },
615       { 0, NULL }
616 };
617
618 static const value_string zero_is_none_vals[] = {
619       { 0, "None" },
620       { 0, NULL }
621 };
622
623 /************************************************************************
624  ***                                                                  ***
625  ***           F I E L D   D E C O D I N G   M A C R O S              ***
626  ***                                                                  ***
627  ************************************************************************/
628
629 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
630 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
631 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
632
633 #define FIELD8(name)  (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
634 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
635 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
636
637 #define BITFIELD(TYPE, position, name) {\
638   int unused;\
639   int save = *offsetp;\
640   proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
641                       bitmask_size, little_endian); \
642   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
643        TYPE(name);\
644        unused = save + 4 - *offsetp;\
645        if (unused)\
646            proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
647        *offsetp = save + 4;\
648  }\
649 }
650
651 #define FLAG(position, name) {\
652        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
653
654 #define FLAG_IF_NONZERO(position, name) {\
655   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
656        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
657
658 #define ATOM(name)     { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
659 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
660 #define BITMASK(name, size) {\
661       proto_item *ti; \
662       guint32 bitmask_value; \
663       int bitmask_offset; \
664       int bitmask_size; \
665       proto_tree *bitmask_tree; \
666       bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
667                        ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
668                                       (guint32)VALUE32(tvb, *offsetp))); \
669       bitmask_offset = *offsetp; \
670       bitmask_size = size; \
671       ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
672       bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
673       *offsetp += size;
674 #define ENDBITMASK      }
675 #define BITMASK8(name)  BITMASK(name, 1);
676 #define BITMASK16(name) BITMASK(name, 2);
677 #define BITMASK32(name) BITMASK(name, 4);
678 #define BOOL(name)     (add_boolean(tvb, offsetp, t, hf_x11_##name))
679 #define BUTTON(name)   { FIELD8(name); }
680 #define CARD8(name)    { FIELD8(name); }
681 #define CARD16(name)   (FIELD16(name))
682 #define CARD32(name)   (FIELD32(name))
683 #define COLOR_FLAGS(name) { colorFlags(tvb, offsetp, t); }
684 #define COLORMAP(name) { FIELD32(name); }
685 #define CURSOR(name)   { FIELD32(name); }
686 #define DRAWABLE(name) { FIELD32(name); }
687 #define ENUM8(name)    (FIELD8(name))
688 #define ENUM16(name)   { FIELD16(name); }
689 #define FONT(name)     { FIELD32(name); }
690 #define FONTABLE(name) { FIELD32(name); }
691 #define GCONTEXT(name) { FIELD32(name); }
692 #define INT8(name)     { FIELD8(name); }
693 #define INT16(name)    { FIELD16(name); }
694 #define KEYCODE(name)  { FIELD8(name); }
695 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
696 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
697 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
698 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
699 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
700 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
701 #define LISTofKEYCODE(name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
702 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
703       listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode), little_endian); }
704 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
705 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
706 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
707 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
708 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
709 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
710 #define OPCODE()       { opcode = FIELD8(opcode); }
711 #define PIXMAP(name)   { FIELD32(name); }
712 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
713 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
714 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
715 #define SETofKEYMASK(name) { setOfKeyMask(tvb, offsetp, t, little_endian); }
716 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
717 #define STRING8(name, length)  { string8(tvb, offsetp, t, hf_x11_##name, length); }
718 #define STRING16(name, length)  { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
719 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
720 #define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp,  x, little_endian); *offsetp += x; }
721 #define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp,  x, little_endian); *offsetp += x; }
722 #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; }
723 #define WINDOW(name)   { FIELD32(name); }
724 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
725
726 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
727     proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
728                                v ? "" : " (CopyFromParent)"); *offsetp += 4; }
729
730 /************************************************************************
731  ***                                                                  ***
732  ***                  D E C O D I N G   F I E L D S                   ***
733  ***                                                                  ***
734  ************************************************************************/
735
736 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
737                  gboolean little_endian)
738 {
739       const char *interpretation = NULL;
740
741       guint32 v = VALUE32(tvb, *offsetp);
742       if (v >= 1 && v < array_length(atom_predefined_interpretation))
743             interpretation = atom_predefined_interpretation[v];
744       else if (v)
745             interpretation = "Not a predefined atom";
746       else {
747             header_field_info *hfi = proto_registrar_get_nth(hf);
748             if (hfi -> strings)
749                   interpretation = match_strval(v, cVALS(hfi -> strings));
750       }
751       if (!interpretation) interpretation = "error in Xlib client program ?";
752       proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
753                                  proto_registrar_get_nth(hf) -> name, v, interpretation);
754       *offsetp += 4;
755 }
756
757 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
758 {
759       guint32 v = VALUE8(tvb, *offsetp);
760       proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
761       *offsetp += 1;
762       return v;
763 }
764
765 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
766 {
767       unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
768       proto_item *ti;
769       proto_tree *tt;
770
771       if (do_red_green_blue) {
772             int sep = FALSE;
773             char buffer[512];
774             char *bp = buffer + sprintf(buffer, "flags: ");
775
776             if (do_red_green_blue & 0x1) {
777                   bp += sprintf(bp, "DoRed");
778                   sep = TRUE;
779             }
780
781             if (do_red_green_blue & 0x2) {
782                   if (sep) bp += sprintf(bp, " | ");
783                   bp += sprintf(bp, "DoGreen");
784                   sep = TRUE;
785             }
786
787             if (do_red_green_blue & 0x4) {
788                   if (sep) bp += sprintf(bp, " | ");
789                   bp += sprintf(bp, "DoBlue");
790                   sep = TRUE;
791             }
792
793             if (do_red_green_blue & 0xf8) {
794                   if (sep) bp += sprintf(bp, " + ");
795                   sprintf(bp, "trash");
796             }
797
798             ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
799                                             "%s", buffer);
800             tt = proto_item_add_subtree(ti, ett_x11_color_flags);
801             if (do_red_green_blue & 0x1)
802                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
803                                          do_red_green_blue & 0x1);
804             if (do_red_green_blue & 0x2)
805                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
806                                          do_red_green_blue & 0x2);
807             if (do_red_green_blue & 0x4)
808                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
809                                          do_red_green_blue & 0x4);
810             if (do_red_green_blue & 0xf8)
811                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
812                                          do_red_green_blue & 0xf8);
813       } else
814             proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
815                                        "flags: none");
816       *offsetp += 1;
817 }
818
819 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
820     int hf, const char *nullInterpretation)
821 {
822       guint8 v = VALUE8(tvb, *offsetp);
823
824       if (!v)
825             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
826                                        proto_registrar_get_nth(hf) -> name,
827                                        nullInterpretation);
828       else
829             proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
830       *offsetp += 1;
831 }
832
833 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
834                       int length, gboolean little_endian)
835 {
836       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
837       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
838       while(length--) {
839             gint16 x = VALUE16(tvb, *offsetp);
840             gint16 y = VALUE16(tvb, *offsetp + 2);
841             guint16 width = VALUE16(tvb, *offsetp + 4);
842             guint16 height = VALUE16(tvb, *offsetp + 6);
843             gint16 angle1 = VALUE16(tvb, *offsetp + 8);
844             gint16 angle2 = VALUE16(tvb, *offsetp + 10);
845
846             proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
847                                                              "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
848                                                              width, height, x, y, angle1, angle2,
849                                                              angle1 / 64.0, angle2 / 64.0);
850             proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
851             proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
852             *offsetp += 2;
853             proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
854             *offsetp += 2;
855             proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
856             *offsetp += 2;
857             proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
858             *offsetp += 2;
859             proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
860             *offsetp += 2;
861             proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
862             *offsetp += 2;
863       }
864 }
865
866 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
867                        int length, gboolean little_endian)
868 {
869       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
870       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
871       while(length--)
872             atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
873 }
874
875 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
876                        int length, gboolean little_endian)
877 {
878       if (length <= 0) length = 1;
879       proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
880       *offsetp += length;
881 }
882
883 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
884                          int hf_item, int length, gboolean little_endian)
885 {
886       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
887       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
888       while(length--) {
889             proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
890             *offsetp += 4;
891       }
892 }
893
894 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
895                             int length, gboolean little_endian)
896 {
897       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
898       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
899       while(length--) {
900             proto_item *tti;
901             proto_tree *ttt;
902             unsigned do_red_green_blue;
903             guint16 red, green, blue;
904             char buffer[1024];
905             char *bp;
906             const char *sep;
907
908             red = VALUE16(tvb, *offsetp + 4);
909             green = VALUE16(tvb, *offsetp + 6);
910             blue = VALUE16(tvb, *offsetp + 8);
911             do_red_green_blue = VALUE8(tvb, *offsetp + 10);
912
913             bp = buffer + sprintf(buffer, "colorItem: ");
914             sep = "";
915             if (do_red_green_blue & 0x1) {
916                 bp += sprintf(bp, "red = %d", red);
917                 sep = ", ";
918             }
919             if (do_red_green_blue & 0x2) {
920                 bp += sprintf(bp, "%sgreen = %d", sep, green);
921                 sep = ", ";
922             }
923             if (do_red_green_blue & 0x4)
924                 bp += sprintf(bp, "%sblue = %d", sep, blue);
925
926             tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
927             ttt = proto_item_add_subtree(tti, ett_x11_color_item);
928             proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
929             *offsetp += 4;
930             proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
931             *offsetp += 2;
932             proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
933             *offsetp += 2;
934             proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
935             *offsetp += 2;
936             colorFlags(tvb, offsetp, ttt);
937             proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
938             *offsetp += 1;
939       }
940 }
941
942 static GTree *keysymTable = NULL;
943
944 static gint compareGuint32(gconstpointer a, gconstpointer b)
945 {
946       return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
947 }
948
949 static const char *keysymString(guint32 v)
950 {
951       gpointer res;
952       if (!keysymTable) {
953
954             /* This table is so big that we built it only if necessary */
955
956             const value_string *p = keysym_vals_source;
957             keysymTable = g_tree_new(compareGuint32);
958             for(; p -> strptr; p++)
959                   g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
960       }
961       res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
962       return res ? res : "Unknown";
963 }
964
965 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
966
967 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
968                           int length, gboolean little_endian)
969 {
970       char buffer[1024];
971       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
972       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
973
974       while(length--) {
975             char *bp = buffer;
976             const char **m;
977             int i;
978
979             for(i = 8, m = modifiers; i; i--, m++) {
980                 guchar c = tvb_get_guint8(tvb, *offsetp);
981                 *offsetp += 1;
982                 if (c)
983                     bp += sprintf(bp, "  %s=%d", *m, c);
984             }
985
986             proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, *offsetp - 8, 8, tvb_get_ptr(tvb, *offsetp - 8, 8),      "item: %s", buffer);
987       }
988 }
989
990 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
991                           int hf_item, int keycode_count,
992                           int keysyms_per_keycode, gboolean little_endian)
993 {
994       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
995       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
996       proto_item *tti;
997       proto_tree *ttt;
998       int i;
999
1000       while(keycode_count--) {
1001             tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp, keysyms_per_keycode * 4,
1002                                                  "keysyms:");
1003             ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1004             for(i = keysyms_per_keycode; i; i--) {
1005                   guint32 v = VALUE32(tvb, *offsetp);
1006                   proto_item_append_text(tti, " %s", keysymString(v));
1007                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, *offsetp, 4, v,
1008                                              "keysym: 0x%08x (%s)", v, keysymString(v));
1009                   *offsetp += 4;
1010             }
1011       }
1012 }
1013
1014 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1015                         int length, gboolean little_endian)
1016 {
1017       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1018       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1019       while(length--) {
1020             gint16 x, y;
1021             proto_item *tti;
1022             proto_tree *ttt;
1023
1024             x = VALUE16(tvb, *offsetp);
1025             y = VALUE16(tvb, *offsetp + 2);
1026
1027             tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1028             ttt = proto_item_add_subtree(tti, ett_x11_point);
1029             proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1030             *offsetp += 2;
1031             proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1032             *offsetp += 2;
1033       }
1034 }
1035
1036 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1037                             int length, gboolean little_endian)
1038 {
1039       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1040       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1041       while(length--) {
1042             gint16 x, y;
1043             unsigned width, height;
1044             proto_item *tti;
1045             proto_tree *ttt;
1046
1047             x = VALUE16(tvb, *offsetp);
1048             y = VALUE16(tvb, *offsetp + 2);
1049             width = VALUE16(tvb, *offsetp + 4);
1050             height = VALUE16(tvb, *offsetp + 6);
1051
1052             tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1053                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1054             ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1055             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1056             *offsetp += 2;
1057             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1058             *offsetp += 2;
1059             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1060             *offsetp += 2;
1061             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1062             *offsetp += 2;
1063       }
1064 }
1065
1066 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1067                           int length, gboolean little_endian)
1068 {
1069       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1070       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1071       while(length--) {
1072             gint16 x1, y1, x2, y2;
1073             proto_item *tti;
1074             proto_tree *ttt;
1075
1076             x1 = VALUE16(tvb, *offsetp);
1077             y1 = VALUE16(tvb, *offsetp + 2);
1078             x2 = VALUE16(tvb, *offsetp + 4);
1079             y2 = VALUE16(tvb, *offsetp + 6);
1080
1081             tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1082                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1083             ttt = proto_item_add_subtree(tti, ett_x11_segment);
1084             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1085             *offsetp += 2;
1086             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1087             *offsetp += 2;
1088             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1089             *offsetp += 2;
1090             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1091             *offsetp += 2;
1092       }
1093 }
1094
1095 /* XXX - the protocol tree code should handle non-printable characters.
1096    Note that "non-printable characters" may depend on your locale.... */
1097 static void stringCopy(char *dest, const char *source, int length)
1098 {
1099       guchar c;
1100       while(length--) {
1101             c = *source++;
1102             if (!isgraph(c) && c != ' ') c = '.';
1103             *dest++ = c;
1104       }
1105       *dest++ = '\0';
1106 }
1107
1108 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1109                           int hf_item, int length, gboolean little_endian)
1110 {
1111       char *s = NULL;
1112       guint allocated = 0;
1113       proto_item *ti;
1114       proto_tree *tt;
1115       int i;
1116
1117       /* Compute total length */
1118
1119       int scanning_offset = *offsetp; /* Scanning pointer */
1120       int l;
1121       for(i = length; i; i--) {
1122             l = tvb_get_guint8(tvb, scanning_offset);
1123             scanning_offset += 1 + l;
1124       }
1125
1126       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1127       tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1128
1129       /*
1130        * In case we throw an exception, clean up whatever stuff we've
1131        * allocated (if any).
1132        */
1133       CLEANUP_PUSH(g_free, s);
1134
1135       while(length--) {
1136             unsigned l = VALUE8(tvb, *offsetp);
1137             if (allocated < (l + 1)) {
1138                   /* g_realloc doesn't work ??? */
1139                   g_free(s);
1140                   s = g_malloc(l + 1);
1141                   allocated = l + 1;
1142             }
1143             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1144             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1145             *offsetp += l + 1;
1146       }
1147
1148       /*
1149        * Call the cleanup handler to free the string and pop the handler.
1150        */
1151       CLEANUP_CALL_AND_POP;
1152 }
1153
1154 #define STRING16_MAX_DISPLAYED_LENGTH 150
1155
1156 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1157 {
1158       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1159       for(; length > 0; offset += 2, length--) {
1160             if (tvb_get_guint8(tvb, offset))
1161                 return FALSE;
1162       }
1163       return TRUE;
1164 }
1165
1166 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1167
1168 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1169                                               int hf, int hf_bytes,
1170                                               int offset, unsigned length,
1171                                               char **s, int *sLength,
1172                                               gboolean little_endian)
1173 {
1174       int truncated = FALSE;
1175       unsigned l = length / 2;
1176
1177       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1178             char *dp;
1179             int soffset = offset;
1180
1181             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1182                   truncated = TRUE;
1183                   l = STRING16_MAX_DISPLAYED_LENGTH;
1184             }
1185             if (*sLength < (int) l + 3) {
1186                   g_free(*s);
1187                   *s = g_malloc(l + 3);
1188                   *sLength = l + 3;
1189             }
1190             dp = *s;
1191             *dp++ = '"';
1192             if (truncated) l -= 3;
1193
1194             while(l--) {
1195                   soffset++;
1196                   *dp++ = tvb_get_guint8(tvb, soffset);
1197                   soffset++;
1198             }
1199             *dp++ = '"';
1200
1201             /* If truncated, add an ellipsis */
1202             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1203
1204             *dp++ = '\0';
1205             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1206                                         proto_registrar_get_nth(hf) -> name, *s);
1207       } else
1208             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1209
1210 }
1211
1212 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1213     int sizeIs16, int next_offset, gboolean little_endian)
1214 {
1215       int allocated = 0;
1216       char *s = NULL;
1217       proto_item *ti;
1218       proto_tree *tt;
1219       guint32 fid;
1220
1221       /* Compute total length */
1222
1223       int scanning_offset = *offsetp; /* Scanning pointer */
1224       int l;                            /* Length of an individual item */
1225       int n = 0;                        /* Number of items */
1226
1227       while(scanning_offset < next_offset) {
1228             l = tvb_get_guint8(tvb, scanning_offset);
1229             scanning_offset++;
1230             if (!l) break;
1231             n++;
1232             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1233       }
1234
1235       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1236       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
1237
1238       /*
1239        * In case we throw an exception, clean up whatever stuff we've
1240        * allocated (if any).
1241        */
1242       CLEANUP_PUSH(g_free, s);
1243
1244       while(n--) {
1245             unsigned l = VALUE8(tvb, *offsetp);
1246             if (l == 255) { /* Item is a font */
1247                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
1248                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
1249                   *offsetp += 5;
1250             } else { /* Item is a string */
1251                   proto_item *tti;
1252                   proto_tree *ttt;
1253                   gint8 delta = VALUE8(tvb, *offsetp + 1);
1254                   if (sizeIs16) l += l;
1255                   if ((unsigned) allocated < l + 1) {
1256                         /* g_realloc doesn't work ??? */
1257                         g_free(s);
1258                         s = g_malloc(l + 1);
1259                         allocated = l + 1;
1260                   }
1261                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
1262                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
1263                                                        "textitem (string): delta = %d, \"%s\"",
1264                                                        delta, s);
1265                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
1266                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
1267                   if (sizeIs16)
1268                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
1269                                                           hf_x11_textitem_string_string16_bytes,
1270                                                           *offsetp + 2, l,
1271                                                           &s, &allocated,
1272                                                           little_endian);
1273                   else
1274                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
1275                                                      *offsetp + 2, l, s, "\"%s\"", s);
1276                   *offsetp += l + 2;
1277             }
1278       }
1279
1280       /*
1281        * Call the cleanup handler to free the string and pop the handler.
1282        */
1283       CLEANUP_CALL_AND_POP;
1284 }
1285
1286 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1287                       gboolean little_endian)
1288 {
1289       guint32 v = VALUE8(tvb, *offsetp);
1290       header_field_info *hfi = proto_registrar_get_nth(hf);
1291       gchar *enumValue = NULL;
1292
1293       if (hfi -> strings)
1294             enumValue = match_strval(v, cVALS(hfi -> strings));
1295       if (enumValue)
1296             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
1297                                        hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
1298                                        hfi -> name, v, enumValue);
1299       else
1300             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
1301       *offsetp += 1;
1302       return v;
1303 }
1304
1305 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1306                        gboolean little_endian)
1307 {
1308       guint32 v = VALUE16(tvb, *offsetp);
1309       proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
1310       *offsetp += 2;
1311       return v;
1312 }
1313
1314 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1315                        gboolean little_endian)
1316 {
1317       guint32 v = VALUE32(tvb, *offsetp);
1318       header_field_info *hfi = proto_registrar_get_nth(hf);
1319       gchar *enumValue = NULL;
1320       gchar *nameAsChar = hfi -> name;
1321
1322       if (hfi -> strings)
1323             enumValue = match_strval(v, cVALS(hfi -> strings));
1324       if (enumValue)
1325             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
1326                                        hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
1327                                        nameAsChar, v, enumValue);
1328       else
1329             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
1330                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1331                                        nameAsChar, v);
1332       *offsetp += 4;
1333       return v;
1334 }
1335
1336 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1337                          gboolean little_endian)
1338 {
1339       BITMASK32(gc_value);
1340       BITFIELD(ENUM8,  gc_value_mask, function);
1341       BITFIELD(CARD32, gc_value_mask, plane_mask);
1342       BITFIELD(CARD32, gc_value_mask, foreground);
1343       BITFIELD(CARD32, gc_value_mask, background);
1344       BITFIELD(CARD16, gc_value_mask, line_width);
1345       BITFIELD(ENUM8,  gc_value_mask, line_style);
1346       BITFIELD(ENUM8,  gc_value_mask, cap_style);
1347       BITFIELD(ENUM8,  gc_value_mask, join_style);
1348       BITFIELD(ENUM8,  gc_value_mask, fill_style);
1349       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
1350       BITFIELD(PIXMAP, gc_value_mask, tile);
1351       BITFIELD(PIXMAP, gc_value_mask, stipple);
1352       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
1353       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
1354       BITFIELD(FONT,   gc_value_mask, font);
1355       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
1356       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
1357       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
1358       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
1359       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1360       BITFIELD(CARD16, gc_value_mask, dash_offset);
1361       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
1362       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
1363       ENDBITMASK;
1364 }
1365
1366 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1367                    gboolean little_endian)
1368 {
1369       BITMASK32(gc_value);
1370       FLAG(gc_value, function);
1371       FLAG(gc_value, plane_mask);
1372       FLAG(gc_value, foreground);
1373       FLAG(gc_value, background);
1374       FLAG(gc_value, line_width);
1375       FLAG(gc_value, line_style);
1376       FLAG(gc_value, cap_style);
1377       FLAG(gc_value, join_style);
1378       FLAG(gc_value, fill_style);
1379       FLAG(gc_value, fill_rule);
1380       FLAG(gc_value, tile);
1381       FLAG(gc_value, stipple);
1382       FLAG(gc_value, tile_stipple_x_origin);
1383       FLAG(gc_value, tile_stipple_y_origin);
1384       FLAG(gc_value, font);
1385       FLAG(gc_value, subwindow_mode);
1386       FLAG(gc_value, graphics_exposures);
1387       FLAG(gc_value, clip_x_origin);
1388       FLAG(gc_value, clip_y_origin);
1389       FLAG(gc_value, clip_mask);
1390       FLAG(gc_value, dash_offset);
1391       FLAG(gc_value, gc_dashes);
1392       FLAG(gc_value, arc_mode);
1393       ENDBITMASK;
1394 }
1395
1396 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1397                              gboolean little_endian)
1398 {
1399       guint32 res = VALUE16(tvb, *offsetp) * 4;
1400       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
1401       *offsetp += 2;
1402       return res;
1403 }
1404
1405 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1406                        gboolean little_endian)
1407 {
1408       BITMASK32(event);
1409       FLAG(event, KeyPress);
1410       FLAG(event, KeyRelease);
1411       FLAG(event, ButtonPress);
1412       FLAG(event, ButtonRelease);
1413       FLAG(event, EnterWindow);
1414       FLAG(event, LeaveWindow);
1415       FLAG(event, PointerMotion);
1416       FLAG(event, PointerMotionHint);
1417       FLAG(event, Button1Motion);
1418       FLAG(event, Button2Motion);
1419       FLAG(event, Button3Motion);
1420       FLAG(event, Button4Motion);
1421       FLAG(event, Button5Motion);
1422       FLAG(event, ButtonMotion);
1423       FLAG(event, KeymapState);
1424       FLAG(event, Exposure);
1425       FLAG(event, VisibilityChange);
1426       FLAG(event, StructureNotify);
1427       FLAG(event, ResizeRedirect);
1428       FLAG(event, SubstructureNotify);
1429       FLAG(event, SubstructureRedirect);
1430       FLAG(event, FocusChange);
1431       FLAG(event, PropertyChange);
1432       FLAG(event, ColormapChange);
1433       FLAG(event, OwnerGrabButton);
1434       FLAG_IF_NONZERO(event, erroneous_bits);
1435       ENDBITMASK;
1436 }
1437
1438 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1439                              gboolean little_endian)
1440 {
1441       BITMASK32(do_not_propagate);
1442       FLAG(do_not_propagate, KeyPress);
1443       FLAG(do_not_propagate, KeyRelease);
1444       FLAG(do_not_propagate, ButtonPress);
1445       FLAG(do_not_propagate, ButtonRelease);
1446       FLAG(do_not_propagate, PointerMotion);
1447       FLAG(do_not_propagate, Button1Motion);
1448       FLAG(do_not_propagate, Button2Motion);
1449       FLAG(do_not_propagate, Button3Motion);
1450       FLAG(do_not_propagate, Button4Motion);
1451       FLAG(do_not_propagate, Button5Motion);
1452       FLAG(do_not_propagate, ButtonMotion);
1453       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
1454       ENDBITMASK;
1455 }
1456
1457 static void setOfKeyMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1458                          gboolean little_endian)
1459 {
1460       proto_item *ti;
1461       guint32 bitmask_value;
1462       int bitmask_offset;
1463       int bitmask_size;
1464       proto_tree *bitmask_tree;
1465
1466       bitmask_value = VALUE16(tvb, *offsetp);
1467       bitmask_offset = *offsetp;
1468       bitmask_size = 2;
1469       if (bitmask_value == 0x8000)
1470             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
1471                                        "modifiers-masks: 0x8000 (AnyModifier)");
1472       else {
1473             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
1474                                                  bitmask_value);
1475             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
1476             FLAG(modifiers, Shift);
1477             FLAG(modifiers, Lock);
1478             FLAG(modifiers, Control);
1479             FLAG(modifiers, Mod1);
1480             FLAG(modifiers, Mod2);
1481             FLAG(modifiers, Mod3);
1482             FLAG(modifiers, Mod4);
1483             FLAG(modifiers, Mod5);
1484             FLAG_IF_NONZERO(modifiers, erroneous_bits);
1485       }
1486       *offsetp += 2;
1487 }
1488
1489 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1490                               gboolean little_endian)
1491 {
1492       BITMASK16(pointer_event);
1493       FLAG(pointer_event, ButtonPress);
1494       FLAG(pointer_event, ButtonRelease);
1495       FLAG(pointer_event, EnterWindow);
1496       FLAG(pointer_event, LeaveWindow);
1497       FLAG(pointer_event, PointerMotion);
1498       FLAG(pointer_event, PointerMotionHint);
1499       FLAG(pointer_event, Button1Motion);
1500       FLAG(pointer_event, Button2Motion);
1501       FLAG(pointer_event, Button3Motion);
1502       FLAG(pointer_event, Button4Motion);
1503       FLAG(pointer_event, Button5Motion);
1504       FLAG(pointer_event, ButtonMotion);
1505       FLAG(pointer_event, KeymapState);
1506       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
1507       ENDBITMASK;
1508 }
1509
1510 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1511     int hf, unsigned length)
1512 {
1513       char *s = g_malloc(length + 1);
1514
1515       /*
1516        * In case we throw an exception, clean up whatever stuff we've
1517        * allocated (if any).
1518        */
1519       CLEANUP_PUSH(g_free, s);
1520
1521       stringCopy(s, tvb_get_ptr(tvb, *offsetp, length), length);
1522       proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
1523
1524       /*
1525        * Call the cleanup handler to free the string and pop the handler.
1526        */
1527       CLEANUP_CALL_AND_POP;
1528
1529       *offsetp += length;
1530 }
1531
1532 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1533
1534 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1535     int hf_bytes, unsigned length, gboolean little_endian)
1536 {
1537       char *s = NULL;
1538       unsigned l = 0;
1539
1540       /*
1541        * In case we throw an exception, clean up whatever stuff we've
1542        * allocated (if any).
1543        */
1544       CLEANUP_PUSH(g_free, s);
1545
1546       length += length;
1547       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
1548                                         &s, &l, little_endian);
1549
1550       /*
1551        * Call the cleanup handler to free the string and pop the handler.
1552        */
1553       CLEANUP_CALL_AND_POP;
1554
1555       *offsetp += length;
1556 }
1557
1558 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1559                       gboolean little_endian)
1560 {
1561       guint32 v = VALUE32(tvb, *offsetp);
1562
1563       if (!v)
1564             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
1565                 proto_registrar_get_nth(hf) -> name);
1566       else
1567             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
1568       *offsetp += 4;
1569 }
1570
1571 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1572                              gboolean little_endian)
1573 {
1574       BITMASK32(window_value);
1575       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1576       BITFIELD(CARD32, window_value_mask, background_pixel);
1577       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1578       BITFIELD(CARD32, window_value_mask, border_pixel);
1579       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1580       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1581       BITFIELD(ENUM8, window_value_mask, backing_store);
1582       BITFIELD(CARD32, window_value_mask, backing_planes);
1583       BITFIELD(CARD32, window_value_mask, backing_pixel);
1584       BITFIELD(BOOL,   window_value_mask, override_redirect);
1585       BITFIELD(BOOL,   window_value_mask, save_under);
1586       BITFIELD(SETofEVENT, window_value_mask, event_mask);
1587       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1588       BITFIELD(COLORMAP, window_value_mask, colormap);
1589       BITFIELD(CURSOR, window_value_mask, cursor);
1590       ENDBITMASK;
1591 }
1592
1593 /*
1594  * Data structure associated with a conversation; keeps track of the
1595  * request for which we're expecting a reply, the frame number of
1596  * the initial connection request, and the byte order of the connection.
1597  *
1598  * An opcode of -3 means we haven't yet seen any requests yet.
1599  * An opcode of -2 means we're not expecting a reply.
1600  * An opcode of -1 means means we're waiting for a reply to the initial
1601  * connection request.
1602  * Other values are the opcode of the request for which we're expecting
1603  * a reply.
1604  *
1605  * XXX - assumes only one outstanding request is awaiting a reply,
1606  * which should always be the case.
1607  */
1608 #define NOTHING_SEEN            -3
1609 #define NOTHING_EXPECTED        -2
1610 #define INITIAL_CONN            -1
1611
1612 #define BYTE_ORDER_BE           0
1613 #define BYTE_ORDER_LE           1
1614 #define BYTE_ORDER_UNKNOWN      -1
1615
1616 typedef struct {
1617       int       opcode;         /* opcode for which we're awaiting a reply */
1618       guint32   iconn_frame;    /* frame # of initial connection request */
1619       int       byte_order;     /* byte order of connection */
1620 } x11_conv_data_t;
1621
1622 static GMemChunk *x11_state_chunk = NULL;
1623
1624 static void x11_init_protocol(void)
1625 {
1626       if (x11_state_chunk != NULL)
1627             g_mem_chunk_destroy(x11_state_chunk);
1628
1629       x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
1630                                         sizeof (x11_conv_data_t),
1631                                         128 * sizeof (x11_conv_data_t),
1632                                         G_ALLOC_ONLY);
1633 }
1634
1635 /************************************************************************
1636  ***                                                                  ***
1637  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
1638  ***                                                                  ***
1639  ************************************************************************/
1640
1641 /* If we can't guess, we return TRUE (that is little_endian), cause
1642    I'm developing on a Linux box :-). The (non-)guess isn't cached
1643    however, so we may have more luck next time. I'm quite conservative
1644    in my assertions, cause once it's cached, it's stay in cache, and
1645    we may be fooled up by a packet starting with the end of a request
1646    started in a previous packet...
1647 */
1648
1649 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
1650
1651 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
1652 {
1653       int res = 0;
1654       while(maskLength--) {
1655             int c = tvb_get_guint8(tvb, offset);
1656             offset++;
1657             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
1658       }
1659       return res;
1660 }
1661
1662 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
1663 {
1664       if (listLength > length) return FALSE;
1665       while(listLength--) {
1666             int l;
1667             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
1668             l = tvb_get_guint8(tvb, offset);
1669             if (!l) break;
1670             l++;
1671             if (l > length) return FALSE;
1672             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
1673             offset += l;
1674             length -= l;
1675       }
1676       if (length > 3) return FALSE;
1677       return TRUE;
1678 }
1679
1680 static int rounded4(int n)
1681 {
1682       int remainder = n % 4;
1683       int res = n / 4;
1684       if (remainder) res++;
1685       return res;
1686 }
1687
1688 /* We assume the order to be consistent, until proven wrong. */
1689
1690 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
1691 {
1692       switch(tvb_get_guint8(tvb, offset)) {
1693           case 1: /* CreateWindow */
1694             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
1695
1696           case 2: /* ChangeWindowAttributes */
1697           case 56: /* ChangeGC */
1698             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
1699
1700           case 3: /* GetWindowAttributes */
1701           case 4: /* DestroyWindow */
1702           case 5: /* DestroySubwindows */
1703           case 6: /* ChangeSaveSet */
1704           case 8: /* MapWindow */
1705           case 9: /* MapSubWindow */
1706           case 10: /* UnmapWindow */
1707           case 11: /* UnmapSubwindows */
1708           case 13: /* CirculateWindow */
1709           case 14: /* GetGeometry */
1710           case 15: /* QueryTree */
1711           case 17: /* GetAtomName */
1712           case 21: /* ListProperties */
1713           case 23: /* GetSelectionOwner */
1714           case 27: /* UngrabPointer */
1715           case 32: /* UngrabKeyboard */
1716           case 35: /* AllowEvents */
1717           case 38: /* QueryPointer */
1718           case 46: /* CloseFont */
1719           case 47: /* QueryFont */
1720           case 54: /* FreePixmap */
1721           case 60: /* FreeGC */
1722           case 79: /* FreeColormap */
1723           case 81: /* InstallColormap */
1724           case 82: /* UninstallColormap */
1725           case 83: /* ListInstalledColormaps */
1726           case 95: /* FreeCursor */
1727           case 101: /* GetKeyboardMapping */
1728           case 113: /* KillClient */
1729             return length == 2;
1730
1731           case 7: /* ReparentWindow */
1732           case 22: /* SetSelectionOwner */
1733           case 30: /* ChangeActivePointerGrab */
1734           case 31: /* GrabKeyboard */
1735           case 33: /* GrabKey */
1736           case 39: /* GetMotionEvents */
1737           case 40: /* TranslateCoordinates */
1738           case 53: /* CreatePixmap */
1739           case 57: /* CopyGC */
1740           case 61: /* ClearArea */
1741           case 78: /* CreateColormap */
1742           case 84: /* AllocColor */
1743           case 87: /* AllocColorPlanes */
1744             return length == 4;
1745
1746           case 12: /* ConfigureWindow */
1747             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
1748
1749           case 16: /* InternAtom */
1750           case 98: /* QueryExtension */
1751             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
1752
1753           case 18: /* ChangeProperty */
1754             {
1755                   int multiplier, type;
1756                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
1757                   type = tvb_get_guint8(tvb, 16);
1758                   if (type != 8 && type != 16 && type != 32) return FALSE;
1759                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
1760                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
1761                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
1762             }
1763
1764           case 19: /* DeleteProperty */
1765           case 29: /* UngrabButton */
1766           case 34: /* UngrabKey */
1767           case 42: /* SetInputFocus */
1768           case 80: /* CopyColormapAndFree */
1769           case 86: /* AllocColorCells */
1770           case 97: /* QueryBestSize */
1771           case 105: /* ChangePointerControl */
1772           case 107: /* SetScreenSaver */
1773             return length == 3;
1774
1775           case 20: /* GetProperty */
1776           case 24: /* ConvertSelection */
1777           case 26: /* GrabPointer */
1778           case 28: /* GrabButton */
1779           case 41: /* WarpPointer */
1780             return length == 6;
1781
1782           case 25: /* SendEvent */
1783             return length == 11;
1784
1785           case 36: /* GrabServer */
1786           case 37: /* UngrabServer */
1787           case 43: /* GetInputFocus */
1788           case 44: /* QueryKeymap */
1789           case 52: /* GetFontPath */
1790           case 99: /* ListExtensions */
1791           case 103: /* GetKeyboardControl */
1792           case 104: /* Bell */
1793           case 106: /* GetPointerControl */
1794           case 108: /* GetScreenSaver */
1795           case 110: /* ListHosts */
1796           case 111: /* SetAccessControl */
1797           case 112: /* SetCloseDownMode */
1798           case 115: /* ForceScreenSaver */
1799           case 117: /* GetPointerMapping */
1800           case 119: /* GetModifierMapping */
1801             return length == 1;
1802
1803           case 45: /* OpenFont */
1804           case 85: /* AllocNamedColor */
1805           case 92: /* LookupColor */
1806             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
1807
1808           case 48: /* QueryTextExtents */
1809             return length >= 2;
1810
1811           case 49: /* ListFonts */
1812           case 50: /* ListFontsWithInfo */
1813           case 109: /* ChangeHosts */
1814             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
1815
1816           case 51: /* SetFontPath */
1817             if (length < 2) return FALSE;
1818             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
1819             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
1820
1821           case 55: /* CreateGC */
1822             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
1823
1824           case 58: /* SetDashes */
1825             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
1826
1827           case 59: /* SetClipRectangles */
1828           case 66: /* PolySegment */
1829           case 67: /* PolyRectangle */
1830           case 70: /* PolyFillRectangle */
1831             return length >= 3 && (length - 3) % 2 == 0;
1832
1833           case 62: /* CopyArea */
1834             return length == 7;
1835
1836           case 63: /* CopyPlane */
1837           case 93: /* CreateCursor */
1838           case 94: /* CreateGlyphCursor */
1839             return length == 8;
1840
1841           case 64: /* PolyPoint */
1842           case 65: /* PolyLine */
1843           case 88: /* FreeColors */
1844             return length >= 3;
1845
1846           case 68: /* PolyArc */
1847           case 71: /* PolyFillArc */
1848             return length >= 3 && (length - 3) % 3 == 0;
1849
1850           case 69: /* FillPoly */
1851           case 76: /* ImageText8 */
1852             return length >= 4;
1853
1854           case 72: /* PutImage */
1855             return length >= 6;
1856
1857           case 73: /* GetImage */
1858           case 96: /* RecolorCursor */
1859             return length == 5;
1860
1861           case 74: /* PolyText8 */
1862             if (length < 4) return FALSE;
1863             return TRUE; /* We don't perform many controls on this one */
1864
1865           case 75: /* PolyText16 */
1866             if (length < 4) return FALSE;
1867             return TRUE; /* We don't perform many controls on this one */
1868
1869           case 77: /* ImageText16 */
1870             return length >= 4;
1871
1872           case 89: /* StoreColors */
1873             return length > 2 && (length - 2) % 3 == 0;
1874
1875           case 90: /* StoreNamedColor */
1876             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
1877
1878           case 91: /* QueryColors */
1879             return length >= 2;
1880
1881           case 100: /* ChangeKeyboardMapping */
1882             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
1883
1884           case 102: /* ChangeKeyboardControl */
1885             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
1886
1887           case 114: /* RotateProperties */
1888             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
1889
1890           case 116: /* SetPointerMapping */
1891             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
1892
1893           case 118: /* SetModifierMapping */
1894             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
1895
1896           case 127: /* NoOperation */
1897             return length >= 1;
1898
1899           default:
1900             return TRUE;
1901       }
1902 }
1903
1904 /* -1 means doesn't match, +1 means match, 0 means don't know */
1905
1906 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
1907 {
1908       int offset, nextoffset;
1909       int atLeastOne = 0;
1910
1911       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
1912             int length;
1913             length = v16(tvb, offset + 2);
1914             if (!length) return -1;
1915             nextoffset = offset + length * 4;
1916             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
1917             atLeastOne = 1;
1918       }
1919       return atLeastOne;
1920 }
1921
1922 static gboolean
1923 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
1924                     x11_conv_data_t *state_info)
1925 {
1926       /* With X the client gives the byte ordering for the protocol,
1927          and the port on the server tells us we're speaking X. */
1928
1929       int le, be, decision, decisionToCache;
1930
1931       if (state_info->byte_order == BYTE_ORDER_BE)
1932             return FALSE;       /* known to be big-endian */
1933       else if (state_info->byte_order == BYTE_ORDER_LE)
1934             return TRUE;        /* known to be little-endian */
1935
1936       if (pinfo->srcport == pinfo->match_port) {
1937             /*
1938              * This is a reply or event; we don't try to guess the
1939              * byte order on it for now.
1940              */
1941             return TRUE;
1942       }
1943
1944       le = x_endian_match(tvb, tvb_get_letohs);
1945       be = x_endian_match(tvb, tvb_get_ntohs);
1946
1947       /* remember that "decision" really means "little_endian". */
1948       if (le == be) {
1949             /* We have no reason to believe it's little- rather than
1950                big-endian, so we guess the shortest length is the
1951                right one.
1952             */
1953             if (!tvb_bytes_exist(tvb, 0, 4))
1954                   /* Not even a way to get the length. We're biased
1955                      toward little endianness here (essentially the
1956                      x86 world right now). Decoding won't go very far
1957                      anyway.
1958                   */
1959                   decision = TRUE;
1960             else
1961                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
1962       } else
1963           decision = le >= be;
1964
1965       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
1966       if (decisionToCache) {
1967             /*
1968              * Remember the decision.
1969              */
1970             state_info->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
1971       }
1972
1973       /*
1974       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
1975               pinfo->fd -> num, le, be, decision, decisionToCache);
1976       */
1977       return decision;
1978 }
1979
1980 /************************************************************************
1981  ***                                                                  ***
1982  ***              D E C O D I N G   O N E   P A C K E T               ***
1983  ***                                                                  ***
1984  ************************************************************************/
1985
1986 /*
1987  * Decode an initial connection request.
1988  */
1989 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
1990     proto_tree *tree, x11_conv_data_t *state_info, gboolean little_endian)
1991 {
1992       int offset = 0;
1993       int *offsetp = &offset;
1994       proto_item *ti;
1995       proto_tree *t;
1996       guint16 auth_proto_name_length, auth_proto_data_length;
1997       gint left;
1998
1999       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2000       t = proto_item_add_subtree(ti, ett_x11);
2001
2002       CARD8(byte_order);
2003       UNUSED(1);
2004       CARD16(protocol_major_version);
2005       CARD16(protocol_minor_version);
2006       auth_proto_name_length = CARD16(authorization_protocol_name_length);
2007       auth_proto_data_length = CARD16(authorization_protocol_data_length);
2008       UNUSED(2);
2009       if (auth_proto_name_length != 0) {
2010             STRING8(authorization_protocol_name, auth_proto_name_length);
2011             offset = ROUND_LENGTH(offset);
2012       }
2013       if (auth_proto_data_length != 0) {
2014             STRING8(authorization_protocol_data, auth_proto_data_length);
2015             offset = ROUND_LENGTH(offset);
2016       }
2017       left = tvb_length_remaining(tvb, offset);
2018       if (left)
2019             proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
2020
2021       /*
2022        * This is the initial connection request...
2023        */
2024       state_info->iconn_frame = pinfo->fd->num;
2025
2026       /*
2027        * ...and we're expecting a reply to it.
2028        */
2029       state_info->opcode = INITIAL_CONN;
2030 }
2031
2032 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2033     proto_tree *tree, const char *sep, x11_conv_data_t *state_info,
2034     gboolean little_endian)
2035 {
2036       int offset = 0;
2037       int *offsetp = &offset;
2038       int next_offset;
2039       proto_item *ti;
2040       proto_tree *t;
2041       int length, opcode;
2042       guint8 v8, v8_2;
2043       guint16 v16;
2044       guint32 v32;
2045       gint left;
2046
2047       length = VALUE16(tvb, 2) * 4;
2048
2049       if (length < 4) {
2050             /* Bogus message length? */
2051             return;
2052       }
2053
2054       next_offset = offset + length;
2055
2056       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2057       t = proto_item_add_subtree(ti, ett_x11);
2058
2059       OPCODE();
2060
2061       if (check_col(pinfo->cinfo, COL_INFO))
2062           col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2063                           val_to_str(opcode, opcode_vals, "Unknown (%u)"));
2064
2065       /*
2066        * Does this request expect a reply?
2067        */
2068       switch(opcode) {
2069
2070       case 3: /* GetWindowAttributes */
2071       case 14: /* GetGeometry */
2072       case 15: /* QueryTree */
2073       case 16: /* InternAtom */
2074       case 17: /* GetAtomName */
2075       case 20: /* GetProperty */
2076       case 21: /* ListProperties */
2077       case 23: /* GetSelectionOwner */
2078       case 26: /* GrabPointer */
2079       case 31: /* GrabKeyboard */
2080       case 38: /* QueryPointer */
2081       case 39: /* GetMotionEvents */
2082       case 40: /* TranslateCoordinates */
2083       case 44: /* QueryKeymap */
2084       case 47: /* QueryFont */
2085       case 48: /* QueryTextExtents */
2086       case 49: /* ListFonts */
2087       case 73: /* GetImage */
2088       case 83: /* ListInstalledColormaps */
2089       case 84: /* AllocColor */
2090       case 91: /* QueryColors */
2091       case 92: /* LookupColor */
2092       case 97: /* QueryBestSize */
2093       case 98: /* QueryExtension */
2094       case 99: /* ListExtensions */
2095       case 101: /* GetKeyboardMapping */
2096       case 103: /* GetKeyboardControl */
2097       case 106: /* GetPointerControl */
2098       case 108: /* GetScreenSaver */
2099       case 110: /* ListHosts */
2100       case 116: /* SetPointerMapping */
2101       case 117: /* GetPointerMapping */
2102       case 118: /* SetModifierMapping */
2103       case 119: /* GetModifierMapping */
2104             /*
2105              * Those requests expect a reply.
2106              */
2107             state_info->opcode = opcode;
2108             break;
2109
2110       default:
2111             /*
2112              * No reply is expected from any other request.
2113              */
2114             state_info->opcode = NOTHING_EXPECTED;
2115             break;
2116       }
2117
2118       if (!tree) return;
2119
2120       switch(opcode) {
2121
2122       case 1: /* CreateWindow */
2123             CARD8(depth);
2124             REQUEST_LENGTH();
2125             WINDOW(wid);
2126             WINDOW(parent);
2127             INT16(x);
2128             INT16(y);
2129             CARD16(width);
2130             CARD16(height);
2131             CARD16(border_width);
2132             ENUM16(window_class);
2133             VISUALID(visual);
2134             windowAttributes(tvb, offsetp, t, little_endian);
2135             break;
2136
2137       case 2: /* ChangeWindowAttributes */
2138             UNUSED(1);
2139             REQUEST_LENGTH();
2140             WINDOW(window);
2141             windowAttributes(tvb, offsetp, t, little_endian);
2142             break;
2143
2144       case 3: /* GetWindowAttributes */
2145       case 4: /* DestroyWindow */
2146       case 5: /* DestroySubwindows */
2147             UNUSED(1);
2148             REQUEST_LENGTH();
2149             WINDOW(window);
2150             break;
2151
2152       case 6: /* ChangeSaveSet */
2153             ENUM8(save_set_mode);
2154             REQUEST_LENGTH();
2155             WINDOW(window);
2156             break;
2157
2158       case 7: /* ReparentWindow */
2159             UNUSED(1);
2160             REQUEST_LENGTH();
2161             WINDOW(window);
2162             WINDOW(parent);
2163             INT16(x);
2164             INT16(y);
2165             break;
2166
2167       case 8: /* MapWindow */
2168       case 9: /* MapSubWindow */
2169       case 10: /* UnmapWindow */
2170       case 11: /* UnmapSubwindows */
2171             UNUSED(1);
2172             REQUEST_LENGTH();
2173             WINDOW(window);
2174             break;
2175
2176       case 12: /* ConfigureWindow */
2177             UNUSED(1);
2178             REQUEST_LENGTH();
2179             WINDOW(window);
2180             BITMASK16(configure_window);
2181             UNUSED(2);
2182             BITFIELD(INT16,  configure_window_mask, x);
2183             BITFIELD(INT16,  configure_window_mask, y);
2184             BITFIELD(CARD16, configure_window_mask, width);
2185             BITFIELD(CARD16, configure_window_mask, height);
2186             BITFIELD(CARD16, configure_window_mask, border_width);
2187             BITFIELD(WINDOW, configure_window_mask, sibling);
2188             BITFIELD(ENUM8,  configure_window_mask, stack_mode);
2189             ENDBITMASK;
2190             PAD();
2191             break;
2192
2193       case 13: /* CirculateWindow */
2194             ENUM8(direction);
2195             REQUEST_LENGTH();
2196             WINDOW(window);
2197             break;
2198
2199       case 14: /* GetGeometry */
2200       case 15: /* QueryTree */
2201             UNUSED(1);
2202             REQUEST_LENGTH();
2203             DRAWABLE(drawable);
2204             break;
2205
2206       case 16: /* InternAtom */
2207             BOOL(only_if_exists);
2208             REQUEST_LENGTH();
2209             v16 = FIELD16(name_length);
2210             UNUSED(2);
2211             STRING8(name, v16);
2212             PAD();
2213             break;
2214
2215       case 17: /* GetAtomName */
2216             UNUSED(1);
2217             REQUEST_LENGTH();
2218             ATOM(atom);
2219             break;
2220
2221       case 18: /* ChangeProperty */
2222             ENUM8(mode);
2223             REQUEST_LENGTH();
2224             WINDOW(window);
2225             ATOM(property);
2226             ATOM(type);
2227             CARD8(format);
2228             UNUSED(3);
2229             v32 = CARD32(data_length);
2230             LISTofBYTE(data, v32);
2231             PAD();
2232             break;
2233
2234       case 19: /* DeleteProperty */
2235             UNUSED(1);
2236             REQUEST_LENGTH();
2237             WINDOW(window);
2238             ATOM(property);
2239             break;
2240
2241       case 20: /* GetProperty */
2242             BOOL(delete);
2243             REQUEST_LENGTH();
2244             WINDOW(window);
2245             ATOM(property);
2246             ATOM(get_property_type);
2247             CARD32(long_offset);
2248             CARD32(long_length);
2249             break;
2250
2251       case 21: /* ListProperties */
2252             UNUSED(1);
2253             REQUEST_LENGTH();
2254             WINDOW(window);
2255             break;
2256
2257       case 22: /* SetSelectionOwner */
2258             UNUSED(1);
2259             REQUEST_LENGTH();
2260             WINDOW(owner);
2261             ATOM(selection);
2262             TIMESTAMP(time);
2263             break;
2264
2265       case 23: /* GetSelectionOwner */
2266             UNUSED(1);
2267             REQUEST_LENGTH();
2268             ATOM(selection);
2269             break;
2270
2271       case 24: /* ConvertSelection */
2272             UNUSED(1);
2273             REQUEST_LENGTH();
2274             WINDOW(requestor);
2275             ATOM(selection);
2276             ATOM(target);
2277             ATOM(property);
2278             TIMESTAMP(time);
2279             break;
2280
2281       case 26: /* GrabPointer */
2282             BOOL(owner_events);
2283             REQUEST_LENGTH();
2284             WINDOW(grab_window);
2285             SETofPOINTEREVENT(pointer_event_mask);
2286             ENUM8(pointer_mode);
2287             ENUM8(keyboard_mode);
2288             WINDOW(confine_to);
2289             CURSOR(cursor);
2290             TIMESTAMP(time);
2291             break;
2292
2293       case 27: /* UngrabPointer */
2294             UNUSED(1);
2295             REQUEST_LENGTH();
2296             TIMESTAMP(time);
2297             break;
2298
2299       case 28: /* GrabButton */
2300             BOOL(owner_events);
2301             REQUEST_LENGTH();
2302             WINDOW(grab_window);
2303             SETofPOINTEREVENT(event_mask);
2304             ENUM8(pointer_mode);
2305             ENUM8(keyboard_mode);
2306             WINDOW(confine_to);
2307             CURSOR(cursor);
2308             BUTTON(button);
2309             UNUSED(1);
2310             SETofKEYMASK(modifiers);
2311             break;
2312
2313       case 29: /* UngrabButton */
2314             BUTTON(button);
2315             REQUEST_LENGTH();
2316             WINDOW(grab_window);
2317             SETofKEYMASK(modifiers);
2318             UNUSED(2);
2319             break;
2320
2321       case 30: /* ChangeActivePointerGrab */
2322             UNUSED(1);
2323             REQUEST_LENGTH();
2324             CURSOR(cursor);
2325             TIMESTAMP(time);
2326             SETofPOINTEREVENT(event_mask);
2327             UNUSED(2);
2328             break;
2329
2330       case 31: /* GrabKeyboard */
2331             BOOL(owner_events);
2332             REQUEST_LENGTH();
2333             WINDOW(grab_window);
2334             TIMESTAMP(time);
2335             ENUM8(pointer_mode);
2336             ENUM8(keyboard_mode);
2337             UNUSED(2);
2338             break;
2339
2340       case 32: /* UngrabKeyboard */
2341             UNUSED(1);
2342             REQUEST_LENGTH();
2343             TIMESTAMP(time);
2344             break;
2345
2346       case 33: /* GrabKey */
2347             BOOL(owner_events);
2348             REQUEST_LENGTH();
2349             WINDOW(grab_window);
2350             SETofKEYMASK(modifiers);
2351             KEYCODE(key);
2352             ENUM8(pointer_mode);
2353             ENUM8(keyboard_mode);
2354             UNUSED(3);
2355             break;
2356
2357       case 34: /* UngrabKey */
2358             KEYCODE(key);
2359             REQUEST_LENGTH();
2360             WINDOW(grab_window);
2361             SETofKEYMASK(modifiers);
2362             UNUSED(2);
2363             break;
2364
2365       case 35: /* AllowEvents */
2366             ENUM8(allow_events_mode);
2367             REQUEST_LENGTH();
2368             TIMESTAMP(time);
2369             break;
2370
2371       case 36: /* GrabServer */
2372             UNUSED(1);
2373             REQUEST_LENGTH();
2374             break;
2375
2376       case 37: /* UngrabServer */
2377             UNUSED(1);
2378             REQUEST_LENGTH();
2379             break;
2380
2381       case 38: /* QueryPointer */
2382             UNUSED(1);
2383             REQUEST_LENGTH();
2384             WINDOW(window);
2385             break;
2386
2387       case 39: /* GetMotionEvents */
2388             UNUSED(1);
2389             REQUEST_LENGTH();
2390             WINDOW(window);
2391             TIMESTAMP(start);
2392             TIMESTAMP(stop);
2393             break;
2394
2395       case 40: /* TranslateCoordinates */
2396             UNUSED(1);
2397             REQUEST_LENGTH();
2398             WINDOW(src_window);
2399             WINDOW(dst_window);
2400             INT16(src_x);
2401             INT16(src_y);
2402             break;
2403
2404       case 41: /* WarpPointer */
2405             UNUSED(1);
2406             REQUEST_LENGTH();
2407             WINDOW(warp_pointer_src_window);
2408             WINDOW(warp_pointer_dst_window);
2409             INT16(src_x);
2410             INT16(src_y);
2411             CARD16(src_width);
2412             CARD16(src_height);
2413             INT16(dst_x);
2414             INT16(dst_y);
2415             break;
2416
2417       case 42: /* SetInputFocus */
2418             ENUM8(revert_to);
2419             REQUEST_LENGTH();
2420             WINDOW(focus);
2421             TIMESTAMP(time);
2422             break;
2423
2424       case 43: /* GetInputFocus */
2425             UNUSED(1);
2426             REQUEST_LENGTH();
2427             break;
2428
2429       case 44: /* QueryKeymap */
2430             UNUSED(1);
2431             REQUEST_LENGTH();
2432             break;
2433
2434       case 45: /* OpenFont */
2435             UNUSED(1);
2436             REQUEST_LENGTH();
2437             FONT(fid);
2438             v16 = FIELD16(name_length);
2439             UNUSED(2);
2440             STRING8(name, v16);
2441             PAD();
2442             break;
2443
2444       case 46: /* CloseFont */
2445             UNUSED(1);
2446             REQUEST_LENGTH();
2447             FONT(font);
2448             break;
2449
2450       case 47: /* QueryFont */
2451             UNUSED(1);
2452             REQUEST_LENGTH();
2453             FONTABLE(font);
2454             break;
2455
2456       case 48: /* QueryTextExtents */
2457             v8 = BOOL(odd_length);
2458             REQUEST_LENGTH();
2459             FONTABLE(font);
2460             STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
2461             PAD();
2462             break;
2463
2464       case 49: /* ListFonts */
2465             UNUSED(1);
2466             REQUEST_LENGTH();
2467             CARD16(max_names);
2468             v16 = FIELD16(pattern_length);
2469             STRING8(pattern, v16);
2470             PAD();
2471             break;
2472
2473       case 50: /* ListFontsWithInfo */
2474             UNUSED(1);
2475             REQUEST_LENGTH();
2476             CARD16(max_names);
2477             v16 = FIELD16(pattern_length);
2478             STRING8(pattern, v16);
2479             PAD();
2480             break;
2481
2482       case 51: /* SetFontPath */
2483             UNUSED(1);
2484             REQUEST_LENGTH();
2485             v16 = CARD16(str_number_in_path);
2486             UNUSED(2);
2487             LISTofSTRING8(path, v16);
2488             PAD();
2489             break;
2490
2491       case 52: /* GetFontPath */
2492             UNUSED(1);
2493             REQUEST_LENGTH();
2494             break;
2495
2496       case 53: /* CreatePixmap */
2497             CARD8(depth);
2498             REQUEST_LENGTH();
2499             PIXMAP(pid);
2500             DRAWABLE(drawable);
2501             CARD16(width);
2502             CARD16(height);
2503             break;
2504
2505       case 54: /* FreePixmap */
2506             UNUSED(1);
2507             REQUEST_LENGTH();
2508             PIXMAP(pixmap);
2509             break;
2510
2511       case 55: /* CreateGC */
2512             UNUSED(1);
2513             REQUEST_LENGTH();
2514             GCONTEXT(cid);
2515             DRAWABLE(drawable);
2516             gcAttributes(tvb, offsetp, t, little_endian);
2517             break;
2518
2519       case 56: /* ChangeGC */
2520             UNUSED(1);
2521             REQUEST_LENGTH();
2522             GCONTEXT(gc);
2523             gcAttributes(tvb, offsetp, t, little_endian);
2524             break;
2525
2526       case 57: /* CopyGC */
2527             UNUSED(1);
2528             REQUEST_LENGTH();
2529             GCONTEXT(src_gc);
2530             GCONTEXT(dst_gc);
2531             gcMask(tvb, offsetp, t, little_endian);
2532             break;
2533
2534       case 58: /* SetDashes */
2535             UNUSED(1);
2536             REQUEST_LENGTH();
2537             GCONTEXT(gc);
2538             CARD16(dash_offset);
2539             v16 = FIELD16(dashes_length);
2540             LISTofCARD8(dashes, v16);
2541             PAD();
2542             break;
2543
2544       case 59: /* SetClipRectangles */
2545             ENUM8(ordering);
2546             REQUEST_LENGTH();
2547             GCONTEXT(gc);
2548             INT16(clip_x_origin);
2549             INT16(clip_y_origin);
2550             LISTofRECTANGLE(rectangles);
2551             break;
2552
2553       case 60: /* FreeGC */
2554             UNUSED(1);
2555             REQUEST_LENGTH();
2556             GCONTEXT(gc);
2557             break;
2558
2559       case 61: /* ClearArea */
2560             BOOL(exposures);
2561             REQUEST_LENGTH();
2562             WINDOW(window);
2563             INT16(x);
2564             INT16(y);
2565             CARD16(width);
2566             CARD16(height);
2567             break;
2568
2569       case 62: /* CopyArea */
2570             UNUSED(1);
2571             REQUEST_LENGTH();
2572             DRAWABLE(src_drawable);
2573             DRAWABLE(dst_drawable);
2574             GCONTEXT(gc);
2575             INT16(src_x);
2576             INT16(src_y);
2577             INT16(dst_x);
2578             INT16(dst_y);
2579             CARD16(width);
2580             CARD16(height);
2581             break;
2582
2583       case 63: /* CopyPlane */
2584             UNUSED(1);
2585             REQUEST_LENGTH();
2586             DRAWABLE(src_drawable);
2587             DRAWABLE(dst_drawable);
2588             GCONTEXT(gc);
2589             INT16(src_x);
2590             INT16(src_y);
2591             INT16(dst_x);
2592             INT16(dst_y);
2593             CARD16(width);
2594             CARD16(height);
2595             CARD32(bit_plane);
2596             break;
2597
2598       case 64: /* PolyPoint */
2599             ENUM8(coordinate_mode);
2600             v16 = REQUEST_LENGTH();
2601             DRAWABLE(drawable);
2602             GCONTEXT(gc);
2603             LISTofPOINT(points, v16 - 12);
2604             break;
2605
2606       case 65: /* PolyLine */
2607             ENUM8(coordinate_mode);
2608             v16 = REQUEST_LENGTH();
2609             DRAWABLE(drawable);
2610             GCONTEXT(gc);
2611             LISTofPOINT(points, v16 - 12);
2612             break;
2613
2614       case 66: /* PolySegment */
2615             UNUSED(1);
2616             REQUEST_LENGTH();
2617             DRAWABLE(drawable);
2618             GCONTEXT(gc);
2619             LISTofSEGMENT(segments);
2620             break;
2621
2622       case 67: /* PolyRectangle */
2623             UNUSED(1);
2624             REQUEST_LENGTH();
2625             DRAWABLE(drawable);
2626             GCONTEXT(gc);
2627             LISTofRECTANGLE(rectangles);
2628             break;
2629
2630       case 68: /* PolyArc */
2631             UNUSED(1);
2632             REQUEST_LENGTH();
2633             DRAWABLE(drawable);
2634             GCONTEXT(gc);
2635             LISTofARC(arcs);
2636             break;
2637
2638       case 69: /* FillPoly */
2639             UNUSED(1);
2640             v16 = REQUEST_LENGTH();
2641             DRAWABLE(drawable);
2642             GCONTEXT(gc);
2643             ENUM8(shape);
2644             ENUM8(coordinate_mode);
2645             UNUSED(2);
2646             LISTofPOINT(points, v16 - 16);
2647             break;
2648
2649       case 70: /* PolyFillRectangle */
2650             UNUSED(1);
2651             REQUEST_LENGTH();
2652             DRAWABLE(drawable);
2653             GCONTEXT(gc);
2654             LISTofRECTANGLE(rectangles);
2655             break;
2656
2657       case 71: /* PolyFillArc */
2658             UNUSED(1);
2659             REQUEST_LENGTH();
2660             DRAWABLE(drawable);
2661             GCONTEXT(gc);
2662             LISTofARC(arcs);
2663             break;
2664
2665       case 72: /* PutImage */
2666             ENUM8(image_format);
2667             v16 = REQUEST_LENGTH();
2668             DRAWABLE(drawable);
2669             GCONTEXT(gc);
2670             CARD16(width);
2671             CARD16(height);
2672             INT16(dst_x);
2673             INT16(dst_y);
2674             CARD8(left_pad);
2675             CARD8(depth);
2676             UNUSED(2);
2677             LISTofBYTE(data, v16 - 24);
2678             PAD();
2679             break;
2680
2681       case 73: /* GetImage */
2682             ENUM8(image_pixmap_format);
2683             REQUEST_LENGTH();
2684             DRAWABLE(drawable);
2685             INT16(x);
2686             INT16(y);
2687             CARD16(width);
2688             CARD16(height);
2689             CARD32(plane_mask);
2690             break;
2691
2692       case 74: /* PolyText8 */
2693             UNUSED(1);
2694             v16 = REQUEST_LENGTH();
2695             DRAWABLE(drawable);
2696             GCONTEXT(gc);
2697             INT16(x);
2698             INT16(y);
2699             LISTofTEXTITEM8(items);
2700             PAD();
2701             break;
2702
2703       case 75: /* PolyText16 */
2704             UNUSED(1);
2705             v16 = REQUEST_LENGTH();
2706             DRAWABLE(drawable);
2707             GCONTEXT(gc);
2708             INT16(x);
2709             INT16(y);
2710             LISTofTEXTITEM16(items);
2711             PAD();
2712             break;
2713
2714       case 76: /* ImageText8 */
2715             v8 = FIELD8(string_length);
2716             REQUEST_LENGTH();
2717             DRAWABLE(drawable);
2718             GCONTEXT(gc);
2719             INT16(x);
2720             INT16(y);
2721             STRING8(string, v8);
2722             PAD();
2723             break;
2724
2725       case 77: /* ImageText16 */
2726             v8 = FIELD8(string_length);
2727             REQUEST_LENGTH();
2728             DRAWABLE(drawable);
2729             GCONTEXT(gc);
2730             INT16(x);
2731             INT16(y);
2732             STRING16(string16, v8);
2733             PAD();
2734             break;
2735
2736       case 78: /* CreateColormap */
2737             ENUM8(alloc);
2738             REQUEST_LENGTH();
2739             COLORMAP(mid);
2740             WINDOW(window);
2741             VISUALID(visual);
2742             break;
2743
2744       case 79: /* FreeColormap */
2745             UNUSED(1);
2746             REQUEST_LENGTH();
2747             COLORMAP(cmap);
2748             break;
2749
2750       case 80: /* CopyColormapAndFree */
2751             UNUSED(1);
2752             REQUEST_LENGTH();
2753             COLORMAP(mid);
2754             COLORMAP(src_cmap);
2755             break;
2756
2757       case 81: /* InstallColormap */
2758             UNUSED(1);
2759             REQUEST_LENGTH();
2760             COLORMAP(cmap);
2761             break;
2762
2763       case 82: /* UninstallColormap */
2764             UNUSED(1);
2765             REQUEST_LENGTH();
2766             COLORMAP(cmap);
2767             break;
2768
2769       case 83: /* ListInstalledColormaps */
2770             UNUSED(1);
2771             REQUEST_LENGTH();
2772             WINDOW(window);
2773             break;
2774
2775       case 84: /* AllocColor */
2776             UNUSED(1);
2777             REQUEST_LENGTH();
2778             COLORMAP(cmap);
2779             CARD16(red);
2780             CARD16(green);
2781             CARD16(blue);
2782             UNUSED(2);
2783             break;
2784
2785       case 85: /* AllocNamedColor */
2786             UNUSED(1);
2787             REQUEST_LENGTH();
2788             COLORMAP(cmap);
2789             v16 = FIELD16(name_length);
2790             UNUSED(2);
2791             STRING8(name, v16);
2792             PAD();
2793             break;
2794
2795       case 86: /* AllocColorCells */
2796             BOOL(contiguous);
2797             REQUEST_LENGTH();
2798             COLORMAP(cmap);
2799             CARD16(colors);
2800             CARD16(planes);
2801             break;
2802
2803       case 87: /* AllocColorPlanes */
2804             BOOL(contiguous);
2805             REQUEST_LENGTH();
2806             COLORMAP(cmap);
2807             CARD16(colors);
2808             CARD16(reds);
2809             CARD16(greens);
2810             CARD16(blues);
2811             break;
2812
2813       case 88: /* FreeColors */
2814             UNUSED(1);
2815             v16 = REQUEST_LENGTH();
2816             COLORMAP(cmap);
2817             CARD32(plane_mask);
2818             LISTofCARD32(pixels, v16 - 12);
2819             break;
2820
2821       case 89: /* StoreColors */
2822             UNUSED(1);
2823             v16 = REQUEST_LENGTH();
2824             COLORMAP(cmap);
2825             LISTofCOLORITEM(color_items, v16 - 8);
2826             break;
2827
2828       case 90: /* StoreNamedColor */
2829             COLOR_FLAGS(color);
2830             REQUEST_LENGTH();
2831             COLORMAP(cmap);
2832             CARD32(pixel);
2833             v16 = FIELD16(name_length);
2834             UNUSED(2);
2835             STRING8(name, v16);
2836             PAD();
2837             break;
2838
2839       case 91: /* QueryColors */
2840             UNUSED(1);
2841             v16 = REQUEST_LENGTH();
2842             COLORMAP(cmap);
2843             LISTofCARD32(pixels, v16 - 8);
2844             break;
2845
2846       case 92: /* LookupColor */
2847             UNUSED(1);
2848             REQUEST_LENGTH();
2849             COLORMAP(cmap);
2850             v16 = FIELD16(name_length);
2851             UNUSED(2);
2852             STRING8(name, v16);
2853             PAD();
2854             break;
2855
2856       case 93: /* CreateCursor */
2857             UNUSED(1);
2858             REQUEST_LENGTH();
2859             CURSOR(cid);
2860             PIXMAP(source_pixmap);
2861             PIXMAP(mask);
2862             CARD16(fore_red);
2863             CARD16(fore_green);
2864             CARD16(fore_blue);
2865             CARD16(back_red);
2866             CARD16(back_green);
2867             CARD16(back_blue);
2868             CARD16(x);
2869             CARD16(y);
2870             break;
2871
2872       case 94: /* CreateGlyphCursor */
2873             UNUSED(1);
2874             REQUEST_LENGTH();
2875             CURSOR(cid);
2876             FONT(source_font);
2877             FONT(mask_font);
2878             CARD16(source_char);
2879             CARD16(mask_char);
2880             CARD16(fore_red);
2881             CARD16(fore_green);
2882             CARD16(fore_blue);
2883             CARD16(back_red);
2884             CARD16(back_green);
2885             CARD16(back_blue);
2886             break;
2887
2888       case 95: /* FreeCursor */
2889             UNUSED(1);
2890             REQUEST_LENGTH();
2891             CURSOR(cursor);
2892             break;
2893
2894       case 96: /* RecolorCursor */
2895             UNUSED(1);
2896             REQUEST_LENGTH();
2897             CURSOR(cursor);
2898             CARD16(fore_red);
2899             CARD16(fore_green);
2900             CARD16(fore_blue);
2901             CARD16(back_red);
2902             CARD16(back_green);
2903             CARD16(back_blue);
2904             break;
2905
2906       case 97: /* QueryBestSize */
2907             ENUM8(class);
2908             REQUEST_LENGTH();
2909             DRAWABLE(drawable);
2910             CARD16(width);
2911             CARD16(height);
2912             break;
2913
2914       case 98: /* QueryExtension */
2915             UNUSED(1);
2916             REQUEST_LENGTH();
2917             v16 = FIELD16(name_length);
2918             UNUSED(2);
2919             STRING8(name, v16);
2920             PAD();
2921             break;
2922
2923       case 99: /* ListExtensions */
2924             UNUSED(1);
2925             REQUEST_LENGTH();
2926             break;
2927
2928       case 100: /* ChangeKeyboardMapping */
2929             v8 = FIELD8(keycode_count);
2930             REQUEST_LENGTH();
2931             KEYCODE(first_keycode);
2932             v8_2 = FIELD8(keysyms_per_keycode);
2933             UNUSED(2);
2934             LISTofKEYSYM(keysyms, v8, v8_2);
2935             break;
2936
2937       case 101: /* GetKeyboardMapping */
2938             UNUSED(1);
2939             REQUEST_LENGTH();
2940             KEYCODE(first_keycode);
2941             FIELD8(count);
2942             UNUSED(2);
2943             break;
2944
2945       case 102: /* ChangeKeyboardControl */
2946             UNUSED(1);
2947             REQUEST_LENGTH();
2948             BITMASK32(keyboard_value);
2949             BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2950             BITFIELD(INT8, keyboard_value_mask, bell_percent);
2951             BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2952             BITFIELD(INT16, keyboard_value_mask, bell_duration);
2953             BITFIELD(INT16, keyboard_value_mask, led);
2954             BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2955             BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2956             BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2957             ENDBITMASK;
2958             break;
2959
2960       case 103: /* GetKeyboardControl */
2961             UNUSED(1);
2962             REQUEST_LENGTH();
2963             break;
2964
2965       case 104: /* Bell */
2966             INT8(percent);
2967             REQUEST_LENGTH();
2968             break;
2969
2970       case 105: /* ChangePointerControl */
2971             UNUSED(1);
2972             REQUEST_LENGTH();
2973             INT16(acceleration_numerator);
2974             INT16(acceleration_denominator);
2975             INT16(threshold);
2976             BOOL(do_acceleration);
2977             BOOL(do_threshold);
2978             break;
2979
2980       case 106: /* GetPointerControl */
2981             UNUSED(1);
2982             REQUEST_LENGTH();
2983             break;
2984
2985       case 107: /* SetScreenSaver */
2986             UNUSED(1);
2987             REQUEST_LENGTH();
2988             INT16(timeout);
2989             INT16(interval);
2990             ENUM8(prefer_blanking);
2991             ENUM8(allow_exposures);
2992             UNUSED(2);
2993             break;
2994
2995       case 108: /* GetScreenSaver */
2996             UNUSED(1);
2997             REQUEST_LENGTH();
2998             break;
2999
3000       case 109: /* ChangeHosts */
3001             ENUM8(change_host_mode);
3002             REQUEST_LENGTH();
3003             v8 = ENUM8(family);
3004             UNUSED(1);
3005             v16 = CARD16(address_length);
3006             if (v8 == FAMILY_INTERNET && v16 == 4) {
3007                   /*
3008                    * IPv4 addresses.
3009                    * XXX - what about IPv6?  Is that a family of
3010                    * FAMILY_INTERNET (0) with a length of 16?
3011                    */
3012                   LISTofCARD8(ip_address, v16);
3013             } else
3014                   LISTofCARD8(address, v16);
3015             break;
3016
3017       case 110: /* ListHosts */
3018             UNUSED(1);
3019             REQUEST_LENGTH();
3020             break;
3021
3022       case 111: /* SetAccessControl */
3023             ENUM8(access_mode);
3024             REQUEST_LENGTH();
3025             break;
3026
3027       case 112: /* SetCloseDownMode */
3028             ENUM8(close_down_mode);
3029             REQUEST_LENGTH();
3030             break;
3031
3032       case 113: /* KillClient */
3033             UNUSED(1);
3034             REQUEST_LENGTH();
3035             CARD32(resource);
3036             break;
3037
3038       case 114: /* RotateProperties */
3039             UNUSED(1);
3040             v16 = REQUEST_LENGTH();
3041             WINDOW(window);
3042             CARD16(property_number);
3043             INT16(delta);
3044             LISTofATOM(properties, (v16 - 12));
3045             break;
3046
3047       case 115: /* ForceScreenSaver */
3048             ENUM8(screen_saver_mode);
3049             REQUEST_LENGTH();
3050             break;
3051
3052       case 116: /* SetPointerMapping */
3053             v8 = FIELD8(map_length);
3054             REQUEST_LENGTH();
3055             LISTofCARD8(map, v8);
3056             PAD();
3057             break;
3058
3059       case 117: /* GetPointerMapping */
3060             UNUSED(1);
3061             REQUEST_LENGTH();
3062             break;
3063
3064       case 118: /* SetModifierMapping */
3065             v8 = FIELD8(keycodes_per_modifier);
3066             REQUEST_LENGTH();
3067             LISTofKEYCODE(keycodes, v8);
3068             break;
3069
3070       case 119: /* GetModifierMapping */
3071             UNUSED(1);
3072             REQUEST_LENGTH();
3073             break;
3074
3075       case 127: /* NoOperation */
3076             UNUSED(1);
3077             REQUEST_LENGTH();
3078             break;
3079       }
3080       left = tvb_length_remaining(tvb, offset);
3081       if (left)
3082             proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
3083 }
3084
3085 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
3086     proto_tree *tree)
3087 {
3088       volatile int offset = 0;
3089       int length_remaining;
3090       volatile gboolean little_endian;
3091       guint8 opcode;
3092       volatile int plen;
3093       proto_item *ti;
3094       proto_tree *t;
3095       volatile gboolean is_initial_creq;
3096       guint16 auth_proto_len, auth_data_len;
3097       const char *volatile sep = NULL;
3098       conversation_t *conversation;
3099       x11_conv_data_t *volatile state_info;
3100       int length;
3101       tvbuff_t *next_tvb;
3102
3103       while (tvb_reported_length_remaining(tvb, offset) != 0) {
3104             length_remaining = tvb_length_remaining(tvb, offset);
3105
3106             /*
3107              * Can we do reassembly?
3108              */
3109             if (x11_desegment && pinfo->can_desegment) {
3110                   /*
3111                    * Yes - is the X11 request header split across
3112                    * segment boundaries?
3113                    */
3114                   if (length_remaining < 4) {
3115                         /*
3116                          * Yes.  Tell the TCP dissector where the data
3117                          * for this message starts in the data it handed
3118                          * us, and how many more bytes we need, and return.
3119                          */
3120                         pinfo->desegment_offset = offset;
3121                         pinfo->desegment_len = 4 - length_remaining;
3122                         return;
3123                   }
3124             }
3125
3126             /*
3127              * Get the state for this conversation; create the conversation
3128              * if we don't have one, and create the state if we don't have
3129              * any.
3130              */
3131             conversation = find_conversation(&pinfo->src, &pinfo->dst,
3132                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3133             if (conversation == NULL) {
3134                   /*
3135                    * No - create one.
3136                    */
3137                   conversation = conversation_new(&pinfo->src,
3138                         &pinfo->dst, pinfo->ptype, pinfo->srcport,
3139                         pinfo->destport, 0);
3140             }
3141
3142             /*
3143              * Is there state attached to this conversation?
3144              */
3145             state_info = conversation_get_proto_data(conversation, proto_x11);
3146             if (state_info == NULL) {
3147                   /*
3148                    * No - create a state structure and attach it.
3149                    */
3150                   state_info = g_mem_chunk_alloc(x11_state_chunk);
3151                   state_info->opcode = NOTHING_SEEN;    /* nothing seen yet */
3152                   state_info->iconn_frame = 0;  /* don't know it yet */
3153                   state_info->byte_order = BYTE_ORDER_UNKNOWN;  /* don't know it yet */
3154                   conversation_add_proto_data(conversation, proto_x11,
3155                         state_info);
3156             }
3157
3158             /*
3159              * Guess the byte order if we don't already know it.
3160              */
3161             little_endian = guess_byte_ordering(tvb, pinfo, state_info);
3162
3163             /*
3164              * Get the opcode and length of the putative X11 request.
3165              */
3166             opcode = VALUE8(tvb, 0);
3167             plen = VALUE16(tvb, offset + 2);
3168
3169             if (plen == 0) {
3170                   /*
3171                    * This can't be 0, as it includes the header length.
3172                    * A different choice of byte order wouldn't have
3173                    * helped.
3174                    * Give up.
3175                    */
3176                   ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1, FALSE);
3177                   t = proto_item_add_subtree(ti, ett_x11);
3178                   proto_tree_add_text(t, tvb, offset, -1, "Bogus request length (0)");
3179                   return;
3180             }
3181
3182             if (state_info->iconn_frame == pinfo->fd->num ||
3183                 (state_info->opcode == NOTHING_SEEN &&
3184                  (opcode == 'B' || opcode == 'l') &&
3185                  (plen == 11 || plen == 2816))) {
3186                   /*
3187                    * Either
3188                    *
3189                    *    we saw this on the first pass and this is
3190                    *    it again
3191                    *
3192                    * or
3193                    *    we haven't already seen any requests, the first
3194                    *    byte of the message is 'B' or 'l', and the 16-bit
3195                    *    integer 2 bytes into the data stream is either 11
3196                    *    or a byte-swapped 11.
3197                    *
3198                    * This means it's probably an initial connection
3199                    * request, not a message.
3200                    *
3201                    * 'B' is decimal 66, which is the opcode for a
3202                    * PolySegment request; unfortunately, 11 is a valid
3203                    * length for a PolySegment request request, so we
3204                    * might mis-identify that request.  (Are there any
3205                    * other checks we can do?)
3206                    *
3207                    * 'l' is decimal 108, which is the opcode for a
3208                    * GetScreenSaver request; the only valid length
3209                    * for that request is 1.
3210                    */
3211                   is_initial_creq = TRUE;
3212
3213                   /*
3214                    * We now know the byte order.  Override the guess.
3215                    */
3216                   if (state_info->byte_order == BYTE_ORDER_UNKNOWN) {
3217                         if (opcode == 'B') {
3218                               /*
3219                                * Big-endian.
3220                                */
3221                               state_info->byte_order = BYTE_ORDER_BE;
3222                               little_endian = FALSE;
3223                         } else {
3224                               /*
3225                                * Little-endian.
3226                                */
3227                               state_info->byte_order = BYTE_ORDER_LE;
3228                               little_endian = TRUE;
3229                         }
3230                   }
3231
3232                   /*
3233                    * Can we do reassembly?
3234                    */
3235                   if (x11_desegment && pinfo->can_desegment) {
3236                         /*
3237                          * Yes - is the fixed-length portion of the
3238                          * initial connection header split across
3239                          * segment boundaries?
3240                          */
3241                         if (length_remaining < 10) {
3242                               /*
3243                                * Yes.  Tell the TCP dissector where the
3244                                * data for this message starts in the data
3245                                * it handed us, and how many more bytes we
3246                                * need, and return.
3247                                */
3248                               pinfo->desegment_offset = offset;
3249                               pinfo->desegment_len = 10 - length_remaining;
3250                               return;
3251                         }
3252                   }
3253
3254                   /*
3255                    * Get the lengths of the authorization protocol and
3256                    * the authorization data.
3257                    */
3258                   auth_proto_len = VALUE16(tvb, offset + 6);
3259                   auth_data_len = VALUE16(tvb, offset + 8);
3260                   plen = 12 + ROUND_LENGTH(auth_proto_len) +
3261                         ROUND_LENGTH(auth_data_len);
3262             } else {
3263                   /*
3264                    * This is probably an ordinary request.
3265                    */
3266                   is_initial_creq = FALSE;
3267
3268                   /*
3269                    * The length of a request is in 4-byte words.
3270                    */
3271                   plen *= 4;
3272             }
3273
3274             /*
3275              * Can we do reassembly?
3276              */
3277             if (x11_desegment && pinfo->can_desegment) {
3278                   /*
3279                    * Yes - is the X11 request split across segment
3280                    * boundaries?
3281                    */
3282                   if (length_remaining < plen) {
3283                         /*
3284                          * Yes.  Tell the TCP dissector where the data
3285                          * for this message starts in the data it handed
3286                          * us, and how many more bytes we need, and return.
3287                          */
3288                         pinfo->desegment_offset = offset;
3289                         pinfo->desegment_len = plen - length_remaining;
3290                         return;
3291                   }
3292             }
3293
3294             /*
3295              * Construct a tvbuff containing the amount of the payload
3296              * we have available.  Make its reported length the
3297              * amount of data in the X11 request.
3298              *
3299              * XXX - if reassembly isn't enabled. the subdissector
3300              * will throw a BoundsError exception, rather than a
3301              * ReportedBoundsError exception.  We really want a tvbuff
3302              * where the length is "length", the reported length is "plen",
3303              * and the "if the snapshot length were infinite" length is the
3304              * minimum of the reported length of the tvbuff handed to us
3305              * and "plen", with a new type of exception thrown if the offset
3306              * is within the reported length but beyond that third length,
3307              * with that exception getting the "Unreassembled Packet" error.
3308              */
3309             length = length_remaining;
3310             if (length > plen)
3311                   length = plen;
3312             next_tvb = tvb_new_subset(tvb, offset, length, plen);
3313
3314             /*
3315              * Set the column appropriately.
3316              */
3317             if (is_initial_creq) {
3318                   if (check_col(pinfo->cinfo, COL_INFO))
3319                         col_set_str(pinfo->cinfo, COL_INFO, "Initial connection request");
3320             } else {
3321                   if (sep == NULL) {
3322                         /*
3323                          * We haven't set the column yet; set it.
3324                          */
3325                         if (check_col(pinfo->cinfo, COL_INFO))
3326                               col_add_str(pinfo->cinfo, COL_INFO, "Requests");
3327
3328                         /*
3329                          * Initialize the separator.
3330                          */
3331                         sep = ":";
3332                   }
3333             }
3334
3335             /*
3336              * Dissect the X11 request.
3337              *
3338              * Catch the ReportedBoundsError exception; if this
3339              * particular message happens to get a ReportedBoundsError
3340              * exception, that doesn't mean that we should stop
3341              * dissecting X11 requests within this frame or chunk of
3342              * reassembled data.
3343              *
3344              * If it gets a BoundsError, we can stop, as there's nothing
3345              * more to see, so we just re-throw it.
3346              */
3347             TRY {
3348                   if (is_initial_creq) {
3349                         dissect_x11_initial_conn(next_tvb, pinfo, tree,
3350                             state_info, little_endian);
3351                   } else {
3352                         dissect_x11_request(next_tvb, pinfo, tree, sep,
3353                             state_info, little_endian);
3354                   }
3355             }
3356             CATCH(BoundsError) {
3357                   RETHROW;
3358             }
3359             CATCH(ReportedBoundsError) {
3360                   show_reported_bounds_error(tvb, pinfo, tree);
3361             }
3362             ENDTRY;
3363
3364             /*
3365              * Skip the X11 message.
3366              */
3367             offset += plen;
3368
3369             sep = ",";
3370       }
3371 }
3372
3373 static void
3374 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3375 {
3376 /* Set up structures we will need to add the protocol subtree and manage it */
3377       proto_item *ti;
3378       proto_tree *x11_tree;
3379
3380 /* This field shows up as the "Info" column in the display; you should make
3381    it, if possible, summarize what's in the packet, so that a user looking
3382    at the list of packets can tell what type of packet it is. */
3383       if (check_col(pinfo->cinfo, COL_INFO))
3384             col_set_str(pinfo->cinfo, COL_INFO, "Replies/events");
3385
3386 /* In the interest of speed, if "tree" is NULL, don't do any work not
3387    necessary to generate protocol tree items. */
3388       if (!tree) return;
3389       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
3390       x11_tree = proto_item_add_subtree(ti, ett_x11);
3391
3392       /*
3393        * XXX - dissect these in a loop, like the requests.
3394        */
3395       call_dissector(data_handle,tvb, pinfo, x11_tree);
3396 }
3397
3398 /************************************************************************
3399  ***                                                                  ***
3400  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
3401  ***                                                                  ***
3402  ************************************************************************/
3403
3404 static void
3405 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3406 {
3407       if (check_col(pinfo->cinfo, COL_PROTOCOL))
3408             col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
3409
3410       if (pinfo->match_port == pinfo->destport)
3411             dissect_x11_requests(tvb, pinfo, tree);
3412       else
3413             dissect_x11_replies(tvb, pinfo, tree);
3414 }
3415
3416 /* Register the protocol with Ethereal */
3417 void proto_register_x11(void)
3418 {
3419
3420 /* Setup list of header fields */
3421       static hf_register_info hf[] = {
3422 /*
3423   { &hf_x11_FIELDABBREV,
3424   { "FIELDNAME",           "x11.FIELDABBREV",
3425   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
3426   "FIELDDESCR", HFILL }
3427   },
3428 */
3429 #include "x11-register-info.h"
3430       };
3431
3432 /* Setup protocol subtree array */
3433       static gint *ett[] = {
3434             &ett_x11,
3435             &ett_x11_color_flags,
3436             &ett_x11_list_of_arc,
3437             &ett_x11_arc,
3438             &ett_x11_list_of_atom,
3439             &ett_x11_list_of_card32,
3440             &ett_x11_list_of_color_item,
3441             &ett_x11_color_item,
3442             &ett_x11_list_of_keycode,
3443             &ett_x11_list_of_keysyms,
3444             &ett_x11_keysym,
3445             &ett_x11_list_of_point,
3446             &ett_x11_point,
3447             &ett_x11_list_of_rectangle,
3448             &ett_x11_rectangle,
3449             &ett_x11_list_of_segment,
3450             &ett_x11_segment,
3451             &ett_x11_list_of_string8,
3452             &ett_x11_list_of_text_item,
3453             &ett_x11_text_item,
3454             &ett_x11_gc_value_mask,
3455             &ett_x11_event_mask,
3456             &ett_x11_do_not_propagate_mask,
3457             &ett_x11_set_of_key_mask,
3458             &ett_x11_pointer_event_mask,
3459             &ett_x11_window_value_mask,
3460             &ett_x11_configure_window_mask,
3461             &ett_x11_keyboard_value_mask,
3462       };
3463       module_t *x11_module;
3464
3465 /* Register the protocol name and description */
3466       proto_x11 = proto_register_protocol("X11", "X11", "x11");
3467
3468 /* Required function calls to register the header fields and subtrees used */
3469       proto_register_field_array(proto_x11, hf, array_length(hf));
3470       proto_register_subtree_array(ett, array_length(ett));
3471
3472       register_init_routine(x11_init_protocol);
3473
3474       x11_module = prefs_register_protocol(proto_x11, NULL);
3475       prefs_register_bool_preference(x11_module, "desegment",
3476             "Desegment all X11 messages spanning multiple TCP segments",
3477             "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
3478             &x11_desegment);
3479 }
3480
3481 void
3482 proto_reg_handoff_x11(void)
3483 {
3484   dissector_handle_t x11_handle;
3485
3486   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
3487   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
3488   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
3489   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
3490   data_handle = find_dissector("data");
3491 }