2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
5 * $Id: packet-x11.c,v 1.11 2000/08/13 14:09:11 deniel 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/
56 #ifdef HAVE_SYS_TYPES_H
57 # include <sys/types.h>
64 #define cVALS(x) (const value_string*)(x)
66 /* Initialize the protocol and registered fields */
67 static int proto_x11 = -1;
69 #include "packet-x11-declarations.h"
71 /* Initialize the subtree pointers */
72 static gint ett_x11 = -1;
73 static gint ett_x11_request = -1;
75 #define TCP_PORT_X11 6000
76 #define TCP_PORT_X11_2 6001
77 #define TCP_PORT_X11_3 6002
79 /************************************************************************
81 *** E N U M T A B L E S D E F I N I T I O N S ***
83 ************************************************************************/
85 static const value_string access_mode_vals[] = {
91 static const value_string all_temporary_vals[] = {
92 { 0, "AllTemporary" },
96 static const value_string alloc_vals[] = {
102 static const value_string allow_events_mode_vals[] = {
103 { 0, "AsyncPointer" },
104 { 1, "SyncPointer" },
105 { 2, "ReplayPointer" },
106 { 3, "AsyncKeyboard" },
107 { 4, "SyncKeyboard" },
108 { 5, "ReplayKeyboard" },
114 static const value_string arc_mode_vals[] = {
120 static const char *atom_predefined_interpretation[] = {
172 "UNDERLINE_POSITION",
173 "UNDERLINE_THICKNESS",
192 static const value_string auto_repeat_mode_vals[] = {
199 static const value_string background_pixmap_vals[] = {
201 { 1, "ParentRelative" },
205 static const value_string backing_store_vals[] = {
212 static const value_string border_pixmap_vals[] = {
213 { 0, "CopyFromParent" },
217 static const value_string button_vals[] = {
218 { 0x8000, "AnyButton" },
222 static const value_string cap_style_vals[] = {
230 static const value_string class_vals[] = {
237 static const value_string close_down_mode_vals[] = {
239 { 1, "RetainPermanent" },
240 { 2, "RetainTemporary" },
244 static const value_string coordinate_mode_vals[] = {
250 static const value_string direction_vals[] = {
251 { 0, "RaiseLowest" },
252 { 1, "LowerHighest" },
256 static const value_string family_vals[] = {
263 static const value_string fill_rule_vals[] = {
269 static const value_string fill_style_vals[] = {
273 { 3, "OpaqueStippled" },
277 static const value_string focus_vals[] = {
279 { 1, "PointerRoot" },
283 static const value_string function_vals[] = {
288 { 4, "AndInverted" },
296 { 12, "CopyInverted" },
297 { 13, "OrInverted" },
303 static const value_string gravity_vals[] = {
317 static const value_string image_format_vals[] = {
324 static const value_string image_pixmap_format_vals[] = {
330 static const value_string join_style_vals[] = {
337 static const value_string key_vals[] = {
342 #include "packet-x11-keysym.h"
344 static const value_string line_style_vals[] = {
351 static const value_string mode_vals[] = {
358 static const value_string on_off_vals[] = {
364 static const value_string opcode_vals[] = {
365 { 1, "CreateWindow" },
366 { 2, "ChangeWindowAttributes" },
367 { 3, "GetWindowAttributes" },
368 { 4, "DestroyWindow" },
369 { 5, "DestroySubwindows" },
370 { 6, "ChangeSaveSet" },
371 { 7, "ReparentWindow" },
373 { 9, "MapSubwindows" },
374 { 10, "UnmapWindow" },
375 { 11, "UnmapSubwindows" },
376 { 12, "ConfigureWindow" },
377 { 13, "CirculateWindow" },
378 { 14, "GetGeometry" },
380 { 16, "InternAtom" },
381 { 17, "GetAtomName" },
382 { 18, "ChangeProperty" },
383 { 19, "DeleteProperty" },
384 { 20, "GetProperty" },
385 { 21, "ListProperties" },
386 { 22, "SetSelectionOwner" },
387 { 23, "GetSelectionOwner" },
388 { 24, "ConvertSelection" },
390 { 26, "GrabPointer" },
391 { 27, "UngrabPointer" },
392 { 28, "GrabButton" },
393 { 29, "UngrabButton" },
394 { 30, "ChangeActivePointerGrab" },
395 { 31, "GrabKeyboard" },
396 { 32, "UngrabKeyboard" },
399 { 35, "AllowEvents" },
400 { 36, "GrabServer" },
401 { 37, "UngrabServer" },
402 { 38, "QueryPointer" },
403 { 39, "GetMotionEvents" },
404 { 40, "TranslateCoordinates" },
405 { 41, "WarpPointer" },
406 { 42, "SetInputFocus" },
407 { 43, "GetInputFocus" },
408 { 44, "QueryKeymap" },
412 { 48, "QueryTextExtents" },
414 { 50, "ListFontsWithInfo" },
415 { 51, "SetFontPath" },
416 { 52, "GetFontPath" },
417 { 53, "CreatePixmap" },
418 { 54, "FreePixmap" },
423 { 59, "SetClipRectangles" },
430 { 66, "PolySegment" },
431 { 67, "PolyRectangle" },
434 { 70, "PolyFillRectangle" },
435 { 71, "PolyFillArc" },
439 { 75, "PolyText16" },
440 { 76, "ImageText8" },
441 { 77, "ImageText16" },
442 { 78, "CreateColormap" },
443 { 79, "FreeColormap" },
444 { 80, "CopyColormapAndFree" },
445 { 81, "InstallColormap" },
446 { 82, "UninstallColormap" },
447 { 83, "ListInstalledColormaps" },
448 { 84, "AllocColor" },
449 { 85, "AllocNamedColor" },
450 { 86, "AllocColorCells" },
451 { 87, "AllocColorPlanes" },
452 { 88, "FreeColors" },
453 { 89, "StoreColors" },
454 { 90, "StoreNamedColor" },
455 { 91, "QueryColors" },
456 { 92, "LookupColor" },
457 { 93, "CreateCursor" },
458 { 94, "CreateGlyphCursor" },
459 { 95, "FreeCursor" },
460 { 96, "RecolorCursor" },
461 { 97, "QueryBestSize" },
462 { 98, "QueryExtension" },
463 { 99, "ListExtensions" },
464 { 100, "ChangeKeyboardMapping" },
465 { 101, "GetKeyboardMapping" },
466 { 102, "ChangeKeyboardControl" },
467 { 103, "GetKeyboardControl" },
469 { 105, "ChangePointerControl" },
470 { 106, "GetPointerControl" },
471 { 107, "SetScreenSaver" },
472 { 108, "GetScreenSaver" },
473 { 109, "ChangeHosts" },
474 { 110, "ListHosts" },
475 { 111, "SetAccessControl" },
476 { 112, "SetCloseDownMode" },
477 { 113, "KillClient" },
478 { 114, "RotateProperties" },
479 { 115, "ForceScreenSaver" },
480 { 116, "SetPointerMapping" },
481 { 117, "GetPointerMapping" },
482 { 118, "SetModifierMapping" },
483 { 119, "GetModifierMapping" },
484 { 127, "NoOperation" },
488 static const value_string ordering_vals[] = {
496 static const value_string plane_mask_vals[] = {
497 { 0xFFFFFFFF, "AllPlanes" },
501 static const value_string pointer_keyboard_mode_vals[] = {
502 { 0, "Synchronous" },
503 { 1, "Asynchronous" },
507 static const value_string revert_to_vals[] = {
509 { 1, "PointerRoot" },
514 static const value_string insert_delete_vals[] = {
520 static const value_string screen_saver_mode_vals[] = {
526 static const value_string shape_vals[] = {
533 static const value_string stack_mode_vals[] = {
542 static const value_string subwindow_mode_vals[] = {
543 { 0, "ClipByChildren" },
544 { 1, "IncludeInferiors" },
548 static const value_string window_class_vals[] = {
549 { 0, "CopyFromParent" },
550 { 1, "InputOutput" },
555 static const value_string yes_no_default_vals[] = {
562 static const value_string zero_is_any_property_type_vals[] = {
563 { 0, "AnyPropertyType" },
567 static const value_string zero_is_none_vals[] = {
572 /************************************************************************
574 *** G L O B A L V A R I A B L E S ( A R G H H ! ) ***
576 ************************************************************************/
578 static int cur_offset; /* The current offset in the frame */
579 static int next_offset = 0; /* Offset of the next request in the frame */
580 static tvbuff_t *tvb = NULL;
581 static gboolean little_endian = TRUE;
582 static proto_tree *t = NULL;
584 static struct maskStruct {
589 } lastMask = { 0, 0, 0, NULL };
591 /************************************************************************
593 *** F I E L D D E C O D I N G M A C R O S ***
595 ************************************************************************/
597 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
598 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
599 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
601 #define FIELD8(name) (field8(hf_x11_##name))
602 #define FIELD16(name) (field16(hf_x11_##name))
603 #define FIELD32(name) (field32(hf_x11_##name))
605 #define BITFIELD(TYPE, position, name) {\
606 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
608 int save = cur_offset;\
609 proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
610 lastMask._zone, little_endian); \
612 unused = save + 4 - cur_offset;\
614 proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
615 cur_offset = save + 4;\
619 #define FLAG(position, name) {\
620 if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
621 proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
623 #define ATOM(name) { atom(t, hf_x11_##name); }
624 #define BITGRAVITY(name) { gravity(#name, hf_x11_##name, "Forget"); }
625 #define BITMASK8(name) { bitmask(hf_x11_##name##_mask, 1); }
626 #define BITMASK16(name) { bitmask(hf_x11_##name##_mask, 2); }
627 #define BITMASK32(name) { bitmask(hf_x11_##name##_mask, 4); }
628 #define BOOL(name) (add_boolean(#name, hf_x11_##name))
629 #define BUTTON(name) { FIELD8(name); }
630 #define CARD8(name) { FIELD8(name); }
631 #define CARD16(name) (FIELD16(name))
632 #define CARD32(name) (FIELD32(name))
633 #define COLOR_FLAGS(name) { colorFlags(t); }
634 #define COLORMAP(name) { FIELD32(name); }
635 #define CURSOR(name) { FIELD32(name); }
636 #define DRAWABLE(name) { FIELD32(name); }
637 #define ENUM8(name) { FIELD8(name); }
638 #define ENUM16(name) { FIELD16(name); }
639 #define FONT(name) { FIELD32(name); }
640 #define FONTABLE(name) { FIELD32(name); }
641 #define GCONTEXT(name) { FIELD32(name); }
642 #define INT8(name) { FIELD8(name); }
643 #define INT16(name) { FIELD16(name); }
644 #define KEYCODE(name) { FIELD8(name); }
645 #define LISTofARC(name) { listOfArc(hf_x11_##name, (next_offset - cur_offset) / 12); }
646 #define LISTofATOM(name, length) { listOfAtom(hf_x11_##name, (length) / 4); }
647 #define LISTofBYTE(name, length) { listOfByte(hf_x11_##name, (length)); }
648 #define LISTofCARD8(name, length) { listOfByte(hf_x11_##name, (length)); }
649 #define LISTofCARD32(name, length) { listOfCard32(hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
650 #define LISTofCOLORITEM(name, length) { listOfColorItem(hf_x11_##name, (length) / 12); }
651 #define LISTofKEYCODE(name, length) { listOfKeycode(hf_x11_##name, (length)); }
652 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
653 listOfKeysyms(hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
654 #define LISTofPOINT(name, length) { listOfPoint(hf_x11_##name, (length) / 4); }
655 #define LISTofRECTANGLE(name) { listOfRectangle(hf_x11_##name, (next_offset - cur_offset) / 8); }
656 #define LISTofSEGMENT(name) { listOfSegment(hf_x11_##name, (next_offset - cur_offset) / 8); }
657 #define LISTofSTRING8(name, length) { listOfString8(hf_x11_##name, hf_x11_##name##_string, (length)); }
658 #define LISTofTEXTITEM8(name) { listOfTextItem(hf_x11_##name, FALSE); }
659 #define LISTofTEXTITEM16(name) { listOfTextItem(hf_x11_##name, TRUE); }
660 #define OPCODE() { opcode = FIELD8(opcode); }
661 #define PIXMAP(name) { FIELD32(name); }
662 #define REQUEST_LENGTH() (requestLength())
663 #define SETofEVENT(name) { setOfEvent(); }
664 #define SETofDEVICEEVENT(name) { setOfDeviceEvent();}
665 #define SETofKEYMASK(name) { setOfKeyMask(); }
666 #define SETofPOINTEREVENT(name) { setOfPointerEvent(); }
667 #define STRING8(name, length) { string8(#name, hf_x11_##name, length); }
668 #define STRING16(name, length) { string16(hf_x11_##name, hf_x11_##name##_bytes, length); }
669 #define TIMESTAMP(name){ timestamp(#name, hf_x11_##name); }
670 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, x, little_endian); p += x; }
671 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, x, little_endian); cur_offset += x; }
672 #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; }
673 #define WINDOW(name) { FIELD32(name); }
674 #define WINGRAVITY(name) { gravity(#name, hf_x11_##name, "Unmap"); }
676 #define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
677 proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
678 v ? "" : " (CopyFromParent)"); cur_offset += 4; }
680 /************************************************************************
682 *** D E C O D I N G F I E L D S ***
684 ************************************************************************/
686 static void atom(proto_tree *t, int hf)
688 const char *interpretation = NULL;
690 guint32 v = VALUE32(tvb, cur_offset);
691 if (v >= 1 && v < array_length(atom_predefined_interpretation))
692 interpretation = atom_predefined_interpretation[v];
694 interpretation = "Not a predefined atom";
696 struct header_field_info *hfi = proto_registrar_get_nth(hf);
698 interpretation = match_strval(v, cVALS(hfi -> strings));
700 if (!interpretation) interpretation = "error in Xlib client program ?";
701 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %d (%s)",
702 proto_registrar_get_nth(hf) -> name, v, interpretation);
706 static void bitmask(int hf, int size)
708 lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
709 lastMask._offset = cur_offset;
710 lastMask._zone = size;
711 lastMask._tree = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
715 static guint32 add_boolean(const char *nameAsChar, int hf)
717 guint32 v = VALUE8(tvb, cur_offset);
718 proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
723 static void colorFlags(proto_tree *t)
725 unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
728 if (do_red_green_blue) {
731 char *bp = buffer + sprintf(buffer, "flags: ");
733 if (do_red_green_blue & 0x1) {
734 bp += sprintf(bp, "DoRed");
738 if (do_red_green_blue & 0x2) {
739 if (sep) bp += sprintf(bp, " | ");
740 bp += sprintf(bp, "DoGreen");
744 if (do_red_green_blue & 0x4) {
745 if (sep) bp += sprintf(bp, " | ");
746 bp += sprintf(bp, "DoBlue");
750 if (do_red_green_blue & 0xf8) {
751 if (sep) bp += sprintf(bp, " + ");
752 sprintf(bp, "trash");
755 tt = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
757 if (do_red_green_blue & 0x1)
758 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1,
759 do_red_green_blue & 0x1);
760 if (do_red_green_blue & 0x2)
761 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1,
762 do_red_green_blue & 0x2);
763 if (do_red_green_blue & 0x4)
764 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1,
765 do_red_green_blue & 0x4);
766 if (do_red_green_blue & 0xf8)
767 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1,
768 do_red_green_blue & 0xf8);
770 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
775 static void gravity(const char *nameAsChar, int hf, const char *nullInterpretation)
777 guint8 v = VALUE8(tvb, cur_offset);
779 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar,
782 proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
786 static void listOfArc(int hf, int length)
788 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
790 gint16 x = VALUE16(tvb, cur_offset);
791 gint16 y = VALUE16(tvb, cur_offset + 2);
792 guint16 width = VALUE16(tvb, cur_offset + 4);
793 guint16 height = VALUE16(tvb, cur_offset + 6);
794 gint16 angle1 = VALUE16(tvb, cur_offset + 8);
795 gint16 angle2 = VALUE16(tvb, cur_offset + 10);
797 proto_tree *ttt = proto_tree_add_protocol_format(tt, hf_x11_arc, tvb, cur_offset, 12,
798 "arc: %dx%d+%d+%d, angle %d -> %d (%f° -> %f°)",
799 width, height, x, y, angle1, angle2,
800 angle1 / 64.0, angle2 / 64.0);
801 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
802 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
803 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
804 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
805 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
806 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
810 static void listOfAtom(int hf, int length)
812 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
814 if (cur_offset + 4 > next_offset) {
815 /* List runs past end of message. */
818 atom(tt, hf_x11_properties_item);
822 static void listOfByte(int hf, int length)
824 if (cur_offset + length > next_offset) {
825 /* List runs past end of message. */
826 length = next_offset - cur_offset;
828 if (length <= 0) length = 1;
829 proto_tree_add_bytes(t, hf, tvb, cur_offset, length, tvb_get_ptr(tvb, cur_offset, length));
830 cur_offset += length;
833 static void listOfCard32(int hf, int hf_item, int length)
835 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
837 if (cur_offset + 4 > next_offset) {
838 /* List runs past end of message. */
841 proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
846 static void listOfColorItem(int hf, int length)
848 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
851 unsigned do_red_green_blue;
852 guint16 red, green, blue;
857 if (cur_offset + 12 > next_offset) {
858 /* List runs past end of message. */
861 red = VALUE16(tvb, cur_offset + 4);
862 green = VALUE16(tvb, cur_offset + 6);
863 blue = VALUE16(tvb, cur_offset + 8);
864 do_red_green_blue = VALUE8(tvb, cur_offset + 10);
866 bp = buffer + sprintf(buffer, "colorItem: ");
868 if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
869 if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
870 if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
872 ttt = proto_tree_add_protocol_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
873 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
874 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
875 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
876 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
878 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
882 static GTree *keysymTable = NULL;
884 static gint compareGuint32(gconstpointer a, gconstpointer b)
886 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
889 static const char *keysymString(guint32 v)
894 /* This table is so big that we built it only if necessary */
896 const value_string *p = keysym_vals_source;
897 keysymTable = g_tree_new(compareGuint32);
898 for(; p -> strptr; p++)
899 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
901 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
902 return res ? res : "Unknown";
905 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
907 static void listOfKeycode(int hf, int length)
910 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
917 if (cur_offset + 8 > next_offset) {
918 /* List runs past end of message. */
921 for(i = 8, m = modifiers; i; i--, m++) {
922 u_char c = tvb_get_guint8(tvb, cur_offset);
924 if (c) bp += sprintf(bp, " %s=%d", *m, c);
927 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);
931 static void listOfKeysyms(int hf, int hf_item, int keycode_count, int keysyms_per_keycode)
933 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
939 while(keycode_count--) {
940 if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
941 /* List runs past end of message. */
944 bp = buffer + sprintf(buffer, "keysyms:");
945 for(i = 0; i < keysyms_per_keycode; i++) {
946 bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
949 ttt = proto_tree_add_protocol_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
951 for(i = keysyms_per_keycode; i; i--) {
952 guint32 v = VALUE32(tvb, cur_offset);
953 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
954 "keysym: 0x%08x (%s)", v, keysymString(v));
960 static void listOfPoint(int hf, int length)
962 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
967 if (cur_offset + 4 > next_offset) {
968 /* List runs past end of message. */
971 x = VALUE16(tvb, cur_offset);
972 y = VALUE16(tvb, cur_offset + 2);
974 ttt = proto_tree_add_protocol_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
975 proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
976 proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
980 static void listOfRectangle(int hf, int length)
982 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
985 unsigned width, height;
988 if (cur_offset + 8 > next_offset) {
989 /* List runs past end of message. */
992 x = VALUE16(tvb, cur_offset);
993 y = VALUE16(tvb, cur_offset + 2);
994 width = VALUE16(tvb, cur_offset + 4);
995 height = VALUE16(tvb, cur_offset + 6);
997 ttt = proto_tree_add_protocol_format(tt, hf_x11_rectangle, tvb, cur_offset, 8,
998 "rectangle: %dx%d+%d+%d", width, height, x, y);
999 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
1000 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
1001 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
1002 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
1006 static void listOfSegment(int hf, int length)
1008 proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1010 gint16 x1, y1, x2, y2;
1013 if (cur_offset + 8 > next_offset) {
1014 /* List runs past end of message. */
1017 x1 = VALUE16(tvb, cur_offset);
1018 y1 = VALUE16(tvb, cur_offset + 2);
1019 x2 = VALUE16(tvb, cur_offset + 4);
1020 y2 = VALUE16(tvb, cur_offset + 6);
1022 ttt = proto_tree_add_protocol_format(tt, hf_x11_segment, tvb, cur_offset, 8,
1023 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1024 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1025 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1026 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1027 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1031 /* XXX - the protocol tree code should handle non-printable characters.
1032 Note that "non-printable characters" may depend on your locale.... */
1033 static void stringCopy(char *dest, const char *source, int length)
1038 if (!isgraph(c) && c != ' ') c = '.';
1044 static void listOfString8(int hf, int hf_item, int length)
1051 /* Compute total length */
1053 int scanning_offset = cur_offset; /* Scanning pointer */
1055 for(i = length; i; i--) {
1056 l = tvb_get_guint8(tvb, scanning_offset);
1057 scanning_offset += 1 + l;
1060 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1063 unsigned l = VALUE8(tvb, cur_offset);
1064 if (allocated < l + 1) {
1065 /* g_realloc doesn't work ??? */
1067 s = g_malloc(l + 1);
1070 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1071 proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
1072 cur_offset += l + 1;
1077 #define STRING16_MAX_DISPLAYED_LENGTH 150
1079 static int stringIsActuallyAn8BitString(int offset, unsigned length)
1081 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1082 for(; length > 0; cur_offset += 2, length--) {
1083 if (tvb_get_guint8(tvb, cur_offset))
1089 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1091 static void string16_with_buffer_preallocated(proto_tree *t, int hf, int hf_bytes,
1092 int offset, unsigned length,
1093 char **s, int *sLength)
1095 int truncated = FALSE;
1096 unsigned l = length / 2;
1098 if (stringIsActuallyAn8BitString(offset, l)) {
1100 int soffset = offset;
1102 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1104 l = STRING16_MAX_DISPLAYED_LENGTH;
1106 if (*sLength < l + 3) {
1108 *s = g_malloc(l + 3);
1113 if (truncated) l -= 3;
1117 *dp++ = tvb_get_guint8(tvb, soffset);
1122 /* If truncated, add an ellipsis */
1123 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1126 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1127 proto_registrar_get_nth(hf) -> name, *s);
1129 proto_tree_add_bytes(t, hf_bytes, tvb, offset, length, tvb_get_ptr(tvb, offset, length));
1133 static void listOfTextItem(int hf, int sizeIs16)
1140 /* Compute total length */
1142 int scanning_offset = cur_offset; /* Scanning pointer */
1143 int l; /* Length of an individual item */
1144 int n = 0; /* Number of items */
1146 while(scanning_offset < next_offset) {
1147 l = tvb_get_guint8(tvb, scanning_offset);
1151 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1154 tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1157 unsigned l = VALUE8(tvb, cur_offset);
1158 if (l == 255) { /* Item is a font */
1159 fid = tvb_get_ntohl(tvb, cur_offset + 1);
1160 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
1162 } else { /* Item is a string */
1164 gint8 delta = VALUE8(tvb, cur_offset + 1);
1165 if (sizeIs16) l += l;
1166 if (allocated < l + 1) {
1167 /* g_realloc doesn't work ??? */
1169 s = g_malloc(l + 1);
1172 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
1173 ttt = proto_tree_add_protocol_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
1174 "textitem (string): delta = %d, \"%s\"",
1176 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
1178 string16_with_buffer_preallocated(ttt, hf_x11_textitem_string_string16,
1179 hf_x11_textitem_string_string16_bytes,
1183 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
1184 cur_offset + 2, l, s, "\"%s\"", s);
1185 cur_offset += l + 2;
1191 static guint32 field8(int hf)
1193 guint32 v = VALUE8(tvb, cur_offset);
1194 struct header_field_info *hfi = proto_registrar_get_nth(hf);
1195 gchar *enumValue = NULL;
1196 gchar *nameAsChar = hfi -> name;
1199 enumValue = match_strval(v, cVALS(hfi -> strings));
1201 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %d (%s)", nameAsChar, v, enumValue);
1203 proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
1208 static guint32 field16(int hf)
1210 guint32 v = VALUE16(tvb, cur_offset);
1211 proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
1216 static guint32 field32(int hf)
1218 guint32 v = VALUE32(tvb, cur_offset);
1219 struct header_field_info *hfi = proto_registrar_get_nth(hf);
1220 gchar *enumValue = NULL;
1221 gchar *nameAsChar = hfi -> name;
1224 enumValue = match_strval(v, cVALS(hfi -> strings));
1226 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1228 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v,
1229 hfi -> display == BASE_DEC ? "%s: %d" : "%s : 0x%08x",
1235 static void gcAttributes(void)
1237 BITMASK32(gc_value);
1238 BITFIELD(ENUM8, gc_value_mask, function);
1239 BITFIELD(CARD32, gc_value_mask, plane_mask);
1240 BITFIELD(CARD32, gc_value_mask, foreground);
1241 BITFIELD(CARD32, gc_value_mask, background);
1242 BITFIELD(CARD16, gc_value_mask, line_width);
1243 BITFIELD(ENUM8, gc_value_mask, line_style);
1244 BITFIELD(ENUM8, gc_value_mask, cap_style);
1245 BITFIELD(ENUM8, gc_value_mask, join_style);
1246 BITFIELD(ENUM8, gc_value_mask, fill_style);
1247 BITFIELD(ENUM8, gc_value_mask, fill_rule);
1248 BITFIELD(PIXMAP, gc_value_mask, tile);
1249 BITFIELD(PIXMAP, gc_value_mask, stipple);
1250 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
1251 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
1252 BITFIELD(FONT, gc_value_mask, font);
1253 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
1254 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
1255 BITFIELD(INT16, gc_value_mask, clip_x_origin);
1256 BITFIELD(INT16, gc_value_mask, clip_y_origin);
1257 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1258 BITFIELD(CARD16, gc_value_mask, dash_offset);
1259 BITFIELD(CARD8, gc_value_mask, gc_dashes);
1260 BITFIELD(ENUM8, gc_value_mask, arc_mode);
1263 static void gcMask(void)
1265 BITMASK32(gc_value);
1266 FLAG(gc_value, function);
1267 FLAG(gc_value, plane_mask);
1268 FLAG(gc_value, foreground);
1269 FLAG(gc_value, background);
1270 FLAG(gc_value, line_width);
1271 FLAG(gc_value, line_style);
1272 FLAG(gc_value, cap_style);
1273 FLAG(gc_value, join_style);
1274 FLAG(gc_value, fill_style);
1275 FLAG(gc_value, fill_rule);
1276 FLAG(gc_value, tile);
1277 FLAG(gc_value, stipple);
1278 FLAG(gc_value, tile_stipple_x_origin);
1279 FLAG(gc_value, tile_stipple_y_origin);
1280 FLAG(gc_value, font);
1281 FLAG(gc_value, subwindow_mode);
1282 FLAG(gc_value, graphics_exposures);
1283 FLAG(gc_value, clip_x_origin);
1284 FLAG(gc_value, clip_y_origin);
1285 FLAG(gc_value, clip_mask);
1286 FLAG(gc_value, dash_offset);
1287 FLAG(gc_value, gc_dashes);
1288 FLAG(gc_value, arc_mode);
1291 static guint32 requestLength(void)
1293 guint32 res = VALUE16(tvb, cur_offset) * 4;
1294 proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
1299 static void setOfEvent(void)
1301 struct maskStruct save = lastMask;
1303 FLAG(event, KeyPress);
1304 FLAG(event, KeyRelease);
1305 FLAG(event, ButtonPress);
1306 FLAG(event, ButtonRelease);
1307 FLAG(event, EnterWindow);
1308 FLAG(event, LeaveWindow);
1309 FLAG(event, PointerMotion);
1310 FLAG(event, PointerMotionHint);
1311 FLAG(event, Button1Motion);
1312 FLAG(event, Button2Motion);
1313 FLAG(event, Button3Motion);
1314 FLAG(event, Button4Motion);
1315 FLAG(event, Button5Motion);
1316 FLAG(event, ButtonMotion);
1317 FLAG(event, KeymapState);
1318 FLAG(event, Exposure);
1319 FLAG(event, VisibilityChange);
1320 FLAG(event, StructureNotify);
1321 FLAG(event, ResizeRedirect);
1322 FLAG(event, SubstructureNotify);
1323 FLAG(event, SubstructureRedirect);
1324 FLAG(event, FocusChange);
1325 FLAG(event, PropertyChange);
1326 FLAG(event, ColormapChange);
1327 FLAG(event, OwnerGrabButton);
1328 FLAG(event, erroneous_bits);
1332 static void setOfDeviceEvent(void)
1334 struct maskStruct save = lastMask;
1335 BITMASK32(do_not_propagate);
1336 FLAG(do_not_propagate, KeyPress);
1337 FLAG(do_not_propagate, KeyRelease);
1338 FLAG(do_not_propagate, ButtonPress);
1339 FLAG(do_not_propagate, ButtonRelease);
1340 FLAG(do_not_propagate, PointerMotion);
1341 FLAG(do_not_propagate, Button1Motion);
1342 FLAG(do_not_propagate, Button2Motion);
1343 FLAG(do_not_propagate, Button3Motion);
1344 FLAG(do_not_propagate, Button4Motion);
1345 FLAG(do_not_propagate, Button5Motion);
1346 FLAG(do_not_propagate, ButtonMotion);
1347 FLAG(do_not_propagate, erroneous_bits);
1351 static void setOfKeyMask(void)
1353 struct maskStruct save = lastMask;
1354 lastMask._value = VALUE16(tvb, cur_offset);
1355 lastMask._offset = cur_offset;
1357 if (lastMask._value == 0x8000)
1358 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
1359 "modifiers-masks: 0x8000 (AnyModifier)");
1361 lastMask._tree = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2,
1363 FLAG(modifiers, Shift);
1364 FLAG(modifiers, Lock);
1365 FLAG(modifiers, Control);
1366 FLAG(modifiers, Mod1);
1367 FLAG(modifiers, Mod2);
1368 FLAG(modifiers, Mod3);
1369 FLAG(modifiers, Mod4);
1370 FLAG(modifiers, Mod5);
1371 FLAG(modifiers, erroneous_bits);
1377 static void setOfPointerEvent(void)
1379 struct maskStruct save = lastMask;
1380 BITMASK16(pointer_event);
1381 FLAG(pointer_event, ButtonPress);
1382 FLAG(pointer_event, ButtonRelease);
1383 FLAG(pointer_event, EnterWindow);
1384 FLAG(pointer_event, LeaveWindow);
1385 FLAG(pointer_event, PointerMotion);
1386 FLAG(pointer_event, PointerMotionHint);
1387 FLAG(pointer_event, Button1Motion);
1388 FLAG(pointer_event, Button2Motion);
1389 FLAG(pointer_event, Button3Motion);
1390 FLAG(pointer_event, Button4Motion);
1391 FLAG(pointer_event, Button5Motion);
1392 FLAG(pointer_event, ButtonMotion);
1393 FLAG(pointer_event, KeymapState);
1394 FLAG(pointer_event, erroneous_bits);
1398 static void string8(const char *nameAsChar, int hf, unsigned length)
1400 char *s = g_malloc(length + 1);
1401 stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
1402 proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
1404 cur_offset += length;
1407 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1409 static void string16(int hf, int hf_bytes, unsigned length)
1414 string16_with_buffer_preallocated(t, hf, hf_bytes, cur_offset, length, &s, &l);
1416 cur_offset += length;
1419 static void timestamp(const char *nameAsChar, int hf)
1421 guint32 v = VALUE32(tvb, cur_offset);
1423 proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1425 proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
1429 static void windowAttributes(void)
1431 BITMASK32(window_value);
1432 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1433 BITFIELD(CARD32, window_value_mask, background_pixel);
1434 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1435 BITFIELD(CARD32, window_value_mask, border_pixel);
1436 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1437 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1438 BITFIELD(ENUM8, window_value_mask, backing_store);
1439 BITFIELD(CARD32, window_value_mask, backing_planes);
1440 BITFIELD(CARD32, window_value_mask, backing_pixel);
1441 BITFIELD(BOOL, window_value_mask, override_redirect);
1442 BITFIELD(BOOL, window_value_mask, save_under);
1443 BITFIELD(SETofEVENT, window_value_mask, event_mask);
1444 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1445 BITFIELD(COLORMAP, window_value_mask, colormap);
1446 BITFIELD(CURSOR, window_value_mask, cursor);
1449 /************************************************************************
1451 *** D E C O D I N G O N E P A C K E T ***
1453 ************************************************************************/
1455 static int dissect_x11_request_loop(proto_tree *root)
1457 int left = tvb_reported_length(tvb), nextLeft;
1463 /* The X11 data stream to the server is just a sequence of requests,
1464 each of which contains a length; for now, we dissect all the
1465 requests in this frame until we run out of data in the frame.
1466 Eventually, we should handle requests that cross frame
1469 Note that "in this frame" refers to everything in the frame
1470 as it appeared in the wire, not as it was captured; we want
1471 an exception to be thrown if we go past the end of the
1472 captured data in the frame without going past the end of the
1473 data in the frame. */
1477 /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
1479 /* We ran out of data - we don't have enough data in
1480 the frame to get the length of this request. */
1483 length = VALUE16(tvb, cur_offset + 2) * 4;
1484 /* fprintf(stderr, "length = %d\n", length);*/
1485 if (left < length) {
1486 /* We ran out of data - we don't have enough data in
1487 the frame for the full request. */
1491 /* Bogus message length? */
1495 next_offset = cur_offset + length;
1496 nextLeft = left - length;
1498 ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
1499 t = proto_item_add_subtree(ti, ett_x11_request);
1504 case 1: /* CreateWindow */
1513 CARD16(border_width);
1514 ENUM16(window_class);
1519 case 2: /* ChangeWindowAttributes */
1526 case 3: /* GetWindowAttributes */
1527 case 4: /* DestroyWindow */
1528 case 5: /* DestroySubwindows */
1534 case 6: /* ChangeSaveSet */
1535 ENUM8(save_set_mode);
1540 case 7: /* ReparentWindow */
1549 case 8: /* MapWindow */
1550 case 9: /* MapSubWindow */
1551 case 10: /* UnmapWindow */
1552 case 11: /* UnmapSubwindows */
1558 case 12: /* ConfigureWindow */
1562 BITMASK16(configure_window);
1564 BITFIELD(INT16, configure_window_mask, x);
1565 BITFIELD(INT16, configure_window_mask, y);
1566 BITFIELD(CARD16, configure_window_mask, width);
1567 BITFIELD(CARD16, configure_window_mask, height);
1568 BITFIELD(CARD16, configure_window_mask, border_width);
1569 BITFIELD(WINDOW, configure_window_mask, sibling);
1570 BITFIELD(ENUM8, configure_window_mask, stack_mode);
1574 case 13: /* CirculateWindow */
1580 case 14: /* GetGeometry */
1581 case 15: /* QueryTree */
1587 case 16: /* InternAtom */
1588 BOOL(only_if_exists);
1590 v16 = FIELD16(name_length);
1596 case 17: /* GetAtomName */
1602 case 18: /* ChangeProperty */
1610 v32 = CARD32(data_length);
1611 LISTofBYTE(data, v32);
1615 case 19: /* DeleteProperty */
1622 case 20: /* GetProperty */
1627 ATOM(get_property_type);
1628 CARD32(long_offset);
1629 CARD32(long_length);
1632 case 21: /* ListProperties */
1638 case 22: /* SetSelectionOwner */
1646 case 23: /* GetSelectionOwner */
1652 case 24: /* ConvertSelection */
1662 case 26: /* GrabPointer */
1665 WINDOW(grab_window);
1666 SETofPOINTEREVENT(pointer_event_mask);
1667 ENUM8(pointer_mode);
1668 ENUM8(keyboard_mode);
1674 case 27: /* UngrabPointer */
1680 case 28: /* GrabButton */
1683 WINDOW(grab_window);
1684 SETofPOINTEREVENT(event_mask);
1685 ENUM8(pointer_mode);
1686 ENUM8(keyboard_mode);
1691 SETofKEYMASK(modifiers);
1694 case 29: /* UngrabButton */
1697 WINDOW(grab_window);
1698 SETofKEYMASK(modifiers);
1702 case 30: /* ChangeActivePointerGrab */
1707 SETofPOINTEREVENT(event_mask);
1711 case 31: /* GrabKeyboard */
1714 WINDOW(grab_window);
1716 ENUM8(pointer_mode);
1717 ENUM8(keyboard_mode);
1721 case 32: /* UngrabKeyboard */
1727 case 33: /* GrabKey */
1730 WINDOW(grab_window);
1731 SETofKEYMASK(modifiers);
1733 ENUM8(pointer_mode);
1734 ENUM8(keyboard_mode);
1738 case 34: /* UngrabKey */
1741 WINDOW(grab_window);
1742 SETofKEYMASK(modifiers);
1746 case 35: /* AllowEvents */
1747 ENUM8(allow_events_mode);
1752 case 36: /* GrabServer */
1757 case 37: /* UngrabServer */
1762 case 38: /* QueryPointer */
1768 case 39: /* GetMotionEvents */
1776 case 40: /* TranslateCoordinates */
1785 case 41: /* WarpPointer */
1788 WINDOW(warp_pointer_src_window);
1789 WINDOW(warp_pointer_dst_window);
1798 case 42: /* SetInputFocus */
1805 case 43: /* GetInputFocus */
1810 case 44: /* QueryKeymap */
1815 case 45: /* OpenFont */
1819 v16 = FIELD16(name_length);
1825 case 46: /* CloseFont */
1831 case 47: /* QueryFont */
1837 case 48: /* QueryTextExtents */
1838 v8 = BOOL(odd_length);
1841 STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
1845 case 49: /* ListFonts */
1849 v16 = FIELD16(pattern_length);
1850 STRING8(pattern, v16);
1854 case 50: /* ListFontsWithInfo */
1858 v16 = FIELD16(pattern_length);
1859 STRING8(pattern, v16);
1863 case 51: /* SetFontPath */
1866 v16 = CARD16(str_number_in_path);
1868 LISTofSTRING8(path, v16);
1872 case 52: /* GetFontPath */
1877 case 53: /* CreatePixmap */
1886 case 54: /* FreePixmap */
1892 case 55: /* CreateGC */
1900 case 56: /* ChangeGC */
1907 case 57: /* CopyGC */
1915 case 58: /* SetDashes */
1919 CARD16(dash_offset);
1920 v16 = FIELD16(dashes_length);
1921 LISTofCARD8(dashes, v16);
1925 case 59: /* SetClipRectangles */
1929 INT16(clip_x_origin);
1930 INT16(clip_y_origin);
1931 LISTofRECTANGLE(rectangles);
1934 case 60: /* FreeGC */
1940 case 61: /* ClearArea */
1950 case 62: /* CopyArea */
1953 DRAWABLE(src_drawable);
1954 DRAWABLE(dst_drawable);
1964 case 63: /* CopyPlane */
1967 DRAWABLE(src_drawable);
1968 DRAWABLE(dst_drawable);
1979 case 64: /* PolyPoint */
1980 ENUM8(coordinate_mode);
1981 v16 = REQUEST_LENGTH();
1984 LISTofPOINT(points, v16 - 12);
1987 case 65: /* PolyLine */
1988 ENUM8(coordinate_mode);
1989 v16 = REQUEST_LENGTH();
1992 LISTofPOINT(points, v16 - 12);
1995 case 66: /* PolySegment */
2000 LISTofSEGMENT(segments);
2003 case 67: /* PolyRectangle */
2008 LISTofRECTANGLE(rectangles);
2011 case 68: /* PolyArc */
2019 case 69: /* FillPoly */
2021 v16 = REQUEST_LENGTH();
2025 ENUM8(coordinate_mode);
2027 LISTofPOINT(points, v16 - 16);
2030 case 70: /* PolyFillRectangle */
2035 LISTofRECTANGLE(rectangles);
2038 case 71: /* PolyFillArc */
2046 case 72: /* PutImage */
2047 ENUM8(image_format);
2048 v16 = REQUEST_LENGTH();
2058 LISTofBYTE(data, v16 - 24);
2062 case 73: /* GetImage */
2063 ENUM8(image_pixmap_format);
2073 case 74: /* PolyText8 */
2075 v16 = REQUEST_LENGTH();
2080 LISTofTEXTITEM8(items);
2084 case 75: /* PolyText16 */
2086 v16 = REQUEST_LENGTH();
2091 LISTofTEXTITEM16(items);
2095 case 76: /* ImageText8 */
2096 v8 = FIELD8(string_length);
2102 STRING8(string, v8);
2106 case 77: /* ImageText16 */
2107 v8 = FIELD8(string_length);
2113 STRING16(string16, v8);
2117 case 78: /* CreateColormap */
2125 case 79: /* FreeColormap */
2131 case 80: /* CopyColormapAndFree */
2138 case 81: /* InstallColormap */
2144 case 82: /* UninstallColormap */
2150 case 83: /* ListInstalledColormaps */
2156 case 84: /* AllocColor */
2166 case 85: /* AllocNamedColor */
2170 v16 = FIELD16(name_length);
2176 case 86: /* AllocColorCells */
2184 case 87: /* AllocColorPlanes */
2194 case 88: /* FreeColors */
2196 v16 = REQUEST_LENGTH();
2199 LISTofCARD32(pixels, v16 - 12);
2202 case 89: /* StoreColors */
2204 v16 = REQUEST_LENGTH();
2206 LISTofCOLORITEM(color_items, v16 - 8);
2209 case 90: /* StoreNamedColor */
2214 v16 = FIELD16(name_length);
2220 case 91: /* QueryColors */
2222 v16 = REQUEST_LENGTH();
2224 LISTofCARD32(pixels, v16 - 8);
2227 case 92: /* LookupColor */
2231 v16 = FIELD16(name_length);
2237 case 93: /* CreateCursor */
2241 PIXMAP(source_pixmap);
2253 case 94: /* CreateGlyphCursor */
2259 CARD16(source_char);
2269 case 95: /* FreeCursor */
2275 case 96: /* RecolorCursor */
2287 case 97: /* QueryBestSize */
2295 case 98: /* QueryExtension */
2298 v16 = FIELD16(name_length);
2304 case 99: /* ListExtensions */
2309 case 100: /* ChangeKeyboardMapping */
2310 v8 = FIELD8(keycode_count);
2312 KEYCODE(first_keycode);
2313 v8_2 = FIELD8(keysyms_per_keycode);
2315 LISTofKEYSYM(keysyms, v8, v8_2);
2318 case 101: /* GetKeyboardMapping */
2321 KEYCODE(first_keycode);
2326 case 102: /* ChangeKeyboardControl */
2329 BITMASK32(keyboard_value);
2330 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2331 BITFIELD(INT8, keyboard_value_mask, bell_percent);
2332 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2333 BITFIELD(INT16, keyboard_value_mask, bell_duration);
2334 BITFIELD(INT16, keyboard_value_mask, led);
2335 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2336 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2337 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2340 case 103: /* GetKeyboardControl */
2345 case 104: /* Bell */
2350 case 105: /* ChangePointerControl */
2353 INT16(acceleration_numerator);
2354 INT16(acceleration_denominator);
2356 BOOL(do_acceleration);
2360 case 106: /* GetPointerControl */
2365 case 107: /* SetScreenSaver */
2370 ENUM8(prefer_blanking);
2371 ENUM8(allow_exposures);
2375 case 108: /* GetScreenSaver */
2380 case 109: /* ChangeHosts */
2381 ENUM8(change_host_mode);
2385 v16 = CARD16(address_length);
2386 LISTofCARD8(address, v16);
2389 case 110: /* ListHosts */
2394 case 111: /* SetAccessControl */
2399 case 112: /* SetCloseDownMode */
2400 ENUM8(close_down_mode);
2404 case 113: /* KillClient */
2410 case 114: /* RotateProperties */
2412 v16 = REQUEST_LENGTH();
2414 CARD16(property_number);
2416 LISTofATOM(properties, (v16 - 12));
2419 case 115: /* ForceScreenSaver */
2420 ENUM8(screen_saver_mode);
2424 case 116: /* SetPointerMapping */
2425 v8 = FIELD8(map_length);
2427 LISTofCARD8(map, v8);
2431 case 117: /* GetPointerMapping */
2436 case 118: /* SetModifierMapping */
2437 v8 = FIELD8(keycodes_per_modifier);
2439 LISTofKEYCODE(keycodes, v8);
2442 case 119: /* GetModifierMapping */
2447 case 127: /* NoOperation */
2452 if (cur_offset < next_offset)
2453 proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
2454 cur_offset = next_offset;
2461 /************************************************************************
2463 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2465 ************************************************************************/
2467 static GTree *byte_ordering_cache = NULL;
2468 static GMemChunk *address_chunk = NULL;
2469 static GMemChunk *ipv4_chunk = NULL;
2470 static GMemChunk *ipv6_chunk = NULL;
2472 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2474 const address *a = (const address *)aa;
2475 const address *b = (const address *)bb;
2476 int c = b -> type - a -> type;
2478 c = b -> len - a -> len;
2480 return memcmp(b -> data, a -> data, a -> len);
2483 /* If we can't guess, we return TRUE (that is little_endian), cause
2484 I'm developing on a Linux box :-). The (non-)guess isn't cached
2485 however, so we may have more luck next time. I'm quite conservative
2486 in my assertions, cause once it's cached, it's stay in cache, and
2487 we may be fooled up by a packet starting with the end of a request
2488 started in a previous packet...
2491 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2493 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2496 while(maskLength--) {
2497 int c = tvb_get_guint8(tvb, offset);
2499 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2504 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2506 if (listLength > length) return FALSE;
2507 while(listLength--) {
2509 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2510 l = tvb_get_guint8(tvb, offset);
2513 if (l > length) return FALSE;
2514 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2518 if (length > 3) return FALSE;
2522 static int rounded4(int n)
2524 int remainder = n % 4;
2526 if (remainder) res++;
2530 /* We assume the order to be consistent, until proven wrong. */
2532 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2534 switch(tvb_get_guint8(tvb, offset)) {
2535 case 1: /* CreateWindow */
2536 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2538 case 2: /* ChangeWindowAttributes */
2539 case 56: /* ChangeGC */
2540 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2542 case 3: /* GetWindowAttributes */
2543 case 4: /* DestroyWindow */
2544 case 5: /* DestroySubwindows */
2545 case 6: /* ChangeSaveSet */
2546 case 8: /* MapWindow */
2547 case 9: /* MapSubWindow */
2548 case 10: /* UnmapWindow */
2549 case 11: /* UnmapSubwindows */
2550 case 13: /* CirculateWindow */
2551 case 14: /* GetGeometry */
2552 case 15: /* QueryTree */
2553 case 17: /* GetAtomName */
2554 case 21: /* ListProperties */
2555 case 23: /* GetSelectionOwner */
2556 case 27: /* UngrabPointer */
2557 case 32: /* UngrabKeyboard */
2558 case 35: /* AllowEvents */
2559 case 38: /* QueryPointer */
2560 case 46: /* CloseFont */
2561 case 47: /* QueryFont */
2562 case 54: /* FreePixmap */
2563 case 60: /* FreeGC */
2564 case 79: /* FreeColormap */
2565 case 81: /* InstallColormap */
2566 case 82: /* UninstallColormap */
2567 case 83: /* ListInstalledColormaps */
2568 case 95: /* FreeCursor */
2569 case 101: /* GetKeyboardMapping */
2570 case 113: /* KillClient */
2573 case 7: /* ReparentWindow */
2574 case 22: /* SetSelectionOwner */
2575 case 30: /* ChangeActivePointerGrab */
2576 case 31: /* GrabKeyboard */
2577 case 33: /* GrabKey */
2578 case 39: /* GetMotionEvents */
2579 case 40: /* TranslateCoordinates */
2580 case 53: /* CreatePixmap */
2581 case 57: /* CopyGC */
2582 case 61: /* ClearArea */
2583 case 78: /* CreateColormap */
2584 case 84: /* AllocColor */
2585 case 87: /* AllocColorPlanes */
2588 case 12: /* ConfigureWindow */
2589 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2591 case 16: /* InternAtom */
2592 case 98: /* QueryExtension */
2593 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2595 case 18: /* ChangeProperty */
2597 int multiplier, type;
2598 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2599 type = tvb_get_guint8(tvb, 16);
2600 if (type != 8 && type != 16 && type != 32) return FALSE;
2601 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2602 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2603 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2606 case 19: /* DeleteProperty */
2607 case 29: /* UngrabButton */
2608 case 34: /* UngrabKey */
2609 case 42: /* SetInputFocus */
2610 case 80: /* CopyColormapAndFree */
2611 case 86: /* AllocColorCells */
2612 case 97: /* QueryBestSize */
2613 case 105: /* ChangePointerControl */
2614 case 107: /* SetScreenSaver */
2617 case 20: /* GetProperty */
2618 case 24: /* ConvertSelection */
2619 case 26: /* GrabPointer */
2620 case 28: /* GrabButton */
2621 case 41: /* WarpPointer */
2624 case 25: /* SendEvent */
2625 return length == 11;
2627 case 36: /* GrabServer */
2628 case 37: /* UngrabServer */
2629 case 43: /* GetInputFocus */
2630 case 44: /* QueryKeymap */
2631 case 52: /* GetFontPath */
2632 case 99: /* ListExtensions */
2633 case 103: /* GetKeyboardControl */
2634 case 104: /* Bell */
2635 case 106: /* GetPointerControl */
2636 case 108: /* GetScreenSaver */
2637 case 110: /* ListHosts */
2638 case 111: /* SetAccessControl */
2639 case 112: /* SetCloseDownMode */
2640 case 115: /* ForceScreenSaver */
2641 case 117: /* GetPointerMapping */
2642 case 119: /* GetModifierMapping */
2645 case 45: /* OpenFont */
2646 case 85: /* AllocNamedColor */
2647 case 92: /* LookupColor */
2648 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2650 case 48: /* QueryTextExtents */
2653 case 49: /* ListFonts */
2654 case 50: /* ListFontsWithInfo */
2655 case 109: /* ChangeHosts */
2656 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2658 case 51: /* SetFontPath */
2659 if (length < 2) return FALSE;
2660 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2661 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2663 case 55: /* CreateGC */
2664 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2666 case 58: /* SetDashes */
2667 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2669 case 59: /* SetClipRectangles */
2670 case 66: /* PolySegment */
2671 case 67: /* PolyRectangle */
2672 case 70: /* PolyFillRectangle */
2673 return length >= 3 && (length - 3) % 2 == 0;
2675 case 62: /* CopyArea */
2678 case 63: /* CopyPlane */
2679 case 93: /* CreateCursor */
2680 case 94: /* CreateGlyphCursor */
2683 case 64: /* PolyPoint */
2684 case 65: /* PolyLine */
2685 case 88: /* FreeColors */
2688 case 68: /* PolyArc */
2689 case 71: /* PolyFillArc */
2690 return length >= 3 && (length - 3) % 3 == 0;
2692 case 69: /* FillPoly */
2693 case 76: /* ImageText8 */
2696 case 72: /* PutImage */
2699 case 73: /* GetImage */
2700 case 96: /* RecolorCursor */
2703 case 74: /* PolyText8 */
2704 if (length < 4) return FALSE;
2705 return TRUE; /* We don't perform many controls on this one */
2707 case 75: /* PolyText16 */
2708 if (length < 4) return FALSE;
2709 return TRUE; /* We don't perform many controls on this one */
2711 case 77: /* ImageText16 */
2714 case 89: /* StoreColors */
2715 return length > 2 && (length - 2) % 3 == 0;
2717 case 90: /* StoreNamedColor */
2718 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2720 case 91: /* QueryColors */
2723 case 100: /* ChangeKeyboardMapping */
2724 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2726 case 102: /* ChangeKeyboardControl */
2727 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2729 case 114: /* RotateProperties */
2730 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2732 case 116: /* SetPointerMapping */
2733 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2735 case 118: /* SetModifierMapping */
2736 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2738 case 127: /* NoOperation */
2746 /* -1 means doesn't match, +1 means match, 0 means don't know */
2748 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2750 int offset, nextoffset;
2753 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2755 length = v16(tvb, offset + 2);
2756 if (!length) return -1;
2757 nextoffset = offset + length * 4;
2758 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2765 guess_byte_ordering(tvbuff_t *tvb)
2767 /* With X the client gives the byte ordering for the protocol,
2768 and the port on the server tells us we're speaking X. */
2770 int le, be, decision, decisionToCache;
2772 address *addr = pi.srcport == pi.match_port ? &pi.net_dst : &pi.net_src;
2773 gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2774 if (cache) return cache > 0 ? TRUE : FALSE;
2775 if (pi.srcport == pi.match_port) return TRUE; /* We don't try to guess on a reply / event for now */
2777 le = x_endian_match(tvb, tvb_get_letohs);
2778 be = x_endian_match(tvb, tvb_get_ntohs);
2780 /* remember that "decision" really means "little_endian". */
2782 /* We have no reason to believe it's little- rather than
2783 big-endian, so we guess the shortest length is the
2786 if (!tvb_bytes_exist(tvb, 0, 4))
2787 /* Not even a way to get the length. We're biased
2788 toward little endianness here (essentially the
2789 x86 world right now). Decoding won't go very far
2794 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2796 decision = le >= be;
2798 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2799 if (decisionToCache) {
2800 /* We encode the decision as 1 for TRUE and -1 for FALSE
2801 to be able to distinguish between FALSE and no value in
2802 the cache when recalling the value.
2807 if (addr -> type == AT_IPv4) {
2809 address_data = g_mem_chunk_alloc(ipv4_chunk);
2810 } else if (addr -> type == AT_IPv6) {
2811 address_length = 16;
2812 address_data = g_mem_chunk_alloc(ipv6_chunk);
2814 address_length = addr -> len;
2815 address_data = g_malloc(address_length);
2817 cached = g_mem_chunk_alloc(address_chunk);
2818 memcpy(address_data, addr -> data, address_length);
2819 SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2820 g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2824 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2825 pi.fd -> num, le, be, decision, decisionToCache);
2830 /************************************************************************
2832 *** I N I T I A L I Z A T I O N A N D M A I N ***
2834 ************************************************************************/
2837 dissect_x11_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2839 /* Set up structures we will need to add the protocol subtree and manage it */
2841 proto_tree *x11_tree;
2844 /* Make entries in Protocol column and Info column on summary display */
2845 if (check_col(fd, COL_PROTOCOL))
2846 col_add_str(fd, COL_PROTOCOL, "X11");
2848 /* This field shows up as the "Info" column in the display; you should make
2849 it, if possible, summarize what's in the packet, so that a user looking
2850 at the list of packets can tell what type of packet it is.
2852 "col_add_fstr()" can be used instead of "col_add_str()"; it takes
2853 "printf()"-like arguments. */
2854 if (check_col(fd, COL_INFO))
2855 col_add_str(fd, COL_INFO, "X11 request");
2857 /* In the interest of speed, if "tree" is NULL, don't do any work not
2858 necessary to generate protocol tree items. */
2860 /* NOTE: The offset and length values in the previous call to
2861 "proto_tree_add_item()" define what data bytes to highlight in the hex
2862 display window when the line in the protocol tree display
2863 corresponding to that item is selected.
2865 END_OF_FRAME is a handy way to highlight all data from the offset to
2866 the end of the packet. */
2867 ti = proto_tree_add_item(tree, proto_x11, NullTVB, offset, END_OF_FRAME, FALSE);
2868 x11_tree = proto_item_add_subtree(ti, ett_x11);
2870 /* Code to process the packet goes here */
2872 tvb = tvb_create_from_top(offset);
2874 little_endian = guess_byte_ordering(tvb);
2875 left = dissect_x11_request_loop(x11_tree);
2877 old_dissect_data(pd, offset + cur_offset, fd, x11_tree);
2881 dissect_x11_event(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2883 /* Set up structures we will need to add the protocol subtree and manage it */
2885 proto_tree *x11_tree;
2887 /* Make entries in Protocol column and Info column on summary display */
2888 if (check_col(fd, COL_PROTOCOL))
2889 col_add_str(fd, COL_PROTOCOL, "X11");
2891 /* This field shows up as the "Info" column in the display; you should make
2892 it, if possible, summarize what's in the packet, so that a user looking
2893 at the list of packets can tell what type of packet it is.
2895 "col_add_fstr()" can be used instead of "col_add_str()"; it takes
2896 "printf()"-like arguments. */
2897 if (check_col(fd, COL_INFO))
2898 col_add_str(fd, COL_INFO, "X11 event");
2900 /* In the interest of speed, if "tree" is NULL, don't do any work not
2901 necessary to generate protocol tree items. */
2903 /* NOTE: The offset and length values in the previous call to
2904 "proto_tree_add_item()" define what data bytes to highlight in the hex
2905 display window when the line in the protocol tree display
2906 corresponding to that item is selected.
2908 END_OF_FRAME is a handy way to highlight all data from the offset to
2909 the end of the packet. */
2910 ti = proto_tree_add_item(tree, proto_x11, NullTVB, offset, END_OF_FRAME, FALSE);
2911 x11_tree = proto_item_add_subtree(ti, ett_x11);
2913 /* Code to process the packet goes here */
2915 old_dissect_data(pd, offset, fd, tree);
2920 dissect_x11(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2923 OLD_CHECK_DISPLAY_AS_DATA(proto_x11, pd, offset, fd, tree);
2925 pi.current_proto = "X11";
2926 if (pi.destport == TCP_PORT_X11 || pi.destport == TCP_PORT_X11_2 || pi.destport == TCP_PORT_X11_3)
2927 dissect_x11_request(pd, offset, fd, tree);
2929 dissect_x11_event(pd, offset, fd, tree);
2932 /* Register the protocol with Ethereal */
2933 void proto_register_x11(void)
2936 /* Setup list of header fields */
2937 static hf_register_info hf[] = {
2939 { &hf_x11_FIELDABBREV,
2940 { "FIELDNAME", "x11.FIELDABBREV",
2941 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
2945 #include "packet-x11-register-info.h"
2948 /* Setup protocol subtree array */
2949 static gint *ett[] = {
2954 /* Register the protocol name and description */
2955 proto_x11 = proto_register_protocol("X11", "x11");
2957 /* Required function calls to register the header fields and subtrees used */
2958 proto_register_field_array(proto_x11, hf, array_length(hf));
2959 proto_register_subtree_array(ett, array_length(ett));
2961 byte_ordering_cache = g_tree_new(compareAddresses);
2962 address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address),
2963 sizeof(address) * 128, G_ALLOC_ONLY);
2964 ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
2965 ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
2970 proto_reg_handoff_x11(void)
2972 old_dissector_add("tcp.port", TCP_PORT_X11, dissect_x11);
2973 old_dissector_add("tcp.port", TCP_PORT_X11_2, dissect_x11);
2974 old_dissector_add("tcp.port", TCP_PORT_X11_3, dissect_x11);