2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
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>
67 #include <epan/prefs.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 LISTofIPADDRESS(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), FALSE); }
1133 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1134 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1135 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1136 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1137 keysyms_per_keycode) {\
1138 listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1139 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1140 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1141 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1142 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1143 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1144 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1145 #define OPCODE() { opcode = FIELD8(opcode); }
1146 #define PIXMAP(name) { FIELD32(name); }
1147 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1148 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1149 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1150 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1151 #define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 1); }
1152 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1153 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1154 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1155 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1156 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
1157 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
1158 #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; }
1159 #define WINDOW(name) { FIELD32(name); }
1160 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1162 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1163 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1164 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1165 #define REPLY(name) FIELD8(name);
1166 #define REPLYLENGTH(name) FIELD32(name);
1168 #define EVENTCONTENTS_COMMON() do { \
1170 WINDOW(rootwindow); \
1171 WINDOW(eventwindow); \
1172 WINDOW(childwindow); \
1177 setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
1180 #define SEQUENCENUMBER_REPLY(name) do { \
1183 seqno = VALUE16(tvb, *offsetp); \
1184 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1185 *offsetp, sizeof(seqno), seqno, \
1186 "sequencenumber: %d (%s)", \
1188 val_to_str(opcode, state->opcode_vals, "<Unknown opcode %d>")); \
1189 *offsetp += sizeof(seqno); \
1192 #define REPLYCONTENTS_COMMON() do { \
1194 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1195 1, little_endian); \
1197 SEQUENCENUMBER_REPLY(sequencenumber); \
1198 REPLYLENGTH(replylength); \
1199 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1200 tvb_reported_length_remaining(tvb, offset), little_endian); \
1201 offset += tvb_reported_length_remaining(tvb, offset); \
1205 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1206 if (length_remaining < plen) { \
1207 if (x11_desegment && pinfo->can_desegment) { \
1208 pinfo->desegment_offset = offset; \
1209 pinfo->desegment_len = plen - length_remaining;\
1212 ; /* XXX yes, what then? Need to skip/join. */ \
1215 if (length_remaining > plen) \
1216 length_remaining = plen; \
1217 next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1219 if (sep == NULL) { \
1220 if (check_col(pinfo->cinfo, COL_INFO)) \
1221 col_add_str(pinfo->cinfo, COL_INFO, str); \
1226 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1229 CATCH(BoundsError) { \
1232 CATCH(ReportedBoundsError) { \
1233 show_reported_bounds_error(next_tvb, pinfo, tree); \
1241 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1242 const char *sep, x11_conv_data_t *volatile state,
1243 gboolean little_endian);
1246 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1247 const char *volatile sep, x11_conv_data_t *volatile state,
1248 gboolean little_endian);
1251 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1252 const char *volatile sep, x11_conv_data_t *volatile state,
1253 gboolean little_endian);
1256 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1257 const char *volatile sep, x11_conv_data_t *volatile state,
1258 gboolean little_endian);
1261 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation);
1264 keysymString(guint32 v);
1267 /************************************************************************
1269 *** D E C O D I N G F I E L D S ***
1271 ************************************************************************/
1273 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1274 gboolean little_endian)
1276 const char *interpretation = NULL;
1278 guint32 v = VALUE32(tvb, *offsetp);
1279 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1280 interpretation = atom_predefined_interpretation[v];
1282 interpretation = "Not a predefined atom";
1284 header_field_info *hfi = proto_registrar_get_nth(hf);
1286 interpretation = match_strval(v, cVALS(hfi -> strings));
1288 if (!interpretation) interpretation = "error in Xlib client program ?";
1289 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1290 proto_registrar_get_nth(hf) -> name, v, interpretation);
1294 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1296 guint32 v = VALUE8(tvb, *offsetp);
1297 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1302 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1304 unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1308 if (do_red_green_blue) {
1311 char *bp = buffer + sprintf(buffer, "flags: ");
1313 if (do_red_green_blue & 0x1) {
1314 bp += sprintf(bp, "DoRed");
1318 if (do_red_green_blue & 0x2) {
1319 if (sep) bp += sprintf(bp, " | ");
1320 bp += sprintf(bp, "DoGreen");
1324 if (do_red_green_blue & 0x4) {
1325 if (sep) bp += sprintf(bp, " | ");
1326 bp += sprintf(bp, "DoBlue");
1330 if (do_red_green_blue & 0xf8) {
1331 if (sep) bp += sprintf(bp, " + ");
1332 sprintf(bp, "trash");
1335 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1337 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1338 if (do_red_green_blue & 0x1)
1339 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1340 do_red_green_blue & 0x1);
1341 if (do_red_green_blue & 0x2)
1342 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1343 do_red_green_blue & 0x2);
1344 if (do_red_green_blue & 0x4)
1345 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1346 do_red_green_blue & 0x4);
1347 if (do_red_green_blue & 0xf8)
1348 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1349 do_red_green_blue & 0xf8);
1351 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1356 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1357 int hf, const char *nullInterpretation)
1359 guint8 v = VALUE8(tvb, *offsetp);
1362 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1363 proto_registrar_get_nth(hf) -> name,
1364 nullInterpretation);
1366 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1370 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1371 int length, gboolean little_endian)
1373 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1374 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1376 gint16 x = VALUE16(tvb, *offsetp);
1377 gint16 y = VALUE16(tvb, *offsetp + 2);
1378 guint16 width = VALUE16(tvb, *offsetp + 4);
1379 guint16 height = VALUE16(tvb, *offsetp + 6);
1380 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1381 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1383 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1384 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1385 width, height, x, y, angle1, angle2,
1386 angle1 / 64.0, angle2 / 64.0);
1387 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1388 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1390 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1392 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1394 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1396 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1398 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1403 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1404 int length, gboolean little_endian)
1406 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1407 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1409 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1412 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1413 int length, gboolean little_endian)
1415 if (length <= 0) length = 1;
1416 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1420 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1421 int hf_item, int length, gboolean little_endian)
1423 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1424 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1426 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1431 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1432 int length, gboolean little_endian)
1434 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1435 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1439 unsigned do_red_green_blue;
1440 guint16 red, green, blue;
1445 red = VALUE16(tvb, *offsetp + 4);
1446 green = VALUE16(tvb, *offsetp + 6);
1447 blue = VALUE16(tvb, *offsetp + 8);
1448 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1450 bp = buffer + sprintf(buffer, "colorItem: ");
1452 if (do_red_green_blue & 0x1) {
1453 bp += sprintf(bp, "red = %d", red);
1456 if (do_red_green_blue & 0x2) {
1457 bp += sprintf(bp, "%sgreen = %d", sep, green);
1460 if (do_red_green_blue & 0x4)
1461 bp += sprintf(bp, "%sblue = %d", sep, blue);
1463 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1464 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1465 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1467 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1469 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1471 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1473 colorFlags(tvb, offsetp, ttt);
1474 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1479 static GTree *keysymTable = NULL;
1481 static gint compareGuint32(gconstpointer a, gconstpointer b)
1483 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1487 XConvertCase(register int sym, int *lower, int *upper)
1492 case 0: /* Latin 1 */
1493 if ((sym >= XK_A) && (sym <= XK_Z))
1494 *lower += (XK_a - XK_A);
1495 else if ((sym >= XK_a) && (sym <= XK_z))
1496 *upper -= (XK_a - XK_A);
1497 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1498 *lower += (XK_agrave - XK_Agrave);
1499 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1500 *upper -= (XK_agrave - XK_Agrave);
1501 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1502 *lower += (XK_oslash - XK_Ooblique);
1503 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1504 *upper -= (XK_oslash - XK_Ooblique);
1506 case 1: /* Latin 2 */
1507 /* Assume the KeySym is a legal value (ignore discontinuities) */
1508 if (sym == XK_Aogonek)
1509 *lower = XK_aogonek;
1510 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1511 *lower += (XK_lstroke - XK_Lstroke);
1512 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1513 *lower += (XK_scaron - XK_Scaron);
1514 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1515 *lower += (XK_zcaron - XK_Zcaron);
1516 else if (sym == XK_aogonek)
1517 *upper = XK_Aogonek;
1518 else if (sym >= XK_lstroke && sym <= XK_sacute)
1519 *upper -= (XK_lstroke - XK_Lstroke);
1520 else if (sym >= XK_scaron && sym <= XK_zacute)
1521 *upper -= (XK_scaron - XK_Scaron);
1522 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1523 *upper -= (XK_zcaron - XK_Zcaron);
1524 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1525 *lower += (XK_racute - XK_Racute);
1526 else if (sym >= XK_racute && sym <= XK_tcedilla)
1527 *upper -= (XK_racute - XK_Racute);
1529 case 2: /* Latin 3 */
1530 /* Assume the KeySym is a legal value (ignore discontinuities) */
1531 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1532 *lower += (XK_hstroke - XK_Hstroke);
1533 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1534 *lower += (XK_gbreve - XK_Gbreve);
1535 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1536 *upper -= (XK_hstroke - XK_Hstroke);
1537 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1538 *upper -= (XK_gbreve - XK_Gbreve);
1539 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1540 *lower += (XK_cabovedot - XK_Cabovedot);
1541 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1542 *upper -= (XK_cabovedot - XK_Cabovedot);
1544 case 3: /* Latin 4 */
1545 /* Assume the KeySym is a legal value (ignore discontinuities) */
1546 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1547 *lower += (XK_rcedilla - XK_Rcedilla);
1548 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1549 *upper -= (XK_rcedilla - XK_Rcedilla);
1550 else if (sym == XK_ENG)
1552 else if (sym == XK_eng)
1554 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1555 *lower += (XK_amacron - XK_Amacron);
1556 else if (sym >= XK_amacron && sym <= XK_umacron)
1557 *upper -= (XK_amacron - XK_Amacron);
1559 case 6: /* Cyrillic */
1560 /* Assume the KeySym is a legal value (ignore discontinuities) */
1561 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1562 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1563 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1564 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1565 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1566 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1567 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1568 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1571 /* Assume the KeySym is a legal value (ignore discontinuities) */
1572 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1573 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1574 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1575 sym != XK_Greek_iotaaccentdieresis &&
1576 sym != XK_Greek_upsilonaccentdieresis)
1577 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1578 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1579 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1580 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1581 sym != XK_Greek_finalsmallsigma)
1582 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1588 keycode2keysymString(int *keycodemap[256], int first_keycode,
1589 int keysyms_per_keycode,
1590 int *modifiermap[array_length(modifiers)],
1591 int keycodes_per_modifier,
1592 guint32 keycode, guint32 bitmask)
1594 static char buf[32];
1596 int groupmodkc, numlockkc, numlockmod, groupmod;
1597 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1598 int lockmod_is_nosymbol = 1;
1599 int modifier, kc, keysym;
1601 if ((syms = keycodemap[keycode]) == NULL)
1604 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1605 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1606 if (keycodemap[kc] == NULL)
1608 switch (keycodemap[kc][keysym]) {
1618 lockmod_is_capslock = kc;
1622 lockmod_is_shiftlock = kc;
1629 * If we have not seen the modifiermap we don't know what the
1630 * keycode translates to, but we do know it's one of the keys
1631 * in syms (give or take a case-conversion), so we could in
1632 * theory list them all.
1634 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1637 /* find out what the numlockmodifer and groupmodifier is. */
1638 for (modifier = 0, numlockmod = groupmod = -1;
1639 modifier < (int)array_length(modifiers) && numlockmod == -1;
1641 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1642 if (modifiermap[modifier][kc] == numlockkc)
1643 numlockmod = modifier;
1644 else if (modifiermap[modifier][kc] == groupmodkc)
1645 groupmod = modifier;
1648 * ... and what the lockmodifier is interpreted as.
1649 * (X11v4r6 ref, keyboard and pointers section.)
1651 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1652 if (modifiermap[1][kc] == lockmod_is_capslock) {
1653 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1656 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1657 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1663 * This is (how I understand) the X11v4R6 protocol description given
1664 * in A. Nye's book. It is quite different from the
1665 * code in _XTranslateKey() in the file
1666 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1667 * as shipped with XFree, and doesn't work correctly, nor do I see
1668 * how it could (e.g. the case of lower/uppercase-letters).
1669 * -- Michael Shuldman
1672 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1673 && ((syms[1] >= 0xff80
1674 && syms[1] <= 0xffbd)
1675 || (syms[1] >= 0x11000000
1676 && syms[1] <= 0x1100ffff))) {
1677 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1678 return keysymString(syms[groupmod + 0]);
1680 if (syms[groupmod + 1] == NoSymbol)
1681 return keysymString(syms[groupmod + 0]);
1683 return keysymString(syms[groupmod + 1]);
1685 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1686 return keysymString(syms[groupmod + 0]);
1687 else if (!(bitmask & ShiftMask)
1688 && ((bitmask & LockMask) && lockmod_is_capslock))
1689 if (islower(syms[groupmod + 0]))
1690 /* return toupper(keysymString(syms[groupmod + 0])); */
1691 return "Uppercase"; /* XXX */
1693 return keysymString(syms[groupmod + 0]);
1695 else if ((bitmask & ShiftMask)
1696 && ((bitmask & LockMask) && lockmod_is_capslock))
1697 if (islower(syms[groupmod + 1]))
1698 /* return toupper(keysymString(syms[groupmod + 1])); */
1699 return "Uppercase"; /* XXX */
1701 return keysymString(syms[groupmod + 1]);
1703 else if ((bitmask & ShiftMask)
1704 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1705 return keysymString(syms[groupmod + 1]);
1706 #else /* _XTranslateKey() based code. */
1708 while (keysyms_per_keycode > 2
1709 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1710 --keysyms_per_keycode;
1711 if (keysyms_per_keycode > 2
1712 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1714 keysyms_per_keycode -= 2;
1717 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1718 && keysyms_per_keycode > 1
1719 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1720 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1721 if ((bitmask & ShiftMask)
1722 || (bitmask & LockMask && lockmod_is_shiftlock))
1727 else if (!(bitmask & ShiftMask)
1728 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1729 if (keysyms_per_keycode == 1
1730 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1733 XConvertCase(syms[0], &keysym, &usym);
1738 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1741 if (keysyms_per_keycode == 1
1742 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1743 XConvertCase(syms[0], &lsym, &usym);
1749 if (keysyms_per_keycode == 1
1750 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1753 XConvertCase(keysym, &lsym, &usym);
1755 if (!(bitmask & ShiftMask) && keysym != syms[0]
1756 && ((keysym != usym) || (lsym == usym)))
1757 XConvertCase(syms[0], &lsym, &usym);
1761 if (keysym == XK_VoidSymbol)
1764 sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1769 static const char *keysymString(guint32 v)
1774 /* This table is so big that we built it only if necessary */
1776 const value_string *p = keysym_vals_source;
1777 keysymTable = g_tree_new(compareGuint32);
1778 for(; p -> strptr; p++)
1779 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
1781 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1782 return res ? res : "<Unknown>";
1785 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1786 int *modifiermap[], int keycodes_per_modifier,
1787 gboolean little_endian)
1790 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1791 array_length(modifiers) * keycodes_per_modifier, little_endian);
1793 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1796 for (m = 0; m < array_length(modifiers);
1797 ++m, *offsetp += keycodes_per_modifier) {
1802 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1804 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1806 for(i = 0; i < keycodes_per_modifier; ++i) {
1810 bp += sprintf(bp, " %s=%d", modifiers[m], c);
1812 modifiermap[m][i] = c;
1815 proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1816 *offsetp, keycodes_per_modifier, p,
1817 "item: %s", buffer);
1821 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1822 int hf_item, int *keycodemap[256],
1823 int keycode_first, int keycode_count,
1824 int keysyms_per_keycode, gboolean little_endian)
1826 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1827 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1832 g_assert(keycode_first >= 0);
1833 g_assert(keycode_count >= 0);
1834 g_assert((size_t)(keycode_first + keycode_count) <= 256);
1837 for (keycode = keycode_first; keycode_count > 0;
1838 ++keycode, --keycode_count) {
1839 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1840 keysyms_per_keycode * 4, "keysyms (keycode %d):", keycode);
1842 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1844 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1846 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1848 for(i = 0; i < keysyms_per_keycode; ++i) {
1849 /* keysymvalue = byte3 * 256 + byte4. */
1850 guint32 v = VALUE32(tvb, *offsetp);
1852 proto_item_append_text(tti, " %s", keysymString(v));
1853 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1854 tvb, *offsetp, 4, v,
1855 "keysym (keycode %d): 0x%08x (%s)",
1856 keycode, v, keysymString(v));
1858 keycodemap[keycode][i] = v;
1862 for (i = 1; i < keysyms_per_keycode; ++i)
1863 if (keycodemap[keycode][i] != NoSymbol)
1866 if (i == keysyms_per_keycode) {
1867 /* all but (possibly) first were NoSymbol. */
1868 if (keysyms_per_keycode == 4) {
1869 keycodemap[keycode][1] = NoSymbol;
1870 keycodemap[keycode][2] = keycodemap[keycode][0];
1871 keycodemap[keycode][3] = NoSymbol;
1877 for (i = 2; i < keysyms_per_keycode; ++i)
1878 if (keycodemap[keycode][i] != NoSymbol)
1880 if (i == keysyms_per_keycode) {
1881 /* all but (possibly) first two were NoSymbol. */
1882 if (keysyms_per_keycode == 4) {
1883 keycodemap[keycode][2] = keycodemap[keycode][0];
1884 keycodemap[keycode][3] = keycodemap[keycode][1];
1892 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1893 int length, gboolean little_endian)
1895 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1896 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1902 x = VALUE16(tvb, *offsetp);
1903 y = VALUE16(tvb, *offsetp + 2);
1905 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1906 ttt = proto_item_add_subtree(tti, ett_x11_point);
1907 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1909 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1914 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1915 int length, gboolean little_endian)
1917 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1918 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1921 unsigned width, height;
1925 x = VALUE16(tvb, *offsetp);
1926 y = VALUE16(tvb, *offsetp + 2);
1927 width = VALUE16(tvb, *offsetp + 4);
1928 height = VALUE16(tvb, *offsetp + 6);
1930 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1931 "rectangle: %dx%d+%d+%d", width, height, x, y);
1932 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1933 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1935 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1937 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1939 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1944 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1945 int length, gboolean little_endian)
1947 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1948 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1950 gint16 x1, y1, x2, y2;
1954 x1 = VALUE16(tvb, *offsetp);
1955 y1 = VALUE16(tvb, *offsetp + 2);
1956 x2 = VALUE16(tvb, *offsetp + 4);
1957 y2 = VALUE16(tvb, *offsetp + 6);
1959 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1960 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1961 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1962 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1964 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1966 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1968 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1973 /* XXX - the protocol tree code should handle non-printable characters.
1974 Note that "non-printable characters" may depend on your locale.... */
1975 static void stringCopy(char *dest, const char *source, int length)
1980 if (!isgraph(c) && c != ' ') c = '.';
1986 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1987 int hf_item, int length, gboolean little_endian)
1990 guint allocated = 0;
1995 /* Compute total length */
1997 int scanning_offset = *offsetp; /* Scanning pointer */
1999 for(i = length; i; i--) {
2000 l = tvb_get_guint8(tvb, scanning_offset);
2001 scanning_offset += 1 + l;
2004 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2005 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2008 * In case we throw an exception, clean up whatever stuff we've
2009 * allocated (if any).
2011 CLEANUP_PUSH(g_free, s);
2014 unsigned l = VALUE8(tvb, *offsetp);
2015 if (allocated < (l + 1)) {
2016 /* g_realloc doesn't work ??? */
2018 s = g_malloc(l + 1);
2021 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2022 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2027 * Call the cleanup handler to free the string and pop the handler.
2029 CLEANUP_CALL_AND_POP;
2032 #define STRING16_MAX_DISPLAYED_LENGTH 150
2034 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2036 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2037 for(; length > 0; offset += 2, length--) {
2038 if (tvb_get_guint8(tvb, offset))
2044 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2046 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2047 int hf, int hf_bytes,
2048 int offset, unsigned length,
2049 char **s, int *sLength,
2050 gboolean little_endian)
2052 int truncated = FALSE;
2053 unsigned l = length / 2;
2055 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2057 int soffset = offset;
2059 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2061 l = STRING16_MAX_DISPLAYED_LENGTH;
2063 if (*sLength < (int) l + 3) {
2065 *s = g_malloc(l + 3);
2070 if (truncated) l -= 3;
2074 *dp++ = tvb_get_guint8(tvb, soffset);
2079 /* If truncated, add an ellipsis */
2080 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2083 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
2084 proto_registrar_get_nth(hf) -> name, *s);
2086 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2090 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2091 int sizeIs16, int next_offset, gboolean little_endian)
2099 /* Compute total length */
2101 int scanning_offset = *offsetp; /* Scanning pointer */
2102 int l; /* Length of an individual item */
2103 int n = 0; /* Number of items */
2105 while(scanning_offset < next_offset) {
2106 l = tvb_get_guint8(tvb, scanning_offset);
2110 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2113 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2114 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2117 * In case we throw an exception, clean up whatever stuff we've
2118 * allocated (if any).
2120 CLEANUP_PUSH(g_free, s);
2123 unsigned l = VALUE8(tvb, *offsetp);
2124 if (l == 255) { /* Item is a font */
2125 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2126 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2128 } else { /* Item is a string */
2131 gint8 delta = VALUE8(tvb, *offsetp + 1);
2132 if (sizeIs16) l += l;
2133 if ((unsigned) allocated < l + 1) {
2134 /* g_realloc doesn't work ??? */
2136 s = g_malloc(l + 1);
2139 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2140 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2141 "textitem (string): delta = %d, \"%s\"",
2143 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2144 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2146 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2147 hf_x11_textitem_string_string16_bytes,
2152 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2153 *offsetp + 2, l, s, "\"%s\"", s);
2159 * Call the cleanup handler to free the string and pop the handler.
2161 CLEANUP_CALL_AND_POP;
2164 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2165 gboolean little_endian)
2167 guint32 v = VALUE8(tvb, *offsetp);
2168 header_field_info *hfi = proto_registrar_get_nth(hf);
2169 gchar *enumValue = NULL;
2172 enumValue = match_strval(v, cVALS(hfi -> strings));
2174 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2175 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2176 hfi -> name, v, enumValue);
2178 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2183 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2184 gboolean little_endian)
2186 guint32 v = VALUE16(tvb, *offsetp);
2187 header_field_info *hfi = proto_registrar_get_nth(hf);
2188 gchar *enumValue = NULL;
2191 enumValue = match_strval(v, cVALS(hfi -> strings));
2193 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2194 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2195 hfi -> name, v, enumValue);
2197 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2202 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2203 gboolean little_endian)
2205 guint32 v = VALUE32(tvb, *offsetp);
2206 header_field_info *hfi = proto_registrar_get_nth(hf);
2207 gchar *enumValue = NULL;
2208 gchar *nameAsChar = hfi -> name;
2211 enumValue = match_strval(v, cVALS(hfi -> strings));
2213 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2214 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2215 nameAsChar, v, enumValue);
2217 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2218 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2224 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2225 gboolean little_endian)
2227 BITMASK32(gc_value);
2228 BITFIELD(ENUM8, gc_value_mask, function);
2229 BITFIELD(CARD32, gc_value_mask, plane_mask);
2230 BITFIELD(CARD32, gc_value_mask, foreground);
2231 BITFIELD(CARD32, gc_value_mask, background);
2232 BITFIELD(CARD16, gc_value_mask, line_width);
2233 BITFIELD(ENUM8, gc_value_mask, line_style);
2234 BITFIELD(ENUM8, gc_value_mask, cap_style);
2235 BITFIELD(ENUM8, gc_value_mask, join_style);
2236 BITFIELD(ENUM8, gc_value_mask, fill_style);
2237 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2238 BITFIELD(PIXMAP, gc_value_mask, tile);
2239 BITFIELD(PIXMAP, gc_value_mask, stipple);
2240 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2241 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2242 BITFIELD(FONT, gc_value_mask, font);
2243 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2244 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2245 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2246 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2247 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2248 BITFIELD(CARD16, gc_value_mask, dash_offset);
2249 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2250 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2254 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2255 gboolean little_endian)
2257 BITMASK32(gc_value);
2258 FLAG(gc_value, function);
2259 FLAG(gc_value, plane_mask);
2260 FLAG(gc_value, foreground);
2261 FLAG(gc_value, background);
2262 FLAG(gc_value, line_width);
2263 FLAG(gc_value, line_style);
2264 FLAG(gc_value, cap_style);
2265 FLAG(gc_value, join_style);
2266 FLAG(gc_value, fill_style);
2267 FLAG(gc_value, fill_rule);
2268 FLAG(gc_value, tile);
2269 FLAG(gc_value, stipple);
2270 FLAG(gc_value, tile_stipple_x_origin);
2271 FLAG(gc_value, tile_stipple_y_origin);
2272 FLAG(gc_value, font);
2273 FLAG(gc_value, subwindow_mode);
2274 FLAG(gc_value, graphics_exposures);
2275 FLAG(gc_value, clip_x_origin);
2276 FLAG(gc_value, clip_y_origin);
2277 FLAG(gc_value, clip_mask);
2278 FLAG(gc_value, dash_offset);
2279 FLAG(gc_value, gc_dashes);
2280 FLAG(gc_value, arc_mode);
2284 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2285 gboolean little_endian)
2287 guint32 res = VALUE16(tvb, *offsetp);
2288 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2293 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2294 gboolean little_endian)
2297 FLAG(event, KeyPress);
2298 FLAG(event, KeyRelease);
2299 FLAG(event, ButtonPress);
2300 FLAG(event, ButtonRelease);
2301 FLAG(event, EnterWindow);
2302 FLAG(event, LeaveWindow);
2303 FLAG(event, PointerMotion);
2304 FLAG(event, PointerMotionHint);
2305 FLAG(event, Button1Motion);
2306 FLAG(event, Button2Motion);
2307 FLAG(event, Button3Motion);
2308 FLAG(event, Button4Motion);
2309 FLAG(event, Button5Motion);
2310 FLAG(event, ButtonMotion);
2311 FLAG(event, KeymapState);
2312 FLAG(event, Exposure);
2313 FLAG(event, VisibilityChange);
2314 FLAG(event, StructureNotify);
2315 FLAG(event, ResizeRedirect);
2316 FLAG(event, SubstructureNotify);
2317 FLAG(event, SubstructureRedirect);
2318 FLAG(event, FocusChange);
2319 FLAG(event, PropertyChange);
2320 FLAG(event, ColormapChange);
2321 FLAG(event, OwnerGrabButton);
2322 FLAG_IF_NONZERO(event, erroneous_bits);
2326 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2327 gboolean little_endian)
2329 BITMASK32(do_not_propagate);
2330 FLAG(do_not_propagate, KeyPress);
2331 FLAG(do_not_propagate, KeyRelease);
2332 FLAG(do_not_propagate, ButtonPress);
2333 FLAG(do_not_propagate, ButtonRelease);
2334 FLAG(do_not_propagate, PointerMotion);
2335 FLAG(do_not_propagate, Button1Motion);
2336 FLAG(do_not_propagate, Button2Motion);
2337 FLAG(do_not_propagate, Button3Motion);
2338 FLAG(do_not_propagate, Button4Motion);
2339 FLAG(do_not_propagate, Button5Motion);
2340 FLAG(do_not_propagate, ButtonMotion);
2341 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2346 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2347 gboolean little_endian, gboolean butmask)
2350 guint32 bitmask_value;
2353 proto_tree *bitmask_tree;
2355 bitmask_value = VALUE16(tvb, *offsetp);
2356 bitmask_offset = *offsetp;
2359 if (!butmask && bitmask_value == 0x8000)
2360 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2361 "modifiers-masks: 0x8000 (AnyModifier)");
2363 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2365 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2366 FLAG(modifiers, Shift);
2367 FLAG(modifiers, Lock);
2368 FLAG(modifiers, Control);
2369 FLAG(modifiers, Mod1);
2370 FLAG(modifiers, Mod2);
2371 FLAG(modifiers, Mod3);
2372 FLAG(modifiers, Mod4);
2373 FLAG(modifiers, Mod5);
2376 FLAG(modifiers, Button1);
2377 FLAG(modifiers, Button2);
2378 FLAG(modifiers, Button3);
2379 FLAG(modifiers, Button4);
2380 FLAG(modifiers, Button5);
2384 FLAG_IF_NONZERO(keybut, erroneous_bits);
2386 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2391 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2392 gboolean little_endian)
2394 BITMASK16(pointer_event);
2395 FLAG(pointer_event, ButtonPress);
2396 FLAG(pointer_event, ButtonRelease);
2397 FLAG(pointer_event, EnterWindow);
2398 FLAG(pointer_event, LeaveWindow);
2399 FLAG(pointer_event, PointerMotion);
2400 FLAG(pointer_event, PointerMotionHint);
2401 FLAG(pointer_event, Button1Motion);
2402 FLAG(pointer_event, Button2Motion);
2403 FLAG(pointer_event, Button3Motion);
2404 FLAG(pointer_event, Button4Motion);
2405 FLAG(pointer_event, Button5Motion);
2406 FLAG(pointer_event, ButtonMotion);
2407 FLAG(pointer_event, KeymapState);
2408 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2412 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2413 int hf, unsigned length)
2418 p = tvb_get_ptr(tvb, *offsetp, length);
2419 s = g_malloc(length + 1);
2420 stringCopy(s, p, length);
2421 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2426 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2428 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2429 int hf_bytes, unsigned length, gboolean little_endian)
2435 * In case we throw an exception, clean up whatever stuff we've
2436 * allocated (if any).
2438 CLEANUP_PUSH(g_free, s);
2441 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2442 &s, &l, little_endian);
2445 * Call the cleanup handler to free the string and pop the handler.
2447 CLEANUP_CALL_AND_POP;
2452 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2453 gboolean little_endian)
2455 guint32 v = VALUE32(tvb, *offsetp);
2458 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2459 proto_registrar_get_nth(hf) -> name);
2461 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2465 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2466 gboolean little_endian)
2468 BITMASK32(window_value);
2469 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2470 BITFIELD(CARD32, window_value_mask, background_pixel);
2471 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2472 BITFIELD(CARD32, window_value_mask, border_pixel);
2473 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2474 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2475 BITFIELD(ENUM8, window_value_mask, backing_store);
2476 BITFIELD(CARD32, window_value_mask, backing_planes);
2477 BITFIELD(CARD32, window_value_mask, backing_pixel);
2478 BITFIELD(BOOL, window_value_mask, override_redirect);
2479 BITFIELD(BOOL, window_value_mask, save_under);
2480 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2481 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2482 BITFIELD(COLORMAP, window_value_mask, colormap);
2483 BITFIELD(CURSOR, window_value_mask, cursor);
2487 static void x11_init_protocol(void)
2489 if (x11_state_chunk != NULL)
2490 g_mem_chunk_destroy(x11_state_chunk);
2492 x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2493 sizeof (x11_conv_data_t),
2494 128 * sizeof (x11_conv_data_t),
2498 /************************************************************************
2500 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2502 ************************************************************************/
2504 /* If we can't guess, we return TRUE (that is little_endian), cause
2505 I'm developing on a Linux box :-). The (non-)guess isn't cached
2506 however, so we may have more luck next time. I'm quite conservative
2507 in my assertions, cause once it's cached, it's stay in cache, and
2508 we may be fooled up by a packet starting with the end of a request
2509 started in a previous packet...
2512 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2514 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2517 while(maskLength--) {
2518 int c = tvb_get_guint8(tvb, offset);
2520 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2525 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2527 if (listLength > length) return FALSE;
2528 while(listLength--) {
2530 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2531 l = tvb_get_guint8(tvb, offset);
2534 if (l > length) return FALSE;
2535 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2539 if (length > 3) return FALSE;
2543 static int rounded4(int n)
2545 int remainder = n % 4;
2547 if (remainder) res++;
2551 /* We assume the order to be consistent, until proven wrong. */
2553 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2555 switch(tvb_get_guint8(tvb, offset)) {
2556 case X_CreateWindow:
2557 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2559 case X_ChangeWindowAttributes:
2561 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2563 case X_GetWindowAttributes:
2564 case X_DestroyWindow:
2565 case X_DestroySubwindows:
2566 case X_ChangeSaveSet:
2568 case X_MapSubwindows:
2570 case X_UnmapSubwindows:
2571 case X_CirculateWindow:
2575 case X_ListProperties:
2576 case X_GetSelectionOwner:
2577 case X_UngrabPointer:
2578 case X_UngrabKeyboard:
2580 case X_QueryPointer:
2585 case X_FreeColormap:
2586 case X_InstallColormap:
2587 case X_UninstallColormap:
2588 case X_ListInstalledColormaps:
2590 case X_GetKeyboardMapping:
2594 case X_ReparentWindow:
2595 case X_SetSelectionOwner:
2596 case X_ChangeActivePointerGrab:
2597 case X_GrabKeyboard:
2599 case X_GetMotionEvents:
2600 case X_TranslateCoords:
2601 case X_CreatePixmap:
2604 case X_CreateColormap:
2606 case X_AllocColorPlanes:
2609 case X_ConfigureWindow:
2610 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2613 case X_QueryExtension:
2614 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2616 case X_ChangeProperty:
2618 int multiplier, type;
2619 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2620 type = tvb_get_guint8(tvb, 16);
2621 if (type != 8 && type != 16 && type != 32) return FALSE;
2622 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2623 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2624 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2627 case X_DeleteProperty:
2628 case X_UngrabButton:
2630 case X_SetInputFocus:
2631 case X_CopyColormapAndFree:
2632 case X_AllocColorCells:
2633 case X_QueryBestSize:
2634 case X_ChangePointerControl:
2635 case X_SetScreenSaver:
2639 case X_ConvertSelection:
2646 return length == 11;
2649 case X_UngrabServer:
2650 case X_GetInputFocus:
2653 case X_ListExtensions:
2654 case X_GetKeyboardControl:
2656 case X_GetPointerControl:
2657 case X_GetScreenSaver:
2659 case X_SetAccessControl:
2660 case X_SetCloseDownMode:
2661 case X_ForceScreenSaver:
2662 case X_GetPointerMapping:
2663 case X_GetModifierMapping:
2667 case X_AllocNamedColor:
2669 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2671 case X_QueryTextExtents:
2675 case X_ListFontsWithInfo:
2677 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2680 if (length < 2) return FALSE;
2681 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2682 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2685 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2688 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2690 case X_SetClipRectangles:
2692 case X_PolyRectangle:
2693 case X_PolyFillRectangle:
2694 return length >= 3 && (length - 3) % 2 == 0;
2700 case X_CreateCursor:
2701 case X_CreateGlyphCursor:
2711 return length >= 3 && (length - 3) % 3 == 0;
2721 case X_RecolorCursor:
2725 if (length < 4) return FALSE;
2726 return TRUE; /* We don't perform many controls on this one */
2729 if (length < 4) return FALSE;
2730 return TRUE; /* We don't perform many controls on this one */
2736 return length > 2 && (length - 2) % 3 == 0;
2738 case X_StoreNamedColor:
2739 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2744 case X_ChangeKeyboardMapping:
2745 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2747 case X_ChangeKeyboardControl:
2748 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2750 case X_RotateProperties:
2751 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2753 case X_SetPointerMapping:
2754 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2756 case X_SetModifierMapping:
2757 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2767 /* -1 means doesn't match, +1 means match, 0 means don't know */
2769 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2771 int offset, nextoffset;
2774 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2776 length = v16(tvb, offset + 2);
2777 if (!length) return -1;
2778 nextoffset = offset + length * 4;
2779 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2786 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2787 x11_conv_data_t *state)
2789 /* With X the client gives the byte ordering for the protocol,
2790 and the port on the server tells us we're speaking X. */
2792 int le, be, decision, decisionToCache;
2794 if (state->byte_order == BYTE_ORDER_BE)
2795 return FALSE; /* known to be big-endian */
2796 else if (state->byte_order == BYTE_ORDER_LE)
2797 return TRUE; /* known to be little-endian */
2799 if (pinfo->srcport == pinfo->match_port) {
2801 * This is a reply or event; we don't try to guess the
2802 * byte order on it for now.
2807 le = x_endian_match(tvb, tvb_get_letohs);
2808 be = x_endian_match(tvb, tvb_get_ntohs);
2810 /* remember that "decision" really means "little_endian". */
2812 /* We have no reason to believe it's little- rather than
2813 big-endian, so we guess the shortest length is the
2816 if (!tvb_bytes_exist(tvb, 0, 4))
2817 /* Not even a way to get the length. We're biased
2818 toward little endianness here (essentially the
2819 x86 world right now). Decoding won't go very far
2824 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2826 decision = le >= be;
2828 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2829 if (decisionToCache) {
2831 * Remember the decision.
2833 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2837 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2838 pinfo->fd -> num, le, be, decision, decisionToCache);
2843 /************************************************************************
2845 *** D E C O D I N G O N E P A C K E T ***
2847 ************************************************************************/
2850 * Decode an initial connection request.
2852 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2853 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2856 int *offsetp = &offset;
2859 guint16 auth_proto_name_length, auth_proto_data_length;
2862 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2863 proto_item_append_text(ti, ", Request, Initial connection request");
2864 t = proto_item_add_subtree(ti, ett_x11);
2868 CARD16(protocol_major_version);
2869 CARD16(protocol_minor_version);
2870 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2871 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2874 if (auth_proto_name_length != 0) {
2875 STRING8(authorization_protocol_name, auth_proto_name_length);
2876 offset = ROUND_LENGTH(offset);
2879 if (auth_proto_data_length != 0) {
2880 STRING8(authorization_protocol_data, auth_proto_data_length);
2881 offset = ROUND_LENGTH(offset);
2884 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2885 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2889 * This is the initial connection request...
2891 state->iconn_frame = pinfo->fd->num;
2894 * ...and we're expecting a reply to it.
2896 state->sequencenumber = 0;
2897 g_hash_table_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
2898 (int *)INITIAL_CONN);
2901 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2902 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2903 gboolean little_endian)
2905 int offset = 0, *offsetp = &offset, left;
2906 unsigned char success;
2907 int length_of_vendor;
2908 int length_of_reason;
2912 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2913 proto_item_append_text(ti, ", Reply, Initial connection reply");
2914 t = proto_item_add_subtree(ti, ett_x11);
2916 state->iconn_reply = pinfo->fd->num;
2917 success = INT8(success);
2920 length_of_reason = 0;
2923 length_of_reason = INT8(length_of_reason);
2926 INT16(protocol_major_version);
2927 INT16(protocol_minor_version);
2930 INT32(release_number);
2931 INT32(resource_id_base);
2932 INT32(resource_id_mask);
2933 INT32(motion_buffer_size);
2934 length_of_vendor = INT16(length_of_vendor);
2935 INT16(maximum_request_length);
2936 INT8(number_of_screens_in_roots);
2937 INT8(number_of_formats_in_pixmap_formats);
2938 INT8(image_byte_order);
2939 INT8(bitmap_format_bit_order);
2940 INT8(bitmap_format_scanline_unit);
2941 INT8(bitmap_format_scanline_pad);
2945 STRING8(vendor, length_of_vendor);
2947 STRING8(reason, length_of_reason);
2950 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2955 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2956 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2957 gboolean little_endian)
2960 int *offsetp = &offset;
2964 int length, opcode, i;
2965 guint8 v8, v8_2, v8_3;
2971 length = VALUE16(tvb, 2) * 4;
2974 /* Bogus message length? */
2978 next_offset = offset + length;
2980 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2981 t = proto_item_add_subtree(ti, ett_x11);
2983 if (PACKET_IS_NEW(pinfo))
2984 ++state->sequencenumber;
2988 if (check_col(pinfo->cinfo, COL_INFO))
2989 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2990 val_to_str(opcode, state->opcode_vals,
2991 "<Unknown opcode %d>"));
2993 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2994 opcode, val_to_str(opcode, state->opcode_vals,
2995 "<Unknown opcode %d>"));
2998 * Does this request expect a reply?
3002 case X_QueryExtension:
3004 /* necessary processing even if tree == NULL */
3006 v16 = VALUE16(tvb, 4);
3007 name = g_malloc(v16 + 1);
3008 stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
3010 /* store string of extension, opcode will be set at reply */
3012 while(i < MAX_OPCODES) {
3013 if (state->opcode_vals[i].strptr == NULL) {
3014 state->opcode_vals[i].strptr = name;
3015 g_hash_table_insert(state->valtable,
3016 GINT_TO_POINTER(state->sequencenumber),
3017 (int *)&state->opcode_vals[i]);
3019 } else if (strcmp(state->opcode_vals[i].strptr,
3021 g_hash_table_insert(state->valtable,
3022 GINT_TO_POINTER(state->sequencenumber),
3023 (int *)&state->opcode_vals[i]);
3029 /* QueryExtension expects a reply, fall through */
3032 case X_AllocColorCells:
3033 case X_AllocColorPlanes:
3034 case X_AllocNamedColor:
3039 case X_GetInputFocus:
3040 case X_GetKeyboardControl:
3041 case X_GetKeyboardMapping:
3042 case X_GetModifierMapping:
3043 case X_GetMotionEvents:
3044 case X_GetPointerControl:
3045 case X_GetPointerMapping:
3047 case X_GetScreenSaver:
3048 case X_GetSelectionOwner:
3049 case X_GetWindowAttributes:
3050 case X_GrabKeyboard:
3053 case X_ListExtensions:
3055 case X_ListFontsWithInfo:
3057 case X_ListInstalledColormaps:
3058 case X_ListProperties:
3060 case X_QueryBestSize:
3064 case X_QueryPointer:
3065 case X_QueryTextExtents:
3067 case X_SetModifierMapping:
3068 case X_SetPointerMapping:
3069 case X_TranslateCoords:
3071 * Those requests expect a reply.
3073 g_hash_table_insert(state->seqtable,
3074 GINT_TO_POINTER(state->sequencenumber),
3081 * With Extension, we don't know, so assume there could be one
3083 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3084 g_hash_table_insert(state->seqtable,
3085 GINT_TO_POINTER(state->sequencenumber),
3090 * No reply is expected from any other request.
3100 case X_CreateWindow:
3109 CARD16(border_width);
3110 ENUM16(window_class);
3112 windowAttributes(tvb, offsetp, t, little_endian);
3115 case X_ChangeWindowAttributes:
3119 windowAttributes(tvb, offsetp, t, little_endian);
3122 case X_GetWindowAttributes:
3123 case X_DestroyWindow:
3124 case X_DestroySubwindows:
3130 case X_ChangeSaveSet:
3131 ENUM8(save_set_mode);
3136 case X_ReparentWindow:
3146 case X_MapSubwindows:
3148 case X_UnmapSubwindows:
3154 case X_ConfigureWindow:
3158 BITMASK16(configure_window);
3160 BITFIELD(INT16, configure_window_mask, x);
3161 BITFIELD(INT16, configure_window_mask, y);
3162 BITFIELD(CARD16, configure_window_mask, width);
3163 BITFIELD(CARD16, configure_window_mask, height);
3164 BITFIELD(CARD16, configure_window_mask, border_width);
3165 BITFIELD(WINDOW, configure_window_mask, sibling);
3166 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3171 case X_CirculateWindow:
3185 BOOL(only_if_exists);
3187 v16 = FIELD16(name_length);
3199 case X_ChangeProperty:
3207 v32 = CARD32(data_length);
3208 LISTofBYTE(data, v32);
3212 case X_DeleteProperty:
3224 ATOM(get_property_type);
3225 CARD32(long_offset);
3226 CARD32(long_length);
3229 case X_ListProperties:
3235 case X_SetSelectionOwner:
3243 case X_GetSelectionOwner:
3249 case X_ConvertSelection:
3262 WINDOW(destination);
3263 SETofEVENT(event_mask);
3270 WINDOW(grab_window);
3271 SETofPOINTEREVENT(pointer_event_mask);
3272 ENUM8(pointer_mode);
3273 ENUM8(keyboard_mode);
3279 case X_UngrabPointer:
3288 WINDOW(grab_window);
3289 SETofPOINTEREVENT(event_mask);
3290 ENUM8(pointer_mode);
3291 ENUM8(keyboard_mode);
3296 SETofKEYMASK(modifiers);
3299 case X_UngrabButton:
3302 WINDOW(grab_window);
3303 SETofKEYMASK(modifiers);
3307 case X_ChangeActivePointerGrab:
3312 SETofPOINTEREVENT(event_mask);
3316 case X_GrabKeyboard:
3319 WINDOW(grab_window);
3321 ENUM8(pointer_mode);
3322 ENUM8(keyboard_mode);
3326 case X_UngrabKeyboard:
3335 WINDOW(grab_window);
3336 SETofKEYMASK(modifiers);
3338 ENUM8(pointer_mode);
3339 ENUM8(keyboard_mode);
3346 WINDOW(grab_window);
3347 SETofKEYMASK(modifiers);
3352 ENUM8(allow_events_mode);
3362 case X_UngrabServer:
3367 case X_QueryPointer:
3373 case X_GetMotionEvents:
3381 case X_TranslateCoords:
3393 WINDOW(warp_pointer_src_window);
3394 WINDOW(warp_pointer_dst_window);
3403 case X_SetInputFocus:
3410 case X_GetInputFocus:
3424 v16 = FIELD16(name_length);
3442 case X_QueryTextExtents:
3443 v8 = BOOL(odd_length);
3446 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3454 v16 = FIELD16(pattern_length);
3455 STRING8(pattern, v16);
3459 case X_ListFontsWithInfo:
3463 v16 = FIELD16(pattern_length);
3464 STRING8(pattern, v16);
3471 v16 = CARD16(str_number_in_path);
3473 LISTofSTRING8(path, v16);
3482 case X_CreatePixmap:
3502 gcAttributes(tvb, offsetp, t, little_endian);
3509 gcAttributes(tvb, offsetp, t, little_endian);
3517 gcMask(tvb, offsetp, t, little_endian);
3524 CARD16(dash_offset);
3525 v16 = FIELD16(dashes_length);
3526 LISTofCARD8(dashes, v16);
3530 case X_SetClipRectangles:
3534 INT16(clip_x_origin);
3535 INT16(clip_y_origin);
3536 LISTofRECTANGLE(rectangles);
3558 DRAWABLE(src_drawable);
3559 DRAWABLE(dst_drawable);
3572 DRAWABLE(src_drawable);
3573 DRAWABLE(dst_drawable);
3585 ENUM8(coordinate_mode);
3586 v16 = REQUEST_LENGTH();
3589 LISTofPOINT(points, v16 - 12);
3593 ENUM8(coordinate_mode);
3594 v16 = REQUEST_LENGTH();
3597 LISTofPOINT(points, v16 - 12);
3605 LISTofSEGMENT(segments);
3608 case X_PolyRectangle:
3613 LISTofRECTANGLE(rectangles);
3626 v16 = REQUEST_LENGTH();
3630 ENUM8(coordinate_mode);
3632 LISTofPOINT(points, v16 - 16);
3635 case X_PolyFillRectangle:
3640 LISTofRECTANGLE(rectangles);
3652 ENUM8(image_format);
3653 v16 = REQUEST_LENGTH();
3663 LISTofBYTE(data, v16 - 24);
3668 ENUM8(image_pixmap_format);
3680 v16 = REQUEST_LENGTH();
3685 LISTofTEXTITEM8(items);
3691 v16 = REQUEST_LENGTH();
3696 LISTofTEXTITEM16(items);
3701 v8 = FIELD8(string_length);
3707 STRING8(string, v8);
3712 v8 = FIELD8(string_length);
3718 STRING16(string16, v8);
3722 case X_CreateColormap:
3730 case X_FreeColormap:
3736 case X_CopyColormapAndFree:
3743 case X_InstallColormap:
3749 case X_UninstallColormap:
3755 case X_ListInstalledColormaps:
3771 case X_AllocNamedColor:
3775 v16 = FIELD16(name_length);
3781 case X_AllocColorCells:
3789 case X_AllocColorPlanes:
3801 v16 = REQUEST_LENGTH();
3804 LISTofCARD32(pixels, v16 - 12);
3809 v16 = REQUEST_LENGTH();
3811 LISTofCOLORITEM(color_items, v16 - 8);
3814 case X_StoreNamedColor:
3819 v16 = FIELD16(name_length);
3827 v16 = REQUEST_LENGTH();
3829 LISTofCARD32(pixels, v16 - 8);
3836 v16 = FIELD16(name_length);
3842 case X_CreateCursor:
3846 PIXMAP(source_pixmap);
3858 case X_CreateGlyphCursor:
3864 CARD16(source_char);
3880 case X_RecolorCursor:
3892 case X_QueryBestSize:
3900 case X_QueryExtension:
3903 v16 = FIELD16(name_length);
3909 case X_ListExtensions:
3914 case X_ChangeKeyboardMapping:
3915 v8 = FIELD8(keycode_count);
3917 v8_2 = KEYCODE(first_keycode);
3918 v8_3 = FIELD8(keysyms_per_keycode);
3920 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3923 case X_GetKeyboardMapping:
3926 state->request.GetKeyboardMapping.first_keycode
3927 = KEYCODE(first_keycode);
3932 case X_ChangeKeyboardControl:
3935 BITMASK32(keyboard_value);
3936 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3937 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3938 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3939 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3940 BITFIELD(INT16, keyboard_value_mask, led);
3941 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3942 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3943 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3947 case X_GetKeyboardControl:
3957 case X_ChangePointerControl:
3960 INT16(acceleration_numerator);
3961 INT16(acceleration_denominator);
3963 BOOL(do_acceleration);
3967 case X_GetPointerControl:
3972 case X_SetScreenSaver:
3977 ENUM8(prefer_blanking);
3978 ENUM8(allow_exposures);
3982 case X_GetScreenSaver:
3988 ENUM8(change_host_mode);
3992 v16 = CARD16(address_length);
3993 if (v8 == FAMILY_INTERNET && v16 == 4) {
3996 * XXX - what about IPv6? Is that a family of
3997 * FAMILY_INTERNET (0) with a length of 16?
3999 LISTofIPADDRESS(ip_address, v16);
4001 LISTofCARD8(address, v16);
4009 case X_SetAccessControl:
4014 case X_SetCloseDownMode:
4015 ENUM8(close_down_mode);
4025 case X_RotateProperties:
4027 v16 = REQUEST_LENGTH();
4029 CARD16(property_number);
4031 LISTofATOM(properties, (v16 - 12));
4034 case X_ForceScreenSaver:
4035 ENUM8(screen_saver_mode);
4039 case X_SetPointerMapping:
4040 v8 = FIELD8(map_length);
4042 LISTofCARD8(map, v8);
4046 case X_GetPointerMapping:
4051 case X_SetModifierMapping:
4052 v8 = FIELD8(keycodes_per_modifier);
4054 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4057 case X_GetModifierMapping:
4068 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4072 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4075 volatile int offset = 0;
4076 int length_remaining;
4077 volatile gboolean little_endian;
4082 volatile gboolean is_initial_creq;
4083 guint16 auth_proto_len, auth_data_len;
4084 const char *volatile sep = NULL;
4085 conversation_t *conversation;
4086 x11_conv_data_t *state;
4090 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4092 * We use "tvb_ensure_length_remaining()" to make sure there
4093 * actually *is* data remaining.
4095 * This means we're guaranteed that "length_remaining" is
4098 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4101 * Can we do reassembly?
4103 if (x11_desegment && pinfo->can_desegment) {
4105 * Yes - is the X11 request header split across
4106 * segment boundaries?
4108 if (length_remaining < 4) {
4110 * Yes. Tell the TCP dissector where the data
4111 * for this message starts in the data it handed
4112 * us, and how many more bytes we need, and return.
4114 pinfo->desegment_offset = offset;
4115 pinfo->desegment_len = 4 - length_remaining;
4121 * Get the state for this conversation; create the conversation
4122 * if we don't have one, and create the state if we don't have
4125 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4126 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4127 if (conversation == NULL) {
4131 conversation = conversation_new(&pinfo->src,
4132 &pinfo->dst, pinfo->ptype, pinfo->srcport,
4133 pinfo->destport, 0);
4137 * Is there state attached to this conversation?
4139 if ((state = conversation_get_proto_data(conversation, proto_x11))
4141 x11_stateinit(&state, conversation);
4144 * Guess the byte order if we don't already know it.
4146 little_endian = guess_byte_ordering(tvb, pinfo, state);
4149 * Get the opcode and length of the putative X11 request.
4151 opcode = VALUE8(tvb, 0);
4152 plen = VALUE16(tvb, offset + 2);
4156 * This can't be 0, as it includes the header length.
4157 * A different choice of byte order wouldn't have
4161 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4163 t = proto_item_add_subtree(ti, ett_x11);
4164 proto_tree_add_text(t, tvb, offset, -1,
4165 "Bogus request length (0)");
4169 if (state->iconn_frame == pinfo->fd->num ||
4170 (g_hash_table_lookup(state->seqtable,
4171 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4172 (opcode == 'B' || opcode == 'l') &&
4173 (plen == 11 || plen == 2816))) {
4177 * we saw this on the first pass and this is
4181 * we haven't already seen any requests, the first
4182 * byte of the message is 'B' or 'l', and the 16-bit
4183 * integer 2 bytes into the data stream is either 11
4184 * or a byte-swapped 11.
4186 * This means it's probably an initial connection
4187 * request, not a message.
4189 * 'B' is decimal 66, which is the opcode for a
4190 * PolySegment request; unfortunately, 11 is a valid
4191 * length for a PolySegment request request, so we
4192 * might mis-identify that request. (Are there any
4193 * other checks we can do?)
4195 * 'l' is decimal 108, which is the opcode for a
4196 * GetScreenSaver request; the only valid length
4197 * for that request is 1.
4199 is_initial_creq = TRUE;
4202 * We now know the byte order. Override the guess.
4204 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4205 if (opcode == 'B') {
4209 state->byte_order = BYTE_ORDER_BE;
4210 little_endian = FALSE;
4215 state->byte_order = BYTE_ORDER_LE;
4216 little_endian = TRUE;
4221 * Can we do reassembly?
4223 if (x11_desegment && pinfo->can_desegment) {
4225 * Yes - is the fixed-length portion of the
4226 * initial connection header split across
4227 * segment boundaries?
4229 if (length_remaining < 10) {
4231 * Yes. Tell the TCP dissector where the
4232 * data for this message starts in the data
4233 * it handed us, and how many more bytes we
4236 pinfo->desegment_offset = offset;
4237 pinfo->desegment_len = 10 - length_remaining;
4243 * Get the lengths of the authorization protocol and
4244 * the authorization data.
4246 auth_proto_len = VALUE16(tvb, offset + 6);
4247 auth_data_len = VALUE16(tvb, offset + 8);
4248 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4249 ROUND_LENGTH(auth_data_len);
4252 * This is probably an ordinary request.
4254 is_initial_creq = FALSE;
4257 * The length of a request is in 4-byte words.
4263 * Can we do reassembly?
4265 if (x11_desegment && pinfo->can_desegment) {
4267 * Yes - is the X11 request split across segment
4270 if (length_remaining < plen) {
4272 * Yes. Tell the TCP dissector where the data
4273 * for this message starts in the data it handed
4274 * us, and how many more bytes we need, and return.
4276 pinfo->desegment_offset = offset;
4277 pinfo->desegment_len = plen - length_remaining;
4283 * Construct a tvbuff containing the amount of the payload
4284 * we have available. Make its reported length the
4285 * amount of data in the X11 request.
4287 * XXX - if reassembly isn't enabled. the subdissector
4288 * will throw a BoundsError exception, rather than a
4289 * ReportedBoundsError exception. We really want a tvbuff
4290 * where the length is "length", the reported length is "plen",
4291 * and the "if the snapshot length were infinite" length is the
4292 * minimum of the reported length of the tvbuff handed to us
4293 * and "plen", with a new type of exception thrown if the offset
4294 * is within the reported length but beyond that third length,
4295 * with that exception getting the "Unreassembled Packet" error.
4297 length = length_remaining;
4300 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4303 * Set the column appropriately.
4305 if (is_initial_creq) {
4306 if (check_col(pinfo->cinfo, COL_INFO))
4307 col_set_str(pinfo->cinfo, COL_INFO,
4308 "Initial connection request");
4312 * We haven't set the column yet; set it.
4314 if (check_col(pinfo->cinfo, COL_INFO))
4315 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4318 * Initialize the separator.
4325 * Dissect the X11 request.
4327 * Catch the ReportedBoundsError exception; if this
4328 * particular message happens to get a ReportedBoundsError
4329 * exception, that doesn't mean that we should stop
4330 * dissecting X11 requests within this frame or chunk of
4333 * If it gets a BoundsError, we can stop, as there's nothing
4334 * more to see, so we just re-throw it.
4337 if (is_initial_creq) {
4338 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4339 state, little_endian);
4341 dissect_x11_request(next_tvb, pinfo, tree, sep,
4342 state, little_endian);
4345 CATCH(BoundsError) {
4348 CATCH(ReportedBoundsError) {
4349 show_reported_bounds_error(tvb, pinfo, tree);
4354 * Skip the X11 message.
4363 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4365 static x11_conv_data_t stateinit;
4368 *state = g_mem_chunk_alloc(x11_state_chunk);
4369 **state = stateinit;
4371 /* initialise opcodes */
4373 if (opcode_vals[i].strptr == NULL) break;
4374 (*state)->opcode_vals[i].value = opcode_vals[i].value;
4375 (*state)->opcode_vals[i].strptr = opcode_vals[i].strptr;
4378 while (i <= MAX_OPCODES) {
4379 (*state)->opcode_vals[i].value = 0;
4380 (*state)->opcode_vals[i].strptr = NULL;
4384 (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4385 (*state)->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4386 g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4387 (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4388 conversation_add_proto_data(conversation, proto_x11, *state);
4393 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4395 /* Set up structures we will need to add the protocol subtree and manage it */
4396 volatile int offset, plen;
4397 tvbuff_t * volatile next_tvb;
4398 conversation_t *conversation;
4399 x11_conv_data_t *state;
4400 gboolean little_endian;
4401 int length_remaining;
4402 const char *volatile sep = NULL;
4406 * Get the state for this conversation; create the conversation
4407 * if we don't have one, and create the state if we don't have
4410 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4411 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4412 if (conversation == NULL) {
4416 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4417 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4421 * Is there state attached to this conversation?
4423 if ((state = conversation_get_proto_data(conversation, proto_x11))
4426 * No - create a state structure and attach it.
4428 x11_stateinit(&state, conversation);
4432 * Guess the byte order if we don't already know it.
4434 little_endian = guess_byte_ordering(tvb, pinfo, state);
4437 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4439 * We use "tvb_ensure_length_remaining()" to make sure there
4440 * actually *is* data remaining.
4442 * This means we're guaranteed that "length_remaining" is
4445 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4448 * Can we do reassembly?
4450 if (x11_desegment && pinfo->can_desegment) {
4452 * Yes - is the X11 reply header split across
4453 * segment boundaries?
4455 if (length_remaining < 8) {
4457 * Yes. Tell the TCP dissector where the data
4458 * for this message starts in the data it handed
4459 * us, and how many more bytes we need, and
4462 pinfo->desegment_offset = offset;
4463 pinfo->desegment_len = 4 - length_remaining;
4469 * Find out what kind of a reply it is.
4470 * There are four possible:
4471 * - reply to initial connection
4472 * - errorreply (a request generated an error)
4473 * - requestreply (reply to a request)
4474 * - event (some event occured)
4476 if (g_hash_table_lookup(state->seqtable,
4477 GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN
4478 || (state->iconn_reply == pinfo->fd->num)) {
4480 * Either the connection is in the "initial
4481 * connection" state, or this frame is known
4482 * to have the initial connection reply.
4483 * That means this is the initial connection
4486 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4488 HANDLE_REPLY(plen, length_remaining,
4489 "Initial connection reply",
4490 dissect_x11_initial_reply);
4493 * This isn't an initial connection reply
4494 * (XXX - unless we missed the initial
4495 * connection request). Look at the first
4496 * byte to determine what it is; errors
4497 * start with a byte of 0, replies start
4498 * with a byte of 1, events start with
4499 * a byte with of 2 or greater.
4501 switch (tvb_get_guint8(tvb, offset)) {
4505 HANDLE_REPLY(plen, length_remaining,
4506 "Error", dissect_x11_error);
4510 /* replylength is in units of four. */
4511 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4513 HANDLE_REPLY(plen, length_remaining,
4514 "Reply", dissect_x11_reply);
4520 HANDLE_REPLY(plen, length_remaining,
4521 "Event", dissect_x11_event);
4533 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4534 const char *volatile sep, x11_conv_data_t *volatile state,
4535 gboolean little_endian)
4537 int offset = 0, *offsetp = &offset, length, left, opcode;
4538 int major_opcode, sequence_number;
4539 value_string *vals_p;
4543 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4544 tvb_reported_length_remaining(tvb, offset),
4546 t = proto_item_add_subtree(ti, ett_x11);
4550 * XXX - this doesn't work correctly if either
4552 * 1) the request sequence number wraps in the lower 16
4555 * 2) we don't see the initial connection request and the
4556 * resynchronization of sequence number fails and thus
4557 * don't have the right sequence numbers
4559 * 3) we don't have all the packets in the capture and
4560 * get out of sequence.
4562 * We might, instead, want to assume that a reply is a reply to
4563 * the most recent not-already-replied-to request in the same
4564 * connection. That also might mismatch replies to requests if
4565 * packets are lost, but there's nothing you can do to fix that.
4568 sequence_number = VALUE16(tvb, offset + 2);
4569 opcode = (int)g_hash_table_lookup(state->seqtable,
4570 GINT_TO_POINTER(sequence_number));
4572 if (state->iconn_frame == 0 && state->resync == FALSE) {
4575 * We don't see the initial connection request and no
4576 * resynchronization has been performed yet (first reply),
4577 * set the current sequence number to the one of the
4578 * current reply (this is only performed once).
4580 state->sequencenumber = sequence_number;
4581 state->resync = TRUE;
4584 if (opcode == UNKNOWN_OPCODE) {
4585 if (check_col(pinfo->cinfo, COL_INFO))
4586 col_append_fstr(pinfo->cinfo, COL_INFO,
4587 "%s to unknown request", sep);
4588 proto_item_append_text(ti, ", Reply to unknown request");
4590 if (check_col(pinfo->cinfo, COL_INFO))
4591 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4593 val_to_str(opcode, state->opcode_vals,
4594 "<Unknown opcode %d>"));
4596 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4597 opcode, val_to_str(opcode,
4599 "<Unknown opcode %d>"));
4605 * Replies that need special processing outside tree
4608 case X_QueryExtension:
4611 * if extension is present and request is known:
4612 * store opcode of extension in value_string of
4615 if (!VALUE8(tvb, offset + 8)) {
4620 vals_p = g_hash_table_lookup(state->valtable,
4621 GINT_TO_POINTER(sequence_number));
4622 if (vals_p != NULL) {
4623 major_opcode = VALUE8(tvb, offset + 9);
4624 vals_p->value = major_opcode;
4625 g_hash_table_remove(state->valtable,
4626 GINT_TO_POINTER(sequence_number));
4639 * Requests that expect a reply.
4642 case X_GetWindowAttributes:
4643 REPLYCONTENTS_COMMON();
4649 SEQUENCENUMBER_REPLY(sequencenumber);
4650 REPLYLENGTH(replylength);
4656 CARD16(border_width);
4661 REPLYCONTENTS_COMMON();
4667 SEQUENCENUMBER_REPLY(sequencenumber);
4668 REPLYLENGTH(replylength);
4674 REPLYCONTENTS_COMMON();
4680 SEQUENCENUMBER_REPLY(sequencenumber);
4681 length = REPLYLENGTH(replylength);
4682 ATOM(get_property_type);
4683 CARD32(bytes_after);
4684 CARD32(valuelength);
4688 case X_ListProperties:
4691 SEQUENCENUMBER_REPLY(sequencenumber);
4692 REPLYLENGTH(replylength);
4693 length = CARD16(property_number);
4695 LISTofATOM(properties, length*4);
4698 case X_GetSelectionOwner:
4701 SEQUENCENUMBER_REPLY(sequencenumber);
4702 REPLYLENGTH(replylength);
4708 case X_GrabKeyboard:
4711 SEQUENCENUMBER_REPLY(sequencenumber);
4712 REPLYLENGTH(replylength);
4716 case X_QueryPointer:
4719 SEQUENCENUMBER_REPLY(sequencenumber);
4720 REPLYLENGTH(replylength);
4722 WINDOW(childwindow);
4727 SETofKEYBUTMASK(mask);
4731 case X_GetMotionEvents:
4732 REPLYCONTENTS_COMMON();
4735 case X_TranslateCoords:
4738 SEQUENCENUMBER_REPLY(sequencenumber);
4739 REPLYLENGTH(replylength);
4740 WINDOW(childwindow);
4746 case X_GetInputFocus:
4749 SEQUENCENUMBER_REPLY(sequencenumber);
4750 REPLYLENGTH(replylength);
4758 SEQUENCENUMBER_REPLY(sequencenumber);
4759 REPLYLENGTH(replylength);
4760 LISTofCARD8(keys, 32);
4764 case X_QueryTextExtents:
4767 case X_ListInstalledColormaps:
4768 REPLYCONTENTS_COMMON();
4774 SEQUENCENUMBER_REPLY(sequencenumber);
4775 REPLYLENGTH(replylength);
4785 REPLYCONTENTS_COMMON();
4791 SEQUENCENUMBER_REPLY(sequencenumber);
4792 REPLYLENGTH(replylength);
4794 CARD16(exact_green);
4797 CARD16(visual_green);
4798 CARD16(visual_blue);
4802 case X_QueryBestSize:
4805 SEQUENCENUMBER_REPLY(sequencenumber);
4806 REPLYLENGTH(replylength);
4812 case X_QueryExtension:
4815 SEQUENCENUMBER_REPLY(sequencenumber);
4816 REPLYLENGTH(replylength);
4818 CARD8(major_opcode);
4824 case X_ListExtensions:
4825 REPLYCONTENTS_COMMON();
4828 case X_GetKeyboardMapping:
4829 state->first_keycode =
4830 state->request.GetKeyboardMapping.first_keycode;
4832 state->keysyms_per_keycode =
4833 FIELD8(keysyms_per_keycode);
4834 SEQUENCENUMBER_REPLY(sequencenumber);
4835 length = REPLYLENGTH(replylength);
4837 LISTofKEYSYM(keysyms, state->keycodemap,
4838 state->request.GetKeyboardMapping.first_keycode,
4839 length / state->keysyms_per_keycode,
4840 state->keysyms_per_keycode);
4843 case X_GetKeyboardControl:
4844 REPLYCONTENTS_COMMON();
4847 case X_GetPointerControl:
4850 SEQUENCENUMBER_REPLY(sequencenumber);
4851 REPLYLENGTH(replylength);
4852 CARD16(acceleration_numerator);
4853 CARD16(acceleration_denominator);
4858 case X_GetScreenSaver:
4861 SEQUENCENUMBER_REPLY(sequencenumber);
4862 REPLYLENGTH(replylength);
4865 ENUM8(prefer_blanking);
4866 ENUM8(allow_exposures);
4871 case X_SetPointerMapping:
4872 case X_GetPointerMapping:
4873 case X_SetModifierMapping:
4874 REPLYCONTENTS_COMMON();
4877 case X_GetModifierMapping:
4879 state->keycodes_per_modifier =
4880 FIELD8(keycodes_per_modifier);
4881 SEQUENCENUMBER_REPLY(sequencenumber);
4882 REPLYLENGTH(replylength);
4884 LISTofKEYCODE(state->modifiermap, keycodes,
4885 state->keycodes_per_modifier);
4889 REPLYCONTENTS_COMMON();
4892 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4897 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4900 guint32 bitmask_value;
4903 proto_tree *bitmask_tree;
4905 bitmask_value = VALUE8(tvb, *offsetp);
4906 bitmask_offset = *offsetp;
4909 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4911 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4912 FLAG(same_screen_focus, focus);
4913 FLAG(same_screen_focus, same_screen);
4919 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4920 const char *volatile sep, x11_conv_data_t *volatile state,
4921 gboolean little_endian)
4923 int offset = 0, *offsetp = &offset, left;
4924 unsigned char eventcode;
4928 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4929 t = proto_item_add_subtree(ti, ett_x11);
4931 eventcode = tvb_get_guint8(tvb, offset);
4933 if (check_col(pinfo->cinfo, COL_INFO))
4934 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4935 sep, val_to_str(eventcode, eventcode_vals,
4936 "<Unknown eventcode %u>"));
4938 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4940 "eventcode: %d (%s)",
4942 val_to_str(eventcode, eventcode_vals,
4943 "<Unknown eventcode %u>"));
4946 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4947 eventcode, val_to_str(eventcode, eventcode_vals,
4948 "<Unknown eventcode %u>"));
4953 switch (eventcode) {
4958 /* need to do some prefetching here ... */
4959 code = VALUE8(tvb, offset);
4960 mask = VALUE16(tvb, 28);
4962 KEYCODE_DECODED(keycode, code, mask);
4963 CARD16(event_sequencenumber);
4964 EVENTCONTENTS_COMMON();
4972 BUTTON(eventbutton);
4973 CARD16(event_sequencenumber);
4974 EVENTCONTENTS_COMMON();
4981 CARD16(event_sequencenumber);
4982 EVENTCONTENTS_COMMON();
4989 ENUM8(event_detail);
4990 CARD16(event_sequencenumber);
4991 EVENTCONTENTS_COMMON();
4993 same_screen_focus(tvb, offsetp, t);
4998 ENUM8(focus_detail);
4999 CARD16(event_sequencenumber);
5000 WINDOW(eventwindow);
5010 CARD16(event_sequencenumber);
5011 WINDOW(eventwindow);
5020 case GraphicsExpose:
5022 CARD16(event_sequencenumber);
5028 CARD16(minor_opcode);
5030 CARD8(major_opcode);
5036 CARD16(event_sequencenumber);
5038 CARD16(minor_opcode);
5039 CARD8(major_opcode);
5043 case VisibilityNotify:
5045 CARD16(event_sequencenumber);
5046 WINDOW(eventwindow);
5047 ENUM8(visibility_state);
5053 CARD16(event_sequencenumber);
5055 WINDOW(eventwindow);
5060 CARD16(border_width);
5061 BOOL(override_redirect);
5067 CARD16(event_sequencenumber);
5068 WINDOW(eventwindow);
5075 CARD16(event_sequencenumber);
5076 WINDOW(eventwindow);
5078 BOOL(from_configure);
5084 CARD16(event_sequencenumber);
5085 WINDOW(eventwindow);
5087 BOOL(override_redirect);
5093 CARD16(event_sequencenumber);
5095 WINDOW(eventwindow);
5099 case ReparentNotify:
5101 CARD16(event_sequencenumber);
5102 WINDOW(eventwindow);
5107 BOOL(override_redirect);
5111 case ConfigureNotify:
5113 CARD16(event_sequencenumber);
5114 WINDOW(eventwindow);
5116 WINDOW(above_sibling);
5121 CARD16(border_width);
5122 BOOL(override_redirect);
5126 case ConfigureRequest:
5131 CARD16(event_sequencenumber);
5132 WINDOW(eventwindow);
5141 CARD16(event_sequencenumber);
5142 WINDOW(eventwindow);
5148 case CirculateNotify:
5150 CARD16(event_sequencenumber);
5151 WINDOW(eventwindow);
5158 case CirculateRequest:
5160 CARD16(event_sequencenumber);
5162 WINDOW(eventwindow);
5168 case PropertyNotify:
5170 CARD16(event_sequencenumber);
5171 WINDOW(eventwindow);
5174 ENUM8(property_state);
5178 case SelectionClear:
5180 CARD16(event_sequencenumber);
5187 case SelectionRequest:
5189 CARD16(event_sequencenumber);
5199 case SelectionNotify:
5201 CARD16(event_sequencenumber);
5210 case ColormapNotify:
5212 CARD16(event_sequencenumber);
5213 WINDOW(eventwindow);
5216 ENUM8(colormap_state);
5222 CARD16(event_sequencenumber);
5223 WINDOW(eventwindow);
5225 LISTofBYTE(data, 20);
5233 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5240 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5241 const char *volatile sep, x11_conv_data_t *volatile state _U_,
5242 gboolean little_endian)
5244 int offset = 0, *offsetp = &offset, left;
5245 unsigned char errorcode, error;
5249 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5250 t = proto_item_add_subtree(ti, ett_x11);
5252 error = tvb_get_guint8(tvb, offset);
5255 errorcode = tvb_get_guint8(tvb, offset);
5256 if (check_col(pinfo->cinfo, COL_INFO))
5257 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5258 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5260 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5262 "errorcode: %d (%s)",
5264 val_to_str(errorcode, errorcode_vals,
5265 "<Unknown errocode %u>"));
5268 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
5269 errorcode, val_to_str(errorcode, errorcode_vals,
5270 "<Unknown errorcode %u>"));
5275 CARD16(error_sequencenumber);
5277 switch (errorcode) {
5279 CARD32(error_badvalue);
5286 CARD16(minor_opcode);
5287 CARD8(major_opcode);
5289 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5295 /************************************************************************
5297 *** I N I T I A L I Z A T I O N A N D M A I N ***
5299 ************************************************************************/
5302 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5304 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5305 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5307 if (pinfo->match_port == pinfo->srcport)
5308 dissect_x11_replies(tvb, pinfo, tree);
5310 dissect_x11_requests(tvb, pinfo, tree);
5313 /* Register the protocol with Ethereal */
5314 void proto_register_x11(void)
5317 /* Setup list of header fields */
5318 static hf_register_info hf[] = {
5319 #include "x11-register-info.h"
5322 /* Setup protocol subtree array */
5323 static gint *ett[] = {
5325 &ett_x11_color_flags,
5326 &ett_x11_list_of_arc,
5328 &ett_x11_list_of_atom,
5329 &ett_x11_list_of_card32,
5330 &ett_x11_list_of_color_item,
5331 &ett_x11_color_item,
5332 &ett_x11_list_of_keycode,
5333 &ett_x11_list_of_keysyms,
5335 &ett_x11_list_of_point,
5337 &ett_x11_list_of_rectangle,
5339 &ett_x11_list_of_segment,
5341 &ett_x11_list_of_string8,
5342 &ett_x11_list_of_text_item,
5344 &ett_x11_gc_value_mask,
5345 &ett_x11_event_mask,
5346 &ett_x11_do_not_propagate_mask,
5347 &ett_x11_set_of_key_mask,
5348 &ett_x11_pointer_event_mask,
5349 &ett_x11_window_value_mask,
5350 &ett_x11_configure_window_mask,
5351 &ett_x11_keyboard_value_mask,
5352 &ett_x11_same_screen_focus,
5354 module_t *x11_module;
5356 /* Register the protocol name and description */
5357 proto_x11 = proto_register_protocol("X11", "X11", "x11");
5359 /* Required function calls to register the header fields and subtrees used */
5360 proto_register_field_array(proto_x11, hf, array_length(hf));
5361 proto_register_subtree_array(ett, array_length(ett));
5363 register_init_routine(x11_init_protocol);
5365 x11_module = prefs_register_protocol(proto_x11, NULL);
5366 prefs_register_bool_preference(x11_module, "desegment",
5367 "Reassemble X11 messages spanning multiple TCP segments",
5368 "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
5369 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5374 proto_reg_handoff_x11(void)
5376 dissector_handle_t x11_handle;
5378 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5379 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5380 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5381 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
5382 data_handle = find_dissector("data");