2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
5 * $Id: packet-x11.c,v 1.29 2002/01/24 09:20:52 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;
75 static dissector_handle_t data_handle;
77 #define TCP_PORT_X11 6000
78 #define TCP_PORT_X11_2 6001
79 #define TCP_PORT_X11_3 6002
81 /************************************************************************
83 *** E N U M T A B L E S D E F I N I T I O N S ***
85 ************************************************************************/
87 static const value_string access_mode_vals[] = {
93 static const value_string all_temporary_vals[] = {
94 { 0, "AllTemporary" },
98 static const value_string alloc_vals[] = {
104 static const value_string allow_events_mode_vals[] = {
105 { 0, "AsyncPointer" },
106 { 1, "SyncPointer" },
107 { 2, "ReplayPointer" },
108 { 3, "AsyncKeyboard" },
109 { 4, "SyncKeyboard" },
110 { 5, "ReplayKeyboard" },
116 static const value_string arc_mode_vals[] = {
122 static const char *atom_predefined_interpretation[] = {
174 "UNDERLINE_POSITION",
175 "UNDERLINE_THICKNESS",
194 static const value_string auto_repeat_mode_vals[] = {
201 static const value_string background_pixmap_vals[] = {
203 { 1, "ParentRelative" },
207 static const value_string backing_store_vals[] = {
214 static const value_string border_pixmap_vals[] = {
215 { 0, "CopyFromParent" },
219 static const value_string button_vals[] = {
220 { 0x8000, "AnyButton" },
224 static const value_string cap_style_vals[] = {
232 static const value_string class_vals[] = {
239 static const value_string close_down_mode_vals[] = {
241 { 1, "RetainPermanent" },
242 { 2, "RetainTemporary" },
246 static const value_string coordinate_mode_vals[] = {
252 static const value_string direction_vals[] = {
253 { 0, "RaiseLowest" },
254 { 1, "LowerHighest" },
258 static const value_string family_vals[] = {
265 static const value_string fill_rule_vals[] = {
271 static const value_string fill_style_vals[] = {
275 { 3, "OpaqueStippled" },
279 static const value_string focus_vals[] = {
281 { 1, "PointerRoot" },
285 static const value_string function_vals[] = {
290 { 4, "AndInverted" },
298 { 12, "CopyInverted" },
299 { 13, "OrInverted" },
305 static const value_string gravity_vals[] = {
319 static const value_string image_format_vals[] = {
326 static const value_string image_pixmap_format_vals[] = {
332 static const value_string join_style_vals[] = {
339 static const value_string key_vals[] = {
344 #include "packet-x11-keysym.h"
346 static const value_string line_style_vals[] = {
353 static const value_string mode_vals[] = {
360 static const value_string on_off_vals[] = {
366 static const value_string opcode_vals[] = {
367 { 1, "CreateWindow" },
368 { 2, "ChangeWindowAttributes" },
369 { 3, "GetWindowAttributes" },
370 { 4, "DestroyWindow" },
371 { 5, "DestroySubwindows" },
372 { 6, "ChangeSaveSet" },
373 { 7, "ReparentWindow" },
375 { 9, "MapSubwindows" },
376 { 10, "UnmapWindow" },
377 { 11, "UnmapSubwindows" },
378 { 12, "ConfigureWindow" },
379 { 13, "CirculateWindow" },
380 { 14, "GetGeometry" },
382 { 16, "InternAtom" },
383 { 17, "GetAtomName" },
384 { 18, "ChangeProperty" },
385 { 19, "DeleteProperty" },
386 { 20, "GetProperty" },
387 { 21, "ListProperties" },
388 { 22, "SetSelectionOwner" },
389 { 23, "GetSelectionOwner" },
390 { 24, "ConvertSelection" },
392 { 26, "GrabPointer" },
393 { 27, "UngrabPointer" },
394 { 28, "GrabButton" },
395 { 29, "UngrabButton" },
396 { 30, "ChangeActivePointerGrab" },
397 { 31, "GrabKeyboard" },
398 { 32, "UngrabKeyboard" },
401 { 35, "AllowEvents" },
402 { 36, "GrabServer" },
403 { 37, "UngrabServer" },
404 { 38, "QueryPointer" },
405 { 39, "GetMotionEvents" },
406 { 40, "TranslateCoordinates" },
407 { 41, "WarpPointer" },
408 { 42, "SetInputFocus" },
409 { 43, "GetInputFocus" },
410 { 44, "QueryKeymap" },
414 { 48, "QueryTextExtents" },
416 { 50, "ListFontsWithInfo" },
417 { 51, "SetFontPath" },
418 { 52, "GetFontPath" },
419 { 53, "CreatePixmap" },
420 { 54, "FreePixmap" },
425 { 59, "SetClipRectangles" },
432 { 66, "PolySegment" },
433 { 67, "PolyRectangle" },
436 { 70, "PolyFillRectangle" },
437 { 71, "PolyFillArc" },
441 { 75, "PolyText16" },
442 { 76, "ImageText8" },
443 { 77, "ImageText16" },
444 { 78, "CreateColormap" },
445 { 79, "FreeColormap" },
446 { 80, "CopyColormapAndFree" },
447 { 81, "InstallColormap" },
448 { 82, "UninstallColormap" },
449 { 83, "ListInstalledColormaps" },
450 { 84, "AllocColor" },
451 { 85, "AllocNamedColor" },
452 { 86, "AllocColorCells" },
453 { 87, "AllocColorPlanes" },
454 { 88, "FreeColors" },
455 { 89, "StoreColors" },
456 { 90, "StoreNamedColor" },
457 { 91, "QueryColors" },
458 { 92, "LookupColor" },
459 { 93, "CreateCursor" },
460 { 94, "CreateGlyphCursor" },
461 { 95, "FreeCursor" },
462 { 96, "RecolorCursor" },
463 { 97, "QueryBestSize" },
464 { 98, "QueryExtension" },
465 { 99, "ListExtensions" },
466 { 100, "ChangeKeyboardMapping" },
467 { 101, "GetKeyboardMapping" },
468 { 102, "ChangeKeyboardControl" },
469 { 103, "GetKeyboardControl" },
471 { 105, "ChangePointerControl" },
472 { 106, "GetPointerControl" },
473 { 107, "SetScreenSaver" },
474 { 108, "GetScreenSaver" },
475 { 109, "ChangeHosts" },
476 { 110, "ListHosts" },
477 { 111, "SetAccessControl" },
478 { 112, "SetCloseDownMode" },
479 { 113, "KillClient" },
480 { 114, "RotateProperties" },
481 { 115, "ForceScreenSaver" },
482 { 116, "SetPointerMapping" },
483 { 117, "GetPointerMapping" },
484 { 118, "SetModifierMapping" },
485 { 119, "GetModifierMapping" },
486 { 127, "NoOperation" },
490 static const value_string ordering_vals[] = {
498 static const value_string plane_mask_vals[] = {
499 { 0xFFFFFFFF, "AllPlanes" },
503 static const value_string pointer_keyboard_mode_vals[] = {
504 { 0, "Synchronous" },
505 { 1, "Asynchronous" },
509 static const value_string revert_to_vals[] = {
511 { 1, "PointerRoot" },
516 static const value_string insert_delete_vals[] = {
522 static const value_string screen_saver_mode_vals[] = {
528 static const value_string shape_vals[] = {
535 static const value_string stack_mode_vals[] = {
544 static const value_string subwindow_mode_vals[] = {
545 { 0, "ClipByChildren" },
546 { 1, "IncludeInferiors" },
550 static const value_string window_class_vals[] = {
551 { 0, "CopyFromParent" },
552 { 1, "InputOutput" },
557 static const value_string yes_no_default_vals[] = {
564 static const value_string zero_is_any_property_type_vals[] = {
565 { 0, "AnyPropertyType" },
569 static const value_string zero_is_none_vals[] = {
574 /************************************************************************
576 *** G L O B A L V A R I A B L E S ( A R G H H ! ) ***
578 ************************************************************************/
580 static int cur_offset; /* The current offset in the frame */
581 static int next_offset = 0; /* Offset of the next request in the frame */
582 static gboolean little_endian = TRUE;
583 static proto_tree *t = NULL;
585 static struct maskStruct {
590 } lastMask = { 0, 0, 0, NULL };
592 /************************************************************************
594 *** F I E L D D E C O D I N G M A C R O S ***
596 ************************************************************************/
598 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
599 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
600 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
602 #define FIELD8(name) (field8(tvb, hf_x11_##name))
603 #define FIELD16(name) (field16(tvb, hf_x11_##name))
604 #define FIELD32(name) (field32(tvb, hf_x11_##name))
606 #define BITFIELD(TYPE, position, name) {\
607 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
609 int save = cur_offset;\
610 proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
611 lastMask._zone, little_endian); \
613 unused = save + 4 - cur_offset;\
615 proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
616 cur_offset = save + 4;\
620 #define FLAG(position, name) {\
621 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
622 proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
624 #define ATOM(name) { atom(tvb, t, hf_x11_##name); }
625 #define BITGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Forget"); }
626 #define BITMASK8(name) { bitmask(tvb, hf_x11_##name##_mask, 1); }
627 #define BITMASK16(name) { bitmask(tvb, hf_x11_##name##_mask, 2); }
628 #define BITMASK32(name) { bitmask(tvb, hf_x11_##name##_mask, 4); }
629 #define BOOL(name) (add_boolean(tvb, #name, hf_x11_##name))
630 #define BUTTON(name) { FIELD8(name); }
631 #define CARD8(name) { FIELD8(name); }
632 #define CARD16(name) (FIELD16(name))
633 #define CARD32(name) (FIELD32(name))
634 #define COLOR_FLAGS(name) { colorFlags(tvb, t); }
635 #define COLORMAP(name) { FIELD32(name); }
636 #define CURSOR(name) { FIELD32(name); }
637 #define DRAWABLE(name) { FIELD32(name); }
638 #define ENUM8(name) { FIELD8(name); }
639 #define ENUM16(name) { FIELD16(name); }
640 #define FONT(name) { FIELD32(name); }
641 #define FONTABLE(name) { FIELD32(name); }
642 #define GCONTEXT(name) { FIELD32(name); }
643 #define INT8(name) { FIELD8(name); }
644 #define INT16(name) { FIELD16(name); }
645 #define KEYCODE(name) { FIELD8(name); }
646 #define LISTofARC(name) { listOfArc(tvb, hf_x11_##name, (next_offset - cur_offset) / 12); }
647 #define LISTofATOM(name, length) { listOfAtom(tvb, hf_x11_##name, (length) / 4); }
648 #define LISTofBYTE(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
649 #define LISTofCARD8(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
650 #define LISTofCARD32(name, length) { listOfCard32(tvb, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
651 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, hf_x11_##name, (length) / 12); }
652 #define LISTofKEYCODE(name, length) { listOfKeycode(tvb, hf_x11_##name, (length)); }
653 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
654 listOfKeysyms(tvb, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
655 #define LISTofPOINT(name, length) { listOfPoint(tvb, hf_x11_##name, (length) / 4); }
656 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
657 #define LISTofSEGMENT(name) { listOfSegment(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
658 #define LISTofSTRING8(name, length) { listOfString8(tvb, hf_x11_##name, hf_x11_##name##_string, (length)); }
659 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, hf_x11_##name, FALSE); }
660 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, hf_x11_##name, TRUE); }
661 #define OPCODE() { opcode = FIELD8(opcode); }
662 #define PIXMAP(name) { FIELD32(name); }
663 #define REQUEST_LENGTH() (requestLength(tvb))
664 #define SETofEVENT(name) { setOfEvent(tvb); }
665 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb);}
666 #define SETofKEYMASK(name) { setOfKeyMask(tvb); }
667 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb); }
668 #define STRING8(name, length) { string8(tvb, #name, hf_x11_##name, length); }
669 #define STRING16(name, length) { string16(tvb, hf_x11_##name, hf_x11_##name##_bytes, length); }
670 #define TIMESTAMP(name){ timestamp(tvb, #name, hf_x11_##name); }
671 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, x, little_endian); p += x; }
672 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, x, little_endian); cur_offset += x; }
673 #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; }
674 #define WINDOW(name) { FIELD32(name); }
675 #define WINGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Unmap"); }
677 #define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
678 proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
679 v ? "" : " (CopyFromParent)"); cur_offset += 4; }
681 /************************************************************************
683 *** D E C O D I N G F I E L D S ***
685 ************************************************************************/
687 static void atom(tvbuff_t *tvb, proto_tree *t, int hf)
689 const char *interpretation = NULL;
691 guint32 v = VALUE32(tvb, cur_offset);
692 if (v >= 1 && v < array_length(atom_predefined_interpretation))
693 interpretation = atom_predefined_interpretation[v];
695 interpretation = "Not a predefined atom";
697 header_field_info *hfi = proto_registrar_get_nth(hf);
699 interpretation = match_strval(v, cVALS(hfi -> strings));
701 if (!interpretation) interpretation = "error in Xlib client program ?";
702 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %u (%s)",
703 proto_registrar_get_nth(hf) -> name, v, interpretation);
707 static void bitmask(tvbuff_t *tvb, int hf, int size)
709 lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
710 lastMask._offset = cur_offset;
711 lastMask._zone = size;
712 lastMask._tree = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
716 static guint32 add_boolean(tvbuff_t *tvb, const char *nameAsChar, int hf)
718 guint32 v = VALUE8(tvb, cur_offset);
719 proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
724 static void colorFlags(tvbuff_t *tvb, proto_tree *t)
726 unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
729 if (do_red_green_blue) {
732 char *bp = buffer + sprintf(buffer, "flags: ");
734 if (do_red_green_blue & 0x1) {
735 bp += sprintf(bp, "DoRed");
739 if (do_red_green_blue & 0x2) {
740 if (sep) bp += sprintf(bp, " | ");
741 bp += sprintf(bp, "DoGreen");
745 if (do_red_green_blue & 0x4) {
746 if (sep) bp += sprintf(bp, " | ");
747 bp += sprintf(bp, "DoBlue");
751 if (do_red_green_blue & 0xf8) {
752 if (sep) bp += sprintf(bp, " + ");
753 sprintf(bp, "trash");
756 tt = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
758 if (do_red_green_blue & 0x1)
759 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1,
760 do_red_green_blue & 0x1);
761 if (do_red_green_blue & 0x2)
762 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1,
763 do_red_green_blue & 0x2);
764 if (do_red_green_blue & 0x4)
765 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1,
766 do_red_green_blue & 0x4);
767 if (do_red_green_blue & 0xf8)
768 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1,
769 do_red_green_blue & 0xf8);
771 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
776 static void gravity(tvbuff_t *tvb, const char *nameAsChar, int hf, const char *nullInterpretation)
778 guint8 v = VALUE8(tvb, cur_offset);
780 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar,
783 proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
787 static void listOfArc(tvbuff_t *tvb, int hf, int length)
789 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
791 gint16 x = VALUE16(tvb, cur_offset);
792 gint16 y = VALUE16(tvb, cur_offset + 2);
793 guint16 width = VALUE16(tvb, cur_offset + 4);
794 guint16 height = VALUE16(tvb, cur_offset + 6);
795 gint16 angle1 = VALUE16(tvb, cur_offset + 8);
796 gint16 angle2 = VALUE16(tvb, cur_offset + 10);
798 proto_tree *ttt = proto_tree_add_none_format(tt, hf_x11_arc, tvb, cur_offset, 12,
799 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
800 width, height, x, y, angle1, angle2,
801 angle1 / 64.0, angle2 / 64.0);
802 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
803 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
804 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
805 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
806 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
807 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
811 static void listOfAtom(tvbuff_t *tvb, int hf, int length)
813 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
815 if (cur_offset + 4 > next_offset) {
816 /* List runs past end of message. */
819 atom(tvb, tt, hf_x11_properties_item);
823 static void listOfByte(tvbuff_t *tvb, int hf, int length)
825 if (cur_offset + length > next_offset) {
826 /* List runs past end of message. */
827 length = next_offset - cur_offset;
829 if (length <= 0) length = 1;
830 proto_tree_add_item(t, hf, tvb, cur_offset, length, little_endian);
831 cur_offset += length;
834 static void listOfCard32(tvbuff_t *tvb, int hf, int hf_item, int length)
836 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
838 if (cur_offset + 4 > next_offset) {
839 /* List runs past end of message. */
842 proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
847 static void listOfColorItem(tvbuff_t *tvb, int hf, int length)
849 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
852 unsigned do_red_green_blue;
853 guint16 red, green, blue;
858 if (cur_offset + 12 > next_offset) {
859 /* List runs past end of message. */
862 red = VALUE16(tvb, cur_offset + 4);
863 green = VALUE16(tvb, cur_offset + 6);
864 blue = VALUE16(tvb, cur_offset + 8);
865 do_red_green_blue = VALUE8(tvb, cur_offset + 10);
867 bp = buffer + sprintf(buffer, "colorItem: ");
869 if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
870 if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
871 if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
873 ttt = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
874 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
875 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
876 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
877 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
878 colorFlags(tvb, ttt);
879 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
883 static GTree *keysymTable = NULL;
885 static gint compareGuint32(gconstpointer a, gconstpointer b)
887 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
890 static const char *keysymString(guint32 v)
895 /* This table is so big that we built it only if necessary */
897 const value_string *p = keysym_vals_source;
898 keysymTable = g_tree_new(compareGuint32);
899 for(; p -> strptr; p++)
900 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
902 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
903 return res ? res : "Unknown";
906 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
908 static void listOfKeycode(tvbuff_t *tvb, int hf, int length)
911 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
918 if (cur_offset + 8 > next_offset) {
919 /* List runs past end of message. */
922 for(i = 8, m = modifiers; i; i--, m++) {
923 u_char c = tvb_get_guint8(tvb, cur_offset);
925 if (c) bp += sprintf(bp, " %s=%d", *m, c);
928 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);
932 static void listOfKeysyms(tvbuff_t *tvb, int hf, int hf_item, int keycode_count, int keysyms_per_keycode)
934 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
940 while(keycode_count--) {
941 if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
942 /* List runs past end of message. */
945 bp = buffer + sprintf(buffer, "keysyms:");
946 for(i = 0; i < keysyms_per_keycode; i++) {
947 bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
950 ttt = proto_tree_add_none_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
952 for(i = keysyms_per_keycode; i; i--) {
953 guint32 v = VALUE32(tvb, cur_offset);
954 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
955 "keysym: 0x%08x (%s)", v, keysymString(v));
961 static void listOfPoint(tvbuff_t *tvb, int hf, int length)
963 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
968 if (cur_offset + 4 > next_offset) {
969 /* List runs past end of message. */
972 x = VALUE16(tvb, cur_offset);
973 y = VALUE16(tvb, cur_offset + 2);
975 ttt = proto_tree_add_none_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
976 proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
977 proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
981 static void listOfRectangle(tvbuff_t *tvb, int hf, int length)
983 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
986 unsigned width, height;
989 if (cur_offset + 8 > next_offset) {
990 /* List runs past end of message. */
993 x = VALUE16(tvb, cur_offset);
994 y = VALUE16(tvb, cur_offset + 2);
995 width = VALUE16(tvb, cur_offset + 4);
996 height = VALUE16(tvb, cur_offset + 6);
998 ttt = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, cur_offset, 8,
999 "rectangle: %dx%d+%d+%d", width, height, x, y);
1000 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
1001 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
1002 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
1003 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
1007 static void listOfSegment(tvbuff_t *tvb, int hf, int length)
1009 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1011 gint16 x1, y1, x2, y2;
1014 if (cur_offset + 8 > next_offset) {
1015 /* List runs past end of message. */
1018 x1 = VALUE16(tvb, cur_offset);
1019 y1 = VALUE16(tvb, cur_offset + 2);
1020 x2 = VALUE16(tvb, cur_offset + 4);
1021 y2 = VALUE16(tvb, cur_offset + 6);
1023 ttt = proto_tree_add_none_format(tt, hf_x11_segment, tvb, cur_offset, 8,
1024 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1025 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1026 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1027 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1028 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1032 /* XXX - the protocol tree code should handle non-printable characters.
1033 Note that "non-printable characters" may depend on your locale.... */
1034 static void stringCopy(char *dest, const char *source, int length)
1039 if (!isgraph(c) && c != ' ') c = '.';
1045 static void listOfString8(tvbuff_t *tvb, int hf, int hf_item, int length)
1048 guint allocated = 0;
1052 /* Compute total length */
1054 int scanning_offset = cur_offset; /* Scanning pointer */
1056 for(i = length; i; i--) {
1057 l = tvb_get_guint8(tvb, scanning_offset);
1058 scanning_offset += 1 + l;
1061 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1064 unsigned l = VALUE8(tvb, cur_offset);
1065 if (allocated < (l + 1)) {
1066 /* g_realloc doesn't work ??? */
1068 s = g_malloc(l + 1);
1071 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1072 proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
1073 cur_offset += l + 1;
1078 #define STRING16_MAX_DISPLAYED_LENGTH 150
1080 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1082 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1083 for(; length > 0; cur_offset += 2, length--) {
1084 if (tvb_get_guint8(tvb, cur_offset))
1090 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1092 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1093 int hf, int hf_bytes,
1094 int offset, unsigned length,
1095 char **s, int *sLength)
1097 int truncated = FALSE;
1098 unsigned l = length / 2;
1100 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1102 int soffset = offset;
1104 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1106 l = STRING16_MAX_DISPLAYED_LENGTH;
1108 if (*sLength < (int) l + 3) {
1110 *s = g_malloc(l + 3);
1115 if (truncated) l -= 3;
1119 *dp++ = tvb_get_guint8(tvb, soffset);
1124 /* If truncated, add an ellipsis */
1125 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1128 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1129 proto_registrar_get_nth(hf) -> name, *s);
1131 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1135 static void listOfTextItem(tvbuff_t *tvb, int hf, int sizeIs16)
1142 /* Compute total length */
1144 int scanning_offset = cur_offset; /* Scanning pointer */
1145 int l; /* Length of an individual item */
1146 int n = 0; /* Number of items */
1148 while(scanning_offset < next_offset) {
1149 l = tvb_get_guint8(tvb, scanning_offset);
1153 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1156 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1159 unsigned l = VALUE8(tvb, cur_offset);
1160 if (l == 255) { /* Item is a font */
1161 fid = tvb_get_ntohl(tvb, cur_offset + 1);
1162 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
1164 } else { /* Item is a string */
1166 gint8 delta = VALUE8(tvb, cur_offset + 1);
1167 if (sizeIs16) l += l;
1168 if ((unsigned) allocated < l + 1) {
1169 /* g_realloc doesn't work ??? */
1171 s = g_malloc(l + 1);
1174 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
1175 ttt = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
1176 "textitem (string): delta = %d, \"%s\"",
1178 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
1180 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
1181 hf_x11_textitem_string_string16_bytes,
1185 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
1186 cur_offset + 2, l, s, "\"%s\"", s);
1187 cur_offset += l + 2;
1193 static guint32 field8(tvbuff_t *tvb, int hf)
1195 guint32 v = VALUE8(tvb, cur_offset);
1196 header_field_info *hfi = proto_registrar_get_nth(hf);
1197 gchar *enumValue = NULL;
1198 gchar *nameAsChar = hfi -> name;
1201 enumValue = match_strval(v, cVALS(hfi -> strings));
1203 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
1205 proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
1210 static guint32 field16(tvbuff_t *tvb, int hf)
1212 guint32 v = VALUE16(tvb, cur_offset);
1213 proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
1218 static guint32 field32(tvbuff_t *tvb, int hf)
1220 guint32 v = VALUE32(tvb, cur_offset);
1221 header_field_info *hfi = proto_registrar_get_nth(hf);
1222 gchar *enumValue = NULL;
1223 gchar *nameAsChar = hfi -> name;
1226 enumValue = match_strval(v, cVALS(hfi -> strings));
1228 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1230 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v,
1231 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1237 static void gcAttributes(tvbuff_t *tvb)
1239 BITMASK32(gc_value);
1240 BITFIELD(ENUM8, gc_value_mask, function);
1241 BITFIELD(CARD32, gc_value_mask, plane_mask);
1242 BITFIELD(CARD32, gc_value_mask, foreground);
1243 BITFIELD(CARD32, gc_value_mask, background);
1244 BITFIELD(CARD16, gc_value_mask, line_width);
1245 BITFIELD(ENUM8, gc_value_mask, line_style);
1246 BITFIELD(ENUM8, gc_value_mask, cap_style);
1247 BITFIELD(ENUM8, gc_value_mask, join_style);
1248 BITFIELD(ENUM8, gc_value_mask, fill_style);
1249 BITFIELD(ENUM8, gc_value_mask, fill_rule);
1250 BITFIELD(PIXMAP, gc_value_mask, tile);
1251 BITFIELD(PIXMAP, gc_value_mask, stipple);
1252 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
1253 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
1254 BITFIELD(FONT, gc_value_mask, font);
1255 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
1256 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
1257 BITFIELD(INT16, gc_value_mask, clip_x_origin);
1258 BITFIELD(INT16, gc_value_mask, clip_y_origin);
1259 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1260 BITFIELD(CARD16, gc_value_mask, dash_offset);
1261 BITFIELD(CARD8, gc_value_mask, gc_dashes);
1262 BITFIELD(ENUM8, gc_value_mask, arc_mode);
1265 static void gcMask(tvbuff_t *tvb)
1267 BITMASK32(gc_value);
1268 FLAG(gc_value, function);
1269 FLAG(gc_value, plane_mask);
1270 FLAG(gc_value, foreground);
1271 FLAG(gc_value, background);
1272 FLAG(gc_value, line_width);
1273 FLAG(gc_value, line_style);
1274 FLAG(gc_value, cap_style);
1275 FLAG(gc_value, join_style);
1276 FLAG(gc_value, fill_style);
1277 FLAG(gc_value, fill_rule);
1278 FLAG(gc_value, tile);
1279 FLAG(gc_value, stipple);
1280 FLAG(gc_value, tile_stipple_x_origin);
1281 FLAG(gc_value, tile_stipple_y_origin);
1282 FLAG(gc_value, font);
1283 FLAG(gc_value, subwindow_mode);
1284 FLAG(gc_value, graphics_exposures);
1285 FLAG(gc_value, clip_x_origin);
1286 FLAG(gc_value, clip_y_origin);
1287 FLAG(gc_value, clip_mask);
1288 FLAG(gc_value, dash_offset);
1289 FLAG(gc_value, gc_dashes);
1290 FLAG(gc_value, arc_mode);
1293 static guint32 requestLength(tvbuff_t *tvb)
1295 guint32 res = VALUE16(tvb, cur_offset) * 4;
1296 proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
1301 static void setOfEvent(tvbuff_t *tvb)
1303 struct maskStruct save = lastMask;
1305 FLAG(event, KeyPress);
1306 FLAG(event, KeyRelease);
1307 FLAG(event, ButtonPress);
1308 FLAG(event, ButtonRelease);
1309 FLAG(event, EnterWindow);
1310 FLAG(event, LeaveWindow);
1311 FLAG(event, PointerMotion);
1312 FLAG(event, PointerMotionHint);
1313 FLAG(event, Button1Motion);
1314 FLAG(event, Button2Motion);
1315 FLAG(event, Button3Motion);
1316 FLAG(event, Button4Motion);
1317 FLAG(event, Button5Motion);
1318 FLAG(event, ButtonMotion);
1319 FLAG(event, KeymapState);
1320 FLAG(event, Exposure);
1321 FLAG(event, VisibilityChange);
1322 FLAG(event, StructureNotify);
1323 FLAG(event, ResizeRedirect);
1324 FLAG(event, SubstructureNotify);
1325 FLAG(event, SubstructureRedirect);
1326 FLAG(event, FocusChange);
1327 FLAG(event, PropertyChange);
1328 FLAG(event, ColormapChange);
1329 FLAG(event, OwnerGrabButton);
1330 FLAG(event, erroneous_bits);
1334 static void setOfDeviceEvent(tvbuff_t *tvb)
1336 struct maskStruct save = lastMask;
1337 BITMASK32(do_not_propagate);
1338 FLAG(do_not_propagate, KeyPress);
1339 FLAG(do_not_propagate, KeyRelease);
1340 FLAG(do_not_propagate, ButtonPress);
1341 FLAG(do_not_propagate, ButtonRelease);
1342 FLAG(do_not_propagate, PointerMotion);
1343 FLAG(do_not_propagate, Button1Motion);
1344 FLAG(do_not_propagate, Button2Motion);
1345 FLAG(do_not_propagate, Button3Motion);
1346 FLAG(do_not_propagate, Button4Motion);
1347 FLAG(do_not_propagate, Button5Motion);
1348 FLAG(do_not_propagate, ButtonMotion);
1349 FLAG(do_not_propagate, erroneous_bits);
1353 static void setOfKeyMask(tvbuff_t *tvb)
1355 struct maskStruct save = lastMask;
1356 lastMask._value = VALUE16(tvb, cur_offset);
1357 lastMask._offset = cur_offset;
1359 if (lastMask._value == 0x8000)
1360 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
1361 "modifiers-masks: 0x8000 (AnyModifier)");
1363 lastMask._tree = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2,
1365 FLAG(modifiers, Shift);
1366 FLAG(modifiers, Lock);
1367 FLAG(modifiers, Control);
1368 FLAG(modifiers, Mod1);
1369 FLAG(modifiers, Mod2);
1370 FLAG(modifiers, Mod3);
1371 FLAG(modifiers, Mod4);
1372 FLAG(modifiers, Mod5);
1373 FLAG(modifiers, erroneous_bits);
1379 static void setOfPointerEvent(tvbuff_t *tvb)
1381 struct maskStruct save = lastMask;
1382 BITMASK16(pointer_event);
1383 FLAG(pointer_event, ButtonPress);
1384 FLAG(pointer_event, ButtonRelease);
1385 FLAG(pointer_event, EnterWindow);
1386 FLAG(pointer_event, LeaveWindow);
1387 FLAG(pointer_event, PointerMotion);
1388 FLAG(pointer_event, PointerMotionHint);
1389 FLAG(pointer_event, Button1Motion);
1390 FLAG(pointer_event, Button2Motion);
1391 FLAG(pointer_event, Button3Motion);
1392 FLAG(pointer_event, Button4Motion);
1393 FLAG(pointer_event, Button5Motion);
1394 FLAG(pointer_event, ButtonMotion);
1395 FLAG(pointer_event, KeymapState);
1396 FLAG(pointer_event, erroneous_bits);
1400 static void string8(tvbuff_t *tvb, const char *nameAsChar, int hf, unsigned length)
1402 char *s = g_malloc(length + 1);
1403 stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
1404 proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
1406 cur_offset += length;
1409 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1411 static void string16(tvbuff_t *tvb, int hf, int hf_bytes, unsigned length)
1416 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, cur_offset, length, &s, &l);
1418 cur_offset += length;
1421 static void timestamp(tvbuff_t *tvb, const char *nameAsChar, int hf)
1423 guint32 v = VALUE32(tvb, cur_offset);
1425 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1427 proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
1431 static void windowAttributes(tvbuff_t *tvb)
1433 BITMASK32(window_value);
1434 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1435 BITFIELD(CARD32, window_value_mask, background_pixel);
1436 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1437 BITFIELD(CARD32, window_value_mask, border_pixel);
1438 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1439 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1440 BITFIELD(ENUM8, window_value_mask, backing_store);
1441 BITFIELD(CARD32, window_value_mask, backing_planes);
1442 BITFIELD(CARD32, window_value_mask, backing_pixel);
1443 BITFIELD(BOOL, window_value_mask, override_redirect);
1444 BITFIELD(BOOL, window_value_mask, save_under);
1445 BITFIELD(SETofEVENT, window_value_mask, event_mask);
1446 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1447 BITFIELD(COLORMAP, window_value_mask, colormap);
1448 BITFIELD(CURSOR, window_value_mask, cursor);
1451 /************************************************************************
1453 *** D E C O D I N G O N E P A C K E T ***
1455 ************************************************************************/
1457 static int dissect_x11_request_loop(tvbuff_t *tvb, proto_tree *root)
1459 int left = tvb_reported_length(tvb), nextLeft;
1465 /* The X11 data stream to the server is just a sequence of requests,
1466 each of which contains a length; for now, we dissect all the
1467 requests in this frame until we run out of data in the frame.
1468 Eventually, we should handle requests that cross frame
1471 Note that "in this frame" refers to everything in the frame
1472 as it appeared in the wire, not as it was captured; we want
1473 an exception to be thrown if we go past the end of the
1474 captured data in the frame without going past the end of the
1475 data in the frame. */
1479 /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
1481 /* We ran out of data - we don't have enough data in
1482 the frame to get the length of this request. */
1485 length = VALUE16(tvb, cur_offset + 2) * 4;
1486 /* fprintf(stderr, "length = %d\n", length);*/
1487 if (left < length) {
1488 /* We ran out of data - we don't have enough data in
1489 the frame for the full request. */
1493 /* Bogus message length? */
1497 next_offset = cur_offset + length;
1498 nextLeft = left - length;
1500 ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
1501 t = proto_item_add_subtree(ti, ett_x11_request);
1506 case 1: /* CreateWindow */
1515 CARD16(border_width);
1516 ENUM16(window_class);
1518 windowAttributes(tvb);
1521 case 2: /* ChangeWindowAttributes */
1525 windowAttributes(tvb);
1528 case 3: /* GetWindowAttributes */
1529 case 4: /* DestroyWindow */
1530 case 5: /* DestroySubwindows */
1536 case 6: /* ChangeSaveSet */
1537 ENUM8(save_set_mode);
1542 case 7: /* ReparentWindow */
1551 case 8: /* MapWindow */
1552 case 9: /* MapSubWindow */
1553 case 10: /* UnmapWindow */
1554 case 11: /* UnmapSubwindows */
1560 case 12: /* ConfigureWindow */
1564 BITMASK16(configure_window);
1566 BITFIELD(INT16, configure_window_mask, x);
1567 BITFIELD(INT16, configure_window_mask, y);
1568 BITFIELD(CARD16, configure_window_mask, width);
1569 BITFIELD(CARD16, configure_window_mask, height);
1570 BITFIELD(CARD16, configure_window_mask, border_width);
1571 BITFIELD(WINDOW, configure_window_mask, sibling);
1572 BITFIELD(ENUM8, configure_window_mask, stack_mode);
1576 case 13: /* CirculateWindow */
1582 case 14: /* GetGeometry */
1583 case 15: /* QueryTree */
1589 case 16: /* InternAtom */
1590 BOOL(only_if_exists);
1592 v16 = FIELD16(name_length);
1598 case 17: /* GetAtomName */
1604 case 18: /* ChangeProperty */
1612 v32 = CARD32(data_length);
1613 LISTofBYTE(data, v32);
1617 case 19: /* DeleteProperty */
1624 case 20: /* GetProperty */
1629 ATOM(get_property_type);
1630 CARD32(long_offset);
1631 CARD32(long_length);
1634 case 21: /* ListProperties */
1640 case 22: /* SetSelectionOwner */
1648 case 23: /* GetSelectionOwner */
1654 case 24: /* ConvertSelection */
1664 case 26: /* GrabPointer */
1667 WINDOW(grab_window);
1668 SETofPOINTEREVENT(pointer_event_mask);
1669 ENUM8(pointer_mode);
1670 ENUM8(keyboard_mode);
1676 case 27: /* UngrabPointer */
1682 case 28: /* GrabButton */
1685 WINDOW(grab_window);
1686 SETofPOINTEREVENT(event_mask);
1687 ENUM8(pointer_mode);
1688 ENUM8(keyboard_mode);
1693 SETofKEYMASK(modifiers);
1696 case 29: /* UngrabButton */
1699 WINDOW(grab_window);
1700 SETofKEYMASK(modifiers);
1704 case 30: /* ChangeActivePointerGrab */
1709 SETofPOINTEREVENT(event_mask);
1713 case 31: /* GrabKeyboard */
1716 WINDOW(grab_window);
1718 ENUM8(pointer_mode);
1719 ENUM8(keyboard_mode);
1723 case 32: /* UngrabKeyboard */
1729 case 33: /* GrabKey */
1732 WINDOW(grab_window);
1733 SETofKEYMASK(modifiers);
1735 ENUM8(pointer_mode);
1736 ENUM8(keyboard_mode);
1740 case 34: /* UngrabKey */
1743 WINDOW(grab_window);
1744 SETofKEYMASK(modifiers);
1748 case 35: /* AllowEvents */
1749 ENUM8(allow_events_mode);
1754 case 36: /* GrabServer */
1759 case 37: /* UngrabServer */
1764 case 38: /* QueryPointer */
1770 case 39: /* GetMotionEvents */
1778 case 40: /* TranslateCoordinates */
1787 case 41: /* WarpPointer */
1790 WINDOW(warp_pointer_src_window);
1791 WINDOW(warp_pointer_dst_window);
1800 case 42: /* SetInputFocus */
1807 case 43: /* GetInputFocus */
1812 case 44: /* QueryKeymap */
1817 case 45: /* OpenFont */
1821 v16 = FIELD16(name_length);
1827 case 46: /* CloseFont */
1833 case 47: /* QueryFont */
1839 case 48: /* QueryTextExtents */
1840 v8 = BOOL(odd_length);
1843 STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
1847 case 49: /* ListFonts */
1851 v16 = FIELD16(pattern_length);
1852 STRING8(pattern, v16);
1856 case 50: /* ListFontsWithInfo */
1860 v16 = FIELD16(pattern_length);
1861 STRING8(pattern, v16);
1865 case 51: /* SetFontPath */
1868 v16 = CARD16(str_number_in_path);
1870 LISTofSTRING8(path, v16);
1874 case 52: /* GetFontPath */
1879 case 53: /* CreatePixmap */
1888 case 54: /* FreePixmap */
1894 case 55: /* CreateGC */
1902 case 56: /* ChangeGC */
1909 case 57: /* CopyGC */
1917 case 58: /* SetDashes */
1921 CARD16(dash_offset);
1922 v16 = FIELD16(dashes_length);
1923 LISTofCARD8(dashes, v16);
1927 case 59: /* SetClipRectangles */
1931 INT16(clip_x_origin);
1932 INT16(clip_y_origin);
1933 LISTofRECTANGLE(rectangles);
1936 case 60: /* FreeGC */
1942 case 61: /* ClearArea */
1952 case 62: /* CopyArea */
1955 DRAWABLE(src_drawable);
1956 DRAWABLE(dst_drawable);
1966 case 63: /* CopyPlane */
1969 DRAWABLE(src_drawable);
1970 DRAWABLE(dst_drawable);
1981 case 64: /* PolyPoint */
1982 ENUM8(coordinate_mode);
1983 v16 = REQUEST_LENGTH();
1986 LISTofPOINT(points, v16 - 12);
1989 case 65: /* PolyLine */
1990 ENUM8(coordinate_mode);
1991 v16 = REQUEST_LENGTH();
1994 LISTofPOINT(points, v16 - 12);
1997 case 66: /* PolySegment */
2002 LISTofSEGMENT(segments);
2005 case 67: /* PolyRectangle */
2010 LISTofRECTANGLE(rectangles);
2013 case 68: /* PolyArc */
2021 case 69: /* FillPoly */
2023 v16 = REQUEST_LENGTH();
2027 ENUM8(coordinate_mode);
2029 LISTofPOINT(points, v16 - 16);
2032 case 70: /* PolyFillRectangle */
2037 LISTofRECTANGLE(rectangles);
2040 case 71: /* PolyFillArc */
2048 case 72: /* PutImage */
2049 ENUM8(image_format);
2050 v16 = REQUEST_LENGTH();
2060 LISTofBYTE(data, v16 - 24);
2064 case 73: /* GetImage */
2065 ENUM8(image_pixmap_format);
2075 case 74: /* PolyText8 */
2077 v16 = REQUEST_LENGTH();
2082 LISTofTEXTITEM8(items);
2086 case 75: /* PolyText16 */
2088 v16 = REQUEST_LENGTH();
2093 LISTofTEXTITEM16(items);
2097 case 76: /* ImageText8 */
2098 v8 = FIELD8(string_length);
2104 STRING8(string, v8);
2108 case 77: /* ImageText16 */
2109 v8 = FIELD8(string_length);
2115 STRING16(string16, v8);
2119 case 78: /* CreateColormap */
2127 case 79: /* FreeColormap */
2133 case 80: /* CopyColormapAndFree */
2140 case 81: /* InstallColormap */
2146 case 82: /* UninstallColormap */
2152 case 83: /* ListInstalledColormaps */
2158 case 84: /* AllocColor */
2168 case 85: /* AllocNamedColor */
2172 v16 = FIELD16(name_length);
2178 case 86: /* AllocColorCells */
2186 case 87: /* AllocColorPlanes */
2196 case 88: /* FreeColors */
2198 v16 = REQUEST_LENGTH();
2201 LISTofCARD32(pixels, v16 - 12);
2204 case 89: /* StoreColors */
2206 v16 = REQUEST_LENGTH();
2208 LISTofCOLORITEM(color_items, v16 - 8);
2211 case 90: /* StoreNamedColor */
2216 v16 = FIELD16(name_length);
2222 case 91: /* QueryColors */
2224 v16 = REQUEST_LENGTH();
2226 LISTofCARD32(pixels, v16 - 8);
2229 case 92: /* LookupColor */
2233 v16 = FIELD16(name_length);
2239 case 93: /* CreateCursor */
2243 PIXMAP(source_pixmap);
2255 case 94: /* CreateGlyphCursor */
2261 CARD16(source_char);
2271 case 95: /* FreeCursor */
2277 case 96: /* RecolorCursor */
2289 case 97: /* QueryBestSize */
2297 case 98: /* QueryExtension */
2300 v16 = FIELD16(name_length);
2306 case 99: /* ListExtensions */
2311 case 100: /* ChangeKeyboardMapping */
2312 v8 = FIELD8(keycode_count);
2314 KEYCODE(first_keycode);
2315 v8_2 = FIELD8(keysyms_per_keycode);
2317 LISTofKEYSYM(keysyms, v8, v8_2);
2320 case 101: /* GetKeyboardMapping */
2323 KEYCODE(first_keycode);
2328 case 102: /* ChangeKeyboardControl */
2331 BITMASK32(keyboard_value);
2332 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2333 BITFIELD(INT8, keyboard_value_mask, bell_percent);
2334 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2335 BITFIELD(INT16, keyboard_value_mask, bell_duration);
2336 BITFIELD(INT16, keyboard_value_mask, led);
2337 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2338 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2339 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2342 case 103: /* GetKeyboardControl */
2347 case 104: /* Bell */
2352 case 105: /* ChangePointerControl */
2355 INT16(acceleration_numerator);
2356 INT16(acceleration_denominator);
2358 BOOL(do_acceleration);
2362 case 106: /* GetPointerControl */
2367 case 107: /* SetScreenSaver */
2372 ENUM8(prefer_blanking);
2373 ENUM8(allow_exposures);
2377 case 108: /* GetScreenSaver */
2382 case 109: /* ChangeHosts */
2383 ENUM8(change_host_mode);
2387 v16 = CARD16(address_length);
2388 LISTofCARD8(address, v16);
2391 case 110: /* ListHosts */
2396 case 111: /* SetAccessControl */
2401 case 112: /* SetCloseDownMode */
2402 ENUM8(close_down_mode);
2406 case 113: /* KillClient */
2412 case 114: /* RotateProperties */
2414 v16 = REQUEST_LENGTH();
2416 CARD16(property_number);
2418 LISTofATOM(properties, (v16 - 12));
2421 case 115: /* ForceScreenSaver */
2422 ENUM8(screen_saver_mode);
2426 case 116: /* SetPointerMapping */
2427 v8 = FIELD8(map_length);
2429 LISTofCARD8(map, v8);
2433 case 117: /* GetPointerMapping */
2438 case 118: /* SetModifierMapping */
2439 v8 = FIELD8(keycodes_per_modifier);
2441 LISTofKEYCODE(keycodes, v8);
2444 case 119: /* GetModifierMapping */
2449 case 127: /* NoOperation */
2454 if (cur_offset < next_offset)
2455 proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
2456 cur_offset = next_offset;
2463 /************************************************************************
2465 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2467 ************************************************************************/
2469 static GTree *byte_ordering_cache = NULL;
2470 static GMemChunk *address_chunk = NULL;
2471 static GMemChunk *ipv4_chunk = NULL;
2472 static GMemChunk *ipv6_chunk = NULL;
2474 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2476 const address *a = (const address *)aa;
2477 const address *b = (const address *)bb;
2478 int c = b -> type - a -> type;
2480 c = b -> len - a -> len;
2482 return memcmp(b -> data, a -> data, a -> len);
2485 /* If we can't guess, we return TRUE (that is little_endian), cause
2486 I'm developing on a Linux box :-). The (non-)guess isn't cached
2487 however, so we may have more luck next time. I'm quite conservative
2488 in my assertions, cause once it's cached, it's stay in cache, and
2489 we may be fooled up by a packet starting with the end of a request
2490 started in a previous packet...
2493 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2495 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2498 while(maskLength--) {
2499 int c = tvb_get_guint8(tvb, offset);
2501 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2506 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2508 if (listLength > length) return FALSE;
2509 while(listLength--) {
2511 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2512 l = tvb_get_guint8(tvb, offset);
2515 if (l > length) return FALSE;
2516 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2520 if (length > 3) return FALSE;
2524 static int rounded4(int n)
2526 int remainder = n % 4;
2528 if (remainder) res++;
2532 /* We assume the order to be consistent, until proven wrong. */
2534 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2536 switch(tvb_get_guint8(tvb, offset)) {
2537 case 1: /* CreateWindow */
2538 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2540 case 2: /* ChangeWindowAttributes */
2541 case 56: /* ChangeGC */
2542 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2544 case 3: /* GetWindowAttributes */
2545 case 4: /* DestroyWindow */
2546 case 5: /* DestroySubwindows */
2547 case 6: /* ChangeSaveSet */
2548 case 8: /* MapWindow */
2549 case 9: /* MapSubWindow */
2550 case 10: /* UnmapWindow */
2551 case 11: /* UnmapSubwindows */
2552 case 13: /* CirculateWindow */
2553 case 14: /* GetGeometry */
2554 case 15: /* QueryTree */
2555 case 17: /* GetAtomName */
2556 case 21: /* ListProperties */
2557 case 23: /* GetSelectionOwner */
2558 case 27: /* UngrabPointer */
2559 case 32: /* UngrabKeyboard */
2560 case 35: /* AllowEvents */
2561 case 38: /* QueryPointer */
2562 case 46: /* CloseFont */
2563 case 47: /* QueryFont */
2564 case 54: /* FreePixmap */
2565 case 60: /* FreeGC */
2566 case 79: /* FreeColormap */
2567 case 81: /* InstallColormap */
2568 case 82: /* UninstallColormap */
2569 case 83: /* ListInstalledColormaps */
2570 case 95: /* FreeCursor */
2571 case 101: /* GetKeyboardMapping */
2572 case 113: /* KillClient */
2575 case 7: /* ReparentWindow */
2576 case 22: /* SetSelectionOwner */
2577 case 30: /* ChangeActivePointerGrab */
2578 case 31: /* GrabKeyboard */
2579 case 33: /* GrabKey */
2580 case 39: /* GetMotionEvents */
2581 case 40: /* TranslateCoordinates */
2582 case 53: /* CreatePixmap */
2583 case 57: /* CopyGC */
2584 case 61: /* ClearArea */
2585 case 78: /* CreateColormap */
2586 case 84: /* AllocColor */
2587 case 87: /* AllocColorPlanes */
2590 case 12: /* ConfigureWindow */
2591 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2593 case 16: /* InternAtom */
2594 case 98: /* QueryExtension */
2595 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2597 case 18: /* ChangeProperty */
2599 int multiplier, type;
2600 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2601 type = tvb_get_guint8(tvb, 16);
2602 if (type != 8 && type != 16 && type != 32) return FALSE;
2603 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2604 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2605 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2608 case 19: /* DeleteProperty */
2609 case 29: /* UngrabButton */
2610 case 34: /* UngrabKey */
2611 case 42: /* SetInputFocus */
2612 case 80: /* CopyColormapAndFree */
2613 case 86: /* AllocColorCells */
2614 case 97: /* QueryBestSize */
2615 case 105: /* ChangePointerControl */
2616 case 107: /* SetScreenSaver */
2619 case 20: /* GetProperty */
2620 case 24: /* ConvertSelection */
2621 case 26: /* GrabPointer */
2622 case 28: /* GrabButton */
2623 case 41: /* WarpPointer */
2626 case 25: /* SendEvent */
2627 return length == 11;
2629 case 36: /* GrabServer */
2630 case 37: /* UngrabServer */
2631 case 43: /* GetInputFocus */
2632 case 44: /* QueryKeymap */
2633 case 52: /* GetFontPath */
2634 case 99: /* ListExtensions */
2635 case 103: /* GetKeyboardControl */
2636 case 104: /* Bell */
2637 case 106: /* GetPointerControl */
2638 case 108: /* GetScreenSaver */
2639 case 110: /* ListHosts */
2640 case 111: /* SetAccessControl */
2641 case 112: /* SetCloseDownMode */
2642 case 115: /* ForceScreenSaver */
2643 case 117: /* GetPointerMapping */
2644 case 119: /* GetModifierMapping */
2647 case 45: /* OpenFont */
2648 case 85: /* AllocNamedColor */
2649 case 92: /* LookupColor */
2650 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2652 case 48: /* QueryTextExtents */
2655 case 49: /* ListFonts */
2656 case 50: /* ListFontsWithInfo */
2657 case 109: /* ChangeHosts */
2658 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2660 case 51: /* SetFontPath */
2661 if (length < 2) return FALSE;
2662 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2663 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2665 case 55: /* CreateGC */
2666 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2668 case 58: /* SetDashes */
2669 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2671 case 59: /* SetClipRectangles */
2672 case 66: /* PolySegment */
2673 case 67: /* PolyRectangle */
2674 case 70: /* PolyFillRectangle */
2675 return length >= 3 && (length - 3) % 2 == 0;
2677 case 62: /* CopyArea */
2680 case 63: /* CopyPlane */
2681 case 93: /* CreateCursor */
2682 case 94: /* CreateGlyphCursor */
2685 case 64: /* PolyPoint */
2686 case 65: /* PolyLine */
2687 case 88: /* FreeColors */
2690 case 68: /* PolyArc */
2691 case 71: /* PolyFillArc */
2692 return length >= 3 && (length - 3) % 3 == 0;
2694 case 69: /* FillPoly */
2695 case 76: /* ImageText8 */
2698 case 72: /* PutImage */
2701 case 73: /* GetImage */
2702 case 96: /* RecolorCursor */
2705 case 74: /* PolyText8 */
2706 if (length < 4) return FALSE;
2707 return TRUE; /* We don't perform many controls on this one */
2709 case 75: /* PolyText16 */
2710 if (length < 4) return FALSE;
2711 return TRUE; /* We don't perform many controls on this one */
2713 case 77: /* ImageText16 */
2716 case 89: /* StoreColors */
2717 return length > 2 && (length - 2) % 3 == 0;
2719 case 90: /* StoreNamedColor */
2720 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2722 case 91: /* QueryColors */
2725 case 100: /* ChangeKeyboardMapping */
2726 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2728 case 102: /* ChangeKeyboardControl */
2729 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2731 case 114: /* RotateProperties */
2732 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2734 case 116: /* SetPointerMapping */
2735 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2737 case 118: /* SetModifierMapping */
2738 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2740 case 127: /* NoOperation */
2748 /* -1 means doesn't match, +1 means match, 0 means don't know */
2750 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2752 int offset, nextoffset;
2755 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2757 length = v16(tvb, offset + 2);
2758 if (!length) return -1;
2759 nextoffset = offset + length * 4;
2760 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2767 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
2769 /* With X the client gives the byte ordering for the protocol,
2770 and the port on the server tells us we're speaking X. */
2772 int le, be, decision, decisionToCache;
2774 gboolean is_reply = (pinfo->srcport == pinfo->match_port);
2775 address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
2776 gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2777 if (cache) return cache > 0 ? TRUE : FALSE;
2778 if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
2780 le = x_endian_match(tvb, tvb_get_letohs);
2781 be = x_endian_match(tvb, tvb_get_ntohs);
2783 /* remember that "decision" really means "little_endian". */
2785 /* We have no reason to believe it's little- rather than
2786 big-endian, so we guess the shortest length is the
2789 if (!tvb_bytes_exist(tvb, 0, 4))
2790 /* Not even a way to get the length. We're biased
2791 toward little endianness here (essentially the
2792 x86 world right now). Decoding won't go very far
2797 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2799 decision = le >= be;
2801 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2802 if (decisionToCache) {
2803 /* We encode the decision as 1 for TRUE and -1 for FALSE
2804 to be able to distinguish between FALSE and no value in
2805 the cache when recalling the value.
2810 if (addr -> type == AT_IPv4) {
2812 address_data = g_mem_chunk_alloc(ipv4_chunk);
2813 } else if (addr -> type == AT_IPv6) {
2814 address_length = 16;
2815 address_data = g_mem_chunk_alloc(ipv6_chunk);
2817 address_length = addr -> len;
2818 address_data = g_malloc(address_length);
2820 cached = g_mem_chunk_alloc(address_chunk);
2821 memcpy(address_data, addr -> data, address_length);
2822 SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2823 g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2827 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2828 pinfo->fd -> num, le, be, decision, decisionToCache);
2833 /************************************************************************
2835 *** I N I T I A L I Z A T I O N A N D M A I N ***
2837 ************************************************************************/
2840 dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2842 /* Set up structures we will need to add the protocol subtree and manage it */
2844 proto_tree *x11_tree;
2847 /* This field shows up as the "Info" column in the display; you should make
2848 it, if possible, summarize what's in the packet, so that a user looking
2849 at the list of packets can tell what type of packet it is. */
2850 if (check_col(pinfo->cinfo, COL_INFO))
2851 col_set_str(pinfo->cinfo, COL_INFO, "X11 request");
2853 /* In the interest of speed, if "tree" is NULL, don't do any work not
2854 necessary to generate protocol tree items. */
2856 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2857 x11_tree = proto_item_add_subtree(ti, ett_x11);
2860 little_endian = guess_byte_ordering(tvb, pinfo);
2861 left = dissect_x11_request_loop(tvb, x11_tree);
2863 call_dissector(data_handle,tvb_new_subset(tvb, cur_offset,-1, tvb_reported_length_remaining(tvb,cur_offset)), pinfo, x11_tree);
2867 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2869 /* Set up structures we will need to add the protocol subtree and manage it */
2871 proto_tree *x11_tree;
2873 /* This field shows up as the "Info" column in the display; you should make
2874 it, if possible, summarize what's in the packet, so that a user looking
2875 at the list of packets can tell what type of packet it is. */
2876 if (check_col(pinfo->cinfo, COL_INFO))
2877 col_set_str(pinfo->cinfo, COL_INFO, "X11 event");
2879 /* In the interest of speed, if "tree" is NULL, don't do any work not
2880 necessary to generate protocol tree items. */
2882 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2883 x11_tree = proto_item_add_subtree(ti, ett_x11);
2885 /* Code to process the packet goes here */
2887 call_dissector(data_handle,tvb, pinfo, x11_tree);
2892 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2894 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2895 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
2897 if (pinfo->match_port == pinfo->destport)
2898 dissect_x11_request(tvb, pinfo, tree);
2900 dissect_x11_event(tvb, pinfo, tree);
2903 /* Register the protocol with Ethereal */
2904 void proto_register_x11(void)
2907 /* Setup list of header fields */
2908 static hf_register_info hf[] = {
2910 { &hf_x11_FIELDABBREV,
2911 { "FIELDNAME", "x11.FIELDABBREV",
2912 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
2913 "FIELDDESCR", HFILL }
2916 #include "x11-register-info.h"
2919 /* Setup protocol subtree array */
2920 static gint *ett[] = {
2925 /* Register the protocol name and description */
2926 proto_x11 = proto_register_protocol("X11", "X11", "x11");
2928 /* Required function calls to register the header fields and subtrees used */
2929 proto_register_field_array(proto_x11, hf, array_length(hf));
2930 proto_register_subtree_array(ett, array_length(ett));
2932 byte_ordering_cache = g_tree_new(compareAddresses);
2933 address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address),
2934 sizeof(address) * 128, G_ALLOC_ONLY);
2935 ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
2936 ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
2941 proto_reg_handoff_x11(void)
2943 dissector_handle_t x11_handle;
2945 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
2946 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
2947 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
2948 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
2949 data_handle = find_dissector("data");