2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
5 * $Id: packet-x11.c,v 1.2 2000/06/12 08:28:13 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
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/
59 #ifdef HAVE_SYS_TYPES_H
60 # include <sys/types.h>
63 #ifdef HAVE_NETINET_IN_H
64 # include <netinet/in.h>
67 #ifdef NEED_SNPRINTF_H
73 # include "snprintf.h"
80 #define cVALS(x) (const value_string*)(x)
82 /* Initialize the protocol and registered fields */
83 static int proto_x11 = -1;
85 #include "packet-x11-declarations.h"
87 /* Initialize the subtree pointers */
88 static gint ett_x11 = -1;
89 static gint ett_x11_request = -1;
91 #define TCP_PORT_X11 6000
92 #define TCP_PORT_X11_2 6001
93 #define TCP_PORT_X11_3 6002
95 /************************************************************************
97 *** E N U M T A B L E S D E F I N I T I O N S ***
99 ************************************************************************/
101 static const value_string access_mode_vals[] = {
107 static const value_string all_temporary_vals[] = {
108 { 0, "AllTemporary" },
112 static const value_string alloc_vals[] = {
118 static const value_string allow_events_mode_vals[] = {
119 { 0, "AsyncPointer" },
120 { 1, "SyncPointer" },
121 { 2, "ReplayPointer" },
122 { 3, "AsyncKeyboard" },
123 { 4, "SyncKeyboard" },
124 { 5, "ReplayKeyboard" },
130 static const value_string arc_mode_vals[] = {
136 static const char *atom_predefined_interpretation[] = {
188 "UNDERLINE_POSITION",
189 "UNDERLINE_THICKNESS",
208 static const value_string auto_repeat_mode_vals[] = {
215 static const value_string background_pixmap_vals[] = {
217 { 1, "ParentRelative" },
221 static const value_string backing_store_vals[] = {
228 static const value_string border_pixmap_vals[] = {
229 { 0, "CopyFromParent" },
233 static const value_string button_vals[] = {
234 { 0x8000, "AnyButton" },
238 static const value_string cap_style_vals[] = {
246 static const value_string class_vals[] = {
253 static const value_string close_down_mode_vals[] = {
255 { 1, "RetainPermanent" },
256 { 2, "RetainTemporary" },
260 static const value_string coordinate_mode_vals[] = {
266 static const value_string direction_vals[] = {
267 { 0, "RaiseLowest" },
268 { 1, "LowerHighest" },
272 static const value_string family_vals[] = {
279 static const value_string fill_rule_vals[] = {
285 static const value_string fill_style_vals[] = {
289 { 3, "OpaqueStippled" },
293 static const value_string focus_vals[] = {
295 { 1, "PointerRoot" },
299 static const value_string function_vals[] = {
304 { 4, "AndInverted" },
312 { 12, "CopyInverted" },
313 { 13, "OrInverted" },
319 static const value_string gravity_vals[] = {
333 static const value_string image_format_vals[] = {
340 static const value_string image_pixmap_format_vals[] = {
346 static const value_string join_style_vals[] = {
353 static const value_string key_vals[] = {
358 #include "packet-x11-keysym.h"
360 static const value_string line_style_vals[] = {
367 static const value_string mode_vals[] = {
374 static const value_string on_off_vals[] = {
380 static const value_string opcode_vals[] = {
381 { 1, "CreateWindow" },
382 { 2, "ChangeWindowAttributes" },
383 { 3, "GetWindowAttributes" },
384 { 4, "DestroyWindow" },
385 { 5, "DestroySubwindows" },
386 { 6, "ChangeSaveSet" },
387 { 7, "ReparentWindow" },
389 { 9, "MapSubwindows" },
390 { 10, "UnmapWindow" },
391 { 11, "UnmapSubwindows" },
392 { 12, "ConfigureWindow" },
393 { 13, "CirculateWindow" },
394 { 14, "GetGeometry" },
396 { 16, "InternAtom" },
397 { 17, "GetAtomName" },
398 { 18, "ChangeProperty" },
399 { 19, "DeleteProperty" },
400 { 20, "GetProperty" },
401 { 21, "ListProperties" },
402 { 22, "SetSelectionOwner" },
403 { 23, "GetSelectionOwner" },
404 { 24, "ConvertSelection" },
406 { 26, "GrabPointer" },
407 { 27, "UngrabPointer" },
408 { 28, "GrabButton" },
409 { 29, "UngrabButton" },
410 { 30, "ChangeActivePointerGrab" },
411 { 31, "GrabKeyboard" },
412 { 32, "UngrabKeyboard" },
415 { 35, "AllowEvents" },
416 { 36, "GrabServer" },
417 { 37, "UngrabServer" },
418 { 38, "QueryPointer" },
419 { 39, "GetMotionEvents" },
420 { 40, "TranslateCoordinates" },
421 { 41, "WarpPointer" },
422 { 42, "SetInputFocus" },
423 { 43, "GetInputFocus" },
424 { 44, "QueryKeymap" },
428 { 48, "QueryTextExtents" },
430 { 50, "ListFontsWithInfo" },
431 { 51, "SetFontPath" },
432 { 52, "GetFontPath" },
433 { 53, "CreatePixmap" },
434 { 54, "FreePixmap" },
439 { 59, "SetClipRectangles" },
446 { 66, "PolySegment" },
447 { 67, "PolyRectangle" },
450 { 70, "PolyFillRectangle" },
451 { 71, "PolyFillArc" },
455 { 75, "PolyText16" },
456 { 76, "ImageText8" },
457 { 77, "ImageText16" },
458 { 78, "CreateColormap" },
459 { 79, "FreeColormap" },
460 { 80, "CopyColormapAndFree" },
461 { 81, "InstallColormap" },
462 { 82, "UninstallColormap" },
463 { 83, "ListInstalledColormaps" },
464 { 84, "AllocColor" },
465 { 85, "AllocNamedColor" },
466 { 86, "AllocColorCells" },
467 { 87, "AllocColorPlanes" },
468 { 88, "FreeColors" },
469 { 89, "StoreColors" },
470 { 90, "StoreNamedColor" },
471 { 91, "QueryColors" },
472 { 92, "LookupColor" },
473 { 93, "CreateCursor" },
474 { 94, "CreateGlyphCursor" },
475 { 95, "FreeCursor" },
476 { 96, "RecolorCursor" },
477 { 97, "QueryBestSize" },
478 { 98, "QueryExtension" },
479 { 99, "ListExtensions" },
480 { 100, "ChangeKeyboardMapping" },
481 { 101, "GetKeyboardMapping" },
482 { 102, "ChangeKeyboardControl" },
483 { 103, "GetKeyboardControl" },
485 { 105, "ChangePointerControl" },
486 { 106, "GetPointerControl" },
487 { 107, "SetScreenSaver" },
488 { 108, "GetScreenSaver" },
489 { 109, "ChangeHosts" },
490 { 110, "ListHosts" },
491 { 111, "SetAccessControl" },
492 { 112, "SetCloseDownMode" },
493 { 113, "KillClient" },
494 { 114, "RotateProperties" },
495 { 115, "ForceScreenSaver" },
496 { 116, "SetPointerMapping" },
497 { 117, "GetPointerMapping" },
498 { 118, "SetModifierMapping" },
499 { 119, "GetModifierMapping" },
500 { 127, "NoOperation" },
504 static const value_string ordering_vals[] = {
512 static const value_string plane_mask_vals[] = {
513 { AllPlanes, "AllPlanes" },
517 static const value_string pointer_keyboard_mode_vals[] = {
518 { 0, "Synchronous" },
519 { 1, "Asynchronous" },
523 static const value_string revert_to_vals[] = {
525 { 1, "PointerRoot" },
530 static const value_string insert_delete_vals[] = {
536 static const value_string screen_saver_mode_vals[] = {
542 static const value_string shape_vals[] = {
549 static const value_string stack_mode_vals[] = {
558 static const value_string subwindow_mode_vals[] = {
559 { 0, "ClipByChildren" },
560 { 1, "IncludeInferiors" },
564 static const value_string window_class_vals[] = {
565 { 0, "CopyFromParent" },
566 { 1, "InputOutput" },
571 static const value_string yes_no_default_vals[] = {
578 static const value_string zero_is_any_property_type_vals[] = {
579 { 0, "AnyPropertyType" },
583 static const value_string zero_is_none_vals[] = {
588 /************************************************************************
590 *** G L O B A L V A R I A B L E S ( A R G H H ! ) ***
592 ************************************************************************/
594 static int cur_offset; /* The current offset in the frame */
595 static int next_offset = NULL; /* Offset of the next request in the frame */
596 static tvbuff_t *tvb = NULL;
597 static gboolean little_endian = TRUE;
598 static proto_tree *t = NULL;
600 static struct maskStruct {
605 } lastMask = { 0, 0, 0, NULL };
607 /************************************************************************
609 *** F I E L D D E C O D I N G M A C R O S ***
611 ************************************************************************/
613 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
614 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
615 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
617 #define FIELD8(name) (field8(hf_x11_##name))
618 #define FIELD16(name) (field16(hf_x11_##name))
619 #define FIELD32(name) (field32(hf_x11_##name))
621 #define BITFIELD(TYPE, position, name) {\
622 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
624 int save = cur_offset;\
625 proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
626 lastMask._zone, little_endian); \
628 unused = save + 4 - cur_offset;\
630 proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
631 cur_offset = save + 4;\
635 #define FLAG(position, name) {\
636 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
637 proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
639 #define ATOM(name) { atom(t, hf_x11_##name); }
640 #define BITGRAVITY(name) { gravity(#name, hf_x11_##name, "Forget"); }
641 #define BITMASK8(name) { bitmask(hf_x11_##name##_mask, 1); }
642 #define BITMASK16(name) { bitmask(hf_x11_##name##_mask, 2); }
643 #define BITMASK32(name) { bitmask(hf_x11_##name##_mask, 4); }
644 #define BOOL(name) (boolean(#name, hf_x11_##name))
645 #define BUTTON(name) { FIELD8(name); }
646 #define CARD8(name) { FIELD8(name); }
647 #define CARD16(name) (FIELD16(name))
648 #define CARD32(name) (FIELD32(name))
649 #define COLOR_FLAGS(name) { colorFlags(t); }
650 #define COLORMAP(name) { FIELD32(name); }
651 #define CURSOR(name) { FIELD32(name); }
652 #define DRAWABLE(name) { FIELD32(name); }
653 #define ENUM8(name) { FIELD8(name); }
654 #define ENUM16(name) { FIELD16(name); }
655 #define FONT(name) { FIELD32(name); }
656 #define FONTABLE(name) { FIELD32(name); }
657 #define GCONTEXT(name) { FIELD32(name); }
658 #define INT8(name) { FIELD8(name); }
659 #define INT16(name) { FIELD16(name); }
660 #define KEYCODE(name) { FIELD8(name); }
661 #define LISTofARC(name) { listOfArc(hf_x11_##name, (next_offset - cur_offset) / 12); }
662 #define LISTofATOM(name, length) { listOfAtom(hf_x11_##name, (length) / 4); }
663 #define LISTofBYTE(name, length) { listOfByte(hf_x11_##name, (length)); }
664 #define LISTofCARD8(name, length) { listOfByte(hf_x11_##name, (length)); }
665 #define LISTofCARD32(name, length) { listOfCard32(hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
666 #define LISTofCOLORITEM(name, length) { listOfColorItem(hf_x11_##name, (length) / 12); }
667 #define LISTofKEYCODE(name, length) { listOfKeycode(hf_x11_##name, (length)); }
668 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
669 listOfKeysyms(hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
670 #define LISTofPOINT(name, length) { listOfPoint(hf_x11_##name, (length) / 4); }
671 #define LISTofRECTANGLE(name) { listOfRectangle(hf_x11_##name, (next_offset - cur_offset) / 8); }
672 #define LISTofSEGMENT(name) { listOfSegment(hf_x11_##name, (next_offset - cur_offset) / 8); }
673 #define LISTofSTRING8(name, length) { listOfString8(hf_x11_##name, hf_x11_##name##_string, (length)); }
674 #define LISTofTEXTITEM8(name) { listOfTextItem(hf_x11_##name, FALSE); }
675 #define LISTofTEXTITEM16(name) { listOfTextItem(hf_x11_##name, TRUE); }
676 #define OPCODE() { opcode = FIELD8(opcode); }
677 #define PIXMAP(name) { FIELD32(name); }
678 #define REQUEST_LENGTH() (requestLength())
679 #define SETofEVENT(name) { setOfEvent(); }
680 #define SETofDEVICEEVENT(name) { setOfDeviceEvent();}
681 #define SETofKEYMASK(name) { setOfKeyMask(); }
682 #define SETofPOINTEREVENT(name) { setOfPointerEvent(); }
683 #define STRING8(name, length) { string8(#name, hf_x11_##name, length); }
684 #define STRING16(name, length) { string16(hf_x11_##name, hf_x11_##name##_bytes, length); }
685 #define TIMESTAMP(name){ timestamp(#name, hf_x11_##name); }
686 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, x, little_endian); p += x; }
687 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, x, little_endian); cur_offset += x; }
688 #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; }
689 #define WINDOW(name) { FIELD32(name); }
690 #define WINGRAVITY(name) { gravity(#name, hf_x11_##name, "Unmap"); }
692 #define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
693 proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
694 v ? "" : " (CopyFromParent)"); cur_offset += 4; }
696 /************************************************************************
698 *** D E C O D I N G F I E L D S ***
700 ************************************************************************/
702 static void atom(proto_tree *t, int hf)
704 const char *interpretation = NULL;
706 guint32 v = VALUE32(tvb, cur_offset);
707 if (v >= 1 && v < array_length(atom_predefined_interpretation))
708 interpretation = atom_predefined_interpretation[v];
710 interpretation = "Not a predefined atom";
712 struct header_field_info *hfi = proto_registrar_get_nth(hf);
714 interpretation = match_strval(v, cVALS(hfi -> strings));
716 if (!interpretation) interpretation = "error in Xlib client program ?";
717 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %d (%s)",
718 proto_registrar_get_nth(hf) -> name, v, interpretation);
722 static void bitmask(int hf, int size)
724 lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
725 lastMask._offset = cur_offset;
726 lastMask._zone = size;
727 lastMask._tree = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
731 static guint32 boolean(const char *nameAsChar, int hf)
733 guint32 v = VALUE8(tvb, cur_offset);
734 proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
739 static void colorFlags(proto_tree *t)
741 unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
744 if (do_red_green_blue) {
747 char *bp = buffer + sprintf(buffer, "flags: ");
749 if (do_red_green_blue & 0x1) {
750 bp += sprintf(bp, "DoRed");
754 if (do_red_green_blue & 0x2) {
755 if (sep) bp += sprintf(bp, " | ");
756 bp += sprintf(bp, "DoGreen");
760 if (do_red_green_blue & 0x4) {
761 if (sep) bp += sprintf(bp, " | ");
762 bp += sprintf(bp, "DoBlue");
766 if (do_red_green_blue & 0xf8) {
767 if (sep) bp += sprintf(bp, " + ");
768 sprintf(bp, "trash");
771 tt = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
773 if (do_red_green_blue & 0x1)
774 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1,
775 do_red_green_blue & 0x1);
776 if (do_red_green_blue & 0x2)
777 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1,
778 do_red_green_blue & 0x2);
779 if (do_red_green_blue & 0x4)
780 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1,
781 do_red_green_blue & 0x4);
782 if (do_red_green_blue & 0xf8)
783 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1,
784 do_red_green_blue & 0xf8);
786 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
791 static void gravity(const char *nameAsChar, int hf, const char *nullInterpretation)
793 guint8 v = VALUE8(tvb, cur_offset);
795 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar,
798 proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
802 static void listOfArc(int hf, int length)
804 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
806 gint16 x = VALUE16(tvb, cur_offset);
807 gint16 y = VALUE16(tvb, cur_offset + 2);
808 guint16 width = VALUE16(tvb, cur_offset + 4);
809 guint16 height = VALUE16(tvb, cur_offset + 6);
810 gint16 angle1 = VALUE16(tvb, cur_offset + 8);
811 gint16 angle2 = VALUE16(tvb, cur_offset + 10);
813 proto_tree *ttt = proto_tree_add_protocol_format(tt, hf_x11_arc, tvb, cur_offset, 12,
814 "arc: %dx%d%+d%+d, angle %d -> %d (%f° -> %f°)",
815 width, height, x, y, angle1, angle2,
816 angle1 / 64.0, angle2 / 64.0);
817 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
818 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
819 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
820 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
821 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
822 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
826 static void listOfAtom(int hf, int length)
828 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
830 if (cur_offset + 4 > next_offset) {
831 /* List runs past end of message. */
834 atom(tt, hf_x11_properties_item);
838 static void listOfByte(int hf, int length)
840 if (cur_offset + length > next_offset) {
841 /* List runs past end of message. */
842 length = next_offset - cur_offset;
844 if (length <= 0) length = 1;
845 proto_tree_add_bytes(t, hf, tvb, cur_offset, length, tvb_get_ptr(tvb, cur_offset, length));
846 cur_offset += length;
849 static void listOfCard32(int hf, int hf_item, int length)
851 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
853 if (cur_offset + 4 > next_offset) {
854 /* List runs past end of message. */
857 proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
862 static void listOfColorItem(int hf, int length)
864 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
867 unsigned do_red_green_blue;
868 guint16 red, green, blue;
873 if (cur_offset + 12 > next_offset) {
874 /* List runs past end of message. */
877 red = VALUE16(tvb, cur_offset + 4);
878 green = VALUE16(tvb, cur_offset + 6);
879 blue = VALUE16(tvb, cur_offset + 8);
880 do_red_green_blue = VALUE8(tvb, cur_offset + 10);
882 bp = buffer + sprintf(buffer, "colorItem: ");
884 if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
885 if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
886 if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
888 ttt = proto_tree_add_protocol_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
889 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
890 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
891 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
892 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
894 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
898 static GTree *keysymTable = NULL;
900 static gint compareGuint32(gconstpointer a, gconstpointer b)
902 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
905 static const char *keysymString(guint32 v)
910 /* This table is so big that we built it only if necessary */
912 const value_string *p = keysym_vals_source;
913 keysymTable = g_tree_new(compareGuint32);
914 for(; p -> strptr; p++)
915 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
917 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
918 return res ? res : "Unknown";
921 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
923 static void listOfKeycode(int hf, int length)
926 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
933 if (cur_offset + 8 > next_offset) {
934 /* List runs past end of message. */
937 for(i = 8, m = modifiers; i; i--, m++) {
938 u_char c = tvb_get_guint8(tvb, cur_offset);
940 if (c) bp += sprintf(bp, " %s=%d", *m, c);
943 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);
947 static void listOfKeysyms(int hf, int hf_item, int keycode_count, int keysyms_per_keycode)
949 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
955 while(keycode_count--) {
956 if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
957 /* List runs past end of message. */
960 bp = buffer + sprintf(buffer, "keysyms:");
961 for(i = 0; i < keysyms_per_keycode; i++) {
962 bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
965 ttt = proto_tree_add_protocol_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
967 for(i = keysyms_per_keycode; i; i--) {
968 guint32 v = VALUE32(tvb, cur_offset);
969 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
970 "keysym: 0x%08x (%s)", v, keysymString(v));
976 static void listOfPoint(int hf, int length)
978 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
983 if (cur_offset + 4 > next_offset) {
984 /* List runs past end of message. */
987 x = VALUE16(tvb, cur_offset);
988 y = VALUE16(tvb, cur_offset + 2);
990 ttt = proto_tree_add_protocol_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
991 proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
992 proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
996 static void listOfRectangle(int hf, int length)
998 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1001 unsigned width, height;
1004 if (cur_offset + 8 > next_offset) {
1005 /* List runs past end of message. */
1008 x = VALUE16(tvb, cur_offset);
1009 y = VALUE16(tvb, cur_offset + 2);
1010 width = VALUE16(tvb, cur_offset + 4);
1011 height = VALUE16(tvb, cur_offset + 6);
1013 ttt = proto_tree_add_protocol_format(tt, hf_x11_rectangle, tvb, cur_offset, 8,
1014 "rectangle: %dx%d%+d%+d", width, height, x, y);
1015 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
1016 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
1017 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
1018 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
1022 static void listOfSegment(int hf, int length)
1024 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1026 gint16 x1, y1, x2, y2;
1029 if (cur_offset + 8 > next_offset) {
1030 /* List runs past end of message. */
1033 x1 = VALUE16(tvb, cur_offset);
1034 y1 = VALUE16(tvb, cur_offset + 2);
1035 x2 = VALUE16(tvb, cur_offset + 4);
1036 y2 = VALUE16(tvb, cur_offset + 6);
1038 ttt = proto_tree_add_protocol_format(tt, hf_x11_segment, tvb, cur_offset, 8,
1039 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1040 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1041 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1042 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1043 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1047 /* XXX - the protocol tree code should handle non-printable characters.
1048 Note that "non-printable characters" may depend on your locale.... */
1049 static void stringCopy(char *dest, const char *source, int length)
1054 if (!isgraph(c) && c != ' ') c = '.';
1060 static void listOfString8(int hf, int hf_item, int length)
1067 /* Compute total length */
1069 int scanning_offset = cur_offset; /* Scanning pointer */
1071 for(i = length; i; i--) {
1072 l = tvb_get_guint8(tvb, scanning_offset);
1073 scanning_offset += 1 + l;
1076 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1079 unsigned l = VALUE8(tvb, cur_offset);
1080 if (allocated < l + 1) {
1081 /* g_realloc doesn't work ??? */
1083 s = g_malloc(l + 1);
1086 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1087 proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
1088 cur_offset += l + 1;
1093 #define STRING16_MAX_DISPLAYED_LENGTH 150
1095 static int stringIsActuallyAn8BitString(int offset, unsigned length)
1097 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1098 for(; length > 0; cur_offset += 2, length--) {
1099 if (tvb_get_guint8(tvb, cur_offset))
1105 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1107 static void string16_with_buffer_preallocated(proto_tree *t, int hf, int hf_bytes,
1108 int offset, unsigned length,
1109 char **s, int *sLength)
1111 int truncated = FALSE;
1112 unsigned l = length / 2;
1114 if (stringIsActuallyAn8BitString(offset, l)) {
1116 int soffset = offset;
1118 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1120 l = STRING16_MAX_DISPLAYED_LENGTH;
1122 if (*sLength < l + 3) {
1124 *s = g_malloc(l + 3);
1129 if (truncated) l -= 3;
1133 *dp++ = tvb_get_guint8(tvb, soffset);
1138 /* If truncated, add an ellipsis */
1139 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1142 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1143 proto_registrar_get_nth(hf) -> name, *s);
1145 proto_tree_add_bytes(t, hf_bytes, tvb, offset, length, tvb_get_ptr(tvb, offset, length));
1149 static void listOfTextItem(int hf, int sizeIs16)
1156 /* Compute total length */
1158 int scanning_offset = cur_offset; /* Scanning pointer */
1159 int l; /* Length of an individual item */
1160 int n = 0; /* Number of items */
1162 while(scanning_offset < next_offset) {
1163 l = tvb_get_guint8(tvb, scanning_offset);
1167 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1170 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1173 unsigned l = VALUE8(tvb, cur_offset);
1174 if (l == 255) { /* Item is a font */
1175 fid = tvb_get_ntohl(tvb, cur_offset + 1);
1176 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
1178 } else { /* Item is a string */
1180 gint8 delta = VALUE8(tvb, cur_offset + 1);
1181 if (sizeIs16) l += l;
1182 if (allocated < l + 1) {
1183 /* g_realloc doesn't work ??? */
1185 s = g_malloc(l + 1);
1188 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
1189 ttt = proto_tree_add_protocol_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
1190 "textitem (string): delta = %d, \"%s\"",
1192 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
1194 string16_with_buffer_preallocated(ttt, hf_x11_textitem_string_string16,
1195 hf_x11_textitem_string_string16_bytes,
1199 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
1200 cur_offset + 2, l, s, "\"%s\"", s);
1201 cur_offset += l + 2;
1207 static guint32 field8(int hf)
1209 guint32 v = VALUE8(tvb, cur_offset);
1210 struct header_field_info *hfi = proto_registrar_get_nth(hf);
1211 gchar *enumValue = NULL;
1212 gchar *nameAsChar = hfi -> name;
1215 enumValue = match_strval(v, cVALS(hfi -> strings));
1217 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %d (%s)", nameAsChar, v, enumValue);
1219 proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
1224 static guint32 field16(int hf)
1226 guint32 v = VALUE16(tvb, cur_offset);
1227 proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
1232 static guint32 field32(int hf)
1234 guint32 v = VALUE32(tvb, cur_offset);
1235 struct header_field_info *hfi = proto_registrar_get_nth(hf);
1236 gchar *enumValue = NULL;
1237 gchar *nameAsChar = hfi -> name;
1240 enumValue = match_strval(v, cVALS(hfi -> strings));
1242 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1244 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v,
1245 hfi -> display == BASE_DEC ? "%s: %d" : "%s : 0x%08x",
1251 static void gcAttributes(void)
1253 BITMASK32(gc_value);
1254 BITFIELD(ENUM8, gc_value_mask, function);
1255 BITFIELD(CARD32, gc_value_mask, plane_mask);
1256 BITFIELD(CARD32, gc_value_mask, foreground);
1257 BITFIELD(CARD32, gc_value_mask, background);
1258 BITFIELD(CARD16, gc_value_mask, line_width);
1259 BITFIELD(ENUM8, gc_value_mask, line_style);
1260 BITFIELD(ENUM8, gc_value_mask, cap_style);
1261 BITFIELD(ENUM8, gc_value_mask, join_style);
1262 BITFIELD(ENUM8, gc_value_mask, fill_style);
1263 BITFIELD(ENUM8, gc_value_mask, fill_rule);
1264 BITFIELD(PIXMAP, gc_value_mask, tile);
1265 BITFIELD(PIXMAP, gc_value_mask, stipple);
1266 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
1267 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
1268 BITFIELD(FONT, gc_value_mask, font);
1269 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
1270 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
1271 BITFIELD(INT16, gc_value_mask, clip_x_origin);
1272 BITFIELD(INT16, gc_value_mask, clip_y_origin);
1273 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1274 BITFIELD(CARD16, gc_value_mask, dash_offset);
1275 BITFIELD(CARD8, gc_value_mask, gc_dashes);
1276 BITFIELD(ENUM8, gc_value_mask, arc_mode);
1279 static void gcMask(void)
1281 BITMASK32(gc_value);
1282 FLAG(gc_value, function);
1283 FLAG(gc_value, plane_mask);
1284 FLAG(gc_value, foreground);
1285 FLAG(gc_value, background);
1286 FLAG(gc_value, line_width);
1287 FLAG(gc_value, line_style);
1288 FLAG(gc_value, cap_style);
1289 FLAG(gc_value, join_style);
1290 FLAG(gc_value, fill_style);
1291 FLAG(gc_value, fill_rule);
1292 FLAG(gc_value, tile);
1293 FLAG(gc_value, stipple);
1294 FLAG(gc_value, tile_stipple_x_origin);
1295 FLAG(gc_value, tile_stipple_y_origin);
1296 FLAG(gc_value, font);
1297 FLAG(gc_value, subwindow_mode);
1298 FLAG(gc_value, graphics_exposures);
1299 FLAG(gc_value, clip_x_origin);
1300 FLAG(gc_value, clip_y_origin);
1301 FLAG(gc_value, clip_mask);
1302 FLAG(gc_value, dash_offset);
1303 FLAG(gc_value, gc_dashes);
1304 FLAG(gc_value, arc_mode);
1307 static guint32 requestLength(void)
1309 guint32 res = VALUE16(tvb, cur_offset) * 4;
1310 proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
1315 static void setOfEvent(void)
1317 struct maskStruct save = lastMask;
1319 FLAG(event, KeyPress);
1320 FLAG(event, KeyRelease);
1321 FLAG(event, ButtonPress);
1322 FLAG(event, ButtonRelease);
1323 FLAG(event, EnterWindow);
1324 FLAG(event, LeaveWindow);
1325 FLAG(event, PointerMotion);
1326 FLAG(event, PointerMotionHint);
1327 FLAG(event, Button1Motion);
1328 FLAG(event, Button2Motion);
1329 FLAG(event, Button3Motion);
1330 FLAG(event, Button4Motion);
1331 FLAG(event, Button5Motion);
1332 FLAG(event, ButtonMotion);
1333 FLAG(event, KeymapState);
1334 FLAG(event, Exposure);
1335 FLAG(event, VisibilityChange);
1336 FLAG(event, StructureNotify);
1337 FLAG(event, ResizeRedirect);
1338 FLAG(event, SubstructureNotify);
1339 FLAG(event, SubstructureRedirect);
1340 FLAG(event, FocusChange);
1341 FLAG(event, PropertyChange);
1342 FLAG(event, ColormapChange);
1343 FLAG(event, OwnerGrabButton);
1344 FLAG(event, erroneous_bits);
1348 static void setOfDeviceEvent(void)
1350 struct maskStruct save = lastMask;
1351 BITMASK32(do_not_propagate);
1352 FLAG(do_not_propagate, KeyPress);
1353 FLAG(do_not_propagate, KeyRelease);
1354 FLAG(do_not_propagate, ButtonPress);
1355 FLAG(do_not_propagate, ButtonRelease);
1356 FLAG(do_not_propagate, PointerMotion);
1357 FLAG(do_not_propagate, Button1Motion);
1358 FLAG(do_not_propagate, Button2Motion);
1359 FLAG(do_not_propagate, Button3Motion);
1360 FLAG(do_not_propagate, Button4Motion);
1361 FLAG(do_not_propagate, Button5Motion);
1362 FLAG(do_not_propagate, ButtonMotion);
1363 FLAG(do_not_propagate, erroneous_bits);
1367 static void setOfKeyMask(void)
1369 struct maskStruct save = lastMask;
1370 lastMask._value = VALUE16(tvb, cur_offset);
1371 lastMask._offset = cur_offset;
1373 if (lastMask._value == 0x8000)
1374 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
1375 "modifiers-masks: 0x8000 (AnyModifier)");
1377 lastMask._tree = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2,
1379 FLAG(modifiers, Shift);
1380 FLAG(modifiers, Lock);
1381 FLAG(modifiers, Control);
1382 FLAG(modifiers, Mod1);
1383 FLAG(modifiers, Mod2);
1384 FLAG(modifiers, Mod3);
1385 FLAG(modifiers, Mod4);
1386 FLAG(modifiers, Mod5);
1387 FLAG(modifiers, erroneous_bits);
1393 static void setOfPointerEvent(void)
1395 struct maskStruct save = lastMask;
1396 BITMASK16(pointer_event);
1397 FLAG(pointer_event, ButtonPress);
1398 FLAG(pointer_event, ButtonRelease);
1399 FLAG(pointer_event, EnterWindow);
1400 FLAG(pointer_event, LeaveWindow);
1401 FLAG(pointer_event, PointerMotion);
1402 FLAG(pointer_event, PointerMotionHint);
1403 FLAG(pointer_event, Button1Motion);
1404 FLAG(pointer_event, Button2Motion);
1405 FLAG(pointer_event, Button3Motion);
1406 FLAG(pointer_event, Button4Motion);
1407 FLAG(pointer_event, Button5Motion);
1408 FLAG(pointer_event, ButtonMotion);
1409 FLAG(pointer_event, KeymapState);
1410 FLAG(pointer_event, erroneous_bits);
1414 static void string8(const char *nameAsChar, int hf, unsigned length)
1416 char *s = g_malloc(length + 1);
1417 stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
1418 proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
1420 cur_offset += length;
1423 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1425 static void string16(int hf, int hf_bytes, unsigned length)
1430 string16_with_buffer_preallocated(t, hf, hf_bytes, cur_offset, length, &s, &l);
1432 cur_offset += length;
1435 static void timestamp(const char *nameAsChar, int hf)
1437 guint32 v = VALUE32(tvb, cur_offset);
1439 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1441 proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
1445 static void windowAttributes(void)
1447 BITMASK32(window_value);
1448 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1449 BITFIELD(CARD32, window_value_mask, background_pixel);
1450 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1451 BITFIELD(CARD32, window_value_mask, border_pixel);
1452 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1453 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1454 BITFIELD(ENUM8, window_value_mask, backing_store);
1455 BITFIELD(CARD32, window_value_mask, backing_planes);
1456 BITFIELD(CARD32, window_value_mask, backing_pixel);
1457 BITFIELD(BOOL, window_value_mask, override_redirect);
1458 BITFIELD(BOOL, window_value_mask, save_under);
1459 BITFIELD(SETofEVENT, window_value_mask, event_mask);
1460 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1461 BITFIELD(COLORMAP, window_value_mask, colormap);
1462 BITFIELD(CURSOR, window_value_mask, cursor);
1465 /************************************************************************
1467 *** D E C O D I N G O N E P A C K E T ***
1469 ************************************************************************/
1471 static int dissect_x11_request_loop(proto_tree *root)
1473 int left = tvb_reported_length(tvb), nextLeft;
1479 /* The X11 data stream to the server is just a sequence of requests,
1480 each of which contains a length; for now, we dissect all the
1481 requests in this frame until we run out of data in the frame.
1482 Eventually, we should handle requests that cross frame
1485 Note that "in this frame" refers to everything in the frame
1486 as it appeared in the wire, not as it was captured; we want
1487 an exception to be thrown if we go past the end of the
1488 captured data in the frame without going past the end of the
1489 data in the frame. */
1493 /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
1495 /* We ran out of data - we don't have enough data in
1496 the frame to get the length of this request. */
1499 length = VALUE16(tvb, cur_offset + 2) * 4;
1500 /* fprintf(stderr, "length = %d\n", length);*/
1501 if (left < length) {
1502 /* We ran out of data - we don't have enough data in
1503 the frame for the full request. */
1507 /* Bogus message length? */
1511 next_offset = cur_offset + length;
1512 nextLeft = left - length;
1514 ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
1515 t = proto_item_add_subtree(ti, ett_x11_request);
1520 case 1: /* CreateWindow */
1529 CARD16(border_width);
1530 ENUM16(window_class);
1535 case 2: /* ChangeWindowAttributes */
1542 case 3: /* GetWindowAttributes */
1543 case 4: /* DestroyWindow */
1544 case 5: /* DestroySubwindows */
1550 case 6: /* ChangeSaveSet */
1551 ENUM8(save_set_mode);
1556 case 7: /* ReparentWindow */
1565 case 8: /* MapWindow */
1566 case 9: /* MapSubWindow */
1567 case 10: /* UnmapWindow */
1568 case 11: /* UnmapSubwindows */
1574 case 12: /* ConfigureWindow */
1578 BITMASK16(configure_window);
1580 BITFIELD(INT16, configure_window_mask, x);
1581 BITFIELD(INT16, configure_window_mask, y);
1582 BITFIELD(CARD16, configure_window_mask, width);
1583 BITFIELD(CARD16, configure_window_mask, height);
1584 BITFIELD(CARD16, configure_window_mask, border_width);
1585 BITFIELD(WINDOW, configure_window_mask, sibling);
1586 BITFIELD(ENUM8, configure_window_mask, stack_mode);
1590 case 13: /* CirculateWindow */
1596 case 14: /* GetGeometry */
1597 case 15: /* QueryTree */
1603 case 16: /* InternAtom */
1604 BOOL(only_if_exists);
1606 v16 = FIELD16(name_length);
1612 case 17: /* GetAtomName */
1618 case 18: /* ChangeProperty */
1626 v32 = CARD32(data_length);
1627 LISTofBYTE(data, v32);
1631 case 19: /* DeleteProperty */
1638 case 20: /* GetProperty */
1643 ATOM(get_property_type);
1644 CARD32(long_offset);
1645 CARD32(long_length);
1648 case 21: /* ListProperties */
1654 case 22: /* SetSelectionOwner */
1662 case 23: /* GetSelectionOwner */
1668 case 24: /* ConvertSelection */
1678 case 26: /* GrabPointer */
1681 WINDOW(grab_window);
1682 SETofPOINTEREVENT(pointer_event_mask);
1683 ENUM8(pointer_mode);
1684 ENUM8(keyboard_mode);
1690 case 27: /* UngrabPointer */
1696 case 28: /* GrabButton */
1699 WINDOW(grab_window);
1700 SETofPOINTEREVENT(event_mask);
1701 ENUM8(pointer_mode);
1702 ENUM8(keyboard_mode);
1707 SETofKEYMASK(modifiers);
1710 case 29: /* UngrabButton */
1713 WINDOW(grab_window);
1714 SETofKEYMASK(modifiers);
1718 case 30: /* ChangeActivePointerGrab */
1723 SETofPOINTEREVENT(event_mask);
1727 case 31: /* GrabKeyboard */
1730 WINDOW(grab_window);
1732 ENUM8(pointer_mode);
1733 ENUM8(keyboard_mode);
1737 case 32: /* UngrabKeyboard */
1743 case 33: /* GrabKey */
1746 WINDOW(grab_window);
1747 SETofKEYMASK(modifiers);
1749 ENUM8(pointer_mode);
1750 ENUM8(keyboard_mode);
1754 case 34: /* UngrabKey */
1757 WINDOW(grab_window);
1758 SETofKEYMASK(modifiers);
1762 case 35: /* AllowEvents */
1763 ENUM8(allow_events_mode);
1768 case 36: /* GrabServer */
1773 case 37: /* UngrabServer */
1778 case 38: /* QueryPointer */
1784 case 39: /* GetMotionEvents */
1792 case 40: /* TranslateCoordinates */
1801 case 41: /* WarpPointer */
1804 WINDOW(warp_pointer_src_window);
1805 WINDOW(warp_pointer_dst_window);
1814 case 42: /* SetInputFocus */
1821 case 43: /* GetInputFocus */
1826 case 44: /* QueryKeymap */
1831 case 45: /* OpenFont */
1835 v16 = FIELD16(name_length);
1841 case 46: /* CloseFont */
1847 case 47: /* QueryFont */
1853 case 48: /* QueryTextExtents */
1854 v8 = BOOL(odd_length);
1857 STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
1861 case 49: /* ListFonts */
1865 v16 = FIELD16(pattern_length);
1866 STRING8(pattern, v16);
1870 case 50: /* ListFontsWithInfo */
1874 v16 = FIELD16(pattern_length);
1875 STRING8(pattern, v16);
1879 case 51: /* SetFontPath */
1882 v16 = CARD16(str_number_in_path);
1884 LISTofSTRING8(path, v16);
1888 case 52: /* GetFontPath */
1893 case 53: /* CreatePixmap */
1902 case 54: /* FreePixmap */
1908 case 55: /* CreateGC */
1916 case 56: /* ChangeGC */
1923 case 57: /* CopyGC */
1931 case 58: /* SetDashes */
1935 CARD16(dash_offset);
1936 v16 = FIELD16(dashes_length);
1937 LISTofCARD8(dashes, v16);
1941 case 59: /* SetClipRectangles */
1945 INT16(clip_x_origin);
1946 INT16(clip_y_origin);
1947 LISTofRECTANGLE(rectangles);
1950 case 60: /* FreeGC */
1956 case 61: /* ClearArea */
1966 case 62: /* CopyArea */
1969 DRAWABLE(src_drawable);
1970 DRAWABLE(dst_drawable);
1980 case 63: /* CopyPlane */
1983 DRAWABLE(src_drawable);
1984 DRAWABLE(dst_drawable);
1995 case 64: /* PolyPoint */
1996 ENUM8(coordinate_mode);
1997 v16 = REQUEST_LENGTH();
2000 LISTofPOINT(points, v16 - 12);
2003 case 65: /* PolyLine */
2004 ENUM8(coordinate_mode);
2005 v16 = REQUEST_LENGTH();
2008 LISTofPOINT(points, v16 - 12);
2011 case 66: /* PolySegment */
2016 LISTofSEGMENT(segments);
2019 case 67: /* PolyRectangle */
2024 LISTofRECTANGLE(rectangles);
2027 case 68: /* PolyArc */
2035 case 69: /* FillPoly */
2037 v16 = REQUEST_LENGTH();
2041 ENUM8(coordinate_mode);
2043 LISTofPOINT(points, v16 - 16);
2046 case 70: /* PolyFillRectangle */
2051 LISTofRECTANGLE(rectangles);
2054 case 71: /* PolyFillArc */
2062 case 72: /* PutImage */
2063 ENUM8(image_format);
2064 v16 = REQUEST_LENGTH();
2074 LISTofBYTE(data, v16 - 24);
2078 case 73: /* GetImage */
2079 ENUM8(image_pixmap_format);
2089 case 74: /* PolyText8 */
2091 v16 = REQUEST_LENGTH();
2096 LISTofTEXTITEM8(items);
2100 case 75: /* PolyText16 */
2102 v16 = REQUEST_LENGTH();
2107 LISTofTEXTITEM16(items);
2111 case 76: /* ImageText8 */
2112 v8 = FIELD8(string_length);
2118 STRING8(string, v8);
2122 case 77: /* ImageText16 */
2123 v8 = FIELD8(string_length);
2129 STRING16(string16, v8);
2133 case 78: /* CreateColormap */
2141 case 79: /* FreeColormap */
2147 case 80: /* CopyColormapAndFree */
2154 case 81: /* InstallColormap */
2160 case 82: /* UninstallColormap */
2166 case 83: /* ListInstalledColormaps */
2172 case 84: /* AllocColor */
2182 case 85: /* AllocNamedColor */
2186 v16 = FIELD16(name_length);
2192 case 86: /* AllocColorCells */
2200 case 87: /* AllocColorPlanes */
2210 case 88: /* FreeColors */
2212 v16 = REQUEST_LENGTH();
2215 LISTofCARD32(pixels, v16 - 12);
2218 case 89: /* StoreColors */
2220 v16 = REQUEST_LENGTH();
2222 LISTofCOLORITEM(color_items, v16 - 8);
2225 case 90: /* StoreNamedColor */
2230 v16 = FIELD16(name_length);
2236 case 91: /* QueryColors */
2238 v16 = REQUEST_LENGTH();
2240 LISTofCARD32(pixels, v16 - 8);
2243 case 92: /* LookupColor */
2247 v16 = FIELD16(name_length);
2253 case 93: /* CreateCursor */
2257 PIXMAP(source_pixmap);
2269 case 94: /* CreateGlyphCursor */
2275 CARD16(source_char);
2285 case 95: /* FreeCursor */
2291 case 96: /* RecolorCursor */
2303 case 97: /* QueryBestSize */
2311 case 98: /* QueryExtension */
2314 v16 = FIELD16(name_length);
2320 case 99: /* ListExtensions */
2325 case 100: /* ChangeKeyboardMapping */
2326 v8 = FIELD8(keycode_count);
2328 KEYCODE(first_keycode);
2329 v8_2 = FIELD8(keysyms_per_keycode);
2331 LISTofKEYSYM(keysyms, v8, v8_2);
2334 case 101: /* GetKeyboardMapping */
2337 KEYCODE(first_keycode);
2342 case 102: /* ChangeKeyboardControl */
2345 BITMASK32(keyboard_value);
2346 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2347 BITFIELD(INT8, keyboard_value_mask, bell_percent);
2348 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2349 BITFIELD(INT16, keyboard_value_mask, bell_duration);
2350 BITFIELD(INT16, keyboard_value_mask, led);
2351 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2352 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2353 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2356 case 103: /* GetKeyboardControl */
2361 case 104: /* Bell */
2366 case 105: /* ChangePointerControl */
2369 INT16(acceleration_numerator);
2370 INT16(acceleration_denominator);
2372 BOOL(do_acceleration);
2376 case 106: /* GetPointerControl */
2381 case 107: /* SetScreenSaver */
2386 ENUM8(prefer_blanking);
2387 ENUM8(allow_exposures);
2391 case 108: /* GetScreenSaver */
2396 case 109: /* ChangeHosts */
2397 ENUM8(change_host_mode);
2401 v16 = CARD16(address_length);
2402 LISTofCARD8(address, v16);
2405 case 110: /* ListHosts */
2410 case 111: /* SetAccessControl */
2415 case 112: /* SetCloseDownMode */
2416 ENUM8(close_down_mode);
2420 case 113: /* KillClient */
2426 case 114: /* RotateProperties */
2428 v16 = REQUEST_LENGTH();
2430 CARD16(property_number);
2432 LISTofATOM(properties, (v16 - 12));
2435 case 115: /* ForceScreenSaver */
2436 ENUM8(screen_saver_mode);
2440 case 116: /* SetPointerMapping */
2441 v8 = FIELD8(map_length);
2443 LISTofCARD8(map, v8);
2447 case 117: /* GetPointerMapping */
2452 case 118: /* SetModifierMapping */
2453 v8 = FIELD8(keycodes_per_modifier);
2455 LISTofKEYCODE(keycodes, v8);
2458 case 119: /* GetModifierMapping */
2463 case 127: /* NoOperation */
2468 if (cur_offset < next_offset)
2469 proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
2470 cur_offset = next_offset;
2477 /************************************************************************
2479 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2481 ************************************************************************/
2483 static GTree *byte_ordering_cache = NULL;
2484 static GMemChunk *address_chunk = NULL;
2485 static GMemChunk *ipv4_chunk = NULL;
2486 static GMemChunk *ipv6_chunk = NULL;
2488 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2490 const address *a = (const address *)aa;
2491 const address *b = (const address *)bb;
2492 int c = b -> type - a -> type;
2494 c = b -> len - a -> len;
2496 return memcmp(b -> data, a -> data, a -> len);
2499 /* If we can't guess, we return TRUE (that is little_endian), cause
2500 I'm developing on a Linux box :-). The (non-)guess isn't cached
2501 however, so we may have more luck next time. I'm quite conservative
2502 in my assertions, cause once it's cached, it's stay in cache, and
2503 we may be fooled up by a packet starting with the end of a request
2504 started in a previous packet...
2507 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2509 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2512 while(maskLength--) {
2513 int c = tvb_get_guint8(tvb, offset);
2515 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2520 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2522 if (listLength > length) return FALSE;
2523 while(listLength--) {
2525 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2526 l = tvb_get_guint8(tvb, offset);
2529 if (l > length) return FALSE;
2530 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2534 if (length > 3) return FALSE;
2538 static int rounded4(int n)
2540 int remainder = n % 4;
2542 if (remainder) res++;
2546 /* We assume the order to be consistent, until proven wrong. */
2548 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2550 switch(tvb_get_guint8(tvb, offset)) {
2551 case 1: /* CreateWindow */
2552 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2554 case 2: /* ChangeWindowAttributes */
2555 case 56: /* ChangeGC */
2556 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2558 case 3: /* GetWindowAttributes */
2559 case 4: /* DestroyWindow */
2560 case 5: /* DestroySubwindows */
2561 case 6: /* ChangeSaveSet */
2562 case 8: /* MapWindow */
2563 case 9: /* MapSubWindow */
2564 case 10: /* UnmapWindow */
2565 case 11: /* UnmapSubwindows */
2566 case 13: /* CirculateWindow */
2567 case 14: /* GetGeometry */
2568 case 15: /* QueryTree */
2569 case 17: /* GetAtomName */
2570 case 21: /* ListProperties */
2571 case 23: /* GetSelectionOwner */
2572 case 27: /* UngrabPointer */
2573 case 32: /* UngrabKeyboard */
2574 case 35: /* AllowEvents */
2575 case 38: /* QueryPointer */
2576 case 46: /* CloseFont */
2577 case 47: /* QueryFont */
2578 case 54: /* FreePixmap */
2579 case 60: /* FreeGC */
2580 case 79: /* FreeColormap */
2581 case 81: /* InstallColormap */
2582 case 82: /* UninstallColormap */
2583 case 83: /* ListInstalledColormaps */
2584 case 95: /* FreeCursor */
2585 case 101: /* GetKeyboardMapping */
2586 case 113: /* KillClient */
2589 case 7: /* ReparentWindow */
2590 case 22: /* SetSelectionOwner */
2591 case 30: /* ChangeActivePointerGrab */
2592 case 31: /* GrabKeyboard */
2593 case 33: /* GrabKey */
2594 case 39: /* GetMotionEvents */
2595 case 40: /* TranslateCoordinates */
2596 case 53: /* CreatePixmap */
2597 case 57: /* CopyGC */
2598 case 61: /* ClearArea */
2599 case 78: /* CreateColormap */
2600 case 84: /* AllocColor */
2601 case 87: /* AllocColorPlanes */
2604 case 12: /* ConfigureWindow */
2605 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2607 case 16: /* InternAtom */
2608 case 98: /* QueryExtension */
2609 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2611 case 18: /* ChangeProperty */
2613 int multiplier, type;
2614 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2615 type = tvb_get_guint8(tvb, 16);
2616 if (type != 8 && type != 16 && type != 32) return FALSE;
2617 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2618 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2619 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2622 case 19: /* DeleteProperty */
2623 case 29: /* UngrabButton */
2624 case 34: /* UngrabKey */
2625 case 42: /* SetInputFocus */
2626 case 80: /* CopyColormapAndFree */
2627 case 86: /* AllocColorCells */
2628 case 97: /* QueryBestSize */
2629 case 105: /* ChangePointerControl */
2630 case 107: /* SetScreenSaver */
2633 case 20: /* GetProperty */
2634 case 24: /* ConvertSelection */
2635 case 26: /* GrabPointer */
2636 case 28: /* GrabButton */
2637 case 41: /* WarpPointer */
2640 case 25: /* SendEvent */
2641 return length == 11;
2643 case 36: /* GrabServer */
2644 case 37: /* UngrabServer */
2645 case 43: /* GetInputFocus */
2646 case 44: /* QueryKeymap */
2647 case 52: /* GetFontPath */
2648 case 99: /* ListExtensions */
2649 case 103: /* GetKeyboardControl */
2650 case 104: /* Bell */
2651 case 106: /* GetPointerControl */
2652 case 108: /* GetScreenSaver */
2653 case 110: /* ListHosts */
2654 case 111: /* SetAccessControl */
2655 case 112: /* SetCloseDownMode */
2656 case 115: /* ForceScreenSaver */
2657 case 117: /* GetPointerMapping */
2658 case 119: /* GetModifierMapping */
2661 case 45: /* OpenFont */
2662 case 85: /* AllocNamedColor */
2663 case 92: /* LookupColor */
2664 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2666 case 48: /* QueryTextExtents */
2669 case 49: /* ListFonts */
2670 case 50: /* ListFontsWithInfo */
2671 case 109: /* ChangeHosts */
2672 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2674 case 51: /* SetFontPath */
2675 if (length < 2) return FALSE;
2676 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2677 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2679 case 55: /* CreateGC */
2680 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2682 case 58: /* SetDashes */
2683 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2685 case 59: /* SetClipRectangles */
2686 case 66: /* PolySegment */
2687 case 67: /* PolyRectangle */
2688 case 70: /* PolyFillRectangle */
2689 return length >= 3 && (length - 3) % 2 == 0;
2691 case 62: /* CopyArea */
2694 case 63: /* CopyPlane */
2695 case 93: /* CreateCursor */
2696 case 94: /* CreateGlyphCursor */
2699 case 64: /* PolyPoint */
2700 case 65: /* PolyLine */
2701 case 88: /* FreeColors */
2704 case 68: /* PolyArc */
2705 case 71: /* PolyFillArc */
2706 return length >= 3 && (length - 3) % 3 == 0;
2708 case 69: /* FillPoly */
2709 case 76: /* ImageText8 */
2712 case 72: /* PutImage */
2715 case 73: /* GetImage */
2716 case 96: /* RecolorCursor */
2719 case 74: /* PolyText8 */
2720 if (length < 4) return FALSE;
2721 return TRUE; /* We don't perform many controls on this one */
2723 case 75: /* PolyText16 */
2724 if (length < 4) return FALSE;
2725 return TRUE; /* We don't perform many controls on this one */
2727 case 77: /* ImageText16 */
2730 case 89: /* StoreColors */
2731 return length > 2 && (length - 2) % 3 == 0;
2733 case 90: /* StoreNamedColor */
2734 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2736 case 91: /* QueryColors */
2739 case 100: /* ChangeKeyboardMapping */
2740 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2742 case 102: /* ChangeKeyboardControl */
2743 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2745 case 114: /* RotateProperties */
2746 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2748 case 116: /* SetPointerMapping */
2749 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2751 case 118: /* SetModifierMapping */
2752 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2754 case 127: /* NoOperation */
2762 /* -1 means doesn't match, +1 means match, 0 means don't know */
2764 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2766 int offset, nextoffset;
2769 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2771 length = v16(tvb, offset + 2);
2772 if (!length) return -1;
2773 nextoffset = offset + length * 4;
2774 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2781 guess_byte_ordering(tvbuff_t *tvb)
2783 /* With X the client gives the byte ordering for the protocol,
2784 and the port on the server tells us we're speaking X. */
2786 int le, be, decision, decisionToCache;
2788 address *addr = pi.srcport == pi.match_port ? &pi.net_dst : &pi.net_src;
2789 gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2790 if (cache) return cache > 0 ? TRUE : FALSE;
2791 if (pi.srcport == pi.match_port) return TRUE; /* We don't try to guess on a reply / event for now */
2793 le = x_endian_match(tvb, tvb_get_letohs);
2794 be = x_endian_match(tvb, tvb_get_ntohs);
2796 /* remember that "decision" really means "little_endian". */
2798 /* We have no reason to believe it's little- rather than
2799 big-endian, so we guess the shortest length is the
2802 if (!tvb_bytes_exist(tvb, 0, 4))
2803 /* Not even a way to get the length. We're biased
2804 toward little endianness here (essentially the
2805 x86 world right now). Decoding won't go very far
2810 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2812 decision = le >= be;
2814 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2815 if (decisionToCache) {
2816 /* We encode the decision as 1 for TRUE and -1 for FALSE
2817 to be able to distinguish between FALSE and no value in
2818 the cache when recalling the value.
2823 if (addr -> type == AT_IPv4) {
2825 address_data = g_mem_chunk_alloc(ipv4_chunk);
2826 } else if (addr -> type == AT_IPv6) {
2827 address_length = 16;
2828 address_data = g_mem_chunk_alloc(ipv6_chunk);
2830 address_length = addr -> len;
2831 address_data = g_malloc(address_length);
2833 cached = g_mem_chunk_alloc(address_chunk);
2834 memcpy(address_data, addr -> data, address_length);
2835 SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2836 g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2840 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2841 pi.fd -> num, le, be, decision, decisionToCache);
2846 /************************************************************************
2848 *** I N I T I A L I Z A T I O N A N D M A I N ***
2850 ************************************************************************/
2853 dissect_x11_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2855 /* Set up structures we will need to add the protocol subtree and manage it */
2857 proto_tree *x11_tree;
2860 /* Make entries in Protocol column and Info column on summary display */
2861 if (check_col(fd, COL_PROTOCOL))
2862 col_add_str(fd, COL_PROTOCOL, "X11");
2864 /* This field shows up as the "Info" column in the display; you should make
2865 it, if possible, summarize what's in the packet, so that a user looking
2866 at the list of packets can tell what type of packet it is.
2868 "col_add_fstr()" can be used instead of "col_add_str()"; it takes
2869 "printf()"-like arguments. */
2870 if (check_col(fd, COL_INFO))
2871 col_add_str(fd, COL_INFO, "X11 request");
2873 /* In the interest of speed, if "tree" is NULL, don't do any work not
2874 necessary to generate protocol tree items. */
2876 /* NOTE: The offset and length values in the previous call to
2877 "proto_tree_add_item()" define what data bytes to highlight in the hex
2878 display window when the line in the protocol tree display
2879 corresponding to that item is selected.
2881 END_OF_FRAME is a handy way to highlight all data from the offset to
2882 the end of the packet. */
2883 ti = proto_tree_add_item(tree, proto_x11, NullTVB, offset, END_OF_FRAME, FALSE);
2884 x11_tree = proto_item_add_subtree(ti, ett_x11);
2886 /* Code to process the packet goes here */
2888 tvb = tvb_new_subset(pi.compat_top_tvb, offset, -1, -1);
2890 little_endian = guess_byte_ordering(tvb);
2891 left = dissect_x11_request_loop(x11_tree);
2893 dissect_data(pd, offset + cur_offset, fd, x11_tree);
2897 dissect_x11_event(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2899 /* Set up structures we will need to add the protocol subtree and manage it */
2901 proto_tree *x11_tree;
2903 /* Make entries in Protocol column and Info column on summary display */
2904 if (check_col(fd, COL_PROTOCOL))
2905 col_add_str(fd, COL_PROTOCOL, "X11");
2907 /* This field shows up as the "Info" column in the display; you should make
2908 it, if possible, summarize what's in the packet, so that a user looking
2909 at the list of packets can tell what type of packet it is.
2911 "col_add_fstr()" can be used instead of "col_add_str()"; it takes
2912 "printf()"-like arguments. */
2913 if (check_col(fd, COL_INFO))
2914 col_add_str(fd, COL_INFO, "X11 event");
2916 /* In the interest of speed, if "tree" is NULL, don't do any work not
2917 necessary to generate protocol tree items. */
2919 /* NOTE: The offset and length values in the previous call to
2920 "proto_tree_add_item()" define what data bytes to highlight in the hex
2921 display window when the line in the protocol tree display
2922 corresponding to that item is selected.
2924 END_OF_FRAME is a handy way to highlight all data from the offset to
2925 the end of the packet. */
2926 ti = proto_tree_add_item(tree, proto_x11, NullTVB, offset, END_OF_FRAME, FALSE);
2927 x11_tree = proto_item_add_subtree(ti, ett_x11);
2929 /* Code to process the packet goes here */
2931 dissect_data(pd, offset, fd, tree);
2936 dissect_x11(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2938 if (pi.destport == TCP_PORT_X11 || pi.destport == TCP_PORT_X11_2 || pi.destport == TCP_PORT_X11_3)
2939 dissect_x11_request(pd, offset, fd, tree);
2941 dissect_x11_event(pd, offset, fd, tree);
2944 /* Register the protocol with Ethereal */
2945 void proto_register_x11(void)
2948 /* Setup list of header fields */
2949 static hf_register_info hf[] = {
2951 { &hf_x11_FIELDABBREV,
2952 { "FIELDNAME", "x11.FIELDABBREV",
2953 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
2957 #include "packet-x11-register-info.h"
2960 /* Setup protocol subtree array */
2961 static gint *ett[] = {
2966 /* Register the protocol name and description */
2967 proto_x11 = proto_register_protocol("X11", "x11");
2969 /* Required function calls to register the header fields and subtrees used */
2970 proto_register_field_array(proto_x11, hf, array_length(hf));
2971 proto_register_subtree_array(ett, array_length(ett));
2973 byte_ordering_cache = g_tree_new(compareAddresses);
2974 address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address),
2975 sizeof(address) * 128, G_ALLOC_ONLY);
2976 ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
2977 ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
2982 proto_reg_handoff_x11(void)
2984 dissector_add("tcp.port", TCP_PORT_X11, dissect_x11);
2985 dissector_add("tcp.port", TCP_PORT_X11_2, dissect_x11);
2986 dissector_add("tcp.port", TCP_PORT_X11_3, dissect_x11);