2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /* TODO (in no particular order):
31 * - keep track of Atom creation by server to be able to display
32 * non-predefined atoms
33 * - Idem for keysym <-> keycode ???
35 * - Subtree the request ids (that is x11.create-window.window and
36 * x11.change-window.window should be distinct), and add hidden fields
37 * (so we still have x11.window).
38 * - add hidden fields so we can have x11.circulate-window in addition to
39 * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
41 * - add hidden fields so we have x11.listOfStuff.length
42 * - use a faster scheme that linear list searching for the opcode.
43 * - correct display of Unicode chars.
44 * - Not everything is homogeneous, in particular the handling of items in
45 * list is a total mess.
48 /* By the way, I wrote a program to generate every request and test
49 * that stuff. If you're interested, you can get it at
50 * http://tronche.com/gui/x/
64 #include <epan/packet.h>
65 #include <epan/conversation.h>
67 #include <epan/prefs.h>
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
70 #include <epan/emem.h>
72 #define cVALS(x) (const value_string*)(x)
75 * Data structure associated with a conversation; keeps track of the
76 * request for which we're expecting a reply, the frame number of
77 * the initial connection request, and the byte order of the connection.
79 * An opcode of -3 means we haven't yet seen any requests yet.
80 * An opcode of -2 means we're not expecting a reply (unused).
81 * An opcode of -1 means we're waiting for a reply to the initial
83 * An opcode of 0 means the request was not seen (or unknown).
84 * Other values are the opcode of the request for which we're expecting
88 #define NOTHING_SEEN -3
89 #define NOTHING_EXPECTED -2
90 #define INITIAL_CONN -1
91 #define UNKNOWN_OPCODE 0
93 #define MAX_OPCODES (255 + 1) /* 255 + INITIAL_CONN */
95 #define BYTE_ORDER_BE 0
96 #define BYTE_ORDER_LE 1
97 #define BYTE_ORDER_UNKNOWN -1
99 static const char *modifiers[] = {
110 /* Keymasks. From <X11/X.h>. */
111 #define ShiftMask (1<<0)
112 #define LockMask (1<<1)
113 #define ControlMask (1<<2)
114 #define Mod1Mask (1<<3)
115 #define Mod2Mask (1<<4)
116 #define Mod3Mask (1<<5)
117 #define Mod4Mask (1<<6)
118 #define Mod5Mask (1<<7)
120 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
121 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
124 #define NoSymbol 0L /* special KeySym */
126 typedef struct _x11_conv_data {
127 struct _x11_conv_data *next;
128 GHashTable *seqtable; /* hashtable of sequencenumber <-> opcode. */
129 GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
130 /* major opcodes including extensions (NULL terminated) */
131 value_string opcode_vals[MAX_OPCODES+1];
132 int sequencenumber; /* sequencenumber of current packet. */
133 guint32 iconn_frame; /* frame # of initial connection request */
134 guint32 iconn_reply; /* frame # of initial connection reply */
135 int byte_order; /* byte order of connection */
136 gboolean resync; /* resynchronization of sequence number performed */
138 int *keycodemap[256]; /* keycode to keysymvalue map. */
139 int keysyms_per_keycode;
141 int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
142 int keycodes_per_modifier;
147 } GetKeyboardMapping;
151 static x11_conv_data_t *x11_conv_data_list;
153 /* Initialize the protocol and registered fields */
154 static int proto_x11 = -1;
156 #include "x11-declarations.h"
158 /* Initialize the subtree pointers */
159 static gint ett_x11 = -1;
160 static gint ett_x11_color_flags = -1;
161 static gint ett_x11_list_of_arc = -1;
162 static gint ett_x11_arc = -1;
163 static gint ett_x11_list_of_atom = -1;
164 static gint ett_x11_list_of_card32 = -1;
165 static gint ett_x11_list_of_color_item = -1;
166 static gint ett_x11_color_item = -1;
167 static gint ett_x11_list_of_keycode = -1;
168 static gint ett_x11_list_of_keysyms = -1;
169 static gint ett_x11_keysym = -1;
170 static gint ett_x11_list_of_point = -1;
171 static gint ett_x11_point = -1;
172 static gint ett_x11_list_of_rectangle = -1;
173 static gint ett_x11_rectangle = -1;
174 static gint ett_x11_list_of_segment = -1;
175 static gint ett_x11_segment = -1;
176 static gint ett_x11_list_of_string8 = -1;
177 static gint ett_x11_list_of_text_item = -1;
178 static gint ett_x11_text_item = -1;
179 static gint ett_x11_gc_value_mask = -1; /* XXX - unused */
180 static gint ett_x11_event_mask = -1; /* XXX - unused */
181 static gint ett_x11_do_not_propagate_mask = -1; /* XXX - unused */
182 static gint ett_x11_set_of_key_mask = -1;
183 static gint ett_x11_pointer_event_mask = -1; /* XXX - unused */
184 static gint ett_x11_window_value_mask = -1; /* XXX - unused */
185 static gint ett_x11_configure_window_mask = -1; /* XXX - unused */
186 static gint ett_x11_keyboard_value_mask = -1; /* XXX - unused */
187 static gint ett_x11_same_screen_focus = -1;
188 static gint ett_x11_event = -1;
190 /* desegmentation of X11 messages */
191 static gboolean x11_desegment = TRUE;
193 #define TCP_PORT_X11 6000
194 #define TCP_PORT_X11_2 6001
195 #define TCP_PORT_X11_3 6002
198 * Round a length to a multiple of 4 bytes.
200 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
202 /************************************************************************
204 *** E N U M T A B L E S D E F I N I T I O N S ***
206 ************************************************************************/
208 static const value_string byte_order_vals[] = {
209 { 'B', "Big-endian" },
210 { 'l', "Little-endian" },
214 static const value_string image_byte_order_vals[] = {
220 static const value_string access_mode_vals[] = {
226 static const value_string all_temporary_vals[] = {
227 { 0, "AllTemporary" },
231 static const value_string alloc_vals[] = {
237 static const value_string allow_events_mode_vals[] = {
238 { 0, "AsyncPointer" },
239 { 1, "SyncPointer" },
240 { 2, "ReplayPointer" },
241 { 3, "AsyncKeyboard" },
242 { 4, "SyncKeyboard" },
243 { 5, "ReplayKeyboard" },
249 static const value_string arc_mode_vals[] = {
255 static const char *atom_predefined_interpretation[] = {
307 "UNDERLINE_POSITION",
308 "UNDERLINE_THICKNESS",
327 static const value_string auto_repeat_mode_vals[] = {
334 static const value_string background_pixmap_vals[] = {
336 { 1, "ParentRelative" },
340 static const value_string backing_store_vals[] = {
347 static const value_string border_pixmap_vals[] = {
348 { 0, "CopyFromParent" },
352 static const value_string button_vals[] = {
353 { 0x8000, "AnyButton" },
357 static const value_string cap_style_vals[] = {
365 static const value_string class_vals[] = {
372 static const value_string close_down_mode_vals[] = {
374 { 1, "RetainPermanent" },
375 { 2, "RetainTemporary" },
379 static const value_string colormap_state_vals[] = {
380 { 0, "Uninstalled" },
385 static const value_string coordinate_mode_vals[] = {
391 static const value_string destination_vals[] = {
392 { 0, "PointerWindow" },
397 static const value_string direction_vals[] = {
398 { 0, "RaiseLowest" },
399 { 1, "LowerHighest" },
403 static const value_string event_detail_vals[] = {
408 { 4, "NonlinearVirtual" },
412 #define FAMILY_INTERNET 0
413 #define FAMILY_DECNET 1
414 #define FAMILY_CHAOS 2
416 static const value_string family_vals[] = {
417 { FAMILY_INTERNET, "Internet" },
418 { FAMILY_DECNET, "DECnet" },
419 { FAMILY_CHAOS, "Chaos" },
423 static const value_string fill_rule_vals[] = {
429 static const value_string fill_style_vals[] = {
433 { 3, "OpaqueStippled" },
437 static const value_string focus_detail_vals[] = {
442 { 4, "NonlinearVirtual" },
444 { 6, "PointerRoot" },
449 static const value_string focus_mode_vals[] = {
453 { 3, "WhileGrabbed" },
457 static const value_string focus_vals[] = {
459 { 1, "PointerRoot" },
463 static const value_string function_vals[] = {
468 { 4, "AndInverted" },
476 { 12, "CopyInverted" },
477 { 13, "OrInverted" },
483 static const value_string grab_mode_vals[] = {
490 static const value_string grab_status_vals[] = {
492 { 1, "AlreadyGrabbed" },
493 { 2, "InvalidTime" },
494 { 3, "NotViewable" },
499 static const value_string gravity_vals[] = {
513 static const value_string image_format_vals[] = {
520 static const value_string image_pixmap_format_vals[] = {
526 static const value_string join_style_vals[] = {
533 static const value_string key_vals[] = {
538 #include "packet-x11-keysym.h"
540 static const value_string line_style_vals[] = {
547 static const value_string mode_vals[] = {
554 static const value_string on_off_vals[] = {
560 static const value_string place_vals[] = {
566 static const value_string property_state_vals[] = {
572 static const value_string visibility_state_vals[] = {
574 { 1, "PartiallyObscured" },
575 { 2, "FullyObscured" },
579 static const value_string mapping_request_vals[] = {
580 { 0, "MappingModifier" },
581 { 1, "MappingKeyboard" },
582 { 2, "MappingPointer" },
586 /* Requestcodes. From <X11/Xproto.h>. */
587 #define X_CreateWindow 1
588 #define X_ChangeWindowAttributes 2
589 #define X_GetWindowAttributes 3
590 #define X_DestroyWindow 4
591 #define X_DestroySubwindows 5
592 #define X_ChangeSaveSet 6
593 #define X_ReparentWindow 7
594 #define X_MapWindow 8
595 #define X_MapSubwindows 9
596 #define X_UnmapWindow 10
597 #define X_UnmapSubwindows 11
598 #define X_ConfigureWindow 12
599 #define X_CirculateWindow 13
600 #define X_GetGeometry 14
601 #define X_QueryTree 15
602 #define X_InternAtom 16
603 #define X_GetAtomName 17
604 #define X_ChangeProperty 18
605 #define X_DeleteProperty 19
606 #define X_GetProperty 20
607 #define X_ListProperties 21
608 #define X_SetSelectionOwner 22
609 #define X_GetSelectionOwner 23
610 #define X_ConvertSelection 24
611 #define X_SendEvent 25
612 #define X_GrabPointer 26
613 #define X_UngrabPointer 27
614 #define X_GrabButton 28
615 #define X_UngrabButton 29
616 #define X_ChangeActivePointerGrab 30
617 #define X_GrabKeyboard 31
618 #define X_UngrabKeyboard 32
620 #define X_UngrabKey 34
621 #define X_AllowEvents 35
622 #define X_GrabServer 36
623 #define X_UngrabServer 37
624 #define X_QueryPointer 38
625 #define X_GetMotionEvents 39
626 #define X_TranslateCoords 40
627 #define X_WarpPointer 41
628 #define X_SetInputFocus 42
629 #define X_GetInputFocus 43
630 #define X_QueryKeymap 44
631 #define X_OpenFont 45
632 #define X_CloseFont 46
633 #define X_QueryFont 47
634 #define X_QueryTextExtents 48
635 #define X_ListFonts 49
636 #define X_ListFontsWithInfo 50
637 #define X_SetFontPath 51
638 #define X_GetFontPath 52
639 #define X_CreatePixmap 53
640 #define X_FreePixmap 54
641 #define X_CreateGC 55
642 #define X_ChangeGC 56
644 #define X_SetDashes 58
645 #define X_SetClipRectangles 59
647 #define X_ClearArea 61
648 #define X_CopyArea 62
649 #define X_CopyPlane 63
650 #define X_PolyPoint 64
651 #define X_PolyLine 65
652 #define X_PolySegment 66
653 #define X_PolyRectangle 67
655 #define X_FillPoly 69
656 #define X_PolyFillRectangle 70
657 #define X_PolyFillArc 71
658 #define X_PutImage 72
659 #define X_GetImage 73
660 #define X_PolyText8 74
661 #define X_PolyText16 75
662 #define X_ImageText8 76
663 #define X_ImageText16 77
664 #define X_CreateColormap 78
665 #define X_FreeColormap 79
666 #define X_CopyColormapAndFree 80
667 #define X_InstallColormap 81
668 #define X_UninstallColormap 82
669 #define X_ListInstalledColormaps 83
670 #define X_AllocColor 84
671 #define X_AllocNamedColor 85
672 #define X_AllocColorCells 86
673 #define X_AllocColorPlanes 87
674 #define X_FreeColors 88
675 #define X_StoreColors 89
676 #define X_StoreNamedColor 90
677 #define X_QueryColors 91
678 #define X_LookupColor 92
679 #define X_CreateCursor 93
680 #define X_CreateGlyphCursor 94
681 #define X_FreeCursor 95
682 #define X_RecolorCursor 96
683 #define X_QueryBestSize 97
684 #define X_QueryExtension 98
685 #define X_ListExtensions 99
686 #define X_ChangeKeyboardMapping 100
687 #define X_GetKeyboardMapping 101
688 #define X_ChangeKeyboardControl 102
689 #define X_GetKeyboardControl 103
691 #define X_ChangePointerControl 105
692 #define X_GetPointerControl 106
693 #define X_SetScreenSaver 107
694 #define X_GetScreenSaver 108
695 #define X_ChangeHosts 109
696 #define X_ListHosts 110
697 #define X_SetAccessControl 111
698 #define X_SetCloseDownMode 112
699 #define X_KillClient 113
700 #define X_RotateProperties 114
701 #define X_ForceScreenSaver 115
702 #define X_SetPointerMapping 116
703 #define X_GetPointerMapping 117
704 #define X_SetModifierMapping 118
705 #define X_GetModifierMapping 119
706 #define X_NoOperation 127
707 #define X_FirstExtension 128
708 #define X_LastExtension 255
710 static const value_string opcode_vals[] = {
711 { INITIAL_CONN, "Initial connection request" },
712 { X_CreateWindow, "CreateWindow" },
713 { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
714 { X_GetWindowAttributes, "GetWindowAttributes" },
715 { X_DestroyWindow, "DestroyWindow" },
716 { X_DestroySubwindows, "DestroySubwindows" },
717 { X_ChangeSaveSet, "ChangeSaveSet" },
718 { X_ReparentWindow, "ReparentWindow" },
719 { X_MapWindow, "MapWindow" },
720 { X_MapSubwindows, "MapSubwindows" },
721 { X_UnmapWindow, "UnmapWindow" },
722 { X_UnmapSubwindows, "UnmapSubwindows" },
723 { X_ConfigureWindow, "ConfigureWindow" },
724 { X_CirculateWindow, "CirculateWindow" },
725 { X_GetGeometry, "GetGeometry" },
726 { X_QueryTree, "QueryTree" },
727 { X_InternAtom, "InternAtom" },
728 { X_GetAtomName, "GetAtomName" },
729 { X_ChangeProperty, "ChangeProperty" },
730 { X_DeleteProperty, "DeleteProperty" },
731 { X_GetProperty, "GetProperty" },
732 { X_ListProperties, "ListProperties" },
733 { X_SetSelectionOwner, "SetSelectionOwner" },
734 { X_GetSelectionOwner, "GetSelectionOwner" },
735 { X_ConvertSelection, "ConvertSelection" },
736 { X_SendEvent, "SendEvent" },
737 { X_GrabPointer, "GrabPointer" },
738 { X_UngrabPointer, "UngrabPointer" },
739 { X_GrabButton, "GrabButton" },
740 { X_UngrabButton, "UngrabButton" },
741 { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
742 { X_GrabKeyboard, "GrabKeyboard" },
743 { X_UngrabKeyboard, "UngrabKeyboard" },
744 { X_GrabKey, "GrabKey" },
745 { X_UngrabKey, "UngrabKey" },
746 { X_AllowEvents, "AllowEvents" },
747 { X_GrabServer, "GrabServer" },
748 { X_UngrabServer, "UngrabServer" },
749 { X_QueryPointer, "QueryPointer" },
750 { X_GetMotionEvents, "GetMotionEvents" },
751 { X_TranslateCoords, "TranslateCoordinates" },
752 { X_WarpPointer, "WarpPointer" },
753 { X_SetInputFocus, "SetInputFocus" },
754 { X_GetInputFocus, "GetInputFocus" },
755 { X_QueryKeymap, "QueryKeymap" },
756 { X_OpenFont, "OpenFont" },
757 { X_CloseFont, "CloseFont" },
758 { X_QueryFont, "QueryFont" },
759 { X_QueryTextExtents, "QueryTextExtents" },
760 { X_ListFonts, "ListFonts" },
761 { X_ListFontsWithInfo, "ListFontsWithInfo" },
762 { X_SetFontPath, "SetFontPath" },
763 { X_GetFontPath, "GetFontPath" },
764 { X_CreatePixmap, "CreatePixmap" },
765 { X_FreePixmap, "FreePixmap" },
766 { X_CreateGC, "CreateGC" },
767 { X_ChangeGC, "ChangeGC" },
768 { X_CopyGC, "CopyGC" },
769 { X_SetDashes, "SetDashes" },
770 { X_SetClipRectangles, "SetClipRectangles" },
771 { X_FreeGC, "FreeGC" },
772 { X_ClearArea, "ClearArea" },
773 { X_CopyArea, "CopyArea" },
774 { X_CopyPlane, "CopyPlane" },
775 { X_PolyPoint, "PolyPoint" },
776 { X_PolyLine, "PolyLine" },
777 { X_PolySegment, "PolySegment" },
778 { X_PolyRectangle, "PolyRectangle" },
779 { X_PolyArc, "PolyArc" },
780 { X_FillPoly, "FillPoly" },
781 { X_PolyFillRectangle, "PolyFillRectangle" },
782 { X_PolyFillArc, "PolyFillArc" },
783 { X_PutImage, "PutImage" },
784 { X_GetImage, "GetImage" },
785 { X_PolyText8, "PolyText8" },
786 { X_PolyText16, "PolyText16" },
787 { X_ImageText8, "ImageText8" },
788 { X_ImageText16, "ImageText16" },
789 { X_CreateColormap, "CreateColormap" },
790 { X_FreeColormap, "FreeColormap" },
791 { X_CopyColormapAndFree, "CopyColormapAndFree" },
792 { X_InstallColormap, "InstallColormap" },
793 { X_UninstallColormap, "UninstallColormap" },
794 { X_ListInstalledColormaps, "ListInstalledColormaps" },
795 { X_AllocColor, "AllocColor" },
796 { X_AllocNamedColor, "AllocNamedColor" },
797 { X_AllocColorCells, "AllocColorCells" },
798 { X_AllocColorPlanes, "AllocColorPlanes" },
799 { X_FreeColors, "FreeColors" },
800 { X_StoreColors, "StoreColors" },
801 { X_StoreNamedColor, "StoreNamedColor" },
802 { X_QueryColors, "QueryColors" },
803 { X_LookupColor, "LookupColor" },
804 { X_CreateCursor, "CreateCursor" },
805 { X_CreateGlyphCursor, "CreateGlyphCursor" },
806 { X_FreeCursor, "FreeCursor" },
807 { X_RecolorCursor, "RecolorCursor" },
808 { X_QueryBestSize, "QueryBestSize" },
809 { X_QueryExtension, "QueryExtension" },
810 { X_ListExtensions, "ListExtensions" },
811 { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
812 { X_GetKeyboardMapping, "GetKeyboardMapping" },
813 { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
814 { X_GetKeyboardControl, "GetKeyboardControl" },
816 { X_ChangePointerControl, "ChangePointerControl" },
817 { X_GetPointerControl, "GetPointerControl" },
818 { X_SetScreenSaver, "SetScreenSaver" },
819 { X_GetScreenSaver, "GetScreenSaver" },
820 { X_ChangeHosts, "ChangeHosts" },
821 { X_ListHosts, "ListHosts" },
822 { X_SetAccessControl, "SetAccessControl" },
823 { X_SetCloseDownMode, "SetCloseDownMode" },
824 { X_KillClient, "KillClient" },
825 { X_RotateProperties, "RotateProperties" },
826 { X_ForceScreenSaver, "ForceScreenSaver" },
827 { X_SetPointerMapping, "SetPointerMapping" },
828 { X_GetPointerMapping, "GetPointerMapping" },
829 { X_SetModifierMapping, "SetModifierMapping" },
830 { X_GetModifierMapping, "GetModifierMapping" },
831 { X_NoOperation, "NoOperation" },
835 /* Eventscodes. From <X11/X.h>. */
838 #define ButtonPress 4
839 #define ButtonRelease 5
840 #define MotionNotify 6
841 #define EnterNotify 7
842 #define LeaveNotify 8
845 #define KeymapNotify 11
847 #define GraphicsExpose 13
849 #define VisibilityNotify 15
850 #define CreateNotify 16
851 #define DestroyNotify 17
852 #define UnmapNotify 18
854 #define MapRequest 20
855 #define ReparentNotify 21
856 #define ConfigureNotify 22
857 #define ConfigureRequest 23
858 #define GravityNotify 24
859 #define ResizeRequest 25
860 #define CirculateNotify 26
861 #define CirculateRequest 27
862 #define PropertyNotify 28
863 #define SelectionClear 29
864 #define SelectionRequest 30
865 #define SelectionNotify 31
866 #define ColormapNotify 32
867 #define ClientMessage 33
868 #define MappingNotify 34
869 #define FirstExtensionEvent 64
870 #define LastExtensionEvent 127
872 static const value_string eventcode_vals[] = {
873 { KeyPress, "KeyPress" },
874 { KeyRelease, "KeyRelease" },
875 { ButtonPress, "ButtonPress" },
876 { ButtonRelease, "ButtonRelease" },
877 { MotionNotify, "MotionNotify" },
878 { EnterNotify, "EnterNotify" },
879 { LeaveNotify, "LeaveNotify" },
880 { FocusIn, "FocusIn" },
881 { FocusOut, "FocusOut" },
882 { KeymapNotify, "KeymapNotify" },
883 { Expose, "Expose" },
884 { GraphicsExpose, "GraphicsExpose" },
885 { NoExpose, "NoExpose" },
886 { VisibilityNotify, "VisibilityNotify" },
887 { CreateNotify, "CreateNotify" },
888 { DestroyNotify, "DestroyNotify" },
889 { UnmapNotify, "UnmapNotify" },
890 { MapNotify, "MapNotify" },
891 { MapRequest, "MapRequest" },
892 { ReparentNotify, "ReparentNotify" },
893 { ConfigureNotify, "ConfigureNotify" },
894 { ConfigureRequest, "ConfigureRequest" },
895 { GravityNotify, "GravityNotify" },
896 { ResizeRequest, "ResizeRequest" },
897 { CirculateNotify, "CirculateNotify" },
898 { CirculateRequest, "CirculateRequest" },
899 { PropertyNotify, "PropertyNotify" },
900 { SelectionClear, "SelectionClear" },
901 { SelectionRequest, "SelectionRequest" },
902 { SelectionNotify, "SelectionNotify" },
903 { ColormapNotify, "ColormapNotify" },
904 { ClientMessage, "ClientMessage" },
905 { MappingNotify, "MappingNotify" },
909 /* Errorcodes. From <X11/X.h> */
910 #define Success 0 /* everything's okay */
911 #define BadRequest 1 /* bad request code */
912 #define BadValue 2 /* int parameter out of range */
913 #define BadWindow 3 /* parameter not a Window */
914 #define BadPixmap 4 /* parameter not a Pixmap */
915 #define BadAtom 5 /* parameter not an Atom */
916 #define BadCursor 6 /* parameter not a Cursor */
917 #define BadFont 7 /* parameter not a Font */
918 #define BadMatch 8 /* parameter mismatch */
919 #define BadDrawable 9 /* parameter not a Pixmap or Window */
920 #define BadAccess 10 /* depending on context:
921 - key/button already grabbed
922 - attempt to free an illegal
924 - attempt to store into a read-only
926 - attempt to modify the access control
927 list from other than the local host.
929 #define BadAlloc 11 /* insufficient resources */
930 #define BadColor 12 /* no such colormap */
931 #define BadGC 13 /* parameter not a GC */
932 #define BadIDChoice 14 /* choice not in range or already used */
933 #define BadName 15 /* font or color name doesn't exist */
934 #define BadLength 16 /* Request length incorrect */
935 #define BadImplementation 17 /* server is defective */
937 #define FirstExtensionError 128
938 #define LastExtensionError 255
940 static const value_string errorcode_vals[] = {
941 { Success, "Success" },
942 { BadRequest, "BadRequest" },
943 { BadValue, "BadValue" },
944 { BadWindow, "BadWindow" },
945 { BadPixmap, "BadPixmap" },
946 { BadAtom, "BadAtom" },
947 { BadCursor, "BadCursor" },
948 { BadFont, "BadFont" },
949 { BadMatch, "BadMatch" },
950 { BadDrawable, "BadDrawable" },
951 { BadAccess, "BadAccess" },
952 { BadAlloc, "BadAlloc" },
953 { BadColor, "BadColor" },
955 { BadIDChoice, "BadIDChoice" },
956 { BadName, "BadName" },
957 { BadLength, "BadLength" },
958 { BadImplementation, "BadImplementation" },
959 { FirstExtensionError, "FirstExtensionError" },
960 { LastExtensionError, "LastExtensionError" },
964 static const value_string ordering_vals[] = {
972 static const value_string plane_mask_vals[] = {
973 { 0xFFFFFFFF, "AllPlanes" },
977 static const value_string pointer_keyboard_mode_vals[] = {
978 { 0, "Synchronous" },
979 { 1, "Asynchronous" },
983 static const value_string revert_to_vals[] = {
985 { 1, "PointerRoot" },
990 static const value_string insert_delete_vals[] = {
996 static const value_string screen_saver_mode_vals[] = {
1002 static const value_string shape_vals[] = {
1009 static const value_string stack_mode_vals[] = {
1018 static const value_string subwindow_mode_vals[] = {
1019 { 0, "ClipByChildren" },
1020 { 1, "IncludeInferiors" },
1024 static const value_string window_class_vals[] = {
1025 { 0, "CopyFromParent" },
1026 { 1, "InputOutput" },
1031 static const value_string yes_no_default_vals[] = {
1038 static const value_string zero_is_any_property_type_vals[] = {
1039 { 0, "AnyPropertyType" },
1043 static const value_string zero_is_none_vals[] = {
1048 /* we have not seen packet before. */
1049 #define PACKET_IS_NEW(pinfo) \
1050 (!((pinfo)->fd->flags.visited))
1052 /************************************************************************
1054 *** F I E L D D E C O D I N G M A C R O S ***
1056 ************************************************************************/
1058 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
1059 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
1060 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
1062 #define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
1063 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
1064 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
1066 #define BITFIELD(TYPE, position, name) {\
1068 int save = *offsetp;\
1069 proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
1070 bitmask_size, little_endian); \
1071 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
1073 unused = save + 4 - *offsetp;\
1075 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
1076 *offsetp = save + 4;\
1080 #define FLAG(position, name) {\
1081 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
1083 #define FLAG_IF_NONZERO(position, name) do {\
1084 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
1085 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
1087 #define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
1088 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
1089 #define BITMASK(name, size) {\
1091 guint32 bitmask_value; \
1092 int bitmask_offset; \
1094 proto_tree *bitmask_tree; \
1095 bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
1096 ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
1097 (guint32)VALUE32(tvb, *offsetp))); \
1098 bitmask_offset = *offsetp; \
1099 bitmask_size = size; \
1100 ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
1101 bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
1103 #define ENDBITMASK }
1104 #define BITMASK8(name) BITMASK(name, 1);
1105 #define BITMASK16(name) BITMASK(name, 2);
1106 #define BITMASK32(name) BITMASK(name, 4);
1107 #define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
1108 #define BUTTON(name) FIELD8(name)
1109 #define CARD8(name) FIELD8(name)
1110 #define CARD16(name) (FIELD16(name))
1111 #define CARD32(name) (FIELD32(name))
1112 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1113 #define COLORMAP(name) FIELD32(name)
1114 #define CURSOR(name) FIELD32(name)
1115 #define DRAWABLE(name) FIELD32(name)
1116 #define ENUM8(name) (FIELD8(name))
1117 #define ENUM16(name) (FIELD16(name))
1118 #define FONT(name) FIELD32(name)
1119 #define FONTABLE(name) FIELD32(name)
1120 #define GCONTEXT(name) FIELD32(name)
1121 #define INT8(name) FIELD8(name)
1122 #define INT16(name) FIELD16(name)
1123 #define INT32(name) FIELD32(name)
1124 #define KEYCODE(name) FIELD8(name)
1125 #define KEYCODE_DECODED(name, keycode, mask) do { \
1126 proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
1127 keycode, "keycode: %d (%s)", \
1128 keycode, keycode2keysymString(state->keycodemap, \
1129 state->first_keycode, state->keysyms_per_keycode, \
1130 state->modifiermap, state->keycodes_per_modifier, \
1134 #define EVENT() do { \
1135 tvbuff_t *next_tvb; \
1136 unsigned char eventcode; \
1139 proto_tree *proto_tree; \
1140 next_tvb = tvb_new_subset(tvb, offset, next_offset - offset, \
1141 next_offset - offset); \
1142 eventcode = tvb_get_guint8(next_tvb, 0); \
1143 sent = (eventcode & 0x80) ? "Sent-" : ""; \
1144 ti = proto_tree_add_text(t, next_tvb, 0, -1, "event: %d (%s)", \
1146 val_to_str(eventcode & 0x7F, \
1148 "<Unknown eventcode %u>")); \
1149 proto_tree = proto_item_add_subtree(ti, ett_x11_event); \
1150 decode_x11_event(next_tvb, eventcode, sent, proto_tree, \
1151 state, little_endian); \
1152 offset = next_offset; \
1155 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
1156 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1157 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1158 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1159 #define LISTofIPADDRESS(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), FALSE); }
1160 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1161 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1162 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1163 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1164 keysyms_per_keycode) {\
1165 listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1166 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1167 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1168 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1169 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1170 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1171 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1172 #define OPCODE() { opcode = FIELD8(opcode); }
1173 #define PIXMAP(name) { FIELD32(name); }
1174 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1175 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1176 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1177 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1178 #define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 1); }
1179 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1180 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1181 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1182 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1183 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
1184 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
1185 #define PAD() { if (next_offset - *offsetp > 0) proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, next_offset - *offsetp, little_endian); *offsetp = next_offset; }
1186 #define WINDOW(name) { FIELD32(name); }
1187 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1189 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1190 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1191 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1192 #define REPLY(name) FIELD8(name);
1193 #define REPLYLENGTH(name) FIELD32(name);
1195 #define EVENTCONTENTS_COMMON() do { \
1197 WINDOW(rootwindow); \
1198 WINDOW(eventwindow); \
1199 WINDOW(childwindow); \
1204 setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
1207 #define SEQUENCENUMBER_REPLY(name) do { \
1210 seqno = VALUE16(tvb, *offsetp); \
1211 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1212 *offsetp, sizeof(seqno), seqno, \
1213 "sequencenumber: %d (%s)", \
1215 val_to_str(opcode, state->opcode_vals, "<Unknown opcode %d>")); \
1216 *offsetp += sizeof(seqno); \
1219 #define REPLYCONTENTS_COMMON() do { \
1221 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1222 1, little_endian); \
1224 SEQUENCENUMBER_REPLY(sequencenumber); \
1225 REPLYLENGTH(replylength); \
1226 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1227 tvb_reported_length_remaining(tvb, offset), little_endian); \
1228 offset += tvb_reported_length_remaining(tvb, offset); \
1232 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1233 if (length_remaining < plen) { \
1234 if (x11_desegment && pinfo->can_desegment) { \
1235 pinfo->desegment_offset = offset; \
1236 pinfo->desegment_len = plen - length_remaining;\
1239 ; /* XXX yes, what then? Need to skip/join. */ \
1242 if (length_remaining > plen) \
1243 length_remaining = plen; \
1244 next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1246 if (sep == NULL) { \
1247 if (check_col(pinfo->cinfo, COL_INFO)) \
1248 col_set_str(pinfo->cinfo, COL_INFO, str); \
1253 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1256 CATCH(BoundsError) { \
1259 CATCH(ReportedBoundsError) { \
1260 show_reported_bounds_error(next_tvb, pinfo, tree); \
1268 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1269 const char *sep, x11_conv_data_t *volatile state,
1270 gboolean little_endian);
1273 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1274 const char *volatile sep, x11_conv_data_t *volatile state,
1275 gboolean little_endian);
1278 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1279 const char *volatile sep, x11_conv_data_t *volatile state,
1280 gboolean little_endian);
1283 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1284 const char *volatile sep, x11_conv_data_t *volatile state,
1285 gboolean little_endian);
1288 decode_x11_event(tvbuff_t *tvb, unsigned char eventcode, const char *sent,
1289 proto_tree *t, x11_conv_data_t *volatile state,
1290 gboolean little_endian);
1292 static x11_conv_data_t *
1293 x11_stateinit(conversation_t *conversation);
1296 keysymString(guint32 v);
1299 /************************************************************************
1301 *** D E C O D I N G F I E L D S ***
1303 ************************************************************************/
1305 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1306 gboolean little_endian)
1308 const char *interpretation = NULL;
1310 guint32 v = VALUE32(tvb, *offsetp);
1311 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1312 interpretation = atom_predefined_interpretation[v];
1314 interpretation = "Not a predefined atom";
1316 header_field_info *hfi = proto_registrar_get_nth(hf);
1318 interpretation = match_strval(v, cVALS(hfi -> strings));
1320 if (!interpretation) interpretation = "error in Xlib client program ?";
1321 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1322 proto_registrar_get_nth(hf) -> name, v, interpretation);
1326 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1328 guint32 v = VALUE8(tvb, *offsetp);
1329 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1334 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1336 unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1340 if (do_red_green_blue) {
1342 emem_strbuf_t *buffer = ep_strbuf_new_label("flags: ");
1344 if (do_red_green_blue & 0x1) {
1345 ep_strbuf_append(buffer, "DoRed");
1349 if (do_red_green_blue & 0x2) {
1350 if (sep) ep_strbuf_append(buffer, " | ");
1351 ep_strbuf_append(buffer, "DoGreen");
1355 if (do_red_green_blue & 0x4) {
1356 if (sep) ep_strbuf_append(buffer, " | ");
1357 ep_strbuf_append(buffer, "DoBlue");
1361 if (do_red_green_blue & 0xf8) {
1362 if (sep) ep_strbuf_append(buffer, " + trash");
1365 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1367 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1368 if (do_red_green_blue & 0x1)
1369 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1370 do_red_green_blue & 0x1);
1371 if (do_red_green_blue & 0x2)
1372 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1373 do_red_green_blue & 0x2);
1374 if (do_red_green_blue & 0x4)
1375 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1376 do_red_green_blue & 0x4);
1377 if (do_red_green_blue & 0xf8)
1378 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1379 do_red_green_blue & 0xf8);
1381 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1386 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1387 int hf, const char *nullInterpretation)
1389 guint8 v = VALUE8(tvb, *offsetp);
1392 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1393 proto_registrar_get_nth(hf) -> name,
1394 nullInterpretation);
1396 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1400 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1401 int length, gboolean little_endian)
1403 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1404 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1406 gint16 x = VALUE16(tvb, *offsetp);
1407 gint16 y = VALUE16(tvb, *offsetp + 2);
1408 guint16 width = VALUE16(tvb, *offsetp + 4);
1409 guint16 height = VALUE16(tvb, *offsetp + 6);
1410 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1411 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1413 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1414 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1415 width, height, x, y, angle1, angle2,
1416 angle1 / 64.0, angle2 / 64.0);
1417 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1418 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1420 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1422 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1424 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1426 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1428 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1433 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1434 int length, gboolean little_endian)
1436 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1437 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1439 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1442 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1443 int length, gboolean little_endian)
1445 if (length <= 0) length = 1;
1446 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1450 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1451 int hf_item, int length, gboolean little_endian)
1453 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1454 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1456 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1461 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1462 int length, gboolean little_endian)
1464 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1465 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1469 unsigned do_red_green_blue;
1470 guint16 red, green, blue;
1471 emem_strbuf_t *buffer;
1474 buffer=ep_strbuf_new_label("colorItem ");
1475 red = VALUE16(tvb, *offsetp + 4);
1476 green = VALUE16(tvb, *offsetp + 6);
1477 blue = VALUE16(tvb, *offsetp + 8);
1478 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1481 if (do_red_green_blue & 0x1) {
1482 ep_strbuf_append_printf(buffer, "red = %d", red);
1485 if (do_red_green_blue & 0x2) {
1486 ep_strbuf_append_printf(buffer, "%sgreen = %d", sep, green);
1489 if (do_red_green_blue & 0x4)
1490 ep_strbuf_append_printf(buffer, "%sblue = %d", sep, blue);
1492 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer->str);
1493 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1494 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1496 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1498 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1500 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1502 colorFlags(tvb, offsetp, ttt);
1503 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1508 static GTree *keysymTable = NULL;
1510 static gint compareGuint32(gconstpointer a, gconstpointer b)
1512 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1516 XConvertCase(register int sym, int *lower, int *upper)
1521 case 0: /* Latin 1 */
1522 if ((sym >= XK_A) && (sym <= XK_Z))
1523 *lower += (XK_a - XK_A);
1524 else if ((sym >= XK_a) && (sym <= XK_z))
1525 *upper -= (XK_a - XK_A);
1526 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1527 *lower += (XK_agrave - XK_Agrave);
1528 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1529 *upper -= (XK_agrave - XK_Agrave);
1530 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1531 *lower += (XK_oslash - XK_Ooblique);
1532 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1533 *upper -= (XK_oslash - XK_Ooblique);
1535 case 1: /* Latin 2 */
1536 /* Assume the KeySym is a legal value (ignore discontinuities) */
1537 if (sym == XK_Aogonek)
1538 *lower = XK_aogonek;
1539 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1540 *lower += (XK_lstroke - XK_Lstroke);
1541 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1542 *lower += (XK_scaron - XK_Scaron);
1543 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1544 *lower += (XK_zcaron - XK_Zcaron);
1545 else if (sym == XK_aogonek)
1546 *upper = XK_Aogonek;
1547 else if (sym >= XK_lstroke && sym <= XK_sacute)
1548 *upper -= (XK_lstroke - XK_Lstroke);
1549 else if (sym >= XK_scaron && sym <= XK_zacute)
1550 *upper -= (XK_scaron - XK_Scaron);
1551 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1552 *upper -= (XK_zcaron - XK_Zcaron);
1553 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1554 *lower += (XK_racute - XK_Racute);
1555 else if (sym >= XK_racute && sym <= XK_tcedilla)
1556 *upper -= (XK_racute - XK_Racute);
1558 case 2: /* Latin 3 */
1559 /* Assume the KeySym is a legal value (ignore discontinuities) */
1560 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1561 *lower += (XK_hstroke - XK_Hstroke);
1562 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1563 *lower += (XK_gbreve - XK_Gbreve);
1564 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1565 *upper -= (XK_hstroke - XK_Hstroke);
1566 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1567 *upper -= (XK_gbreve - XK_Gbreve);
1568 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1569 *lower += (XK_cabovedot - XK_Cabovedot);
1570 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1571 *upper -= (XK_cabovedot - XK_Cabovedot);
1573 case 3: /* Latin 4 */
1574 /* Assume the KeySym is a legal value (ignore discontinuities) */
1575 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1576 *lower += (XK_rcedilla - XK_Rcedilla);
1577 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1578 *upper -= (XK_rcedilla - XK_Rcedilla);
1579 else if (sym == XK_ENG)
1581 else if (sym == XK_eng)
1583 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1584 *lower += (XK_amacron - XK_Amacron);
1585 else if (sym >= XK_amacron && sym <= XK_umacron)
1586 *upper -= (XK_amacron - XK_Amacron);
1588 case 6: /* Cyrillic */
1589 /* Assume the KeySym is a legal value (ignore discontinuities) */
1590 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1591 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1592 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1593 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1594 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1595 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1596 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1597 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1600 /* Assume the KeySym is a legal value (ignore discontinuities) */
1601 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1602 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1603 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1604 sym != XK_Greek_iotaaccentdieresis &&
1605 sym != XK_Greek_upsilonaccentdieresis)
1606 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1607 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1608 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1609 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1610 sym != XK_Greek_finalsmallsigma)
1611 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1617 keycode2keysymString(int *keycodemap[256], int first_keycode,
1618 int keysyms_per_keycode,
1619 int *modifiermap[array_length(modifiers)],
1620 int keycodes_per_modifier,
1621 guint32 keycode, guint32 bitmask)
1625 int groupmodkc, numlockkc, numlockmod, groupmod;
1626 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1627 int lockmod_is_nosymbol = 1;
1628 int modifier, kc, keysym;
1630 if ((syms = keycodemap[keycode]) == NULL)
1633 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1634 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1635 if (keycodemap[kc] == NULL)
1637 switch (keycodemap[kc][keysym]) {
1647 lockmod_is_capslock = kc;
1651 lockmod_is_shiftlock = kc;
1658 * If we have not seen the modifiermap we don't know what the
1659 * keycode translates to, but we do know it's one of the keys
1660 * in syms (give or take a case-conversion), so we could in
1661 * theory list them all.
1663 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1666 /* find out what the numlockmodifer and groupmodifier is. */
1667 for (modifier = 0, numlockmod = groupmod = -1;
1668 modifier < (int)array_length(modifiers) && numlockmod == -1;
1670 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1671 if (modifiermap[modifier][kc] == numlockkc)
1672 numlockmod = modifier;
1673 else if (modifiermap[modifier][kc] == groupmodkc)
1674 groupmod = modifier;
1677 * ... and what the lockmodifier is interpreted as.
1678 * (X11v4r6 ref, keyboard and pointers section.)
1680 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1681 if (modifiermap[1][kc] == lockmod_is_capslock) {
1682 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1685 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1686 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1692 * This is (how I understand) the X11v4R6 protocol description given
1693 * in A. Nye's book. It is quite different from the
1694 * code in _XTranslateKey() in the file
1695 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1696 * as shipped with XFree, and doesn't work correctly, nor do I see
1697 * how it could (e.g. the case of lower/uppercase-letters).
1698 * -- Michael Shuldman
1701 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1702 && ((syms[1] >= 0xff80
1703 && syms[1] <= 0xffbd)
1704 || (syms[1] >= 0x11000000
1705 && syms[1] <= 0x1100ffff))) {
1706 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1707 return keysymString(syms[groupmod + 0]);
1709 if (syms[groupmod + 1] == NoSymbol)
1710 return keysymString(syms[groupmod + 0]);
1712 return keysymString(syms[groupmod + 1]);
1714 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1715 return keysymString(syms[groupmod + 0]);
1716 else if (!(bitmask & ShiftMask)
1717 && ((bitmask & LockMask) && lockmod_is_capslock))
1718 if (islower(syms[groupmod + 0]))
1719 /* return toupper(keysymString(syms[groupmod + 0])); */
1720 return "Uppercase"; /* XXX */
1722 return keysymString(syms[groupmod + 0]);
1724 else if ((bitmask & ShiftMask)
1725 && ((bitmask & LockMask) && lockmod_is_capslock))
1726 if (islower(syms[groupmod + 1]))
1727 /* return toupper(keysymString(syms[groupmod + 1])); */
1728 return "Uppercase"; /* XXX */
1730 return keysymString(syms[groupmod + 1]);
1732 else if ((bitmask & ShiftMask)
1733 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1734 return keysymString(syms[groupmod + 1]);
1735 #else /* _XTranslateKey() based code. */
1737 while (keysyms_per_keycode > 2
1738 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1739 --keysyms_per_keycode;
1740 if (keysyms_per_keycode > 2
1741 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1743 keysyms_per_keycode -= 2;
1746 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1747 && keysyms_per_keycode > 1
1748 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1749 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1750 if ((bitmask & ShiftMask)
1751 || (bitmask & LockMask && lockmod_is_shiftlock))
1756 else if (!(bitmask & ShiftMask)
1757 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1758 if (keysyms_per_keycode == 1
1759 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1762 XConvertCase(syms[0], &keysym, &usym);
1767 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1770 if (keysyms_per_keycode == 1
1771 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1772 XConvertCase(syms[0], &lsym, &usym);
1778 if (keysyms_per_keycode == 1
1779 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1782 XConvertCase(keysym, &lsym, &usym);
1784 if (!(bitmask & ShiftMask) && keysym != syms[0]
1785 && ((keysym != usym) || (lsym == usym)))
1786 XConvertCase(syms[0], &lsym, &usym);
1790 if (keysym == XK_VoidSymbol)
1794 g_snprintf(buf, 32, "%d, \"%s\"", keysym, keysymString(keysym));
1799 static const char *keysymString(guint32 v)
1804 /* This table is so big that we built it only if necessary */
1806 const value_string *p = keysym_vals_source;
1807 keysymTable = g_tree_new(compareGuint32);
1808 for(; p -> strptr; p++)
1809 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), (gpointer) (p -> strptr) );
1811 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1812 return res ? res : "<Unknown>";
1815 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1816 int *modifiermap[], int keycodes_per_modifier,
1817 gboolean little_endian)
1819 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1820 array_length(modifiers) * keycodes_per_modifier, little_endian);
1821 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1824 for (m = 0; m < array_length(modifiers);
1825 ++m, *offsetp += keycodes_per_modifier) {
1830 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1832 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1834 tikc = proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1835 *offsetp, keycodes_per_modifier, p, "item: ");
1836 for(i = 0; i < keycodes_per_modifier; ++i) {
1840 proto_item_append_text(tikc, " %s=%d", modifiers[m], c);
1842 modifiermap[m][i] = c;
1847 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1848 int hf_item, int *keycodemap[256],
1849 int keycode_first, int keycode_count,
1850 int keysyms_per_keycode, gboolean little_endian)
1852 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1853 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1858 DISSECTOR_ASSERT(keycode_first >= 0);
1859 DISSECTOR_ASSERT(keycode_count >= 0);
1861 for (keycode = keycode_first; keycode_count > 0;
1862 ++keycode, --keycode_count) {
1863 if (keycode >= 256) {
1864 proto_tree_add_text(tt, tvb, *offsetp, 4 * keysyms_per_keycode,
1865 "keycode value %d is out of range", keycode);
1866 *offsetp += 4 * keysyms_per_keycode;
1869 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1870 4 * keysyms_per_keycode, "keysyms (keycode %d):", keycode);
1872 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1874 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1876 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1878 for(i = 0; i < keysyms_per_keycode; ++i) {
1879 /* keysymvalue = byte3 * 256 + byte4. */
1880 guint32 v = VALUE32(tvb, *offsetp);
1882 proto_item_append_text(tti, " %s", keysymString(v));
1883 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1884 tvb, *offsetp, 4, v,
1885 "keysym (keycode %d): 0x%08x (%s)",
1886 keycode, v, keysymString(v));
1888 keycodemap[keycode][i] = v;
1892 for (i = 1; i < keysyms_per_keycode; ++i)
1893 if (keycodemap[keycode][i] != NoSymbol)
1896 if (i == keysyms_per_keycode) {
1897 /* all but (possibly) first were NoSymbol. */
1898 if (keysyms_per_keycode == 4) {
1899 keycodemap[keycode][1] = NoSymbol;
1900 keycodemap[keycode][2] = keycodemap[keycode][0];
1901 keycodemap[keycode][3] = NoSymbol;
1907 for (i = 2; i < keysyms_per_keycode; ++i)
1908 if (keycodemap[keycode][i] != NoSymbol)
1910 if (i == keysyms_per_keycode) {
1911 /* all but (possibly) first two were NoSymbol. */
1912 if (keysyms_per_keycode == 4) {
1913 keycodemap[keycode][2] = keycodemap[keycode][0];
1914 keycodemap[keycode][3] = keycodemap[keycode][1];
1922 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1923 int length, gboolean little_endian)
1925 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1926 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1932 x = VALUE16(tvb, *offsetp);
1933 y = VALUE16(tvb, *offsetp + 2);
1935 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1936 ttt = proto_item_add_subtree(tti, ett_x11_point);
1937 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1939 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1944 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1945 int length, gboolean little_endian)
1947 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1948 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1951 unsigned width, height;
1955 x = VALUE16(tvb, *offsetp);
1956 y = VALUE16(tvb, *offsetp + 2);
1957 width = VALUE16(tvb, *offsetp + 4);
1958 height = VALUE16(tvb, *offsetp + 6);
1960 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1961 "rectangle: %dx%d+%d+%d", width, height, x, y);
1962 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1963 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1965 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1967 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1969 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1974 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1975 int length, gboolean little_endian)
1977 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1978 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1980 gint16 x1, y1, x2, y2;
1984 x1 = VALUE16(tvb, *offsetp);
1985 y1 = VALUE16(tvb, *offsetp + 2);
1986 x2 = VALUE16(tvb, *offsetp + 4);
1987 y2 = VALUE16(tvb, *offsetp + 6);
1989 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1990 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1991 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1992 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1994 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1996 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1998 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
2003 /* XXX - the protocol tree code should handle non-printable characters.
2004 Note that "non-printable characters" may depend on your locale.... */
2005 static void stringCopy(char *dest, const char *source, int length)
2010 if (!isgraph(c) && c != ' ') c = '.';
2016 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2017 int hf_item, int length, gboolean little_endian)
2020 guint allocated = 0;
2025 /* Compute total length */
2027 int scanning_offset = *offsetp; /* Scanning pointer */
2029 for(i = length; i; i--) {
2030 l = tvb_get_guint8(tvb, scanning_offset);
2031 scanning_offset += 1 + l;
2034 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2035 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2038 unsigned l = VALUE8(tvb, *offsetp);
2039 if (allocated < (l + 1)) {
2040 s = ep_alloc(l + 1);
2043 stringCopy(s, (gchar *)tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2044 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2049 #define STRING16_MAX_DISPLAYED_LENGTH 150
2051 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2053 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2054 for(; length > 0; offset += 2, length--) {
2055 if (tvb_get_guint8(tvb, offset))
2061 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2063 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2064 int hf, int hf_bytes,
2065 int offset, unsigned length,
2066 char **s, int *sLength,
2067 gboolean little_endian)
2069 int truncated = FALSE;
2070 unsigned l = length / 2;
2072 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2074 int soffset = offset;
2076 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2078 l = STRING16_MAX_DISPLAYED_LENGTH;
2080 if (*sLength < (int) l + 3) {
2081 *s = ep_alloc(l + 3);
2086 if (truncated) l -= 3;
2090 *dp++ = tvb_get_guint8(tvb, soffset);
2095 /* If truncated, add an ellipsis */
2096 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2099 proto_tree_add_string_format(t, hf, tvb, offset, length, (gchar *)tvb_get_ptr(tvb, offset, length), "%s: %s",
2100 proto_registrar_get_nth(hf) -> name, *s);
2102 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2106 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2107 int sizeIs16, int next_offset, gboolean little_endian)
2115 /* Compute total length */
2117 int scanning_offset = *offsetp; /* Scanning pointer */
2118 int l; /* Length of an individual item */
2119 int n = 0; /* Number of items */
2121 while(scanning_offset < next_offset) {
2122 l = tvb_get_guint8(tvb, scanning_offset);
2126 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2129 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2130 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2133 unsigned l = VALUE8(tvb, *offsetp);
2134 if (l == 255) { /* Item is a font */
2135 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2136 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2138 } else { /* Item is a string */
2141 gint8 delta = VALUE8(tvb, *offsetp + 1);
2142 if (sizeIs16) l += l;
2143 if ((unsigned) allocated < l + 1) {
2144 s = ep_alloc(l + 1);
2147 stringCopy(s, (gchar *)tvb_get_ptr(tvb, *offsetp + 2, l), l);
2148 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2149 "textitem (string): delta = %d, \"%s\"",
2151 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2152 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2154 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2155 hf_x11_textitem_string_string16_bytes,
2160 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2161 *offsetp + 2, l, s, "\"%s\"", s);
2167 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2168 gboolean little_endian)
2170 guint32 v = VALUE8(tvb, *offsetp);
2171 header_field_info *hfi = proto_registrar_get_nth(hf);
2172 const gchar *enumValue = NULL;
2175 enumValue = match_strval(v, cVALS(hfi -> strings));
2177 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2178 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2179 hfi -> name, v, enumValue);
2181 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2186 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2187 gboolean little_endian)
2189 guint32 v = VALUE16(tvb, *offsetp);
2190 header_field_info *hfi = proto_registrar_get_nth(hf);
2191 const gchar *enumValue = NULL;
2194 enumValue = match_strval(v, cVALS(hfi -> strings));
2196 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2197 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2198 hfi -> name, v, enumValue);
2200 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2205 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2206 gboolean little_endian)
2208 guint32 v = VALUE32(tvb, *offsetp);
2209 header_field_info *hfi = proto_registrar_get_nth(hf);
2210 const gchar *enumValue = NULL;
2211 const gchar *nameAsChar = hfi -> name;
2214 enumValue = match_strval(v, cVALS(hfi -> strings));
2216 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2217 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2218 nameAsChar, v, enumValue);
2220 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2221 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2227 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2228 gboolean little_endian)
2230 BITMASK32(gc_value);
2231 BITFIELD(ENUM8, gc_value_mask, function);
2232 BITFIELD(CARD32, gc_value_mask, plane_mask);
2233 BITFIELD(CARD32, gc_value_mask, foreground);
2234 BITFIELD(CARD32, gc_value_mask, background);
2235 BITFIELD(CARD16, gc_value_mask, line_width);
2236 BITFIELD(ENUM8, gc_value_mask, line_style);
2237 BITFIELD(ENUM8, gc_value_mask, cap_style);
2238 BITFIELD(ENUM8, gc_value_mask, join_style);
2239 BITFIELD(ENUM8, gc_value_mask, fill_style);
2240 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2241 BITFIELD(PIXMAP, gc_value_mask, tile);
2242 BITFIELD(PIXMAP, gc_value_mask, stipple);
2243 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2244 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2245 BITFIELD(FONT, gc_value_mask, font);
2246 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2247 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2248 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2249 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2250 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2251 BITFIELD(CARD16, gc_value_mask, dash_offset);
2252 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2253 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2257 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2258 gboolean little_endian)
2260 BITMASK32(gc_value);
2261 FLAG(gc_value, function);
2262 FLAG(gc_value, plane_mask);
2263 FLAG(gc_value, foreground);
2264 FLAG(gc_value, background);
2265 FLAG(gc_value, line_width);
2266 FLAG(gc_value, line_style);
2267 FLAG(gc_value, cap_style);
2268 FLAG(gc_value, join_style);
2269 FLAG(gc_value, fill_style);
2270 FLAG(gc_value, fill_rule);
2271 FLAG(gc_value, tile);
2272 FLAG(gc_value, stipple);
2273 FLAG(gc_value, tile_stipple_x_origin);
2274 FLAG(gc_value, tile_stipple_y_origin);
2275 FLAG(gc_value, font);
2276 FLAG(gc_value, subwindow_mode);
2277 FLAG(gc_value, graphics_exposures);
2278 FLAG(gc_value, clip_x_origin);
2279 FLAG(gc_value, clip_y_origin);
2280 FLAG(gc_value, clip_mask);
2281 FLAG(gc_value, dash_offset);
2282 FLAG(gc_value, gc_dashes);
2283 FLAG(gc_value, arc_mode);
2287 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2288 gboolean little_endian)
2290 guint32 res = VALUE16(tvb, *offsetp);
2291 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2296 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2297 gboolean little_endian)
2300 FLAG(event, KeyPress);
2301 FLAG(event, KeyRelease);
2302 FLAG(event, ButtonPress);
2303 FLAG(event, ButtonRelease);
2304 FLAG(event, EnterWindow);
2305 FLAG(event, LeaveWindow);
2306 FLAG(event, PointerMotion);
2307 FLAG(event, PointerMotionHint);
2308 FLAG(event, Button1Motion);
2309 FLAG(event, Button2Motion);
2310 FLAG(event, Button3Motion);
2311 FLAG(event, Button4Motion);
2312 FLAG(event, Button5Motion);
2313 FLAG(event, ButtonMotion);
2314 FLAG(event, KeymapState);
2315 FLAG(event, Exposure);
2316 FLAG(event, VisibilityChange);
2317 FLAG(event, StructureNotify);
2318 FLAG(event, ResizeRedirect);
2319 FLAG(event, SubstructureNotify);
2320 FLAG(event, SubstructureRedirect);
2321 FLAG(event, FocusChange);
2322 FLAG(event, PropertyChange);
2323 FLAG(event, ColormapChange);
2324 FLAG(event, OwnerGrabButton);
2325 FLAG_IF_NONZERO(event, erroneous_bits);
2329 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2330 gboolean little_endian)
2332 BITMASK32(do_not_propagate);
2333 FLAG(do_not_propagate, KeyPress);
2334 FLAG(do_not_propagate, KeyRelease);
2335 FLAG(do_not_propagate, ButtonPress);
2336 FLAG(do_not_propagate, ButtonRelease);
2337 FLAG(do_not_propagate, PointerMotion);
2338 FLAG(do_not_propagate, Button1Motion);
2339 FLAG(do_not_propagate, Button2Motion);
2340 FLAG(do_not_propagate, Button3Motion);
2341 FLAG(do_not_propagate, Button4Motion);
2342 FLAG(do_not_propagate, Button5Motion);
2343 FLAG(do_not_propagate, ButtonMotion);
2344 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2349 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2350 gboolean little_endian, gboolean butmask)
2353 guint32 bitmask_value;
2356 proto_tree *bitmask_tree;
2358 bitmask_value = VALUE16(tvb, *offsetp);
2359 bitmask_offset = *offsetp;
2362 if (!butmask && bitmask_value == 0x8000)
2363 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2364 "modifiers-masks: 0x8000 (AnyModifier)");
2366 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2368 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2369 FLAG(modifiers, Shift);
2370 FLAG(modifiers, Lock);
2371 FLAG(modifiers, Control);
2372 FLAG(modifiers, Mod1);
2373 FLAG(modifiers, Mod2);
2374 FLAG(modifiers, Mod3);
2375 FLAG(modifiers, Mod4);
2376 FLAG(modifiers, Mod5);
2379 FLAG(modifiers, Button1);
2380 FLAG(modifiers, Button2);
2381 FLAG(modifiers, Button3);
2382 FLAG(modifiers, Button4);
2383 FLAG(modifiers, Button5);
2387 FLAG_IF_NONZERO(keybut, erroneous_bits);
2389 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2394 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2395 gboolean little_endian)
2397 BITMASK16(pointer_event);
2398 FLAG(pointer_event, ButtonPress);
2399 FLAG(pointer_event, ButtonRelease);
2400 FLAG(pointer_event, EnterWindow);
2401 FLAG(pointer_event, LeaveWindow);
2402 FLAG(pointer_event, PointerMotion);
2403 FLAG(pointer_event, PointerMotionHint);
2404 FLAG(pointer_event, Button1Motion);
2405 FLAG(pointer_event, Button2Motion);
2406 FLAG(pointer_event, Button3Motion);
2407 FLAG(pointer_event, Button4Motion);
2408 FLAG(pointer_event, Button5Motion);
2409 FLAG(pointer_event, ButtonMotion);
2410 FLAG(pointer_event, KeymapState);
2411 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2415 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2416 int hf, unsigned length)
2421 p = tvb_get_ptr(tvb, *offsetp, length);
2422 s = ep_alloc(length + 1);
2423 stringCopy(s, (gchar *)p, length);
2424 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2428 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2430 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2431 int hf_bytes, unsigned length, gboolean little_endian)
2437 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2438 &s, &l, little_endian);
2443 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2444 gboolean little_endian)
2446 guint32 v = VALUE32(tvb, *offsetp);
2449 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2450 proto_registrar_get_nth(hf) -> name);
2452 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2456 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2457 gboolean little_endian)
2459 BITMASK32(window_value);
2460 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2461 BITFIELD(CARD32, window_value_mask, background_pixel);
2462 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2463 BITFIELD(CARD32, window_value_mask, border_pixel);
2464 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2465 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2466 BITFIELD(ENUM8, window_value_mask, backing_store);
2467 BITFIELD(CARD32, window_value_mask, backing_planes);
2468 BITFIELD(CARD32, window_value_mask, backing_pixel);
2469 BITFIELD(BOOL, window_value_mask, override_redirect);
2470 BITFIELD(BOOL, window_value_mask, save_under);
2471 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2472 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2473 BITFIELD(COLORMAP, window_value_mask, colormap);
2474 BITFIELD(CURSOR, window_value_mask, cursor);
2478 static void x11_init_protocol(void)
2480 x11_conv_data_t *state;
2482 for (state = x11_conv_data_list; state != NULL; ) {
2483 x11_conv_data_t *last;
2485 g_hash_table_destroy(state->seqtable);
2486 g_hash_table_destroy(state->valtable);
2489 state = state->next;
2492 x11_conv_data_list = NULL;
2495 /************************************************************************
2497 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2499 ************************************************************************/
2501 /* If we can't guess, we return TRUE (that is little_endian), cause
2502 I'm developing on a Linux box :-). The (non-)guess isn't cached
2503 however, so we may have more luck next time. I'm quite conservative
2504 in my assertions, cause once it's cached, it's stay in cache, and
2505 we may be fooled up by a packet starting with the end of a request
2506 started in a previous packet...
2509 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2511 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2514 while(maskLength--) {
2515 int c = tvb_get_guint8(tvb, offset);
2517 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2522 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2524 if (listLength > length) return FALSE;
2525 while(listLength--) {
2527 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2528 l = tvb_get_guint8(tvb, offset);
2531 if (l > length) return FALSE;
2532 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2536 if (length > 3) return FALSE;
2540 static int rounded4(int n)
2542 int remainder = n % 4;
2544 if (remainder) res++;
2548 /* We assume the order to be consistent, until proven wrong. */
2550 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2552 switch(tvb_get_guint8(tvb, offset)) {
2553 case X_CreateWindow:
2554 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2556 case X_ChangeWindowAttributes:
2558 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2560 case X_GetWindowAttributes:
2561 case X_DestroyWindow:
2562 case X_DestroySubwindows:
2563 case X_ChangeSaveSet:
2565 case X_MapSubwindows:
2567 case X_UnmapSubwindows:
2568 case X_CirculateWindow:
2572 case X_ListProperties:
2573 case X_GetSelectionOwner:
2574 case X_UngrabPointer:
2575 case X_UngrabKeyboard:
2577 case X_QueryPointer:
2582 case X_FreeColormap:
2583 case X_InstallColormap:
2584 case X_UninstallColormap:
2585 case X_ListInstalledColormaps:
2587 case X_GetKeyboardMapping:
2591 case X_ReparentWindow:
2592 case X_SetSelectionOwner:
2593 case X_ChangeActivePointerGrab:
2594 case X_GrabKeyboard:
2596 case X_GetMotionEvents:
2597 case X_TranslateCoords:
2598 case X_CreatePixmap:
2601 case X_CreateColormap:
2603 case X_AllocColorPlanes:
2606 case X_ConfigureWindow:
2607 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2610 case X_QueryExtension:
2611 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2613 case X_ChangeProperty:
2615 int multiplier, type;
2616 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2617 type = tvb_get_guint8(tvb, 16);
2618 if (type != 8 && type != 16 && type != 32) return FALSE;
2619 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2620 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2621 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2624 case X_DeleteProperty:
2625 case X_UngrabButton:
2627 case X_SetInputFocus:
2628 case X_CopyColormapAndFree:
2629 case X_AllocColorCells:
2630 case X_QueryBestSize:
2631 case X_ChangePointerControl:
2632 case X_SetScreenSaver:
2636 case X_ConvertSelection:
2643 return length == 11;
2646 case X_UngrabServer:
2647 case X_GetInputFocus:
2650 case X_ListExtensions:
2651 case X_GetKeyboardControl:
2653 case X_GetPointerControl:
2654 case X_GetScreenSaver:
2656 case X_SetAccessControl:
2657 case X_SetCloseDownMode:
2658 case X_ForceScreenSaver:
2659 case X_GetPointerMapping:
2660 case X_GetModifierMapping:
2664 case X_AllocNamedColor:
2666 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2668 case X_QueryTextExtents:
2672 case X_ListFontsWithInfo:
2674 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2677 if (length < 2) return FALSE;
2678 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2679 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2682 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2685 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2687 case X_SetClipRectangles:
2689 case X_PolyRectangle:
2690 case X_PolyFillRectangle:
2691 return length >= 3 && (length - 3) % 2 == 0;
2697 case X_CreateCursor:
2698 case X_CreateGlyphCursor:
2708 return length >= 3 && (length - 3) % 3 == 0;
2718 case X_RecolorCursor:
2722 if (length < 4) return FALSE;
2723 return TRUE; /* We don't perform many controls on this one */
2726 if (length < 4) return FALSE;
2727 return TRUE; /* We don't perform many controls on this one */
2733 return length > 2 && (length - 2) % 3 == 0;
2735 case X_StoreNamedColor:
2736 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2741 case X_ChangeKeyboardMapping:
2742 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2744 case X_ChangeKeyboardControl:
2745 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2747 case X_RotateProperties:
2748 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2750 case X_SetPointerMapping:
2751 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2753 case X_SetModifierMapping:
2754 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2764 /* -1 means doesn't match, +1 means match, 0 means don't know */
2766 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2768 int offset, nextoffset;
2771 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2773 length = v16(tvb, offset + 2);
2774 if (!length) return -1;
2775 nextoffset = offset + length * 4;
2776 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2783 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2784 x11_conv_data_t *state)
2786 /* With X the client gives the byte ordering for the protocol,
2787 and the port on the server tells us we're speaking X. */
2789 int le, be, decision, decisionToCache;
2791 if (state->byte_order == BYTE_ORDER_BE)
2792 return FALSE; /* known to be big-endian */
2793 else if (state->byte_order == BYTE_ORDER_LE)
2794 return TRUE; /* known to be little-endian */
2796 if (pinfo->srcport == pinfo->match_port) {
2798 * This is a reply or event; we don't try to guess the
2799 * byte order on it for now.
2804 le = x_endian_match(tvb, tvb_get_letohs);
2805 be = x_endian_match(tvb, tvb_get_ntohs);
2807 /* remember that "decision" really means "little_endian". */
2809 /* We have no reason to believe it's little- rather than
2810 big-endian, so we guess the shortest length is the
2813 if (!tvb_bytes_exist(tvb, 0, 4))
2814 /* Not even a way to get the length. We're biased
2815 toward little endianness here (essentially the
2816 x86 world right now). Decoding won't go very far
2821 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2823 decision = le >= be;
2825 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2826 if (decisionToCache) {
2828 * Remember the decision.
2830 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2834 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2835 pinfo->fd -> num, le, be, decision, decisionToCache);
2840 /************************************************************************
2842 *** D E C O D I N G O N E P A C K E T ***
2844 ************************************************************************/
2847 * Decode an initial connection request.
2849 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2850 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2853 int *offsetp = &offset;
2856 guint16 auth_proto_name_length, auth_proto_data_length;
2859 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2860 proto_item_append_text(ti, ", Request, Initial connection request");
2861 t = proto_item_add_subtree(ti, ett_x11);
2865 CARD16(protocol_major_version);
2866 CARD16(protocol_minor_version);
2867 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2868 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2871 if (auth_proto_name_length != 0) {
2872 STRING8(authorization_protocol_name, auth_proto_name_length);
2873 offset = ROUND_LENGTH(offset);
2876 if (auth_proto_data_length != 0) {
2877 STRING8(authorization_protocol_data, auth_proto_data_length);
2878 offset = ROUND_LENGTH(offset);
2881 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2882 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2886 * This is the initial connection request...
2888 state->iconn_frame = pinfo->fd->num;
2891 * ...and we're expecting a reply to it.
2893 state->sequencenumber = 0;
2894 g_hash_table_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
2895 (int *)INITIAL_CONN);
2898 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2899 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2900 gboolean little_endian)
2902 int offset = 0, *offsetp = &offset, left;
2903 unsigned char success;
2904 int length_of_vendor;
2905 int length_of_reason;
2909 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2910 proto_item_append_text(ti, ", Reply, Initial connection reply");
2911 t = proto_item_add_subtree(ti, ett_x11);
2913 state->iconn_reply = pinfo->fd->num;
2914 success = INT8(success);
2917 length_of_reason = 0;
2920 length_of_reason = INT8(length_of_reason);
2923 INT16(protocol_major_version);
2924 INT16(protocol_minor_version);
2927 INT32(release_number);
2928 INT32(resource_id_base);
2929 INT32(resource_id_mask);
2930 INT32(motion_buffer_size);
2931 length_of_vendor = INT16(length_of_vendor);
2932 INT16(maximum_request_length);
2933 INT8(number_of_screens_in_roots);
2934 INT8(number_of_formats_in_pixmap_formats);
2935 INT8(image_byte_order);
2936 INT8(bitmap_format_bit_order);
2937 INT8(bitmap_format_scanline_unit);
2938 INT8(bitmap_format_scanline_pad);
2942 STRING8(vendor, length_of_vendor);
2944 STRING8(reason, length_of_reason);
2947 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2952 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2953 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2954 gboolean little_endian)
2957 int *offsetp = &offset;
2961 int length, opcode, i;
2962 guint8 v8, v8_2, v8_3;
2968 length = VALUE16(tvb, 2) * 4;
2971 /* Bogus message length? */
2975 next_offset = offset + length;
2977 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2978 t = proto_item_add_subtree(ti, ett_x11);
2980 if (PACKET_IS_NEW(pinfo))
2981 ++state->sequencenumber;
2985 if (check_col(pinfo->cinfo, COL_INFO))
2986 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2987 val_to_str(opcode, state->opcode_vals,
2988 "<Unknown opcode %d>"));
2990 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2991 opcode, val_to_str(opcode, state->opcode_vals,
2992 "<Unknown opcode %d>"));
2995 * Does this request expect a reply?
2999 case X_QueryExtension:
3001 /* necessary processing even if tree == NULL */
3003 v16 = VALUE16(tvb, 4);
3004 name = se_alloc(v16 + 1);
3005 stringCopy(name, (gchar*)tvb_get_ptr(tvb, 8, v16), v16);
3007 /* store string of extension, opcode will be set at reply */
3009 while(i < MAX_OPCODES) {
3010 if (state->opcode_vals[i].strptr == NULL) {
3011 state->opcode_vals[i].strptr = name;
3012 g_hash_table_insert(state->valtable,
3013 GINT_TO_POINTER(state->sequencenumber),
3014 (int *)&state->opcode_vals[i]);
3016 } else if (strcmp(state->opcode_vals[i].strptr,
3018 g_hash_table_insert(state->valtable,
3019 GINT_TO_POINTER(state->sequencenumber),
3020 (int *)&state->opcode_vals[i]);
3026 /* QueryExtension expects a reply, fall through */
3029 case X_AllocColorCells:
3030 case X_AllocColorPlanes:
3031 case X_AllocNamedColor:
3036 case X_GetInputFocus:
3037 case X_GetKeyboardControl:
3038 case X_GetKeyboardMapping:
3039 case X_GetModifierMapping:
3040 case X_GetMotionEvents:
3041 case X_GetPointerControl:
3042 case X_GetPointerMapping:
3044 case X_GetScreenSaver:
3045 case X_GetSelectionOwner:
3046 case X_GetWindowAttributes:
3047 case X_GrabKeyboard:
3050 case X_ListExtensions:
3052 case X_ListFontsWithInfo:
3054 case X_ListInstalledColormaps:
3055 case X_ListProperties:
3057 case X_QueryBestSize:
3061 case X_QueryPointer:
3062 case X_QueryTextExtents:
3064 case X_SetModifierMapping:
3065 case X_SetPointerMapping:
3066 case X_TranslateCoords:
3068 * Those requests expect a reply.
3070 g_hash_table_insert(state->seqtable,
3071 GINT_TO_POINTER(state->sequencenumber),
3072 GINT_TO_POINTER(opcode));
3078 * With Extension, we don't know, so assume there could be one
3080 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3081 g_hash_table_insert(state->seqtable,
3082 GINT_TO_POINTER(state->sequencenumber),
3083 GINT_TO_POINTER(opcode));
3087 * No reply is expected from any other request.
3097 case X_CreateWindow:
3106 CARD16(border_width);
3107 ENUM16(window_class);
3109 windowAttributes(tvb, offsetp, t, little_endian);
3112 case X_ChangeWindowAttributes:
3116 windowAttributes(tvb, offsetp, t, little_endian);
3119 case X_GetWindowAttributes:
3120 case X_DestroyWindow:
3121 case X_DestroySubwindows:
3127 case X_ChangeSaveSet:
3128 ENUM8(save_set_mode);
3133 case X_ReparentWindow:
3143 case X_MapSubwindows:
3145 case X_UnmapSubwindows:
3151 case X_ConfigureWindow:
3155 BITMASK16(configure_window);
3157 BITFIELD(INT16, configure_window_mask, x);
3158 BITFIELD(INT16, configure_window_mask, y);
3159 BITFIELD(CARD16, configure_window_mask, width);
3160 BITFIELD(CARD16, configure_window_mask, height);
3161 BITFIELD(CARD16, configure_window_mask, border_width);
3162 BITFIELD(WINDOW, configure_window_mask, sibling);
3163 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3168 case X_CirculateWindow:
3182 BOOL(only_if_exists);
3184 v16 = FIELD16(name_length);
3196 case X_ChangeProperty:
3204 v32 = CARD32(data_length);
3205 LISTofBYTE(data, v32);
3209 case X_DeleteProperty:
3221 ATOM(get_property_type);
3222 CARD32(long_offset);
3223 CARD32(long_length);
3226 case X_ListProperties:
3232 case X_SetSelectionOwner:
3240 case X_GetSelectionOwner:
3246 case X_ConvertSelection:
3259 WINDOW(destination);
3260 SETofEVENT(event_mask);
3267 WINDOW(grab_window);
3268 SETofPOINTEREVENT(pointer_event_mask);
3269 ENUM8(pointer_mode);
3270 ENUM8(keyboard_mode);
3276 case X_UngrabPointer:
3285 WINDOW(grab_window);
3286 SETofPOINTEREVENT(event_mask);
3287 ENUM8(pointer_mode);
3288 ENUM8(keyboard_mode);
3293 SETofKEYMASK(modifiers);
3296 case X_UngrabButton:
3299 WINDOW(grab_window);
3300 SETofKEYMASK(modifiers);
3304 case X_ChangeActivePointerGrab:
3309 SETofPOINTEREVENT(event_mask);
3313 case X_GrabKeyboard:
3316 WINDOW(grab_window);
3318 ENUM8(pointer_mode);
3319 ENUM8(keyboard_mode);
3323 case X_UngrabKeyboard:
3332 WINDOW(grab_window);
3333 SETofKEYMASK(modifiers);
3335 ENUM8(pointer_mode);
3336 ENUM8(keyboard_mode);
3343 WINDOW(grab_window);
3344 SETofKEYMASK(modifiers);
3349 ENUM8(allow_events_mode);
3359 case X_UngrabServer:
3364 case X_QueryPointer:
3370 case X_GetMotionEvents:
3378 case X_TranslateCoords:
3390 WINDOW(warp_pointer_src_window);
3391 WINDOW(warp_pointer_dst_window);
3400 case X_SetInputFocus:
3407 case X_GetInputFocus:
3421 v16 = FIELD16(name_length);
3439 case X_QueryTextExtents:
3440 v8 = BOOL(odd_length);
3443 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3451 v16 = FIELD16(pattern_length);
3452 STRING8(pattern, v16);
3456 case X_ListFontsWithInfo:
3460 v16 = FIELD16(pattern_length);
3461 STRING8(pattern, v16);
3468 v16 = CARD16(str_number_in_path);
3470 LISTofSTRING8(path, v16);
3479 case X_CreatePixmap:
3499 gcAttributes(tvb, offsetp, t, little_endian);
3506 gcAttributes(tvb, offsetp, t, little_endian);
3514 gcMask(tvb, offsetp, t, little_endian);
3521 CARD16(dash_offset);
3522 v16 = FIELD16(dashes_length);
3523 LISTofCARD8(dashes, v16);
3527 case X_SetClipRectangles:
3531 INT16(clip_x_origin);
3532 INT16(clip_y_origin);
3533 LISTofRECTANGLE(rectangles);
3555 DRAWABLE(src_drawable);
3556 DRAWABLE(dst_drawable);
3569 DRAWABLE(src_drawable);
3570 DRAWABLE(dst_drawable);
3582 ENUM8(coordinate_mode);
3583 v16 = REQUEST_LENGTH();
3586 LISTofPOINT(points, v16 - 12);
3590 ENUM8(coordinate_mode);
3591 v16 = REQUEST_LENGTH();
3594 LISTofPOINT(points, v16 - 12);
3602 LISTofSEGMENT(segments);
3605 case X_PolyRectangle:
3610 LISTofRECTANGLE(rectangles);
3623 v16 = REQUEST_LENGTH();
3627 ENUM8(coordinate_mode);
3629 LISTofPOINT(points, v16 - 16);
3632 case X_PolyFillRectangle:
3637 LISTofRECTANGLE(rectangles);
3649 ENUM8(image_format);
3650 v16 = REQUEST_LENGTH();
3660 LISTofBYTE(data, v16 - 24);
3665 ENUM8(image_pixmap_format);
3677 v16 = REQUEST_LENGTH();
3682 LISTofTEXTITEM8(items);
3688 v16 = REQUEST_LENGTH();
3693 LISTofTEXTITEM16(items);
3698 v8 = FIELD8(string_length);
3704 STRING8(string, v8);
3709 v8 = FIELD8(string_length);
3715 STRING16(string16, v8);
3719 case X_CreateColormap:
3727 case X_FreeColormap:
3733 case X_CopyColormapAndFree:
3740 case X_InstallColormap:
3746 case X_UninstallColormap:
3752 case X_ListInstalledColormaps:
3768 case X_AllocNamedColor:
3772 v16 = FIELD16(name_length);
3778 case X_AllocColorCells:
3786 case X_AllocColorPlanes:
3798 v16 = REQUEST_LENGTH();
3801 LISTofCARD32(pixels, v16 - 12);
3806 v16 = REQUEST_LENGTH();
3808 LISTofCOLORITEM(color_items, v16 - 8);
3811 case X_StoreNamedColor:
3816 v16 = FIELD16(name_length);
3824 v16 = REQUEST_LENGTH();
3826 LISTofCARD32(pixels, v16 - 8);
3833 v16 = FIELD16(name_length);
3839 case X_CreateCursor:
3843 PIXMAP(source_pixmap);
3855 case X_CreateGlyphCursor:
3861 CARD16(source_char);
3877 case X_RecolorCursor:
3889 case X_QueryBestSize:
3897 case X_QueryExtension:
3900 v16 = FIELD16(name_length);
3906 case X_ListExtensions:
3911 case X_ChangeKeyboardMapping:
3912 v8 = FIELD8(keycode_count);
3914 v8_2 = KEYCODE(first_keycode);
3915 v8_3 = FIELD8(keysyms_per_keycode);
3917 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3920 case X_GetKeyboardMapping:
3923 state->request.GetKeyboardMapping.first_keycode
3924 = KEYCODE(first_keycode);
3929 case X_ChangeKeyboardControl:
3932 BITMASK32(keyboard_value);
3933 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3934 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3935 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3936 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3937 BITFIELD(INT16, keyboard_value_mask, led);
3938 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3939 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3940 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3944 case X_GetKeyboardControl:
3954 case X_ChangePointerControl:
3957 INT16(acceleration_numerator);
3958 INT16(acceleration_denominator);
3960 BOOL(do_acceleration);
3964 case X_GetPointerControl:
3969 case X_SetScreenSaver:
3974 ENUM8(prefer_blanking);
3975 ENUM8(allow_exposures);
3979 case X_GetScreenSaver:
3985 ENUM8(change_host_mode);
3989 v16 = CARD16(address_length);
3990 if (v8 == FAMILY_INTERNET && v16 == 4) {
3993 * XXX - what about IPv6? Is that a family of
3994 * FAMILY_INTERNET (0) with a length of 16?
3996 LISTofIPADDRESS(ip_address, v16);
3998 LISTofCARD8(address, v16);
4006 case X_SetAccessControl:
4011 case X_SetCloseDownMode:
4012 ENUM8(close_down_mode);
4022 case X_RotateProperties:
4024 v16 = REQUEST_LENGTH();
4026 CARD16(property_number);
4028 LISTofATOM(properties, (v16 - 12));
4031 case X_ForceScreenSaver:
4032 ENUM8(screen_saver_mode);
4036 case X_SetPointerMapping:
4037 v8 = FIELD8(map_length);
4039 LISTofCARD8(map, v8);
4043 case X_GetPointerMapping:
4048 case X_SetModifierMapping:
4049 v8 = FIELD8(keycodes_per_modifier);
4051 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4054 case X_GetModifierMapping:
4065 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4069 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4072 volatile int offset = 0;
4073 int length_remaining;
4074 volatile gboolean little_endian;
4079 volatile gboolean is_initial_creq;
4080 guint16 auth_proto_len, auth_data_len;
4081 const char *volatile sep = NULL;
4082 conversation_t *conversation;
4083 x11_conv_data_t *volatile state;
4085 tvbuff_t *volatile next_tvb;
4087 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4089 * We use "tvb_ensure_length_remaining()" to make sure there
4090 * actually *is* data remaining.
4092 * This means we're guaranteed that "length_remaining" is
4095 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4098 * Can we do reassembly?
4100 if (x11_desegment && pinfo->can_desegment) {
4102 * Yes - is the X11 request header split across
4103 * segment boundaries?
4105 if (length_remaining < 4) {
4107 * Yes. Tell the TCP dissector where the data
4108 * for this message starts in the data it handed
4109 * us, and how many more bytes we need, and return.
4111 pinfo->desegment_offset = offset;
4112 pinfo->desegment_len = 4 - length_remaining;
4118 * Get the state for this conversation; create the conversation
4119 * if we don't have one, and create the state if we don't have
4122 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4123 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4124 if (conversation == NULL) {
4128 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4129 &pinfo->dst, pinfo->ptype, pinfo->srcport,
4130 pinfo->destport, 0);
4134 * Is there state attached to this conversation?
4136 if ((state = conversation_get_proto_data(conversation, proto_x11))
4138 state = x11_stateinit(conversation);
4141 * Guess the byte order if we don't already know it.
4143 little_endian = guess_byte_ordering(tvb, pinfo, state);
4146 * Get the opcode and length of the putative X11 request.
4148 opcode = VALUE8(tvb, 0);
4149 plen = VALUE16(tvb, offset + 2);
4153 * This can't be 0, as it includes the header length.
4154 * A different choice of byte order wouldn't have
4158 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4160 t = proto_item_add_subtree(ti, ett_x11);
4161 proto_tree_add_text(t, tvb, offset, -1,
4162 "Bogus request length (0)");
4166 if (state->iconn_frame == pinfo->fd->num ||
4167 (g_hash_table_lookup(state->seqtable,
4168 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4169 (opcode == 'B' || opcode == 'l') &&
4170 (plen == 11 || plen == 2816))) {
4174 * we saw this on the first pass and this is
4178 * we haven't already seen any requests, the first
4179 * byte of the message is 'B' or 'l', and the 16-bit
4180 * integer 2 bytes into the data stream is either 11
4181 * or a byte-swapped 11.
4183 * This means it's probably an initial connection
4184 * request, not a message.
4186 * 'B' is decimal 66, which is the opcode for a
4187 * PolySegment request; unfortunately, 11 is a valid
4188 * length for a PolySegment request request, so we
4189 * might mis-identify that request. (Are there any
4190 * other checks we can do?)
4192 * 'l' is decimal 108, which is the opcode for a
4193 * GetScreenSaver request; the only valid length
4194 * for that request is 1.
4196 is_initial_creq = TRUE;
4199 * We now know the byte order. Override the guess.
4201 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4202 if (opcode == 'B') {
4206 state->byte_order = BYTE_ORDER_BE;
4207 little_endian = FALSE;
4212 state->byte_order = BYTE_ORDER_LE;
4213 little_endian = TRUE;
4218 * Can we do reassembly?
4220 if (x11_desegment && pinfo->can_desegment) {
4222 * Yes - is the fixed-length portion of the
4223 * initial connection header split across
4224 * segment boundaries?
4226 if (length_remaining < 10) {
4228 * Yes. Tell the TCP dissector where the
4229 * data for this message starts in the data
4230 * it handed us, and how many more bytes we
4233 pinfo->desegment_offset = offset;
4234 pinfo->desegment_len = 10 - length_remaining;
4240 * Get the lengths of the authorization protocol and
4241 * the authorization data.
4243 auth_proto_len = VALUE16(tvb, offset + 6);
4244 auth_data_len = VALUE16(tvb, offset + 8);
4245 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4246 ROUND_LENGTH(auth_data_len);
4249 * This is probably an ordinary request.
4251 is_initial_creq = FALSE;
4254 * The length of a request is in 4-byte words.
4260 * Can we do reassembly?
4262 if (x11_desegment && pinfo->can_desegment) {
4264 * Yes - is the X11 request split across segment
4267 if (length_remaining < plen) {
4269 * Yes. Tell the TCP dissector where the data
4270 * for this message starts in the data it handed
4271 * us, and how many more bytes we need, and return.
4273 pinfo->desegment_offset = offset;
4274 pinfo->desegment_len = plen - length_remaining;
4280 * Construct a tvbuff containing the amount of the payload
4281 * we have available. Make its reported length the
4282 * amount of data in the X11 request.
4284 * XXX - if reassembly isn't enabled. the subdissector
4285 * will throw a BoundsError exception, rather than a
4286 * ReportedBoundsError exception. We really want a tvbuff
4287 * where the length is "length", the reported length is "plen",
4288 * and the "if the snapshot length were infinite" length is the
4289 * minimum of the reported length of the tvbuff handed to us
4290 * and "plen", with a new type of exception thrown if the offset
4291 * is within the reported length but beyond that third length,
4292 * with that exception getting the "Unreassembled Packet" error.
4294 length = length_remaining;
4297 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4300 * Set the column appropriately.
4302 if (is_initial_creq) {
4303 col_set_str(pinfo->cinfo, COL_INFO, "Initial connection request");
4307 * We haven't set the column yet; set it.
4309 col_set_str(pinfo->cinfo, COL_INFO, "Requests");
4312 * Initialize the separator.
4319 * Dissect the X11 request.
4321 * Catch the ReportedBoundsError exception; if this
4322 * particular message happens to get a ReportedBoundsError
4323 * exception, that doesn't mean that we should stop
4324 * dissecting X11 requests within this frame or chunk of
4327 * If it gets a BoundsError, we can stop, as there's nothing
4328 * more to see, so we just re-throw it.
4331 if (is_initial_creq) {
4332 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4333 state, little_endian);
4335 dissect_x11_request(next_tvb, pinfo, tree, sep,
4336 state, little_endian);
4339 CATCH(BoundsError) {
4342 CATCH(ReportedBoundsError) {
4343 show_reported_bounds_error(tvb, pinfo, tree);
4348 * Skip the X11 message.
4356 static x11_conv_data_t *
4357 x11_stateinit(conversation_t *conversation)
4359 x11_conv_data_t *state;
4360 static x11_conv_data_t stateinit;
4363 state = g_malloc(sizeof (x11_conv_data_t));
4365 state->next = x11_conv_data_list;
4366 x11_conv_data_list = state;
4368 /* initialise opcodes */
4370 if (opcode_vals[i].strptr == NULL) break;
4371 state->opcode_vals[i].value = opcode_vals[i].value;
4372 state->opcode_vals[i].strptr = opcode_vals[i].strptr;
4375 while (i <= MAX_OPCODES) {
4376 state->opcode_vals[i].value = 0;
4377 state->opcode_vals[i].strptr = NULL;
4381 state->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4382 state->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4383 g_hash_table_insert(state->seqtable, (int *)0, (int *)NOTHING_SEEN);
4384 state->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4385 conversation_add_proto_data(conversation, proto_x11, state);
4391 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4393 /* Set up structures we will need to add the protocol subtree and manage it */
4394 volatile int offset, plen;
4395 tvbuff_t * volatile next_tvb;
4396 conversation_t *conversation;
4397 x11_conv_data_t *volatile state;
4398 gboolean little_endian;
4399 int length_remaining;
4400 const char *volatile sep = NULL;
4404 * Get the state for this conversation; create the conversation
4405 * if we don't have one, and create the state if we don't have
4408 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4409 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4410 if (conversation == NULL) {
4414 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4415 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4419 * Is there state attached to this conversation?
4421 if ((state = conversation_get_proto_data(conversation, proto_x11))
4424 * No - create a state structure and attach it.
4426 state = x11_stateinit(conversation);
4430 * Guess the byte order if we don't already know it.
4432 little_endian = guess_byte_ordering(tvb, pinfo, state);
4435 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4437 * We use "tvb_ensure_length_remaining()" to make sure there
4438 * actually *is* data remaining.
4440 * This means we're guaranteed that "length_remaining" is
4443 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4446 * Can we do reassembly?
4448 if (x11_desegment && pinfo->can_desegment) {
4450 * Yes - is the X11 reply header split across
4451 * segment boundaries?
4453 if (length_remaining < 8) {
4455 * Yes. Tell the TCP dissector where the data
4456 * for this message starts in the data it handed
4457 * us, and how many more bytes we need, and
4460 pinfo->desegment_offset = offset;
4461 pinfo->desegment_len = 8 - length_remaining;
4467 * Find out what kind of a reply it is.
4468 * There are four possible:
4469 * - reply to initial connection
4470 * - errorreply (a request generated an error)
4471 * - requestreply (reply to a request)
4472 * - event (some event occured)
4474 if (g_hash_table_lookup(state->seqtable,
4475 GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN
4476 || (state->iconn_reply == pinfo->fd->num)) {
4478 * Either the connection is in the "initial
4479 * connection" state, or this frame is known
4480 * to have the initial connection reply.
4481 * That means this is the initial connection
4484 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4486 HANDLE_REPLY(plen, length_remaining,
4487 "Initial connection reply",
4488 dissect_x11_initial_reply);
4491 * This isn't an initial connection reply
4492 * (XXX - unless we missed the initial
4493 * connection request). Look at the first
4494 * byte to determine what it is; errors
4495 * start with a byte of 0, replies start
4496 * with a byte of 1, events start with
4497 * a byte with of 2 or greater.
4499 switch (tvb_get_guint8(tvb, offset)) {
4503 HANDLE_REPLY(plen, length_remaining,
4504 "Error", dissect_x11_error);
4508 /* replylength is in units of four. */
4509 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4510 DISSECTOR_ASSERT(plen >= 32);
4511 HANDLE_REPLY(plen, length_remaining,
4512 "Reply", dissect_x11_reply);
4518 HANDLE_REPLY(plen, length_remaining,
4519 "Event", dissect_x11_event);
4531 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4532 const char *volatile sep, x11_conv_data_t *volatile state,
4533 gboolean little_endian)
4535 int offset = 0, *offsetp = &offset, length, left, opcode;
4536 int major_opcode, sequence_number;
4537 value_string *vals_p;
4541 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4542 t = proto_item_add_subtree(ti, ett_x11);
4546 * XXX - this doesn't work correctly if either
4548 * 1) the request sequence number wraps in the lower 16
4551 * 2) we don't see the initial connection request and the
4552 * resynchronization of sequence number fails and thus
4553 * don't have the right sequence numbers
4555 * 3) we don't have all the packets in the capture and
4556 * get out of sequence.
4558 * We might, instead, want to assume that a reply is a reply to
4559 * the most recent not-already-replied-to request in the same
4560 * connection. That also might mismatch replies to requests if
4561 * packets are lost, but there's nothing you can do to fix that.
4564 sequence_number = VALUE16(tvb, offset + 2);
4565 opcode = GPOINTER_TO_INT(g_hash_table_lookup(state->seqtable,
4566 GINT_TO_POINTER(sequence_number)));
4568 if (state->iconn_frame == 0 && state->resync == FALSE) {
4571 * We don't see the initial connection request and no
4572 * resynchronization has been performed yet (first reply),
4573 * set the current sequence number to the one of the
4574 * current reply (this is only performed once).
4576 state->sequencenumber = sequence_number;
4577 state->resync = TRUE;
4580 if (opcode == UNKNOWN_OPCODE) {
4581 if (check_col(pinfo->cinfo, COL_INFO))
4582 col_append_fstr(pinfo->cinfo, COL_INFO,
4583 "%s to unknown request", sep);
4584 proto_item_append_text(ti, ", Reply to unknown request");
4586 if (check_col(pinfo->cinfo, COL_INFO))
4587 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4589 val_to_str(opcode, state->opcode_vals,
4590 "<Unknown opcode %d>"));
4592 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4593 opcode, val_to_str(opcode,
4595 "<Unknown opcode %d>"));
4601 * Replies that need special processing outside tree
4604 case X_QueryExtension:
4607 * if extension is present and request is known:
4608 * store opcode of extension in value_string of
4611 if (!VALUE8(tvb, offset + 8)) {
4616 vals_p = g_hash_table_lookup(state->valtable,
4617 GINT_TO_POINTER(sequence_number));
4618 if (vals_p != NULL) {
4619 major_opcode = VALUE8(tvb, offset + 9);
4620 vals_p->value = major_opcode;
4621 g_hash_table_remove(state->valtable,
4622 GINT_TO_POINTER(sequence_number));
4635 * Requests that expect a reply.
4638 case X_GetWindowAttributes:
4639 REPLYCONTENTS_COMMON();
4645 SEQUENCENUMBER_REPLY(sequencenumber);
4646 REPLYLENGTH(replylength);
4652 CARD16(border_width);
4657 REPLYCONTENTS_COMMON();
4663 SEQUENCENUMBER_REPLY(sequencenumber);
4664 REPLYLENGTH(replylength);
4670 REPLYCONTENTS_COMMON();
4676 SEQUENCENUMBER_REPLY(sequencenumber);
4677 length = REPLYLENGTH(replylength);
4678 ATOM(get_property_type);
4679 CARD32(bytes_after);
4680 CARD32(valuelength);
4684 case X_ListProperties:
4687 SEQUENCENUMBER_REPLY(sequencenumber);
4688 REPLYLENGTH(replylength);
4689 length = CARD16(property_number);
4691 LISTofATOM(properties, length*4);
4694 case X_GetSelectionOwner:
4697 SEQUENCENUMBER_REPLY(sequencenumber);
4698 REPLYLENGTH(replylength);
4704 case X_GrabKeyboard:
4707 SEQUENCENUMBER_REPLY(sequencenumber);
4708 REPLYLENGTH(replylength);
4712 case X_QueryPointer:
4715 SEQUENCENUMBER_REPLY(sequencenumber);
4716 REPLYLENGTH(replylength);
4718 WINDOW(childwindow);
4723 SETofKEYBUTMASK(mask);
4727 case X_GetMotionEvents:
4728 REPLYCONTENTS_COMMON();
4731 case X_TranslateCoords:
4734 SEQUENCENUMBER_REPLY(sequencenumber);
4735 REPLYLENGTH(replylength);
4736 WINDOW(childwindow);
4742 case X_GetInputFocus:
4745 SEQUENCENUMBER_REPLY(sequencenumber);
4746 REPLYLENGTH(replylength);
4754 SEQUENCENUMBER_REPLY(sequencenumber);
4755 REPLYLENGTH(replylength);
4756 LISTofCARD8(keys, 32);
4760 case X_QueryTextExtents:
4763 case X_ListInstalledColormaps:
4764 REPLYCONTENTS_COMMON();
4770 SEQUENCENUMBER_REPLY(sequencenumber);
4771 REPLYLENGTH(replylength);
4781 REPLYCONTENTS_COMMON();
4787 SEQUENCENUMBER_REPLY(sequencenumber);
4788 REPLYLENGTH(replylength);
4790 CARD16(exact_green);
4793 CARD16(visual_green);
4794 CARD16(visual_blue);
4798 case X_QueryBestSize:
4801 SEQUENCENUMBER_REPLY(sequencenumber);
4802 REPLYLENGTH(replylength);
4808 case X_QueryExtension:
4811 SEQUENCENUMBER_REPLY(sequencenumber);
4812 REPLYLENGTH(replylength);
4814 CARD8(major_opcode);
4820 case X_ListExtensions:
4821 REPLYCONTENTS_COMMON();
4824 case X_GetKeyboardMapping:
4825 state->first_keycode =
4826 state->request.GetKeyboardMapping.first_keycode;
4828 state->keysyms_per_keycode =
4829 FIELD8(keysyms_per_keycode);
4830 SEQUENCENUMBER_REPLY(sequencenumber);
4831 length = REPLYLENGTH(replylength);
4833 LISTofKEYSYM(keysyms, state->keycodemap,
4834 state->request.GetKeyboardMapping.first_keycode,
4835 /* XXX - length / state->keysyms_per_keycode can raise a division by zero,
4836 * don't know if this is the *right* way to fix it ... */
4837 state->keysyms_per_keycode ? length / state->keysyms_per_keycode : 0,
4838 state->keysyms_per_keycode);
4841 case X_GetKeyboardControl:
4842 REPLYCONTENTS_COMMON();
4845 case X_GetPointerControl:
4848 SEQUENCENUMBER_REPLY(sequencenumber);
4849 REPLYLENGTH(replylength);
4850 CARD16(acceleration_numerator);
4851 CARD16(acceleration_denominator);
4856 case X_GetScreenSaver:
4859 SEQUENCENUMBER_REPLY(sequencenumber);
4860 REPLYLENGTH(replylength);
4863 ENUM8(prefer_blanking);
4864 ENUM8(allow_exposures);
4869 case X_SetPointerMapping:
4870 case X_GetPointerMapping:
4871 case X_SetModifierMapping:
4872 REPLYCONTENTS_COMMON();
4875 case X_GetModifierMapping:
4877 state->keycodes_per_modifier =
4878 FIELD8(keycodes_per_modifier);
4879 SEQUENCENUMBER_REPLY(sequencenumber);
4880 REPLYLENGTH(replylength);
4882 LISTofKEYCODE(state->modifiermap, keycodes,
4883 state->keycodes_per_modifier);
4887 REPLYCONTENTS_COMMON();
4890 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4895 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4898 guint32 bitmask_value;
4901 proto_tree *bitmask_tree;
4903 bitmask_value = VALUE8(tvb, *offsetp);
4904 bitmask_offset = *offsetp;
4907 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4909 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4910 FLAG(same_screen_focus, focus);
4911 FLAG(same_screen_focus, same_screen);
4917 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4918 const char *volatile sep, x11_conv_data_t *volatile state,
4919 gboolean little_endian)
4921 unsigned char eventcode;
4926 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4927 t = proto_item_add_subtree(ti, ett_x11);
4929 eventcode = tvb_get_guint8(tvb, 0);
4930 sent = (eventcode & 0x80) ? "Sent-" : "";
4932 if (check_col(pinfo->cinfo, COL_INFO))
4933 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s%s",
4935 val_to_str(eventcode & 0x7F, eventcode_vals,
4936 "<Unknown eventcode %u>"));
4938 proto_item_append_text(ti, ", Event, eventcode: %d (%s%s)",
4940 val_to_str(eventcode & 0x7F, eventcode_vals,
4941 "<Unknown eventcode %u>"));
4946 decode_x11_event(tvb, eventcode, sent, t, state, little_endian);
4952 decode_x11_event(tvbuff_t *tvb, unsigned char eventcode, const char *sent,
4953 proto_tree *t, x11_conv_data_t *volatile state,
4954 gboolean little_endian)
4956 int offset = 0, *offsetp = &offset, left;
4958 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4960 "eventcode: %d (%s%s)",
4962 val_to_str(eventcode & 0x7F, eventcode_vals,
4963 "<Unknown eventcode %u>"));
4966 switch (eventcode & 0x7F) {
4971 /* need to do some prefetching here ... */
4972 code = VALUE8(tvb, offset);
4973 mask = VALUE16(tvb, 28);
4975 KEYCODE_DECODED(keycode, code, mask);
4976 CARD16(event_sequencenumber);
4977 EVENTCONTENTS_COMMON();
4985 BUTTON(eventbutton);
4986 CARD16(event_sequencenumber);
4987 EVENTCONTENTS_COMMON();
4994 CARD16(event_sequencenumber);
4995 EVENTCONTENTS_COMMON();
5002 ENUM8(event_detail);
5003 CARD16(event_sequencenumber);
5004 EVENTCONTENTS_COMMON();
5006 same_screen_focus(tvb, offsetp, t);
5011 ENUM8(focus_detail);
5012 CARD16(event_sequencenumber);
5013 WINDOW(eventwindow);
5023 CARD16(event_sequencenumber);
5024 WINDOW(eventwindow);
5033 case GraphicsExpose:
5035 CARD16(event_sequencenumber);
5041 CARD16(minor_opcode);
5043 CARD8(major_opcode);
5049 CARD16(event_sequencenumber);
5051 CARD16(minor_opcode);
5052 CARD8(major_opcode);
5056 case VisibilityNotify:
5058 CARD16(event_sequencenumber);
5059 WINDOW(eventwindow);
5060 ENUM8(visibility_state);
5066 CARD16(event_sequencenumber);
5068 WINDOW(eventwindow);
5073 CARD16(border_width);
5074 BOOL(override_redirect);
5080 CARD16(event_sequencenumber);
5081 WINDOW(eventwindow);
5088 CARD16(event_sequencenumber);
5089 WINDOW(eventwindow);
5091 BOOL(from_configure);
5097 CARD16(event_sequencenumber);
5098 WINDOW(eventwindow);
5100 BOOL(override_redirect);
5106 CARD16(event_sequencenumber);
5108 WINDOW(eventwindow);
5112 case ReparentNotify:
5114 CARD16(event_sequencenumber);
5115 WINDOW(eventwindow);
5120 BOOL(override_redirect);
5124 case ConfigureNotify:
5126 CARD16(event_sequencenumber);
5127 WINDOW(eventwindow);
5129 WINDOW(above_sibling);
5134 CARD16(border_width);
5135 BOOL(override_redirect);
5139 case ConfigureRequest:
5144 CARD16(event_sequencenumber);
5145 WINDOW(eventwindow);
5154 CARD16(event_sequencenumber);
5155 WINDOW(eventwindow);
5161 case CirculateNotify:
5163 CARD16(event_sequencenumber);
5164 WINDOW(eventwindow);
5171 case CirculateRequest:
5173 CARD16(event_sequencenumber);
5175 WINDOW(eventwindow);
5181 case PropertyNotify:
5183 CARD16(event_sequencenumber);
5184 WINDOW(eventwindow);
5187 ENUM8(property_state);
5191 case SelectionClear:
5193 CARD16(event_sequencenumber);
5200 case SelectionRequest:
5202 CARD16(event_sequencenumber);
5212 case SelectionNotify:
5214 CARD16(event_sequencenumber);
5223 case ColormapNotify:
5225 CARD16(event_sequencenumber);
5226 WINDOW(eventwindow);
5229 ENUM8(colormap_state);
5235 CARD16(event_sequencenumber);
5236 WINDOW(eventwindow);
5238 LISTofBYTE(data, 20);
5243 CARD16(event_sequencenumber);
5244 ENUM8(mapping_request);
5245 CARD8(first_keycode);
5254 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5261 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5262 const char *volatile sep, x11_conv_data_t *volatile state _U_,
5263 gboolean little_endian)
5265 int offset = 0, *offsetp = &offset, left;
5266 unsigned char errorcode, error;
5270 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5271 t = proto_item_add_subtree(ti, ett_x11);
5273 error = tvb_get_guint8(tvb, offset);
5276 errorcode = tvb_get_guint8(tvb, offset);
5277 if (check_col(pinfo->cinfo, COL_INFO))
5278 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5279 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5281 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5283 "errorcode: %d (%s)",
5285 val_to_str(errorcode, errorcode_vals,
5286 "<Unknown errorcode %u>"));
5289 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
5290 errorcode, val_to_str(errorcode, errorcode_vals,
5291 "<Unknown errorcode %u>"));
5296 CARD16(error_sequencenumber);
5298 switch (errorcode) {
5300 CARD32(error_badvalue);
5307 CARD16(minor_opcode);
5308 CARD8(major_opcode);
5310 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5316 /************************************************************************
5318 *** I N I T I A L I Z A T I O N A N D M A I N ***
5320 ************************************************************************/
5323 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5325 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5327 if (pinfo->match_port == pinfo->srcport)
5328 dissect_x11_replies(tvb, pinfo, tree);
5330 dissect_x11_requests(tvb, pinfo, tree);
5333 /* Register the protocol with Wireshark */
5334 void proto_register_x11(void)
5337 /* Setup list of header fields */
5338 static hf_register_info hf[] = {
5339 #include "x11-register-info.h"
5342 /* Setup protocol subtree array */
5343 static gint *ett[] = {
5345 &ett_x11_color_flags,
5346 &ett_x11_list_of_arc,
5348 &ett_x11_list_of_atom,
5349 &ett_x11_list_of_card32,
5350 &ett_x11_list_of_color_item,
5351 &ett_x11_color_item,
5352 &ett_x11_list_of_keycode,
5353 &ett_x11_list_of_keysyms,
5355 &ett_x11_list_of_point,
5357 &ett_x11_list_of_rectangle,
5359 &ett_x11_list_of_segment,
5361 &ett_x11_list_of_string8,
5362 &ett_x11_list_of_text_item,
5364 &ett_x11_gc_value_mask,
5365 &ett_x11_event_mask,
5366 &ett_x11_do_not_propagate_mask,
5367 &ett_x11_set_of_key_mask,
5368 &ett_x11_pointer_event_mask,
5369 &ett_x11_window_value_mask,
5370 &ett_x11_configure_window_mask,
5371 &ett_x11_keyboard_value_mask,
5372 &ett_x11_same_screen_focus,
5375 module_t *x11_module;
5377 /* Register the protocol name and description */
5378 proto_x11 = proto_register_protocol("X11", "X11", "x11");
5380 /* Required function calls to register the header fields and subtrees used */
5381 proto_register_field_array(proto_x11, hf, array_length(hf));
5382 proto_register_subtree_array(ett, array_length(ett));
5384 register_init_routine(x11_init_protocol);
5386 x11_module = prefs_register_protocol(proto_x11, NULL);
5387 prefs_register_bool_preference(x11_module, "desegment",
5388 "Reassemble X11 messages spanning multiple TCP segments",
5389 "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
5390 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5395 proto_reg_handoff_x11(void)
5397 dissector_handle_t x11_handle;
5399 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5400 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5401 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5402 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);