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 */
125 typedef struct _x11_conv_data {
126 struct _x11_conv_data *next;
127 GHashTable *seqtable; /* hashtable of sequencenumber <-> opcode. */
128 GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
129 /* major opcodes including extensions (NULL terminated) */
130 value_string opcode_vals[MAX_OPCODES+1];
131 int sequencenumber; /* sequencenumber of current packet. */
132 guint32 iconn_frame; /* frame # of initial connection request */
133 guint32 iconn_reply; /* frame # of initial connection reply */
134 int byte_order; /* byte order of connection */
135 gboolean resync; /* resynchronization of sequence number performed */
137 int *keycodemap[256]; /* keycode to keysymvalue map. */
138 int keysyms_per_keycode;
140 int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
141 int keycodes_per_modifier;
146 } GetKeyboardMapping;
150 static GMemChunk *x11_state_chunk = NULL;
151 static x11_conv_data_t *x11_conv_data_list;
153 /* Initialize the protocol and registered fields */
154 static int proto_x11 = -1;
156 #include "x11-declarations.h"
158 /* Initialize the subtree pointers */
159 static gint ett_x11 = -1;
160 static gint ett_x11_color_flags = -1;
161 static gint ett_x11_list_of_arc = -1;
162 static gint ett_x11_arc = -1;
163 static gint ett_x11_list_of_atom = -1;
164 static gint ett_x11_list_of_card32 = -1;
165 static gint ett_x11_list_of_color_item = -1;
166 static gint ett_x11_color_item = -1;
167 static gint ett_x11_list_of_keycode = -1;
168 static gint ett_x11_list_of_keysyms = -1;
169 static gint ett_x11_keysym = -1;
170 static gint ett_x11_list_of_point = -1;
171 static gint ett_x11_point = -1;
172 static gint ett_x11_list_of_rectangle = -1;
173 static gint ett_x11_rectangle = -1;
174 static gint ett_x11_list_of_segment = -1;
175 static gint ett_x11_segment = -1;
176 static gint ett_x11_list_of_string8 = -1;
177 static gint ett_x11_list_of_text_item = -1;
178 static gint ett_x11_text_item = -1;
179 static gint ett_x11_gc_value_mask = -1; /* XXX - unused */
180 static gint ett_x11_event_mask = -1; /* XXX - unused */
181 static gint ett_x11_do_not_propagate_mask = -1; /* XXX - unused */
182 static gint ett_x11_set_of_key_mask = -1;
183 static gint ett_x11_pointer_event_mask = -1; /* XXX - unused */
184 static gint ett_x11_window_value_mask = -1; /* XXX - unused */
185 static gint ett_x11_configure_window_mask = -1; /* XXX - unused */
186 static gint ett_x11_keyboard_value_mask = -1; /* XXX - unused */
187 static gint ett_x11_same_screen_focus = -1;
189 /* desegmentation of X11 messages */
190 static gboolean x11_desegment = TRUE;
192 static dissector_handle_t data_handle;
194 #define TCP_PORT_X11 6000
195 #define TCP_PORT_X11_2 6001
196 #define TCP_PORT_X11_3 6002
199 * Round a length to a multiple of 4 bytes.
201 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
203 /************************************************************************
205 *** E N U M T A B L E S D E F I N I T I O N S ***
207 ************************************************************************/
209 static const value_string byte_order_vals[] = {
210 { 'B', "Big-endian" },
211 { 'l', "Little-endian" },
215 static const value_string image_byte_order_vals[] = {
221 static const value_string access_mode_vals[] = {
227 static const value_string all_temporary_vals[] = {
228 { 0, "AllTemporary" },
232 static const value_string alloc_vals[] = {
238 static const value_string allow_events_mode_vals[] = {
239 { 0, "AsyncPointer" },
240 { 1, "SyncPointer" },
241 { 2, "ReplayPointer" },
242 { 3, "AsyncKeyboard" },
243 { 4, "SyncKeyboard" },
244 { 5, "ReplayKeyboard" },
250 static const value_string arc_mode_vals[] = {
256 static const char *atom_predefined_interpretation[] = {
308 "UNDERLINE_POSITION",
309 "UNDERLINE_THICKNESS",
328 static const value_string auto_repeat_mode_vals[] = {
335 static const value_string background_pixmap_vals[] = {
337 { 1, "ParentRelative" },
341 static const value_string backing_store_vals[] = {
348 static const value_string border_pixmap_vals[] = {
349 { 0, "CopyFromParent" },
353 static const value_string button_vals[] = {
354 { 0x8000, "AnyButton" },
358 static const value_string cap_style_vals[] = {
366 static const value_string class_vals[] = {
373 static const value_string close_down_mode_vals[] = {
375 { 1, "RetainPermanent" },
376 { 2, "RetainTemporary" },
380 static const value_string colormap_state_vals[] = {
381 { 0, "Uninstalled" },
386 static const value_string coordinate_mode_vals[] = {
392 static const value_string destination_vals[] = {
393 { 0, "PointerWindow" },
398 static const value_string direction_vals[] = {
399 { 0, "RaiseLowest" },
400 { 1, "LowerHighest" },
404 static const value_string event_detail_vals[] = {
409 { 4, "NonlinearVirtual" },
413 #define FAMILY_INTERNET 0
414 #define FAMILY_DECNET 1
415 #define FAMILY_CHAOS 2
417 static const value_string family_vals[] = {
418 { FAMILY_INTERNET, "Internet" },
419 { FAMILY_DECNET, "DECnet" },
420 { FAMILY_CHAOS, "Chaos" },
424 static const value_string fill_rule_vals[] = {
430 static const value_string fill_style_vals[] = {
434 { 3, "OpaqueStippled" },
438 static const value_string focus_detail_vals[] = {
443 { 4, "NonlinearVirtual" },
445 { 6, "PointerRoot" },
450 static const value_string focus_mode_vals[] = {
454 { 3, "WhileGrabbed" },
458 static const value_string focus_vals[] = {
460 { 1, "PointerRoot" },
464 static const value_string function_vals[] = {
469 { 4, "AndInverted" },
477 { 12, "CopyInverted" },
478 { 13, "OrInverted" },
484 static const value_string grab_mode_vals[] = {
491 static const value_string grab_status_vals[] = {
493 { 1, "AlreadyGrabbed" },
494 { 2, "InvalidTime" },
495 { 3, "NotViewable" },
500 static const value_string gravity_vals[] = {
514 static const value_string image_format_vals[] = {
521 static const value_string image_pixmap_format_vals[] = {
527 static const value_string join_style_vals[] = {
534 static const value_string key_vals[] = {
539 #include "packet-x11-keysym.h"
541 static const value_string line_style_vals[] = {
548 static const value_string mode_vals[] = {
555 static const value_string on_off_vals[] = {
561 static const value_string place_vals[] = {
567 static const value_string property_state_vals[] = {
573 static const value_string visibility_state_vals[] = {
575 { 1, "PartiallyObscured" },
576 { 2, "FullyObscured" },
580 /* Requestcodes. From <X11/Xproto.h>. */
581 #define X_CreateWindow 1
582 #define X_ChangeWindowAttributes 2
583 #define X_GetWindowAttributes 3
584 #define X_DestroyWindow 4
585 #define X_DestroySubwindows 5
586 #define X_ChangeSaveSet 6
587 #define X_ReparentWindow 7
588 #define X_MapWindow 8
589 #define X_MapSubwindows 9
590 #define X_UnmapWindow 10
591 #define X_UnmapSubwindows 11
592 #define X_ConfigureWindow 12
593 #define X_CirculateWindow 13
594 #define X_GetGeometry 14
595 #define X_QueryTree 15
596 #define X_InternAtom 16
597 #define X_GetAtomName 17
598 #define X_ChangeProperty 18
599 #define X_DeleteProperty 19
600 #define X_GetProperty 20
601 #define X_ListProperties 21
602 #define X_SetSelectionOwner 22
603 #define X_GetSelectionOwner 23
604 #define X_ConvertSelection 24
605 #define X_SendEvent 25
606 #define X_GrabPointer 26
607 #define X_UngrabPointer 27
608 #define X_GrabButton 28
609 #define X_UngrabButton 29
610 #define X_ChangeActivePointerGrab 30
611 #define X_GrabKeyboard 31
612 #define X_UngrabKeyboard 32
614 #define X_UngrabKey 34
615 #define X_AllowEvents 35
616 #define X_GrabServer 36
617 #define X_UngrabServer 37
618 #define X_QueryPointer 38
619 #define X_GetMotionEvents 39
620 #define X_TranslateCoords 40
621 #define X_WarpPointer 41
622 #define X_SetInputFocus 42
623 #define X_GetInputFocus 43
624 #define X_QueryKeymap 44
625 #define X_OpenFont 45
626 #define X_CloseFont 46
627 #define X_QueryFont 47
628 #define X_QueryTextExtents 48
629 #define X_ListFonts 49
630 #define X_ListFontsWithInfo 50
631 #define X_SetFontPath 51
632 #define X_GetFontPath 52
633 #define X_CreatePixmap 53
634 #define X_FreePixmap 54
635 #define X_CreateGC 55
636 #define X_ChangeGC 56
638 #define X_SetDashes 58
639 #define X_SetClipRectangles 59
641 #define X_ClearArea 61
642 #define X_CopyArea 62
643 #define X_CopyPlane 63
644 #define X_PolyPoint 64
645 #define X_PolyLine 65
646 #define X_PolySegment 66
647 #define X_PolyRectangle 67
649 #define X_FillPoly 69
650 #define X_PolyFillRectangle 70
651 #define X_PolyFillArc 71
652 #define X_PutImage 72
653 #define X_GetImage 73
654 #define X_PolyText8 74
655 #define X_PolyText16 75
656 #define X_ImageText8 76
657 #define X_ImageText16 77
658 #define X_CreateColormap 78
659 #define X_FreeColormap 79
660 #define X_CopyColormapAndFree 80
661 #define X_InstallColormap 81
662 #define X_UninstallColormap 82
663 #define X_ListInstalledColormaps 83
664 #define X_AllocColor 84
665 #define X_AllocNamedColor 85
666 #define X_AllocColorCells 86
667 #define X_AllocColorPlanes 87
668 #define X_FreeColors 88
669 #define X_StoreColors 89
670 #define X_StoreNamedColor 90
671 #define X_QueryColors 91
672 #define X_LookupColor 92
673 #define X_CreateCursor 93
674 #define X_CreateGlyphCursor 94
675 #define X_FreeCursor 95
676 #define X_RecolorCursor 96
677 #define X_QueryBestSize 97
678 #define X_QueryExtension 98
679 #define X_ListExtensions 99
680 #define X_ChangeKeyboardMapping 100
681 #define X_GetKeyboardMapping 101
682 #define X_ChangeKeyboardControl 102
683 #define X_GetKeyboardControl 103
685 #define X_ChangePointerControl 105
686 #define X_GetPointerControl 106
687 #define X_SetScreenSaver 107
688 #define X_GetScreenSaver 108
689 #define X_ChangeHosts 109
690 #define X_ListHosts 110
691 #define X_SetAccessControl 111
692 #define X_SetCloseDownMode 112
693 #define X_KillClient 113
694 #define X_RotateProperties 114
695 #define X_ForceScreenSaver 115
696 #define X_SetPointerMapping 116
697 #define X_GetPointerMapping 117
698 #define X_SetModifierMapping 118
699 #define X_GetModifierMapping 119
700 #define X_NoOperation 127
701 #define X_FirstExtension 128
702 #define X_LastExtension 255
704 static const value_string opcode_vals[] = {
705 { INITIAL_CONN, "Initial connection request" },
706 { X_CreateWindow, "CreateWindow" },
707 { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
708 { X_GetWindowAttributes, "GetWindowAttributes" },
709 { X_DestroyWindow, "DestroyWindow" },
710 { X_DestroySubwindows, "DestroySubwindows" },
711 { X_ChangeSaveSet, "ChangeSaveSet" },
712 { X_ReparentWindow, "ReparentWindow" },
713 { X_MapWindow, "MapWindow" },
714 { X_MapSubwindows, "MapSubwindows" },
715 { X_UnmapWindow, "UnmapWindow" },
716 { X_UnmapSubwindows, "UnmapSubwindows" },
717 { X_ConfigureWindow, "ConfigureWindow" },
718 { X_CirculateWindow, "CirculateWindow" },
719 { X_GetGeometry, "GetGeometry" },
720 { X_QueryTree, "QueryTree" },
721 { X_InternAtom, "InternAtom" },
722 { X_GetAtomName, "GetAtomName" },
723 { X_ChangeProperty, "ChangeProperty" },
724 { X_DeleteProperty, "DeleteProperty" },
725 { X_GetProperty, "GetProperty" },
726 { X_ListProperties, "ListProperties" },
727 { X_SetSelectionOwner, "SetSelectionOwner" },
728 { X_GetSelectionOwner, "GetSelectionOwner" },
729 { X_ConvertSelection, "ConvertSelection" },
730 { X_SendEvent, "SendEvent" },
731 { X_GrabPointer, "GrabPointer" },
732 { X_UngrabPointer, "UngrabPointer" },
733 { X_GrabButton, "GrabButton" },
734 { X_UngrabButton, "UngrabButton" },
735 { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
736 { X_GrabKeyboard, "GrabKeyboard" },
737 { X_UngrabKeyboard, "UngrabKeyboard" },
738 { X_GrabKey, "GrabKey" },
739 { X_UngrabKey, "UngrabKey" },
740 { X_AllowEvents, "AllowEvents" },
741 { X_GrabServer, "GrabServer" },
742 { X_UngrabServer, "UngrabServer" },
743 { X_QueryPointer, "QueryPointer" },
744 { X_GetMotionEvents, "GetMotionEvents" },
745 { X_TranslateCoords, "TranslateCoordinates" },
746 { X_WarpPointer, "WarpPointer" },
747 { X_SetInputFocus, "SetInputFocus" },
748 { X_GetInputFocus, "GetInputFocus" },
749 { X_QueryKeymap, "QueryKeymap" },
750 { X_OpenFont, "OpenFont" },
751 { X_CloseFont, "CloseFont" },
752 { X_QueryFont, "QueryFont" },
753 { X_QueryTextExtents, "QueryTextExtents" },
754 { X_ListFonts, "ListFonts" },
755 { X_ListFontsWithInfo, "ListFontsWithInfo" },
756 { X_SetFontPath, "SetFontPath" },
757 { X_GetFontPath, "GetFontPath" },
758 { X_CreatePixmap, "CreatePixmap" },
759 { X_FreePixmap, "FreePixmap" },
760 { X_CreateGC, "CreateGC" },
761 { X_ChangeGC, "ChangeGC" },
762 { X_CopyGC, "CopyGC" },
763 { X_SetDashes, "SetDashes" },
764 { X_SetClipRectangles, "SetClipRectangles" },
765 { X_FreeGC, "FreeGC" },
766 { X_ClearArea, "ClearArea" },
767 { X_CopyArea, "CopyArea" },
768 { X_CopyPlane, "CopyPlane" },
769 { X_PolyPoint, "PolyPoint" },
770 { X_PolyLine, "PolyLine" },
771 { X_PolySegment, "PolySegment" },
772 { X_PolyRectangle, "PolyRectangle" },
773 { X_PolyArc, "PolyArc" },
774 { X_FillPoly, "FillPoly" },
775 { X_PolyFillRectangle, "PolyFillRectangle" },
776 { X_PolyFillArc, "PolyFillArc" },
777 { X_PutImage, "PutImage" },
778 { X_GetImage, "GetImage" },
779 { X_PolyText8, "PolyText8" },
780 { X_PolyText16, "PolyText16" },
781 { X_ImageText8, "ImageText8" },
782 { X_ImageText16, "ImageText16" },
783 { X_CreateColormap, "CreateColormap" },
784 { X_FreeColormap, "FreeColormap" },
785 { X_CopyColormapAndFree, "CopyColormapAndFree" },
786 { X_InstallColormap, "InstallColormap" },
787 { X_UninstallColormap, "UninstallColormap" },
788 { X_ListInstalledColormaps, "ListInstalledColormaps" },
789 { X_AllocColor, "AllocColor" },
790 { X_AllocNamedColor, "AllocNamedColor" },
791 { X_AllocColorCells, "AllocColorCells" },
792 { X_AllocColorPlanes, "AllocColorPlanes" },
793 { X_FreeColors, "FreeColors" },
794 { X_StoreColors, "StoreColors" },
795 { X_StoreNamedColor, "StoreNamedColor" },
796 { X_QueryColors, "QueryColors" },
797 { X_LookupColor, "LookupColor" },
798 { X_CreateCursor, "CreateCursor" },
799 { X_CreateGlyphCursor, "CreateGlyphCursor" },
800 { X_FreeCursor, "FreeCursor" },
801 { X_RecolorCursor, "RecolorCursor" },
802 { X_QueryBestSize, "QueryBestSize" },
803 { X_QueryExtension, "QueryExtension" },
804 { X_ListExtensions, "ListExtensions" },
805 { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
806 { X_GetKeyboardMapping, "GetKeyboardMapping" },
807 { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
808 { X_GetKeyboardControl, "GetKeyboardControl" },
810 { X_ChangePointerControl, "ChangePointerControl" },
811 { X_GetPointerControl, "GetPointerControl" },
812 { X_SetScreenSaver, "SetScreenSaver" },
813 { X_GetScreenSaver, "GetScreenSaver" },
814 { X_ChangeHosts, "ChangeHosts" },
815 { X_ListHosts, "ListHosts" },
816 { X_SetAccessControl, "SetAccessControl" },
817 { X_SetCloseDownMode, "SetCloseDownMode" },
818 { X_KillClient, "KillClient" },
819 { X_RotateProperties, "RotateProperties" },
820 { X_ForceScreenSaver, "ForceScreenSaver" },
821 { X_SetPointerMapping, "SetPointerMapping" },
822 { X_GetPointerMapping, "GetPointerMapping" },
823 { X_SetModifierMapping, "SetModifierMapping" },
824 { X_GetModifierMapping, "GetModifierMapping" },
825 { X_NoOperation, "NoOperation" },
829 /* Eventscodes. From <X11/X.h>. */
832 #define ButtonPress 4
833 #define ButtonRelease 5
834 #define MotionNotify 6
835 #define EnterNotify 7
836 #define LeaveNotify 8
839 #define KeymapNotify 11
841 #define GraphicsExpose 13
843 #define VisibilityNotify 15
844 #define CreateNotify 16
845 #define DestroyNotify 17
846 #define UnmapNotify 18
848 #define MapRequest 20
849 #define ReparentNotify 21
850 #define ConfigureNotify 22
851 #define ConfigureRequest 23
852 #define GravityNotify 24
853 #define ResizeRequest 25
854 #define CirculateNotify 26
855 #define CirculateRequest 27
856 #define PropertyNotify 28
857 #define SelectionClear 29
858 #define SelectionRequest 30
859 #define SelectionNotify 31
860 #define ColormapNotify 32
861 #define ClientMessage 33
862 #define MappingNotify 34
863 #define FirstExtensionEvent 64
864 #define LastExtensionEvent 127
866 static const value_string eventcode_vals[] = {
867 { KeyPress, "KeyPress" },
868 { KeyRelease, "KeyRelease" },
869 { ButtonPress, "ButtonPress" },
870 { ButtonRelease, "ButtonRelease" },
871 { MotionNotify, "MotionNotify" },
872 { EnterNotify, "EnterNotify" },
873 { LeaveNotify, "LeaveNotify" },
874 { FocusIn, "FocusIn" },
875 { FocusOut, "FocusOut" },
876 { KeymapNotify, "KeymapNotify" },
877 { Expose, "Expose" },
878 { GraphicsExpose, "GraphicsExpose" },
879 { NoExpose, "NoExpose" },
880 { VisibilityNotify, "VisibilityNotify" },
881 { CreateNotify, "CreateNotify" },
882 { DestroyNotify, "DestroyNotify" },
883 { UnmapNotify, "UnmapNotify" },
884 { MapNotify, "MapNotify" },
885 { MapRequest, "MapRequest" },
886 { ReparentNotify, "ReparentNotify" },
887 { ConfigureNotify, "ConfigureNotify" },
888 { ConfigureRequest, "ConfigureRequest" },
889 { GravityNotify, "GravityNotify" },
890 { ResizeRequest, "ResizeRequest" },
891 { CirculateNotify, "CirculateNotify" },
892 { CirculateRequest, "CirculateRequest" },
893 { PropertyNotify, "PropertyNotify" },
894 { SelectionClear, "SelectionClear" },
895 { SelectionRequest, "SelectionRequest" },
896 { SelectionNotify, "SelectionNotify" },
897 { ColormapNotify, "ColormapNotify" },
898 { ClientMessage, "ClientMessage" },
899 { MappingNotify, "MappingNotify" },
903 /* Errorcodes. From <X11/X.h> */
904 #define Success 0 /* everything's okay */
905 #define BadRequest 1 /* bad request code */
906 #define BadValue 2 /* int parameter out of range */
907 #define BadWindow 3 /* parameter not a Window */
908 #define BadPixmap 4 /* parameter not a Pixmap */
909 #define BadAtom 5 /* parameter not an Atom */
910 #define BadCursor 6 /* parameter not a Cursor */
911 #define BadFont 7 /* parameter not a Font */
912 #define BadMatch 8 /* parameter mismatch */
913 #define BadDrawable 9 /* parameter not a Pixmap or Window */
914 #define BadAccess 10 /* depending on context:
915 - key/button already grabbed
916 - attempt to free an illegal
918 - attempt to store into a read-only
920 - attempt to modify the access control
921 list from other than the local host.
923 #define BadAlloc 11 /* insufficient resources */
924 #define BadColor 12 /* no such colormap */
925 #define BadGC 13 /* parameter not a GC */
926 #define BadIDChoice 14 /* choice not in range or already used */
927 #define BadName 15 /* font or color name doesn't exist */
928 #define BadLength 16 /* Request length incorrect */
929 #define BadImplementation 17 /* server is defective */
931 #define FirstExtensionError 128
932 #define LastExtensionError 255
934 static const value_string errorcode_vals[] = {
935 { Success, "Success" },
936 { BadRequest, "BadRequest" },
937 { BadValue, "BadValue" },
938 { BadWindow, "BadWindow" },
939 { BadPixmap, "BadPixmap" },
940 { BadAtom, "BadAtom" },
941 { BadCursor, "BadCursor" },
942 { BadFont, "BadFont" },
943 { BadMatch, "BadMatch" },
944 { BadDrawable, "BadDrawable" },
945 { BadAccess, "BadAccess" },
946 { BadAlloc, "BadAlloc" },
947 { BadColor, "BadColor" },
949 { BadIDChoice, "BadIDChoice" },
950 { BadName, "BadName" },
951 { BadLength, "BadLength" },
952 { BadImplementation, "BadImplementation" },
953 { FirstExtensionError, "FirstExtensionError" },
954 { LastExtensionError, "LastExtensionError" },
958 static const value_string ordering_vals[] = {
966 static const value_string plane_mask_vals[] = {
967 { 0xFFFFFFFF, "AllPlanes" },
971 static const value_string pointer_keyboard_mode_vals[] = {
972 { 0, "Synchronous" },
973 { 1, "Asynchronous" },
977 static const value_string revert_to_vals[] = {
979 { 1, "PointerRoot" },
984 static const value_string insert_delete_vals[] = {
990 static const value_string screen_saver_mode_vals[] = {
996 static const value_string shape_vals[] = {
1003 static const value_string stack_mode_vals[] = {
1012 static const value_string subwindow_mode_vals[] = {
1013 { 0, "ClipByChildren" },
1014 { 1, "IncludeInferiors" },
1018 static const value_string window_class_vals[] = {
1019 { 0, "CopyFromParent" },
1020 { 1, "InputOutput" },
1025 static const value_string yes_no_default_vals[] = {
1032 static const value_string zero_is_any_property_type_vals[] = {
1033 { 0, "AnyPropertyType" },
1037 static const value_string zero_is_none_vals[] = {
1042 /* we have not seen packet before. */
1043 #define PACKET_IS_NEW(pinfo) \
1044 (!((pinfo)->fd->flags.visited))
1046 /************************************************************************
1048 *** F I E L D D E C O D I N G M A C R O S ***
1050 ************************************************************************/
1052 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
1053 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
1054 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
1056 #define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
1057 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
1058 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
1060 #define BITFIELD(TYPE, position, name) {\
1062 int save = *offsetp;\
1063 proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
1064 bitmask_size, little_endian); \
1065 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
1067 unused = save + 4 - *offsetp;\
1069 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
1070 *offsetp = save + 4;\
1074 #define FLAG(position, name) {\
1075 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
1077 #define FLAG_IF_NONZERO(position, name) do {\
1078 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
1079 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
1081 #define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
1082 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
1083 #define BITMASK(name, size) {\
1085 guint32 bitmask_value; \
1086 int bitmask_offset; \
1088 proto_tree *bitmask_tree; \
1089 bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
1090 ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
1091 (guint32)VALUE32(tvb, *offsetp))); \
1092 bitmask_offset = *offsetp; \
1093 bitmask_size = size; \
1094 ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
1095 bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
1097 #define ENDBITMASK }
1098 #define BITMASK8(name) BITMASK(name, 1);
1099 #define BITMASK16(name) BITMASK(name, 2);
1100 #define BITMASK32(name) BITMASK(name, 4);
1101 #define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
1102 #define BUTTON(name) FIELD8(name)
1103 #define CARD8(name) FIELD8(name)
1104 #define CARD16(name) (FIELD16(name))
1105 #define CARD32(name) (FIELD32(name))
1106 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1107 #define COLORMAP(name) FIELD32(name)
1108 #define CURSOR(name) FIELD32(name)
1109 #define DRAWABLE(name) FIELD32(name)
1110 #define ENUM8(name) (FIELD8(name))
1111 #define ENUM16(name) (FIELD16(name))
1112 #define FONT(name) FIELD32(name)
1113 #define FONTABLE(name) FIELD32(name)
1114 #define GCONTEXT(name) FIELD32(name)
1115 #define INT8(name) FIELD8(name)
1116 #define INT16(name) FIELD16(name)
1117 #define INT32(name) FIELD32(name)
1118 #define KEYCODE(name) FIELD8(name)
1119 #define KEYCODE_DECODED(name, keycode, mask) do { \
1120 proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
1121 keycode, "keycode: %d (%s)", \
1122 keycode, keycode2keysymString(state->keycodemap, \
1123 state->first_keycode, state->keysyms_per_keycode, \
1124 state->modifiermap, state->keycodes_per_modifier, \
1129 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
1130 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1131 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1132 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1133 #define LISTofIPADDRESS(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), FALSE); }
1134 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1135 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1136 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1137 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1138 keysyms_per_keycode) {\
1139 listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1140 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1141 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1142 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1143 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1144 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1145 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1146 #define OPCODE() { opcode = FIELD8(opcode); }
1147 #define PIXMAP(name) { FIELD32(name); }
1148 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1149 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1150 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1151 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1152 #define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 1); }
1153 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1154 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1155 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1156 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1157 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
1158 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
1159 #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; }
1160 #define WINDOW(name) { FIELD32(name); }
1161 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1163 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1164 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1165 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1166 #define REPLY(name) FIELD8(name);
1167 #define REPLYLENGTH(name) FIELD32(name);
1169 #define EVENTCONTENTS_COMMON() do { \
1171 WINDOW(rootwindow); \
1172 WINDOW(eventwindow); \
1173 WINDOW(childwindow); \
1178 setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
1181 #define SEQUENCENUMBER_REPLY(name) do { \
1184 seqno = VALUE16(tvb, *offsetp); \
1185 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1186 *offsetp, sizeof(seqno), seqno, \
1187 "sequencenumber: %d (%s)", \
1189 val_to_str(opcode, state->opcode_vals, "<Unknown opcode %d>")); \
1190 *offsetp += sizeof(seqno); \
1193 #define REPLYCONTENTS_COMMON() do { \
1195 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1196 1, little_endian); \
1198 SEQUENCENUMBER_REPLY(sequencenumber); \
1199 REPLYLENGTH(replylength); \
1200 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1201 tvb_reported_length_remaining(tvb, offset), little_endian); \
1202 offset += tvb_reported_length_remaining(tvb, offset); \
1206 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1207 if (length_remaining < plen) { \
1208 if (x11_desegment && pinfo->can_desegment) { \
1209 pinfo->desegment_offset = offset; \
1210 pinfo->desegment_len = plen - length_remaining;\
1213 ; /* XXX yes, what then? Need to skip/join. */ \
1216 if (length_remaining > plen) \
1217 length_remaining = plen; \
1218 next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1220 if (sep == NULL) { \
1221 if (check_col(pinfo->cinfo, COL_INFO)) \
1222 col_add_str(pinfo->cinfo, COL_INFO, str); \
1227 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1230 CATCH(BoundsError) { \
1233 CATCH(ReportedBoundsError) { \
1234 show_reported_bounds_error(next_tvb, pinfo, tree); \
1242 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1243 const char *sep, x11_conv_data_t *volatile state,
1244 gboolean little_endian);
1247 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1248 const char *volatile sep, x11_conv_data_t *volatile state,
1249 gboolean little_endian);
1252 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1253 const char *volatile sep, x11_conv_data_t *volatile state,
1254 gboolean little_endian);
1257 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1258 const char *volatile sep, x11_conv_data_t *volatile state,
1259 gboolean little_endian);
1261 static x11_conv_data_t *
1262 x11_stateinit(conversation_t *conversation);
1265 keysymString(guint32 v);
1268 /************************************************************************
1270 *** D E C O D I N G F I E L D S ***
1272 ************************************************************************/
1274 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1275 gboolean little_endian)
1277 const char *interpretation = NULL;
1279 guint32 v = VALUE32(tvb, *offsetp);
1280 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1281 interpretation = atom_predefined_interpretation[v];
1283 interpretation = "Not a predefined atom";
1285 header_field_info *hfi = proto_registrar_get_nth(hf);
1287 interpretation = match_strval(v, cVALS(hfi -> strings));
1289 if (!interpretation) interpretation = "error in Xlib client program ?";
1290 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1291 proto_registrar_get_nth(hf) -> name, v, interpretation);
1295 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1297 guint32 v = VALUE8(tvb, *offsetp);
1298 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1303 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1305 unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1309 if (do_red_green_blue) {
1312 char *bp = buffer + sprintf(buffer, "flags: ");
1314 if (do_red_green_blue & 0x1) {
1315 bp += sprintf(bp, "DoRed");
1319 if (do_red_green_blue & 0x2) {
1320 if (sep) bp += sprintf(bp, " | ");
1321 bp += sprintf(bp, "DoGreen");
1325 if (do_red_green_blue & 0x4) {
1326 if (sep) bp += sprintf(bp, " | ");
1327 bp += sprintf(bp, "DoBlue");
1331 if (do_red_green_blue & 0xf8) {
1332 if (sep) bp += sprintf(bp, " + ");
1333 sprintf(bp, "trash");
1336 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1338 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1339 if (do_red_green_blue & 0x1)
1340 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1341 do_red_green_blue & 0x1);
1342 if (do_red_green_blue & 0x2)
1343 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1344 do_red_green_blue & 0x2);
1345 if (do_red_green_blue & 0x4)
1346 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1347 do_red_green_blue & 0x4);
1348 if (do_red_green_blue & 0xf8)
1349 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1350 do_red_green_blue & 0xf8);
1352 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1357 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1358 int hf, const char *nullInterpretation)
1360 guint8 v = VALUE8(tvb, *offsetp);
1363 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1364 proto_registrar_get_nth(hf) -> name,
1365 nullInterpretation);
1367 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1371 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1372 int length, gboolean little_endian)
1374 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1375 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1377 gint16 x = VALUE16(tvb, *offsetp);
1378 gint16 y = VALUE16(tvb, *offsetp + 2);
1379 guint16 width = VALUE16(tvb, *offsetp + 4);
1380 guint16 height = VALUE16(tvb, *offsetp + 6);
1381 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1382 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1384 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1385 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1386 width, height, x, y, angle1, angle2,
1387 angle1 / 64.0, angle2 / 64.0);
1388 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1389 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1391 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1393 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1395 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1397 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1399 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1404 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1405 int length, gboolean little_endian)
1407 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1408 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1410 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1413 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1414 int length, gboolean little_endian)
1416 if (length <= 0) length = 1;
1417 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1421 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1422 int hf_item, int length, gboolean little_endian)
1424 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1425 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1427 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1432 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1433 int length, gboolean little_endian)
1435 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1436 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1440 unsigned do_red_green_blue;
1441 guint16 red, green, blue;
1446 red = VALUE16(tvb, *offsetp + 4);
1447 green = VALUE16(tvb, *offsetp + 6);
1448 blue = VALUE16(tvb, *offsetp + 8);
1449 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1451 bp = buffer + sprintf(buffer, "colorItem: ");
1453 if (do_red_green_blue & 0x1) {
1454 bp += sprintf(bp, "red = %d", red);
1457 if (do_red_green_blue & 0x2) {
1458 bp += sprintf(bp, "%sgreen = %d", sep, green);
1461 if (do_red_green_blue & 0x4)
1462 bp += sprintf(bp, "%sblue = %d", sep, blue);
1464 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1465 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1466 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1468 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1470 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1472 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1474 colorFlags(tvb, offsetp, ttt);
1475 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1480 static GTree *keysymTable = NULL;
1482 static gint compareGuint32(gconstpointer a, gconstpointer b)
1484 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1488 XConvertCase(register int sym, int *lower, int *upper)
1493 case 0: /* Latin 1 */
1494 if ((sym >= XK_A) && (sym <= XK_Z))
1495 *lower += (XK_a - XK_A);
1496 else if ((sym >= XK_a) && (sym <= XK_z))
1497 *upper -= (XK_a - XK_A);
1498 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1499 *lower += (XK_agrave - XK_Agrave);
1500 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1501 *upper -= (XK_agrave - XK_Agrave);
1502 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1503 *lower += (XK_oslash - XK_Ooblique);
1504 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1505 *upper -= (XK_oslash - XK_Ooblique);
1507 case 1: /* Latin 2 */
1508 /* Assume the KeySym is a legal value (ignore discontinuities) */
1509 if (sym == XK_Aogonek)
1510 *lower = XK_aogonek;
1511 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1512 *lower += (XK_lstroke - XK_Lstroke);
1513 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1514 *lower += (XK_scaron - XK_Scaron);
1515 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1516 *lower += (XK_zcaron - XK_Zcaron);
1517 else if (sym == XK_aogonek)
1518 *upper = XK_Aogonek;
1519 else if (sym >= XK_lstroke && sym <= XK_sacute)
1520 *upper -= (XK_lstroke - XK_Lstroke);
1521 else if (sym >= XK_scaron && sym <= XK_zacute)
1522 *upper -= (XK_scaron - XK_Scaron);
1523 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1524 *upper -= (XK_zcaron - XK_Zcaron);
1525 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1526 *lower += (XK_racute - XK_Racute);
1527 else if (sym >= XK_racute && sym <= XK_tcedilla)
1528 *upper -= (XK_racute - XK_Racute);
1530 case 2: /* Latin 3 */
1531 /* Assume the KeySym is a legal value (ignore discontinuities) */
1532 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1533 *lower += (XK_hstroke - XK_Hstroke);
1534 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1535 *lower += (XK_gbreve - XK_Gbreve);
1536 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1537 *upper -= (XK_hstroke - XK_Hstroke);
1538 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1539 *upper -= (XK_gbreve - XK_Gbreve);
1540 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1541 *lower += (XK_cabovedot - XK_Cabovedot);
1542 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1543 *upper -= (XK_cabovedot - XK_Cabovedot);
1545 case 3: /* Latin 4 */
1546 /* Assume the KeySym is a legal value (ignore discontinuities) */
1547 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1548 *lower += (XK_rcedilla - XK_Rcedilla);
1549 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1550 *upper -= (XK_rcedilla - XK_Rcedilla);
1551 else if (sym == XK_ENG)
1553 else if (sym == XK_eng)
1555 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1556 *lower += (XK_amacron - XK_Amacron);
1557 else if (sym >= XK_amacron && sym <= XK_umacron)
1558 *upper -= (XK_amacron - XK_Amacron);
1560 case 6: /* Cyrillic */
1561 /* Assume the KeySym is a legal value (ignore discontinuities) */
1562 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1563 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1564 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1565 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1566 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1567 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1568 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1569 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1572 /* Assume the KeySym is a legal value (ignore discontinuities) */
1573 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1574 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1575 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1576 sym != XK_Greek_iotaaccentdieresis &&
1577 sym != XK_Greek_upsilonaccentdieresis)
1578 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1579 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1580 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1581 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1582 sym != XK_Greek_finalsmallsigma)
1583 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1589 keycode2keysymString(int *keycodemap[256], int first_keycode,
1590 int keysyms_per_keycode,
1591 int *modifiermap[array_length(modifiers)],
1592 int keycodes_per_modifier,
1593 guint32 keycode, guint32 bitmask)
1595 static char buf[32];
1597 int groupmodkc, numlockkc, numlockmod, groupmod;
1598 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1599 int lockmod_is_nosymbol = 1;
1600 int modifier, kc, keysym;
1602 if ((syms = keycodemap[keycode]) == NULL)
1605 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1606 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1607 if (keycodemap[kc] == NULL)
1609 switch (keycodemap[kc][keysym]) {
1619 lockmod_is_capslock = kc;
1623 lockmod_is_shiftlock = kc;
1630 * If we have not seen the modifiermap we don't know what the
1631 * keycode translates to, but we do know it's one of the keys
1632 * in syms (give or take a case-conversion), so we could in
1633 * theory list them all.
1635 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1638 /* find out what the numlockmodifer and groupmodifier is. */
1639 for (modifier = 0, numlockmod = groupmod = -1;
1640 modifier < (int)array_length(modifiers) && numlockmod == -1;
1642 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1643 if (modifiermap[modifier][kc] == numlockkc)
1644 numlockmod = modifier;
1645 else if (modifiermap[modifier][kc] == groupmodkc)
1646 groupmod = modifier;
1649 * ... and what the lockmodifier is interpreted as.
1650 * (X11v4r6 ref, keyboard and pointers section.)
1652 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1653 if (modifiermap[1][kc] == lockmod_is_capslock) {
1654 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1657 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1658 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1664 * This is (how I understand) the X11v4R6 protocol description given
1665 * in A. Nye's book. It is quite different from the
1666 * code in _XTranslateKey() in the file
1667 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1668 * as shipped with XFree, and doesn't work correctly, nor do I see
1669 * how it could (e.g. the case of lower/uppercase-letters).
1670 * -- Michael Shuldman
1673 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1674 && ((syms[1] >= 0xff80
1675 && syms[1] <= 0xffbd)
1676 || (syms[1] >= 0x11000000
1677 && syms[1] <= 0x1100ffff))) {
1678 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1679 return keysymString(syms[groupmod + 0]);
1681 if (syms[groupmod + 1] == NoSymbol)
1682 return keysymString(syms[groupmod + 0]);
1684 return keysymString(syms[groupmod + 1]);
1686 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1687 return keysymString(syms[groupmod + 0]);
1688 else if (!(bitmask & ShiftMask)
1689 && ((bitmask & LockMask) && lockmod_is_capslock))
1690 if (islower(syms[groupmod + 0]))
1691 /* return toupper(keysymString(syms[groupmod + 0])); */
1692 return "Uppercase"; /* XXX */
1694 return keysymString(syms[groupmod + 0]);
1696 else if ((bitmask & ShiftMask)
1697 && ((bitmask & LockMask) && lockmod_is_capslock))
1698 if (islower(syms[groupmod + 1]))
1699 /* return toupper(keysymString(syms[groupmod + 1])); */
1700 return "Uppercase"; /* XXX */
1702 return keysymString(syms[groupmod + 1]);
1704 else if ((bitmask & ShiftMask)
1705 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1706 return keysymString(syms[groupmod + 1]);
1707 #else /* _XTranslateKey() based code. */
1709 while (keysyms_per_keycode > 2
1710 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1711 --keysyms_per_keycode;
1712 if (keysyms_per_keycode > 2
1713 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1715 keysyms_per_keycode -= 2;
1718 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1719 && keysyms_per_keycode > 1
1720 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1721 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1722 if ((bitmask & ShiftMask)
1723 || (bitmask & LockMask && lockmod_is_shiftlock))
1728 else if (!(bitmask & ShiftMask)
1729 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1730 if (keysyms_per_keycode == 1
1731 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1734 XConvertCase(syms[0], &keysym, &usym);
1739 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1742 if (keysyms_per_keycode == 1
1743 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1744 XConvertCase(syms[0], &lsym, &usym);
1750 if (keysyms_per_keycode == 1
1751 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1754 XConvertCase(keysym, &lsym, &usym);
1756 if (!(bitmask & ShiftMask) && keysym != syms[0]
1757 && ((keysym != usym) || (lsym == usym)))
1758 XConvertCase(syms[0], &lsym, &usym);
1762 if (keysym == XK_VoidSymbol)
1765 sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1770 static const char *keysymString(guint32 v)
1775 /* This table is so big that we built it only if necessary */
1777 const value_string *p = keysym_vals_source;
1778 keysymTable = g_tree_new(compareGuint32);
1779 for(; p -> strptr; p++)
1780 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), (gpointer) (p -> strptr) );
1782 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1783 return res ? res : "<Unknown>";
1786 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1787 int *modifiermap[], int keycodes_per_modifier,
1788 gboolean little_endian)
1790 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1791 array_length(modifiers) * keycodes_per_modifier, little_endian);
1792 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1795 for (m = 0; m < array_length(modifiers);
1796 ++m, *offsetp += keycodes_per_modifier) {
1801 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1803 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1805 tikc = proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1806 *offsetp, keycodes_per_modifier, p, "item: ");
1807 for(i = 0; i < keycodes_per_modifier; ++i) {
1811 proto_item_append_text(tikc, " %s=%d", modifiers[m], c);
1813 modifiermap[m][i] = c;
1818 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1819 int hf_item, int *keycodemap[256],
1820 int keycode_first, int keycode_count,
1821 int keysyms_per_keycode, gboolean little_endian)
1823 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1824 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1829 DISSECTOR_ASSERT(keycode_first >= 0);
1830 DISSECTOR_ASSERT(keycode_count >= 0);
1832 for (keycode = keycode_first; keycode_count > 0;
1833 ++keycode, --keycode_count) {
1834 if (keycode >= 256) {
1835 proto_tree_add_text(tt, tvb, *offsetp, 4 * keysyms_per_keycode,
1836 "keycode value %d is out of range", keycode);
1837 *offsetp += 4 * keysyms_per_keycode;
1840 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1841 4 * keysyms_per_keycode, "keysyms (keycode %d):", keycode);
1843 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1845 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1847 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1849 for(i = 0; i < keysyms_per_keycode; ++i) {
1850 /* keysymvalue = byte3 * 256 + byte4. */
1851 guint32 v = VALUE32(tvb, *offsetp);
1853 proto_item_append_text(tti, " %s", keysymString(v));
1854 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1855 tvb, *offsetp, 4, v,
1856 "keysym (keycode %d): 0x%08x (%s)",
1857 keycode, v, keysymString(v));
1859 keycodemap[keycode][i] = v;
1863 for (i = 1; i < keysyms_per_keycode; ++i)
1864 if (keycodemap[keycode][i] != NoSymbol)
1867 if (i == keysyms_per_keycode) {
1868 /* all but (possibly) first were NoSymbol. */
1869 if (keysyms_per_keycode == 4) {
1870 keycodemap[keycode][1] = NoSymbol;
1871 keycodemap[keycode][2] = keycodemap[keycode][0];
1872 keycodemap[keycode][3] = NoSymbol;
1878 for (i = 2; i < keysyms_per_keycode; ++i)
1879 if (keycodemap[keycode][i] != NoSymbol)
1881 if (i == keysyms_per_keycode) {
1882 /* all but (possibly) first two were NoSymbol. */
1883 if (keysyms_per_keycode == 4) {
1884 keycodemap[keycode][2] = keycodemap[keycode][0];
1885 keycodemap[keycode][3] = keycodemap[keycode][1];
1893 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1894 int length, gboolean little_endian)
1896 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1897 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1903 x = VALUE16(tvb, *offsetp);
1904 y = VALUE16(tvb, *offsetp + 2);
1906 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1907 ttt = proto_item_add_subtree(tti, ett_x11_point);
1908 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1910 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1915 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1916 int length, gboolean little_endian)
1918 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1919 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1922 unsigned width, height;
1926 x = VALUE16(tvb, *offsetp);
1927 y = VALUE16(tvb, *offsetp + 2);
1928 width = VALUE16(tvb, *offsetp + 4);
1929 height = VALUE16(tvb, *offsetp + 6);
1931 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1932 "rectangle: %dx%d+%d+%d", width, height, x, y);
1933 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1934 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1936 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1938 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1940 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1945 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1946 int length, gboolean little_endian)
1948 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1949 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1951 gint16 x1, y1, x2, y2;
1955 x1 = VALUE16(tvb, *offsetp);
1956 y1 = VALUE16(tvb, *offsetp + 2);
1957 x2 = VALUE16(tvb, *offsetp + 4);
1958 y2 = VALUE16(tvb, *offsetp + 6);
1960 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1961 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1962 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1963 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1965 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1967 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1969 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1974 /* XXX - the protocol tree code should handle non-printable characters.
1975 Note that "non-printable characters" may depend on your locale.... */
1976 static void stringCopy(char *dest, const char *source, int length)
1981 if (!isgraph(c) && c != ' ') c = '.';
1987 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1988 int hf_item, int length, gboolean little_endian)
1991 guint allocated = 0;
1996 /* Compute total length */
1998 int scanning_offset = *offsetp; /* Scanning pointer */
2000 for(i = length; i; i--) {
2001 l = tvb_get_guint8(tvb, scanning_offset);
2002 scanning_offset += 1 + l;
2005 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2006 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2009 * In case we throw an exception, clean up whatever stuff we've
2010 * allocated (if any).
2012 CLEANUP_PUSH(g_free, s);
2015 unsigned l = VALUE8(tvb, *offsetp);
2016 if (allocated < (l + 1)) {
2017 /* g_realloc doesn't work ??? */
2019 s = g_malloc(l + 1);
2022 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2023 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2028 * Call the cleanup handler to free the string and pop the handler.
2030 CLEANUP_CALL_AND_POP;
2033 #define STRING16_MAX_DISPLAYED_LENGTH 150
2035 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2037 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2038 for(; length > 0; offset += 2, length--) {
2039 if (tvb_get_guint8(tvb, offset))
2045 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2047 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2048 int hf, int hf_bytes,
2049 int offset, unsigned length,
2050 char **s, int *sLength,
2051 gboolean little_endian)
2053 int truncated = FALSE;
2054 unsigned l = length / 2;
2056 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2058 int soffset = offset;
2060 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2062 l = STRING16_MAX_DISPLAYED_LENGTH;
2064 if (*sLength < (int) l + 3) {
2066 *s = g_malloc(l + 3);
2071 if (truncated) l -= 3;
2075 *dp++ = tvb_get_guint8(tvb, soffset);
2080 /* If truncated, add an ellipsis */
2081 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2084 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
2085 proto_registrar_get_nth(hf) -> name, *s);
2087 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2091 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2092 int sizeIs16, int next_offset, gboolean little_endian)
2100 /* Compute total length */
2102 int scanning_offset = *offsetp; /* Scanning pointer */
2103 int l; /* Length of an individual item */
2104 int n = 0; /* Number of items */
2106 while(scanning_offset < next_offset) {
2107 l = tvb_get_guint8(tvb, scanning_offset);
2111 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2114 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2115 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2118 * In case we throw an exception, clean up whatever stuff we've
2119 * allocated (if any).
2121 CLEANUP_PUSH(g_free, s);
2124 unsigned l = VALUE8(tvb, *offsetp);
2125 if (l == 255) { /* Item is a font */
2126 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2127 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2129 } else { /* Item is a string */
2132 gint8 delta = VALUE8(tvb, *offsetp + 1);
2133 if (sizeIs16) l += l;
2134 if ((unsigned) allocated < l + 1) {
2135 /* g_realloc doesn't work ??? */
2137 s = g_malloc(l + 1);
2140 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2141 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2142 "textitem (string): delta = %d, \"%s\"",
2144 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2145 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2147 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2148 hf_x11_textitem_string_string16_bytes,
2153 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2154 *offsetp + 2, l, s, "\"%s\"", s);
2160 * Call the cleanup handler to free the string and pop the handler.
2162 CLEANUP_CALL_AND_POP;
2165 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2166 gboolean little_endian)
2168 guint32 v = VALUE8(tvb, *offsetp);
2169 header_field_info *hfi = proto_registrar_get_nth(hf);
2170 gchar *enumValue = NULL;
2173 enumValue = match_strval(v, cVALS(hfi -> strings));
2175 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2176 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2177 hfi -> name, v, enumValue);
2179 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2184 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2185 gboolean little_endian)
2187 guint32 v = VALUE16(tvb, *offsetp);
2188 header_field_info *hfi = proto_registrar_get_nth(hf);
2189 gchar *enumValue = NULL;
2192 enumValue = match_strval(v, cVALS(hfi -> strings));
2194 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2195 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2196 hfi -> name, v, enumValue);
2198 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2203 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2204 gboolean little_endian)
2206 guint32 v = VALUE32(tvb, *offsetp);
2207 header_field_info *hfi = proto_registrar_get_nth(hf);
2208 gchar *enumValue = NULL;
2209 const gchar *nameAsChar = hfi -> name;
2212 enumValue = match_strval(v, cVALS(hfi -> strings));
2214 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2215 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2216 nameAsChar, v, enumValue);
2218 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2219 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2225 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2226 gboolean little_endian)
2228 BITMASK32(gc_value);
2229 BITFIELD(ENUM8, gc_value_mask, function);
2230 BITFIELD(CARD32, gc_value_mask, plane_mask);
2231 BITFIELD(CARD32, gc_value_mask, foreground);
2232 BITFIELD(CARD32, gc_value_mask, background);
2233 BITFIELD(CARD16, gc_value_mask, line_width);
2234 BITFIELD(ENUM8, gc_value_mask, line_style);
2235 BITFIELD(ENUM8, gc_value_mask, cap_style);
2236 BITFIELD(ENUM8, gc_value_mask, join_style);
2237 BITFIELD(ENUM8, gc_value_mask, fill_style);
2238 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2239 BITFIELD(PIXMAP, gc_value_mask, tile);
2240 BITFIELD(PIXMAP, gc_value_mask, stipple);
2241 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2242 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2243 BITFIELD(FONT, gc_value_mask, font);
2244 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2245 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2246 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2247 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2248 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2249 BITFIELD(CARD16, gc_value_mask, dash_offset);
2250 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2251 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2255 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2256 gboolean little_endian)
2258 BITMASK32(gc_value);
2259 FLAG(gc_value, function);
2260 FLAG(gc_value, plane_mask);
2261 FLAG(gc_value, foreground);
2262 FLAG(gc_value, background);
2263 FLAG(gc_value, line_width);
2264 FLAG(gc_value, line_style);
2265 FLAG(gc_value, cap_style);
2266 FLAG(gc_value, join_style);
2267 FLAG(gc_value, fill_style);
2268 FLAG(gc_value, fill_rule);
2269 FLAG(gc_value, tile);
2270 FLAG(gc_value, stipple);
2271 FLAG(gc_value, tile_stipple_x_origin);
2272 FLAG(gc_value, tile_stipple_y_origin);
2273 FLAG(gc_value, font);
2274 FLAG(gc_value, subwindow_mode);
2275 FLAG(gc_value, graphics_exposures);
2276 FLAG(gc_value, clip_x_origin);
2277 FLAG(gc_value, clip_y_origin);
2278 FLAG(gc_value, clip_mask);
2279 FLAG(gc_value, dash_offset);
2280 FLAG(gc_value, gc_dashes);
2281 FLAG(gc_value, arc_mode);
2285 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2286 gboolean little_endian)
2288 guint32 res = VALUE16(tvb, *offsetp);
2289 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2294 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2295 gboolean little_endian)
2298 FLAG(event, KeyPress);
2299 FLAG(event, KeyRelease);
2300 FLAG(event, ButtonPress);
2301 FLAG(event, ButtonRelease);
2302 FLAG(event, EnterWindow);
2303 FLAG(event, LeaveWindow);
2304 FLAG(event, PointerMotion);
2305 FLAG(event, PointerMotionHint);
2306 FLAG(event, Button1Motion);
2307 FLAG(event, Button2Motion);
2308 FLAG(event, Button3Motion);
2309 FLAG(event, Button4Motion);
2310 FLAG(event, Button5Motion);
2311 FLAG(event, ButtonMotion);
2312 FLAG(event, KeymapState);
2313 FLAG(event, Exposure);
2314 FLAG(event, VisibilityChange);
2315 FLAG(event, StructureNotify);
2316 FLAG(event, ResizeRedirect);
2317 FLAG(event, SubstructureNotify);
2318 FLAG(event, SubstructureRedirect);
2319 FLAG(event, FocusChange);
2320 FLAG(event, PropertyChange);
2321 FLAG(event, ColormapChange);
2322 FLAG(event, OwnerGrabButton);
2323 FLAG_IF_NONZERO(event, erroneous_bits);
2327 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2328 gboolean little_endian)
2330 BITMASK32(do_not_propagate);
2331 FLAG(do_not_propagate, KeyPress);
2332 FLAG(do_not_propagate, KeyRelease);
2333 FLAG(do_not_propagate, ButtonPress);
2334 FLAG(do_not_propagate, ButtonRelease);
2335 FLAG(do_not_propagate, PointerMotion);
2336 FLAG(do_not_propagate, Button1Motion);
2337 FLAG(do_not_propagate, Button2Motion);
2338 FLAG(do_not_propagate, Button3Motion);
2339 FLAG(do_not_propagate, Button4Motion);
2340 FLAG(do_not_propagate, Button5Motion);
2341 FLAG(do_not_propagate, ButtonMotion);
2342 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2347 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2348 gboolean little_endian, gboolean butmask)
2351 guint32 bitmask_value;
2354 proto_tree *bitmask_tree;
2356 bitmask_value = VALUE16(tvb, *offsetp);
2357 bitmask_offset = *offsetp;
2360 if (!butmask && bitmask_value == 0x8000)
2361 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2362 "modifiers-masks: 0x8000 (AnyModifier)");
2364 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2366 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2367 FLAG(modifiers, Shift);
2368 FLAG(modifiers, Lock);
2369 FLAG(modifiers, Control);
2370 FLAG(modifiers, Mod1);
2371 FLAG(modifiers, Mod2);
2372 FLAG(modifiers, Mod3);
2373 FLAG(modifiers, Mod4);
2374 FLAG(modifiers, Mod5);
2377 FLAG(modifiers, Button1);
2378 FLAG(modifiers, Button2);
2379 FLAG(modifiers, Button3);
2380 FLAG(modifiers, Button4);
2381 FLAG(modifiers, Button5);
2385 FLAG_IF_NONZERO(keybut, erroneous_bits);
2387 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2392 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2393 gboolean little_endian)
2395 BITMASK16(pointer_event);
2396 FLAG(pointer_event, ButtonPress);
2397 FLAG(pointer_event, ButtonRelease);
2398 FLAG(pointer_event, EnterWindow);
2399 FLAG(pointer_event, LeaveWindow);
2400 FLAG(pointer_event, PointerMotion);
2401 FLAG(pointer_event, PointerMotionHint);
2402 FLAG(pointer_event, Button1Motion);
2403 FLAG(pointer_event, Button2Motion);
2404 FLAG(pointer_event, Button3Motion);
2405 FLAG(pointer_event, Button4Motion);
2406 FLAG(pointer_event, Button5Motion);
2407 FLAG(pointer_event, ButtonMotion);
2408 FLAG(pointer_event, KeymapState);
2409 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2413 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2414 int hf, unsigned length)
2419 p = tvb_get_ptr(tvb, *offsetp, length);
2420 s = g_malloc(length + 1);
2421 stringCopy(s, p, length);
2422 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2427 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2429 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2430 int hf_bytes, unsigned length, gboolean little_endian)
2436 * In case we throw an exception, clean up whatever stuff we've
2437 * allocated (if any).
2439 CLEANUP_PUSH(g_free, s);
2442 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2443 &s, &l, little_endian);
2446 * Call the cleanup handler to free the string and pop the handler.
2448 CLEANUP_CALL_AND_POP;
2453 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2454 gboolean little_endian)
2456 guint32 v = VALUE32(tvb, *offsetp);
2459 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2460 proto_registrar_get_nth(hf) -> name);
2462 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2466 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2467 gboolean little_endian)
2469 BITMASK32(window_value);
2470 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2471 BITFIELD(CARD32, window_value_mask, background_pixel);
2472 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2473 BITFIELD(CARD32, window_value_mask, border_pixel);
2474 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2475 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2476 BITFIELD(ENUM8, window_value_mask, backing_store);
2477 BITFIELD(CARD32, window_value_mask, backing_planes);
2478 BITFIELD(CARD32, window_value_mask, backing_pixel);
2479 BITFIELD(BOOL, window_value_mask, override_redirect);
2480 BITFIELD(BOOL, window_value_mask, save_under);
2481 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2482 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2483 BITFIELD(COLORMAP, window_value_mask, colormap);
2484 BITFIELD(CURSOR, window_value_mask, cursor);
2488 static void x11_init_protocol(void)
2490 x11_conv_data_t *state;
2492 for (state = x11_conv_data_list; state != NULL; state = state->next) {
2493 g_hash_table_destroy(state->seqtable);
2494 g_hash_table_destroy(state->valtable);
2496 x11_conv_data_list = NULL;
2497 if (x11_state_chunk != NULL)
2498 g_mem_chunk_destroy(x11_state_chunk);
2500 x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2501 sizeof (x11_conv_data_t),
2502 128 * sizeof (x11_conv_data_t),
2506 /************************************************************************
2508 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2510 ************************************************************************/
2512 /* If we can't guess, we return TRUE (that is little_endian), cause
2513 I'm developing on a Linux box :-). The (non-)guess isn't cached
2514 however, so we may have more luck next time. I'm quite conservative
2515 in my assertions, cause once it's cached, it's stay in cache, and
2516 we may be fooled up by a packet starting with the end of a request
2517 started in a previous packet...
2520 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2522 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2525 while(maskLength--) {
2526 int c = tvb_get_guint8(tvb, offset);
2528 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2533 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2535 if (listLength > length) return FALSE;
2536 while(listLength--) {
2538 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2539 l = tvb_get_guint8(tvb, offset);
2542 if (l > length) return FALSE;
2543 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2547 if (length > 3) return FALSE;
2551 static int rounded4(int n)
2553 int remainder = n % 4;
2555 if (remainder) res++;
2559 /* We assume the order to be consistent, until proven wrong. */
2561 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2563 switch(tvb_get_guint8(tvb, offset)) {
2564 case X_CreateWindow:
2565 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2567 case X_ChangeWindowAttributes:
2569 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2571 case X_GetWindowAttributes:
2572 case X_DestroyWindow:
2573 case X_DestroySubwindows:
2574 case X_ChangeSaveSet:
2576 case X_MapSubwindows:
2578 case X_UnmapSubwindows:
2579 case X_CirculateWindow:
2583 case X_ListProperties:
2584 case X_GetSelectionOwner:
2585 case X_UngrabPointer:
2586 case X_UngrabKeyboard:
2588 case X_QueryPointer:
2593 case X_FreeColormap:
2594 case X_InstallColormap:
2595 case X_UninstallColormap:
2596 case X_ListInstalledColormaps:
2598 case X_GetKeyboardMapping:
2602 case X_ReparentWindow:
2603 case X_SetSelectionOwner:
2604 case X_ChangeActivePointerGrab:
2605 case X_GrabKeyboard:
2607 case X_GetMotionEvents:
2608 case X_TranslateCoords:
2609 case X_CreatePixmap:
2612 case X_CreateColormap:
2614 case X_AllocColorPlanes:
2617 case X_ConfigureWindow:
2618 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2621 case X_QueryExtension:
2622 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2624 case X_ChangeProperty:
2626 int multiplier, type;
2627 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2628 type = tvb_get_guint8(tvb, 16);
2629 if (type != 8 && type != 16 && type != 32) return FALSE;
2630 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2631 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2632 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2635 case X_DeleteProperty:
2636 case X_UngrabButton:
2638 case X_SetInputFocus:
2639 case X_CopyColormapAndFree:
2640 case X_AllocColorCells:
2641 case X_QueryBestSize:
2642 case X_ChangePointerControl:
2643 case X_SetScreenSaver:
2647 case X_ConvertSelection:
2654 return length == 11;
2657 case X_UngrabServer:
2658 case X_GetInputFocus:
2661 case X_ListExtensions:
2662 case X_GetKeyboardControl:
2664 case X_GetPointerControl:
2665 case X_GetScreenSaver:
2667 case X_SetAccessControl:
2668 case X_SetCloseDownMode:
2669 case X_ForceScreenSaver:
2670 case X_GetPointerMapping:
2671 case X_GetModifierMapping:
2675 case X_AllocNamedColor:
2677 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2679 case X_QueryTextExtents:
2683 case X_ListFontsWithInfo:
2685 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2688 if (length < 2) return FALSE;
2689 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2690 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2693 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2696 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2698 case X_SetClipRectangles:
2700 case X_PolyRectangle:
2701 case X_PolyFillRectangle:
2702 return length >= 3 && (length - 3) % 2 == 0;
2708 case X_CreateCursor:
2709 case X_CreateGlyphCursor:
2719 return length >= 3 && (length - 3) % 3 == 0;
2729 case X_RecolorCursor:
2733 if (length < 4) return FALSE;
2734 return TRUE; /* We don't perform many controls on this one */
2737 if (length < 4) return FALSE;
2738 return TRUE; /* We don't perform many controls on this one */
2744 return length > 2 && (length - 2) % 3 == 0;
2746 case X_StoreNamedColor:
2747 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2752 case X_ChangeKeyboardMapping:
2753 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2755 case X_ChangeKeyboardControl:
2756 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2758 case X_RotateProperties:
2759 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2761 case X_SetPointerMapping:
2762 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2764 case X_SetModifierMapping:
2765 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2775 /* -1 means doesn't match, +1 means match, 0 means don't know */
2777 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2779 int offset, nextoffset;
2782 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2784 length = v16(tvb, offset + 2);
2785 if (!length) return -1;
2786 nextoffset = offset + length * 4;
2787 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2794 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2795 x11_conv_data_t *state)
2797 /* With X the client gives the byte ordering for the protocol,
2798 and the port on the server tells us we're speaking X. */
2800 int le, be, decision, decisionToCache;
2802 if (state->byte_order == BYTE_ORDER_BE)
2803 return FALSE; /* known to be big-endian */
2804 else if (state->byte_order == BYTE_ORDER_LE)
2805 return TRUE; /* known to be little-endian */
2807 if (pinfo->srcport == pinfo->match_port) {
2809 * This is a reply or event; we don't try to guess the
2810 * byte order on it for now.
2815 le = x_endian_match(tvb, tvb_get_letohs);
2816 be = x_endian_match(tvb, tvb_get_ntohs);
2818 /* remember that "decision" really means "little_endian". */
2820 /* We have no reason to believe it's little- rather than
2821 big-endian, so we guess the shortest length is the
2824 if (!tvb_bytes_exist(tvb, 0, 4))
2825 /* Not even a way to get the length. We're biased
2826 toward little endianness here (essentially the
2827 x86 world right now). Decoding won't go very far
2832 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2834 decision = le >= be;
2836 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2837 if (decisionToCache) {
2839 * Remember the decision.
2841 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2845 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2846 pinfo->fd -> num, le, be, decision, decisionToCache);
2851 /************************************************************************
2853 *** D E C O D I N G O N E P A C K E T ***
2855 ************************************************************************/
2858 * Decode an initial connection request.
2860 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2861 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2864 int *offsetp = &offset;
2867 guint16 auth_proto_name_length, auth_proto_data_length;
2870 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2871 proto_item_append_text(ti, ", Request, Initial connection request");
2872 t = proto_item_add_subtree(ti, ett_x11);
2876 CARD16(protocol_major_version);
2877 CARD16(protocol_minor_version);
2878 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2879 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2882 if (auth_proto_name_length != 0) {
2883 STRING8(authorization_protocol_name, auth_proto_name_length);
2884 offset = ROUND_LENGTH(offset);
2887 if (auth_proto_data_length != 0) {
2888 STRING8(authorization_protocol_data, auth_proto_data_length);
2889 offset = ROUND_LENGTH(offset);
2892 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2893 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2897 * This is the initial connection request...
2899 state->iconn_frame = pinfo->fd->num;
2902 * ...and we're expecting a reply to it.
2904 state->sequencenumber = 0;
2905 g_hash_table_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
2906 (int *)INITIAL_CONN);
2909 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2910 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2911 gboolean little_endian)
2913 int offset = 0, *offsetp = &offset, left;
2914 unsigned char success;
2915 int length_of_vendor;
2916 int length_of_reason;
2920 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2921 proto_item_append_text(ti, ", Reply, Initial connection reply");
2922 t = proto_item_add_subtree(ti, ett_x11);
2924 state->iconn_reply = pinfo->fd->num;
2925 success = INT8(success);
2928 length_of_reason = 0;
2931 length_of_reason = INT8(length_of_reason);
2934 INT16(protocol_major_version);
2935 INT16(protocol_minor_version);
2938 INT32(release_number);
2939 INT32(resource_id_base);
2940 INT32(resource_id_mask);
2941 INT32(motion_buffer_size);
2942 length_of_vendor = INT16(length_of_vendor);
2943 INT16(maximum_request_length);
2944 INT8(number_of_screens_in_roots);
2945 INT8(number_of_formats_in_pixmap_formats);
2946 INT8(image_byte_order);
2947 INT8(bitmap_format_bit_order);
2948 INT8(bitmap_format_scanline_unit);
2949 INT8(bitmap_format_scanline_pad);
2953 STRING8(vendor, length_of_vendor);
2955 STRING8(reason, length_of_reason);
2958 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2963 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2964 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2965 gboolean little_endian)
2968 int *offsetp = &offset;
2972 int length, opcode, i;
2973 guint8 v8, v8_2, v8_3;
2979 length = VALUE16(tvb, 2) * 4;
2982 /* Bogus message length? */
2986 next_offset = offset + length;
2988 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2989 t = proto_item_add_subtree(ti, ett_x11);
2991 if (PACKET_IS_NEW(pinfo))
2992 ++state->sequencenumber;
2996 if (check_col(pinfo->cinfo, COL_INFO))
2997 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2998 val_to_str(opcode, state->opcode_vals,
2999 "<Unknown opcode %d>"));
3001 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
3002 opcode, val_to_str(opcode, state->opcode_vals,
3003 "<Unknown opcode %d>"));
3006 * Does this request expect a reply?
3010 case X_QueryExtension:
3012 /* necessary processing even if tree == NULL */
3014 v16 = VALUE16(tvb, 4);
3015 name = g_malloc(v16 + 1);
3016 stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
3018 /* store string of extension, opcode will be set at reply */
3020 while(i < MAX_OPCODES) {
3021 if (state->opcode_vals[i].strptr == NULL) {
3022 state->opcode_vals[i].strptr = name;
3023 g_hash_table_insert(state->valtable,
3024 GINT_TO_POINTER(state->sequencenumber),
3025 (int *)&state->opcode_vals[i]);
3027 } else if (strcmp(state->opcode_vals[i].strptr,
3029 g_hash_table_insert(state->valtable,
3030 GINT_TO_POINTER(state->sequencenumber),
3031 (int *)&state->opcode_vals[i]);
3037 /* QueryExtension expects a reply, fall through */
3040 case X_AllocColorCells:
3041 case X_AllocColorPlanes:
3042 case X_AllocNamedColor:
3047 case X_GetInputFocus:
3048 case X_GetKeyboardControl:
3049 case X_GetKeyboardMapping:
3050 case X_GetModifierMapping:
3051 case X_GetMotionEvents:
3052 case X_GetPointerControl:
3053 case X_GetPointerMapping:
3055 case X_GetScreenSaver:
3056 case X_GetSelectionOwner:
3057 case X_GetWindowAttributes:
3058 case X_GrabKeyboard:
3061 case X_ListExtensions:
3063 case X_ListFontsWithInfo:
3065 case X_ListInstalledColormaps:
3066 case X_ListProperties:
3068 case X_QueryBestSize:
3072 case X_QueryPointer:
3073 case X_QueryTextExtents:
3075 case X_SetModifierMapping:
3076 case X_SetPointerMapping:
3077 case X_TranslateCoords:
3079 * Those requests expect a reply.
3081 g_hash_table_insert(state->seqtable,
3082 GINT_TO_POINTER(state->sequencenumber),
3083 GINT_TO_POINTER(opcode));
3089 * With Extension, we don't know, so assume there could be one
3091 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3092 g_hash_table_insert(state->seqtable,
3093 GINT_TO_POINTER(state->sequencenumber),
3094 GINT_TO_POINTER(opcode));
3098 * No reply is expected from any other request.
3108 case X_CreateWindow:
3117 CARD16(border_width);
3118 ENUM16(window_class);
3120 windowAttributes(tvb, offsetp, t, little_endian);
3123 case X_ChangeWindowAttributes:
3127 windowAttributes(tvb, offsetp, t, little_endian);
3130 case X_GetWindowAttributes:
3131 case X_DestroyWindow:
3132 case X_DestroySubwindows:
3138 case X_ChangeSaveSet:
3139 ENUM8(save_set_mode);
3144 case X_ReparentWindow:
3154 case X_MapSubwindows:
3156 case X_UnmapSubwindows:
3162 case X_ConfigureWindow:
3166 BITMASK16(configure_window);
3168 BITFIELD(INT16, configure_window_mask, x);
3169 BITFIELD(INT16, configure_window_mask, y);
3170 BITFIELD(CARD16, configure_window_mask, width);
3171 BITFIELD(CARD16, configure_window_mask, height);
3172 BITFIELD(CARD16, configure_window_mask, border_width);
3173 BITFIELD(WINDOW, configure_window_mask, sibling);
3174 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3179 case X_CirculateWindow:
3193 BOOL(only_if_exists);
3195 v16 = FIELD16(name_length);
3207 case X_ChangeProperty:
3215 v32 = CARD32(data_length);
3216 LISTofBYTE(data, v32);
3220 case X_DeleteProperty:
3232 ATOM(get_property_type);
3233 CARD32(long_offset);
3234 CARD32(long_length);
3237 case X_ListProperties:
3243 case X_SetSelectionOwner:
3251 case X_GetSelectionOwner:
3257 case X_ConvertSelection:
3270 WINDOW(destination);
3271 SETofEVENT(event_mask);
3278 WINDOW(grab_window);
3279 SETofPOINTEREVENT(pointer_event_mask);
3280 ENUM8(pointer_mode);
3281 ENUM8(keyboard_mode);
3287 case X_UngrabPointer:
3296 WINDOW(grab_window);
3297 SETofPOINTEREVENT(event_mask);
3298 ENUM8(pointer_mode);
3299 ENUM8(keyboard_mode);
3304 SETofKEYMASK(modifiers);
3307 case X_UngrabButton:
3310 WINDOW(grab_window);
3311 SETofKEYMASK(modifiers);
3315 case X_ChangeActivePointerGrab:
3320 SETofPOINTEREVENT(event_mask);
3324 case X_GrabKeyboard:
3327 WINDOW(grab_window);
3329 ENUM8(pointer_mode);
3330 ENUM8(keyboard_mode);
3334 case X_UngrabKeyboard:
3343 WINDOW(grab_window);
3344 SETofKEYMASK(modifiers);
3346 ENUM8(pointer_mode);
3347 ENUM8(keyboard_mode);
3354 WINDOW(grab_window);
3355 SETofKEYMASK(modifiers);
3360 ENUM8(allow_events_mode);
3370 case X_UngrabServer:
3375 case X_QueryPointer:
3381 case X_GetMotionEvents:
3389 case X_TranslateCoords:
3401 WINDOW(warp_pointer_src_window);
3402 WINDOW(warp_pointer_dst_window);
3411 case X_SetInputFocus:
3418 case X_GetInputFocus:
3432 v16 = FIELD16(name_length);
3450 case X_QueryTextExtents:
3451 v8 = BOOL(odd_length);
3454 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3462 v16 = FIELD16(pattern_length);
3463 STRING8(pattern, v16);
3467 case X_ListFontsWithInfo:
3471 v16 = FIELD16(pattern_length);
3472 STRING8(pattern, v16);
3479 v16 = CARD16(str_number_in_path);
3481 LISTofSTRING8(path, v16);
3490 case X_CreatePixmap:
3510 gcAttributes(tvb, offsetp, t, little_endian);
3517 gcAttributes(tvb, offsetp, t, little_endian);
3525 gcMask(tvb, offsetp, t, little_endian);
3532 CARD16(dash_offset);
3533 v16 = FIELD16(dashes_length);
3534 LISTofCARD8(dashes, v16);
3538 case X_SetClipRectangles:
3542 INT16(clip_x_origin);
3543 INT16(clip_y_origin);
3544 LISTofRECTANGLE(rectangles);
3566 DRAWABLE(src_drawable);
3567 DRAWABLE(dst_drawable);
3580 DRAWABLE(src_drawable);
3581 DRAWABLE(dst_drawable);
3593 ENUM8(coordinate_mode);
3594 v16 = REQUEST_LENGTH();
3597 LISTofPOINT(points, v16 - 12);
3601 ENUM8(coordinate_mode);
3602 v16 = REQUEST_LENGTH();
3605 LISTofPOINT(points, v16 - 12);
3613 LISTofSEGMENT(segments);
3616 case X_PolyRectangle:
3621 LISTofRECTANGLE(rectangles);
3634 v16 = REQUEST_LENGTH();
3638 ENUM8(coordinate_mode);
3640 LISTofPOINT(points, v16 - 16);
3643 case X_PolyFillRectangle:
3648 LISTofRECTANGLE(rectangles);
3660 ENUM8(image_format);
3661 v16 = REQUEST_LENGTH();
3671 LISTofBYTE(data, v16 - 24);
3676 ENUM8(image_pixmap_format);
3688 v16 = REQUEST_LENGTH();
3693 LISTofTEXTITEM8(items);
3699 v16 = REQUEST_LENGTH();
3704 LISTofTEXTITEM16(items);
3709 v8 = FIELD8(string_length);
3715 STRING8(string, v8);
3720 v8 = FIELD8(string_length);
3726 STRING16(string16, v8);
3730 case X_CreateColormap:
3738 case X_FreeColormap:
3744 case X_CopyColormapAndFree:
3751 case X_InstallColormap:
3757 case X_UninstallColormap:
3763 case X_ListInstalledColormaps:
3779 case X_AllocNamedColor:
3783 v16 = FIELD16(name_length);
3789 case X_AllocColorCells:
3797 case X_AllocColorPlanes:
3809 v16 = REQUEST_LENGTH();
3812 LISTofCARD32(pixels, v16 - 12);
3817 v16 = REQUEST_LENGTH();
3819 LISTofCOLORITEM(color_items, v16 - 8);
3822 case X_StoreNamedColor:
3827 v16 = FIELD16(name_length);
3835 v16 = REQUEST_LENGTH();
3837 LISTofCARD32(pixels, v16 - 8);
3844 v16 = FIELD16(name_length);
3850 case X_CreateCursor:
3854 PIXMAP(source_pixmap);
3866 case X_CreateGlyphCursor:
3872 CARD16(source_char);
3888 case X_RecolorCursor:
3900 case X_QueryBestSize:
3908 case X_QueryExtension:
3911 v16 = FIELD16(name_length);
3917 case X_ListExtensions:
3922 case X_ChangeKeyboardMapping:
3923 v8 = FIELD8(keycode_count);
3925 v8_2 = KEYCODE(first_keycode);
3926 v8_3 = FIELD8(keysyms_per_keycode);
3928 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3931 case X_GetKeyboardMapping:
3934 state->request.GetKeyboardMapping.first_keycode
3935 = KEYCODE(first_keycode);
3940 case X_ChangeKeyboardControl:
3943 BITMASK32(keyboard_value);
3944 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3945 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3946 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3947 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3948 BITFIELD(INT16, keyboard_value_mask, led);
3949 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3950 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3951 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3955 case X_GetKeyboardControl:
3965 case X_ChangePointerControl:
3968 INT16(acceleration_numerator);
3969 INT16(acceleration_denominator);
3971 BOOL(do_acceleration);
3975 case X_GetPointerControl:
3980 case X_SetScreenSaver:
3985 ENUM8(prefer_blanking);
3986 ENUM8(allow_exposures);
3990 case X_GetScreenSaver:
3996 ENUM8(change_host_mode);
4000 v16 = CARD16(address_length);
4001 if (v8 == FAMILY_INTERNET && v16 == 4) {
4004 * XXX - what about IPv6? Is that a family of
4005 * FAMILY_INTERNET (0) with a length of 16?
4007 LISTofIPADDRESS(ip_address, v16);
4009 LISTofCARD8(address, v16);
4017 case X_SetAccessControl:
4022 case X_SetCloseDownMode:
4023 ENUM8(close_down_mode);
4033 case X_RotateProperties:
4035 v16 = REQUEST_LENGTH();
4037 CARD16(property_number);
4039 LISTofATOM(properties, (v16 - 12));
4042 case X_ForceScreenSaver:
4043 ENUM8(screen_saver_mode);
4047 case X_SetPointerMapping:
4048 v8 = FIELD8(map_length);
4050 LISTofCARD8(map, v8);
4054 case X_GetPointerMapping:
4059 case X_SetModifierMapping:
4060 v8 = FIELD8(keycodes_per_modifier);
4062 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4065 case X_GetModifierMapping:
4076 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4080 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4083 volatile int offset = 0;
4084 int length_remaining;
4085 volatile gboolean little_endian;
4090 volatile gboolean is_initial_creq;
4091 guint16 auth_proto_len, auth_data_len;
4092 const char *volatile sep = NULL;
4093 conversation_t *conversation;
4094 x11_conv_data_t *volatile state;
4098 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4100 * We use "tvb_ensure_length_remaining()" to make sure there
4101 * actually *is* data remaining.
4103 * This means we're guaranteed that "length_remaining" is
4106 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4109 * Can we do reassembly?
4111 if (x11_desegment && pinfo->can_desegment) {
4113 * Yes - is the X11 request header split across
4114 * segment boundaries?
4116 if (length_remaining < 4) {
4118 * Yes. Tell the TCP dissector where the data
4119 * for this message starts in the data it handed
4120 * us, and how many more bytes we need, and return.
4122 pinfo->desegment_offset = offset;
4123 pinfo->desegment_len = 4 - length_remaining;
4129 * Get the state for this conversation; create the conversation
4130 * if we don't have one, and create the state if we don't have
4133 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4134 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4135 if (conversation == NULL) {
4139 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4140 &pinfo->dst, pinfo->ptype, pinfo->srcport,
4141 pinfo->destport, 0);
4145 * Is there state attached to this conversation?
4147 if ((state = conversation_get_proto_data(conversation, proto_x11))
4149 state = x11_stateinit(conversation);
4152 * Guess the byte order if we don't already know it.
4154 little_endian = guess_byte_ordering(tvb, pinfo, state);
4157 * Get the opcode and length of the putative X11 request.
4159 opcode = VALUE8(tvb, 0);
4160 plen = VALUE16(tvb, offset + 2);
4164 * This can't be 0, as it includes the header length.
4165 * A different choice of byte order wouldn't have
4169 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4171 t = proto_item_add_subtree(ti, ett_x11);
4172 proto_tree_add_text(t, tvb, offset, -1,
4173 "Bogus request length (0)");
4177 if (state->iconn_frame == pinfo->fd->num ||
4178 (g_hash_table_lookup(state->seqtable,
4179 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4180 (opcode == 'B' || opcode == 'l') &&
4181 (plen == 11 || plen == 2816))) {
4185 * we saw this on the first pass and this is
4189 * we haven't already seen any requests, the first
4190 * byte of the message is 'B' or 'l', and the 16-bit
4191 * integer 2 bytes into the data stream is either 11
4192 * or a byte-swapped 11.
4194 * This means it's probably an initial connection
4195 * request, not a message.
4197 * 'B' is decimal 66, which is the opcode for a
4198 * PolySegment request; unfortunately, 11 is a valid
4199 * length for a PolySegment request request, so we
4200 * might mis-identify that request. (Are there any
4201 * other checks we can do?)
4203 * 'l' is decimal 108, which is the opcode for a
4204 * GetScreenSaver request; the only valid length
4205 * for that request is 1.
4207 is_initial_creq = TRUE;
4210 * We now know the byte order. Override the guess.
4212 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4213 if (opcode == 'B') {
4217 state->byte_order = BYTE_ORDER_BE;
4218 little_endian = FALSE;
4223 state->byte_order = BYTE_ORDER_LE;
4224 little_endian = TRUE;
4229 * Can we do reassembly?
4231 if (x11_desegment && pinfo->can_desegment) {
4233 * Yes - is the fixed-length portion of the
4234 * initial connection header split across
4235 * segment boundaries?
4237 if (length_remaining < 10) {
4239 * Yes. Tell the TCP dissector where the
4240 * data for this message starts in the data
4241 * it handed us, and how many more bytes we
4244 pinfo->desegment_offset = offset;
4245 pinfo->desegment_len = 10 - length_remaining;
4251 * Get the lengths of the authorization protocol and
4252 * the authorization data.
4254 auth_proto_len = VALUE16(tvb, offset + 6);
4255 auth_data_len = VALUE16(tvb, offset + 8);
4256 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4257 ROUND_LENGTH(auth_data_len);
4260 * This is probably an ordinary request.
4262 is_initial_creq = FALSE;
4265 * The length of a request is in 4-byte words.
4271 * Can we do reassembly?
4273 if (x11_desegment && pinfo->can_desegment) {
4275 * Yes - is the X11 request split across segment
4278 if (length_remaining < plen) {
4280 * Yes. Tell the TCP dissector where the data
4281 * for this message starts in the data it handed
4282 * us, and how many more bytes we need, and return.
4284 pinfo->desegment_offset = offset;
4285 pinfo->desegment_len = plen - length_remaining;
4291 * Construct a tvbuff containing the amount of the payload
4292 * we have available. Make its reported length the
4293 * amount of data in the X11 request.
4295 * XXX - if reassembly isn't enabled. the subdissector
4296 * will throw a BoundsError exception, rather than a
4297 * ReportedBoundsError exception. We really want a tvbuff
4298 * where the length is "length", the reported length is "plen",
4299 * and the "if the snapshot length were infinite" length is the
4300 * minimum of the reported length of the tvbuff handed to us
4301 * and "plen", with a new type of exception thrown if the offset
4302 * is within the reported length but beyond that third length,
4303 * with that exception getting the "Unreassembled Packet" error.
4305 length = length_remaining;
4308 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4311 * Set the column appropriately.
4313 if (is_initial_creq) {
4314 if (check_col(pinfo->cinfo, COL_INFO))
4315 col_set_str(pinfo->cinfo, COL_INFO,
4316 "Initial connection request");
4320 * We haven't set the column yet; set it.
4322 if (check_col(pinfo->cinfo, COL_INFO))
4323 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4326 * Initialize the separator.
4333 * Dissect the X11 request.
4335 * Catch the ReportedBoundsError exception; if this
4336 * particular message happens to get a ReportedBoundsError
4337 * exception, that doesn't mean that we should stop
4338 * dissecting X11 requests within this frame or chunk of
4341 * If it gets a BoundsError, we can stop, as there's nothing
4342 * more to see, so we just re-throw it.
4345 if (is_initial_creq) {
4346 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4347 state, little_endian);
4349 dissect_x11_request(next_tvb, pinfo, tree, sep,
4350 state, little_endian);
4353 CATCH(BoundsError) {
4356 CATCH(ReportedBoundsError) {
4357 show_reported_bounds_error(tvb, pinfo, tree);
4362 * Skip the X11 message.
4370 static x11_conv_data_t *
4371 x11_stateinit(conversation_t *conversation)
4373 x11_conv_data_t *state;
4374 static x11_conv_data_t stateinit;
4377 state = g_mem_chunk_alloc(x11_state_chunk);
4379 state->next = x11_conv_data_list;
4380 x11_conv_data_list = state;
4382 /* initialise opcodes */
4384 if (opcode_vals[i].strptr == NULL) break;
4385 state->opcode_vals[i].value = opcode_vals[i].value;
4386 state->opcode_vals[i].strptr = opcode_vals[i].strptr;
4389 while (i <= MAX_OPCODES) {
4390 state->opcode_vals[i].value = 0;
4391 state->opcode_vals[i].strptr = NULL;
4395 state->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4396 state->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4397 g_hash_table_insert(state->seqtable, (int *)0, (int *)NOTHING_SEEN);
4398 state->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4399 conversation_add_proto_data(conversation, proto_x11, state);
4405 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4407 /* Set up structures we will need to add the protocol subtree and manage it */
4408 volatile int offset, plen;
4409 tvbuff_t * volatile next_tvb;
4410 conversation_t *conversation;
4411 x11_conv_data_t *volatile state;
4412 gboolean little_endian;
4413 int length_remaining;
4414 const char *volatile sep = NULL;
4418 * Get the state for this conversation; create the conversation
4419 * if we don't have one, and create the state if we don't have
4422 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4423 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4424 if (conversation == NULL) {
4428 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4429 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4433 * Is there state attached to this conversation?
4435 if ((state = conversation_get_proto_data(conversation, proto_x11))
4438 * No - create a state structure and attach it.
4440 state = x11_stateinit(conversation);
4444 * Guess the byte order if we don't already know it.
4446 little_endian = guess_byte_ordering(tvb, pinfo, state);
4449 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4451 * We use "tvb_ensure_length_remaining()" to make sure there
4452 * actually *is* data remaining.
4454 * This means we're guaranteed that "length_remaining" is
4457 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4460 * Can we do reassembly?
4462 if (x11_desegment && pinfo->can_desegment) {
4464 * Yes - is the X11 reply header split across
4465 * segment boundaries?
4467 if (length_remaining < 8) {
4469 * Yes. Tell the TCP dissector where the data
4470 * for this message starts in the data it handed
4471 * us, and how many more bytes we need, and
4474 pinfo->desegment_offset = offset;
4475 pinfo->desegment_len = 4 - length_remaining;
4481 * Find out what kind of a reply it is.
4482 * There are four possible:
4483 * - reply to initial connection
4484 * - errorreply (a request generated an error)
4485 * - requestreply (reply to a request)
4486 * - event (some event occured)
4488 if (g_hash_table_lookup(state->seqtable,
4489 GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN
4490 || (state->iconn_reply == pinfo->fd->num)) {
4492 * Either the connection is in the "initial
4493 * connection" state, or this frame is known
4494 * to have the initial connection reply.
4495 * That means this is the initial connection
4498 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4500 HANDLE_REPLY(plen, length_remaining,
4501 "Initial connection reply",
4502 dissect_x11_initial_reply);
4505 * This isn't an initial connection reply
4506 * (XXX - unless we missed the initial
4507 * connection request). Look at the first
4508 * byte to determine what it is; errors
4509 * start with a byte of 0, replies start
4510 * with a byte of 1, events start with
4511 * a byte with of 2 or greater.
4513 switch (tvb_get_guint8(tvb, offset)) {
4517 HANDLE_REPLY(plen, length_remaining,
4518 "Error", dissect_x11_error);
4522 /* replylength is in units of four. */
4523 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4525 HANDLE_REPLY(plen, length_remaining,
4526 "Reply", dissect_x11_reply);
4532 HANDLE_REPLY(plen, length_remaining,
4533 "Event", dissect_x11_event);
4545 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4546 const char *volatile sep, x11_conv_data_t *volatile state,
4547 gboolean little_endian)
4549 int offset = 0, *offsetp = &offset, length, left, opcode;
4550 int major_opcode, sequence_number;
4551 value_string *vals_p;
4555 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4556 tvb_reported_length_remaining(tvb, offset),
4558 t = proto_item_add_subtree(ti, ett_x11);
4562 * XXX - this doesn't work correctly if either
4564 * 1) the request sequence number wraps in the lower 16
4567 * 2) we don't see the initial connection request and the
4568 * resynchronization of sequence number fails and thus
4569 * don't have the right sequence numbers
4571 * 3) we don't have all the packets in the capture and
4572 * get out of sequence.
4574 * We might, instead, want to assume that a reply is a reply to
4575 * the most recent not-already-replied-to request in the same
4576 * connection. That also might mismatch replies to requests if
4577 * packets are lost, but there's nothing you can do to fix that.
4580 sequence_number = VALUE16(tvb, offset + 2);
4581 opcode = GPOINTER_TO_INT(g_hash_table_lookup(state->seqtable,
4582 GINT_TO_POINTER(sequence_number)));
4584 if (state->iconn_frame == 0 && state->resync == FALSE) {
4587 * We don't see the initial connection request and no
4588 * resynchronization has been performed yet (first reply),
4589 * set the current sequence number to the one of the
4590 * current reply (this is only performed once).
4592 state->sequencenumber = sequence_number;
4593 state->resync = TRUE;
4596 if (opcode == UNKNOWN_OPCODE) {
4597 if (check_col(pinfo->cinfo, COL_INFO))
4598 col_append_fstr(pinfo->cinfo, COL_INFO,
4599 "%s to unknown request", sep);
4600 proto_item_append_text(ti, ", Reply to unknown request");
4602 if (check_col(pinfo->cinfo, COL_INFO))
4603 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4605 val_to_str(opcode, state->opcode_vals,
4606 "<Unknown opcode %d>"));
4608 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4609 opcode, val_to_str(opcode,
4611 "<Unknown opcode %d>"));
4617 * Replies that need special processing outside tree
4620 case X_QueryExtension:
4623 * if extension is present and request is known:
4624 * store opcode of extension in value_string of
4627 if (!VALUE8(tvb, offset + 8)) {
4632 vals_p = g_hash_table_lookup(state->valtable,
4633 GINT_TO_POINTER(sequence_number));
4634 if (vals_p != NULL) {
4635 major_opcode = VALUE8(tvb, offset + 9);
4636 vals_p->value = major_opcode;
4637 g_hash_table_remove(state->valtable,
4638 GINT_TO_POINTER(sequence_number));
4651 * Requests that expect a reply.
4654 case X_GetWindowAttributes:
4655 REPLYCONTENTS_COMMON();
4661 SEQUENCENUMBER_REPLY(sequencenumber);
4662 REPLYLENGTH(replylength);
4668 CARD16(border_width);
4673 REPLYCONTENTS_COMMON();
4679 SEQUENCENUMBER_REPLY(sequencenumber);
4680 REPLYLENGTH(replylength);
4686 REPLYCONTENTS_COMMON();
4692 SEQUENCENUMBER_REPLY(sequencenumber);
4693 length = REPLYLENGTH(replylength);
4694 ATOM(get_property_type);
4695 CARD32(bytes_after);
4696 CARD32(valuelength);
4700 case X_ListProperties:
4703 SEQUENCENUMBER_REPLY(sequencenumber);
4704 REPLYLENGTH(replylength);
4705 length = CARD16(property_number);
4707 LISTofATOM(properties, length*4);
4710 case X_GetSelectionOwner:
4713 SEQUENCENUMBER_REPLY(sequencenumber);
4714 REPLYLENGTH(replylength);
4720 case X_GrabKeyboard:
4723 SEQUENCENUMBER_REPLY(sequencenumber);
4724 REPLYLENGTH(replylength);
4728 case X_QueryPointer:
4731 SEQUENCENUMBER_REPLY(sequencenumber);
4732 REPLYLENGTH(replylength);
4734 WINDOW(childwindow);
4739 SETofKEYBUTMASK(mask);
4743 case X_GetMotionEvents:
4744 REPLYCONTENTS_COMMON();
4747 case X_TranslateCoords:
4750 SEQUENCENUMBER_REPLY(sequencenumber);
4751 REPLYLENGTH(replylength);
4752 WINDOW(childwindow);
4758 case X_GetInputFocus:
4761 SEQUENCENUMBER_REPLY(sequencenumber);
4762 REPLYLENGTH(replylength);
4770 SEQUENCENUMBER_REPLY(sequencenumber);
4771 REPLYLENGTH(replylength);
4772 LISTofCARD8(keys, 32);
4776 case X_QueryTextExtents:
4779 case X_ListInstalledColormaps:
4780 REPLYCONTENTS_COMMON();
4786 SEQUENCENUMBER_REPLY(sequencenumber);
4787 REPLYLENGTH(replylength);
4797 REPLYCONTENTS_COMMON();
4803 SEQUENCENUMBER_REPLY(sequencenumber);
4804 REPLYLENGTH(replylength);
4806 CARD16(exact_green);
4809 CARD16(visual_green);
4810 CARD16(visual_blue);
4814 case X_QueryBestSize:
4817 SEQUENCENUMBER_REPLY(sequencenumber);
4818 REPLYLENGTH(replylength);
4824 case X_QueryExtension:
4827 SEQUENCENUMBER_REPLY(sequencenumber);
4828 REPLYLENGTH(replylength);
4830 CARD8(major_opcode);
4836 case X_ListExtensions:
4837 REPLYCONTENTS_COMMON();
4840 case X_GetKeyboardMapping:
4841 state->first_keycode =
4842 state->request.GetKeyboardMapping.first_keycode;
4844 state->keysyms_per_keycode =
4845 FIELD8(keysyms_per_keycode);
4846 SEQUENCENUMBER_REPLY(sequencenumber);
4847 length = REPLYLENGTH(replylength);
4849 LISTofKEYSYM(keysyms, state->keycodemap,
4850 state->request.GetKeyboardMapping.first_keycode,
4851 length / state->keysyms_per_keycode,
4852 state->keysyms_per_keycode);
4855 case X_GetKeyboardControl:
4856 REPLYCONTENTS_COMMON();
4859 case X_GetPointerControl:
4862 SEQUENCENUMBER_REPLY(sequencenumber);
4863 REPLYLENGTH(replylength);
4864 CARD16(acceleration_numerator);
4865 CARD16(acceleration_denominator);
4870 case X_GetScreenSaver:
4873 SEQUENCENUMBER_REPLY(sequencenumber);
4874 REPLYLENGTH(replylength);
4877 ENUM8(prefer_blanking);
4878 ENUM8(allow_exposures);
4883 case X_SetPointerMapping:
4884 case X_GetPointerMapping:
4885 case X_SetModifierMapping:
4886 REPLYCONTENTS_COMMON();
4889 case X_GetModifierMapping:
4891 state->keycodes_per_modifier =
4892 FIELD8(keycodes_per_modifier);
4893 SEQUENCENUMBER_REPLY(sequencenumber);
4894 REPLYLENGTH(replylength);
4896 LISTofKEYCODE(state->modifiermap, keycodes,
4897 state->keycodes_per_modifier);
4901 REPLYCONTENTS_COMMON();
4904 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4909 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4912 guint32 bitmask_value;
4915 proto_tree *bitmask_tree;
4917 bitmask_value = VALUE8(tvb, *offsetp);
4918 bitmask_offset = *offsetp;
4921 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4923 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4924 FLAG(same_screen_focus, focus);
4925 FLAG(same_screen_focus, same_screen);
4931 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4932 const char *volatile sep, x11_conv_data_t *volatile state,
4933 gboolean little_endian)
4935 int offset = 0, *offsetp = &offset, left;
4936 unsigned char eventcode;
4940 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4941 t = proto_item_add_subtree(ti, ett_x11);
4943 eventcode = tvb_get_guint8(tvb, offset);
4945 if (check_col(pinfo->cinfo, COL_INFO))
4946 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4947 sep, val_to_str(eventcode, eventcode_vals,
4948 "<Unknown eventcode %u>"));
4950 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4952 "eventcode: %d (%s)",
4954 val_to_str(eventcode, eventcode_vals,
4955 "<Unknown eventcode %u>"));
4958 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4959 eventcode, val_to_str(eventcode, eventcode_vals,
4960 "<Unknown eventcode %u>"));
4965 switch (eventcode) {
4970 /* need to do some prefetching here ... */
4971 code = VALUE8(tvb, offset);
4972 mask = VALUE16(tvb, 28);
4974 KEYCODE_DECODED(keycode, code, mask);
4975 CARD16(event_sequencenumber);
4976 EVENTCONTENTS_COMMON();
4984 BUTTON(eventbutton);
4985 CARD16(event_sequencenumber);
4986 EVENTCONTENTS_COMMON();
4993 CARD16(event_sequencenumber);
4994 EVENTCONTENTS_COMMON();
5001 ENUM8(event_detail);
5002 CARD16(event_sequencenumber);
5003 EVENTCONTENTS_COMMON();
5005 same_screen_focus(tvb, offsetp, t);
5010 ENUM8(focus_detail);
5011 CARD16(event_sequencenumber);
5012 WINDOW(eventwindow);
5022 CARD16(event_sequencenumber);
5023 WINDOW(eventwindow);
5032 case GraphicsExpose:
5034 CARD16(event_sequencenumber);
5040 CARD16(minor_opcode);
5042 CARD8(major_opcode);
5048 CARD16(event_sequencenumber);
5050 CARD16(minor_opcode);
5051 CARD8(major_opcode);
5055 case VisibilityNotify:
5057 CARD16(event_sequencenumber);
5058 WINDOW(eventwindow);
5059 ENUM8(visibility_state);
5065 CARD16(event_sequencenumber);
5067 WINDOW(eventwindow);
5072 CARD16(border_width);
5073 BOOL(override_redirect);
5079 CARD16(event_sequencenumber);
5080 WINDOW(eventwindow);
5087 CARD16(event_sequencenumber);
5088 WINDOW(eventwindow);
5090 BOOL(from_configure);
5096 CARD16(event_sequencenumber);
5097 WINDOW(eventwindow);
5099 BOOL(override_redirect);
5105 CARD16(event_sequencenumber);
5107 WINDOW(eventwindow);
5111 case ReparentNotify:
5113 CARD16(event_sequencenumber);
5114 WINDOW(eventwindow);
5119 BOOL(override_redirect);
5123 case ConfigureNotify:
5125 CARD16(event_sequencenumber);
5126 WINDOW(eventwindow);
5128 WINDOW(above_sibling);
5133 CARD16(border_width);
5134 BOOL(override_redirect);
5138 case ConfigureRequest:
5143 CARD16(event_sequencenumber);
5144 WINDOW(eventwindow);
5153 CARD16(event_sequencenumber);
5154 WINDOW(eventwindow);
5160 case CirculateNotify:
5162 CARD16(event_sequencenumber);
5163 WINDOW(eventwindow);
5170 case CirculateRequest:
5172 CARD16(event_sequencenumber);
5174 WINDOW(eventwindow);
5180 case PropertyNotify:
5182 CARD16(event_sequencenumber);
5183 WINDOW(eventwindow);
5186 ENUM8(property_state);
5190 case SelectionClear:
5192 CARD16(event_sequencenumber);
5199 case SelectionRequest:
5201 CARD16(event_sequencenumber);
5211 case SelectionNotify:
5213 CARD16(event_sequencenumber);
5222 case ColormapNotify:
5224 CARD16(event_sequencenumber);
5225 WINDOW(eventwindow);
5228 ENUM8(colormap_state);
5234 CARD16(event_sequencenumber);
5235 WINDOW(eventwindow);
5237 LISTofBYTE(data, 20);
5245 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5252 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5253 const char *volatile sep, x11_conv_data_t *volatile state _U_,
5254 gboolean little_endian)
5256 int offset = 0, *offsetp = &offset, left;
5257 unsigned char errorcode, error;
5261 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5262 t = proto_item_add_subtree(ti, ett_x11);
5264 error = tvb_get_guint8(tvb, offset);
5267 errorcode = tvb_get_guint8(tvb, offset);
5268 if (check_col(pinfo->cinfo, COL_INFO))
5269 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5270 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5272 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5274 "errorcode: %d (%s)",
5276 val_to_str(errorcode, errorcode_vals,
5277 "<Unknown errocode %u>"));
5280 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
5281 errorcode, val_to_str(errorcode, errorcode_vals,
5282 "<Unknown errorcode %u>"));
5287 CARD16(error_sequencenumber);
5289 switch (errorcode) {
5291 CARD32(error_badvalue);
5298 CARD16(minor_opcode);
5299 CARD8(major_opcode);
5301 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5307 /************************************************************************
5309 *** I N I T I A L I Z A T I O N A N D M A I N ***
5311 ************************************************************************/
5314 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5316 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5317 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5319 if (pinfo->match_port == pinfo->srcport)
5320 dissect_x11_replies(tvb, pinfo, tree);
5322 dissect_x11_requests(tvb, pinfo, tree);
5325 /* Register the protocol with Ethereal */
5326 void proto_register_x11(void)
5329 /* Setup list of header fields */
5330 static hf_register_info hf[] = {
5331 #include "x11-register-info.h"
5334 /* Setup protocol subtree array */
5335 static gint *ett[] = {
5337 &ett_x11_color_flags,
5338 &ett_x11_list_of_arc,
5340 &ett_x11_list_of_atom,
5341 &ett_x11_list_of_card32,
5342 &ett_x11_list_of_color_item,
5343 &ett_x11_color_item,
5344 &ett_x11_list_of_keycode,
5345 &ett_x11_list_of_keysyms,
5347 &ett_x11_list_of_point,
5349 &ett_x11_list_of_rectangle,
5351 &ett_x11_list_of_segment,
5353 &ett_x11_list_of_string8,
5354 &ett_x11_list_of_text_item,
5356 &ett_x11_gc_value_mask,
5357 &ett_x11_event_mask,
5358 &ett_x11_do_not_propagate_mask,
5359 &ett_x11_set_of_key_mask,
5360 &ett_x11_pointer_event_mask,
5361 &ett_x11_window_value_mask,
5362 &ett_x11_configure_window_mask,
5363 &ett_x11_keyboard_value_mask,
5364 &ett_x11_same_screen_focus,
5366 module_t *x11_module;
5368 /* Register the protocol name and description */
5369 proto_x11 = proto_register_protocol("X11", "X11", "x11");
5371 /* Required function calls to register the header fields and subtrees used */
5372 proto_register_field_array(proto_x11, hf, array_length(hf));
5373 proto_register_subtree_array(ett, array_length(ett));
5375 register_init_routine(x11_init_protocol);
5377 x11_module = prefs_register_protocol(proto_x11, NULL);
5378 prefs_register_bool_preference(x11_module, "desegment",
5379 "Reassemble X11 messages spanning multiple TCP segments",
5380 "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
5381 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5386 proto_reg_handoff_x11(void)
5388 dissector_handle_t x11_handle;
5390 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5391 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5392 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5393 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
5394 data_handle = find_dissector("data");