2 * Routines for X11 dissection
3 * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4 * Copyright 2003, Michael Shuldman
6 * $Id: packet-x11.c,v 1.55 2004/02/25 23:12:49 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /* TODO (in no particular order):
31 * - keep track of Atom creation by server to be able to display
32 * non-predefined atoms
33 * - Idem for keysym <-> keycode ???
35 * - Subtree the request ids (that is x11.create-window.window and
36 * x11.change-window.window should be distinct), and add hidden fields
37 * (so we still have x11.window).
38 * - add hidden fields so we can have x11.circulate-window in addition to
39 * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
41 * - add hidden fields so we have x11.listOfStuff.length
42 * - use a faster scheme that linear list searching for the opcode.
43 * - correct display of Unicode chars.
44 * - Not everything is homogeneous, in particular the handling of items in
45 * list is a total mess.
48 /* By the way, I wrote a program to generate every request and test
49 * that stuff. If you're interested, you can get it at
50 * http://tronche.com/gui/x/
64 #include <epan/packet.h>
65 #include <epan/conversation.h>
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
71 #define cVALS(x) (const value_string*)(x)
74 * Data structure associated with a conversation; keeps track of the
75 * request for which we're expecting a reply, the frame number of
76 * the initial connection request, and the byte order of the connection.
78 * An opcode of -3 means we haven't yet seen any requests yet.
79 * An opcode of -2 means we're not expecting a reply.
80 * An opcode of -1 means means we're waiting for a reply to the initial
82 * Other values are the opcode of the request for which we're expecting
86 #define NOTHING_SEEN -3
87 #define NOTHING_EXPECTED -2
88 #define INITIAL_CONN -1
90 #define BYTE_ORDER_BE 0
91 #define BYTE_ORDER_LE 1
92 #define BYTE_ORDER_UNKNOWN -1
94 static const char *modifiers[] = {
105 /* Keymasks. From <X11/X.h>. */
106 #define ShiftMask (1<<0)
107 #define LockMask (1<<1)
108 #define ControlMask (1<<2)
109 #define Mod1Mask (1<<3)
110 #define Mod2Mask (1<<4)
111 #define Mod3Mask (1<<5)
112 #define Mod4Mask (1<<6)
113 #define Mod5Mask (1<<7)
115 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
116 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
119 #define NoSymbol 0L /* special KeySym */
122 GHashTable *seqtable; /* hashtable of sequncenumber <-> opcode. */
123 int sequencenumber; /* sequencenumber of current packet. */
124 guint32 iconn_frame; /* frame # of initial connection request */
125 guint32 iconn_reply; /* frame # of initial connection reply */
126 int byte_order; /* byte order of connection */
128 int *keycodemap[256]; /* keycode to keysymvalue map. */
129 int keysyms_per_keycode;
131 int *modifiermap[array_length(modifiers)];/* modifier to keycode. */
132 int keycodes_per_modifier;
137 } GetKeyboardMapping;
141 static GMemChunk *x11_state_chunk = NULL;
144 /* Initialize the protocol and registered fields */
145 static int proto_x11 = -1;
147 #include "x11-declarations.h"
149 /* Initialize the subtree pointers */
150 static gint ett_x11 = -1;
151 static gint ett_x11_color_flags = -1;
152 static gint ett_x11_list_of_arc = -1;
153 static gint ett_x11_arc = -1;
154 static gint ett_x11_list_of_atom = -1;
155 static gint ett_x11_list_of_card32 = -1;
156 static gint ett_x11_list_of_color_item = -1;
157 static gint ett_x11_color_item = -1;
158 static gint ett_x11_list_of_keycode = -1;
159 static gint ett_x11_list_of_keysyms = -1;
160 static gint ett_x11_keysym = -1;
161 static gint ett_x11_list_of_point = -1;
162 static gint ett_x11_point = -1;
163 static gint ett_x11_list_of_rectangle = -1;
164 static gint ett_x11_rectangle = -1;
165 static gint ett_x11_list_of_segment = -1;
166 static gint ett_x11_segment = -1;
167 static gint ett_x11_list_of_string8 = -1;
168 static gint ett_x11_list_of_text_item = -1;
169 static gint ett_x11_text_item = -1;
170 static gint ett_x11_gc_value_mask = -1;
171 static gint ett_x11_event_mask = -1;
172 static gint ett_x11_do_not_propagate_mask = -1;
173 static gint ett_x11_set_of_key_mask = -1;
174 static gint ett_x11_pointer_event_mask = -1;
175 static gint ett_x11_window_value_mask = -1;
176 static gint ett_x11_configure_window_mask = -1;
177 static gint ett_x11_keyboard_value_mask = -1;
179 /* desegmentation of X11 messages */
180 static gboolean x11_desegment = TRUE;
182 static dissector_handle_t data_handle;
184 #define TCP_PORT_X11 6000
185 #define TCP_PORT_X11_2 6001
186 #define TCP_PORT_X11_3 6002
189 * Round a length to a multiple of 4 bytes.
191 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
193 /************************************************************************
195 *** E N U M T A B L E S D E F I N I T I O N S ***
197 ************************************************************************/
199 static const value_string byte_order_vals[] = {
200 { 'B', "Big-endian" },
201 { 'l', "Little-endian" },
205 static const value_string image_byte_order_vals[] = {
211 static const value_string access_mode_vals[] = {
217 static const value_string all_temporary_vals[] = {
218 { 0, "AllTemporary" },
222 static const value_string alloc_vals[] = {
228 static const value_string allow_events_mode_vals[] = {
229 { 0, "AsyncPointer" },
230 { 1, "SyncPointer" },
231 { 2, "ReplayPointer" },
232 { 3, "AsyncKeyboard" },
233 { 4, "SyncKeyboard" },
234 { 5, "ReplayKeyboard" },
240 static const value_string arc_mode_vals[] = {
246 static const char *atom_predefined_interpretation[] = {
298 "UNDERLINE_POSITION",
299 "UNDERLINE_THICKNESS",
318 static const value_string auto_repeat_mode_vals[] = {
325 static const value_string background_pixmap_vals[] = {
327 { 1, "ParentRelative" },
331 static const value_string backing_store_vals[] = {
338 static const value_string border_pixmap_vals[] = {
339 { 0, "CopyFromParent" },
343 static const value_string button_vals[] = {
344 { 0x8000, "AnyButton" },
348 static const value_string cap_style_vals[] = {
356 static const value_string class_vals[] = {
363 static const value_string close_down_mode_vals[] = {
365 { 1, "RetainPermanent" },
366 { 2, "RetainTemporary" },
370 static const value_string coordinate_mode_vals[] = {
376 static const value_string direction_vals[] = {
377 { 0, "RaiseLowest" },
378 { 1, "LowerHighest" },
382 #define FAMILY_INTERNET 0
383 #define FAMILY_DECNET 1
384 #define FAMILY_CHAOS 2
386 static const value_string family_vals[] = {
387 { FAMILY_INTERNET, "Internet" },
388 { FAMILY_DECNET, "DECnet" },
389 { FAMILY_CHAOS, "Chaos" },
393 static const value_string fill_rule_vals[] = {
399 static const value_string fill_style_vals[] = {
403 { 3, "OpaqueStippled" },
407 static const value_string focus_vals[] = {
409 { 1, "PointerRoot" },
413 static const value_string function_vals[] = {
418 { 4, "AndInverted" },
426 { 12, "CopyInverted" },
427 { 13, "OrInverted" },
433 static const value_string gravity_vals[] = {
447 static const value_string image_format_vals[] = {
454 static const value_string image_pixmap_format_vals[] = {
460 static const value_string join_style_vals[] = {
467 static const value_string key_vals[] = {
472 #include "packet-x11-keysym.h"
474 static const value_string line_style_vals[] = {
481 static const value_string mode_vals[] = {
488 static const value_string on_off_vals[] = {
494 /* Requestcodes. From <X11/Xproto.h>. */
495 #define X_CreateWindow 1
496 #define X_ChangeWindowAttributes 2
497 #define X_GetWindowAttributes 3
498 #define X_DestroyWindow 4
499 #define X_DestroySubwindows 5
500 #define X_ChangeSaveSet 6
501 #define X_ReparentWindow 7
502 #define X_MapWindow 8
503 #define X_MapSubwindows 9
504 #define X_UnmapWindow 10
505 #define X_UnmapSubwindows 11
506 #define X_ConfigureWindow 12
507 #define X_CirculateWindow 13
508 #define X_GetGeometry 14
509 #define X_QueryTree 15
510 #define X_InternAtom 16
511 #define X_GetAtomName 17
512 #define X_ChangeProperty 18
513 #define X_DeleteProperty 19
514 #define X_GetProperty 20
515 #define X_ListProperties 21
516 #define X_SetSelectionOwner 22
517 #define X_GetSelectionOwner 23
518 #define X_ConvertSelection 24
519 #define X_SendEvent 25
520 #define X_GrabPointer 26
521 #define X_UngrabPointer 27
522 #define X_GrabButton 28
523 #define X_UngrabButton 29
524 #define X_ChangeActivePointerGrab 30
525 #define X_GrabKeyboard 31
526 #define X_UngrabKeyboard 32
528 #define X_UngrabKey 34
529 #define X_AllowEvents 35
530 #define X_GrabServer 36
531 #define X_UngrabServer 37
532 #define X_QueryPointer 38
533 #define X_GetMotionEvents 39
534 #define X_TranslateCoords 40
535 #define X_WarpPointer 41
536 #define X_SetInputFocus 42
537 #define X_GetInputFocus 43
538 #define X_QueryKeymap 44
539 #define X_OpenFont 45
540 #define X_CloseFont 46
541 #define X_QueryFont 47
542 #define X_QueryTextExtents 48
543 #define X_ListFonts 49
544 #define X_ListFontsWithInfo 50
545 #define X_SetFontPath 51
546 #define X_GetFontPath 52
547 #define X_CreatePixmap 53
548 #define X_FreePixmap 54
549 #define X_CreateGC 55
550 #define X_ChangeGC 56
552 #define X_SetDashes 58
553 #define X_SetClipRectangles 59
555 #define X_ClearArea 61
556 #define X_CopyArea 62
557 #define X_CopyPlane 63
558 #define X_PolyPoint 64
559 #define X_PolyLine 65
560 #define X_PolySegment 66
561 #define X_PolyRectangle 67
563 #define X_FillPoly 69
564 #define X_PolyFillRectangle 70
565 #define X_PolyFillArc 71
566 #define X_PutImage 72
567 #define X_GetImage 73
568 #define X_PolyText8 74
569 #define X_PolyText16 75
570 #define X_ImageText8 76
571 #define X_ImageText16 77
572 #define X_CreateColormap 78
573 #define X_FreeColormap 79
574 #define X_CopyColormapAndFree 80
575 #define X_InstallColormap 81
576 #define X_UninstallColormap 82
577 #define X_ListInstalledColormaps 83
578 #define X_AllocColor 84
579 #define X_AllocNamedColor 85
580 #define X_AllocColorCells 86
581 #define X_AllocColorPlanes 87
582 #define X_FreeColors 88
583 #define X_StoreColors 89
584 #define X_StoreNamedColor 90
585 #define X_QueryColors 91
586 #define X_LookupColor 92
587 #define X_CreateCursor 93
588 #define X_CreateGlyphCursor 94
589 #define X_FreeCursor 95
590 #define X_RecolorCursor 96
591 #define X_QueryBestSize 97
592 #define X_QueryExtension 98
593 #define X_ListExtensions 99
594 #define X_ChangeKeyboardMapping 100
595 #define X_GetKeyboardMapping 101
596 #define X_ChangeKeyboardControl 102
597 #define X_GetKeyboardControl 103
599 #define X_ChangePointerControl 105
600 #define X_GetPointerControl 106
601 #define X_SetScreenSaver 107
602 #define X_GetScreenSaver 108
603 #define X_ChangeHosts 109
604 #define X_ListHosts 110
605 #define X_SetAccessControl 111
606 #define X_SetCloseDownMode 112
607 #define X_KillClient 113
608 #define X_RotateProperties 114
609 #define X_ForceScreenSaver 115
610 #define X_SetPointerMapping 116
611 #define X_GetPointerMapping 117
612 #define X_SetModifierMapping 118
613 #define X_GetModifierMapping 119
614 #define X_NoOperation 127
616 static const value_string opcode_vals[] = {
617 { INITIAL_CONN, "Initial connection request" },
618 { X_CreateWindow, "CreateWindow" },
619 { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
620 { X_GetWindowAttributes, "GetWindowAttributes" },
621 { X_DestroyWindow, "DestroyWindow" },
622 { X_DestroySubwindows, "DestroySubwindows" },
623 { X_ChangeSaveSet, "ChangeSaveSet" },
624 { X_ReparentWindow, "ReparentWindow" },
625 { X_MapWindow, "MapWindow" },
626 { X_MapSubwindows, "MapSubwindows" },
627 { X_UnmapWindow, "UnmapWindow" },
628 { X_UnmapSubwindows, "UnmapSubwindows" },
629 { X_ConfigureWindow, "ConfigureWindow" },
630 { X_CirculateWindow, "CirculateWindow" },
631 { X_GetGeometry, "GetGeometry" },
632 { X_QueryTree, "QueryTree" },
633 { X_InternAtom, "InternAtom" },
634 { X_GetAtomName, "GetAtomName" },
635 { X_ChangeProperty, "ChangeProperty" },
636 { X_DeleteProperty, "DeleteProperty" },
637 { X_GetProperty, "GetProperty" },
638 { X_ListProperties, "ListProperties" },
639 { X_SetSelectionOwner, "SetSelectionOwner" },
640 { X_GetSelectionOwner, "GetSelectionOwner" },
641 { X_ConvertSelection, "ConvertSelection" },
642 /* { X_SendEvent, "SendEvent" }, */
643 { X_GrabPointer, "GrabPointer" },
644 { X_UngrabPointer, "UngrabPointer" },
645 { X_GrabButton, "GrabButton" },
646 { X_UngrabButton, "UngrabButton" },
647 { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
648 { X_GrabKeyboard, "GrabKeyboard" },
649 { X_UngrabKeyboard, "UngrabKeyboard" },
650 { X_GrabKey, "GrabKey" },
651 { X_UngrabKey, "UngrabKey" },
652 { X_AllowEvents, "AllowEvents" },
653 { X_GrabServer, "GrabServer" },
654 { X_UngrabServer, "UngrabServer" },
655 { X_QueryPointer, "QueryPointer" },
656 { X_GetMotionEvents, "GetMotionEvents" },
657 { X_TranslateCoords, "TranslateCoordinates" },
658 { X_WarpPointer, "WarpPointer" },
659 { X_SetInputFocus, "SetInputFocus" },
660 { X_GetInputFocus, "GetInputFocus" },
661 { X_QueryKeymap, "QueryKeymap" },
662 { X_OpenFont, "OpenFont" },
663 { X_CloseFont, "CloseFont" },
664 { X_QueryFont, "QueryFont" },
665 { X_QueryTextExtents, "QueryTextExtents" },
666 { X_ListFonts, "ListFonts" },
667 { X_ListFontsWithInfo, "ListFontsWithInfo" },
668 { X_SetFontPath, "SetFontPath" },
669 { X_GetFontPath, "GetFontPath" },
670 { X_CreatePixmap, "CreatePixmap" },
671 { X_FreePixmap, "FreePixmap" },
672 { X_CreateGC, "CreateGC" },
673 { X_ChangeGC, "ChangeGC" },
674 { X_CopyGC, "CopyGC" },
675 { X_SetDashes, "SetDashes" },
676 { X_SetClipRectangles, "SetClipRectangles" },
677 { X_FreeGC, "FreeGC" },
678 { X_ClearArea, "ClearArea" },
679 { X_CopyArea, "CopyArea" },
680 { X_CopyPlane, "CopyPlane" },
681 { X_PolyPoint, "PolyPoint" },
682 { X_PolyLine, "PolyLine" },
683 { X_PolySegment, "PolySegment" },
684 { X_PolyRectangle, "PolyRectangle" },
685 { X_PolyArc, "PolyArc" },
686 { X_FillPoly, "FillPoly" },
687 { X_PolyFillRectangle, "PolyFillRectangle" },
688 { X_PolyFillArc, "PolyFillArc" },
689 { X_PutImage, "PutImage" },
690 { X_GetImage, "GetImage" },
691 { X_PolyText8, "PolyText8" },
692 { X_PolyText16, "PolyText16" },
693 { X_ImageText8, "ImageText8" },
694 { X_ImageText16, "ImageText16" },
695 { X_CreateColormap, "CreateColormap" },
696 { X_FreeColormap, "FreeColormap" },
697 { X_CopyColormapAndFree, "CopyColormapAndFree" },
698 { X_InstallColormap, "InstallColormap" },
699 { X_UninstallColormap, "UninstallColormap" },
700 { X_ListInstalledColormaps, "ListInstalledColormaps" },
701 { X_AllocColor, "AllocColor" },
702 { X_AllocNamedColor, "AllocNamedColor" },
703 { X_AllocColorCells, "AllocColorCells" },
704 { X_AllocColorPlanes, "AllocColorPlanes" },
705 { X_FreeColors, "FreeColors" },
706 { X_StoreColors, "StoreColors" },
707 { X_StoreNamedColor, "StoreNamedColor" },
708 { X_QueryColors, "QueryColors" },
709 { X_LookupColor, "LookupColor" },
710 { X_CreateCursor, "CreateCursor" },
711 { X_CreateGlyphCursor, "CreateGlyphCursor" },
712 { X_FreeCursor, "FreeCursor" },
713 { X_RecolorCursor, "RecolorCursor" },
714 { X_QueryBestSize, "QueryBestSize" },
715 { X_QueryExtension, "QueryExtension" },
716 { X_ListExtensions, "ListExtensions" },
717 { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
718 { X_GetKeyboardMapping, "GetKeyboardMapping" },
719 { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
720 { X_GetKeyboardControl, "GetKeyboardControl" },
722 { X_ChangePointerControl, "ChangePointerControl" },
723 { X_GetPointerControl, "GetPointerControl" },
724 { X_SetScreenSaver, "SetScreenSaver" },
725 { X_GetScreenSaver, "GetScreenSaver" },
726 { X_ChangeHosts, "ChangeHosts" },
727 { X_ListHosts, "ListHosts" },
728 { X_SetAccessControl, "SetAccessControl" },
729 { X_SetCloseDownMode, "SetCloseDownMode" },
730 { X_KillClient, "KillClient" },
731 { X_RotateProperties, "RotateProperties" },
732 { X_ForceScreenSaver, "ForceScreenSaver" },
733 { X_SetPointerMapping, "SetPointerMapping" },
734 { X_GetPointerMapping, "GetPointerMapping" },
735 { X_SetModifierMapping, "SetModifierMapping" },
736 { X_GetModifierMapping, "GetModifierMapping" },
737 { X_NoOperation, "NoOperation" },
741 /* Eventscodes. From <X11/X.h>. */
744 #define ButtonPress 4
745 #define ButtonRelease 5
746 #define MotionNotify 6
747 #define EnterNotify 7
748 #define LeaveNotify 8
751 #define KeymapNotify 11
753 #define GraphicsExpose 13
755 #define VisibilityNotify 15
756 #define CreateNotify 16
757 #define DestroyNotify 17
758 #define UnmapNotify 18
760 #define MapRequest 20
761 #define ReparentNotify 21
762 #define ConfigureNotify 22
763 #define ConfigureRequest 23
764 #define GravityNotify 24
765 #define ResizeRequest 25
766 #define CirculateNotify 26
767 #define CirculateRequest 27
768 #define PropertyNotify 28
769 #define SelectionClear 29
770 #define SelectionRequest 30
771 #define SelectionNotify 31
772 #define ColormapNotify 32
773 #define ClientMessage 33
774 #define MappingNotify 34
776 static const value_string eventcode_vals[] = {
777 { KeyPress, "KeyPress" },
778 { KeyRelease, "KeyRelease" },
779 { ButtonPress, "ButtonPress" },
780 { ButtonRelease, "ButtonRelease" },
781 { MotionNotify, "MotionNotify" },
782 { EnterNotify, "EnterNotify" },
783 { LeaveNotify, "LeaveNotify" },
784 { FocusIn, "FocusIn" },
785 { FocusOut, "FocusOut" },
786 { KeymapNotify, "KeymapNotify" },
787 { Expose, "Expose" },
788 { GraphicsExpose, "GraphicsExpose" },
789 { NoExpose, "NoExpose" },
790 { VisibilityNotify, "VisibilityNotify" },
791 { CreateNotify, "CreateNotify" },
792 { DestroyNotify, "DestroyNotify" },
793 { UnmapNotify, "UnmapNotify" },
794 { MapNotify, "MapNotify" },
795 { MapRequest, "MapRequest" },
796 { ReparentNotify, "ReparentNotify" },
797 { ConfigureNotify, "ConfigureNotify" },
798 { ConfigureRequest, "ConfigureRequest" },
799 { GravityNotify, "GravityNotify" },
800 { ResizeRequest, "ResizeRequest" },
801 { CirculateNotify, "CirculateNotify" },
802 { CirculateRequest, "CirculateRequest" },
803 { PropertyNotify, "PropertyNotify" },
804 { SelectionClear, "SelectionClear" },
805 { SelectionRequest, "SelectionRequest" },
806 { SelectionNotify, "SelectionNotify" },
807 { ColormapNotify, "ColormapNotify" },
808 { ClientMessage, "ClientMessage" },
809 { MappingNotify, "MappingNotify" },
813 /* Errorcodes. From <X11/X.h> */
814 #define Success 0 /* everything's okay */
815 #define BadRequest 1 /* bad request code */
816 #define BadValue 2 /* int parameter out of range */
817 #define BadWindow 3 /* parameter not a Window */
818 #define BadPixmap 4 /* parameter not a Pixmap */
819 #define BadAtom 5 /* parameter not an Atom */
820 #define BadCursor 6 /* parameter not a Cursor */
821 #define BadFont 7 /* parameter not a Font */
822 #define BadMatch 8 /* parameter mismatch */
823 #define BadDrawable 9 /* parameter not a Pixmap or Window */
824 #define BadAccess 10 /* depending on context:
825 - key/button already grabbed
826 - attempt to free an illegal
828 - attempt to store into a read-only
830 - attempt to modify the access control
831 list from other than the local host.
833 #define BadAlloc 11 /* insufficient resources */
834 #define BadColor 12 /* no such colormap */
835 #define BadGC 13 /* parameter not a GC */
836 #define BadIDChoice 14 /* choice not in range or already used */
837 #define BadName 15 /* font or color name doesn't exist */
838 #define BadLength 16 /* Request length incorrect */
839 #define BadImplementation 17 /* server is defective */
841 #define FirstExtensionError 128
842 #define LastExtensionError 255
844 static const value_string errorcode_vals[] = {
845 { Success, "Success" },
846 { BadRequest, "BadRequest" },
847 { BadValue, "BadValue" },
848 { BadWindow, "BadWindow" },
849 { BadPixmap, "BadPixmap" },
850 { BadAtom, "BadAtom" },
851 { BadCursor, "BadCursor" },
852 { BadFont, "BadFont" },
853 { BadMatch, "BadMatch" },
854 { BadDrawable, "BadDrawable" },
855 { BadAccess, "BadAccess" },
856 { BadAlloc, "BadAlloc" },
857 { BadColor, "BadColor" },
859 { BadIDChoice, "BadIDChoice" },
860 { BadName, "BadName" },
861 { BadLength, "BadLength" },
862 { BadImplementation, "BadImplementation" },
863 { FirstExtensionError, "FirstExtensionError" },
864 { LastExtensionError, "LastExtensionError" },
868 static const value_string ordering_vals[] = {
876 static const value_string plane_mask_vals[] = {
877 { 0xFFFFFFFF, "AllPlanes" },
881 static const value_string pointer_keyboard_mode_vals[] = {
882 { 0, "Synchronous" },
883 { 1, "Asynchronous" },
887 static const value_string revert_to_vals[] = {
889 { 1, "PointerRoot" },
894 static const value_string insert_delete_vals[] = {
900 static const value_string screen_saver_mode_vals[] = {
906 static const value_string shape_vals[] = {
913 static const value_string stack_mode_vals[] = {
922 static const value_string subwindow_mode_vals[] = {
923 { 0, "ClipByChildren" },
924 { 1, "IncludeInferiors" },
928 static const value_string window_class_vals[] = {
929 { 0, "CopyFromParent" },
930 { 1, "InputOutput" },
935 static const value_string yes_no_default_vals[] = {
942 static const value_string zero_is_any_property_type_vals[] = {
943 { 0, "AnyPropertyType" },
947 static const value_string zero_is_none_vals[] = {
952 /* we have not seen packet before. */
953 #define PACKET_IS_NEW(pinfo) \
954 (!((pinfo)->fd->flags.visited))
956 /************************************************************************
958 *** F I E L D D E C O D I N G M A C R O S ***
960 ************************************************************************/
962 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
963 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
964 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
966 #define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
967 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
968 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
970 #define BITFIELD(TYPE, position, name) {\
972 int save = *offsetp;\
973 proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
974 bitmask_size, little_endian); \
975 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
977 unused = save + 4 - *offsetp;\
979 proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
980 *offsetp = save + 4;\
984 #define FLAG(position, name) {\
985 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
987 #define FLAG_IF_NONZERO(position, name) do {\
988 if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
989 proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
991 #define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
992 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
993 #define BITMASK(name, size) {\
995 guint32 bitmask_value; \
996 int bitmask_offset; \
998 proto_tree *bitmask_tree; \
999 bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
1000 ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
1001 (guint32)VALUE32(tvb, *offsetp))); \
1002 bitmask_offset = *offsetp; \
1003 bitmask_size = size; \
1004 ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
1005 bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
1007 #define ENDBITMASK }
1008 #define BITMASK8(name) BITMASK(name, 1);
1009 #define BITMASK16(name) BITMASK(name, 2);
1010 #define BITMASK32(name) BITMASK(name, 4);
1011 #define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
1012 #define BUTTON(name) FIELD8(name)
1013 #define CARD8(name) FIELD8(name)
1014 #define CARD16(name) (FIELD16(name))
1015 #define CARD32(name) (FIELD32(name))
1016 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1017 #define COLORMAP(name) FIELD32(name)
1018 #define CURSOR(name) FIELD32(name)
1019 #define DRAWABLE(name) FIELD32(name)
1020 #define ENUM8(name) (FIELD8(name))
1021 #define ENUM16(name) (FIELD16(name))
1022 #define FONT(name) FIELD32(name)
1023 #define FONTABLE(name) FIELD32(name)
1024 #define GCONTEXT(name) FIELD32(name)
1025 #define INT8(name) FIELD8(name)
1026 #define INT16(name) FIELD16(name)
1027 #define INT32(name) FIELD32(name)
1028 #define KEYCODE(name) FIELD8(name)
1029 #define KEYCODE_DECODED(name, keycode, mask) do { \
1030 proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
1031 keycode, "keycode: %d (%s)", \
1032 keycode, keycode2keysymString(state->keycodemap, \
1033 state->first_keycode, state->keysyms_per_keycode, \
1034 state->modifiermap, state->keycodes_per_modifier, \
1039 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
1040 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1041 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1042 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1043 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1044 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1045 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1046 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1047 keysyms_per_keycode) {\
1048 listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1049 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1050 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1051 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1052 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1053 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1054 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1055 #define OPCODE() { opcode = FIELD8(opcode); }
1056 #define PIXMAP(name) { FIELD32(name); }
1057 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1058 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1059 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1060 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1061 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1062 #define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
1063 #define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1064 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1065 #define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
1066 #define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
1067 #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; }
1068 #define WINDOW(name) { FIELD32(name); }
1069 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1071 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1072 proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1073 v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1074 #define REPLY(name) FIELD8(name);
1075 #define REPLYLENGTH(name) FIELD32(name);
1077 #define EVENTCONTENTS_COMMON() do { \
1079 WINDOW(rootwindow); \
1080 WINDOW(eventwindow); \
1081 WINDOW(childwindow); \
1086 setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
1089 #define SEQUENCENUMBER_REPLY(name) do { \
1092 seqno = VALUE16(tvb, *offsetp); \
1093 proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
1094 *offsetp, sizeof(seqno), seqno, \
1095 "sequencenumber: %d (%s)", \
1097 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>")); \
1098 *offsetp += sizeof(seqno); \
1101 #define REPLYCONTENTS_COMMON() do { \
1103 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1104 1, little_endian); \
1106 SEQUENCENUMBER_REPLY(sequencenumber); \
1107 REPLYLENGTH(replylength); \
1108 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
1109 tvb_reported_length_remaining(tvb, offset), little_endian); \
1110 offset += tvb_reported_length_remaining(tvb, offset); \
1114 #define HANDLE_REPLY(plen, length_remaining, str, func) do { \
1115 if (length_remaining < plen) { \
1116 if (x11_desegment && pinfo->can_desegment) { \
1117 pinfo->desegment_offset = offset; \
1118 pinfo->desegment_len = plen - length_remaining;\
1121 ; /* XXX yes, what then? Need to skip/join. */ \
1124 if (length_remaining > plen) \
1125 length_remaining = plen; \
1126 next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1128 if (sep == NULL) { \
1129 if (check_col(pinfo->cinfo, COL_INFO)) \
1130 col_add_str(pinfo->cinfo, COL_INFO, str); \
1135 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1138 CATCH(BoundsError) { \
1141 CATCH(ReportedBoundsError) { \
1142 show_reported_bounds_error(next_tvb, pinfo, tree); \
1150 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1151 const char *sep, x11_conv_data_t *volatile state,
1152 gboolean little_endian);
1155 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1156 const char *volatile sep, x11_conv_data_t *volatile state,
1157 gboolean little_endian);
1160 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1161 const char *volatile sep, x11_conv_data_t *volatile state,
1162 gboolean little_endian);
1165 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1166 const char *volatile sep, x11_conv_data_t *volatile state,
1167 gboolean little_endian);
1170 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation);
1173 keysymString(guint32 v);
1176 /************************************************************************
1178 *** D E C O D I N G F I E L D S ***
1180 ************************************************************************/
1182 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1183 gboolean little_endian)
1185 const char *interpretation = NULL;
1187 guint32 v = VALUE32(tvb, *offsetp);
1188 if (v >= 1 && v < array_length(atom_predefined_interpretation))
1189 interpretation = atom_predefined_interpretation[v];
1191 interpretation = "Not a predefined atom";
1193 header_field_info *hfi = proto_registrar_get_nth(hf);
1195 interpretation = match_strval(v, cVALS(hfi -> strings));
1197 if (!interpretation) interpretation = "error in Xlib client program ?";
1198 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1199 proto_registrar_get_nth(hf) -> name, v, interpretation);
1203 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1205 guint32 v = VALUE8(tvb, *offsetp);
1206 proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1211 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1213 unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1217 if (do_red_green_blue) {
1220 char *bp = buffer + sprintf(buffer, "flags: ");
1222 if (do_red_green_blue & 0x1) {
1223 bp += sprintf(bp, "DoRed");
1227 if (do_red_green_blue & 0x2) {
1228 if (sep) bp += sprintf(bp, " | ");
1229 bp += sprintf(bp, "DoGreen");
1233 if (do_red_green_blue & 0x4) {
1234 if (sep) bp += sprintf(bp, " | ");
1235 bp += sprintf(bp, "DoBlue");
1239 if (do_red_green_blue & 0xf8) {
1240 if (sep) bp += sprintf(bp, " + ");
1241 sprintf(bp, "trash");
1244 ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1246 tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1247 if (do_red_green_blue & 0x1)
1248 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1249 do_red_green_blue & 0x1);
1250 if (do_red_green_blue & 0x2)
1251 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1252 do_red_green_blue & 0x2);
1253 if (do_red_green_blue & 0x4)
1254 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1255 do_red_green_blue & 0x4);
1256 if (do_red_green_blue & 0xf8)
1257 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1258 do_red_green_blue & 0xf8);
1260 proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1265 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1266 int hf, const char *nullInterpretation)
1268 guint8 v = VALUE8(tvb, *offsetp);
1271 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1272 proto_registrar_get_nth(hf) -> name,
1273 nullInterpretation);
1275 proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1279 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1280 int length, gboolean little_endian)
1282 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1283 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1285 gint16 x = VALUE16(tvb, *offsetp);
1286 gint16 y = VALUE16(tvb, *offsetp + 2);
1287 guint16 width = VALUE16(tvb, *offsetp + 4);
1288 guint16 height = VALUE16(tvb, *offsetp + 6);
1289 gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1290 gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1292 proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1293 "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1294 width, height, x, y, angle1, angle2,
1295 angle1 / 64.0, angle2 / 64.0);
1296 proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1297 proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1299 proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1301 proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1303 proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1305 proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1307 proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1312 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1313 int length, gboolean little_endian)
1315 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1316 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1318 atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1321 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1322 int length, gboolean little_endian)
1324 if (length <= 0) length = 1;
1325 proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1329 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1330 int hf_item, int length, gboolean little_endian)
1332 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1333 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1335 proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1340 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1341 int length, gboolean little_endian)
1343 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1344 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1348 unsigned do_red_green_blue;
1349 guint16 red, green, blue;
1354 red = VALUE16(tvb, *offsetp + 4);
1355 green = VALUE16(tvb, *offsetp + 6);
1356 blue = VALUE16(tvb, *offsetp + 8);
1357 do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1359 bp = buffer + sprintf(buffer, "colorItem: ");
1361 if (do_red_green_blue & 0x1) {
1362 bp += sprintf(bp, "red = %d", red);
1365 if (do_red_green_blue & 0x2) {
1366 bp += sprintf(bp, "%sgreen = %d", sep, green);
1369 if (do_red_green_blue & 0x4)
1370 bp += sprintf(bp, "%sblue = %d", sep, blue);
1372 tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1373 ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1374 proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1376 proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1378 proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1380 proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1382 colorFlags(tvb, offsetp, ttt);
1383 proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1388 static GTree *keysymTable = NULL;
1390 static gint compareGuint32(gconstpointer a, gconstpointer b)
1392 return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1396 XConvertCase(register int sym, int *lower, int *upper)
1401 case 0: /* Latin 1 */
1402 if ((sym >= XK_A) && (sym <= XK_Z))
1403 *lower += (XK_a - XK_A);
1404 else if ((sym >= XK_a) && (sym <= XK_z))
1405 *upper -= (XK_a - XK_A);
1406 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1407 *lower += (XK_agrave - XK_Agrave);
1408 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1409 *upper -= (XK_agrave - XK_Agrave);
1410 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1411 *lower += (XK_oslash - XK_Ooblique);
1412 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1413 *upper -= (XK_oslash - XK_Ooblique);
1415 case 1: /* Latin 2 */
1416 /* Assume the KeySym is a legal value (ignore discontinuities) */
1417 if (sym == XK_Aogonek)
1418 *lower = XK_aogonek;
1419 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1420 *lower += (XK_lstroke - XK_Lstroke);
1421 else if (sym >= XK_Scaron && sym <= XK_Zacute)
1422 *lower += (XK_scaron - XK_Scaron);
1423 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1424 *lower += (XK_zcaron - XK_Zcaron);
1425 else if (sym == XK_aogonek)
1426 *upper = XK_Aogonek;
1427 else if (sym >= XK_lstroke && sym <= XK_sacute)
1428 *upper -= (XK_lstroke - XK_Lstroke);
1429 else if (sym >= XK_scaron && sym <= XK_zacute)
1430 *upper -= (XK_scaron - XK_Scaron);
1431 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1432 *upper -= (XK_zcaron - XK_Zcaron);
1433 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1434 *lower += (XK_racute - XK_Racute);
1435 else if (sym >= XK_racute && sym <= XK_tcedilla)
1436 *upper -= (XK_racute - XK_Racute);
1438 case 2: /* Latin 3 */
1439 /* Assume the KeySym is a legal value (ignore discontinuities) */
1440 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1441 *lower += (XK_hstroke - XK_Hstroke);
1442 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1443 *lower += (XK_gbreve - XK_Gbreve);
1444 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1445 *upper -= (XK_hstroke - XK_Hstroke);
1446 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1447 *upper -= (XK_gbreve - XK_Gbreve);
1448 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1449 *lower += (XK_cabovedot - XK_Cabovedot);
1450 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1451 *upper -= (XK_cabovedot - XK_Cabovedot);
1453 case 3: /* Latin 4 */
1454 /* Assume the KeySym is a legal value (ignore discontinuities) */
1455 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1456 *lower += (XK_rcedilla - XK_Rcedilla);
1457 else if (sym >= XK_rcedilla && sym <= XK_tslash)
1458 *upper -= (XK_rcedilla - XK_Rcedilla);
1459 else if (sym == XK_ENG)
1461 else if (sym == XK_eng)
1463 else if (sym >= XK_Amacron && sym <= XK_Umacron)
1464 *lower += (XK_amacron - XK_Amacron);
1465 else if (sym >= XK_amacron && sym <= XK_umacron)
1466 *upper -= (XK_amacron - XK_Amacron);
1468 case 6: /* Cyrillic */
1469 /* Assume the KeySym is a legal value (ignore discontinuities) */
1470 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1471 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1472 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1473 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1474 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1475 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1476 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1477 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1480 /* Assume the KeySym is a legal value (ignore discontinuities) */
1481 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1482 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1483 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1484 sym != XK_Greek_iotaaccentdieresis &&
1485 sym != XK_Greek_upsilonaccentdieresis)
1486 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1487 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1488 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1489 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1490 sym != XK_Greek_finalsmallsigma)
1491 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1497 keycode2keysymString(int *keycodemap[256], int first_keycode,
1498 int keysyms_per_keycode,
1499 int *modifiermap[array_length(modifiers)],
1500 int keycodes_per_modifier,
1501 guint32 keycode, guint32 bitmask)
1503 static char buf[32];
1505 int groupmodkc, numlockkc, numlockmod, groupmod;
1506 int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1507 int lockmod_is_nosymbol = 1;
1508 int modifier, kc, keysym;
1510 if ((syms = keycodemap[keycode]) == NULL)
1513 for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1514 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym)
1515 switch (keycodemap[kc][keysym]) {
1525 lockmod_is_capslock = kc;
1529 lockmod_is_shiftlock = kc;
1535 * If we have not seen the modifiermap we don't know what the
1536 * keycode translates to, but we do know it's one of the keys
1537 * in syms (give or take a case-conversion), so we could in
1538 * theory list them all.
1540 if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1543 /* find out what the numlockmodifer and groupmodifier is. */
1544 for (modifier = 0, numlockmod = groupmod = -1;
1545 modifier < (int)array_length(modifiers) && numlockmod == -1;
1547 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1548 if (modifiermap[modifier][kc] == numlockkc)
1549 numlockmod = modifier;
1550 else if (modifiermap[modifier][kc] == groupmodkc)
1551 groupmod = modifier;
1554 * ... and what the lockmodifier is interpreted as.
1555 * (X11v4r6 ref, keyboard and pointers section.)
1557 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1558 if (modifiermap[1][kc] == lockmod_is_capslock) {
1559 lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1562 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1563 lockmod_is_capslock = lockmod_is_nosymbol = 0;
1569 * This is (how I understand) the X11v4R6 protocol description given
1570 * in A. Nye's book. It is quite different from the
1571 * code in _XTranslateKey() in the file
1572 * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1573 * as shipped with XFree, and doesn't work correctly, nor do I see
1574 * how it could (e.g. the case of lower/uppercase-letters).
1575 * -- Michael Shuldman
1578 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1579 && ((keycodemap[keycode][1] >= 0xff80
1580 && keycodemap[keycode][1] <= 0xffbd)
1581 || (keycodemap[keycode][1] >= 0x11000000
1582 && keycodemap[keycode][1] <= 0x1100ffff))) {
1583 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1584 return keysymString(keycodemap[keycode][groupmod + 0]);
1586 if (keycodemap[keycode][groupmod + 1] == NoSymbol)
1587 return keysymString(keycodemap[keycode]
1590 return keysymString(keycodemap[keycode]
1593 else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1594 return keysymString(keycodemap[keycode][groupmod + 0]);
1595 else if (!(bitmask & ShiftMask)
1596 && ((bitmask & LockMask) && lockmod_is_capslock))
1597 if (islower(keycodemap[keycode][groupmod + 0]))
1598 /* return toupper(keysymString(keycodemap[keycode][groupmod + 0])); */
1599 return "Uppercase"; /* XXX */
1601 return keysymString(keycodemap[keycode][groupmod + 0]);
1603 else if ((bitmask & ShiftMask)
1604 && ((bitmask & LockMask) && lockmod_is_capslock))
1605 if (islower(keycodemap[keycode][groupmod + 1]))
1606 /* return toupper(keysymString(keycodemap[keycode][groupmod + 1])); */
1607 return "Uppercase"; /* XXX */
1609 return keysymString(keycodemap[keycode][groupmod + 1]);
1611 else if ((bitmask & ShiftMask)
1612 || ((bitmask & LockMask) && lockmod_is_shiftlock))
1613 return keysymString(keycodemap[keycode][groupmod + 1]);
1614 #else /* _XTranslateKey() based code. */
1616 while (keysyms_per_keycode > 2
1617 && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1618 --keysyms_per_keycode;
1619 if (keysyms_per_keycode > 2
1620 && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1622 keysyms_per_keycode -= 2;
1625 if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1626 && keysyms_per_keycode > 1 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1627 || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1628 if ((bitmask & ShiftMask)
1629 || (bitmask & LockMask && lockmod_is_shiftlock))
1634 else if (!(bitmask & ShiftMask)
1635 && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1636 if (keysyms_per_keycode == 1
1637 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1640 XConvertCase(syms[0], &keysym, &usym);
1645 else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1648 if (keysyms_per_keycode == 1
1649 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1650 XConvertCase(syms[0], &lsym, &usym);
1656 if (keysyms_per_keycode == 1
1657 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1660 XConvertCase(keysym, &lsym, &usym);
1662 if (!(bitmask & ShiftMask) && keysym != syms[0]
1663 && ((keysym != usym) || (lsym == usym)))
1664 XConvertCase(syms[0], &lsym, &usym);
1668 if (keysym == XK_VoidSymbol)
1671 sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1676 static const char *keysymString(guint32 v)
1681 /* This table is so big that we built it only if necessary */
1683 const value_string *p = keysym_vals_source;
1684 keysymTable = g_tree_new(compareGuint32);
1685 for(; p -> strptr; p++)
1686 g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
1688 res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1689 return res ? res : "<Unknown>";
1692 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1693 int *modifiermap[], int keycodes_per_modifier,
1694 gboolean little_endian)
1697 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1698 array_length(modifiers) * keycodes_per_modifier, little_endian);
1700 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1703 for (m = 0; m < array_length(modifiers);
1704 ++m, *offsetp += keycodes_per_modifier) {
1709 p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1710 modifiermap[m] = g_malloc(keycodes_per_modifier);
1712 for(i = 0; i < keycodes_per_modifier; ++i) {
1716 bp += sprintf(bp, " %s=%d", modifiers[m], c);
1718 modifiermap[m][i] = c;
1721 proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1722 *offsetp, keycodes_per_modifier, p,
1723 "item: %s", buffer);
1727 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1728 int hf_item, int *keycodemap[256],
1729 int keycode_first, int keycode_count,
1730 int keysyms_per_keycode, gboolean little_endian)
1732 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1733 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1738 g_assert(keycode_first >= 0);
1739 g_assert(keycode_count >= 0);
1740 g_assert((size_t)(keycode_first + keycode_count) <= 256);
1743 for (keycode = keycode_first; keycode_count > 0;
1744 ++keycode, --keycode_count) {
1745 tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1746 keysyms_per_keycode * 4, "keysyms (keycode %d):", keycode);
1748 ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1750 tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1752 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1754 for(i = 0; i < keysyms_per_keycode; ++i) {
1755 /* keysymvalue = byte3 * 256 + byte4. */
1756 guint32 v = VALUE32(tvb, *offsetp);
1758 proto_item_append_text(tti, " %s", keysymString(v));
1759 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1760 tvb, *offsetp, 4, v,
1761 "keysym (keycode %d): 0x%08x (%s)",
1762 keycode, v, keysymString(v));
1764 keycodemap[keycode][i] = v;
1768 for (i = 1; i < keysyms_per_keycode; ++i)
1769 if (keycodemap[keycode][i] != NoSymbol)
1772 if (i == keysyms_per_keycode) {
1773 /* all but (possibly) first were NoSymbol. */
1774 if (keysyms_per_keycode == 4) {
1775 keycodemap[keycode][1] = NoSymbol;
1776 keycodemap[keycode][2] = keycodemap[keycode][0];
1777 keycodemap[keycode][3] = NoSymbol;
1783 for (i = 2; i < keysyms_per_keycode; ++i)
1784 if (keycodemap[keycode][i] != NoSymbol)
1786 if (i == keysyms_per_keycode) {
1787 /* all but (possibly) first two were NoSymbol. */
1788 if (keysyms_per_keycode == 4) {
1789 keycodemap[keycode][2] = keycodemap[keycode][0];
1790 keycodemap[keycode][3] = keycodemap[keycode][1];
1798 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1799 int length, gboolean little_endian)
1801 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1802 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1808 x = VALUE16(tvb, *offsetp);
1809 y = VALUE16(tvb, *offsetp + 2);
1811 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1812 ttt = proto_item_add_subtree(tti, ett_x11_point);
1813 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1815 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1820 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1821 int length, gboolean little_endian)
1823 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1824 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1827 unsigned width, height;
1831 x = VALUE16(tvb, *offsetp);
1832 y = VALUE16(tvb, *offsetp + 2);
1833 width = VALUE16(tvb, *offsetp + 4);
1834 height = VALUE16(tvb, *offsetp + 6);
1836 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1837 "rectangle: %dx%d+%d+%d", width, height, x, y);
1838 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1839 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1841 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1843 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1845 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1850 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1851 int length, gboolean little_endian)
1853 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1854 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1856 gint16 x1, y1, x2, y2;
1860 x1 = VALUE16(tvb, *offsetp);
1861 y1 = VALUE16(tvb, *offsetp + 2);
1862 x2 = VALUE16(tvb, *offsetp + 4);
1863 y2 = VALUE16(tvb, *offsetp + 6);
1865 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1866 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1867 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1868 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1870 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1872 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1874 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1879 /* XXX - the protocol tree code should handle non-printable characters.
1880 Note that "non-printable characters" may depend on your locale.... */
1881 static void stringCopy(char *dest, const char *source, int length)
1886 if (!isgraph(c) && c != ' ') c = '.';
1892 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1893 int hf_item, int length, gboolean little_endian)
1896 guint allocated = 0;
1901 /* Compute total length */
1903 int scanning_offset = *offsetp; /* Scanning pointer */
1905 for(i = length; i; i--) {
1906 l = tvb_get_guint8(tvb, scanning_offset);
1907 scanning_offset += 1 + l;
1910 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1911 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1914 * In case we throw an exception, clean up whatever stuff we've
1915 * allocated (if any).
1917 CLEANUP_PUSH(g_free, s);
1920 unsigned l = VALUE8(tvb, *offsetp);
1921 if (allocated < (l + 1)) {
1922 /* g_realloc doesn't work ??? */
1924 s = g_malloc(l + 1);
1927 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1928 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1933 * Call the cleanup handler to free the string and pop the handler.
1935 CLEANUP_CALL_AND_POP;
1938 #define STRING16_MAX_DISPLAYED_LENGTH 150
1940 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1942 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1943 for(; length > 0; offset += 2, length--) {
1944 if (tvb_get_guint8(tvb, offset))
1950 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1952 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1953 int hf, int hf_bytes,
1954 int offset, unsigned length,
1955 char **s, int *sLength,
1956 gboolean little_endian)
1958 int truncated = FALSE;
1959 unsigned l = length / 2;
1961 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1963 int soffset = offset;
1965 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1967 l = STRING16_MAX_DISPLAYED_LENGTH;
1969 if (*sLength < (int) l + 3) {
1971 *s = g_malloc(l + 3);
1976 if (truncated) l -= 3;
1980 *dp++ = tvb_get_guint8(tvb, soffset);
1985 /* If truncated, add an ellipsis */
1986 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1989 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1990 proto_registrar_get_nth(hf) -> name, *s);
1992 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1996 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1997 int sizeIs16, int next_offset, gboolean little_endian)
2005 /* Compute total length */
2007 int scanning_offset = *offsetp; /* Scanning pointer */
2008 int l; /* Length of an individual item */
2009 int n = 0; /* Number of items */
2011 while(scanning_offset < next_offset) {
2012 l = tvb_get_guint8(tvb, scanning_offset);
2016 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2019 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2020 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2023 * In case we throw an exception, clean up whatever stuff we've
2024 * allocated (if any).
2026 CLEANUP_PUSH(g_free, s);
2029 unsigned l = VALUE8(tvb, *offsetp);
2030 if (l == 255) { /* Item is a font */
2031 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2032 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2034 } else { /* Item is a string */
2037 gint8 delta = VALUE8(tvb, *offsetp + 1);
2038 if (sizeIs16) l += l;
2039 if ((unsigned) allocated < l + 1) {
2040 /* g_realloc doesn't work ??? */
2042 s = g_malloc(l + 1);
2045 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2046 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2047 "textitem (string): delta = %d, \"%s\"",
2049 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2050 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2052 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2053 hf_x11_textitem_string_string16_bytes,
2058 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2059 *offsetp + 2, l, s, "\"%s\"", s);
2065 * Call the cleanup handler to free the string and pop the handler.
2067 CLEANUP_CALL_AND_POP;
2070 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2071 gboolean little_endian)
2073 guint32 v = VALUE8(tvb, *offsetp);
2074 header_field_info *hfi = proto_registrar_get_nth(hf);
2075 gchar *enumValue = NULL;
2078 enumValue = match_strval(v, cVALS(hfi -> strings));
2080 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2081 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2082 hfi -> name, v, enumValue);
2084 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2089 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2090 gboolean little_endian)
2092 guint32 v = VALUE16(tvb, *offsetp);
2093 header_field_info *hfi = proto_registrar_get_nth(hf);
2094 gchar *enumValue = NULL;
2097 enumValue = match_strval(v, cVALS(hfi -> strings));
2099 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2100 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2101 hfi -> name, v, enumValue);
2103 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2108 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2109 gboolean little_endian)
2111 guint32 v = VALUE32(tvb, *offsetp);
2112 header_field_info *hfi = proto_registrar_get_nth(hf);
2113 gchar *enumValue = NULL;
2114 gchar *nameAsChar = hfi -> name;
2117 enumValue = match_strval(v, cVALS(hfi -> strings));
2119 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2120 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2121 nameAsChar, v, enumValue);
2123 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2124 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2130 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2131 gboolean little_endian)
2133 BITMASK32(gc_value);
2134 BITFIELD(ENUM8, gc_value_mask, function);
2135 BITFIELD(CARD32, gc_value_mask, plane_mask);
2136 BITFIELD(CARD32, gc_value_mask, foreground);
2137 BITFIELD(CARD32, gc_value_mask, background);
2138 BITFIELD(CARD16, gc_value_mask, line_width);
2139 BITFIELD(ENUM8, gc_value_mask, line_style);
2140 BITFIELD(ENUM8, gc_value_mask, cap_style);
2141 BITFIELD(ENUM8, gc_value_mask, join_style);
2142 BITFIELD(ENUM8, gc_value_mask, fill_style);
2143 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2144 BITFIELD(PIXMAP, gc_value_mask, tile);
2145 BITFIELD(PIXMAP, gc_value_mask, stipple);
2146 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2147 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2148 BITFIELD(FONT, gc_value_mask, font);
2149 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2150 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2151 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2152 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2153 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2154 BITFIELD(CARD16, gc_value_mask, dash_offset);
2155 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2156 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2160 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2161 gboolean little_endian)
2163 BITMASK32(gc_value);
2164 FLAG(gc_value, function);
2165 FLAG(gc_value, plane_mask);
2166 FLAG(gc_value, foreground);
2167 FLAG(gc_value, background);
2168 FLAG(gc_value, line_width);
2169 FLAG(gc_value, line_style);
2170 FLAG(gc_value, cap_style);
2171 FLAG(gc_value, join_style);
2172 FLAG(gc_value, fill_style);
2173 FLAG(gc_value, fill_rule);
2174 FLAG(gc_value, tile);
2175 FLAG(gc_value, stipple);
2176 FLAG(gc_value, tile_stipple_x_origin);
2177 FLAG(gc_value, tile_stipple_y_origin);
2178 FLAG(gc_value, font);
2179 FLAG(gc_value, subwindow_mode);
2180 FLAG(gc_value, graphics_exposures);
2181 FLAG(gc_value, clip_x_origin);
2182 FLAG(gc_value, clip_y_origin);
2183 FLAG(gc_value, clip_mask);
2184 FLAG(gc_value, dash_offset);
2185 FLAG(gc_value, gc_dashes);
2186 FLAG(gc_value, arc_mode);
2190 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2191 gboolean little_endian)
2193 guint32 res = VALUE16(tvb, *offsetp);
2194 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2199 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2200 gboolean little_endian)
2203 FLAG(event, KeyPress);
2204 FLAG(event, KeyRelease);
2205 FLAG(event, ButtonPress);
2206 FLAG(event, ButtonRelease);
2207 FLAG(event, EnterWindow);
2208 FLAG(event, LeaveWindow);
2209 FLAG(event, PointerMotion);
2210 FLAG(event, PointerMotionHint);
2211 FLAG(event, Button1Motion);
2212 FLAG(event, Button2Motion);
2213 FLAG(event, Button3Motion);
2214 FLAG(event, Button4Motion);
2215 FLAG(event, Button5Motion);
2216 FLAG(event, ButtonMotion);
2217 FLAG(event, KeymapState);
2218 FLAG(event, Exposure);
2219 FLAG(event, VisibilityChange);
2220 FLAG(event, StructureNotify);
2221 FLAG(event, ResizeRedirect);
2222 FLAG(event, SubstructureNotify);
2223 FLAG(event, SubstructureRedirect);
2224 FLAG(event, FocusChange);
2225 FLAG(event, PropertyChange);
2226 FLAG(event, ColormapChange);
2227 FLAG(event, OwnerGrabButton);
2228 FLAG_IF_NONZERO(event, erroneous_bits);
2232 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2233 gboolean little_endian)
2235 BITMASK32(do_not_propagate);
2236 FLAG(do_not_propagate, KeyPress);
2237 FLAG(do_not_propagate, KeyRelease);
2238 FLAG(do_not_propagate, ButtonPress);
2239 FLAG(do_not_propagate, ButtonRelease);
2240 FLAG(do_not_propagate, PointerMotion);
2241 FLAG(do_not_propagate, Button1Motion);
2242 FLAG(do_not_propagate, Button2Motion);
2243 FLAG(do_not_propagate, Button3Motion);
2244 FLAG(do_not_propagate, Button4Motion);
2245 FLAG(do_not_propagate, Button5Motion);
2246 FLAG(do_not_propagate, ButtonMotion);
2247 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2252 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2253 gboolean little_endian, gboolean butmask)
2256 guint32 bitmask_value;
2259 proto_tree *bitmask_tree;
2261 bitmask_value = VALUE16(tvb, *offsetp);
2262 bitmask_offset = *offsetp;
2265 if (!butmask && bitmask_value == 0x8000)
2266 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2267 "modifiers-masks: 0x8000 (AnyModifier)");
2269 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2271 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2272 FLAG(modifiers, Shift);
2273 FLAG(modifiers, Lock);
2274 FLAG(modifiers, Control);
2275 FLAG(modifiers, Mod1);
2276 FLAG(modifiers, Mod2);
2277 FLAG(modifiers, Mod3);
2278 FLAG(modifiers, Mod4);
2279 FLAG(modifiers, Mod5);
2282 FLAG(modifiers, Button1);
2283 FLAG(modifiers, Button2);
2284 FLAG(modifiers, Button3);
2285 FLAG(modifiers, Button4);
2286 FLAG(modifiers, Button5);
2290 FLAG_IF_NONZERO(keybut, erroneous_bits);
2292 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2298 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2299 gboolean little_endian)
2301 BITMASK16(pointer_event);
2302 FLAG(pointer_event, ButtonPress);
2303 FLAG(pointer_event, ButtonRelease);
2304 FLAG(pointer_event, EnterWindow);
2305 FLAG(pointer_event, LeaveWindow);
2306 FLAG(pointer_event, PointerMotion);
2307 FLAG(pointer_event, PointerMotionHint);
2308 FLAG(pointer_event, Button1Motion);
2309 FLAG(pointer_event, Button2Motion);
2310 FLAG(pointer_event, Button3Motion);
2311 FLAG(pointer_event, Button4Motion);
2312 FLAG(pointer_event, Button5Motion);
2313 FLAG(pointer_event, ButtonMotion);
2314 FLAG(pointer_event, KeymapState);
2315 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2319 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2320 int hf, unsigned length)
2325 p = tvb_get_ptr(tvb, *offsetp, length);
2326 s = g_malloc(length + 1);
2327 stringCopy(s, p, length);
2328 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2333 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2335 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2336 int hf_bytes, unsigned length, gboolean little_endian)
2342 * In case we throw an exception, clean up whatever stuff we've
2343 * allocated (if any).
2345 CLEANUP_PUSH(g_free, s);
2348 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2349 &s, &l, little_endian);
2352 * Call the cleanup handler to free the string and pop the handler.
2354 CLEANUP_CALL_AND_POP;
2359 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2360 gboolean little_endian)
2362 guint32 v = VALUE32(tvb, *offsetp);
2365 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2366 proto_registrar_get_nth(hf) -> name);
2368 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2372 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2373 gboolean little_endian)
2375 BITMASK32(window_value);
2376 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2377 BITFIELD(CARD32, window_value_mask, background_pixel);
2378 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2379 BITFIELD(CARD32, window_value_mask, border_pixel);
2380 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2381 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2382 BITFIELD(ENUM8, window_value_mask, backing_store);
2383 BITFIELD(CARD32, window_value_mask, backing_planes);
2384 BITFIELD(CARD32, window_value_mask, backing_pixel);
2385 BITFIELD(BOOL, window_value_mask, override_redirect);
2386 BITFIELD(BOOL, window_value_mask, save_under);
2387 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2388 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2389 BITFIELD(COLORMAP, window_value_mask, colormap);
2390 BITFIELD(CURSOR, window_value_mask, cursor);
2394 static void x11_init_protocol(void)
2396 if (x11_state_chunk != NULL)
2397 g_mem_chunk_destroy(x11_state_chunk);
2399 x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2400 sizeof (x11_conv_data_t),
2401 128 * sizeof (x11_conv_data_t),
2405 /************************************************************************
2407 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2409 ************************************************************************/
2411 /* If we can't guess, we return TRUE (that is little_endian), cause
2412 I'm developing on a Linux box :-). The (non-)guess isn't cached
2413 however, so we may have more luck next time. I'm quite conservative
2414 in my assertions, cause once it's cached, it's stay in cache, and
2415 we may be fooled up by a packet starting with the end of a request
2416 started in a previous packet...
2419 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2421 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2424 while(maskLength--) {
2425 int c = tvb_get_guint8(tvb, offset);
2427 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2432 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2434 if (listLength > length) return FALSE;
2435 while(listLength--) {
2437 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2438 l = tvb_get_guint8(tvb, offset);
2441 if (l > length) return FALSE;
2442 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2446 if (length > 3) return FALSE;
2450 static int rounded4(int n)
2452 int remainder = n % 4;
2454 if (remainder) res++;
2458 /* We assume the order to be consistent, until proven wrong. */
2460 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2462 switch(tvb_get_guint8(tvb, offset)) {
2463 case X_CreateWindow:
2464 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2466 case X_ChangeWindowAttributes:
2468 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2470 case X_GetWindowAttributes:
2471 case X_DestroyWindow:
2472 case X_DestroySubwindows:
2473 case X_ChangeSaveSet:
2475 case X_MapSubwindows:
2477 case X_UnmapSubwindows:
2478 case X_CirculateWindow:
2482 case X_ListProperties:
2483 case X_GetSelectionOwner:
2484 case X_UngrabPointer:
2485 case X_UngrabKeyboard:
2487 case X_QueryPointer:
2492 case X_FreeColormap:
2493 case X_InstallColormap:
2494 case X_UninstallColormap:
2495 case X_ListInstalledColormaps:
2497 case X_GetKeyboardMapping:
2501 case X_ReparentWindow:
2502 case X_SetSelectionOwner:
2503 case X_ChangeActivePointerGrab:
2504 case X_GrabKeyboard:
2506 case X_GetMotionEvents:
2507 case X_TranslateCoords:
2508 case X_CreatePixmap:
2511 case X_CreateColormap:
2513 case X_AllocColorPlanes:
2516 case X_ConfigureWindow:
2517 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2520 case X_QueryExtension:
2521 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2523 case X_ChangeProperty:
2525 int multiplier, type;
2526 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2527 type = tvb_get_guint8(tvb, 16);
2528 if (type != 8 && type != 16 && type != 32) return FALSE;
2529 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2530 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2531 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2534 case X_DeleteProperty:
2535 case X_UngrabButton:
2537 case X_SetInputFocus:
2538 case X_CopyColormapAndFree:
2539 case X_AllocColorCells:
2540 case X_QueryBestSize:
2541 case X_ChangePointerControl:
2542 case X_SetScreenSaver:
2546 case X_ConvertSelection:
2553 return length == 11;
2556 case X_UngrabServer:
2557 case X_GetInputFocus:
2560 case X_ListExtensions:
2561 case X_GetKeyboardControl:
2563 case X_GetPointerControl:
2564 case X_GetScreenSaver:
2566 case X_SetAccessControl:
2567 case X_SetCloseDownMode:
2568 case X_ForceScreenSaver:
2569 case X_GetPointerMapping:
2570 case X_GetModifierMapping:
2574 case X_AllocNamedColor:
2576 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2578 case X_QueryTextExtents:
2582 case X_ListFontsWithInfo:
2584 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2587 if (length < 2) return FALSE;
2588 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2589 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2592 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2595 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2597 case X_SetClipRectangles:
2599 case X_PolyRectangle:
2600 case X_PolyFillRectangle:
2601 return length >= 3 && (length - 3) % 2 == 0;
2607 case X_CreateCursor:
2608 case X_CreateGlyphCursor:
2618 return length >= 3 && (length - 3) % 3 == 0;
2628 case X_RecolorCursor:
2632 if (length < 4) return FALSE;
2633 return TRUE; /* We don't perform many controls on this one */
2636 if (length < 4) return FALSE;
2637 return TRUE; /* We don't perform many controls on this one */
2643 return length > 2 && (length - 2) % 3 == 0;
2645 case X_StoreNamedColor:
2646 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2651 case X_ChangeKeyboardMapping:
2652 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2654 case X_ChangeKeyboardControl:
2655 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2657 case X_RotateProperties:
2658 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2660 case X_SetPointerMapping:
2661 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2663 case X_SetModifierMapping:
2664 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2674 /* -1 means doesn't match, +1 means match, 0 means don't know */
2676 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2678 int offset, nextoffset;
2681 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2683 length = v16(tvb, offset + 2);
2684 if (!length) return -1;
2685 nextoffset = offset + length * 4;
2686 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2693 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2694 x11_conv_data_t *state)
2696 /* With X the client gives the byte ordering for the protocol,
2697 and the port on the server tells us we're speaking X. */
2699 int le, be, decision, decisionToCache;
2701 if (state->byte_order == BYTE_ORDER_BE)
2702 return FALSE; /* known to be big-endian */
2703 else if (state->byte_order == BYTE_ORDER_LE)
2704 return TRUE; /* known to be little-endian */
2706 if (pinfo->srcport == pinfo->match_port) {
2708 * This is a reply or event; we don't try to guess the
2709 * byte order on it for now.
2714 le = x_endian_match(tvb, tvb_get_letohs);
2715 be = x_endian_match(tvb, tvb_get_ntohs);
2717 /* remember that "decision" really means "little_endian". */
2719 /* We have no reason to believe it's little- rather than
2720 big-endian, so we guess the shortest length is the
2723 if (!tvb_bytes_exist(tvb, 0, 4))
2724 /* Not even a way to get the length. We're biased
2725 toward little endianness here (essentially the
2726 x86 world right now). Decoding won't go very far
2731 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2733 decision = le >= be;
2735 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2736 if (decisionToCache) {
2738 * Remember the decision.
2740 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2744 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2745 pinfo->fd -> num, le, be, decision, decisionToCache);
2750 /************************************************************************
2752 *** D E C O D I N G O N E P A C K E T ***
2754 ************************************************************************/
2757 * Decode an initial connection request.
2759 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2760 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2763 int *offsetp = &offset;
2766 guint16 auth_proto_name_length, auth_proto_data_length;
2769 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2770 proto_item_append_text(ti, ", Request, Initial connection request");
2771 t = proto_item_add_subtree(ti, ett_x11);
2775 CARD16(protocol_major_version);
2776 CARD16(protocol_minor_version);
2777 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2778 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2781 if (auth_proto_name_length != 0) {
2782 STRING8(authorization_protocol_name, auth_proto_name_length);
2783 offset = ROUND_LENGTH(offset);
2786 if (auth_proto_data_length != 0) {
2787 STRING8(authorization_protocol_data, auth_proto_data_length);
2788 offset = ROUND_LENGTH(offset);
2791 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2792 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2796 * This is the initial connection request...
2798 state->iconn_frame = pinfo->fd->num;
2801 * ...and we're expecting a reply to it.
2803 state->sequencenumber = 0;
2804 g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
2805 (int *)INITIAL_CONN);
2808 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2809 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2810 gboolean little_endian)
2812 int offset = 0, *offsetp = &offset, left;
2813 unsigned char success;
2814 int length_of_vendor;
2815 int length_of_reason;
2819 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2820 proto_item_append_text(ti, ", Reply, Initial connection reply");
2821 t = proto_item_add_subtree(ti, ett_x11);
2823 state->iconn_reply = pinfo->fd->num;
2824 success = INT8(success);
2827 length_of_reason = 0;
2830 length_of_reason = INT8(length_of_reason);
2833 INT16(protocol_major_version);
2834 INT16(protocol_minor_version);
2837 INT32(release_number);
2838 INT32(resource_id_base);
2839 INT32(resource_id_mask);
2840 INT32(motion_buffer_size);
2841 length_of_vendor = INT16(length_of_vendor);
2842 INT16(maximum_request_length);
2843 INT8(number_of_screens_in_roots);
2844 INT8(number_of_formats_in_pixmap_formats);
2845 INT8(image_byte_order);
2846 INT8(bitmap_format_bit_order);
2847 INT8(bitmap_format_scanline_unit);
2848 INT8(bitmap_format_scanline_pad);
2852 STRING8(vendor, length_of_vendor);
2854 STRING8(reason, length_of_reason);
2857 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2862 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2863 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2864 gboolean little_endian)
2867 int *offsetp = &offset;
2872 guint8 v8, v8_2, v8_3;
2877 length = VALUE16(tvb, 2) * 4;
2880 /* Bogus message length? */
2884 next_offset = offset + length;
2886 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2887 t = proto_item_add_subtree(ti, ett_x11);
2889 if (PACKET_IS_NEW(pinfo))
2890 ++state->sequencenumber;
2894 if (check_col(pinfo->cinfo, COL_INFO))
2895 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2896 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
2898 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2899 opcode, val_to_str(opcode, opcode_vals,
2900 "<Unknown opcode %d>"));
2903 * Does this request expect a reply?
2907 case X_AllocColorCells:
2908 case X_AllocColorPlanes:
2909 case X_AllocNamedColor:
2914 case X_GetInputFocus:
2915 case X_GetKeyboardControl:
2916 case X_GetKeyboardMapping:
2917 case X_GetModifierMapping:
2918 case X_GetMotionEvents:
2919 case X_GetPointerControl:
2920 case X_GetPointerMapping:
2922 case X_GetScreenSaver:
2923 case X_GetSelectionOwner:
2924 case X_GetWindowAttributes:
2925 case X_GrabKeyboard:
2928 case X_ListExtensions:
2930 case X_ListFontsWithInfo:
2932 case X_ListInstalledColormaps:
2933 case X_ListProperties:
2935 case X_QueryBestSize:
2937 case X_QueryExtension:
2940 case X_QueryPointer:
2941 case X_QueryTextExtents:
2943 case X_SetModifierMapping:
2944 case X_SetPointerMapping:
2945 case X_TranslateCoords:
2947 * Those requests expect a reply.
2950 g_hash_table_insert(state->seqtable,
2951 (int *)state->sequencenumber, (int *)opcode);
2957 * No reply is expected from any other request.
2967 case X_CreateWindow:
2976 CARD16(border_width);
2977 ENUM16(window_class);
2979 windowAttributes(tvb, offsetp, t, little_endian);
2982 case X_ChangeWindowAttributes:
2986 windowAttributes(tvb, offsetp, t, little_endian);
2989 case X_GetWindowAttributes:
2990 case X_DestroyWindow:
2991 case X_DestroySubwindows:
2997 case X_ChangeSaveSet:
2998 ENUM8(save_set_mode);
3003 case X_ReparentWindow:
3013 case X_MapSubwindows:
3015 case X_UnmapSubwindows:
3021 case X_ConfigureWindow:
3025 BITMASK16(configure_window);
3027 BITFIELD(INT16, configure_window_mask, x);
3028 BITFIELD(INT16, configure_window_mask, y);
3029 BITFIELD(CARD16, configure_window_mask, width);
3030 BITFIELD(CARD16, configure_window_mask, height);
3031 BITFIELD(CARD16, configure_window_mask, border_width);
3032 BITFIELD(WINDOW, configure_window_mask, sibling);
3033 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3038 case X_CirculateWindow:
3052 BOOL(only_if_exists);
3054 v16 = FIELD16(name_length);
3066 case X_ChangeProperty:
3074 v32 = CARD32(data_length);
3075 LISTofBYTE(data, v32);
3079 case X_DeleteProperty:
3091 ATOM(get_property_type);
3092 CARD32(long_offset);
3093 CARD32(long_length);
3096 case X_ListProperties:
3102 case X_SetSelectionOwner:
3110 case X_GetSelectionOwner:
3116 case X_ConvertSelection:
3129 WINDOW(grab_window);
3130 SETofPOINTEREVENT(pointer_event_mask);
3131 ENUM8(pointer_mode);
3132 ENUM8(keyboard_mode);
3138 case X_UngrabPointer:
3147 WINDOW(grab_window);
3148 SETofPOINTEREVENT(event_mask);
3149 ENUM8(pointer_mode);
3150 ENUM8(keyboard_mode);
3155 SETofKEYMASK(modifiers);
3158 case X_UngrabButton:
3161 WINDOW(grab_window);
3162 SETofKEYMASK(modifiers);
3166 case X_ChangeActivePointerGrab:
3171 SETofPOINTEREVENT(event_mask);
3175 case X_GrabKeyboard:
3178 WINDOW(grab_window);
3180 ENUM8(pointer_mode);
3181 ENUM8(keyboard_mode);
3185 case X_UngrabKeyboard:
3194 WINDOW(grab_window);
3195 SETofKEYMASK(modifiers);
3197 ENUM8(pointer_mode);
3198 ENUM8(keyboard_mode);
3205 WINDOW(grab_window);
3206 SETofKEYMASK(modifiers);
3211 ENUM8(allow_events_mode);
3221 case X_UngrabServer:
3226 case X_QueryPointer:
3232 case X_GetMotionEvents:
3240 case X_TranslateCoords:
3252 WINDOW(warp_pointer_src_window);
3253 WINDOW(warp_pointer_dst_window);
3262 case X_SetInputFocus:
3269 case X_GetInputFocus:
3283 v16 = FIELD16(name_length);
3301 case X_QueryTextExtents:
3302 v8 = BOOL(odd_length);
3305 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3313 v16 = FIELD16(pattern_length);
3314 STRING8(pattern, v16);
3318 case X_ListFontsWithInfo:
3322 v16 = FIELD16(pattern_length);
3323 STRING8(pattern, v16);
3330 v16 = CARD16(str_number_in_path);
3332 LISTofSTRING8(path, v16);
3341 case X_CreatePixmap:
3361 gcAttributes(tvb, offsetp, t, little_endian);
3368 gcAttributes(tvb, offsetp, t, little_endian);
3376 gcMask(tvb, offsetp, t, little_endian);
3383 CARD16(dash_offset);
3384 v16 = FIELD16(dashes_length);
3385 LISTofCARD8(dashes, v16);
3389 case X_SetClipRectangles:
3393 INT16(clip_x_origin);
3394 INT16(clip_y_origin);
3395 LISTofRECTANGLE(rectangles);
3417 DRAWABLE(src_drawable);
3418 DRAWABLE(dst_drawable);
3431 DRAWABLE(src_drawable);
3432 DRAWABLE(dst_drawable);
3444 ENUM8(coordinate_mode);
3445 v16 = REQUEST_LENGTH();
3448 LISTofPOINT(points, v16 - 12);
3452 ENUM8(coordinate_mode);
3453 v16 = REQUEST_LENGTH();
3456 LISTofPOINT(points, v16 - 12);
3464 LISTofSEGMENT(segments);
3467 case X_PolyRectangle:
3472 LISTofRECTANGLE(rectangles);
3485 v16 = REQUEST_LENGTH();
3489 ENUM8(coordinate_mode);
3491 LISTofPOINT(points, v16 - 16);
3494 case X_PolyFillRectangle:
3499 LISTofRECTANGLE(rectangles);
3511 ENUM8(image_format);
3512 v16 = REQUEST_LENGTH();
3522 LISTofBYTE(data, v16 - 24);
3527 ENUM8(image_pixmap_format);
3539 v16 = REQUEST_LENGTH();
3544 LISTofTEXTITEM8(items);
3550 v16 = REQUEST_LENGTH();
3555 LISTofTEXTITEM16(items);
3560 v8 = FIELD8(string_length);
3566 STRING8(string, v8);
3571 v8 = FIELD8(string_length);
3577 STRING16(string16, v8);
3581 case X_CreateColormap:
3589 case X_FreeColormap:
3595 case X_CopyColormapAndFree:
3602 case X_InstallColormap:
3608 case X_UninstallColormap:
3614 case X_ListInstalledColormaps:
3630 case X_AllocNamedColor:
3634 v16 = FIELD16(name_length);
3640 case X_AllocColorCells:
3648 case X_AllocColorPlanes:
3660 v16 = REQUEST_LENGTH();
3663 LISTofCARD32(pixels, v16 - 12);
3668 v16 = REQUEST_LENGTH();
3670 LISTofCOLORITEM(color_items, v16 - 8);
3673 case X_StoreNamedColor:
3678 v16 = FIELD16(name_length);
3686 v16 = REQUEST_LENGTH();
3688 LISTofCARD32(pixels, v16 - 8);
3695 v16 = FIELD16(name_length);
3701 case X_CreateCursor:
3705 PIXMAP(source_pixmap);
3717 case X_CreateGlyphCursor:
3723 CARD16(source_char);
3739 case X_RecolorCursor:
3751 case X_QueryBestSize:
3759 case X_QueryExtension:
3762 v16 = FIELD16(name_length);
3768 case X_ListExtensions:
3773 case X_ChangeKeyboardMapping:
3774 v8 = FIELD8(keycode_count);
3776 v8_2 = KEYCODE(first_keycode);
3777 v8_3 = FIELD8(keysyms_per_keycode);
3779 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3782 case X_GetKeyboardMapping:
3785 state->request.GetKeyboardMapping.first_keycode
3786 = KEYCODE(first_keycode);
3791 case X_ChangeKeyboardControl:
3794 BITMASK32(keyboard_value);
3795 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3796 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3797 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3798 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3799 BITFIELD(INT16, keyboard_value_mask, led);
3800 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3801 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3802 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3806 case X_GetKeyboardControl:
3816 case X_ChangePointerControl:
3819 INT16(acceleration_numerator);
3820 INT16(acceleration_denominator);
3822 BOOL(do_acceleration);
3826 case X_GetPointerControl:
3831 case X_SetScreenSaver:
3836 ENUM8(prefer_blanking);
3837 ENUM8(allow_exposures);
3841 case X_GetScreenSaver:
3847 ENUM8(change_host_mode);
3851 v16 = CARD16(address_length);
3852 if (v8 == FAMILY_INTERNET && v16 == 4) {
3855 * XXX - what about IPv6? Is that a family of
3856 * FAMILY_INTERNET (0) with a length of 16?
3858 LISTofCARD8(ip_address, v16);
3860 LISTofCARD8(address, v16);
3868 case X_SetAccessControl:
3873 case X_SetCloseDownMode:
3874 ENUM8(close_down_mode);
3884 case X_RotateProperties:
3886 v16 = REQUEST_LENGTH();
3888 CARD16(property_number);
3890 LISTofATOM(properties, (v16 - 12));
3893 case X_ForceScreenSaver:
3894 ENUM8(screen_saver_mode);
3898 case X_SetPointerMapping:
3899 v8 = FIELD8(map_length);
3901 LISTofCARD8(map, v8);
3905 case X_GetPointerMapping:
3910 case X_SetModifierMapping:
3911 v8 = FIELD8(keycodes_per_modifier);
3913 LISTofKEYCODE(state->modifiermap, keycodes, v8);
3916 case X_GetModifierMapping:
3927 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3931 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
3934 volatile int offset = 0;
3935 int length_remaining;
3936 volatile gboolean little_endian;
3941 volatile gboolean is_initial_creq;
3942 guint16 auth_proto_len, auth_data_len;
3943 const char *volatile sep = NULL;
3944 conversation_t *conversation;
3945 x11_conv_data_t *state;
3949 while (tvb_reported_length_remaining(tvb, offset) != 0) {
3951 * We use "tvb_ensure_length_remaining()" to make sure there
3952 * actually *is* data remaining.
3954 * This means we're guaranteed that "length_remaining" is
3957 length_remaining = tvb_ensure_length_remaining(tvb, offset);
3960 * Can we do reassembly?
3962 if (x11_desegment && pinfo->can_desegment) {
3964 * Yes - is the X11 request header split across
3965 * segment boundaries?
3967 if (length_remaining < 4) {
3969 * Yes. Tell the TCP dissector where the data
3970 * for this message starts in the data it handed
3971 * us, and how many more bytes we need, and return.
3973 pinfo->desegment_offset = offset;
3974 pinfo->desegment_len = 4 - length_remaining;
3980 * Get the state for this conversation; create the conversation
3981 * if we don't have one, and create the state if we don't have
3984 conversation = find_conversation(&pinfo->src, &pinfo->dst,
3985 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3986 if (conversation == NULL) {
3990 conversation = conversation_new(&pinfo->src,
3991 &pinfo->dst, pinfo->ptype, pinfo->srcport,
3992 pinfo->destport, 0);
3996 * Is there state attached to this conversation?
3998 if ((state = conversation_get_proto_data(conversation, proto_x11))
4000 x11_stateinit(&state, conversation);
4003 * Guess the byte order if we don't already know it.
4005 little_endian = guess_byte_ordering(tvb, pinfo, state);
4008 * Get the opcode and length of the putative X11 request.
4010 opcode = VALUE8(tvb, 0);
4011 plen = VALUE16(tvb, offset + 2);
4015 * This can't be 0, as it includes the header length.
4016 * A different choice of byte order wouldn't have
4020 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4022 t = proto_item_add_subtree(ti, ett_x11);
4023 proto_tree_add_text(t, tvb, offset, -1,
4024 "Bogus request length (0)");
4028 if (state->iconn_frame == pinfo->fd->num ||
4029 (g_hash_table_lookup(state->seqtable,
4030 (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
4031 (opcode == 'B' || opcode == 'l') &&
4032 (plen == 11 || plen == 2816))) {
4036 * we saw this on the first pass and this is
4040 * we haven't already seen any requests, the first
4041 * byte of the message is 'B' or 'l', and the 16-bit
4042 * integer 2 bytes into the data stream is either 11
4043 * or a byte-swapped 11.
4045 * This means it's probably an initial connection
4046 * request, not a message.
4048 * 'B' is decimal 66, which is the opcode for a
4049 * PolySegment request; unfortunately, 11 is a valid
4050 * length for a PolySegment request request, so we
4051 * might mis-identify that request. (Are there any
4052 * other checks we can do?)
4054 * 'l' is decimal 108, which is the opcode for a
4055 * GetScreenSaver request; the only valid length
4056 * for that request is 1.
4058 is_initial_creq = TRUE;
4061 * We now know the byte order. Override the guess.
4063 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4064 if (opcode == 'B') {
4068 state->byte_order = BYTE_ORDER_BE;
4069 little_endian = FALSE;
4074 state->byte_order = BYTE_ORDER_LE;
4075 little_endian = TRUE;
4080 * Can we do reassembly?
4082 if (x11_desegment && pinfo->can_desegment) {
4084 * Yes - is the fixed-length portion of the
4085 * initial connection header split across
4086 * segment boundaries?
4088 if (length_remaining < 10) {
4090 * Yes. Tell the TCP dissector where the
4091 * data for this message starts in the data
4092 * it handed us, and how many more bytes we
4095 pinfo->desegment_offset = offset;
4096 pinfo->desegment_len = 10 - length_remaining;
4102 * Get the lengths of the authorization protocol and
4103 * the authorization data.
4105 auth_proto_len = VALUE16(tvb, offset + 6);
4106 auth_data_len = VALUE16(tvb, offset + 8);
4107 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4108 ROUND_LENGTH(auth_data_len);
4111 * This is probably an ordinary request.
4113 is_initial_creq = FALSE;
4116 * The length of a request is in 4-byte words.
4122 * Can we do reassembly?
4124 if (x11_desegment && pinfo->can_desegment) {
4126 * Yes - is the X11 request split across segment
4129 if (length_remaining < plen) {
4131 * Yes. Tell the TCP dissector where the data
4132 * for this message starts in the data it handed
4133 * us, and how many more bytes we need, and return.
4135 pinfo->desegment_offset = offset;
4136 pinfo->desegment_len = plen - length_remaining;
4142 * Construct a tvbuff containing the amount of the payload
4143 * we have available. Make its reported length the
4144 * amount of data in the X11 request.
4146 * XXX - if reassembly isn't enabled. the subdissector
4147 * will throw a BoundsError exception, rather than a
4148 * ReportedBoundsError exception. We really want a tvbuff
4149 * where the length is "length", the reported length is "plen",
4150 * and the "if the snapshot length were infinite" length is the
4151 * minimum of the reported length of the tvbuff handed to us
4152 * and "plen", with a new type of exception thrown if the offset
4153 * is within the reported length but beyond that third length,
4154 * with that exception getting the "Unreassembled Packet" error.
4156 length = length_remaining;
4159 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4162 * Set the column appropriately.
4164 if (is_initial_creq) {
4165 if (check_col(pinfo->cinfo, COL_INFO))
4166 col_set_str(pinfo->cinfo, COL_INFO,
4167 "Initial connection request");
4171 * We haven't set the column yet; set it.
4173 if (check_col(pinfo->cinfo, COL_INFO))
4174 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4177 * Initialize the separator.
4184 * Dissect the X11 request.
4186 * Catch the ReportedBoundsError exception; if this
4187 * particular message happens to get a ReportedBoundsError
4188 * exception, that doesn't mean that we should stop
4189 * dissecting X11 requests within this frame or chunk of
4192 * If it gets a BoundsError, we can stop, as there's nothing
4193 * more to see, so we just re-throw it.
4196 if (is_initial_creq) {
4197 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4198 state, little_endian);
4200 dissect_x11_request(next_tvb, pinfo, tree, sep,
4201 state, little_endian);
4204 CATCH(BoundsError) {
4207 CATCH(ReportedBoundsError) {
4208 show_reported_bounds_error(tvb, pinfo, tree);
4213 * Skip the X11 message.
4222 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4224 static x11_conv_data_t stateinit;
4226 *state = g_mem_chunk_alloc(x11_state_chunk);
4227 **state = stateinit;
4229 (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4230 g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4231 (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4232 conversation_add_proto_data(conversation, proto_x11, *state);
4237 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4239 /* Set up structures we will need to add the protocol subtree and manage it */
4240 volatile int offset, plen;
4241 tvbuff_t * volatile next_tvb;
4242 conversation_t *conversation;
4243 x11_conv_data_t *state;
4244 gboolean little_endian;
4245 int length_remaining;
4246 const char *volatile sep = NULL;
4250 * Get the state for this conversation; create the conversation
4251 * if we don't have one, and create the state if we don't have
4254 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4255 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4256 if (conversation == NULL) {
4260 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4261 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4265 * Is there state attached to this conversation?
4267 if ((state = conversation_get_proto_data(conversation, proto_x11))
4270 * No - create a state structure and attach it.
4272 x11_stateinit(&state, conversation);
4276 * Guess the byte order if we don't already know it.
4278 little_endian = guess_byte_ordering(tvb, pinfo, state);
4281 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4283 * We use "tvb_ensure_length_remaining()" to make sure there
4284 * actually *is* data remaining.
4286 * This means we're guaranteed that "length_remaining" is
4289 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4292 * Can we do reassembly?
4294 if (x11_desegment && pinfo->can_desegment) {
4296 * Yes - is the X11 reply header split across
4297 * segment boundaries?
4299 if (length_remaining < 8) {
4301 * Yes. Tell the TCP dissector where the data
4302 * for this message starts in the data it handed
4303 * us, and how many more bytes we need, and
4306 pinfo->desegment_offset = offset;
4307 pinfo->desegment_len = 4 - length_remaining;
4313 * Find out what kind of a reply it is.
4314 * There are four possible:
4315 * - reply to initial connection
4316 * - errorreply (a request generated an error)
4317 * - requestreply (reply to a request)
4318 * - event (some event occured)
4320 if (g_hash_table_lookup(state->seqtable,
4321 (int *)state->sequencenumber) == (int *)INITIAL_CONN
4322 || (state->iconn_reply == pinfo->fd->num)) {
4324 * Either the connection is in the "initial
4325 * connection" state, or this frame is known
4326 * to have the initial connection reply.
4327 * That means this is the initial connection
4330 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4332 HANDLE_REPLY(plen, length_remaining,
4333 "Initial connection reply",
4334 dissect_x11_initial_reply);
4337 * This isn't an initial connection reply
4338 * (XXX - unless we missed the initial
4339 * connection request). Look at the first
4340 * byte to determine what it is; errors
4341 * start with a byte of 0, replies start
4342 * with a byte of 1, events start with
4343 * a byte with of 2 or greater.
4345 switch (tvb_get_guint8(tvb, offset)) {
4349 HANDLE_REPLY(plen, length_remaining,
4350 "Error", dissect_x11_error);
4354 /* replylength is in units of four. */
4355 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4357 HANDLE_REPLY(plen, length_remaining,
4358 "Reply", dissect_x11_reply);
4364 HANDLE_REPLY(plen, length_remaining,
4365 "Event", dissect_x11_event);
4377 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4378 const char *volatile sep, x11_conv_data_t *volatile state,
4379 gboolean little_endian)
4381 int offset = 0, *offsetp = &offset, length, left, opcode;
4385 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4386 tvb_reported_length_remaining(tvb, offset),
4388 t = proto_item_add_subtree(ti, ett_x11);
4392 * XXX - this doesn't work correctly if either
4394 * 1) the request sequence number wraps in the lower 16
4397 * 2) we don't see the initial connection request and thus
4398 * don't have the right sequence numbers;
4400 * 3) we don't have all the packets in the capture and
4401 * get out of sequence.
4403 * We might, instead, want to assume that a reply is a reply to
4404 * the most recent not-already-replied-to request in the same
4405 * connection. That also might mismatch replies to requests if
4406 * packets are lost, but there's nothing you can do to fix that.
4408 * XXX - if "opcode" is 0, we shouldn't say "Unknown opcode",
4409 * we should say that we don't have the request for the reply.
4411 opcode = (int)g_hash_table_lookup(state->seqtable,
4412 (int *)VALUE16(tvb, offset + 2));
4414 if (check_col(pinfo->cinfo, COL_INFO))
4415 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4418 * don't print opcode value since if it's
4419 * unknown, we didn't know to save the
4422 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
4424 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4425 opcode, val_to_str(opcode, opcode_vals,
4426 "<Unknown opcode %d>"));
4433 * Requests that expect a reply.
4436 case X_GetWindowAttributes:
4441 REPLYCONTENTS_COMMON();
4447 SEQUENCENUMBER_REPLY(sequencenumber);
4448 length = REPLYLENGTH(replylength);
4449 ATOM(get_property_type);
4450 CARD32(bytes_after);
4451 CARD32(valuelength);
4455 case X_ListProperties:
4456 case X_GetSelectionOwner:
4458 case X_GrabKeyboard:
4459 case X_QueryPointer:
4460 case X_GetMotionEvents:
4461 case X_TranslateCoords:
4462 REPLYCONTENTS_COMMON();
4467 case X_QueryTextExtents:
4470 case X_ListInstalledColormaps:
4474 case X_QueryBestSize:
4475 case X_QueryExtension:
4476 case X_ListExtensions:
4477 REPLYCONTENTS_COMMON();
4480 case X_GetKeyboardMapping:
4481 state->first_keycode
4482 = state->request.GetKeyboardMapping.first_keycode,
4484 state->keysyms_per_keycode
4485 = FIELD8(keysyms_per_keycode);
4486 SEQUENCENUMBER_REPLY(sequencenumber);
4487 length = REPLYLENGTH(replylength);
4489 LISTofKEYSYM(keysyms, state->keycodemap,
4490 state->request.GetKeyboardMapping.first_keycode,
4491 length / state->keysyms_per_keycode,
4492 state->keysyms_per_keycode);
4495 case X_GetKeyboardControl:
4496 case X_GetPointerControl:
4497 case X_GetScreenSaver:
4499 case X_SetPointerMapping:
4500 case X_GetPointerMapping:
4501 case X_SetModifierMapping:
4502 REPLYCONTENTS_COMMON();
4505 case X_GetModifierMapping:
4507 state->keycodes_per_modifier
4508 = FIELD8(keycodes_per_modifier);
4509 SEQUENCENUMBER_REPLY(sequencenumber);
4510 REPLYLENGTH(replylength);
4512 LISTofKEYCODE(state->modifiermap, keycodes,
4513 state->keycodes_per_modifier);
4517 REPLYCONTENTS_COMMON();
4520 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4525 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4526 const char *volatile sep, x11_conv_data_t *volatile state,
4527 gboolean little_endian)
4529 int offset = 0, *offsetp = &offset, left;
4530 unsigned char eventcode;
4534 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4535 t = proto_item_add_subtree(ti, ett_x11);
4537 eventcode = tvb_get_guint8(tvb, offset);
4539 if (check_col(pinfo->cinfo, COL_INFO))
4540 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4541 sep, val_to_str(eventcode, eventcode_vals,
4542 "<Unknown eventcode %u>"));
4544 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4546 "eventcode: %d (%s)",
4548 val_to_str(eventcode, eventcode_vals,
4549 "<Unknown eventcode %u>"));
4552 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4553 eventcode, val_to_str(eventcode, eventcode_vals,
4554 "<Unknown eventcode %u>"));
4559 switch (eventcode) {
4564 /* need to do some prefetching here ... */
4565 code = VALUE8(tvb, offset);
4566 mask = VALUE16(tvb, 28);
4568 KEYCODE_DECODED(keycode, code, mask);
4569 CARD16(event_sequencenumber);
4570 EVENTCONTENTS_COMMON();
4578 BUTTON(eventbutton);
4579 CARD16(event_sequencenumber);
4580 EVENTCONTENTS_COMMON();
4587 CARD16(event_sequencenumber);
4588 EVENTCONTENTS_COMMON();
4596 CARD16(event_sequencenumber);
4597 EVENTCONTENTS_COMMON();
4605 case GraphicsExpose:
4607 case VisibilityNotify:
4613 case ReparentNotify:
4614 case ConfigureNotify:
4615 case ConfigureRequest:
4618 case CirculateNotify:
4619 case CirculateRequest:
4620 case PropertyNotify:
4621 case SelectionClear:
4622 case SelectionRequest:
4623 case SelectionNotify:
4624 case ColormapNotify:
4631 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4638 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4639 const char *volatile sep, x11_conv_data_t *volatile state _U_,
4640 gboolean little_endian)
4642 int offset = 0, *offsetp = &offset, left;
4643 unsigned char errorcode, error;
4647 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4648 t = proto_item_add_subtree(ti, ett_x11);
4650 error = tvb_get_guint8(tvb, offset);
4653 errorcode = tvb_get_guint8(tvb, offset);
4654 if (check_col(pinfo->cinfo, COL_INFO))
4655 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4656 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
4658 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
4660 "errorcode: %d (%s)",
4662 val_to_str(errorcode, errorcode_vals,
4663 "<Unknown errocode %u>"));
4666 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
4667 errorcode, val_to_str(errorcode, errorcode_vals,
4668 "<Unknown errorcode %u>"));
4673 CARD16(error_sequencenumber);
4675 switch (errorcode) {
4677 CARD32(error_badvalue);
4684 CARD16(minor_opcode);
4685 CARD8(major_opcode);
4687 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4693 /************************************************************************
4695 *** I N I T I A L I Z A T I O N A N D M A I N ***
4697 ************************************************************************/
4700 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4702 if (check_col(pinfo->cinfo, COL_PROTOCOL))
4703 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
4705 if (pinfo->match_port == pinfo->srcport)
4706 dissect_x11_replies(tvb, pinfo, tree);
4708 dissect_x11_requests(tvb, pinfo, tree);
4711 /* Register the protocol with Ethereal */
4712 void proto_register_x11(void)
4715 /* Setup list of header fields */
4716 static hf_register_info hf[] = {
4718 { &hf_x11_FIELDABBREV,
4719 { "FIELDNAME", "x11.FIELDABBREV",
4720 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
4721 "FIELDDESCR", HFILL }
4724 #include "x11-register-info.h"
4727 /* Setup protocol subtree array */
4728 static gint *ett[] = {
4730 &ett_x11_color_flags,
4731 &ett_x11_list_of_arc,
4733 &ett_x11_list_of_atom,
4734 &ett_x11_list_of_card32,
4735 &ett_x11_list_of_color_item,
4736 &ett_x11_color_item,
4737 &ett_x11_list_of_keycode,
4738 &ett_x11_list_of_keysyms,
4740 &ett_x11_list_of_point,
4742 &ett_x11_list_of_rectangle,
4744 &ett_x11_list_of_segment,
4746 &ett_x11_list_of_string8,
4747 &ett_x11_list_of_text_item,
4749 &ett_x11_gc_value_mask,
4750 &ett_x11_event_mask,
4751 &ett_x11_do_not_propagate_mask,
4752 &ett_x11_set_of_key_mask,
4753 &ett_x11_pointer_event_mask,
4754 &ett_x11_window_value_mask,
4755 &ett_x11_configure_window_mask,
4756 &ett_x11_keyboard_value_mask,
4758 module_t *x11_module;
4760 /* Register the protocol name and description */
4761 proto_x11 = proto_register_protocol("X11", "X11", "x11");
4763 /* Required function calls to register the header fields and subtrees used */
4764 proto_register_field_array(proto_x11, hf, array_length(hf));
4765 proto_register_subtree_array(ett, array_length(ett));
4767 register_init_routine(x11_init_protocol);
4769 x11_module = prefs_register_protocol(proto_x11, NULL);
4770 prefs_register_bool_preference(x11_module, "desegment",
4771 "Desegment all X11 messages spanning multiple TCP segments",
4772 "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
4777 proto_reg_handoff_x11(void)
4779 dissector_handle_t x11_handle;
4781 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
4782 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
4783 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
4784 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
4785 data_handle = find_dissector("data");