2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /* TODO (in no particular order):
31 * - keep track of Atom creation by server to be able to display
32 * non-predefined atoms
33 * - Idem for keysym <-> keycode ???
35 * - Subtree the request ids (that is x11.create-window.window and
36 * x11.change-window.window should be distinct), and add hidden fields
37 * (so we still have x11.window).
38 * - add hidden fields so we can have x11.circulate-window in addition to
39 * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
41 * - add hidden fields so we have x11.listOfStuff.length
42 * - use a faster scheme that linear list searching for the opcode.
43 * - correct display of Unicode chars.
44 * - Not everything is homogeneous, in particular the handling of items in
45 * list is a total mess.
48 /* By the way, I wrote a program to generate every request and test
49 * that stuff. If you're interested, you can get it at
50 * http://tronche.com/gui/x/
64 #include <epan/packet.h>
65 #include <epan/conversation.h>
67 #include <epan/prefs.h>
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
70 #include <epan/emem.h>
72 #define cVALS(x) (const value_string*)(x)
75 * Data structure associated with a conversation; keeps track of the
76 * request for which we're expecting a reply, the frame number of
77 * the initial connection request, and the byte order of the connection.
79 * An opcode of -3 means we haven't yet seen any requests yet.
80 * An opcode of -2 means we're not expecting a reply (unused).
81 * An opcode of -1 means we're waiting for a reply to the initial
83 * An opcode of 0 means the request was not seen (or unknown).
84 * Other values are the opcode of the request for which we're expecting
88 #define NOTHING_SEEN -3
89 #define NOTHING_EXPECTED -2
90 #define INITIAL_CONN -1
91 #define UNKNOWN_OPCODE 0
93 #define MAX_OPCODES (255 + 1) /* 255 + INITIAL_CONN */
95 #define BYTE_ORDER_BE 0
96 #define BYTE_ORDER_LE 1
97 #define BYTE_ORDER_UNKNOWN -1
99 static const char *modifiers[] = {
110 /* Keymasks. From <X11/X.h>. */
111 #define ShiftMask (1<<0)
112 #define LockMask (1<<1)
113 #define ControlMask (1<<2)
114 #define Mod1Mask (1<<3)
115 #define Mod2Mask (1<<4)
116 #define Mod3Mask (1<<5)
117 #define Mod4Mask (1<<6)
118 #define Mod5Mask (1<<7)
120 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
121 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
124 #define NoSymbol 0L /* special KeySym */
126 typedef struct _x11_conv_data {
127 struct _x11_conv_data *next;
128 GHashTable *seqtable; /* hashtable of sequencenumber <-> opcode. */
129 GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
130 /* major opcodes including extensions (NULL terminated) */
131 value_string opcode_vals[MAX_OPCODES+1];
132 int sequencenumber; /* sequencenumber of current packet. */
133 guint32 iconn_frame; /* frame # of initial connection request */
134 guint32 iconn_reply; /* frame # of initial connection reply */
135 int byte_order; /* byte order of connection */
136 gboolean resync; /* resynchronization of sequence number performed */
138 int *keycodemap[256]; /* keycode to keysymvalue map. */
139 int keysyms_per_keycode;
141 int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
142 int keycodes_per_modifier;
147 } GetKeyboardMapping;
151 static x11_conv_data_t *x11_conv_data_list;
153 /* Initialize the protocol and registered fields */
154 static int proto_x11 = -1;
156 #include "x11-declarations.h"
158 /* Initialize the subtree pointers */
159 static gint ett_x11 = -1;
160 static gint ett_x11_color_flags = -1;
161 static gint ett_x11_list_of_arc = -1;
162 static gint ett_x11_arc = -1;
163 static gint ett_x11_list_of_atom = -1;
164 static gint ett_x11_list_of_card32 = -1;
165 static gint ett_x11_list_of_color_item = -1;
166 static gint ett_x11_color_item = -1;
167 static gint ett_x11_list_of_keycode = -1;
168 static gint ett_x11_list_of_keysyms = -1;
169 static gint ett_x11_keysym = -1;
170 static gint ett_x11_list_of_point = -1;
171 static gint ett_x11_point = -1;
172 static gint ett_x11_list_of_rectangle = -1;
173 static gint ett_x11_rectangle = -1;
174 static gint ett_x11_list_of_segment = -1;
175 static gint ett_x11_segment = -1;
176 static gint ett_x11_list_of_string8 = -1;
177 static gint ett_x11_list_of_text_item = -1;
178 static gint ett_x11_text_item = -1;
179 static gint ett_x11_gc_value_mask = -1; /* XXX - unused */
180 static gint ett_x11_event_mask = -1; /* XXX - unused */
181 static gint ett_x11_do_not_propagate_mask = -1; /* XXX - unused */
182 static gint ett_x11_set_of_key_mask = -1;
183 static gint ett_x11_pointer_event_mask = -1; /* XXX - unused */
184 static gint ett_x11_window_value_mask = -1; /* XXX - unused */
185 static gint ett_x11_configure_window_mask = -1; /* XXX - unused */
186 static gint ett_x11_keyboard_value_mask = -1; /* XXX - unused */
187 static gint ett_x11_same_screen_focus = -1;
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) {
1313 buffer=ep_alloc(512);
1315 bp = buffer + MIN(512, g_snprintf(buffer, 512, "flags: "));
1317 if (do_red_green_blue & 0x1) {
1318 bp += MIN(512-(bp-buffer),
1319 g_snprintf(bp, 512-(bp-buffer), "DoRed"));
1323 if (do_red_green_blue & 0x2) {
1324 if (sep) bp += MIN(512-(bp-buffer),
1325 g_snprintf(bp, 512-(bp-buffer), " | "));
1326 bp += MIN(512-(bp-buffer),
1327 g_snprintf(bp, 512-(bp-buffer), "DoGreen"));
1331 if (do_red_green_blue & 0x4) {
1332 if (sep) bp += MIN(512-(bp-buffer),
1333 g_snprintf(bp, 512-(bp-buffer), " | "));
1334 bp += MIN(512-(bp-buffer),
1335 g_snprintf(bp, 512-(bp-buffer), "DoBlue"));
1339 if (do_red_green_blue & 0xf8) {
1340 if (sep) bp += MIN(512-(bp-buffer),
1341 g_snprintf(bp, 512-(bp-buffer), " + "));
1342 MIN(512-(bp-buffer),
1343 g_snprintf(bp, 512-(bp-buffer), "trash"));
1346 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1348 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1349 if (do_red_green_blue & 0x1)
1350 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1351 do_red_green_blue & 0x1);
1352 if (do_red_green_blue & 0x2)
1353 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1354 do_red_green_blue & 0x2);
1355 if (do_red_green_blue & 0x4)
1356 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1357 do_red_green_blue & 0x4);
1358 if (do_red_green_blue & 0xf8)
1359 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1360 do_red_green_blue & 0xf8);
1362 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1367 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1368 int hf, const char *nullInterpretation)
1370 guint8 v = VALUE8(tvb, *offsetp);
1373 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1374 proto_registrar_get_nth(hf) -> name,
1375 nullInterpretation);
1377 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1381 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1382 int length, gboolean little_endian)
1384 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1385 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1387 gint16 x = VALUE16(tvb, *offsetp);
1388 gint16 y = VALUE16(tvb, *offsetp + 2);
1389 guint16 width = VALUE16(tvb, *offsetp + 4);
1390 guint16 height = VALUE16(tvb, *offsetp + 6);
1391 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1392 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1394 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1395 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1396 width, height, x, y, angle1, angle2,
1397 angle1 / 64.0, angle2 / 64.0);
1398 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1399 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1401 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1403 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1405 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1407 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1409 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1414 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1415 int length, gboolean little_endian)
1417 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1418 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1420 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1423 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1424 int length, gboolean little_endian)
1426 if (length <= 0) length = 1;
1427 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1431 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1432 int hf_item, int length, gboolean little_endian)
1434 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1435 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1437 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1442 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1443 int length, gboolean little_endian)
1445 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1446 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1450 unsigned do_red_green_blue;
1451 guint16 red, green, blue;
1456 buffer=ep_alloc(1024);
1457 red = VALUE16(tvb, *offsetp + 4);
1458 green = VALUE16(tvb, *offsetp + 6);
1459 blue = VALUE16(tvb, *offsetp + 8);
1460 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1462 bp = buffer + MIN(1024, g_snprintf(buffer, 1024, "colorItem: "));
1464 if (do_red_green_blue & 0x1) {
1465 bp += MIN(1024-(bp-buffer),
1466 g_snprintf(bp, 1024-(bp-buffer), "red = %d", red));
1469 if (do_red_green_blue & 0x2) {
1470 bp += MIN(1024-(bp-buffer),
1471 g_snprintf(bp, 1024-(bp-buffer), "%sgreen = %d", sep, green));
1474 if (do_red_green_blue & 0x4)
1475 bp += MIN(1024-(bp-buffer),
1476 g_snprintf(bp, 1024-(bp-buffer), "%sblue = %d", sep, blue));
1478 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1479 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1480 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1482 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1484 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1486 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1488 colorFlags(tvb, offsetp, ttt);
1489 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1494 static GTree *keysymTable = NULL;
1496 static gint compareGuint32(gconstpointer a, gconstpointer b)
1498 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1502 XConvertCase(register int sym, int *lower, int *upper)
1507 case 0: /* Latin 1 */
1508 if ((sym >= XK_A) && (sym <= XK_Z))
1509 *lower += (XK_a - XK_A);
1510 else if ((sym >= XK_a) && (sym <= XK_z))
1511 *upper -= (XK_a - XK_A);
1512 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1513 *lower += (XK_agrave - XK_Agrave);
1514 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1515 *upper -= (XK_agrave - XK_Agrave);
1516 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1517 *lower += (XK_oslash - XK_Ooblique);
1518 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1519 *upper -= (XK_oslash - XK_Ooblique);
1521 case 1: /* Latin 2 */
1522 /* Assume the KeySym is a legal value (ignore discontinuities) */
1523 if (sym == XK_Aogonek)
1524 *lower = XK_aogonek;
1525 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1526 *lower += (XK_lstroke - XK_Lstroke);
1527 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1528 *lower += (XK_scaron - XK_Scaron);
1529 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1530 *lower += (XK_zcaron - XK_Zcaron);
1531 else if (sym == XK_aogonek)
1532 *upper = XK_Aogonek;
1533 else if (sym >= XK_lstroke && sym <= XK_sacute)
1534 *upper -= (XK_lstroke - XK_Lstroke);
1535 else if (sym >= XK_scaron && sym <= XK_zacute)
1536 *upper -= (XK_scaron - XK_Scaron);
1537 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1538 *upper -= (XK_zcaron - XK_Zcaron);
1539 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1540 *lower += (XK_racute - XK_Racute);
1541 else if (sym >= XK_racute && sym <= XK_tcedilla)
1542 *upper -= (XK_racute - XK_Racute);
1544 case 2: /* Latin 3 */
1545 /* Assume the KeySym is a legal value (ignore discontinuities) */
1546 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1547 *lower += (XK_hstroke - XK_Hstroke);
1548 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1549 *lower += (XK_gbreve - XK_Gbreve);
1550 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1551 *upper -= (XK_hstroke - XK_Hstroke);
1552 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1553 *upper -= (XK_gbreve - XK_Gbreve);
1554 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1555 *lower += (XK_cabovedot - XK_Cabovedot);
1556 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1557 *upper -= (XK_cabovedot - XK_Cabovedot);
1559 case 3: /* Latin 4 */
1560 /* Assume the KeySym is a legal value (ignore discontinuities) */
1561 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1562 *lower += (XK_rcedilla - XK_Rcedilla);
1563 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1564 *upper -= (XK_rcedilla - XK_Rcedilla);
1565 else if (sym == XK_ENG)
1567 else if (sym == XK_eng)
1569 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1570 *lower += (XK_amacron - XK_Amacron);
1571 else if (sym >= XK_amacron && sym <= XK_umacron)
1572 *upper -= (XK_amacron - XK_Amacron);
1574 case 6: /* Cyrillic */
1575 /* Assume the KeySym is a legal value (ignore discontinuities) */
1576 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1577 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1578 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1579 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1580 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1581 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1582 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1583 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1586 /* Assume the KeySym is a legal value (ignore discontinuities) */
1587 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1588 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1589 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1590 sym != XK_Greek_iotaaccentdieresis &&
1591 sym != XK_Greek_upsilonaccentdieresis)
1592 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1593 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1594 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1595 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1596 sym != XK_Greek_finalsmallsigma)
1597 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1603 keycode2keysymString(int *keycodemap[256], int first_keycode,
1604 int keysyms_per_keycode,
1605 int *modifiermap[array_length(modifiers)],
1606 int keycodes_per_modifier,
1607 guint32 keycode, guint32 bitmask)
1611 int groupmodkc, numlockkc, numlockmod, groupmod;
1612 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1613 int lockmod_is_nosymbol = 1;
1614 int modifier, kc, keysym;
1616 if ((syms = keycodemap[keycode]) == NULL)
1619 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1620 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1621 if (keycodemap[kc] == NULL)
1623 switch (keycodemap[kc][keysym]) {
1633 lockmod_is_capslock = kc;
1637 lockmod_is_shiftlock = kc;
1644 * If we have not seen the modifiermap we don't know what the
1645 * keycode translates to, but we do know it's one of the keys
1646 * in syms (give or take a case-conversion), so we could in
1647 * theory list them all.
1649 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1652 /* find out what the numlockmodifer and groupmodifier is. */
1653 for (modifier = 0, numlockmod = groupmod = -1;
1654 modifier < (int)array_length(modifiers) && numlockmod == -1;
1656 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1657 if (modifiermap[modifier][kc] == numlockkc)
1658 numlockmod = modifier;
1659 else if (modifiermap[modifier][kc] == groupmodkc)
1660 groupmod = modifier;
1663 * ... and what the lockmodifier is interpreted as.
1664 * (X11v4r6 ref, keyboard and pointers section.)
1666 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1667 if (modifiermap[1][kc] == lockmod_is_capslock) {
1668 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1671 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1672 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1678 * This is (how I understand) the X11v4R6 protocol description given
1679 * in A. Nye's book. It is quite different from the
1680 * code in _XTranslateKey() in the file
1681 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1682 * as shipped with XFree, and doesn't work correctly, nor do I see
1683 * how it could (e.g. the case of lower/uppercase-letters).
1684 * -- Michael Shuldman
1687 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1688 && ((syms[1] >= 0xff80
1689 && syms[1] <= 0xffbd)
1690 || (syms[1] >= 0x11000000
1691 && syms[1] <= 0x1100ffff))) {
1692 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1693 return keysymString(syms[groupmod + 0]);
1695 if (syms[groupmod + 1] == NoSymbol)
1696 return keysymString(syms[groupmod + 0]);
1698 return keysymString(syms[groupmod + 1]);
1700 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1701 return keysymString(syms[groupmod + 0]);
1702 else if (!(bitmask & ShiftMask)
1703 && ((bitmask & LockMask) && lockmod_is_capslock))
1704 if (islower(syms[groupmod + 0]))
1705 /* return toupper(keysymString(syms[groupmod + 0])); */
1706 return "Uppercase"; /* XXX */
1708 return keysymString(syms[groupmod + 0]);
1710 else if ((bitmask & ShiftMask)
1711 && ((bitmask & LockMask) && lockmod_is_capslock))
1712 if (islower(syms[groupmod + 1]))
1713 /* return toupper(keysymString(syms[groupmod + 1])); */
1714 return "Uppercase"; /* XXX */
1716 return keysymString(syms[groupmod + 1]);
1718 else if ((bitmask & ShiftMask)
1719 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1720 return keysymString(syms[groupmod + 1]);
1721 #else /* _XTranslateKey() based code. */
1723 while (keysyms_per_keycode > 2
1724 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1725 --keysyms_per_keycode;
1726 if (keysyms_per_keycode > 2
1727 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1729 keysyms_per_keycode -= 2;
1732 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1733 && keysyms_per_keycode > 1
1734 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1735 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1736 if ((bitmask & ShiftMask)
1737 || (bitmask & LockMask && lockmod_is_shiftlock))
1742 else if (!(bitmask & ShiftMask)
1743 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1744 if (keysyms_per_keycode == 1
1745 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1748 XConvertCase(syms[0], &keysym, &usym);
1753 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1756 if (keysyms_per_keycode == 1
1757 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1758 XConvertCase(syms[0], &lsym, &usym);
1764 if (keysyms_per_keycode == 1
1765 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1768 XConvertCase(keysym, &lsym, &usym);
1770 if (!(bitmask & ShiftMask) && keysym != syms[0]
1771 && ((keysym != usym) || (lsym == usym)))
1772 XConvertCase(syms[0], &lsym, &usym);
1776 if (keysym == XK_VoidSymbol)
1780 g_snprintf(buf, 32, "%d, \"%s\"", keysym, keysymString(keysym));
1785 static const char *keysymString(guint32 v)
1790 /* This table is so big that we built it only if necessary */
1792 const value_string *p = keysym_vals_source;
1793 keysymTable = g_tree_new(compareGuint32);
1794 for(; p -> strptr; p++)
1795 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), (gpointer) (p -> strptr) );
1797 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1798 return res ? res : "<Unknown>";
1801 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1802 int *modifiermap[], int keycodes_per_modifier,
1803 gboolean little_endian)
1805 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1806 array_length(modifiers) * keycodes_per_modifier, little_endian);
1807 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1810 for (m = 0; m < array_length(modifiers);
1811 ++m, *offsetp += keycodes_per_modifier) {
1816 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1818 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1820 tikc = proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1821 *offsetp, keycodes_per_modifier, p, "item: ");
1822 for(i = 0; i < keycodes_per_modifier; ++i) {
1826 proto_item_append_text(tikc, " %s=%d", modifiers[m], c);
1828 modifiermap[m][i] = c;
1833 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1834 int hf_item, int *keycodemap[256],
1835 int keycode_first, int keycode_count,
1836 int keysyms_per_keycode, gboolean little_endian)
1838 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1839 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1844 DISSECTOR_ASSERT(keycode_first >= 0);
1845 DISSECTOR_ASSERT(keycode_count >= 0);
1847 for (keycode = keycode_first; keycode_count > 0;
1848 ++keycode, --keycode_count) {
1849 if (keycode >= 256) {
1850 proto_tree_add_text(tt, tvb, *offsetp, 4 * keysyms_per_keycode,
1851 "keycode value %d is out of range", keycode);
1852 *offsetp += 4 * keysyms_per_keycode;
1855 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1856 4 * keysyms_per_keycode, "keysyms (keycode %d):", keycode);
1858 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1860 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1862 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1864 for(i = 0; i < keysyms_per_keycode; ++i) {
1865 /* keysymvalue = byte3 * 256 + byte4. */
1866 guint32 v = VALUE32(tvb, *offsetp);
1868 proto_item_append_text(tti, " %s", keysymString(v));
1869 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1870 tvb, *offsetp, 4, v,
1871 "keysym (keycode %d): 0x%08x (%s)",
1872 keycode, v, keysymString(v));
1874 keycodemap[keycode][i] = v;
1878 for (i = 1; i < keysyms_per_keycode; ++i)
1879 if (keycodemap[keycode][i] != NoSymbol)
1882 if (i == keysyms_per_keycode) {
1883 /* all but (possibly) first were NoSymbol. */
1884 if (keysyms_per_keycode == 4) {
1885 keycodemap[keycode][1] = NoSymbol;
1886 keycodemap[keycode][2] = keycodemap[keycode][0];
1887 keycodemap[keycode][3] = NoSymbol;
1893 for (i = 2; i < keysyms_per_keycode; ++i)
1894 if (keycodemap[keycode][i] != NoSymbol)
1896 if (i == keysyms_per_keycode) {
1897 /* all but (possibly) first two were NoSymbol. */
1898 if (keysyms_per_keycode == 4) {
1899 keycodemap[keycode][2] = keycodemap[keycode][0];
1900 keycodemap[keycode][3] = keycodemap[keycode][1];
1908 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1909 int length, gboolean little_endian)
1911 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1912 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1918 x = VALUE16(tvb, *offsetp);
1919 y = VALUE16(tvb, *offsetp + 2);
1921 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1922 ttt = proto_item_add_subtree(tti, ett_x11_point);
1923 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1925 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1930 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1931 int length, gboolean little_endian)
1933 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1934 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1937 unsigned width, height;
1941 x = VALUE16(tvb, *offsetp);
1942 y = VALUE16(tvb, *offsetp + 2);
1943 width = VALUE16(tvb, *offsetp + 4);
1944 height = VALUE16(tvb, *offsetp + 6);
1946 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1947 "rectangle: %dx%d+%d+%d", width, height, x, y);
1948 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1949 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1951 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1953 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1955 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1960 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1961 int length, gboolean little_endian)
1963 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1964 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1966 gint16 x1, y1, x2, y2;
1970 x1 = VALUE16(tvb, *offsetp);
1971 y1 = VALUE16(tvb, *offsetp + 2);
1972 x2 = VALUE16(tvb, *offsetp + 4);
1973 y2 = VALUE16(tvb, *offsetp + 6);
1975 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1976 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1977 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1978 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1980 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1982 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1984 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1989 /* XXX - the protocol tree code should handle non-printable characters.
1990 Note that "non-printable characters" may depend on your locale.... */
1991 static void stringCopy(char *dest, const char *source, int length)
1996 if (!isgraph(c) && c != ' ') c = '.';
2002 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2003 int hf_item, int length, gboolean little_endian)
2006 guint allocated = 0;
2011 /* Compute total length */
2013 int scanning_offset = *offsetp; /* Scanning pointer */
2015 for(i = length; i; i--) {
2016 l = tvb_get_guint8(tvb, scanning_offset);
2017 scanning_offset += 1 + l;
2020 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2021 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2024 unsigned l = VALUE8(tvb, *offsetp);
2025 if (allocated < (l + 1)) {
2026 s = ep_alloc(l + 1);
2029 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2030 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2035 #define STRING16_MAX_DISPLAYED_LENGTH 150
2037 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2039 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2040 for(; length > 0; offset += 2, length--) {
2041 if (tvb_get_guint8(tvb, offset))
2047 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2049 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2050 int hf, int hf_bytes,
2051 int offset, unsigned length,
2052 char **s, int *sLength,
2053 gboolean little_endian)
2055 int truncated = FALSE;
2056 unsigned l = length / 2;
2058 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2060 int soffset = offset;
2062 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2064 l = STRING16_MAX_DISPLAYED_LENGTH;
2066 if (*sLength < (int) l + 3) {
2067 *s = ep_alloc(l + 3);
2072 if (truncated) l -= 3;
2076 *dp++ = tvb_get_guint8(tvb, soffset);
2081 /* If truncated, add an ellipsis */
2082 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2085 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
2086 proto_registrar_get_nth(hf) -> name, *s);
2088 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2092 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2093 int sizeIs16, int next_offset, gboolean little_endian)
2101 /* Compute total length */
2103 int scanning_offset = *offsetp; /* Scanning pointer */
2104 int l; /* Length of an individual item */
2105 int n = 0; /* Number of items */
2107 while(scanning_offset < next_offset) {
2108 l = tvb_get_guint8(tvb, scanning_offset);
2112 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2115 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2116 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2119 unsigned l = VALUE8(tvb, *offsetp);
2120 if (l == 255) { /* Item is a font */
2121 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2122 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2124 } else { /* Item is a string */
2127 gint8 delta = VALUE8(tvb, *offsetp + 1);
2128 if (sizeIs16) l += l;
2129 if ((unsigned) allocated < l + 1) {
2130 s = ep_alloc(l + 1);
2133 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2134 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2135 "textitem (string): delta = %d, \"%s\"",
2137 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2138 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2140 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2141 hf_x11_textitem_string_string16_bytes,
2146 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2147 *offsetp + 2, l, s, "\"%s\"", s);
2153 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2154 gboolean little_endian)
2156 guint32 v = VALUE8(tvb, *offsetp);
2157 header_field_info *hfi = proto_registrar_get_nth(hf);
2158 const gchar *enumValue = NULL;
2161 enumValue = match_strval(v, cVALS(hfi -> strings));
2163 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2164 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2165 hfi -> name, v, enumValue);
2167 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2172 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2173 gboolean little_endian)
2175 guint32 v = VALUE16(tvb, *offsetp);
2176 header_field_info *hfi = proto_registrar_get_nth(hf);
2177 const gchar *enumValue = NULL;
2180 enumValue = match_strval(v, cVALS(hfi -> strings));
2182 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2183 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2184 hfi -> name, v, enumValue);
2186 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2191 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2192 gboolean little_endian)
2194 guint32 v = VALUE32(tvb, *offsetp);
2195 header_field_info *hfi = proto_registrar_get_nth(hf);
2196 const gchar *enumValue = NULL;
2197 const gchar *nameAsChar = hfi -> name;
2200 enumValue = match_strval(v, cVALS(hfi -> strings));
2202 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2203 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2204 nameAsChar, v, enumValue);
2206 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2207 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2213 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2214 gboolean little_endian)
2216 BITMASK32(gc_value);
2217 BITFIELD(ENUM8, gc_value_mask, function);
2218 BITFIELD(CARD32, gc_value_mask, plane_mask);
2219 BITFIELD(CARD32, gc_value_mask, foreground);
2220 BITFIELD(CARD32, gc_value_mask, background);
2221 BITFIELD(CARD16, gc_value_mask, line_width);
2222 BITFIELD(ENUM8, gc_value_mask, line_style);
2223 BITFIELD(ENUM8, gc_value_mask, cap_style);
2224 BITFIELD(ENUM8, gc_value_mask, join_style);
2225 BITFIELD(ENUM8, gc_value_mask, fill_style);
2226 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2227 BITFIELD(PIXMAP, gc_value_mask, tile);
2228 BITFIELD(PIXMAP, gc_value_mask, stipple);
2229 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2230 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2231 BITFIELD(FONT, gc_value_mask, font);
2232 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2233 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2234 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2235 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2236 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2237 BITFIELD(CARD16, gc_value_mask, dash_offset);
2238 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2239 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2243 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2244 gboolean little_endian)
2246 BITMASK32(gc_value);
2247 FLAG(gc_value, function);
2248 FLAG(gc_value, plane_mask);
2249 FLAG(gc_value, foreground);
2250 FLAG(gc_value, background);
2251 FLAG(gc_value, line_width);
2252 FLAG(gc_value, line_style);
2253 FLAG(gc_value, cap_style);
2254 FLAG(gc_value, join_style);
2255 FLAG(gc_value, fill_style);
2256 FLAG(gc_value, fill_rule);
2257 FLAG(gc_value, tile);
2258 FLAG(gc_value, stipple);
2259 FLAG(gc_value, tile_stipple_x_origin);
2260 FLAG(gc_value, tile_stipple_y_origin);
2261 FLAG(gc_value, font);
2262 FLAG(gc_value, subwindow_mode);
2263 FLAG(gc_value, graphics_exposures);
2264 FLAG(gc_value, clip_x_origin);
2265 FLAG(gc_value, clip_y_origin);
2266 FLAG(gc_value, clip_mask);
2267 FLAG(gc_value, dash_offset);
2268 FLAG(gc_value, gc_dashes);
2269 FLAG(gc_value, arc_mode);
2273 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2274 gboolean little_endian)
2276 guint32 res = VALUE16(tvb, *offsetp);
2277 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2282 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2283 gboolean little_endian)
2286 FLAG(event, KeyPress);
2287 FLAG(event, KeyRelease);
2288 FLAG(event, ButtonPress);
2289 FLAG(event, ButtonRelease);
2290 FLAG(event, EnterWindow);
2291 FLAG(event, LeaveWindow);
2292 FLAG(event, PointerMotion);
2293 FLAG(event, PointerMotionHint);
2294 FLAG(event, Button1Motion);
2295 FLAG(event, Button2Motion);
2296 FLAG(event, Button3Motion);
2297 FLAG(event, Button4Motion);
2298 FLAG(event, Button5Motion);
2299 FLAG(event, ButtonMotion);
2300 FLAG(event, KeymapState);
2301 FLAG(event, Exposure);
2302 FLAG(event, VisibilityChange);
2303 FLAG(event, StructureNotify);
2304 FLAG(event, ResizeRedirect);
2305 FLAG(event, SubstructureNotify);
2306 FLAG(event, SubstructureRedirect);
2307 FLAG(event, FocusChange);
2308 FLAG(event, PropertyChange);
2309 FLAG(event, ColormapChange);
2310 FLAG(event, OwnerGrabButton);
2311 FLAG_IF_NONZERO(event, erroneous_bits);
2315 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2316 gboolean little_endian)
2318 BITMASK32(do_not_propagate);
2319 FLAG(do_not_propagate, KeyPress);
2320 FLAG(do_not_propagate, KeyRelease);
2321 FLAG(do_not_propagate, ButtonPress);
2322 FLAG(do_not_propagate, ButtonRelease);
2323 FLAG(do_not_propagate, PointerMotion);
2324 FLAG(do_not_propagate, Button1Motion);
2325 FLAG(do_not_propagate, Button2Motion);
2326 FLAG(do_not_propagate, Button3Motion);
2327 FLAG(do_not_propagate, Button4Motion);
2328 FLAG(do_not_propagate, Button5Motion);
2329 FLAG(do_not_propagate, ButtonMotion);
2330 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2335 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2336 gboolean little_endian, gboolean butmask)
2339 guint32 bitmask_value;
2342 proto_tree *bitmask_tree;
2344 bitmask_value = VALUE16(tvb, *offsetp);
2345 bitmask_offset = *offsetp;
2348 if (!butmask && bitmask_value == 0x8000)
2349 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2350 "modifiers-masks: 0x8000 (AnyModifier)");
2352 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2354 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2355 FLAG(modifiers, Shift);
2356 FLAG(modifiers, Lock);
2357 FLAG(modifiers, Control);
2358 FLAG(modifiers, Mod1);
2359 FLAG(modifiers, Mod2);
2360 FLAG(modifiers, Mod3);
2361 FLAG(modifiers, Mod4);
2362 FLAG(modifiers, Mod5);
2365 FLAG(modifiers, Button1);
2366 FLAG(modifiers, Button2);
2367 FLAG(modifiers, Button3);
2368 FLAG(modifiers, Button4);
2369 FLAG(modifiers, Button5);
2373 FLAG_IF_NONZERO(keybut, erroneous_bits);
2375 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2380 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2381 gboolean little_endian)
2383 BITMASK16(pointer_event);
2384 FLAG(pointer_event, ButtonPress);
2385 FLAG(pointer_event, ButtonRelease);
2386 FLAG(pointer_event, EnterWindow);
2387 FLAG(pointer_event, LeaveWindow);
2388 FLAG(pointer_event, PointerMotion);
2389 FLAG(pointer_event, PointerMotionHint);
2390 FLAG(pointer_event, Button1Motion);
2391 FLAG(pointer_event, Button2Motion);
2392 FLAG(pointer_event, Button3Motion);
2393 FLAG(pointer_event, Button4Motion);
2394 FLAG(pointer_event, Button5Motion);
2395 FLAG(pointer_event, ButtonMotion);
2396 FLAG(pointer_event, KeymapState);
2397 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2401 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2402 int hf, unsigned length)
2407 p = tvb_get_ptr(tvb, *offsetp, length);
2408 s = ep_alloc(length + 1);
2409 stringCopy(s, p, length);
2410 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2414 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2416 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2417 int hf_bytes, unsigned length, gboolean little_endian)
2423 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2424 &s, &l, little_endian);
2429 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2430 gboolean little_endian)
2432 guint32 v = VALUE32(tvb, *offsetp);
2435 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2436 proto_registrar_get_nth(hf) -> name);
2438 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2442 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2443 gboolean little_endian)
2445 BITMASK32(window_value);
2446 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2447 BITFIELD(CARD32, window_value_mask, background_pixel);
2448 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2449 BITFIELD(CARD32, window_value_mask, border_pixel);
2450 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2451 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2452 BITFIELD(ENUM8, window_value_mask, backing_store);
2453 BITFIELD(CARD32, window_value_mask, backing_planes);
2454 BITFIELD(CARD32, window_value_mask, backing_pixel);
2455 BITFIELD(BOOL, window_value_mask, override_redirect);
2456 BITFIELD(BOOL, window_value_mask, save_under);
2457 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2458 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2459 BITFIELD(COLORMAP, window_value_mask, colormap);
2460 BITFIELD(CURSOR, window_value_mask, cursor);
2464 static void x11_init_protocol(void)
2466 x11_conv_data_t *state;
2468 for (state = x11_conv_data_list; state != NULL; state = state->next) {
2469 g_hash_table_destroy(state->seqtable);
2470 g_hash_table_destroy(state->valtable);
2472 x11_conv_data_list = NULL;
2475 /************************************************************************
2477 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2479 ************************************************************************/
2481 /* If we can't guess, we return TRUE (that is little_endian), cause
2482 I'm developing on a Linux box :-). The (non-)guess isn't cached
2483 however, so we may have more luck next time. I'm quite conservative
2484 in my assertions, cause once it's cached, it's stay in cache, and
2485 we may be fooled up by a packet starting with the end of a request
2486 started in a previous packet...
2489 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2491 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2494 while(maskLength--) {
2495 int c = tvb_get_guint8(tvb, offset);
2497 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2502 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2504 if (listLength > length) return FALSE;
2505 while(listLength--) {
2507 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2508 l = tvb_get_guint8(tvb, offset);
2511 if (l > length) return FALSE;
2512 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2516 if (length > 3) return FALSE;
2520 static int rounded4(int n)
2522 int remainder = n % 4;
2524 if (remainder) res++;
2528 /* We assume the order to be consistent, until proven wrong. */
2530 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2532 switch(tvb_get_guint8(tvb, offset)) {
2533 case X_CreateWindow:
2534 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2536 case X_ChangeWindowAttributes:
2538 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2540 case X_GetWindowAttributes:
2541 case X_DestroyWindow:
2542 case X_DestroySubwindows:
2543 case X_ChangeSaveSet:
2545 case X_MapSubwindows:
2547 case X_UnmapSubwindows:
2548 case X_CirculateWindow:
2552 case X_ListProperties:
2553 case X_GetSelectionOwner:
2554 case X_UngrabPointer:
2555 case X_UngrabKeyboard:
2557 case X_QueryPointer:
2562 case X_FreeColormap:
2563 case X_InstallColormap:
2564 case X_UninstallColormap:
2565 case X_ListInstalledColormaps:
2567 case X_GetKeyboardMapping:
2571 case X_ReparentWindow:
2572 case X_SetSelectionOwner:
2573 case X_ChangeActivePointerGrab:
2574 case X_GrabKeyboard:
2576 case X_GetMotionEvents:
2577 case X_TranslateCoords:
2578 case X_CreatePixmap:
2581 case X_CreateColormap:
2583 case X_AllocColorPlanes:
2586 case X_ConfigureWindow:
2587 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2590 case X_QueryExtension:
2591 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2593 case X_ChangeProperty:
2595 int multiplier, type;
2596 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2597 type = tvb_get_guint8(tvb, 16);
2598 if (type != 8 && type != 16 && type != 32) return FALSE;
2599 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2600 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2601 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2604 case X_DeleteProperty:
2605 case X_UngrabButton:
2607 case X_SetInputFocus:
2608 case X_CopyColormapAndFree:
2609 case X_AllocColorCells:
2610 case X_QueryBestSize:
2611 case X_ChangePointerControl:
2612 case X_SetScreenSaver:
2616 case X_ConvertSelection:
2623 return length == 11;
2626 case X_UngrabServer:
2627 case X_GetInputFocus:
2630 case X_ListExtensions:
2631 case X_GetKeyboardControl:
2633 case X_GetPointerControl:
2634 case X_GetScreenSaver:
2636 case X_SetAccessControl:
2637 case X_SetCloseDownMode:
2638 case X_ForceScreenSaver:
2639 case X_GetPointerMapping:
2640 case X_GetModifierMapping:
2644 case X_AllocNamedColor:
2646 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2648 case X_QueryTextExtents:
2652 case X_ListFontsWithInfo:
2654 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2657 if (length < 2) return FALSE;
2658 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2659 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2662 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2665 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2667 case X_SetClipRectangles:
2669 case X_PolyRectangle:
2670 case X_PolyFillRectangle:
2671 return length >= 3 && (length - 3) % 2 == 0;
2677 case X_CreateCursor:
2678 case X_CreateGlyphCursor:
2688 return length >= 3 && (length - 3) % 3 == 0;
2698 case X_RecolorCursor:
2702 if (length < 4) return FALSE;
2703 return TRUE; /* We don't perform many controls on this one */
2706 if (length < 4) return FALSE;
2707 return TRUE; /* We don't perform many controls on this one */
2713 return length > 2 && (length - 2) % 3 == 0;
2715 case X_StoreNamedColor:
2716 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2721 case X_ChangeKeyboardMapping:
2722 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2724 case X_ChangeKeyboardControl:
2725 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2727 case X_RotateProperties:
2728 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2730 case X_SetPointerMapping:
2731 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2733 case X_SetModifierMapping:
2734 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2744 /* -1 means doesn't match, +1 means match, 0 means don't know */
2746 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2748 int offset, nextoffset;
2751 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2753 length = v16(tvb, offset + 2);
2754 if (!length) return -1;
2755 nextoffset = offset + length * 4;
2756 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2763 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2764 x11_conv_data_t *state)
2766 /* With X the client gives the byte ordering for the protocol,
2767 and the port on the server tells us we're speaking X. */
2769 int le, be, decision, decisionToCache;
2771 if (state->byte_order == BYTE_ORDER_BE)
2772 return FALSE; /* known to be big-endian */
2773 else if (state->byte_order == BYTE_ORDER_LE)
2774 return TRUE; /* known to be little-endian */
2776 if (pinfo->srcport == pinfo->match_port) {
2778 * This is a reply or event; we don't try to guess the
2779 * byte order on it for now.
2784 le = x_endian_match(tvb, tvb_get_letohs);
2785 be = x_endian_match(tvb, tvb_get_ntohs);
2787 /* remember that "decision" really means "little_endian". */
2789 /* We have no reason to believe it's little- rather than
2790 big-endian, so we guess the shortest length is the
2793 if (!tvb_bytes_exist(tvb, 0, 4))
2794 /* Not even a way to get the length. We're biased
2795 toward little endianness here (essentially the
2796 x86 world right now). Decoding won't go very far
2801 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2803 decision = le >= be;
2805 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2806 if (decisionToCache) {
2808 * Remember the decision.
2810 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2814 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2815 pinfo->fd -> num, le, be, decision, decisionToCache);
2820 /************************************************************************
2822 *** D E C O D I N G O N E P A C K E T ***
2824 ************************************************************************/
2827 * Decode an initial connection request.
2829 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2830 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2833 int *offsetp = &offset;
2836 guint16 auth_proto_name_length, auth_proto_data_length;
2839 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2840 proto_item_append_text(ti, ", Request, Initial connection request");
2841 t = proto_item_add_subtree(ti, ett_x11);
2845 CARD16(protocol_major_version);
2846 CARD16(protocol_minor_version);
2847 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2848 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2851 if (auth_proto_name_length != 0) {
2852 STRING8(authorization_protocol_name, auth_proto_name_length);
2853 offset = ROUND_LENGTH(offset);
2856 if (auth_proto_data_length != 0) {
2857 STRING8(authorization_protocol_data, auth_proto_data_length);
2858 offset = ROUND_LENGTH(offset);
2861 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2862 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2866 * This is the initial connection request...
2868 state->iconn_frame = pinfo->fd->num;
2871 * ...and we're expecting a reply to it.
2873 state->sequencenumber = 0;
2874 g_hash_table_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
2875 (int *)INITIAL_CONN);
2878 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2879 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2880 gboolean little_endian)
2882 int offset = 0, *offsetp = &offset, left;
2883 unsigned char success;
2884 int length_of_vendor;
2885 int length_of_reason;
2889 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2890 proto_item_append_text(ti, ", Reply, Initial connection reply");
2891 t = proto_item_add_subtree(ti, ett_x11);
2893 state->iconn_reply = pinfo->fd->num;
2894 success = INT8(success);
2897 length_of_reason = 0;
2900 length_of_reason = INT8(length_of_reason);
2903 INT16(protocol_major_version);
2904 INT16(protocol_minor_version);
2907 INT32(release_number);
2908 INT32(resource_id_base);
2909 INT32(resource_id_mask);
2910 INT32(motion_buffer_size);
2911 length_of_vendor = INT16(length_of_vendor);
2912 INT16(maximum_request_length);
2913 INT8(number_of_screens_in_roots);
2914 INT8(number_of_formats_in_pixmap_formats);
2915 INT8(image_byte_order);
2916 INT8(bitmap_format_bit_order);
2917 INT8(bitmap_format_scanline_unit);
2918 INT8(bitmap_format_scanline_pad);
2922 STRING8(vendor, length_of_vendor);
2924 STRING8(reason, length_of_reason);
2927 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2932 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2933 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2934 gboolean little_endian)
2937 int *offsetp = &offset;
2941 int length, opcode, i;
2942 guint8 v8, v8_2, v8_3;
2948 length = VALUE16(tvb, 2) * 4;
2951 /* Bogus message length? */
2955 next_offset = offset + length;
2957 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2958 t = proto_item_add_subtree(ti, ett_x11);
2960 if (PACKET_IS_NEW(pinfo))
2961 ++state->sequencenumber;
2965 if (check_col(pinfo->cinfo, COL_INFO))
2966 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2967 val_to_str(opcode, state->opcode_vals,
2968 "<Unknown opcode %d>"));
2970 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2971 opcode, val_to_str(opcode, state->opcode_vals,
2972 "<Unknown opcode %d>"));
2975 * Does this request expect a reply?
2979 case X_QueryExtension:
2981 /* necessary processing even if tree == NULL */
2983 v16 = VALUE16(tvb, 4);
2984 name = se_alloc(v16 + 1);
2985 stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
2987 /* store string of extension, opcode will be set at reply */
2989 while(i < MAX_OPCODES) {
2990 if (state->opcode_vals[i].strptr == NULL) {
2991 state->opcode_vals[i].strptr = name;
2992 g_hash_table_insert(state->valtable,
2993 GINT_TO_POINTER(state->sequencenumber),
2994 (int *)&state->opcode_vals[i]);
2996 } else if (strcmp(state->opcode_vals[i].strptr,
2998 g_hash_table_insert(state->valtable,
2999 GINT_TO_POINTER(state->sequencenumber),
3000 (int *)&state->opcode_vals[i]);
3006 /* QueryExtension expects a reply, fall through */
3009 case X_AllocColorCells:
3010 case X_AllocColorPlanes:
3011 case X_AllocNamedColor:
3016 case X_GetInputFocus:
3017 case X_GetKeyboardControl:
3018 case X_GetKeyboardMapping:
3019 case X_GetModifierMapping:
3020 case X_GetMotionEvents:
3021 case X_GetPointerControl:
3022 case X_GetPointerMapping:
3024 case X_GetScreenSaver:
3025 case X_GetSelectionOwner:
3026 case X_GetWindowAttributes:
3027 case X_GrabKeyboard:
3030 case X_ListExtensions:
3032 case X_ListFontsWithInfo:
3034 case X_ListInstalledColormaps:
3035 case X_ListProperties:
3037 case X_QueryBestSize:
3041 case X_QueryPointer:
3042 case X_QueryTextExtents:
3044 case X_SetModifierMapping:
3045 case X_SetPointerMapping:
3046 case X_TranslateCoords:
3048 * Those requests expect a reply.
3050 g_hash_table_insert(state->seqtable,
3051 GINT_TO_POINTER(state->sequencenumber),
3052 GINT_TO_POINTER(opcode));
3058 * With Extension, we don't know, so assume there could be one
3060 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3061 g_hash_table_insert(state->seqtable,
3062 GINT_TO_POINTER(state->sequencenumber),
3063 GINT_TO_POINTER(opcode));
3067 * No reply is expected from any other request.
3077 case X_CreateWindow:
3086 CARD16(border_width);
3087 ENUM16(window_class);
3089 windowAttributes(tvb, offsetp, t, little_endian);
3092 case X_ChangeWindowAttributes:
3096 windowAttributes(tvb, offsetp, t, little_endian);
3099 case X_GetWindowAttributes:
3100 case X_DestroyWindow:
3101 case X_DestroySubwindows:
3107 case X_ChangeSaveSet:
3108 ENUM8(save_set_mode);
3113 case X_ReparentWindow:
3123 case X_MapSubwindows:
3125 case X_UnmapSubwindows:
3131 case X_ConfigureWindow:
3135 BITMASK16(configure_window);
3137 BITFIELD(INT16, configure_window_mask, x);
3138 BITFIELD(INT16, configure_window_mask, y);
3139 BITFIELD(CARD16, configure_window_mask, width);
3140 BITFIELD(CARD16, configure_window_mask, height);
3141 BITFIELD(CARD16, configure_window_mask, border_width);
3142 BITFIELD(WINDOW, configure_window_mask, sibling);
3143 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3148 case X_CirculateWindow:
3162 BOOL(only_if_exists);
3164 v16 = FIELD16(name_length);
3176 case X_ChangeProperty:
3184 v32 = CARD32(data_length);
3185 LISTofBYTE(data, v32);
3189 case X_DeleteProperty:
3201 ATOM(get_property_type);
3202 CARD32(long_offset);
3203 CARD32(long_length);
3206 case X_ListProperties:
3212 case X_SetSelectionOwner:
3220 case X_GetSelectionOwner:
3226 case X_ConvertSelection:
3239 WINDOW(destination);
3240 SETofEVENT(event_mask);
3247 WINDOW(grab_window);
3248 SETofPOINTEREVENT(pointer_event_mask);
3249 ENUM8(pointer_mode);
3250 ENUM8(keyboard_mode);
3256 case X_UngrabPointer:
3265 WINDOW(grab_window);
3266 SETofPOINTEREVENT(event_mask);
3267 ENUM8(pointer_mode);
3268 ENUM8(keyboard_mode);
3273 SETofKEYMASK(modifiers);
3276 case X_UngrabButton:
3279 WINDOW(grab_window);
3280 SETofKEYMASK(modifiers);
3284 case X_ChangeActivePointerGrab:
3289 SETofPOINTEREVENT(event_mask);
3293 case X_GrabKeyboard:
3296 WINDOW(grab_window);
3298 ENUM8(pointer_mode);
3299 ENUM8(keyboard_mode);
3303 case X_UngrabKeyboard:
3312 WINDOW(grab_window);
3313 SETofKEYMASK(modifiers);
3315 ENUM8(pointer_mode);
3316 ENUM8(keyboard_mode);
3323 WINDOW(grab_window);
3324 SETofKEYMASK(modifiers);
3329 ENUM8(allow_events_mode);
3339 case X_UngrabServer:
3344 case X_QueryPointer:
3350 case X_GetMotionEvents:
3358 case X_TranslateCoords:
3370 WINDOW(warp_pointer_src_window);
3371 WINDOW(warp_pointer_dst_window);
3380 case X_SetInputFocus:
3387 case X_GetInputFocus:
3401 v16 = FIELD16(name_length);
3419 case X_QueryTextExtents:
3420 v8 = BOOL(odd_length);
3423 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3431 v16 = FIELD16(pattern_length);
3432 STRING8(pattern, v16);
3436 case X_ListFontsWithInfo:
3440 v16 = FIELD16(pattern_length);
3441 STRING8(pattern, v16);
3448 v16 = CARD16(str_number_in_path);
3450 LISTofSTRING8(path, v16);
3459 case X_CreatePixmap:
3479 gcAttributes(tvb, offsetp, t, little_endian);
3486 gcAttributes(tvb, offsetp, t, little_endian);
3494 gcMask(tvb, offsetp, t, little_endian);
3501 CARD16(dash_offset);
3502 v16 = FIELD16(dashes_length);
3503 LISTofCARD8(dashes, v16);
3507 case X_SetClipRectangles:
3511 INT16(clip_x_origin);
3512 INT16(clip_y_origin);
3513 LISTofRECTANGLE(rectangles);
3535 DRAWABLE(src_drawable);
3536 DRAWABLE(dst_drawable);
3549 DRAWABLE(src_drawable);
3550 DRAWABLE(dst_drawable);
3562 ENUM8(coordinate_mode);
3563 v16 = REQUEST_LENGTH();
3566 LISTofPOINT(points, v16 - 12);
3570 ENUM8(coordinate_mode);
3571 v16 = REQUEST_LENGTH();
3574 LISTofPOINT(points, v16 - 12);
3582 LISTofSEGMENT(segments);
3585 case X_PolyRectangle:
3590 LISTofRECTANGLE(rectangles);
3603 v16 = REQUEST_LENGTH();
3607 ENUM8(coordinate_mode);
3609 LISTofPOINT(points, v16 - 16);
3612 case X_PolyFillRectangle:
3617 LISTofRECTANGLE(rectangles);
3629 ENUM8(image_format);
3630 v16 = REQUEST_LENGTH();
3640 LISTofBYTE(data, v16 - 24);
3645 ENUM8(image_pixmap_format);
3657 v16 = REQUEST_LENGTH();
3662 LISTofTEXTITEM8(items);
3668 v16 = REQUEST_LENGTH();
3673 LISTofTEXTITEM16(items);
3678 v8 = FIELD8(string_length);
3684 STRING8(string, v8);
3689 v8 = FIELD8(string_length);
3695 STRING16(string16, v8);
3699 case X_CreateColormap:
3707 case X_FreeColormap:
3713 case X_CopyColormapAndFree:
3720 case X_InstallColormap:
3726 case X_UninstallColormap:
3732 case X_ListInstalledColormaps:
3748 case X_AllocNamedColor:
3752 v16 = FIELD16(name_length);
3758 case X_AllocColorCells:
3766 case X_AllocColorPlanes:
3778 v16 = REQUEST_LENGTH();
3781 LISTofCARD32(pixels, v16 - 12);
3786 v16 = REQUEST_LENGTH();
3788 LISTofCOLORITEM(color_items, v16 - 8);
3791 case X_StoreNamedColor:
3796 v16 = FIELD16(name_length);
3804 v16 = REQUEST_LENGTH();
3806 LISTofCARD32(pixels, v16 - 8);
3813 v16 = FIELD16(name_length);
3819 case X_CreateCursor:
3823 PIXMAP(source_pixmap);
3835 case X_CreateGlyphCursor:
3841 CARD16(source_char);
3857 case X_RecolorCursor:
3869 case X_QueryBestSize:
3877 case X_QueryExtension:
3880 v16 = FIELD16(name_length);
3886 case X_ListExtensions:
3891 case X_ChangeKeyboardMapping:
3892 v8 = FIELD8(keycode_count);
3894 v8_2 = KEYCODE(first_keycode);
3895 v8_3 = FIELD8(keysyms_per_keycode);
3897 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3900 case X_GetKeyboardMapping:
3903 state->request.GetKeyboardMapping.first_keycode
3904 = KEYCODE(first_keycode);
3909 case X_ChangeKeyboardControl:
3912 BITMASK32(keyboard_value);
3913 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3914 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3915 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3916 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3917 BITFIELD(INT16, keyboard_value_mask, led);
3918 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3919 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3920 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3924 case X_GetKeyboardControl:
3934 case X_ChangePointerControl:
3937 INT16(acceleration_numerator);
3938 INT16(acceleration_denominator);
3940 BOOL(do_acceleration);
3944 case X_GetPointerControl:
3949 case X_SetScreenSaver:
3954 ENUM8(prefer_blanking);
3955 ENUM8(allow_exposures);
3959 case X_GetScreenSaver:
3965 ENUM8(change_host_mode);
3969 v16 = CARD16(address_length);
3970 if (v8 == FAMILY_INTERNET && v16 == 4) {
3973 * XXX - what about IPv6? Is that a family of
3974 * FAMILY_INTERNET (0) with a length of 16?
3976 LISTofIPADDRESS(ip_address, v16);
3978 LISTofCARD8(address, v16);
3986 case X_SetAccessControl:
3991 case X_SetCloseDownMode:
3992 ENUM8(close_down_mode);
4002 case X_RotateProperties:
4004 v16 = REQUEST_LENGTH();
4006 CARD16(property_number);
4008 LISTofATOM(properties, (v16 - 12));
4011 case X_ForceScreenSaver:
4012 ENUM8(screen_saver_mode);
4016 case X_SetPointerMapping:
4017 v8 = FIELD8(map_length);
4019 LISTofCARD8(map, v8);
4023 case X_GetPointerMapping:
4028 case X_SetModifierMapping:
4029 v8 = FIELD8(keycodes_per_modifier);
4031 LISTofKEYCODE(state->modifiermap, keycodes, v8);
4034 case X_GetModifierMapping:
4045 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4049 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4052 volatile int offset = 0;
4053 int length_remaining;
4054 volatile gboolean little_endian;
4059 volatile gboolean is_initial_creq;
4060 guint16 auth_proto_len, auth_data_len;
4061 const char *volatile sep = NULL;
4062 conversation_t *conversation;
4063 x11_conv_data_t *volatile state;
4067 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4069 * We use "tvb_ensure_length_remaining()" to make sure there
4070 * actually *is* data remaining.
4072 * This means we're guaranteed that "length_remaining" is
4075 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4078 * Can we do reassembly?
4080 if (x11_desegment && pinfo->can_desegment) {
4082 * Yes - is the X11 request header split across
4083 * segment boundaries?
4085 if (length_remaining < 4) {
4087 * Yes. Tell the TCP dissector where the data
4088 * for this message starts in the data it handed
4089 * us, and how many more bytes we need, and return.
4091 pinfo->desegment_offset = offset;
4092 pinfo->desegment_len = 4 - length_remaining;
4098 * Get the state for this conversation; create the conversation
4099 * if we don't have one, and create the state if we don't have
4102 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4103 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4104 if (conversation == NULL) {
4108 conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4109 &pinfo->dst, pinfo->ptype, pinfo->srcport,
4110 pinfo->destport, 0);
4114 * Is there state attached to this conversation?
4116 if ((state = conversation_get_proto_data(conversation, proto_x11))
4118 state = x11_stateinit(conversation);
4121 * Guess the byte order if we don't already know it.
4123 little_endian = guess_byte_ordering(tvb, pinfo, state);
4126 * Get the opcode and length of the putative X11 request.
4128 opcode = VALUE8(tvb, 0);
4129 plen = VALUE16(tvb, offset + 2);
4133 * This can't be 0, as it includes the header length.
4134 * A different choice of byte order wouldn't have
4138 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4140 t = proto_item_add_subtree(ti, ett_x11);
4141 proto_tree_add_text(t, tvb, offset, -1,
4142 "Bogus request length (0)");
4146 if (state->iconn_frame == pinfo->fd->num ||
4147 (g_hash_table_lookup(state->seqtable,
4148 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4149 (opcode == 'B' || opcode == 'l') &&
4150 (plen == 11 || plen == 2816))) {
4154 * we saw this on the first pass and this is
4158 * we haven't already seen any requests, the first
4159 * byte of the message is 'B' or 'l', and the 16-bit
4160 * integer 2 bytes into the data stream is either 11
4161 * or a byte-swapped 11.
4163 * This means it's probably an initial connection
4164 * request, not a message.
4166 * 'B' is decimal 66, which is the opcode for a
4167 * PolySegment request; unfortunately, 11 is a valid
4168 * length for a PolySegment request request, so we
4169 * might mis-identify that request. (Are there any
4170 * other checks we can do?)
4172 * 'l' is decimal 108, which is the opcode for a
4173 * GetScreenSaver request; the only valid length
4174 * for that request is 1.
4176 is_initial_creq = TRUE;
4179 * We now know the byte order. Override the guess.
4181 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4182 if (opcode == 'B') {
4186 state->byte_order = BYTE_ORDER_BE;
4187 little_endian = FALSE;
4192 state->byte_order = BYTE_ORDER_LE;
4193 little_endian = TRUE;
4198 * Can we do reassembly?
4200 if (x11_desegment && pinfo->can_desegment) {
4202 * Yes - is the fixed-length portion of the
4203 * initial connection header split across
4204 * segment boundaries?
4206 if (length_remaining < 10) {
4208 * Yes. Tell the TCP dissector where the
4209 * data for this message starts in the data
4210 * it handed us, and how many more bytes we
4213 pinfo->desegment_offset = offset;
4214 pinfo->desegment_len = 10 - length_remaining;
4220 * Get the lengths of the authorization protocol and
4221 * the authorization data.
4223 auth_proto_len = VALUE16(tvb, offset + 6);
4224 auth_data_len = VALUE16(tvb, offset + 8);
4225 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4226 ROUND_LENGTH(auth_data_len);
4229 * This is probably an ordinary request.
4231 is_initial_creq = FALSE;
4234 * The length of a request is in 4-byte words.
4240 * Can we do reassembly?
4242 if (x11_desegment && pinfo->can_desegment) {
4244 * Yes - is the X11 request split across segment
4247 if (length_remaining < plen) {
4249 * Yes. Tell the TCP dissector where the data
4250 * for this message starts in the data it handed
4251 * us, and how many more bytes we need, and return.
4253 pinfo->desegment_offset = offset;
4254 pinfo->desegment_len = plen - length_remaining;
4260 * Construct a tvbuff containing the amount of the payload
4261 * we have available. Make its reported length the
4262 * amount of data in the X11 request.
4264 * XXX - if reassembly isn't enabled. the subdissector
4265 * will throw a BoundsError exception, rather than a
4266 * ReportedBoundsError exception. We really want a tvbuff
4267 * where the length is "length", the reported length is "plen",
4268 * and the "if the snapshot length were infinite" length is the
4269 * minimum of the reported length of the tvbuff handed to us
4270 * and "plen", with a new type of exception thrown if the offset
4271 * is within the reported length but beyond that third length,
4272 * with that exception getting the "Unreassembled Packet" error.
4274 length = length_remaining;
4277 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4280 * Set the column appropriately.
4282 if (is_initial_creq) {
4283 if (check_col(pinfo->cinfo, COL_INFO))
4284 col_set_str(pinfo->cinfo, COL_INFO,
4285 "Initial connection request");
4289 * We haven't set the column yet; set it.
4291 if (check_col(pinfo->cinfo, COL_INFO))
4292 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4295 * Initialize the separator.
4302 * Dissect the X11 request.
4304 * Catch the ReportedBoundsError exception; if this
4305 * particular message happens to get a ReportedBoundsError
4306 * exception, that doesn't mean that we should stop
4307 * dissecting X11 requests within this frame or chunk of
4310 * If it gets a BoundsError, we can stop, as there's nothing
4311 * more to see, so we just re-throw it.
4314 if (is_initial_creq) {
4315 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4316 state, little_endian);
4318 dissect_x11_request(next_tvb, pinfo, tree, sep,
4319 state, little_endian);
4322 CATCH(BoundsError) {
4325 CATCH(ReportedBoundsError) {
4326 show_reported_bounds_error(tvb, pinfo, tree);
4331 * Skip the X11 message.
4339 static x11_conv_data_t *
4340 x11_stateinit(conversation_t *conversation)
4342 x11_conv_data_t *state;
4343 static x11_conv_data_t stateinit;
4346 state = se_alloc(sizeof (x11_conv_data_t));
4348 state->next = x11_conv_data_list;
4349 x11_conv_data_list = state;
4351 /* initialise opcodes */
4353 if (opcode_vals[i].strptr == NULL) break;
4354 state->opcode_vals[i].value = opcode_vals[i].value;
4355 state->opcode_vals[i].strptr = opcode_vals[i].strptr;
4358 while (i <= MAX_OPCODES) {
4359 state->opcode_vals[i].value = 0;
4360 state->opcode_vals[i].strptr = NULL;
4364 state->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4365 state->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4366 g_hash_table_insert(state->seqtable, (int *)0, (int *)NOTHING_SEEN);
4367 state->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4368 conversation_add_proto_data(conversation, proto_x11, state);
4374 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4376 /* Set up structures we will need to add the protocol subtree and manage it */
4377 volatile int offset, plen;
4378 tvbuff_t * volatile next_tvb;
4379 conversation_t *conversation;
4380 x11_conv_data_t *volatile state;
4381 gboolean little_endian;
4382 int length_remaining;
4383 const char *volatile sep = NULL;
4387 * Get the state for this conversation; create the conversation
4388 * if we don't have one, and create the state if we don't have
4391 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4392 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4393 if (conversation == NULL) {
4397 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4398 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4402 * Is there state attached to this conversation?
4404 if ((state = conversation_get_proto_data(conversation, proto_x11))
4407 * No - create a state structure and attach it.
4409 state = x11_stateinit(conversation);
4413 * Guess the byte order if we don't already know it.
4415 little_endian = guess_byte_ordering(tvb, pinfo, state);
4418 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4420 * We use "tvb_ensure_length_remaining()" to make sure there
4421 * actually *is* data remaining.
4423 * This means we're guaranteed that "length_remaining" is
4426 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4429 * Can we do reassembly?
4431 if (x11_desegment && pinfo->can_desegment) {
4433 * Yes - is the X11 reply header split across
4434 * segment boundaries?
4436 if (length_remaining < 8) {
4438 * Yes. Tell the TCP dissector where the data
4439 * for this message starts in the data it handed
4440 * us, and how many more bytes we need, and
4443 pinfo->desegment_offset = offset;
4444 pinfo->desegment_len = 8 - length_remaining;
4450 * Find out what kind of a reply it is.
4451 * There are four possible:
4452 * - reply to initial connection
4453 * - errorreply (a request generated an error)
4454 * - requestreply (reply to a request)
4455 * - event (some event occured)
4457 if (g_hash_table_lookup(state->seqtable,
4458 GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN
4459 || (state->iconn_reply == pinfo->fd->num)) {
4461 * Either the connection is in the "initial
4462 * connection" state, or this frame is known
4463 * to have the initial connection reply.
4464 * That means this is the initial connection
4467 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4469 HANDLE_REPLY(plen, length_remaining,
4470 "Initial connection reply",
4471 dissect_x11_initial_reply);
4474 * This isn't an initial connection reply
4475 * (XXX - unless we missed the initial
4476 * connection request). Look at the first
4477 * byte to determine what it is; errors
4478 * start with a byte of 0, replies start
4479 * with a byte of 1, events start with
4480 * a byte with of 2 or greater.
4482 switch (tvb_get_guint8(tvb, offset)) {
4486 HANDLE_REPLY(plen, length_remaining,
4487 "Error", dissect_x11_error);
4491 /* replylength is in units of four. */
4492 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4494 HANDLE_REPLY(plen, length_remaining,
4495 "Reply", dissect_x11_reply);
4501 HANDLE_REPLY(plen, length_remaining,
4502 "Event", dissect_x11_event);
4514 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4515 const char *volatile sep, x11_conv_data_t *volatile state,
4516 gboolean little_endian)
4518 int offset = 0, *offsetp = &offset, length, left, opcode;
4519 int major_opcode, sequence_number;
4520 value_string *vals_p;
4524 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4525 tvb_reported_length_remaining(tvb, offset),
4527 t = proto_item_add_subtree(ti, ett_x11);
4531 * XXX - this doesn't work correctly if either
4533 * 1) the request sequence number wraps in the lower 16
4536 * 2) we don't see the initial connection request and the
4537 * resynchronization of sequence number fails and thus
4538 * don't have the right sequence numbers
4540 * 3) we don't have all the packets in the capture and
4541 * get out of sequence.
4543 * We might, instead, want to assume that a reply is a reply to
4544 * the most recent not-already-replied-to request in the same
4545 * connection. That also might mismatch replies to requests if
4546 * packets are lost, but there's nothing you can do to fix that.
4549 sequence_number = VALUE16(tvb, offset + 2);
4550 opcode = GPOINTER_TO_INT(g_hash_table_lookup(state->seqtable,
4551 GINT_TO_POINTER(sequence_number)));
4553 if (state->iconn_frame == 0 && state->resync == FALSE) {
4556 * We don't see the initial connection request and no
4557 * resynchronization has been performed yet (first reply),
4558 * set the current sequence number to the one of the
4559 * current reply (this is only performed once).
4561 state->sequencenumber = sequence_number;
4562 state->resync = TRUE;
4565 if (opcode == UNKNOWN_OPCODE) {
4566 if (check_col(pinfo->cinfo, COL_INFO))
4567 col_append_fstr(pinfo->cinfo, COL_INFO,
4568 "%s to unknown request", sep);
4569 proto_item_append_text(ti, ", Reply to unknown request");
4571 if (check_col(pinfo->cinfo, COL_INFO))
4572 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4574 val_to_str(opcode, state->opcode_vals,
4575 "<Unknown opcode %d>"));
4577 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4578 opcode, val_to_str(opcode,
4580 "<Unknown opcode %d>"));
4586 * Replies that need special processing outside tree
4589 case X_QueryExtension:
4592 * if extension is present and request is known:
4593 * store opcode of extension in value_string of
4596 if (!VALUE8(tvb, offset + 8)) {
4601 vals_p = g_hash_table_lookup(state->valtable,
4602 GINT_TO_POINTER(sequence_number));
4603 if (vals_p != NULL) {
4604 major_opcode = VALUE8(tvb, offset + 9);
4605 vals_p->value = major_opcode;
4606 g_hash_table_remove(state->valtable,
4607 GINT_TO_POINTER(sequence_number));
4620 * Requests that expect a reply.
4623 case X_GetWindowAttributes:
4624 REPLYCONTENTS_COMMON();
4630 SEQUENCENUMBER_REPLY(sequencenumber);
4631 REPLYLENGTH(replylength);
4637 CARD16(border_width);
4642 REPLYCONTENTS_COMMON();
4648 SEQUENCENUMBER_REPLY(sequencenumber);
4649 REPLYLENGTH(replylength);
4655 REPLYCONTENTS_COMMON();
4661 SEQUENCENUMBER_REPLY(sequencenumber);
4662 length = REPLYLENGTH(replylength);
4663 ATOM(get_property_type);
4664 CARD32(bytes_after);
4665 CARD32(valuelength);
4669 case X_ListProperties:
4672 SEQUENCENUMBER_REPLY(sequencenumber);
4673 REPLYLENGTH(replylength);
4674 length = CARD16(property_number);
4676 LISTofATOM(properties, length*4);
4679 case X_GetSelectionOwner:
4682 SEQUENCENUMBER_REPLY(sequencenumber);
4683 REPLYLENGTH(replylength);
4689 case X_GrabKeyboard:
4692 SEQUENCENUMBER_REPLY(sequencenumber);
4693 REPLYLENGTH(replylength);
4697 case X_QueryPointer:
4700 SEQUENCENUMBER_REPLY(sequencenumber);
4701 REPLYLENGTH(replylength);
4703 WINDOW(childwindow);
4708 SETofKEYBUTMASK(mask);
4712 case X_GetMotionEvents:
4713 REPLYCONTENTS_COMMON();
4716 case X_TranslateCoords:
4719 SEQUENCENUMBER_REPLY(sequencenumber);
4720 REPLYLENGTH(replylength);
4721 WINDOW(childwindow);
4727 case X_GetInputFocus:
4730 SEQUENCENUMBER_REPLY(sequencenumber);
4731 REPLYLENGTH(replylength);
4739 SEQUENCENUMBER_REPLY(sequencenumber);
4740 REPLYLENGTH(replylength);
4741 LISTofCARD8(keys, 32);
4745 case X_QueryTextExtents:
4748 case X_ListInstalledColormaps:
4749 REPLYCONTENTS_COMMON();
4755 SEQUENCENUMBER_REPLY(sequencenumber);
4756 REPLYLENGTH(replylength);
4766 REPLYCONTENTS_COMMON();
4772 SEQUENCENUMBER_REPLY(sequencenumber);
4773 REPLYLENGTH(replylength);
4775 CARD16(exact_green);
4778 CARD16(visual_green);
4779 CARD16(visual_blue);
4783 case X_QueryBestSize:
4786 SEQUENCENUMBER_REPLY(sequencenumber);
4787 REPLYLENGTH(replylength);
4793 case X_QueryExtension:
4796 SEQUENCENUMBER_REPLY(sequencenumber);
4797 REPLYLENGTH(replylength);
4799 CARD8(major_opcode);
4805 case X_ListExtensions:
4806 REPLYCONTENTS_COMMON();
4809 case X_GetKeyboardMapping:
4810 state->first_keycode =
4811 state->request.GetKeyboardMapping.first_keycode;
4813 state->keysyms_per_keycode =
4814 FIELD8(keysyms_per_keycode);
4815 SEQUENCENUMBER_REPLY(sequencenumber);
4816 length = REPLYLENGTH(replylength);
4818 LISTofKEYSYM(keysyms, state->keycodemap,
4819 state->request.GetKeyboardMapping.first_keycode,
4820 /* XXX - length / state->keysyms_per_keycode can raise a division by zero,
4821 * don't know if this is the *right* way to fix it ... */
4822 state->keysyms_per_keycode ? length / state->keysyms_per_keycode : 0,
4823 state->keysyms_per_keycode);
4826 case X_GetKeyboardControl:
4827 REPLYCONTENTS_COMMON();
4830 case X_GetPointerControl:
4833 SEQUENCENUMBER_REPLY(sequencenumber);
4834 REPLYLENGTH(replylength);
4835 CARD16(acceleration_numerator);
4836 CARD16(acceleration_denominator);
4841 case X_GetScreenSaver:
4844 SEQUENCENUMBER_REPLY(sequencenumber);
4845 REPLYLENGTH(replylength);
4848 ENUM8(prefer_blanking);
4849 ENUM8(allow_exposures);
4854 case X_SetPointerMapping:
4855 case X_GetPointerMapping:
4856 case X_SetModifierMapping:
4857 REPLYCONTENTS_COMMON();
4860 case X_GetModifierMapping:
4862 state->keycodes_per_modifier =
4863 FIELD8(keycodes_per_modifier);
4864 SEQUENCENUMBER_REPLY(sequencenumber);
4865 REPLYLENGTH(replylength);
4867 LISTofKEYCODE(state->modifiermap, keycodes,
4868 state->keycodes_per_modifier);
4872 REPLYCONTENTS_COMMON();
4875 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4880 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4883 guint32 bitmask_value;
4886 proto_tree *bitmask_tree;
4888 bitmask_value = VALUE8(tvb, *offsetp);
4889 bitmask_offset = *offsetp;
4892 ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4894 bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4895 FLAG(same_screen_focus, focus);
4896 FLAG(same_screen_focus, same_screen);
4902 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4903 const char *volatile sep, x11_conv_data_t *volatile state,
4904 gboolean little_endian)
4906 int offset = 0, *offsetp = &offset, left;
4907 unsigned char eventcode;
4911 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4912 t = proto_item_add_subtree(ti, ett_x11);
4914 eventcode = tvb_get_guint8(tvb, offset);
4916 if (check_col(pinfo->cinfo, COL_INFO))
4917 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4918 sep, val_to_str(eventcode, eventcode_vals,
4919 "<Unknown eventcode %u>"));
4921 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4923 "eventcode: %d (%s)",
4925 val_to_str(eventcode, eventcode_vals,
4926 "<Unknown eventcode %u>"));
4929 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4930 eventcode, val_to_str(eventcode, eventcode_vals,
4931 "<Unknown eventcode %u>"));
4936 switch (eventcode) {
4941 /* need to do some prefetching here ... */
4942 code = VALUE8(tvb, offset);
4943 mask = VALUE16(tvb, 28);
4945 KEYCODE_DECODED(keycode, code, mask);
4946 CARD16(event_sequencenumber);
4947 EVENTCONTENTS_COMMON();
4955 BUTTON(eventbutton);
4956 CARD16(event_sequencenumber);
4957 EVENTCONTENTS_COMMON();
4964 CARD16(event_sequencenumber);
4965 EVENTCONTENTS_COMMON();
4972 ENUM8(event_detail);
4973 CARD16(event_sequencenumber);
4974 EVENTCONTENTS_COMMON();
4976 same_screen_focus(tvb, offsetp, t);
4981 ENUM8(focus_detail);
4982 CARD16(event_sequencenumber);
4983 WINDOW(eventwindow);
4993 CARD16(event_sequencenumber);
4994 WINDOW(eventwindow);
5003 case GraphicsExpose:
5005 CARD16(event_sequencenumber);
5011 CARD16(minor_opcode);
5013 CARD8(major_opcode);
5019 CARD16(event_sequencenumber);
5021 CARD16(minor_opcode);
5022 CARD8(major_opcode);
5026 case VisibilityNotify:
5028 CARD16(event_sequencenumber);
5029 WINDOW(eventwindow);
5030 ENUM8(visibility_state);
5036 CARD16(event_sequencenumber);
5038 WINDOW(eventwindow);
5043 CARD16(border_width);
5044 BOOL(override_redirect);
5050 CARD16(event_sequencenumber);
5051 WINDOW(eventwindow);
5058 CARD16(event_sequencenumber);
5059 WINDOW(eventwindow);
5061 BOOL(from_configure);
5067 CARD16(event_sequencenumber);
5068 WINDOW(eventwindow);
5070 BOOL(override_redirect);
5076 CARD16(event_sequencenumber);
5078 WINDOW(eventwindow);
5082 case ReparentNotify:
5084 CARD16(event_sequencenumber);
5085 WINDOW(eventwindow);
5090 BOOL(override_redirect);
5094 case ConfigureNotify:
5096 CARD16(event_sequencenumber);
5097 WINDOW(eventwindow);
5099 WINDOW(above_sibling);
5104 CARD16(border_width);
5105 BOOL(override_redirect);
5109 case ConfigureRequest:
5114 CARD16(event_sequencenumber);
5115 WINDOW(eventwindow);
5124 CARD16(event_sequencenumber);
5125 WINDOW(eventwindow);
5131 case CirculateNotify:
5133 CARD16(event_sequencenumber);
5134 WINDOW(eventwindow);
5141 case CirculateRequest:
5143 CARD16(event_sequencenumber);
5145 WINDOW(eventwindow);
5151 case PropertyNotify:
5153 CARD16(event_sequencenumber);
5154 WINDOW(eventwindow);
5157 ENUM8(property_state);
5161 case SelectionClear:
5163 CARD16(event_sequencenumber);
5170 case SelectionRequest:
5172 CARD16(event_sequencenumber);
5182 case SelectionNotify:
5184 CARD16(event_sequencenumber);
5193 case ColormapNotify:
5195 CARD16(event_sequencenumber);
5196 WINDOW(eventwindow);
5199 ENUM8(colormap_state);
5205 CARD16(event_sequencenumber);
5206 WINDOW(eventwindow);
5208 LISTofBYTE(data, 20);
5216 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5223 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5224 const char *volatile sep, x11_conv_data_t *volatile state _U_,
5225 gboolean little_endian)
5227 int offset = 0, *offsetp = &offset, left;
5228 unsigned char errorcode, error;
5232 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5233 t = proto_item_add_subtree(ti, ett_x11);
5235 error = tvb_get_guint8(tvb, offset);
5238 errorcode = tvb_get_guint8(tvb, offset);
5239 if (check_col(pinfo->cinfo, COL_INFO))
5240 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5241 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5243 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5245 "errorcode: %d (%s)",
5247 val_to_str(errorcode, errorcode_vals,
5248 "<Unknown errocode %u>"));
5251 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
5252 errorcode, val_to_str(errorcode, errorcode_vals,
5253 "<Unknown errorcode %u>"));
5258 CARD16(error_sequencenumber);
5260 switch (errorcode) {
5262 CARD32(error_badvalue);
5269 CARD16(minor_opcode);
5270 CARD8(major_opcode);
5272 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5278 /************************************************************************
5280 *** I N I T I A L I Z A T I O N A N D M A I N ***
5282 ************************************************************************/
5285 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5287 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5288 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5290 if (pinfo->match_port == pinfo->srcport)
5291 dissect_x11_replies(tvb, pinfo, tree);
5293 dissect_x11_requests(tvb, pinfo, tree);
5296 /* Register the protocol with Wireshark */
5297 void proto_register_x11(void)
5300 /* Setup list of header fields */
5301 static hf_register_info hf[] = {
5302 #include "x11-register-info.h"
5305 /* Setup protocol subtree array */
5306 static gint *ett[] = {
5308 &ett_x11_color_flags,
5309 &ett_x11_list_of_arc,
5311 &ett_x11_list_of_atom,
5312 &ett_x11_list_of_card32,
5313 &ett_x11_list_of_color_item,
5314 &ett_x11_color_item,
5315 &ett_x11_list_of_keycode,
5316 &ett_x11_list_of_keysyms,
5318 &ett_x11_list_of_point,
5320 &ett_x11_list_of_rectangle,
5322 &ett_x11_list_of_segment,
5324 &ett_x11_list_of_string8,
5325 &ett_x11_list_of_text_item,
5327 &ett_x11_gc_value_mask,
5328 &ett_x11_event_mask,
5329 &ett_x11_do_not_propagate_mask,
5330 &ett_x11_set_of_key_mask,
5331 &ett_x11_pointer_event_mask,
5332 &ett_x11_window_value_mask,
5333 &ett_x11_configure_window_mask,
5334 &ett_x11_keyboard_value_mask,
5335 &ett_x11_same_screen_focus,
5337 module_t *x11_module;
5339 /* Register the protocol name and description */
5340 proto_x11 = proto_register_protocol("X11", "X11", "x11");
5342 /* Required function calls to register the header fields and subtrees used */
5343 proto_register_field_array(proto_x11, hf, array_length(hf));
5344 proto_register_subtree_array(ett, array_length(ett));
5346 register_init_routine(x11_init_protocol);
5348 x11_module = prefs_register_protocol(proto_x11, NULL);
5349 prefs_register_bool_preference(x11_module, "desegment",
5350 "Reassemble X11 messages spanning multiple TCP segments",
5351 "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
5352 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5357 proto_reg_handoff_x11(void)
5359 dissector_handle_t x11_handle;
5361 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5362 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5363 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5364 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
5365 data_handle = find_dissector("data");