2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
6 * $Id: packet-x11.c,v 1.59 2004/06/23 21:43:02 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
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>
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
71 #define cVALS(x) (const value_string*)(x)
74 * Data structure associated with a conversation; keeps track of the
75 * request for which we're expecting a reply, the frame number of
76 * the initial connection request, and the byte order of the connection.
78 * An opcode of -3 means we haven't yet seen any requests yet.
79 * An opcode of -2 means we're not expecting a reply (unused).
80 * An opcode of -1 means we're waiting for a reply to the initial
82 * An opcode of 0 means the request was not seen (or unknown).
83 * Other values are the opcode of the request for which we're expecting
87 #define NOTHING_SEEN -3
88 #define NOTHING_EXPECTED -2
89 #define INITIAL_CONN -1
90 #define UNKNOWN_OPCODE 0
92 #define MAX_OPCODES (255 + 1) /* 255 + INITIAL_CONN */
94 #define BYTE_ORDER_BE 0
95 #define BYTE_ORDER_LE 1
96 #define BYTE_ORDER_UNKNOWN -1
98 static const char *modifiers[] = {
109 /* Keymasks. From <X11/X.h>. */
110 #define ShiftMask (1<<0)
111 #define LockMask (1<<1)
112 #define ControlMask (1<<2)
113 #define Mod1Mask (1<<3)
114 #define Mod2Mask (1<<4)
115 #define Mod3Mask (1<<5)
116 #define Mod4Mask (1<<6)
117 #define Mod5Mask (1<<7)
119 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
120 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
123 #define NoSymbol 0L /* special KeySym */
126 GHashTable *seqtable; /* hashtable of sequencenumber <-> opcode. */
127 GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
128 /* major opcodes including extensions (NULL terminated) */
129 value_string opcode_vals[MAX_OPCODES+1];
130 int sequencenumber; /* sequencenumber of current packet. */
131 guint32 iconn_frame; /* frame # of initial connection request */
132 guint32 iconn_reply; /* frame # of initial connection reply */
133 int byte_order; /* byte order of connection */
134 gboolean resync; /* resynchronization of sequence number performed */
136 int *keycodemap[256]; /* keycode to keysymvalue map. */
137 int keysyms_per_keycode;
139 int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
140 int keycodes_per_modifier;
145 } GetKeyboardMapping;
149 static GMemChunk *x11_state_chunk = NULL;
152 /* Initialize the protocol and registered fields */
153 static int proto_x11 = -1;
155 #include "x11-declarations.h"
157 /* Initialize the subtree pointers */
158 static gint ett_x11 = -1;
159 static gint ett_x11_color_flags = -1;
160 static gint ett_x11_list_of_arc = -1;
161 static gint ett_x11_arc = -1;
162 static gint ett_x11_list_of_atom = -1;
163 static gint ett_x11_list_of_card32 = -1;
164 static gint ett_x11_list_of_color_item = -1;
165 static gint ett_x11_color_item = -1;
166 static gint ett_x11_list_of_keycode = -1;
167 static gint ett_x11_list_of_keysyms = -1;
168 static gint ett_x11_keysym = -1;
169 static gint ett_x11_list_of_point = -1;
170 static gint ett_x11_point = -1;
171 static gint ett_x11_list_of_rectangle = -1;
172 static gint ett_x11_rectangle = -1;
173 static gint ett_x11_list_of_segment = -1;
174 static gint ett_x11_segment = -1;
175 static gint ett_x11_list_of_string8 = -1;
176 static gint ett_x11_list_of_text_item = -1;
177 static gint ett_x11_text_item = -1;
178 static gint ett_x11_gc_value_mask = -1; /* XXX - unused */
179 static gint ett_x11_event_mask = -1; /* XXX - unused */
180 static gint ett_x11_do_not_propagate_mask = -1; /* XXX - unused */
181 static gint ett_x11_set_of_key_mask = -1;
182 static gint ett_x11_pointer_event_mask = -1; /* XXX - unused */
183 static gint ett_x11_window_value_mask = -1; /* XXX - unused */
184 static gint ett_x11_configure_window_mask = -1; /* XXX - unused */
185 static gint ett_x11_keyboard_value_mask = -1; /* XXX - unused */
186 static gint ett_x11_same_screen_focus = -1;
188 /* desegmentation of X11 messages */
189 static gboolean x11_desegment = TRUE;
191 static dissector_handle_t data_handle;
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 /* Requestcodes. From <X11/Xproto.h>. */
580 #define X_CreateWindow 1
581 #define X_ChangeWindowAttributes 2
582 #define X_GetWindowAttributes 3
583 #define X_DestroyWindow 4
584 #define X_DestroySubwindows 5
585 #define X_ChangeSaveSet 6
586 #define X_ReparentWindow 7
587 #define X_MapWindow 8
588 #define X_MapSubwindows 9
589 #define X_UnmapWindow 10
590 #define X_UnmapSubwindows 11
591 #define X_ConfigureWindow 12
592 #define X_CirculateWindow 13
593 #define X_GetGeometry 14
594 #define X_QueryTree 15
595 #define X_InternAtom 16
596 #define X_GetAtomName 17
597 #define X_ChangeProperty 18
598 #define X_DeleteProperty 19
599 #define X_GetProperty 20
600 #define X_ListProperties 21
601 #define X_SetSelectionOwner 22
602 #define X_GetSelectionOwner 23
603 #define X_ConvertSelection 24
604 #define X_SendEvent 25
605 #define X_GrabPointer 26
606 #define X_UngrabPointer 27
607 #define X_GrabButton 28
608 #define X_UngrabButton 29
609 #define X_ChangeActivePointerGrab 30
610 #define X_GrabKeyboard 31
611 #define X_UngrabKeyboard 32
613 #define X_UngrabKey 34
614 #define X_AllowEvents 35
615 #define X_GrabServer 36
616 #define X_UngrabServer 37
617 #define X_QueryPointer 38
618 #define X_GetMotionEvents 39
619 #define X_TranslateCoords 40
620 #define X_WarpPointer 41
621 #define X_SetInputFocus 42
622 #define X_GetInputFocus 43
623 #define X_QueryKeymap 44
624 #define X_OpenFont 45
625 #define X_CloseFont 46
626 #define X_QueryFont 47
627 #define X_QueryTextExtents 48
628 #define X_ListFonts 49
629 #define X_ListFontsWithInfo 50
630 #define X_SetFontPath 51
631 #define X_GetFontPath 52
632 #define X_CreatePixmap 53
633 #define X_FreePixmap 54
634 #define X_CreateGC 55
635 #define X_ChangeGC 56
637 #define X_SetDashes 58
638 #define X_SetClipRectangles 59
640 #define X_ClearArea 61
641 #define X_CopyArea 62
642 #define X_CopyPlane 63
643 #define X_PolyPoint 64
644 #define X_PolyLine 65
645 #define X_PolySegment 66
646 #define X_PolyRectangle 67
648 #define X_FillPoly 69
649 #define X_PolyFillRectangle 70
650 #define X_PolyFillArc 71
651 #define X_PutImage 72
652 #define X_GetImage 73
653 #define X_PolyText8 74
654 #define X_PolyText16 75
655 #define X_ImageText8 76
656 #define X_ImageText16 77
657 #define X_CreateColormap 78
658 #define X_FreeColormap 79
659 #define X_CopyColormapAndFree 80
660 #define X_InstallColormap 81
661 #define X_UninstallColormap 82
662 #define X_ListInstalledColormaps 83
663 #define X_AllocColor 84
664 #define X_AllocNamedColor 85
665 #define X_AllocColorCells 86
666 #define X_AllocColorPlanes 87
667 #define X_FreeColors 88
668 #define X_StoreColors 89
669 #define X_StoreNamedColor 90
670 #define X_QueryColors 91
671 #define X_LookupColor 92
672 #define X_CreateCursor 93
673 #define X_CreateGlyphCursor 94
674 #define X_FreeCursor 95
675 #define X_RecolorCursor 96
676 #define X_QueryBestSize 97
677 #define X_QueryExtension 98
678 #define X_ListExtensions 99
679 #define X_ChangeKeyboardMapping 100
680 #define X_GetKeyboardMapping 101
681 #define X_ChangeKeyboardControl 102
682 #define X_GetKeyboardControl 103
684 #define X_ChangePointerControl 105
685 #define X_GetPointerControl 106
686 #define X_SetScreenSaver 107
687 #define X_GetScreenSaver 108
688 #define X_ChangeHosts 109
689 #define X_ListHosts 110
690 #define X_SetAccessControl 111
691 #define X_SetCloseDownMode 112
692 #define X_KillClient 113
693 #define X_RotateProperties 114
694 #define X_ForceScreenSaver 115
695 #define X_SetPointerMapping 116
696 #define X_GetPointerMapping 117
697 #define X_SetModifierMapping 118
698 #define X_GetModifierMapping 119
699 #define X_NoOperation 127
700 #define X_FirstExtension 128
701 #define X_LastExtension 255
703 static const value_string opcode_vals[] = {
704 { INITIAL_CONN, "Initial connection request" },
705 { X_CreateWindow, "CreateWindow" },
706 { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
707 { X_GetWindowAttributes, "GetWindowAttributes" },
708 { X_DestroyWindow, "DestroyWindow" },
709 { X_DestroySubwindows, "DestroySubwindows" },
710 { X_ChangeSaveSet, "ChangeSaveSet" },
711 { X_ReparentWindow, "ReparentWindow" },
712 { X_MapWindow, "MapWindow" },
713 { X_MapSubwindows, "MapSubwindows" },
714 { X_UnmapWindow, "UnmapWindow" },
715 { X_UnmapSubwindows, "UnmapSubwindows" },
716 { X_ConfigureWindow, "ConfigureWindow" },
717 { X_CirculateWindow, "CirculateWindow" },
718 { X_GetGeometry, "GetGeometry" },
719 { X_QueryTree, "QueryTree" },
720 { X_InternAtom, "InternAtom" },
721 { X_GetAtomName, "GetAtomName" },
722 { X_ChangeProperty, "ChangeProperty" },
723 { X_DeleteProperty, "DeleteProperty" },
724 { X_GetProperty, "GetProperty" },
725 { X_ListProperties, "ListProperties" },
726 { X_SetSelectionOwner, "SetSelectionOwner" },
727 { X_GetSelectionOwner, "GetSelectionOwner" },
728 { X_ConvertSelection, "ConvertSelection" },
729 { X_SendEvent, "SendEvent" },
730 { X_GrabPointer, "GrabPointer" },
731 { X_UngrabPointer, "UngrabPointer" },
732 { X_GrabButton, "GrabButton" },
733 { X_UngrabButton, "UngrabButton" },
734 { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
735 { X_GrabKeyboard, "GrabKeyboard" },
736 { X_UngrabKeyboard, "UngrabKeyboard" },
737 { X_GrabKey, "GrabKey" },
738 { X_UngrabKey, "UngrabKey" },
739 { X_AllowEvents, "AllowEvents" },
740 { X_GrabServer, "GrabServer" },
741 { X_UngrabServer, "UngrabServer" },
742 { X_QueryPointer, "QueryPointer" },
743 { X_GetMotionEvents, "GetMotionEvents" },
744 { X_TranslateCoords, "TranslateCoordinates" },
745 { X_WarpPointer, "WarpPointer" },
746 { X_SetInputFocus, "SetInputFocus" },
747 { X_GetInputFocus, "GetInputFocus" },
748 { X_QueryKeymap, "QueryKeymap" },
749 { X_OpenFont, "OpenFont" },
750 { X_CloseFont, "CloseFont" },
751 { X_QueryFont, "QueryFont" },
752 { X_QueryTextExtents, "QueryTextExtents" },
753 { X_ListFonts, "ListFonts" },
754 { X_ListFontsWithInfo, "ListFontsWithInfo" },
755 { X_SetFontPath, "SetFontPath" },
756 { X_GetFontPath, "GetFontPath" },
757 { X_CreatePixmap, "CreatePixmap" },
758 { X_FreePixmap, "FreePixmap" },
759 { X_CreateGC, "CreateGC" },
760 { X_ChangeGC, "ChangeGC" },
761 { X_CopyGC, "CopyGC" },
762 { X_SetDashes, "SetDashes" },
763 { X_SetClipRectangles, "SetClipRectangles" },
764 { X_FreeGC, "FreeGC" },
765 { X_ClearArea, "ClearArea" },
766 { X_CopyArea, "CopyArea" },
767 { X_CopyPlane, "CopyPlane" },
768 { X_PolyPoint, "PolyPoint" },
769 { X_PolyLine, "PolyLine" },
770 { X_PolySegment, "PolySegment" },
771 { X_PolyRectangle, "PolyRectangle" },
772 { X_PolyArc, "PolyArc" },
773 { X_FillPoly, "FillPoly" },
774 { X_PolyFillRectangle, "PolyFillRectangle" },
775 { X_PolyFillArc, "PolyFillArc" },
776 { X_PutImage, "PutImage" },
777 { X_GetImage, "GetImage" },
778 { X_PolyText8, "PolyText8" },
779 { X_PolyText16, "PolyText16" },
780 { X_ImageText8, "ImageText8" },
781 { X_ImageText16, "ImageText16" },
782 { X_CreateColormap, "CreateColormap" },
783 { X_FreeColormap, "FreeColormap" },
784 { X_CopyColormapAndFree, "CopyColormapAndFree" },
785 { X_InstallColormap, "InstallColormap" },
786 { X_UninstallColormap, "UninstallColormap" },
787 { X_ListInstalledColormaps, "ListInstalledColormaps" },
788 { X_AllocColor, "AllocColor" },
789 { X_AllocNamedColor, "AllocNamedColor" },
790 { X_AllocColorCells, "AllocColorCells" },
791 { X_AllocColorPlanes, "AllocColorPlanes" },
792 { X_FreeColors, "FreeColors" },
793 { X_StoreColors, "StoreColors" },
794 { X_StoreNamedColor, "StoreNamedColor" },
795 { X_QueryColors, "QueryColors" },
796 { X_LookupColor, "LookupColor" },
797 { X_CreateCursor, "CreateCursor" },
798 { X_CreateGlyphCursor, "CreateGlyphCursor" },
799 { X_FreeCursor, "FreeCursor" },
800 { X_RecolorCursor, "RecolorCursor" },
801 { X_QueryBestSize, "QueryBestSize" },
802 { X_QueryExtension, "QueryExtension" },
803 { X_ListExtensions, "ListExtensions" },
804 { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
805 { X_GetKeyboardMapping, "GetKeyboardMapping" },
806 { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
807 { X_GetKeyboardControl, "GetKeyboardControl" },
809 { X_ChangePointerControl, "ChangePointerControl" },
810 { X_GetPointerControl, "GetPointerControl" },
811 { X_SetScreenSaver, "SetScreenSaver" },
812 { X_GetScreenSaver, "GetScreenSaver" },
813 { X_ChangeHosts, "ChangeHosts" },
814 { X_ListHosts, "ListHosts" },
815 { X_SetAccessControl, "SetAccessControl" },
816 { X_SetCloseDownMode, "SetCloseDownMode" },
817 { X_KillClient, "KillClient" },
818 { X_RotateProperties, "RotateProperties" },
819 { X_ForceScreenSaver, "ForceScreenSaver" },
820 { X_SetPointerMapping, "SetPointerMapping" },
821 { X_GetPointerMapping, "GetPointerMapping" },
822 { X_SetModifierMapping, "SetModifierMapping" },
823 { X_GetModifierMapping, "GetModifierMapping" },
824 { X_NoOperation, "NoOperation" },
828 /* Eventscodes. From <X11/X.h>. */
831 #define ButtonPress 4
832 #define ButtonRelease 5
833 #define MotionNotify 6
834 #define EnterNotify 7
835 #define LeaveNotify 8
838 #define KeymapNotify 11
840 #define GraphicsExpose 13
842 #define VisibilityNotify 15
843 #define CreateNotify 16
844 #define DestroyNotify 17
845 #define UnmapNotify 18
847 #define MapRequest 20
848 #define ReparentNotify 21
849 #define ConfigureNotify 22
850 #define ConfigureRequest 23
851 #define GravityNotify 24
852 #define ResizeRequest 25
853 #define CirculateNotify 26
854 #define CirculateRequest 27
855 #define PropertyNotify 28
856 #define SelectionClear 29
857 #define SelectionRequest 30
858 #define SelectionNotify 31
859 #define ColormapNotify 32
860 #define ClientMessage 33
861 #define MappingNotify 34
862 #define FirstExtensionEvent 64
863 #define LastExtensionEvent 127
865 static const value_string eventcode_vals[] = {
866 { KeyPress, "KeyPress" },
867 { KeyRelease, "KeyRelease" },
868 { ButtonPress, "ButtonPress" },
869 { ButtonRelease, "ButtonRelease" },
870 { MotionNotify, "MotionNotify" },
871 { EnterNotify, "EnterNotify" },
872 { LeaveNotify, "LeaveNotify" },
873 { FocusIn, "FocusIn" },
874 { FocusOut, "FocusOut" },
875 { KeymapNotify, "KeymapNotify" },
876 { Expose, "Expose" },
877 { GraphicsExpose, "GraphicsExpose" },
878 { NoExpose, "NoExpose" },
879 { VisibilityNotify, "VisibilityNotify" },
880 { CreateNotify, "CreateNotify" },
881 { DestroyNotify, "DestroyNotify" },
882 { UnmapNotify, "UnmapNotify" },
883 { MapNotify, "MapNotify" },
884 { MapRequest, "MapRequest" },
885 { ReparentNotify, "ReparentNotify" },
886 { ConfigureNotify, "ConfigureNotify" },
887 { ConfigureRequest, "ConfigureRequest" },
888 { GravityNotify, "GravityNotify" },
889 { ResizeRequest, "ResizeRequest" },
890 { CirculateNotify, "CirculateNotify" },
891 { CirculateRequest, "CirculateRequest" },
892 { PropertyNotify, "PropertyNotify" },
893 { SelectionClear, "SelectionClear" },
894 { SelectionRequest, "SelectionRequest" },
895 { SelectionNotify, "SelectionNotify" },
896 { ColormapNotify, "ColormapNotify" },
897 { ClientMessage, "ClientMessage" },
898 { MappingNotify, "MappingNotify" },
902 /* Errorcodes. From <X11/X.h> */
903 #define Success 0 /* everything's okay */
904 #define BadRequest 1 /* bad request code */
905 #define BadValue 2 /* int parameter out of range */
906 #define BadWindow 3 /* parameter not a Window */
907 #define BadPixmap 4 /* parameter not a Pixmap */
908 #define BadAtom 5 /* parameter not an Atom */
909 #define BadCursor 6 /* parameter not a Cursor */
910 #define BadFont 7 /* parameter not a Font */
911 #define BadMatch 8 /* parameter mismatch */
912 #define BadDrawable 9 /* parameter not a Pixmap or Window */
913 #define BadAccess 10 /* depending on context:
914 - key/button already grabbed
915 - attempt to free an illegal
917 - attempt to store into a read-only
919 - attempt to modify the access control
920 list from other than the local host.
922 #define BadAlloc 11 /* insufficient resources */
923 #define BadColor 12 /* no such colormap */
924 #define BadGC 13 /* parameter not a GC */
925 #define BadIDChoice 14 /* choice not in range or already used */
926 #define BadName 15 /* font or color name doesn't exist */
927 #define BadLength 16 /* Request length incorrect */
928 #define BadImplementation 17 /* server is defective */
930 #define FirstExtensionError 128
931 #define LastExtensionError 255
933 static const value_string errorcode_vals[] = {
934 { Success, "Success" },
935 { BadRequest, "BadRequest" },
936 { BadValue, "BadValue" },
937 { BadWindow, "BadWindow" },
938 { BadPixmap, "BadPixmap" },
939 { BadAtom, "BadAtom" },
940 { BadCursor, "BadCursor" },
941 { BadFont, "BadFont" },
942 { BadMatch, "BadMatch" },
943 { BadDrawable, "BadDrawable" },
944 { BadAccess, "BadAccess" },
945 { BadAlloc, "BadAlloc" },
946 { BadColor, "BadColor" },
948 { BadIDChoice, "BadIDChoice" },
949 { BadName, "BadName" },
950 { BadLength, "BadLength" },
951 { BadImplementation, "BadImplementation" },
952 { FirstExtensionError, "FirstExtensionError" },
953 { LastExtensionError, "LastExtensionError" },
957 static const value_string ordering_vals[] = {
965 static const value_string plane_mask_vals[] = {
966 { 0xFFFFFFFF, "AllPlanes" },
970 static const value_string pointer_keyboard_mode_vals[] = {
971 { 0, "Synchronous" },
972 { 1, "Asynchronous" },
976 static const value_string revert_to_vals[] = {
978 { 1, "PointerRoot" },
983 static const value_string insert_delete_vals[] = {
989 static const value_string screen_saver_mode_vals[] = {
995 static const value_string shape_vals[] = {
1002 static const value_string stack_mode_vals[] = {
1011 static const value_string subwindow_mode_vals[] = {
1012 { 0, "ClipByChildren" },
1013 { 1, "IncludeInferiors" },
1017 static const value_string window_class_vals[] = {
1018 { 0, "CopyFromParent" },
1019 { 1, "InputOutput" },
1024 static const value_string yes_no_default_vals[] = {
1031 static const value_string zero_is_any_property_type_vals[] = {
1032 { 0, "AnyPropertyType" },
1036 static const value_string zero_is_none_vals[] = {
1041 /* we have not seen packet before. */
1042 #define PACKET_IS_NEW(pinfo) \
1043 (!((pinfo)->fd->flags.visited))
1045 /************************************************************************
1047 *** F I E L D D E C O D I N G M A C R O S ***
1049 ************************************************************************/
1051 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
1052 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
1053 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
1055 #define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
1056 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
1057 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
1059 #define BITFIELD(TYPE, position, name) {\
1061 int save = *offsetp;\
1062 proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
1063 bitmask_size, little_endian); \
1064 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
1066 unused = save + 4 - *offsetp;\
1068 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
1069 *offsetp = save + 4;\
1073 #define FLAG(position, name) {\
1074 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
1076 #define FLAG_IF_NONZERO(position, name) do {\
1077 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
1078 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
1080 #define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
1081 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
1082 #define BITMASK(name, size) {\
1084 guint32 bitmask_value; \
1085 int bitmask_offset; \
1087 proto_tree *bitmask_tree; \
1088 bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
1089 ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
1090 (guint32)VALUE32(tvb, *offsetp))); \
1091 bitmask_offset = *offsetp; \
1092 bitmask_size = size; \
1093 ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
1094 bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
1096 #define ENDBITMASK }
1097 #define BITMASK8(name) BITMASK(name, 1);
1098 #define BITMASK16(name) BITMASK(name, 2);
1099 #define BITMASK32(name) BITMASK(name, 4);
1100 #define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
1101 #define BUTTON(name) FIELD8(name)
1102 #define CARD8(name) FIELD8(name)
1103 #define CARD16(name) (FIELD16(name))
1104 #define CARD32(name) (FIELD32(name))
1105 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1106 #define COLORMAP(name) FIELD32(name)
1107 #define CURSOR(name) FIELD32(name)
1108 #define DRAWABLE(name) FIELD32(name)
1109 #define ENUM8(name) (FIELD8(name))
1110 #define ENUM16(name) (FIELD16(name))
1111 #define FONT(name) FIELD32(name)
1112 #define FONTABLE(name) FIELD32(name)
1113 #define GCONTEXT(name) FIELD32(name)
1114 #define INT8(name) FIELD8(name)
1115 #define INT16(name) FIELD16(name)
1116 #define INT32(name) FIELD32(name)
1117 #define KEYCODE(name) FIELD8(name)
1118 #define KEYCODE_DECODED(name, keycode, mask) do { \
1119 proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
1120 keycode, "keycode: %d (%s)", \
1121 keycode, keycode2keysymString(state->keycodemap, \
1122 state->first_keycode, state->keysyms_per_keycode, \
1123 state->modifiermap, state->keycodes_per_modifier, \
1128 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
1129 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1130 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1131 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1132 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1133 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1134 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1135 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1136 keysyms_per_keycode) {\
1137 listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1138 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1139 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1140 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1141 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1142 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1143 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1144 #define OPCODE() { opcode = FIELD8(opcode); }
1145 #define PIXMAP(name) { FIELD32(name); }
1146 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1147 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1148 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1149 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1150 #define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 1); }
1151 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1152 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1153 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1154 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1155 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
1156 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
1157 #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; }
1158 #define WINDOW(name) { FIELD32(name); }
1159 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1161 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1162 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1163 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1164 #define REPLY(name) FIELD8(name);
1165 #define REPLYLENGTH(name) FIELD32(name);
1167 #define EVENTCONTENTS_COMMON() do { \
1169 WINDOW(rootwindow); \
1170 WINDOW(eventwindow); \
1171 WINDOW(childwindow); \
1176 setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
1179 #define SEQUENCENUMBER_REPLY(name) do { \
1182 seqno = VALUE16(tvb, *offsetp); \
1183 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1184 *offsetp, sizeof(seqno), seqno, \
1185 "sequencenumber: %d (%s)", \
1187 val_to_str(opcode, state->opcode_vals, "<Unknown opcode %d>")); \
1188 *offsetp += sizeof(seqno); \
1191 #define REPLYCONTENTS_COMMON() do { \
1193 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1194 1, little_endian); \
1196 SEQUENCENUMBER_REPLY(sequencenumber); \
1197 REPLYLENGTH(replylength); \
1198 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1199 tvb_reported_length_remaining(tvb, offset), little_endian); \
1200 offset += tvb_reported_length_remaining(tvb, offset); \
1204 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1205 if (length_remaining < plen) { \
1206 if (x11_desegment && pinfo->can_desegment) { \
1207 pinfo->desegment_offset = offset; \
1208 pinfo->desegment_len = plen - length_remaining;\
1211 ; /* XXX yes, what then? Need to skip/join. */ \
1214 if (length_remaining > plen) \
1215 length_remaining = plen; \
1216 next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1218 if (sep == NULL) { \
1219 if (check_col(pinfo->cinfo, COL_INFO)) \
1220 col_add_str(pinfo->cinfo, COL_INFO, str); \
1225 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1228 CATCH(BoundsError) { \
1231 CATCH(ReportedBoundsError) { \
1232 show_reported_bounds_error(next_tvb, pinfo, tree); \
1240 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1241 const char *sep, x11_conv_data_t *volatile state,
1242 gboolean little_endian);
1245 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1246 const char *volatile sep, x11_conv_data_t *volatile state,
1247 gboolean little_endian);
1250 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1251 const char *volatile sep, x11_conv_data_t *volatile state,
1252 gboolean little_endian);
1255 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1256 const char *volatile sep, x11_conv_data_t *volatile state,
1257 gboolean little_endian);
1260 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation);
1263 keysymString(guint32 v);
1266 /************************************************************************
1268 *** D E C O D I N G F I E L D S ***
1270 ************************************************************************/
1272 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1273 gboolean little_endian)
1275 const char *interpretation = NULL;
1277 guint32 v = VALUE32(tvb, *offsetp);
1278 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1279 interpretation = atom_predefined_interpretation[v];
1281 interpretation = "Not a predefined atom";
1283 header_field_info *hfi = proto_registrar_get_nth(hf);
1285 interpretation = match_strval(v, cVALS(hfi -> strings));
1287 if (!interpretation) interpretation = "error in Xlib client program ?";
1288 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1289 proto_registrar_get_nth(hf) -> name, v, interpretation);
1293 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1295 guint32 v = VALUE8(tvb, *offsetp);
1296 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1301 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1303 unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1307 if (do_red_green_blue) {
1310 char *bp = buffer + sprintf(buffer, "flags: ");
1312 if (do_red_green_blue & 0x1) {
1313 bp += sprintf(bp, "DoRed");
1317 if (do_red_green_blue & 0x2) {
1318 if (sep) bp += sprintf(bp, " | ");
1319 bp += sprintf(bp, "DoGreen");
1323 if (do_red_green_blue & 0x4) {
1324 if (sep) bp += sprintf(bp, " | ");
1325 bp += sprintf(bp, "DoBlue");
1329 if (do_red_green_blue & 0xf8) {
1330 if (sep) bp += sprintf(bp, " + ");
1331 sprintf(bp, "trash");
1334 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1336 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1337 if (do_red_green_blue & 0x1)
1338 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1339 do_red_green_blue & 0x1);
1340 if (do_red_green_blue & 0x2)
1341 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1342 do_red_green_blue & 0x2);
1343 if (do_red_green_blue & 0x4)
1344 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1345 do_red_green_blue & 0x4);
1346 if (do_red_green_blue & 0xf8)
1347 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1348 do_red_green_blue & 0xf8);
1350 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1355 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1356 int hf, const char *nullInterpretation)
1358 guint8 v = VALUE8(tvb, *offsetp);
1361 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1362 proto_registrar_get_nth(hf) -> name,
1363 nullInterpretation);
1365 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1369 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1370 int length, gboolean little_endian)
1372 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1373 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1375 gint16 x = VALUE16(tvb, *offsetp);
1376 gint16 y = VALUE16(tvb, *offsetp + 2);
1377 guint16 width = VALUE16(tvb, *offsetp + 4);
1378 guint16 height = VALUE16(tvb, *offsetp + 6);
1379 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1380 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1382 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1383 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1384 width, height, x, y, angle1, angle2,
1385 angle1 / 64.0, angle2 / 64.0);
1386 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1387 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1389 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1391 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1393 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1395 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1397 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1402 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1403 int length, gboolean little_endian)
1405 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1406 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1408 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1411 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1412 int length, gboolean little_endian)
1414 if (length <= 0) length = 1;
1415 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1419 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1420 int hf_item, int length, gboolean little_endian)
1422 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1423 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1425 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1430 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1431 int length, gboolean little_endian)
1433 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1434 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1438 unsigned do_red_green_blue;
1439 guint16 red, green, blue;
1444 red = VALUE16(tvb, *offsetp + 4);
1445 green = VALUE16(tvb, *offsetp + 6);
1446 blue = VALUE16(tvb, *offsetp + 8);
1447 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1449 bp = buffer + sprintf(buffer, "colorItem: ");
1451 if (do_red_green_blue & 0x1) {
1452 bp += sprintf(bp, "red = %d", red);
1455 if (do_red_green_blue & 0x2) {
1456 bp += sprintf(bp, "%sgreen = %d", sep, green);
1459 if (do_red_green_blue & 0x4)
1460 bp += sprintf(bp, "%sblue = %d", sep, blue);
1462 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1463 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1464 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1466 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1468 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1470 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1472 colorFlags(tvb, offsetp, ttt);
1473 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1478 static GTree *keysymTable = NULL;
1480 static gint compareGuint32(gconstpointer a, gconstpointer b)
1482 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1486 XConvertCase(register int sym, int *lower, int *upper)
1491 case 0: /* Latin 1 */
1492 if ((sym >= XK_A) && (sym <= XK_Z))
1493 *lower += (XK_a - XK_A);
1494 else if ((sym >= XK_a) && (sym <= XK_z))
1495 *upper -= (XK_a - XK_A);
1496 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1497 *lower += (XK_agrave - XK_Agrave);
1498 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1499 *upper -= (XK_agrave - XK_Agrave);
1500 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1501 *lower += (XK_oslash - XK_Ooblique);
1502 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1503 *upper -= (XK_oslash - XK_Ooblique);
1505 case 1: /* Latin 2 */
1506 /* Assume the KeySym is a legal value (ignore discontinuities) */
1507 if (sym == XK_Aogonek)
1508 *lower = XK_aogonek;
1509 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1510 *lower += (XK_lstroke - XK_Lstroke);
1511 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1512 *lower += (XK_scaron - XK_Scaron);
1513 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1514 *lower += (XK_zcaron - XK_Zcaron);
1515 else if (sym == XK_aogonek)
1516 *upper = XK_Aogonek;
1517 else if (sym >= XK_lstroke && sym <= XK_sacute)
1518 *upper -= (XK_lstroke - XK_Lstroke);
1519 else if (sym >= XK_scaron && sym <= XK_zacute)
1520 *upper -= (XK_scaron - XK_Scaron);
1521 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1522 *upper -= (XK_zcaron - XK_Zcaron);
1523 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1524 *lower += (XK_racute - XK_Racute);
1525 else if (sym >= XK_racute && sym <= XK_tcedilla)
1526 *upper -= (XK_racute - XK_Racute);
1528 case 2: /* Latin 3 */
1529 /* Assume the KeySym is a legal value (ignore discontinuities) */
1530 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1531 *lower += (XK_hstroke - XK_Hstroke);
1532 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1533 *lower += (XK_gbreve - XK_Gbreve);
1534 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1535 *upper -= (XK_hstroke - XK_Hstroke);
1536 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1537 *upper -= (XK_gbreve - XK_Gbreve);
1538 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1539 *lower += (XK_cabovedot - XK_Cabovedot);
1540 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1541 *upper -= (XK_cabovedot - XK_Cabovedot);
1543 case 3: /* Latin 4 */
1544 /* Assume the KeySym is a legal value (ignore discontinuities) */
1545 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1546 *lower += (XK_rcedilla - XK_Rcedilla);
1547 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1548 *upper -= (XK_rcedilla - XK_Rcedilla);
1549 else if (sym == XK_ENG)
1551 else if (sym == XK_eng)
1553 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1554 *lower += (XK_amacron - XK_Amacron);
1555 else if (sym >= XK_amacron && sym <= XK_umacron)
1556 *upper -= (XK_amacron - XK_Amacron);
1558 case 6: /* Cyrillic */
1559 /* Assume the KeySym is a legal value (ignore discontinuities) */
1560 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1561 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1562 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1563 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1564 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1565 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1566 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1567 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1570 /* Assume the KeySym is a legal value (ignore discontinuities) */
1571 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1572 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1573 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1574 sym != XK_Greek_iotaaccentdieresis &&
1575 sym != XK_Greek_upsilonaccentdieresis)
1576 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1577 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1578 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1579 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1580 sym != XK_Greek_finalsmallsigma)
1581 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1587 keycode2keysymString(int *keycodemap[256], int first_keycode,
1588 int keysyms_per_keycode,
1589 int *modifiermap[array_length(modifiers)],
1590 int keycodes_per_modifier,
1591 guint32 keycode, guint32 bitmask)
1593 static char buf[32];
1595 int groupmodkc, numlockkc, numlockmod, groupmod;
1596 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1597 int lockmod_is_nosymbol = 1;
1598 int modifier, kc, keysym;
1600 if ((syms = keycodemap[keycode]) == NULL)
1603 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1604 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1605 if (keycodemap[kc] == NULL)
1607 switch (keycodemap[kc][keysym]) {
1617 lockmod_is_capslock = kc;
1621 lockmod_is_shiftlock = kc;
1628 * If we have not seen the modifiermap we don't know what the
1629 * keycode translates to, but we do know it's one of the keys
1630 * in syms (give or take a case-conversion), so we could in
1631 * theory list them all.
1633 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1636 /* find out what the numlockmodifer and groupmodifier is. */
1637 for (modifier = 0, numlockmod = groupmod = -1;
1638 modifier < (int)array_length(modifiers) && numlockmod == -1;
1640 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1641 if (modifiermap[modifier][kc] == numlockkc)
1642 numlockmod = modifier;
1643 else if (modifiermap[modifier][kc] == groupmodkc)
1644 groupmod = modifier;
1647 * ... and what the lockmodifier is interpreted as.
1648 * (X11v4r6 ref, keyboard and pointers section.)
1650 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1651 if (modifiermap[1][kc] == lockmod_is_capslock) {
1652 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1655 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1656 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1662 * This is (how I understand) the X11v4R6 protocol description given
1663 * in A. Nye's book. It is quite different from the
1664 * code in _XTranslateKey() in the file
1665 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1666 * as shipped with XFree, and doesn't work correctly, nor do I see
1667 * how it could (e.g. the case of lower/uppercase-letters).
1668 * -- Michael Shuldman
1671 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1672 && ((syms[1] >= 0xff80
1673 && syms[1] <= 0xffbd)
1674 || (syms[1] >= 0x11000000
1675 && syms[1] <= 0x1100ffff))) {
1676 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1677 return keysymString(syms[groupmod + 0]);
1679 if (syms[groupmod + 1] == NoSymbol)
1680 return keysymString(syms[groupmod + 0]);
1682 return keysymString(syms[groupmod + 1]);
1684 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1685 return keysymString(syms[groupmod + 0]);
1686 else if (!(bitmask & ShiftMask)
1687 && ((bitmask & LockMask) && lockmod_is_capslock))
1688 if (islower(syms[groupmod + 0]))
1689 /* return toupper(keysymString(syms[groupmod + 0])); */
1690 return "Uppercase"; /* XXX */
1692 return keysymString(syms[groupmod + 0]);
1694 else if ((bitmask & ShiftMask)
1695 && ((bitmask & LockMask) && lockmod_is_capslock))
1696 if (islower(syms[groupmod + 1]))
1697 /* return toupper(keysymString(syms[groupmod + 1])); */
1698 return "Uppercase"; /* XXX */
1700 return keysymString(syms[groupmod + 1]);
1702 else if ((bitmask & ShiftMask)
1703 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1704 return keysymString(syms[groupmod + 1]);
1705 #else /* _XTranslateKey() based code. */
1707 while (keysyms_per_keycode > 2
1708 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1709 --keysyms_per_keycode;
1710 if (keysyms_per_keycode > 2
1711 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1713 keysyms_per_keycode -= 2;
1716 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1717 && keysyms_per_keycode > 1
1718 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1719 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1720 if ((bitmask & ShiftMask)
1721 || (bitmask & LockMask && lockmod_is_shiftlock))
1726 else if (!(bitmask & ShiftMask)
1727 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1728 if (keysyms_per_keycode == 1
1729 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1732 XConvertCase(syms[0], &keysym, &usym);
1737 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1740 if (keysyms_per_keycode == 1
1741 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1742 XConvertCase(syms[0], &lsym, &usym);
1748 if (keysyms_per_keycode == 1
1749 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1752 XConvertCase(keysym, &lsym, &usym);
1754 if (!(bitmask & ShiftMask) && keysym != syms[0]
1755 && ((keysym != usym) || (lsym == usym)))
1756 XConvertCase(syms[0], &lsym, &usym);
1760 if (keysym == XK_VoidSymbol)
1763 sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1768 static const char *keysymString(guint32 v)
1773 /* This table is so big that we built it only if necessary */
1775 const value_string *p = keysym_vals_source;
1776 keysymTable = g_tree_new(compareGuint32);
1777 for(; p -> strptr; p++)
1778 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
1780 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1781 return res ? res : "<Unknown>";
1784 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1785 int *modifiermap[], int keycodes_per_modifier,
1786 gboolean little_endian)
1789 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1790 array_length(modifiers) * keycodes_per_modifier, little_endian);
1792 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1795 for (m = 0; m < array_length(modifiers);
1796 ++m, *offsetp += keycodes_per_modifier) {
1801 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1803 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1805 for(i = 0; i < keycodes_per_modifier; ++i) {
1809 bp += sprintf(bp, " %s=%d", modifiers[m], c);
1811 modifiermap[m][i] = c;
1814 proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1815 *offsetp, keycodes_per_modifier, p,
1816 "item: %s", buffer);
1820 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1821 int hf_item, int *keycodemap[256],
1822 int keycode_first, int keycode_count,
1823 int keysyms_per_keycode, gboolean little_endian)
1825 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1826 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1831 g_assert(keycode_first >= 0);
1832 g_assert(keycode_count >= 0);
1833 g_assert((size_t)(keycode_first + keycode_count) <= 256);
1836 for (keycode = keycode_first; keycode_count > 0;
1837 ++keycode, --keycode_count) {
1838 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1839 keysyms_per_keycode * 4, "keysyms (keycode %d):", keycode);
1841 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1843 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1845 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1847 for(i = 0; i < keysyms_per_keycode; ++i) {
1848 /* keysymvalue = byte3 * 256 + byte4. */
1849 guint32 v = VALUE32(tvb, *offsetp);
1851 proto_item_append_text(tti, " %s", keysymString(v));
1852 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1853 tvb, *offsetp, 4, v,
1854 "keysym (keycode %d): 0x%08x (%s)",
1855 keycode, v, keysymString(v));
1857 keycodemap[keycode][i] = v;
1861 for (i = 1; i < keysyms_per_keycode; ++i)
1862 if (keycodemap[keycode][i] != NoSymbol)
1865 if (i == keysyms_per_keycode) {
1866 /* all but (possibly) first were NoSymbol. */
1867 if (keysyms_per_keycode == 4) {
1868 keycodemap[keycode][1] = NoSymbol;
1869 keycodemap[keycode][2] = keycodemap[keycode][0];
1870 keycodemap[keycode][3] = NoSymbol;
1876 for (i = 2; i < keysyms_per_keycode; ++i)
1877 if (keycodemap[keycode][i] != NoSymbol)
1879 if (i == keysyms_per_keycode) {
1880 /* all but (possibly) first two were NoSymbol. */
1881 if (keysyms_per_keycode == 4) {
1882 keycodemap[keycode][2] = keycodemap[keycode][0];
1883 keycodemap[keycode][3] = keycodemap[keycode][1];
1891 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1892 int length, gboolean little_endian)
1894 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1895 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1901 x = VALUE16(tvb, *offsetp);
1902 y = VALUE16(tvb, *offsetp + 2);
1904 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1905 ttt = proto_item_add_subtree(tti, ett_x11_point);
1906 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1908 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1913 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1914 int length, gboolean little_endian)
1916 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1917 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1920 unsigned width, height;
1924 x = VALUE16(tvb, *offsetp);
1925 y = VALUE16(tvb, *offsetp + 2);
1926 width = VALUE16(tvb, *offsetp + 4);
1927 height = VALUE16(tvb, *offsetp + 6);
1929 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1930 "rectangle: %dx%d+%d+%d", width, height, x, y);
1931 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1932 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1934 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1936 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1938 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1943 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1944 int length, gboolean little_endian)
1946 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1947 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1949 gint16 x1, y1, x2, y2;
1953 x1 = VALUE16(tvb, *offsetp);
1954 y1 = VALUE16(tvb, *offsetp + 2);
1955 x2 = VALUE16(tvb, *offsetp + 4);
1956 y2 = VALUE16(tvb, *offsetp + 6);
1958 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1959 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1960 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1961 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1963 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1965 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1967 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1972 /* XXX - the protocol tree code should handle non-printable characters.
1973 Note that "non-printable characters" may depend on your locale.... */
1974 static void stringCopy(char *dest, const char *source, int length)
1979 if (!isgraph(c) && c != ' ') c = '.';
1985 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1986 int hf_item, int length, gboolean little_endian)
1989 guint allocated = 0;
1994 /* Compute total length */
1996 int scanning_offset = *offsetp; /* Scanning pointer */
1998 for(i = length; i; i--) {
1999 l = tvb_get_guint8(tvb, scanning_offset);
2000 scanning_offset += 1 + l;
2003 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2004 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2007 * In case we throw an exception, clean up whatever stuff we've
2008 * allocated (if any).
2010 CLEANUP_PUSH(g_free, s);
2013 unsigned l = VALUE8(tvb, *offsetp);
2014 if (allocated < (l + 1)) {
2015 /* g_realloc doesn't work ??? */
2017 s = g_malloc(l + 1);
2020 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2021 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2026 * Call the cleanup handler to free the string and pop the handler.
2028 CLEANUP_CALL_AND_POP;
2031 #define STRING16_MAX_DISPLAYED_LENGTH 150
2033 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2035 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2036 for(; length > 0; offset += 2, length--) {
2037 if (tvb_get_guint8(tvb, offset))
2043 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2045 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2046 int hf, int hf_bytes,
2047 int offset, unsigned length,
2048 char **s, int *sLength,
2049 gboolean little_endian)
2051 int truncated = FALSE;
2052 unsigned l = length / 2;
2054 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2056 int soffset = offset;
2058 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2060 l = STRING16_MAX_DISPLAYED_LENGTH;
2062 if (*sLength < (int) l + 3) {
2064 *s = g_malloc(l + 3);
2069 if (truncated) l -= 3;
2073 *dp++ = tvb_get_guint8(tvb, soffset);
2078 /* If truncated, add an ellipsis */
2079 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2082 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
2083 proto_registrar_get_nth(hf) -> name, *s);
2085 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2089 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2090 int sizeIs16, int next_offset, gboolean little_endian)
2098 /* Compute total length */
2100 int scanning_offset = *offsetp; /* Scanning pointer */
2101 int l; /* Length of an individual item */
2102 int n = 0; /* Number of items */
2104 while(scanning_offset < next_offset) {
2105 l = tvb_get_guint8(tvb, scanning_offset);
2109 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2112 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2113 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2116 * In case we throw an exception, clean up whatever stuff we've
2117 * allocated (if any).
2119 CLEANUP_PUSH(g_free, s);
2122 unsigned l = VALUE8(tvb, *offsetp);
2123 if (l == 255) { /* Item is a font */
2124 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2125 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2127 } else { /* Item is a string */
2130 gint8 delta = VALUE8(tvb, *offsetp + 1);
2131 if (sizeIs16) l += l;
2132 if ((unsigned) allocated < l + 1) {
2133 /* g_realloc doesn't work ??? */
2135 s = g_malloc(l + 1);
2138 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2139 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2140 "textitem (string): delta = %d, \"%s\"",
2142 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2143 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2145 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2146 hf_x11_textitem_string_string16_bytes,
2151 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2152 *offsetp + 2, l, s, "\"%s\"", s);
2158 * Call the cleanup handler to free the string and pop the handler.
2160 CLEANUP_CALL_AND_POP;
2163 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2164 gboolean little_endian)
2166 guint32 v = VALUE8(tvb, *offsetp);
2167 header_field_info *hfi = proto_registrar_get_nth(hf);
2168 gchar *enumValue = NULL;
2171 enumValue = match_strval(v, cVALS(hfi -> strings));
2173 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2174 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2175 hfi -> name, v, enumValue);
2177 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2182 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2183 gboolean little_endian)
2185 guint32 v = VALUE16(tvb, *offsetp);
2186 header_field_info *hfi = proto_registrar_get_nth(hf);
2187 gchar *enumValue = NULL;
2190 enumValue = match_strval(v, cVALS(hfi -> strings));
2192 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2193 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2194 hfi -> name, v, enumValue);
2196 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2201 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2202 gboolean little_endian)
2204 guint32 v = VALUE32(tvb, *offsetp);
2205 header_field_info *hfi = proto_registrar_get_nth(hf);
2206 gchar *enumValue = NULL;
2207 gchar *nameAsChar = hfi -> name;
2210 enumValue = match_strval(v, cVALS(hfi -> strings));
2212 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2213 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2214 nameAsChar, v, enumValue);
2216 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2217 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2223 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2224 gboolean little_endian)
2226 BITMASK32(gc_value);
2227 BITFIELD(ENUM8, gc_value_mask, function);
2228 BITFIELD(CARD32, gc_value_mask, plane_mask);
2229 BITFIELD(CARD32, gc_value_mask, foreground);
2230 BITFIELD(CARD32, gc_value_mask, background);
2231 BITFIELD(CARD16, gc_value_mask, line_width);
2232 BITFIELD(ENUM8, gc_value_mask, line_style);
2233 BITFIELD(ENUM8, gc_value_mask, cap_style);
2234 BITFIELD(ENUM8, gc_value_mask, join_style);
2235 BITFIELD(ENUM8, gc_value_mask, fill_style);
2236 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2237 BITFIELD(PIXMAP, gc_value_mask, tile);
2238 BITFIELD(PIXMAP, gc_value_mask, stipple);
2239 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2240 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2241 BITFIELD(FONT, gc_value_mask, font);
2242 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2243 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2244 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2245 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2246 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2247 BITFIELD(CARD16, gc_value_mask, dash_offset);
2248 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2249 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2253 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2254 gboolean little_endian)
2256 BITMASK32(gc_value);
2257 FLAG(gc_value, function);
2258 FLAG(gc_value, plane_mask);
2259 FLAG(gc_value, foreground);
2260 FLAG(gc_value, background);
2261 FLAG(gc_value, line_width);
2262 FLAG(gc_value, line_style);
2263 FLAG(gc_value, cap_style);
2264 FLAG(gc_value, join_style);
2265 FLAG(gc_value, fill_style);
2266 FLAG(gc_value, fill_rule);
2267 FLAG(gc_value, tile);
2268 FLAG(gc_value, stipple);
2269 FLAG(gc_value, tile_stipple_x_origin);
2270 FLAG(gc_value, tile_stipple_y_origin);
2271 FLAG(gc_value, font);
2272 FLAG(gc_value, subwindow_mode);
2273 FLAG(gc_value, graphics_exposures);
2274 FLAG(gc_value, clip_x_origin);
2275 FLAG(gc_value, clip_y_origin);
2276 FLAG(gc_value, clip_mask);
2277 FLAG(gc_value, dash_offset);
2278 FLAG(gc_value, gc_dashes);
2279 FLAG(gc_value, arc_mode);
2283 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2284 gboolean little_endian)
2286 guint32 res = VALUE16(tvb, *offsetp);
2287 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2292 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2293 gboolean little_endian)
2296 FLAG(event, KeyPress);
2297 FLAG(event, KeyRelease);
2298 FLAG(event, ButtonPress);
2299 FLAG(event, ButtonRelease);
2300 FLAG(event, EnterWindow);
2301 FLAG(event, LeaveWindow);
2302 FLAG(event, PointerMotion);
2303 FLAG(event, PointerMotionHint);
2304 FLAG(event, Button1Motion);
2305 FLAG(event, Button2Motion);
2306 FLAG(event, Button3Motion);
2307 FLAG(event, Button4Motion);
2308 FLAG(event, Button5Motion);
2309 FLAG(event, ButtonMotion);
2310 FLAG(event, KeymapState);
2311 FLAG(event, Exposure);
2312 FLAG(event, VisibilityChange);
2313 FLAG(event, StructureNotify);
2314 FLAG(event, ResizeRedirect);
2315 FLAG(event, SubstructureNotify);
2316 FLAG(event, SubstructureRedirect);
2317 FLAG(event, FocusChange);
2318 FLAG(event, PropertyChange);
2319 FLAG(event, ColormapChange);
2320 FLAG(event, OwnerGrabButton);
2321 FLAG_IF_NONZERO(event, erroneous_bits);
2325 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2326 gboolean little_endian)
2328 BITMASK32(do_not_propagate);
2329 FLAG(do_not_propagate, KeyPress);
2330 FLAG(do_not_propagate, KeyRelease);
2331 FLAG(do_not_propagate, ButtonPress);
2332 FLAG(do_not_propagate, ButtonRelease);
2333 FLAG(do_not_propagate, PointerMotion);
2334 FLAG(do_not_propagate, Button1Motion);
2335 FLAG(do_not_propagate, Button2Motion);
2336 FLAG(do_not_propagate, Button3Motion);
2337 FLAG(do_not_propagate, Button4Motion);
2338 FLAG(do_not_propagate, Button5Motion);
2339 FLAG(do_not_propagate, ButtonMotion);
2340 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2345 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2346 gboolean little_endian, gboolean butmask)
2349 guint32 bitmask_value;
2352 proto_tree *bitmask_tree;
2354 bitmask_value = VALUE16(tvb, *offsetp);
2355 bitmask_offset = *offsetp;
2358 if (!butmask && bitmask_value == 0x8000)
2359 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2360 "modifiers-masks: 0x8000 (AnyModifier)");
2362 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2364 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2365 FLAG(modifiers, Shift);
2366 FLAG(modifiers, Lock);
2367 FLAG(modifiers, Control);
2368 FLAG(modifiers, Mod1);
2369 FLAG(modifiers, Mod2);
2370 FLAG(modifiers, Mod3);
2371 FLAG(modifiers, Mod4);
2372 FLAG(modifiers, Mod5);
2375 FLAG(modifiers, Button1);
2376 FLAG(modifiers, Button2);
2377 FLAG(modifiers, Button3);
2378 FLAG(modifiers, Button4);
2379 FLAG(modifiers, Button5);
2383 FLAG_IF_NONZERO(keybut, erroneous_bits);
2385 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2390 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2391 gboolean little_endian)
2393 BITMASK16(pointer_event);
2394 FLAG(pointer_event, ButtonPress);
2395 FLAG(pointer_event, ButtonRelease);
2396 FLAG(pointer_event, EnterWindow);
2397 FLAG(pointer_event, LeaveWindow);
2398 FLAG(pointer_event, PointerMotion);
2399 FLAG(pointer_event, PointerMotionHint);
2400 FLAG(pointer_event, Button1Motion);
2401 FLAG(pointer_event, Button2Motion);
2402 FLAG(pointer_event, Button3Motion);
2403 FLAG(pointer_event, Button4Motion);
2404 FLAG(pointer_event, Button5Motion);
2405 FLAG(pointer_event, ButtonMotion);
2406 FLAG(pointer_event, KeymapState);
2407 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2411 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2412 int hf, unsigned length)
2417 p = tvb_get_ptr(tvb, *offsetp, length);
2418 s = g_malloc(length + 1);
2419 stringCopy(s, p, length);
2420 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2425 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2427 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2428 int hf_bytes, unsigned length, gboolean little_endian)
2434 * In case we throw an exception, clean up whatever stuff we've
2435 * allocated (if any).
2437 CLEANUP_PUSH(g_free, s);
2440 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2441 &s, &l, little_endian);
2444 * Call the cleanup handler to free the string and pop the handler.
2446 CLEANUP_CALL_AND_POP;
2451 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2452 gboolean little_endian)
2454 guint32 v = VALUE32(tvb, *offsetp);
2457 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2458 proto_registrar_get_nth(hf) -> name);
2460 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2464 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2465 gboolean little_endian)
2467 BITMASK32(window_value);
2468 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2469 BITFIELD(CARD32, window_value_mask, background_pixel);
2470 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2471 BITFIELD(CARD32, window_value_mask, border_pixel);
2472 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2473 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2474 BITFIELD(ENUM8, window_value_mask, backing_store);
2475 BITFIELD(CARD32, window_value_mask, backing_planes);
2476 BITFIELD(CARD32, window_value_mask, backing_pixel);
2477 BITFIELD(BOOL, window_value_mask, override_redirect);
2478 BITFIELD(BOOL, window_value_mask, save_under);
2479 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2480 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2481 BITFIELD(COLORMAP, window_value_mask, colormap);
2482 BITFIELD(CURSOR, window_value_mask, cursor);
2486 static void x11_init_protocol(void)
2488 if (x11_state_chunk != NULL)
2489 g_mem_chunk_destroy(x11_state_chunk);
2491 x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2492 sizeof (x11_conv_data_t),
2493 128 * sizeof (x11_conv_data_t),
2497 /************************************************************************
2499 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2501 ************************************************************************/
2503 /* If we can't guess, we return TRUE (that is little_endian), cause
2504 I'm developing on a Linux box :-). The (non-)guess isn't cached
2505 however, so we may have more luck next time. I'm quite conservative
2506 in my assertions, cause once it's cached, it's stay in cache, and
2507 we may be fooled up by a packet starting with the end of a request
2508 started in a previous packet...
2511 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2513 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2516 while(maskLength--) {
2517 int c = tvb_get_guint8(tvb, offset);
2519 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2524 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2526 if (listLength > length) return FALSE;
2527 while(listLength--) {
2529 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2530 l = tvb_get_guint8(tvb, offset);
2533 if (l > length) return FALSE;
2534 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2538 if (length > 3) return FALSE;
2542 static int rounded4(int n)
2544 int remainder = n % 4;
2546 if (remainder) res++;
2550 /* We assume the order to be consistent, until proven wrong. */
2552 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2554 switch(tvb_get_guint8(tvb, offset)) {
2555 case X_CreateWindow:
2556 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2558 case X_ChangeWindowAttributes:
2560 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2562 case X_GetWindowAttributes:
2563 case X_DestroyWindow:
2564 case X_DestroySubwindows:
2565 case X_ChangeSaveSet:
2567 case X_MapSubwindows:
2569 case X_UnmapSubwindows:
2570 case X_CirculateWindow:
2574 case X_ListProperties:
2575 case X_GetSelectionOwner:
2576 case X_UngrabPointer:
2577 case X_UngrabKeyboard:
2579 case X_QueryPointer:
2584 case X_FreeColormap:
2585 case X_InstallColormap:
2586 case X_UninstallColormap:
2587 case X_ListInstalledColormaps:
2589 case X_GetKeyboardMapping:
2593 case X_ReparentWindow:
2594 case X_SetSelectionOwner:
2595 case X_ChangeActivePointerGrab:
2596 case X_GrabKeyboard:
2598 case X_GetMotionEvents:
2599 case X_TranslateCoords:
2600 case X_CreatePixmap:
2603 case X_CreateColormap:
2605 case X_AllocColorPlanes:
2608 case X_ConfigureWindow:
2609 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2612 case X_QueryExtension:
2613 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2615 case X_ChangeProperty:
2617 int multiplier, type;
2618 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2619 type = tvb_get_guint8(tvb, 16);
2620 if (type != 8 && type != 16 && type != 32) return FALSE;
2621 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2622 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2623 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2626 case X_DeleteProperty:
2627 case X_UngrabButton:
2629 case X_SetInputFocus:
2630 case X_CopyColormapAndFree:
2631 case X_AllocColorCells:
2632 case X_QueryBestSize:
2633 case X_ChangePointerControl:
2634 case X_SetScreenSaver:
2638 case X_ConvertSelection:
2645 return length == 11;
2648 case X_UngrabServer:
2649 case X_GetInputFocus:
2652 case X_ListExtensions:
2653 case X_GetKeyboardControl:
2655 case X_GetPointerControl:
2656 case X_GetScreenSaver:
2658 case X_SetAccessControl:
2659 case X_SetCloseDownMode:
2660 case X_ForceScreenSaver:
2661 case X_GetPointerMapping:
2662 case X_GetModifierMapping:
2666 case X_AllocNamedColor:
2668 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2670 case X_QueryTextExtents:
2674 case X_ListFontsWithInfo:
2676 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2679 if (length < 2) return FALSE;
2680 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2681 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2684 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2687 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2689 case X_SetClipRectangles:
2691 case X_PolyRectangle:
2692 case X_PolyFillRectangle:
2693 return length >= 3 && (length - 3) % 2 == 0;
2699 case X_CreateCursor:
2700 case X_CreateGlyphCursor:
2710 return length >= 3 && (length - 3) % 3 == 0;
2720 case X_RecolorCursor:
2724 if (length < 4) return FALSE;
2725 return TRUE; /* We don't perform many controls on this one */
2728 if (length < 4) return FALSE;
2729 return TRUE; /* We don't perform many controls on this one */
2735 return length > 2 && (length - 2) % 3 == 0;
2737 case X_StoreNamedColor:
2738 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2743 case X_ChangeKeyboardMapping:
2744 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2746 case X_ChangeKeyboardControl:
2747 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2749 case X_RotateProperties:
2750 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2752 case X_SetPointerMapping:
2753 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2755 case X_SetModifierMapping:
2756 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2766 /* -1 means doesn't match, +1 means match, 0 means don't know */
2768 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2770 int offset, nextoffset;
2773 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2775 length = v16(tvb, offset + 2);
2776 if (!length) return -1;
2777 nextoffset = offset + length * 4;
2778 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2785 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2786 x11_conv_data_t *state)
2788 /* With X the client gives the byte ordering for the protocol,
2789 and the port on the server tells us we're speaking X. */
2791 int le, be, decision, decisionToCache;
2793 if (state->byte_order == BYTE_ORDER_BE)
2794 return FALSE; /* known to be big-endian */
2795 else if (state->byte_order == BYTE_ORDER_LE)
2796 return TRUE; /* known to be little-endian */
2798 if (pinfo->srcport == pinfo->match_port) {
2800 * This is a reply or event; we don't try to guess the
2801 * byte order on it for now.
2806 le = x_endian_match(tvb, tvb_get_letohs);
2807 be = x_endian_match(tvb, tvb_get_ntohs);
2809 /* remember that "decision" really means "little_endian". */
2811 /* We have no reason to believe it's little- rather than
2812 big-endian, so we guess the shortest length is the
2815 if (!tvb_bytes_exist(tvb, 0, 4))
2816 /* Not even a way to get the length. We're biased
2817 toward little endianness here (essentially the
2818 x86 world right now). Decoding won't go very far
2823 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2825 decision = le >= be;
2827 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2828 if (decisionToCache) {
2830 * Remember the decision.
2832 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2836 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2837 pinfo->fd -> num, le, be, decision, decisionToCache);
2842 /************************************************************************
2844 *** D E C O D I N G O N E P A C K E T ***
2846 ************************************************************************/
2849 * Decode an initial connection request.
2851 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2852 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2855 int *offsetp = &offset;
2858 guint16 auth_proto_name_length, auth_proto_data_length;
2861 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2862 proto_item_append_text(ti, ", Request, Initial connection request");
2863 t = proto_item_add_subtree(ti, ett_x11);
2867 CARD16(protocol_major_version);
2868 CARD16(protocol_minor_version);
2869 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2870 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2873 if (auth_proto_name_length != 0) {
2874 STRING8(authorization_protocol_name, auth_proto_name_length);
2875 offset = ROUND_LENGTH(offset);
2878 if (auth_proto_data_length != 0) {
2879 STRING8(authorization_protocol_data, auth_proto_data_length);
2880 offset = ROUND_LENGTH(offset);
2883 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2884 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2888 * This is the initial connection request...
2890 state->iconn_frame = pinfo->fd->num;
2893 * ...and we're expecting a reply to it.
2895 state->sequencenumber = 0;
2896 g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
2897 (int *)INITIAL_CONN);
2900 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2901 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2902 gboolean little_endian)
2904 int offset = 0, *offsetp = &offset, left;
2905 unsigned char success;
2906 int length_of_vendor;
2907 int length_of_reason;
2911 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2912 proto_item_append_text(ti, ", Reply, Initial connection reply");
2913 t = proto_item_add_subtree(ti, ett_x11);
2915 state->iconn_reply = pinfo->fd->num;
2916 success = INT8(success);
2919 length_of_reason = 0;
2922 length_of_reason = INT8(length_of_reason);
2925 INT16(protocol_major_version);
2926 INT16(protocol_minor_version);
2929 INT32(release_number);
2930 INT32(resource_id_base);
2931 INT32(resource_id_mask);
2932 INT32(motion_buffer_size);
2933 length_of_vendor = INT16(length_of_vendor);
2934 INT16(maximum_request_length);
2935 INT8(number_of_screens_in_roots);
2936 INT8(number_of_formats_in_pixmap_formats);
2937 INT8(image_byte_order);
2938 INT8(bitmap_format_bit_order);
2939 INT8(bitmap_format_scanline_unit);
2940 INT8(bitmap_format_scanline_pad);
2944 STRING8(vendor, length_of_vendor);
2946 STRING8(reason, length_of_reason);
2949 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2954 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2955 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2956 gboolean little_endian)
2959 int *offsetp = &offset;
2963 int length, opcode, i;
2964 guint8 v8, v8_2, v8_3;
2970 length = VALUE16(tvb, 2) * 4;
2973 /* Bogus message length? */
2977 next_offset = offset + length;
2979 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2980 t = proto_item_add_subtree(ti, ett_x11);
2982 if (PACKET_IS_NEW(pinfo))
2983 ++state->sequencenumber;
2987 if (check_col(pinfo->cinfo, COL_INFO))
2988 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2989 val_to_str(opcode, state->opcode_vals,
2990 "<Unknown opcode %d>"));
2992 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2993 opcode, val_to_str(opcode, state->opcode_vals,
2994 "<Unknown opcode %d>"));
2997 * Does this request expect a reply?
3001 case X_QueryExtension:
3003 /* necessary processing even if tree == NULL */
3005 v16 = VALUE16(tvb, 4);
3006 name = g_malloc(v16 + 1);
3007 stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
3009 /* store string of extension, opcode will be set at reply */
3011 while(i < MAX_OPCODES) {
3012 if (state->opcode_vals[i].strptr == NULL) {
3013 state->opcode_vals[i].strptr = name;
3014 g_hash_table_insert(state->valtable,
3015 (int *)state->sequencenumber,
3016 (int *)&state->opcode_vals[i]);
3018 } else if (strcmp(state->opcode_vals[i].strptr,
3020 g_hash_table_insert(state->valtable,
3021 (int *)state->sequencenumber,
3022 (int *)&state->opcode_vals[i]);
3028 /* QueryExtension expects a reply, fall through */
3031 case X_AllocColorCells:
3032 case X_AllocColorPlanes:
3033 case X_AllocNamedColor:
3038 case X_GetInputFocus:
3039 case X_GetKeyboardControl:
3040 case X_GetKeyboardMapping:
3041 case X_GetModifierMapping:
3042 case X_GetMotionEvents:
3043 case X_GetPointerControl:
3044 case X_GetPointerMapping:
3046 case X_GetScreenSaver:
3047 case X_GetSelectionOwner:
3048 case X_GetWindowAttributes:
3049 case X_GrabKeyboard:
3052 case X_ListExtensions:
3054 case X_ListFontsWithInfo:
3056 case X_ListInstalledColormaps:
3057 case X_ListProperties:
3059 case X_QueryBestSize:
3063 case X_QueryPointer:
3064 case X_QueryTextExtents:
3066 case X_SetModifierMapping:
3067 case X_SetPointerMapping:
3068 case X_TranslateCoords:
3070 * Those requests expect a reply.
3072 g_hash_table_insert(state->seqtable,
3073 (int *)state->sequencenumber,
3080 * With Extension, we don't know, so assume there could be one
3082 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3083 g_hash_table_insert(state->seqtable,
3084 (int *)state->sequencenumber,
3089 * No reply is expected from any other request.
3099 case X_CreateWindow:
3108 CARD16(border_width);
3109 ENUM16(window_class);
3111 windowAttributes(tvb, offsetp, t, little_endian);
3114 case X_ChangeWindowAttributes:
3118 windowAttributes(tvb, offsetp, t, little_endian);
3121 case X_GetWindowAttributes:
3122 case X_DestroyWindow:
3123 case X_DestroySubwindows:
3129 case X_ChangeSaveSet:
3130 ENUM8(save_set_mode);
3135 case X_ReparentWindow:
3145 case X_MapSubwindows:
3147 case X_UnmapSubwindows:
3153 case X_ConfigureWindow:
3157 BITMASK16(configure_window);
3159 BITFIELD(INT16, configure_window_mask, x);
3160 BITFIELD(INT16, configure_window_mask, y);
3161 BITFIELD(CARD16, configure_window_mask, width);
3162 BITFIELD(CARD16, configure_window_mask, height);
3163 BITFIELD(CARD16, configure_window_mask, border_width);
3164 BITFIELD(WINDOW, configure_window_mask, sibling);
3165 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3170 case X_CirculateWindow:
3184 BOOL(only_if_exists);
3186 v16 = FIELD16(name_length);
3198 case X_ChangeProperty:
3206 v32 = CARD32(data_length);
3207 LISTofBYTE(data, v32);
3211 case X_DeleteProperty:
3223 ATOM(get_property_type);
3224 CARD32(long_offset);
3225 CARD32(long_length);
3228 case X_ListProperties:
3234 case X_SetSelectionOwner:
3242 case X_GetSelectionOwner:
3248 case X_ConvertSelection:
3261 WINDOW(destination);
3262 SETofEVENT(event_mask);
3269 WINDOW(grab_window);
3270 SETofPOINTEREVENT(pointer_event_mask);
3271 ENUM8(pointer_mode);
3272 ENUM8(keyboard_mode);
3278 case X_UngrabPointer:
3287 WINDOW(grab_window);
3288 SETofPOINTEREVENT(event_mask);
3289 ENUM8(pointer_mode);
3290 ENUM8(keyboard_mode);
3295 SETofKEYMASK(modifiers);
3298 case X_UngrabButton:
3301 WINDOW(grab_window);
3302 SETofKEYMASK(modifiers);
3306 case X_ChangeActivePointerGrab:
3311 SETofPOINTEREVENT(event_mask);
3315 case X_GrabKeyboard:
3318 WINDOW(grab_window);
3320 ENUM8(pointer_mode);
3321 ENUM8(keyboard_mode);
3325 case X_UngrabKeyboard:
3334 WINDOW(grab_window);
3335 SETofKEYMASK(modifiers);
3337 ENUM8(pointer_mode);
3338 ENUM8(keyboard_mode);
3345 WINDOW(grab_window);
3346 SETofKEYMASK(modifiers);
3351 ENUM8(allow_events_mode);
3361 case X_UngrabServer:
3366 case X_QueryPointer:
3372 case X_GetMotionEvents:
3380 case X_TranslateCoords:
3392 WINDOW(warp_pointer_src_window);
3393 WINDOW(warp_pointer_dst_window);
3402 case X_SetInputFocus:
3409 case X_GetInputFocus:
3423 v16 = FIELD16(name_length);
3441 case X_QueryTextExtents:
3442 v8 = BOOL(odd_length);
3445 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3453 v16 = FIELD16(pattern_length);
3454 STRING8(pattern, v16);
3458 case X_ListFontsWithInfo:
3462 v16 = FIELD16(pattern_length);
3463 STRING8(pattern, v16);
3470 v16 = CARD16(str_number_in_path);
3472 LISTofSTRING8(path, v16);
3481 case X_CreatePixmap:
3501 gcAttributes(tvb, offsetp, t, little_endian);
3508 gcAttributes(tvb, offsetp, t, little_endian);
3516 gcMask(tvb, offsetp, t, little_endian);
3523 CARD16(dash_offset);
3524 v16 = FIELD16(dashes_length);
3525 LISTofCARD8(dashes, v16);
3529 case X_SetClipRectangles:
3533 INT16(clip_x_origin);
3534 INT16(clip_y_origin);
3535 LISTofRECTANGLE(rectangles);
3557 DRAWABLE(src_drawable);
3558 DRAWABLE(dst_drawable);
3571 DRAWABLE(src_drawable);
3572 DRAWABLE(dst_drawable);
3584 ENUM8(coordinate_mode);
3585 v16 = REQUEST_LENGTH();
3588 LISTofPOINT(points, v16 - 12);
3592 ENUM8(coordinate_mode);
3593 v16 = REQUEST_LENGTH();
3596 LISTofPOINT(points, v16 - 12);
3604 LISTofSEGMENT(segments);
3607 case X_PolyRectangle:
3612 LISTofRECTANGLE(rectangles);
3625 v16 = REQUEST_LENGTH();
3629 ENUM8(coordinate_mode);
3631 LISTofPOINT(points, v16 - 16);
3634 case X_PolyFillRectangle:
3639 LISTofRECTANGLE(rectangles);
3651 ENUM8(image_format);
3652 v16 = REQUEST_LENGTH();
3662 LISTofBYTE(data, v16 - 24);
3667 ENUM8(image_pixmap_format);
3679 v16 = REQUEST_LENGTH();
3684 LISTofTEXTITEM8(items);
3690 v16 = REQUEST_LENGTH();
3695 LISTofTEXTITEM16(items);
3700 v8 = FIELD8(string_length);
3706 STRING8(string, v8);
3711 v8 = FIELD8(string_length);
3717 STRING16(string16, v8);
3721 case X_CreateColormap:
3729 case X_FreeColormap:
3735 case X_CopyColormapAndFree:
3742 case X_InstallColormap:
3748 case X_UninstallColormap:
3754 case X_ListInstalledColormaps:
3770 case X_AllocNamedColor:
3774 v16 = FIELD16(name_length);
3780 case X_AllocColorCells:
3788 case X_AllocColorPlanes:
3800 v16 = REQUEST_LENGTH();
3803 LISTofCARD32(pixels, v16 - 12);
3808 v16 = REQUEST_LENGTH();
3810 LISTofCOLORITEM(color_items, v16 - 8);
3813 case X_StoreNamedColor:
3818 v16 = FIELD16(name_length);
3826 v16 = REQUEST_LENGTH();
3828 LISTofCARD32(pixels, v16 - 8);
3835 v16 = FIELD16(name_length);
3841 case X_CreateCursor:
3845 PIXMAP(source_pixmap);
3857 case X_CreateGlyphCursor:
3863 CARD16(source_char);
3879 case X_RecolorCursor:
3891 case X_QueryBestSize:
3899 case X_QueryExtension:
3902 v16 = FIELD16(name_length);
3908 case X_ListExtensions:
3913 case X_ChangeKeyboardMapping:
3914 v8 = FIELD8(keycode_count);
3916 v8_2 = KEYCODE(first_keycode);
3917 v8_3 = FIELD8(keysyms_per_keycode);
3919 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3922 case X_GetKeyboardMapping:
3925 state->request.GetKeyboardMapping.first_keycode
3926 = KEYCODE(first_keycode);
3931 case X_ChangeKeyboardControl:
3934 BITMASK32(keyboard_value);
3935 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3936 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3937 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3938 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3939 BITFIELD(INT16, keyboard_value_mask, led);
3940 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3941 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3942 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3946 case X_GetKeyboardControl:
3956 case X_ChangePointerControl:
3959 INT16(acceleration_numerator);
3960 INT16(acceleration_denominator);
3962 BOOL(do_acceleration);
3966 case X_GetPointerControl:
3971 case X_SetScreenSaver:
3976 ENUM8(prefer_blanking);
3977 ENUM8(allow_exposures);
3981 case X_GetScreenSaver:
3987 ENUM8(change_host_mode);
3991 v16 = CARD16(address_length);
3992 if (v8 == FAMILY_INTERNET && v16 == 4) {
3995 * XXX - what about IPv6? Is that a family of
3996 * FAMILY_INTERNET (0) with a length of 16?
3998 LISTofCARD8(ip_address, v16);
4000 LISTofCARD8(address, v16);
4008 case X_SetAccessControl:
4013 case X_SetCloseDownMode:
4014 ENUM8(close_down_mode);
4024 case X_RotateProperties:
4026 v16 = REQUEST_LENGTH();
4028 CARD16(property_number);
4030 LISTofATOM(properties, (v16 - 12));
4033 case X_ForceScreenSaver:
4034 ENUM8(screen_saver_mode);
4038 case X_SetPointerMapping:
4039 v8 = FIELD8(map_length);
4041 LISTofCARD8(map, v8);
4045 case X_GetPointerMapping:
4050 case X_SetModifierMapping:
4051 v8 = FIELD8(keycodes_per_modifier);
4053 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4056 case X_GetModifierMapping:
4067 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4071 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4074 volatile int offset = 0;
4075 int length_remaining;
4076 volatile gboolean little_endian;
4081 volatile gboolean is_initial_creq;
4082 guint16 auth_proto_len, auth_data_len;
4083 const char *volatile sep = NULL;
4084 conversation_t *conversation;
4085 x11_conv_data_t *state;
4089 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4091 * We use "tvb_ensure_length_remaining()" to make sure there
4092 * actually *is* data remaining.
4094 * This means we're guaranteed that "length_remaining" is
4097 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4100 * Can we do reassembly?
4102 if (x11_desegment && pinfo->can_desegment) {
4104 * Yes - is the X11 request header split across
4105 * segment boundaries?
4107 if (length_remaining < 4) {
4109 * Yes. Tell the TCP dissector where the data
4110 * for this message starts in the data it handed
4111 * us, and how many more bytes we need, and return.
4113 pinfo->desegment_offset = offset;
4114 pinfo->desegment_len = 4 - length_remaining;
4120 * Get the state for this conversation; create the conversation
4121 * if we don't have one, and create the state if we don't have
4124 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4125 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4126 if (conversation == NULL) {
4130 conversation = conversation_new(&pinfo->src,
4131 &pinfo->dst, pinfo->ptype, pinfo->srcport,
4132 pinfo->destport, 0);
4136 * Is there state attached to this conversation?
4138 if ((state = conversation_get_proto_data(conversation, proto_x11))
4140 x11_stateinit(&state, conversation);
4143 * Guess the byte order if we don't already know it.
4145 little_endian = guess_byte_ordering(tvb, pinfo, state);
4148 * Get the opcode and length of the putative X11 request.
4150 opcode = VALUE8(tvb, 0);
4151 plen = VALUE16(tvb, offset + 2);
4155 * This can't be 0, as it includes the header length.
4156 * A different choice of byte order wouldn't have
4160 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4162 t = proto_item_add_subtree(ti, ett_x11);
4163 proto_tree_add_text(t, tvb, offset, -1,
4164 "Bogus request length (0)");
4168 if (state->iconn_frame == pinfo->fd->num ||
4169 (g_hash_table_lookup(state->seqtable,
4170 (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
4171 (opcode == 'B' || opcode == 'l') &&
4172 (plen == 11 || plen == 2816))) {
4176 * we saw this on the first pass and this is
4180 * we haven't already seen any requests, the first
4181 * byte of the message is 'B' or 'l', and the 16-bit
4182 * integer 2 bytes into the data stream is either 11
4183 * or a byte-swapped 11.
4185 * This means it's probably an initial connection
4186 * request, not a message.
4188 * 'B' is decimal 66, which is the opcode for a
4189 * PolySegment request; unfortunately, 11 is a valid
4190 * length for a PolySegment request request, so we
4191 * might mis-identify that request. (Are there any
4192 * other checks we can do?)
4194 * 'l' is decimal 108, which is the opcode for a
4195 * GetScreenSaver request; the only valid length
4196 * for that request is 1.
4198 is_initial_creq = TRUE;
4201 * We now know the byte order. Override the guess.
4203 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4204 if (opcode == 'B') {
4208 state->byte_order = BYTE_ORDER_BE;
4209 little_endian = FALSE;
4214 state->byte_order = BYTE_ORDER_LE;
4215 little_endian = TRUE;
4220 * Can we do reassembly?
4222 if (x11_desegment && pinfo->can_desegment) {
4224 * Yes - is the fixed-length portion of the
4225 * initial connection header split across
4226 * segment boundaries?
4228 if (length_remaining < 10) {
4230 * Yes. Tell the TCP dissector where the
4231 * data for this message starts in the data
4232 * it handed us, and how many more bytes we
4235 pinfo->desegment_offset = offset;
4236 pinfo->desegment_len = 10 - length_remaining;
4242 * Get the lengths of the authorization protocol and
4243 * the authorization data.
4245 auth_proto_len = VALUE16(tvb, offset + 6);
4246 auth_data_len = VALUE16(tvb, offset + 8);
4247 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4248 ROUND_LENGTH(auth_data_len);
4251 * This is probably an ordinary request.
4253 is_initial_creq = FALSE;
4256 * The length of a request is in 4-byte words.
4262 * Can we do reassembly?
4264 if (x11_desegment && pinfo->can_desegment) {
4266 * Yes - is the X11 request split across segment
4269 if (length_remaining < plen) {
4271 * Yes. Tell the TCP dissector where the data
4272 * for this message starts in the data it handed
4273 * us, and how many more bytes we need, and return.
4275 pinfo->desegment_offset = offset;
4276 pinfo->desegment_len = plen - length_remaining;
4282 * Construct a tvbuff containing the amount of the payload
4283 * we have available. Make its reported length the
4284 * amount of data in the X11 request.
4286 * XXX - if reassembly isn't enabled. the subdissector
4287 * will throw a BoundsError exception, rather than a
4288 * ReportedBoundsError exception. We really want a tvbuff
4289 * where the length is "length", the reported length is "plen",
4290 * and the "if the snapshot length were infinite" length is the
4291 * minimum of the reported length of the tvbuff handed to us
4292 * and "plen", with a new type of exception thrown if the offset
4293 * is within the reported length but beyond that third length,
4294 * with that exception getting the "Unreassembled Packet" error.
4296 length = length_remaining;
4299 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4302 * Set the column appropriately.
4304 if (is_initial_creq) {
4305 if (check_col(pinfo->cinfo, COL_INFO))
4306 col_set_str(pinfo->cinfo, COL_INFO,
4307 "Initial connection request");
4311 * We haven't set the column yet; set it.
4313 if (check_col(pinfo->cinfo, COL_INFO))
4314 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4317 * Initialize the separator.
4324 * Dissect the X11 request.
4326 * Catch the ReportedBoundsError exception; if this
4327 * particular message happens to get a ReportedBoundsError
4328 * exception, that doesn't mean that we should stop
4329 * dissecting X11 requests within this frame or chunk of
4332 * If it gets a BoundsError, we can stop, as there's nothing
4333 * more to see, so we just re-throw it.
4336 if (is_initial_creq) {
4337 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4338 state, little_endian);
4340 dissect_x11_request(next_tvb, pinfo, tree, sep,
4341 state, little_endian);
4344 CATCH(BoundsError) {
4347 CATCH(ReportedBoundsError) {
4348 show_reported_bounds_error(tvb, pinfo, tree);
4353 * Skip the X11 message.
4362 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4364 static x11_conv_data_t stateinit;
4367 *state = g_mem_chunk_alloc(x11_state_chunk);
4368 **state = stateinit;
4370 /* initialise opcodes */
4372 if (opcode_vals[i].strptr == NULL) break;
4373 (*state)->opcode_vals[i].value = opcode_vals[i].value;
4374 (*state)->opcode_vals[i].strptr = opcode_vals[i].strptr;
4377 while (i <= MAX_OPCODES) {
4378 (*state)->opcode_vals[i].value = 0;
4379 (*state)->opcode_vals[i].strptr = NULL;
4383 (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4384 (*state)->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4385 g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4386 (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4387 conversation_add_proto_data(conversation, proto_x11, *state);
4392 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4394 /* Set up structures we will need to add the protocol subtree and manage it */
4395 volatile int offset, plen;
4396 tvbuff_t * volatile next_tvb;
4397 conversation_t *conversation;
4398 x11_conv_data_t *state;
4399 gboolean little_endian;
4400 int length_remaining;
4401 const char *volatile sep = NULL;
4405 * Get the state for this conversation; create the conversation
4406 * if we don't have one, and create the state if we don't have
4409 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4410 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4411 if (conversation == NULL) {
4415 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4416 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4420 * Is there state attached to this conversation?
4422 if ((state = conversation_get_proto_data(conversation, proto_x11))
4425 * No - create a state structure and attach it.
4427 x11_stateinit(&state, conversation);
4431 * Guess the byte order if we don't already know it.
4433 little_endian = guess_byte_ordering(tvb, pinfo, state);
4436 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4438 * We use "tvb_ensure_length_remaining()" to make sure there
4439 * actually *is* data remaining.
4441 * This means we're guaranteed that "length_remaining" is
4444 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4447 * Can we do reassembly?
4449 if (x11_desegment && pinfo->can_desegment) {
4451 * Yes - is the X11 reply header split across
4452 * segment boundaries?
4454 if (length_remaining < 8) {
4456 * Yes. Tell the TCP dissector where the data
4457 * for this message starts in the data it handed
4458 * us, and how many more bytes we need, and
4461 pinfo->desegment_offset = offset;
4462 pinfo->desegment_len = 4 - length_remaining;
4468 * Find out what kind of a reply it is.
4469 * There are four possible:
4470 * - reply to initial connection
4471 * - errorreply (a request generated an error)
4472 * - requestreply (reply to a request)
4473 * - event (some event occured)
4475 if (g_hash_table_lookup(state->seqtable,
4476 (int *)state->sequencenumber) == (int *)INITIAL_CONN
4477 || (state->iconn_reply == pinfo->fd->num)) {
4479 * Either the connection is in the "initial
4480 * connection" state, or this frame is known
4481 * to have the initial connection reply.
4482 * That means this is the initial connection
4485 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4487 HANDLE_REPLY(plen, length_remaining,
4488 "Initial connection reply",
4489 dissect_x11_initial_reply);
4492 * This isn't an initial connection reply
4493 * (XXX - unless we missed the initial
4494 * connection request). Look at the first
4495 * byte to determine what it is; errors
4496 * start with a byte of 0, replies start
4497 * with a byte of 1, events start with
4498 * a byte with of 2 or greater.
4500 switch (tvb_get_guint8(tvb, offset)) {
4504 HANDLE_REPLY(plen, length_remaining,
4505 "Error", dissect_x11_error);
4509 /* replylength is in units of four. */
4510 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4512 HANDLE_REPLY(plen, length_remaining,
4513 "Reply", dissect_x11_reply);
4519 HANDLE_REPLY(plen, length_remaining,
4520 "Event", dissect_x11_event);
4532 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4533 const char *volatile sep, x11_conv_data_t *volatile state,
4534 gboolean little_endian)
4536 int offset = 0, *offsetp = &offset, length, left, opcode;
4537 int major_opcode, sequence_number;
4538 value_string *vals_p;
4542 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4543 tvb_reported_length_remaining(tvb, offset),
4545 t = proto_item_add_subtree(ti, ett_x11);
4549 * XXX - this doesn't work correctly if either
4551 * 1) the request sequence number wraps in the lower 16
4554 * 2) we don't see the initial connection request and the
4555 * resynchronization of sequence number fails and thus
4556 * don't have the right sequence numbers
4558 * 3) we don't have all the packets in the capture and
4559 * get out of sequence.
4561 * We might, instead, want to assume that a reply is a reply to
4562 * the most recent not-already-replied-to request in the same
4563 * connection. That also might mismatch replies to requests if
4564 * packets are lost, but there's nothing you can do to fix that.
4567 sequence_number = VALUE16(tvb, offset + 2);
4568 opcode = (int)g_hash_table_lookup(state->seqtable,
4569 (int *)sequence_number);
4571 if (state->iconn_frame == 0 && state->resync == FALSE) {
4574 * We don't see the initial connection request and no
4575 * resynchronization has been performed yet (first reply),
4576 * set the current sequence number to the one of the
4577 * current reply (this is only performed once).
4579 state->sequencenumber = sequence_number;
4580 state->resync = TRUE;
4583 if (opcode == UNKNOWN_OPCODE) {
4584 if (check_col(pinfo->cinfo, COL_INFO))
4585 col_append_fstr(pinfo->cinfo, COL_INFO,
4586 "%s to unknown request", sep);
4587 proto_item_append_text(ti, ", Reply to unknown request");
4589 if (check_col(pinfo->cinfo, COL_INFO))
4590 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4592 val_to_str(opcode, state->opcode_vals,
4593 "<Unknown opcode %d>"));
4595 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4596 opcode, val_to_str(opcode,
4598 "<Unknown opcode %d>"));
4604 * Replies that need special processing outside tree
4607 case X_QueryExtension:
4610 * if extension is present and request is known:
4611 * store opcode of extension in value_string of
4614 if (!VALUE8(tvb, offset + 8)) {
4619 vals_p = g_hash_table_lookup(state->valtable,
4620 (int *)sequence_number);
4621 if (vals_p != NULL) {
4622 major_opcode = VALUE8(tvb, offset + 9);
4623 vals_p->value = major_opcode;
4624 g_hash_table_remove(state->valtable,
4625 (int *)sequence_number);
4638 * Requests that expect a reply.
4641 case X_GetWindowAttributes:
4642 REPLYCONTENTS_COMMON();
4648 SEQUENCENUMBER_REPLY(sequencenumber);
4649 REPLYLENGTH(replylength);
4655 CARD16(border_width);
4660 REPLYCONTENTS_COMMON();
4666 SEQUENCENUMBER_REPLY(sequencenumber);
4667 REPLYLENGTH(replylength);
4673 REPLYCONTENTS_COMMON();
4679 SEQUENCENUMBER_REPLY(sequencenumber);
4680 length = REPLYLENGTH(replylength);
4681 ATOM(get_property_type);
4682 CARD32(bytes_after);
4683 CARD32(valuelength);
4687 case X_ListProperties:
4690 SEQUENCENUMBER_REPLY(sequencenumber);
4691 REPLYLENGTH(replylength);
4692 length = CARD16(property_number);
4694 LISTofATOM(properties, length*4);
4697 case X_GetSelectionOwner:
4700 SEQUENCENUMBER_REPLY(sequencenumber);
4701 REPLYLENGTH(replylength);
4707 case X_GrabKeyboard:
4710 SEQUENCENUMBER_REPLY(sequencenumber);
4711 REPLYLENGTH(replylength);
4715 case X_QueryPointer:
4718 SEQUENCENUMBER_REPLY(sequencenumber);
4719 REPLYLENGTH(replylength);
4721 WINDOW(childwindow);
4726 SETofKEYBUTMASK(mask);
4730 case X_GetMotionEvents:
4731 REPLYCONTENTS_COMMON();
4734 case X_TranslateCoords:
4737 SEQUENCENUMBER_REPLY(sequencenumber);
4738 REPLYLENGTH(replylength);
4739 WINDOW(childwindow);
4745 case X_GetInputFocus:
4748 SEQUENCENUMBER_REPLY(sequencenumber);
4749 REPLYLENGTH(replylength);
4757 SEQUENCENUMBER_REPLY(sequencenumber);
4758 REPLYLENGTH(replylength);
4759 LISTofCARD8(keys, 32);
4763 case X_QueryTextExtents:
4766 case X_ListInstalledColormaps:
4767 REPLYCONTENTS_COMMON();
4773 SEQUENCENUMBER_REPLY(sequencenumber);
4774 REPLYLENGTH(replylength);
4784 REPLYCONTENTS_COMMON();
4790 SEQUENCENUMBER_REPLY(sequencenumber);
4791 REPLYLENGTH(replylength);
4793 CARD16(exact_green);
4796 CARD16(visual_green);
4797 CARD16(visual_blue);
4801 case X_QueryBestSize:
4804 SEQUENCENUMBER_REPLY(sequencenumber);
4805 REPLYLENGTH(replylength);
4811 case X_QueryExtension:
4814 SEQUENCENUMBER_REPLY(sequencenumber);
4815 REPLYLENGTH(replylength);
4817 CARD8(major_opcode);
4823 case X_ListExtensions:
4824 REPLYCONTENTS_COMMON();
4827 case X_GetKeyboardMapping:
4828 state->first_keycode =
4829 state->request.GetKeyboardMapping.first_keycode;
4831 state->keysyms_per_keycode =
4832 FIELD8(keysyms_per_keycode);
4833 SEQUENCENUMBER_REPLY(sequencenumber);
4834 length = REPLYLENGTH(replylength);
4836 LISTofKEYSYM(keysyms, state->keycodemap,
4837 state->request.GetKeyboardMapping.first_keycode,
4838 length / state->keysyms_per_keycode,
4839 state->keysyms_per_keycode);
4842 case X_GetKeyboardControl:
4843 REPLYCONTENTS_COMMON();
4846 case X_GetPointerControl:
4849 SEQUENCENUMBER_REPLY(sequencenumber);
4850 REPLYLENGTH(replylength);
4851 CARD16(acceleration_numerator);
4852 CARD16(acceleration_denominator);
4857 case X_GetScreenSaver:
4860 SEQUENCENUMBER_REPLY(sequencenumber);
4861 REPLYLENGTH(replylength);
4864 ENUM8(prefer_blanking);
4865 ENUM8(allow_exposures);
4870 case X_SetPointerMapping:
4871 case X_GetPointerMapping:
4872 case X_SetModifierMapping:
4873 REPLYCONTENTS_COMMON();
4876 case X_GetModifierMapping:
4878 state->keycodes_per_modifier =
4879 FIELD8(keycodes_per_modifier);
4880 SEQUENCENUMBER_REPLY(sequencenumber);
4881 REPLYLENGTH(replylength);
4883 LISTofKEYCODE(state->modifiermap, keycodes,
4884 state->keycodes_per_modifier);
4888 REPLYCONTENTS_COMMON();
4891 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4896 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4899 guint32 bitmask_value;
4902 proto_tree *bitmask_tree;
4904 bitmask_value = VALUE8(tvb, *offsetp);
4905 bitmask_offset = *offsetp;
4908 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4910 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4911 FLAG(same_screen_focus, focus);
4912 FLAG(same_screen_focus, same_screen);
4918 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4919 const char *volatile sep, x11_conv_data_t *volatile state,
4920 gboolean little_endian)
4922 int offset = 0, *offsetp = &offset, left;
4923 unsigned char eventcode;
4927 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4928 t = proto_item_add_subtree(ti, ett_x11);
4930 eventcode = tvb_get_guint8(tvb, offset);
4932 if (check_col(pinfo->cinfo, COL_INFO))
4933 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4934 sep, val_to_str(eventcode, eventcode_vals,
4935 "<Unknown eventcode %u>"));
4937 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4939 "eventcode: %d (%s)",
4941 val_to_str(eventcode, eventcode_vals,
4942 "<Unknown eventcode %u>"));
4945 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4946 eventcode, val_to_str(eventcode, eventcode_vals,
4947 "<Unknown eventcode %u>"));
4952 switch (eventcode) {
4957 /* need to do some prefetching here ... */
4958 code = VALUE8(tvb, offset);
4959 mask = VALUE16(tvb, 28);
4961 KEYCODE_DECODED(keycode, code, mask);
4962 CARD16(event_sequencenumber);
4963 EVENTCONTENTS_COMMON();
4971 BUTTON(eventbutton);
4972 CARD16(event_sequencenumber);
4973 EVENTCONTENTS_COMMON();
4980 CARD16(event_sequencenumber);
4981 EVENTCONTENTS_COMMON();
4988 ENUM8(event_detail);
4989 CARD16(event_sequencenumber);
4990 EVENTCONTENTS_COMMON();
4992 same_screen_focus(tvb, offsetp, t);
4997 ENUM8(focus_detail);
4998 CARD16(event_sequencenumber);
4999 WINDOW(eventwindow);
5009 CARD16(event_sequencenumber);
5010 WINDOW(eventwindow);
5019 case GraphicsExpose:
5021 CARD16(event_sequencenumber);
5027 CARD16(minor_opcode);
5029 CARD8(major_opcode);
5035 CARD16(event_sequencenumber);
5037 CARD16(minor_opcode);
5038 CARD8(major_opcode);
5042 case VisibilityNotify:
5044 CARD16(event_sequencenumber);
5045 WINDOW(eventwindow);
5046 ENUM8(visibility_state);
5052 CARD16(event_sequencenumber);
5054 WINDOW(eventwindow);
5059 CARD16(border_width);
5060 BOOL(override_redirect);
5066 CARD16(event_sequencenumber);
5067 WINDOW(eventwindow);
5074 CARD16(event_sequencenumber);
5075 WINDOW(eventwindow);
5077 BOOL(from_configure);
5083 CARD16(event_sequencenumber);
5084 WINDOW(eventwindow);
5086 BOOL(override_redirect);
5092 CARD16(event_sequencenumber);
5094 WINDOW(eventwindow);
5098 case ReparentNotify:
5100 CARD16(event_sequencenumber);
5101 WINDOW(eventwindow);
5106 BOOL(override_redirect);
5110 case ConfigureNotify:
5112 CARD16(event_sequencenumber);
5113 WINDOW(eventwindow);
5115 WINDOW(above_sibling);
5120 CARD16(border_width);
5121 BOOL(override_redirect);
5125 case ConfigureRequest:
5130 CARD16(event_sequencenumber);
5131 WINDOW(eventwindow);
5140 CARD16(event_sequencenumber);
5141 WINDOW(eventwindow);
5147 case CirculateNotify:
5149 CARD16(event_sequencenumber);
5150 WINDOW(eventwindow);
5157 case CirculateRequest:
5159 CARD16(event_sequencenumber);
5161 WINDOW(eventwindow);
5167 case PropertyNotify:
5169 CARD16(event_sequencenumber);
5170 WINDOW(eventwindow);
5173 ENUM8(property_state);
5177 case SelectionClear:
5179 CARD16(event_sequencenumber);
5186 case SelectionRequest:
5188 CARD16(event_sequencenumber);
5198 case SelectionNotify:
5200 CARD16(event_sequencenumber);
5209 case ColormapNotify:
5211 CARD16(event_sequencenumber);
5212 WINDOW(eventwindow);
5215 ENUM8(colormap_state);
5221 CARD16(event_sequencenumber);
5222 WINDOW(eventwindow);
5224 LISTofBYTE(data, 20);
5232 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5239 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5240 const char *volatile sep, x11_conv_data_t *volatile state _U_,
5241 gboolean little_endian)
5243 int offset = 0, *offsetp = &offset, left;
5244 unsigned char errorcode, error;
5248 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5249 t = proto_item_add_subtree(ti, ett_x11);
5251 error = tvb_get_guint8(tvb, offset);
5254 errorcode = tvb_get_guint8(tvb, offset);
5255 if (check_col(pinfo->cinfo, COL_INFO))
5256 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5257 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5259 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5261 "errorcode: %d (%s)",
5263 val_to_str(errorcode, errorcode_vals,
5264 "<Unknown errocode %u>"));
5267 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
5268 errorcode, val_to_str(errorcode, errorcode_vals,
5269 "<Unknown errorcode %u>"));
5274 CARD16(error_sequencenumber);
5276 switch (errorcode) {
5278 CARD32(error_badvalue);
5285 CARD16(minor_opcode);
5286 CARD8(major_opcode);
5288 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5294 /************************************************************************
5296 *** I N I T I A L I Z A T I O N A N D M A I N ***
5298 ************************************************************************/
5301 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5303 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5304 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5306 if (pinfo->match_port == pinfo->srcport)
5307 dissect_x11_replies(tvb, pinfo, tree);
5309 dissect_x11_requests(tvb, pinfo, tree);
5312 /* Register the protocol with Ethereal */
5313 void proto_register_x11(void)
5316 /* Setup list of header fields */
5317 static hf_register_info hf[] = {
5318 #include "x11-register-info.h"
5321 /* Setup protocol subtree array */
5322 static gint *ett[] = {
5324 &ett_x11_color_flags,
5325 &ett_x11_list_of_arc,
5327 &ett_x11_list_of_atom,
5328 &ett_x11_list_of_card32,
5329 &ett_x11_list_of_color_item,
5330 &ett_x11_color_item,
5331 &ett_x11_list_of_keycode,
5332 &ett_x11_list_of_keysyms,
5334 &ett_x11_list_of_point,
5336 &ett_x11_list_of_rectangle,
5338 &ett_x11_list_of_segment,
5340 &ett_x11_list_of_string8,
5341 &ett_x11_list_of_text_item,
5343 &ett_x11_gc_value_mask,
5344 &ett_x11_event_mask,
5345 &ett_x11_do_not_propagate_mask,
5346 &ett_x11_set_of_key_mask,
5347 &ett_x11_pointer_event_mask,
5348 &ett_x11_window_value_mask,
5349 &ett_x11_configure_window_mask,
5350 &ett_x11_keyboard_value_mask,
5351 &ett_x11_same_screen_focus,
5353 module_t *x11_module;
5355 /* Register the protocol name and description */
5356 proto_x11 = proto_register_protocol("X11", "X11", "x11");
5358 /* Required function calls to register the header fields and subtrees used */
5359 proto_register_field_array(proto_x11, hf, array_length(hf));
5360 proto_register_subtree_array(ett, array_length(ett));
5362 register_init_routine(x11_init_protocol);
5364 x11_module = prefs_register_protocol(proto_x11, NULL);
5365 prefs_register_bool_preference(x11_module, "desegment",
5366 "Desegment all X11 messages spanning multiple TCP segments",
5367 "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
5372 proto_reg_handoff_x11(void)
5374 dissector_handle_t x11_handle;
5376 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5377 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5378 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5379 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
5380 data_handle = find_dissector("data");