2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
5 * $Id: packet-x11.c,v 1.32 2002/04/11 09:38:03 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * Copied from README.developer
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.
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.
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.
28 /* TODO (in no particular order):
30 * - keep track of Atom creation by server to be able to display non predefined atoms
31 * - Idem for keysym <-> keycode ???
33 * - Subtree the request ids (that is x11.create-window.window and x11.change-window.window should be
34 * distinct), and add hidden fields (so we still have x11.window).
35 * - add hidden fields so we can have x11.circulate-window in addition to x11.opcode == 13
36 * - add hidden fields so we have x11.listOfStuff.length
37 * - use a faster scheme that linear list searching for the opcode.
38 * - correct display of unicode chars.
39 * - Not everything is homogeneous, in particular the handling of items in list is a total mess.
42 /* By the way, I wrote a program to generate every request and test
43 * that stuff. If you're interested, you can get it at
44 * http://tronche.com/gui/x/
56 #ifdef HAVE_SYS_TYPES_H
57 # include <sys/types.h>
62 #include <epan/packet.h>
64 #define cVALS(x) (const value_string*)(x)
66 /* Initialize the protocol and registered fields */
67 static int proto_x11 = -1;
69 #include "x11-declarations.h"
71 /* Initialize the subtree pointers */
72 static gint ett_x11 = -1;
73 static gint ett_x11_request = -1;
74 static gint ett_x11_color_flags = -1;
75 static gint ett_x11_list_of_arc = -1;
76 static gint ett_x11_arc = -1;
77 static gint ett_x11_list_of_atom = -1;
78 static gint ett_x11_list_of_card32 = -1;
79 static gint ett_x11_list_of_color_item = -1;
80 static gint ett_x11_color_item = -1;
81 static gint ett_x11_list_of_keycode = -1;
82 static gint ett_x11_list_of_keysyms = -1;
83 static gint ett_x11_keysym = -1;
84 static gint ett_x11_list_of_point = -1;
85 static gint ett_x11_point = -1;
86 static gint ett_x11_list_of_rectangle = -1;
87 static gint ett_x11_rectangle = -1;
88 static gint ett_x11_list_of_segment = -1;
89 static gint ett_x11_segment = -1;
90 static gint ett_x11_list_of_string8 = -1;
91 static gint ett_x11_list_of_text_item = -1;
92 static gint ett_x11_text_item = -1;
93 static gint ett_x11_gc_value_mask = -1;
94 static gint ett_x11_event_mask = -1;
95 static gint ett_x11_do_not_propagate_mask = -1;
96 static gint ett_x11_set_of_key_mask = -1;
97 static gint ett_x11_pointer_event_mask = -1;
98 static gint ett_x11_window_value_mask = -1;
99 static gint ett_x11_configure_window_mask = -1;
100 static gint ett_x11_keyboard_value_mask = -1;
102 static dissector_handle_t data_handle;
104 #define TCP_PORT_X11 6000
105 #define TCP_PORT_X11_2 6001
106 #define TCP_PORT_X11_3 6002
108 /************************************************************************
110 *** E N U M T A B L E S D E F I N I T I O N S ***
112 ************************************************************************/
114 static const value_string access_mode_vals[] = {
120 static const value_string all_temporary_vals[] = {
121 { 0, "AllTemporary" },
125 static const value_string alloc_vals[] = {
131 static const value_string allow_events_mode_vals[] = {
132 { 0, "AsyncPointer" },
133 { 1, "SyncPointer" },
134 { 2, "ReplayPointer" },
135 { 3, "AsyncKeyboard" },
136 { 4, "SyncKeyboard" },
137 { 5, "ReplayKeyboard" },
143 static const value_string arc_mode_vals[] = {
149 static const char *atom_predefined_interpretation[] = {
201 "UNDERLINE_POSITION",
202 "UNDERLINE_THICKNESS",
221 static const value_string auto_repeat_mode_vals[] = {
228 static const value_string background_pixmap_vals[] = {
230 { 1, "ParentRelative" },
234 static const value_string backing_store_vals[] = {
241 static const value_string border_pixmap_vals[] = {
242 { 0, "CopyFromParent" },
246 static const value_string button_vals[] = {
247 { 0x8000, "AnyButton" },
251 static const value_string cap_style_vals[] = {
259 static const value_string class_vals[] = {
266 static const value_string close_down_mode_vals[] = {
268 { 1, "RetainPermanent" },
269 { 2, "RetainTemporary" },
273 static const value_string coordinate_mode_vals[] = {
279 static const value_string direction_vals[] = {
280 { 0, "RaiseLowest" },
281 { 1, "LowerHighest" },
285 static const value_string family_vals[] = {
292 static const value_string fill_rule_vals[] = {
298 static const value_string fill_style_vals[] = {
302 { 3, "OpaqueStippled" },
306 static const value_string focus_vals[] = {
308 { 1, "PointerRoot" },
312 static const value_string function_vals[] = {
317 { 4, "AndInverted" },
325 { 12, "CopyInverted" },
326 { 13, "OrInverted" },
332 static const value_string gravity_vals[] = {
346 static const value_string image_format_vals[] = {
353 static const value_string image_pixmap_format_vals[] = {
359 static const value_string join_style_vals[] = {
366 static const value_string key_vals[] = {
371 #include "packet-x11-keysym.h"
373 static const value_string line_style_vals[] = {
380 static const value_string mode_vals[] = {
387 static const value_string on_off_vals[] = {
393 static const value_string opcode_vals[] = {
394 { 1, "CreateWindow" },
395 { 2, "ChangeWindowAttributes" },
396 { 3, "GetWindowAttributes" },
397 { 4, "DestroyWindow" },
398 { 5, "DestroySubwindows" },
399 { 6, "ChangeSaveSet" },
400 { 7, "ReparentWindow" },
402 { 9, "MapSubwindows" },
403 { 10, "UnmapWindow" },
404 { 11, "UnmapSubwindows" },
405 { 12, "ConfigureWindow" },
406 { 13, "CirculateWindow" },
407 { 14, "GetGeometry" },
409 { 16, "InternAtom" },
410 { 17, "GetAtomName" },
411 { 18, "ChangeProperty" },
412 { 19, "DeleteProperty" },
413 { 20, "GetProperty" },
414 { 21, "ListProperties" },
415 { 22, "SetSelectionOwner" },
416 { 23, "GetSelectionOwner" },
417 { 24, "ConvertSelection" },
419 { 26, "GrabPointer" },
420 { 27, "UngrabPointer" },
421 { 28, "GrabButton" },
422 { 29, "UngrabButton" },
423 { 30, "ChangeActivePointerGrab" },
424 { 31, "GrabKeyboard" },
425 { 32, "UngrabKeyboard" },
428 { 35, "AllowEvents" },
429 { 36, "GrabServer" },
430 { 37, "UngrabServer" },
431 { 38, "QueryPointer" },
432 { 39, "GetMotionEvents" },
433 { 40, "TranslateCoordinates" },
434 { 41, "WarpPointer" },
435 { 42, "SetInputFocus" },
436 { 43, "GetInputFocus" },
437 { 44, "QueryKeymap" },
441 { 48, "QueryTextExtents" },
443 { 50, "ListFontsWithInfo" },
444 { 51, "SetFontPath" },
445 { 52, "GetFontPath" },
446 { 53, "CreatePixmap" },
447 { 54, "FreePixmap" },
452 { 59, "SetClipRectangles" },
459 { 66, "PolySegment" },
460 { 67, "PolyRectangle" },
463 { 70, "PolyFillRectangle" },
464 { 71, "PolyFillArc" },
468 { 75, "PolyText16" },
469 { 76, "ImageText8" },
470 { 77, "ImageText16" },
471 { 78, "CreateColormap" },
472 { 79, "FreeColormap" },
473 { 80, "CopyColormapAndFree" },
474 { 81, "InstallColormap" },
475 { 82, "UninstallColormap" },
476 { 83, "ListInstalledColormaps" },
477 { 84, "AllocColor" },
478 { 85, "AllocNamedColor" },
479 { 86, "AllocColorCells" },
480 { 87, "AllocColorPlanes" },
481 { 88, "FreeColors" },
482 { 89, "StoreColors" },
483 { 90, "StoreNamedColor" },
484 { 91, "QueryColors" },
485 { 92, "LookupColor" },
486 { 93, "CreateCursor" },
487 { 94, "CreateGlyphCursor" },
488 { 95, "FreeCursor" },
489 { 96, "RecolorCursor" },
490 { 97, "QueryBestSize" },
491 { 98, "QueryExtension" },
492 { 99, "ListExtensions" },
493 { 100, "ChangeKeyboardMapping" },
494 { 101, "GetKeyboardMapping" },
495 { 102, "ChangeKeyboardControl" },
496 { 103, "GetKeyboardControl" },
498 { 105, "ChangePointerControl" },
499 { 106, "GetPointerControl" },
500 { 107, "SetScreenSaver" },
501 { 108, "GetScreenSaver" },
502 { 109, "ChangeHosts" },
503 { 110, "ListHosts" },
504 { 111, "SetAccessControl" },
505 { 112, "SetCloseDownMode" },
506 { 113, "KillClient" },
507 { 114, "RotateProperties" },
508 { 115, "ForceScreenSaver" },
509 { 116, "SetPointerMapping" },
510 { 117, "GetPointerMapping" },
511 { 118, "SetModifierMapping" },
512 { 119, "GetModifierMapping" },
513 { 127, "NoOperation" },
517 static const value_string ordering_vals[] = {
525 static const value_string plane_mask_vals[] = {
526 { 0xFFFFFFFF, "AllPlanes" },
530 static const value_string pointer_keyboard_mode_vals[] = {
531 { 0, "Synchronous" },
532 { 1, "Asynchronous" },
536 static const value_string revert_to_vals[] = {
538 { 1, "PointerRoot" },
543 static const value_string insert_delete_vals[] = {
549 static const value_string screen_saver_mode_vals[] = {
555 static const value_string shape_vals[] = {
562 static const value_string stack_mode_vals[] = {
571 static const value_string subwindow_mode_vals[] = {
572 { 0, "ClipByChildren" },
573 { 1, "IncludeInferiors" },
577 static const value_string window_class_vals[] = {
578 { 0, "CopyFromParent" },
579 { 1, "InputOutput" },
584 static const value_string yes_no_default_vals[] = {
591 static const value_string zero_is_any_property_type_vals[] = {
592 { 0, "AnyPropertyType" },
596 static const value_string zero_is_none_vals[] = {
601 /************************************************************************
603 *** G L O B A L V A R I A B L E S ( A R G H H ! ) ***
605 ************************************************************************/
607 static int cur_offset; /* The current offset in the frame */
608 static int next_offset = 0; /* Offset of the next request in the frame */
609 static gboolean little_endian = TRUE;
611 static struct maskStruct {
616 } lastMask = { 0, 0, 0, NULL };
618 /************************************************************************
620 *** F I E L D D E C O D I N G M A C R O S ***
622 ************************************************************************/
624 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
625 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
626 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
628 #define FIELD8(name) (field8(tvb, t, hf_x11_##name))
629 #define FIELD16(name) (field16(tvb, t, hf_x11_##name))
630 #define FIELD32(name) (field32(tvb, t, hf_x11_##name))
632 #define BITFIELD(TYPE, position, name) {\
633 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
635 int save = cur_offset;\
636 proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
637 lastMask._zone, little_endian); \
639 unused = save + 4 - cur_offset;\
641 proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
642 cur_offset = save + 4;\
646 #define FLAG(position, name) {\
647 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
648 proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
650 #define ATOM(name) { atom(tvb, t, hf_x11_##name); }
651 #define BITGRAVITY(name) { gravity(tvb, t, #name, hf_x11_##name, "Forget"); }
652 #define BITMASK8(name) { bitmask(tvb, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 1); }
653 #define BITMASK16(name) { bitmask(tvb, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 2); }
654 #define BITMASK32(name) { bitmask(tvb, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 4); }
655 #define BOOL(name) (add_boolean(tvb, t, hf_x11_##name))
656 #define BUTTON(name) { FIELD8(name); }
657 #define CARD8(name) { FIELD8(name); }
658 #define CARD16(name) (FIELD16(name))
659 #define CARD32(name) (FIELD32(name))
660 #define COLOR_FLAGS(name) { colorFlags(tvb, t); }
661 #define COLORMAP(name) { FIELD32(name); }
662 #define CURSOR(name) { FIELD32(name); }
663 #define DRAWABLE(name) { FIELD32(name); }
664 #define ENUM8(name) { FIELD8(name); }
665 #define ENUM16(name) { FIELD16(name); }
666 #define FONT(name) { FIELD32(name); }
667 #define FONTABLE(name) { FIELD32(name); }
668 #define GCONTEXT(name) { FIELD32(name); }
669 #define INT8(name) { FIELD8(name); }
670 #define INT16(name) { FIELD16(name); }
671 #define KEYCODE(name) { FIELD8(name); }
672 #define LISTofARC(name) { listOfArc(tvb, t, hf_x11_##name, (next_offset - cur_offset) / 12); }
673 #define LISTofATOM(name, length) { listOfAtom(tvb, t, hf_x11_##name, (length) / 4); }
674 #define LISTofBYTE(name, length) { listOfByte(tvb, t, hf_x11_##name, (length)); }
675 #define LISTofCARD8(name, length) { listOfByte(tvb, t, hf_x11_##name, (length)); }
676 #define LISTofCARD32(name, length) { listOfCard32(tvb, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
677 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, t, hf_x11_##name, (length) / 12); }
678 #define LISTofKEYCODE(name, length) { listOfKeycode(tvb, t, hf_x11_##name, (length)); }
679 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
680 listOfKeysyms(tvb, t, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
681 #define LISTofPOINT(name, length) { listOfPoint(tvb, t, hf_x11_##name, (length) / 4); }
682 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, t, hf_x11_##name, (next_offset - cur_offset) / 8); }
683 #define LISTofSEGMENT(name) { listOfSegment(tvb, t, hf_x11_##name, (next_offset - cur_offset) / 8); }
684 #define LISTofSTRING8(name, length) { listOfString8(tvb, t, hf_x11_##name, hf_x11_##name##_string, (length)); }
685 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, t, hf_x11_##name, FALSE); }
686 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, t, hf_x11_##name, TRUE); }
687 #define OPCODE() { opcode = FIELD8(opcode); }
688 #define PIXMAP(name) { FIELD32(name); }
689 #define REQUEST_LENGTH() (requestLength(tvb, t))
690 #define SETofEVENT(name) { setOfEvent(tvb, t); }
691 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, t);}
692 #define SETofKEYMASK(name) { setOfKeyMask(tvb, t); }
693 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, t); }
694 #define STRING8(name, length) { string8(tvb, t, #name, hf_x11_##name, length); }
695 #define STRING16(name, length) { string16(tvb, t, hf_x11_##name, hf_x11_##name##_bytes, length); }
696 #define TIMESTAMP(name){ timestamp(tvb, t, #name, hf_x11_##name); }
697 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, x, little_endian); p += x; }
698 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, x, little_endian); cur_offset += x; }
699 #define PAD() { if (next_offset - cur_offset > 0) proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, next_offset - cur_offset, little_endian); cur_offset = next_offset; }
700 #define WINDOW(name) { FIELD32(name); }
701 #define WINGRAVITY(name) { gravity(tvb, t, #name, hf_x11_##name, "Unmap"); }
703 #define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
704 proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
705 v ? "" : " (CopyFromParent)"); cur_offset += 4; }
707 /************************************************************************
709 *** D E C O D I N G F I E L D S ***
711 ************************************************************************/
713 static void atom(tvbuff_t *tvb, proto_tree *t, int hf)
715 const char *interpretation = NULL;
717 guint32 v = VALUE32(tvb, cur_offset);
718 if (v >= 1 && v < array_length(atom_predefined_interpretation))
719 interpretation = atom_predefined_interpretation[v];
721 interpretation = "Not a predefined atom";
723 header_field_info *hfi = proto_registrar_get_nth(hf);
725 interpretation = match_strval(v, cVALS(hfi -> strings));
727 if (!interpretation) interpretation = "error in Xlib client program ?";
728 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %u (%s)",
729 proto_registrar_get_nth(hf) -> name, v, interpretation);
733 static void bitmask(tvbuff_t *tvb, proto_tree *t, int hf, int ett, int size)
737 lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
738 lastMask._offset = cur_offset;
739 lastMask._zone = size;
740 ti = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
741 lastMask._tree = proto_item_add_subtree(ti, ett);
745 static guint32 add_boolean(tvbuff_t *tvb, proto_tree *t, int hf)
747 guint32 v = VALUE8(tvb, cur_offset);
748 proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
753 static void colorFlags(tvbuff_t *tvb, proto_tree *t)
755 unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
759 if (do_red_green_blue) {
762 char *bp = buffer + sprintf(buffer, "flags: ");
764 if (do_red_green_blue & 0x1) {
765 bp += sprintf(bp, "DoRed");
769 if (do_red_green_blue & 0x2) {
770 if (sep) bp += sprintf(bp, " | ");
771 bp += sprintf(bp, "DoGreen");
775 if (do_red_green_blue & 0x4) {
776 if (sep) bp += sprintf(bp, " | ");
777 bp += sprintf(bp, "DoBlue");
781 if (do_red_green_blue & 0xf8) {
782 if (sep) bp += sprintf(bp, " + ");
783 sprintf(bp, "trash");
786 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
788 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
789 if (do_red_green_blue & 0x1)
790 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1,
791 do_red_green_blue & 0x1);
792 if (do_red_green_blue & 0x2)
793 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1,
794 do_red_green_blue & 0x2);
795 if (do_red_green_blue & 0x4)
796 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1,
797 do_red_green_blue & 0x4);
798 if (do_red_green_blue & 0xf8)
799 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1,
800 do_red_green_blue & 0xf8);
802 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
807 static void gravity(tvbuff_t *tvb, proto_tree *t, const char *nameAsChar,
808 int hf, const char *nullInterpretation)
810 guint8 v = VALUE8(tvb, cur_offset);
812 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar,
815 proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
819 static void listOfArc(tvbuff_t *tvb, proto_tree *t, int hf, int length)
821 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
822 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
824 gint16 x = VALUE16(tvb, cur_offset);
825 gint16 y = VALUE16(tvb, cur_offset + 2);
826 guint16 width = VALUE16(tvb, cur_offset + 4);
827 guint16 height = VALUE16(tvb, cur_offset + 6);
828 gint16 angle1 = VALUE16(tvb, cur_offset + 8);
829 gint16 angle2 = VALUE16(tvb, cur_offset + 10);
831 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, cur_offset, 12,
832 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
833 width, height, x, y, angle1, angle2,
834 angle1 / 64.0, angle2 / 64.0);
835 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
836 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
837 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
838 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
839 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
840 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
841 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
845 static void listOfAtom(tvbuff_t *tvb, proto_tree *t, int hf, int length)
847 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
848 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
850 if (cur_offset + 4 > next_offset) {
851 /* List runs past end of message. */
854 atom(tvb, tt, hf_x11_properties_item);
858 static void listOfByte(tvbuff_t *tvb, proto_tree *t, int hf, int length)
860 if (cur_offset + length > next_offset) {
861 /* List runs past end of message. */
862 length = next_offset - cur_offset;
864 if (length <= 0) length = 1;
865 proto_tree_add_item(t, hf, tvb, cur_offset, length, little_endian);
866 cur_offset += length;
869 static void listOfCard32(tvbuff_t *tvb, proto_tree *t, int hf, int hf_item,
872 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
873 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
875 if (cur_offset + 4 > next_offset) {
876 /* List runs past end of message. */
879 proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
884 static void listOfColorItem(tvbuff_t *tvb, proto_tree *t, int hf, int length)
886 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
887 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
891 unsigned do_red_green_blue;
892 guint16 red, green, blue;
897 if (cur_offset + 12 > next_offset) {
898 /* List runs past end of message. */
901 red = VALUE16(tvb, cur_offset + 4);
902 green = VALUE16(tvb, cur_offset + 6);
903 blue = VALUE16(tvb, cur_offset + 8);
904 do_red_green_blue = VALUE8(tvb, cur_offset + 10);
906 bp = buffer + sprintf(buffer, "colorItem: ");
908 if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
909 if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
910 if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
912 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
913 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
914 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
915 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
916 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
917 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
918 colorFlags(tvb, ttt);
919 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
923 static GTree *keysymTable = NULL;
925 static gint compareGuint32(gconstpointer a, gconstpointer b)
927 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
930 static const char *keysymString(guint32 v)
935 /* This table is so big that we built it only if necessary */
937 const value_string *p = keysym_vals_source;
938 keysymTable = g_tree_new(compareGuint32);
939 for(; p -> strptr; p++)
940 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
942 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
943 return res ? res : "Unknown";
946 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
948 static void listOfKeycode(tvbuff_t *tvb, proto_tree *t, int hf, int length)
951 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
952 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
959 if (cur_offset + 8 > next_offset) {
960 /* List runs past end of message. */
963 for(i = 8, m = modifiers; i; i--, m++) {
964 u_char c = tvb_get_guint8(tvb, cur_offset);
966 if (c) bp += sprintf(bp, " %s=%d", *m, c);
969 proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, cur_offset - 8, 8, tvb_get_ptr(tvb, cur_offset - 8, 8), "item: %s", buffer);
973 static void listOfKeysyms(tvbuff_t *tvb, proto_tree *t, int hf, int hf_item,
974 int keycode_count, int keysyms_per_keycode)
976 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
977 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
984 while(keycode_count--) {
985 if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
986 /* List runs past end of message. */
989 bp = buffer + sprintf(buffer, "keysyms:");
990 for(i = 0; i < keysyms_per_keycode; i++) {
991 bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
994 tti = proto_tree_add_none_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
996 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
997 for(i = keysyms_per_keycode; i; i--) {
998 guint32 v = VALUE32(tvb, cur_offset);
999 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
1000 "keysym: 0x%08x (%s)", v, keysymString(v));
1006 static void listOfPoint(tvbuff_t *tvb, proto_tree *t, int hf, int length)
1008 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
1009 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1015 if (cur_offset + 4 > next_offset) {
1016 /* List runs past end of message. */
1019 x = VALUE16(tvb, cur_offset);
1020 y = VALUE16(tvb, cur_offset + 2);
1022 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
1023 ttt = proto_item_add_subtree(tti, ett_x11_point);
1024 proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
1025 proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
1029 static void listOfRectangle(tvbuff_t *tvb, proto_tree *t, int hf, int length)
1031 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1032 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1035 unsigned width, height;
1039 if (cur_offset + 8 > next_offset) {
1040 /* List runs past end of message. */
1043 x = VALUE16(tvb, cur_offset);
1044 y = VALUE16(tvb, cur_offset + 2);
1045 width = VALUE16(tvb, cur_offset + 4);
1046 height = VALUE16(tvb, cur_offset + 6);
1048 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, cur_offset, 8,
1049 "rectangle: %dx%d+%d+%d", width, height, x, y);
1050 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1051 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
1052 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
1053 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
1054 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
1058 static void listOfSegment(tvbuff_t *tvb, proto_tree *t, int hf, int length)
1060 proto_item *ti = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1061 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1063 gint16 x1, y1, x2, y2;
1067 if (cur_offset + 8 > next_offset) {
1068 /* List runs past end of message. */
1071 x1 = VALUE16(tvb, cur_offset);
1072 y1 = VALUE16(tvb, cur_offset + 2);
1073 x2 = VALUE16(tvb, cur_offset + 4);
1074 y2 = VALUE16(tvb, cur_offset + 6);
1076 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, cur_offset, 8,
1077 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1078 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1079 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1080 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1081 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1082 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1086 /* XXX - the protocol tree code should handle non-printable characters.
1087 Note that "non-printable characters" may depend on your locale.... */
1088 static void stringCopy(char *dest, const char *source, int length)
1093 if (!isgraph(c) && c != ' ') c = '.';
1099 static void listOfString8(tvbuff_t *tvb, proto_tree *t, int hf, int hf_item,
1103 guint allocated = 0;
1108 /* Compute total length */
1110 int scanning_offset = cur_offset; /* Scanning pointer */
1112 for(i = length; i; i--) {
1113 l = tvb_get_guint8(tvb, scanning_offset);
1114 scanning_offset += 1 + l;
1117 ti = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1118 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1121 unsigned l = VALUE8(tvb, cur_offset);
1122 if (allocated < (l + 1)) {
1123 /* g_realloc doesn't work ??? */
1125 s = g_malloc(l + 1);
1128 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1129 proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
1130 cur_offset += l + 1;
1135 #define STRING16_MAX_DISPLAYED_LENGTH 150
1137 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1139 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1140 for(; length > 0; cur_offset += 2, length--) {
1141 if (tvb_get_guint8(tvb, cur_offset))
1147 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1149 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1150 int hf, int hf_bytes,
1151 int offset, unsigned length,
1152 char **s, int *sLength)
1154 int truncated = FALSE;
1155 unsigned l = length / 2;
1157 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1159 int soffset = offset;
1161 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1163 l = STRING16_MAX_DISPLAYED_LENGTH;
1165 if (*sLength < (int) l + 3) {
1167 *s = g_malloc(l + 3);
1172 if (truncated) l -= 3;
1176 *dp++ = tvb_get_guint8(tvb, soffset);
1181 /* If truncated, add an ellipsis */
1182 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1185 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1186 proto_registrar_get_nth(hf) -> name, *s);
1188 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1192 static void listOfTextItem(tvbuff_t *tvb, proto_tree *t, int hf, int sizeIs16)
1200 /* Compute total length */
1202 int scanning_offset = cur_offset; /* Scanning pointer */
1203 int l; /* Length of an individual item */
1204 int n = 0; /* Number of items */
1206 while(scanning_offset < next_offset) {
1207 l = tvb_get_guint8(tvb, scanning_offset);
1211 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1214 ti = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1215 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
1218 unsigned l = VALUE8(tvb, cur_offset);
1219 if (l == 255) { /* Item is a font */
1220 fid = tvb_get_ntohl(tvb, cur_offset + 1);
1221 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
1223 } else { /* Item is a string */
1226 gint8 delta = VALUE8(tvb, cur_offset + 1);
1227 if (sizeIs16) l += l;
1228 if ((unsigned) allocated < l + 1) {
1229 /* g_realloc doesn't work ??? */
1231 s = g_malloc(l + 1);
1234 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
1235 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
1236 "textitem (string): delta = %d, \"%s\"",
1238 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
1239 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
1241 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
1242 hf_x11_textitem_string_string16_bytes,
1246 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
1247 cur_offset + 2, l, s, "\"%s\"", s);
1248 cur_offset += l + 2;
1254 static guint32 field8(tvbuff_t *tvb, proto_tree *t, int hf)
1256 guint32 v = VALUE8(tvb, cur_offset);
1257 header_field_info *hfi = proto_registrar_get_nth(hf);
1258 gchar *enumValue = NULL;
1259 gchar *nameAsChar = hfi -> name;
1262 enumValue = match_strval(v, cVALS(hfi -> strings));
1264 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
1266 proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
1271 static guint32 field16(tvbuff_t *tvb, proto_tree *t, int hf)
1273 guint32 v = VALUE16(tvb, cur_offset);
1274 proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
1279 static guint32 field32(tvbuff_t *tvb, proto_tree *t, int hf)
1281 guint32 v = VALUE32(tvb, cur_offset);
1282 header_field_info *hfi = proto_registrar_get_nth(hf);
1283 gchar *enumValue = NULL;
1284 gchar *nameAsChar = hfi -> name;
1287 enumValue = match_strval(v, cVALS(hfi -> strings));
1289 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1291 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v,
1292 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1298 static void gcAttributes(tvbuff_t *tvb, proto_tree *t)
1300 BITMASK32(gc_value);
1301 BITFIELD(ENUM8, gc_value_mask, function);
1302 BITFIELD(CARD32, gc_value_mask, plane_mask);
1303 BITFIELD(CARD32, gc_value_mask, foreground);
1304 BITFIELD(CARD32, gc_value_mask, background);
1305 BITFIELD(CARD16, gc_value_mask, line_width);
1306 BITFIELD(ENUM8, gc_value_mask, line_style);
1307 BITFIELD(ENUM8, gc_value_mask, cap_style);
1308 BITFIELD(ENUM8, gc_value_mask, join_style);
1309 BITFIELD(ENUM8, gc_value_mask, fill_style);
1310 BITFIELD(ENUM8, gc_value_mask, fill_rule);
1311 BITFIELD(PIXMAP, gc_value_mask, tile);
1312 BITFIELD(PIXMAP, gc_value_mask, stipple);
1313 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
1314 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
1315 BITFIELD(FONT, gc_value_mask, font);
1316 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
1317 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
1318 BITFIELD(INT16, gc_value_mask, clip_x_origin);
1319 BITFIELD(INT16, gc_value_mask, clip_y_origin);
1320 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1321 BITFIELD(CARD16, gc_value_mask, dash_offset);
1322 BITFIELD(CARD8, gc_value_mask, gc_dashes);
1323 BITFIELD(ENUM8, gc_value_mask, arc_mode);
1326 static void gcMask(tvbuff_t *tvb, proto_tree *t)
1328 BITMASK32(gc_value);
1329 FLAG(gc_value, function);
1330 FLAG(gc_value, plane_mask);
1331 FLAG(gc_value, foreground);
1332 FLAG(gc_value, background);
1333 FLAG(gc_value, line_width);
1334 FLAG(gc_value, line_style);
1335 FLAG(gc_value, cap_style);
1336 FLAG(gc_value, join_style);
1337 FLAG(gc_value, fill_style);
1338 FLAG(gc_value, fill_rule);
1339 FLAG(gc_value, tile);
1340 FLAG(gc_value, stipple);
1341 FLAG(gc_value, tile_stipple_x_origin);
1342 FLAG(gc_value, tile_stipple_y_origin);
1343 FLAG(gc_value, font);
1344 FLAG(gc_value, subwindow_mode);
1345 FLAG(gc_value, graphics_exposures);
1346 FLAG(gc_value, clip_x_origin);
1347 FLAG(gc_value, clip_y_origin);
1348 FLAG(gc_value, clip_mask);
1349 FLAG(gc_value, dash_offset);
1350 FLAG(gc_value, gc_dashes);
1351 FLAG(gc_value, arc_mode);
1354 static guint32 requestLength(tvbuff_t *tvb, proto_tree *t)
1356 guint32 res = VALUE16(tvb, cur_offset) * 4;
1357 proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
1362 static void setOfEvent(tvbuff_t *tvb, proto_tree *t)
1364 struct maskStruct save = lastMask;
1366 FLAG(event, KeyPress);
1367 FLAG(event, KeyRelease);
1368 FLAG(event, ButtonPress);
1369 FLAG(event, ButtonRelease);
1370 FLAG(event, EnterWindow);
1371 FLAG(event, LeaveWindow);
1372 FLAG(event, PointerMotion);
1373 FLAG(event, PointerMotionHint);
1374 FLAG(event, Button1Motion);
1375 FLAG(event, Button2Motion);
1376 FLAG(event, Button3Motion);
1377 FLAG(event, Button4Motion);
1378 FLAG(event, Button5Motion);
1379 FLAG(event, ButtonMotion);
1380 FLAG(event, KeymapState);
1381 FLAG(event, Exposure);
1382 FLAG(event, VisibilityChange);
1383 FLAG(event, StructureNotify);
1384 FLAG(event, ResizeRedirect);
1385 FLAG(event, SubstructureNotify);
1386 FLAG(event, SubstructureRedirect);
1387 FLAG(event, FocusChange);
1388 FLAG(event, PropertyChange);
1389 FLAG(event, ColormapChange);
1390 FLAG(event, OwnerGrabButton);
1391 FLAG(event, erroneous_bits);
1395 static void setOfDeviceEvent(tvbuff_t *tvb, proto_tree *t)
1397 struct maskStruct save = lastMask;
1398 BITMASK32(do_not_propagate);
1399 FLAG(do_not_propagate, KeyPress);
1400 FLAG(do_not_propagate, KeyRelease);
1401 FLAG(do_not_propagate, ButtonPress);
1402 FLAG(do_not_propagate, ButtonRelease);
1403 FLAG(do_not_propagate, PointerMotion);
1404 FLAG(do_not_propagate, Button1Motion);
1405 FLAG(do_not_propagate, Button2Motion);
1406 FLAG(do_not_propagate, Button3Motion);
1407 FLAG(do_not_propagate, Button4Motion);
1408 FLAG(do_not_propagate, Button5Motion);
1409 FLAG(do_not_propagate, ButtonMotion);
1410 FLAG(do_not_propagate, erroneous_bits);
1414 static void setOfKeyMask(tvbuff_t *tvb, proto_tree *t)
1416 struct maskStruct save = lastMask;
1419 lastMask._value = VALUE16(tvb, cur_offset);
1420 lastMask._offset = cur_offset;
1422 if (lastMask._value == 0x8000)
1423 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
1424 "modifiers-masks: 0x8000 (AnyModifier)");
1426 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2,
1428 lastMask._tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
1429 FLAG(modifiers, Shift);
1430 FLAG(modifiers, Lock);
1431 FLAG(modifiers, Control);
1432 FLAG(modifiers, Mod1);
1433 FLAG(modifiers, Mod2);
1434 FLAG(modifiers, Mod3);
1435 FLAG(modifiers, Mod4);
1436 FLAG(modifiers, Mod5);
1437 FLAG(modifiers, erroneous_bits);
1443 static void setOfPointerEvent(tvbuff_t *tvb, proto_tree *t)
1445 struct maskStruct save = lastMask;
1446 BITMASK16(pointer_event);
1447 FLAG(pointer_event, ButtonPress);
1448 FLAG(pointer_event, ButtonRelease);
1449 FLAG(pointer_event, EnterWindow);
1450 FLAG(pointer_event, LeaveWindow);
1451 FLAG(pointer_event, PointerMotion);
1452 FLAG(pointer_event, PointerMotionHint);
1453 FLAG(pointer_event, Button1Motion);
1454 FLAG(pointer_event, Button2Motion);
1455 FLAG(pointer_event, Button3Motion);
1456 FLAG(pointer_event, Button4Motion);
1457 FLAG(pointer_event, Button5Motion);
1458 FLAG(pointer_event, ButtonMotion);
1459 FLAG(pointer_event, KeymapState);
1460 FLAG(pointer_event, erroneous_bits);
1464 static void string8(tvbuff_t *tvb, proto_tree *t, const char *nameAsChar,
1465 int hf, unsigned length)
1467 char *s = g_malloc(length + 1);
1468 stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
1469 proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
1471 cur_offset += length;
1474 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1476 static void string16(tvbuff_t *tvb, proto_tree *t, int hf, int hf_bytes,
1482 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, cur_offset, length, &s, &l);
1484 cur_offset += length;
1487 static void timestamp(tvbuff_t *tvb, proto_tree *t, const char *nameAsChar,
1490 guint32 v = VALUE32(tvb, cur_offset);
1492 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1494 proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
1498 static void windowAttributes(tvbuff_t *tvb, proto_tree *t)
1500 BITMASK32(window_value);
1501 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1502 BITFIELD(CARD32, window_value_mask, background_pixel);
1503 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1504 BITFIELD(CARD32, window_value_mask, border_pixel);
1505 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1506 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1507 BITFIELD(ENUM8, window_value_mask, backing_store);
1508 BITFIELD(CARD32, window_value_mask, backing_planes);
1509 BITFIELD(CARD32, window_value_mask, backing_pixel);
1510 BITFIELD(BOOL, window_value_mask, override_redirect);
1511 BITFIELD(BOOL, window_value_mask, save_under);
1512 BITFIELD(SETofEVENT, window_value_mask, event_mask);
1513 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1514 BITFIELD(COLORMAP, window_value_mask, colormap);
1515 BITFIELD(CURSOR, window_value_mask, cursor);
1518 /************************************************************************
1520 *** D E C O D I N G O N E P A C K E T ***
1522 ************************************************************************/
1524 static int dissect_x11_request_loop(tvbuff_t *tvb, proto_tree *root)
1526 int left = tvb_reported_length(tvb), nextLeft;
1533 /* The X11 data stream to the server is just a sequence of requests,
1534 each of which contains a length; for now, we dissect all the
1535 requests in this frame until we run out of data in the frame.
1536 Eventually, we should handle requests that cross frame
1539 Note that "in this frame" refers to everything in the frame
1540 as it appeared in the wire, not as it was captured; we want
1541 an exception to be thrown if we go past the end of the
1542 captured data in the frame without going past the end of the
1543 data in the frame. */
1547 /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
1549 /* We ran out of data - we don't have enough data in
1550 the frame to get the length of this request. */
1553 length = VALUE16(tvb, cur_offset + 2) * 4;
1554 /* fprintf(stderr, "length = %d\n", length);*/
1555 if (left < length) {
1556 /* We ran out of data - we don't have enough data in
1557 the frame for the full request. */
1561 /* Bogus message length? */
1565 next_offset = cur_offset + length;
1566 nextLeft = left - length;
1568 ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
1569 t = proto_item_add_subtree(ti, ett_x11_request);
1574 case 1: /* CreateWindow */
1583 CARD16(border_width);
1584 ENUM16(window_class);
1586 windowAttributes(tvb, t);
1589 case 2: /* ChangeWindowAttributes */
1593 windowAttributes(tvb, t);
1596 case 3: /* GetWindowAttributes */
1597 case 4: /* DestroyWindow */
1598 case 5: /* DestroySubwindows */
1604 case 6: /* ChangeSaveSet */
1605 ENUM8(save_set_mode);
1610 case 7: /* ReparentWindow */
1619 case 8: /* MapWindow */
1620 case 9: /* MapSubWindow */
1621 case 10: /* UnmapWindow */
1622 case 11: /* UnmapSubwindows */
1628 case 12: /* ConfigureWindow */
1632 BITMASK16(configure_window);
1634 BITFIELD(INT16, configure_window_mask, x);
1635 BITFIELD(INT16, configure_window_mask, y);
1636 BITFIELD(CARD16, configure_window_mask, width);
1637 BITFIELD(CARD16, configure_window_mask, height);
1638 BITFIELD(CARD16, configure_window_mask, border_width);
1639 BITFIELD(WINDOW, configure_window_mask, sibling);
1640 BITFIELD(ENUM8, configure_window_mask, stack_mode);
1644 case 13: /* CirculateWindow */
1650 case 14: /* GetGeometry */
1651 case 15: /* QueryTree */
1657 case 16: /* InternAtom */
1658 BOOL(only_if_exists);
1660 v16 = FIELD16(name_length);
1666 case 17: /* GetAtomName */
1672 case 18: /* ChangeProperty */
1680 v32 = CARD32(data_length);
1681 LISTofBYTE(data, v32);
1685 case 19: /* DeleteProperty */
1692 case 20: /* GetProperty */
1697 ATOM(get_property_type);
1698 CARD32(long_offset);
1699 CARD32(long_length);
1702 case 21: /* ListProperties */
1708 case 22: /* SetSelectionOwner */
1716 case 23: /* GetSelectionOwner */
1722 case 24: /* ConvertSelection */
1732 case 26: /* GrabPointer */
1735 WINDOW(grab_window);
1736 SETofPOINTEREVENT(pointer_event_mask);
1737 ENUM8(pointer_mode);
1738 ENUM8(keyboard_mode);
1744 case 27: /* UngrabPointer */
1750 case 28: /* GrabButton */
1753 WINDOW(grab_window);
1754 SETofPOINTEREVENT(event_mask);
1755 ENUM8(pointer_mode);
1756 ENUM8(keyboard_mode);
1761 SETofKEYMASK(modifiers);
1764 case 29: /* UngrabButton */
1767 WINDOW(grab_window);
1768 SETofKEYMASK(modifiers);
1772 case 30: /* ChangeActivePointerGrab */
1777 SETofPOINTEREVENT(event_mask);
1781 case 31: /* GrabKeyboard */
1784 WINDOW(grab_window);
1786 ENUM8(pointer_mode);
1787 ENUM8(keyboard_mode);
1791 case 32: /* UngrabKeyboard */
1797 case 33: /* GrabKey */
1800 WINDOW(grab_window);
1801 SETofKEYMASK(modifiers);
1803 ENUM8(pointer_mode);
1804 ENUM8(keyboard_mode);
1808 case 34: /* UngrabKey */
1811 WINDOW(grab_window);
1812 SETofKEYMASK(modifiers);
1816 case 35: /* AllowEvents */
1817 ENUM8(allow_events_mode);
1822 case 36: /* GrabServer */
1827 case 37: /* UngrabServer */
1832 case 38: /* QueryPointer */
1838 case 39: /* GetMotionEvents */
1846 case 40: /* TranslateCoordinates */
1855 case 41: /* WarpPointer */
1858 WINDOW(warp_pointer_src_window);
1859 WINDOW(warp_pointer_dst_window);
1868 case 42: /* SetInputFocus */
1875 case 43: /* GetInputFocus */
1880 case 44: /* QueryKeymap */
1885 case 45: /* OpenFont */
1889 v16 = FIELD16(name_length);
1895 case 46: /* CloseFont */
1901 case 47: /* QueryFont */
1907 case 48: /* QueryTextExtents */
1908 v8 = BOOL(odd_length);
1911 STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
1915 case 49: /* ListFonts */
1919 v16 = FIELD16(pattern_length);
1920 STRING8(pattern, v16);
1924 case 50: /* ListFontsWithInfo */
1928 v16 = FIELD16(pattern_length);
1929 STRING8(pattern, v16);
1933 case 51: /* SetFontPath */
1936 v16 = CARD16(str_number_in_path);
1938 LISTofSTRING8(path, v16);
1942 case 52: /* GetFontPath */
1947 case 53: /* CreatePixmap */
1956 case 54: /* FreePixmap */
1962 case 55: /* CreateGC */
1967 gcAttributes(tvb, t);
1970 case 56: /* ChangeGC */
1974 gcAttributes(tvb, t);
1977 case 57: /* CopyGC */
1985 case 58: /* SetDashes */
1989 CARD16(dash_offset);
1990 v16 = FIELD16(dashes_length);
1991 LISTofCARD8(dashes, v16);
1995 case 59: /* SetClipRectangles */
1999 INT16(clip_x_origin);
2000 INT16(clip_y_origin);
2001 LISTofRECTANGLE(rectangles);
2004 case 60: /* FreeGC */
2010 case 61: /* ClearArea */
2020 case 62: /* CopyArea */
2023 DRAWABLE(src_drawable);
2024 DRAWABLE(dst_drawable);
2034 case 63: /* CopyPlane */
2037 DRAWABLE(src_drawable);
2038 DRAWABLE(dst_drawable);
2049 case 64: /* PolyPoint */
2050 ENUM8(coordinate_mode);
2051 v16 = REQUEST_LENGTH();
2054 LISTofPOINT(points, v16 - 12);
2057 case 65: /* PolyLine */
2058 ENUM8(coordinate_mode);
2059 v16 = REQUEST_LENGTH();
2062 LISTofPOINT(points, v16 - 12);
2065 case 66: /* PolySegment */
2070 LISTofSEGMENT(segments);
2073 case 67: /* PolyRectangle */
2078 LISTofRECTANGLE(rectangles);
2081 case 68: /* PolyArc */
2089 case 69: /* FillPoly */
2091 v16 = REQUEST_LENGTH();
2095 ENUM8(coordinate_mode);
2097 LISTofPOINT(points, v16 - 16);
2100 case 70: /* PolyFillRectangle */
2105 LISTofRECTANGLE(rectangles);
2108 case 71: /* PolyFillArc */
2116 case 72: /* PutImage */
2117 ENUM8(image_format);
2118 v16 = REQUEST_LENGTH();
2128 LISTofBYTE(data, v16 - 24);
2132 case 73: /* GetImage */
2133 ENUM8(image_pixmap_format);
2143 case 74: /* PolyText8 */
2145 v16 = REQUEST_LENGTH();
2150 LISTofTEXTITEM8(items);
2154 case 75: /* PolyText16 */
2156 v16 = REQUEST_LENGTH();
2161 LISTofTEXTITEM16(items);
2165 case 76: /* ImageText8 */
2166 v8 = FIELD8(string_length);
2172 STRING8(string, v8);
2176 case 77: /* ImageText16 */
2177 v8 = FIELD8(string_length);
2183 STRING16(string16, v8);
2187 case 78: /* CreateColormap */
2195 case 79: /* FreeColormap */
2201 case 80: /* CopyColormapAndFree */
2208 case 81: /* InstallColormap */
2214 case 82: /* UninstallColormap */
2220 case 83: /* ListInstalledColormaps */
2226 case 84: /* AllocColor */
2236 case 85: /* AllocNamedColor */
2240 v16 = FIELD16(name_length);
2246 case 86: /* AllocColorCells */
2254 case 87: /* AllocColorPlanes */
2264 case 88: /* FreeColors */
2266 v16 = REQUEST_LENGTH();
2269 LISTofCARD32(pixels, v16 - 12);
2272 case 89: /* StoreColors */
2274 v16 = REQUEST_LENGTH();
2276 LISTofCOLORITEM(color_items, v16 - 8);
2279 case 90: /* StoreNamedColor */
2284 v16 = FIELD16(name_length);
2290 case 91: /* QueryColors */
2292 v16 = REQUEST_LENGTH();
2294 LISTofCARD32(pixels, v16 - 8);
2297 case 92: /* LookupColor */
2301 v16 = FIELD16(name_length);
2307 case 93: /* CreateCursor */
2311 PIXMAP(source_pixmap);
2323 case 94: /* CreateGlyphCursor */
2329 CARD16(source_char);
2339 case 95: /* FreeCursor */
2345 case 96: /* RecolorCursor */
2357 case 97: /* QueryBestSize */
2365 case 98: /* QueryExtension */
2368 v16 = FIELD16(name_length);
2374 case 99: /* ListExtensions */
2379 case 100: /* ChangeKeyboardMapping */
2380 v8 = FIELD8(keycode_count);
2382 KEYCODE(first_keycode);
2383 v8_2 = FIELD8(keysyms_per_keycode);
2385 LISTofKEYSYM(keysyms, v8, v8_2);
2388 case 101: /* GetKeyboardMapping */
2391 KEYCODE(first_keycode);
2396 case 102: /* ChangeKeyboardControl */
2399 BITMASK32(keyboard_value);
2400 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2401 BITFIELD(INT8, keyboard_value_mask, bell_percent);
2402 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2403 BITFIELD(INT16, keyboard_value_mask, bell_duration);
2404 BITFIELD(INT16, keyboard_value_mask, led);
2405 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2406 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2407 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2410 case 103: /* GetKeyboardControl */
2415 case 104: /* Bell */
2420 case 105: /* ChangePointerControl */
2423 INT16(acceleration_numerator);
2424 INT16(acceleration_denominator);
2426 BOOL(do_acceleration);
2430 case 106: /* GetPointerControl */
2435 case 107: /* SetScreenSaver */
2440 ENUM8(prefer_blanking);
2441 ENUM8(allow_exposures);
2445 case 108: /* GetScreenSaver */
2450 case 109: /* ChangeHosts */
2451 ENUM8(change_host_mode);
2455 v16 = CARD16(address_length);
2456 LISTofCARD8(address, v16);
2459 case 110: /* ListHosts */
2464 case 111: /* SetAccessControl */
2469 case 112: /* SetCloseDownMode */
2470 ENUM8(close_down_mode);
2474 case 113: /* KillClient */
2480 case 114: /* RotateProperties */
2482 v16 = REQUEST_LENGTH();
2484 CARD16(property_number);
2486 LISTofATOM(properties, (v16 - 12));
2489 case 115: /* ForceScreenSaver */
2490 ENUM8(screen_saver_mode);
2494 case 116: /* SetPointerMapping */
2495 v8 = FIELD8(map_length);
2497 LISTofCARD8(map, v8);
2501 case 117: /* GetPointerMapping */
2506 case 118: /* SetModifierMapping */
2507 v8 = FIELD8(keycodes_per_modifier);
2509 LISTofKEYCODE(keycodes, v8);
2512 case 119: /* GetModifierMapping */
2517 case 127: /* NoOperation */
2522 if (cur_offset < next_offset)
2523 proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
2524 cur_offset = next_offset;
2531 /************************************************************************
2533 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2535 ************************************************************************/
2537 static GTree *byte_ordering_cache = NULL;
2538 static GMemChunk *address_chunk = NULL;
2539 static GMemChunk *ipv4_chunk = NULL;
2540 static GMemChunk *ipv6_chunk = NULL;
2542 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2544 const address *a = (const address *)aa;
2545 const address *b = (const address *)bb;
2546 int c = b -> type - a -> type;
2548 c = b -> len - a -> len;
2550 return memcmp(b -> data, a -> data, a -> len);
2553 /* If we can't guess, we return TRUE (that is little_endian), cause
2554 I'm developing on a Linux box :-). The (non-)guess isn't cached
2555 however, so we may have more luck next time. I'm quite conservative
2556 in my assertions, cause once it's cached, it's stay in cache, and
2557 we may be fooled up by a packet starting with the end of a request
2558 started in a previous packet...
2561 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2563 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2566 while(maskLength--) {
2567 int c = tvb_get_guint8(tvb, offset);
2569 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2574 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2576 if (listLength > length) return FALSE;
2577 while(listLength--) {
2579 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2580 l = tvb_get_guint8(tvb, offset);
2583 if (l > length) return FALSE;
2584 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2588 if (length > 3) return FALSE;
2592 static int rounded4(int n)
2594 int remainder = n % 4;
2596 if (remainder) res++;
2600 /* We assume the order to be consistent, until proven wrong. */
2602 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2604 switch(tvb_get_guint8(tvb, offset)) {
2605 case 1: /* CreateWindow */
2606 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2608 case 2: /* ChangeWindowAttributes */
2609 case 56: /* ChangeGC */
2610 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2612 case 3: /* GetWindowAttributes */
2613 case 4: /* DestroyWindow */
2614 case 5: /* DestroySubwindows */
2615 case 6: /* ChangeSaveSet */
2616 case 8: /* MapWindow */
2617 case 9: /* MapSubWindow */
2618 case 10: /* UnmapWindow */
2619 case 11: /* UnmapSubwindows */
2620 case 13: /* CirculateWindow */
2621 case 14: /* GetGeometry */
2622 case 15: /* QueryTree */
2623 case 17: /* GetAtomName */
2624 case 21: /* ListProperties */
2625 case 23: /* GetSelectionOwner */
2626 case 27: /* UngrabPointer */
2627 case 32: /* UngrabKeyboard */
2628 case 35: /* AllowEvents */
2629 case 38: /* QueryPointer */
2630 case 46: /* CloseFont */
2631 case 47: /* QueryFont */
2632 case 54: /* FreePixmap */
2633 case 60: /* FreeGC */
2634 case 79: /* FreeColormap */
2635 case 81: /* InstallColormap */
2636 case 82: /* UninstallColormap */
2637 case 83: /* ListInstalledColormaps */
2638 case 95: /* FreeCursor */
2639 case 101: /* GetKeyboardMapping */
2640 case 113: /* KillClient */
2643 case 7: /* ReparentWindow */
2644 case 22: /* SetSelectionOwner */
2645 case 30: /* ChangeActivePointerGrab */
2646 case 31: /* GrabKeyboard */
2647 case 33: /* GrabKey */
2648 case 39: /* GetMotionEvents */
2649 case 40: /* TranslateCoordinates */
2650 case 53: /* CreatePixmap */
2651 case 57: /* CopyGC */
2652 case 61: /* ClearArea */
2653 case 78: /* CreateColormap */
2654 case 84: /* AllocColor */
2655 case 87: /* AllocColorPlanes */
2658 case 12: /* ConfigureWindow */
2659 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2661 case 16: /* InternAtom */
2662 case 98: /* QueryExtension */
2663 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2665 case 18: /* ChangeProperty */
2667 int multiplier, type;
2668 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2669 type = tvb_get_guint8(tvb, 16);
2670 if (type != 8 && type != 16 && type != 32) return FALSE;
2671 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2672 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2673 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2676 case 19: /* DeleteProperty */
2677 case 29: /* UngrabButton */
2678 case 34: /* UngrabKey */
2679 case 42: /* SetInputFocus */
2680 case 80: /* CopyColormapAndFree */
2681 case 86: /* AllocColorCells */
2682 case 97: /* QueryBestSize */
2683 case 105: /* ChangePointerControl */
2684 case 107: /* SetScreenSaver */
2687 case 20: /* GetProperty */
2688 case 24: /* ConvertSelection */
2689 case 26: /* GrabPointer */
2690 case 28: /* GrabButton */
2691 case 41: /* WarpPointer */
2694 case 25: /* SendEvent */
2695 return length == 11;
2697 case 36: /* GrabServer */
2698 case 37: /* UngrabServer */
2699 case 43: /* GetInputFocus */
2700 case 44: /* QueryKeymap */
2701 case 52: /* GetFontPath */
2702 case 99: /* ListExtensions */
2703 case 103: /* GetKeyboardControl */
2704 case 104: /* Bell */
2705 case 106: /* GetPointerControl */
2706 case 108: /* GetScreenSaver */
2707 case 110: /* ListHosts */
2708 case 111: /* SetAccessControl */
2709 case 112: /* SetCloseDownMode */
2710 case 115: /* ForceScreenSaver */
2711 case 117: /* GetPointerMapping */
2712 case 119: /* GetModifierMapping */
2715 case 45: /* OpenFont */
2716 case 85: /* AllocNamedColor */
2717 case 92: /* LookupColor */
2718 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2720 case 48: /* QueryTextExtents */
2723 case 49: /* ListFonts */
2724 case 50: /* ListFontsWithInfo */
2725 case 109: /* ChangeHosts */
2726 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2728 case 51: /* SetFontPath */
2729 if (length < 2) return FALSE;
2730 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2731 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2733 case 55: /* CreateGC */
2734 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2736 case 58: /* SetDashes */
2737 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2739 case 59: /* SetClipRectangles */
2740 case 66: /* PolySegment */
2741 case 67: /* PolyRectangle */
2742 case 70: /* PolyFillRectangle */
2743 return length >= 3 && (length - 3) % 2 == 0;
2745 case 62: /* CopyArea */
2748 case 63: /* CopyPlane */
2749 case 93: /* CreateCursor */
2750 case 94: /* CreateGlyphCursor */
2753 case 64: /* PolyPoint */
2754 case 65: /* PolyLine */
2755 case 88: /* FreeColors */
2758 case 68: /* PolyArc */
2759 case 71: /* PolyFillArc */
2760 return length >= 3 && (length - 3) % 3 == 0;
2762 case 69: /* FillPoly */
2763 case 76: /* ImageText8 */
2766 case 72: /* PutImage */
2769 case 73: /* GetImage */
2770 case 96: /* RecolorCursor */
2773 case 74: /* PolyText8 */
2774 if (length < 4) return FALSE;
2775 return TRUE; /* We don't perform many controls on this one */
2777 case 75: /* PolyText16 */
2778 if (length < 4) return FALSE;
2779 return TRUE; /* We don't perform many controls on this one */
2781 case 77: /* ImageText16 */
2784 case 89: /* StoreColors */
2785 return length > 2 && (length - 2) % 3 == 0;
2787 case 90: /* StoreNamedColor */
2788 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2790 case 91: /* QueryColors */
2793 case 100: /* ChangeKeyboardMapping */
2794 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2796 case 102: /* ChangeKeyboardControl */
2797 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2799 case 114: /* RotateProperties */
2800 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2802 case 116: /* SetPointerMapping */
2803 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2805 case 118: /* SetModifierMapping */
2806 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2808 case 127: /* NoOperation */
2816 /* -1 means doesn't match, +1 means match, 0 means don't know */
2818 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2820 int offset, nextoffset;
2823 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2825 length = v16(tvb, offset + 2);
2826 if (!length) return -1;
2827 nextoffset = offset + length * 4;
2828 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2835 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
2837 /* With X the client gives the byte ordering for the protocol,
2838 and the port on the server tells us we're speaking X. */
2840 int le, be, decision, decisionToCache;
2842 gboolean is_reply = (pinfo->srcport == pinfo->match_port);
2843 address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
2844 gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2845 if (cache) return cache > 0 ? TRUE : FALSE;
2846 if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
2848 le = x_endian_match(tvb, tvb_get_letohs);
2849 be = x_endian_match(tvb, tvb_get_ntohs);
2851 /* remember that "decision" really means "little_endian". */
2853 /* We have no reason to believe it's little- rather than
2854 big-endian, so we guess the shortest length is the
2857 if (!tvb_bytes_exist(tvb, 0, 4))
2858 /* Not even a way to get the length. We're biased
2859 toward little endianness here (essentially the
2860 x86 world right now). Decoding won't go very far
2865 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2867 decision = le >= be;
2869 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2870 if (decisionToCache) {
2871 /* We encode the decision as 1 for TRUE and -1 for FALSE
2872 to be able to distinguish between FALSE and no value in
2873 the cache when recalling the value.
2878 if (addr -> type == AT_IPv4) {
2880 address_data = g_mem_chunk_alloc(ipv4_chunk);
2881 } else if (addr -> type == AT_IPv6) {
2882 address_length = 16;
2883 address_data = g_mem_chunk_alloc(ipv6_chunk);
2885 address_length = addr -> len;
2886 address_data = g_malloc(address_length);
2888 cached = g_mem_chunk_alloc(address_chunk);
2889 memcpy(address_data, addr -> data, address_length);
2890 SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2891 g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2895 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2896 pinfo->fd -> num, le, be, decision, decisionToCache);
2901 /************************************************************************
2903 *** I N I T I A L I Z A T I O N A N D M A I N ***
2905 ************************************************************************/
2908 dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2910 /* Set up structures we will need to add the protocol subtree and manage it */
2912 proto_tree *x11_tree;
2915 /* This field shows up as the "Info" column in the display; you should make
2916 it, if possible, summarize what's in the packet, so that a user looking
2917 at the list of packets can tell what type of packet it is. */
2918 if (check_col(pinfo->cinfo, COL_INFO))
2919 col_set_str(pinfo->cinfo, COL_INFO, "X11 request");
2921 /* In the interest of speed, if "tree" is NULL, don't do any work not
2922 necessary to generate protocol tree items. */
2924 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2925 x11_tree = proto_item_add_subtree(ti, ett_x11);
2928 little_endian = guess_byte_ordering(tvb, pinfo);
2929 left = dissect_x11_request_loop(tvb, x11_tree);
2931 call_dissector(data_handle,tvb_new_subset(tvb, cur_offset,-1, tvb_reported_length_remaining(tvb,cur_offset)), pinfo, x11_tree);
2935 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2937 /* Set up structures we will need to add the protocol subtree and manage it */
2939 proto_tree *x11_tree;
2941 /* This field shows up as the "Info" column in the display; you should make
2942 it, if possible, summarize what's in the packet, so that a user looking
2943 at the list of packets can tell what type of packet it is. */
2944 if (check_col(pinfo->cinfo, COL_INFO))
2945 col_set_str(pinfo->cinfo, COL_INFO, "X11 event");
2947 /* In the interest of speed, if "tree" is NULL, don't do any work not
2948 necessary to generate protocol tree items. */
2950 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2951 x11_tree = proto_item_add_subtree(ti, ett_x11);
2953 /* Code to process the packet goes here */
2955 call_dissector(data_handle,tvb, pinfo, x11_tree);
2960 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2962 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2963 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
2965 if (pinfo->match_port == pinfo->destport)
2966 dissect_x11_request(tvb, pinfo, tree);
2968 dissect_x11_event(tvb, pinfo, tree);
2971 /* Register the protocol with Ethereal */
2972 void proto_register_x11(void)
2975 /* Setup list of header fields */
2976 static hf_register_info hf[] = {
2978 { &hf_x11_FIELDABBREV,
2979 { "FIELDNAME", "x11.FIELDABBREV",
2980 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
2981 "FIELDDESCR", HFILL }
2984 #include "x11-register-info.h"
2987 /* Setup protocol subtree array */
2988 static gint *ett[] = {
2991 &ett_x11_color_flags,
2992 &ett_x11_list_of_arc,
2994 &ett_x11_list_of_atom,
2995 &ett_x11_list_of_card32,
2996 &ett_x11_list_of_color_item,
2997 &ett_x11_color_item,
2998 &ett_x11_list_of_keycode,
2999 &ett_x11_list_of_keysyms,
3001 &ett_x11_list_of_point,
3003 &ett_x11_list_of_rectangle,
3005 &ett_x11_list_of_segment,
3007 &ett_x11_list_of_string8,
3008 &ett_x11_list_of_text_item,
3010 &ett_x11_gc_value_mask,
3011 &ett_x11_event_mask,
3012 &ett_x11_do_not_propagate_mask,
3013 &ett_x11_set_of_key_mask,
3014 &ett_x11_pointer_event_mask,
3015 &ett_x11_window_value_mask,
3016 &ett_x11_configure_window_mask,
3017 &ett_x11_keyboard_value_mask,
3020 /* Register the protocol name and description */
3021 proto_x11 = proto_register_protocol("X11", "X11", "x11");
3023 /* Required function calls to register the header fields and subtrees used */
3024 proto_register_field_array(proto_x11, hf, array_length(hf));
3025 proto_register_subtree_array(ett, array_length(ett));
3027 byte_ordering_cache = g_tree_new(compareAddresses);
3028 address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address),
3029 sizeof(address) * 128, G_ALLOC_ONLY);
3030 ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
3031 ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
3036 proto_reg_handoff_x11(void)
3038 dissector_handle_t x11_handle;
3040 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
3041 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
3042 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
3043 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
3044 data_handle = find_dissector("data");