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.54 2004/02/25 09:31:07 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);
1751 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1753 for(i = 0; i < keysyms_per_keycode; ++i) {
1754 /* keysymvalue = byte3 * 256 + byte4. */
1755 guint32 v = VALUE32(tvb, *offsetp);
1757 proto_item_append_text(tti, " %s", keysymString(v));
1758 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1759 tvb, *offsetp, 4, v,
1760 "keysym (keycode %d): 0x%08x (%s)",
1761 keycode, v, keysymString(v));
1763 keycodemap[keycode][i] = v;
1767 for (i = 1; i < keysyms_per_keycode; ++i)
1768 if (keycodemap[keycode][i] != NoSymbol)
1771 if (i == keysyms_per_keycode) {
1772 /* all but (possibly) first were NoSymbol. */
1773 if (keysyms_per_keycode == 4) {
1774 keycodemap[keycode][1] = NoSymbol;
1775 keycodemap[keycode][2] = keycodemap[keycode][0];
1776 keycodemap[keycode][3] = NoSymbol;
1782 for (i = 2; i < keysyms_per_keycode; ++i)
1783 if (keycodemap[keycode][i] != NoSymbol)
1785 if (i == keysyms_per_keycode) {
1786 /* all but (possibly) first two were NoSymbol. */
1787 if (keysyms_per_keycode == 4) {
1788 keycodemap[keycode][2] = keycodemap[keycode][0];
1789 keycodemap[keycode][3] = keycodemap[keycode][1];
1797 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1798 int length, gboolean little_endian)
1800 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1801 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1807 x = VALUE16(tvb, *offsetp);
1808 y = VALUE16(tvb, *offsetp + 2);
1810 tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1811 ttt = proto_item_add_subtree(tti, ett_x11_point);
1812 proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1814 proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1819 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1820 int length, gboolean little_endian)
1822 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1823 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1826 unsigned width, height;
1830 x = VALUE16(tvb, *offsetp);
1831 y = VALUE16(tvb, *offsetp + 2);
1832 width = VALUE16(tvb, *offsetp + 4);
1833 height = VALUE16(tvb, *offsetp + 6);
1835 tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1836 "rectangle: %dx%d+%d+%d", width, height, x, y);
1837 ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1838 proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1840 proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1842 proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1844 proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1849 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1850 int length, gboolean little_endian)
1852 proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1853 proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1855 gint16 x1, y1, x2, y2;
1859 x1 = VALUE16(tvb, *offsetp);
1860 y1 = VALUE16(tvb, *offsetp + 2);
1861 x2 = VALUE16(tvb, *offsetp + 4);
1862 y2 = VALUE16(tvb, *offsetp + 6);
1864 tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1865 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1866 ttt = proto_item_add_subtree(tti, ett_x11_segment);
1867 proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1869 proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1871 proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1873 proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1878 /* XXX - the protocol tree code should handle non-printable characters.
1879 Note that "non-printable characters" may depend on your locale.... */
1880 static void stringCopy(char *dest, const char *source, int length)
1885 if (!isgraph(c) && c != ' ') c = '.';
1891 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1892 int hf_item, int length, gboolean little_endian)
1895 guint allocated = 0;
1900 /* Compute total length */
1902 int scanning_offset = *offsetp; /* Scanning pointer */
1904 for(i = length; i; i--) {
1905 l = tvb_get_guint8(tvb, scanning_offset);
1906 scanning_offset += 1 + l;
1909 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1910 tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1913 * In case we throw an exception, clean up whatever stuff we've
1914 * allocated (if any).
1916 CLEANUP_PUSH(g_free, s);
1919 unsigned l = VALUE8(tvb, *offsetp);
1920 if (allocated < (l + 1)) {
1921 /* g_realloc doesn't work ??? */
1923 s = g_malloc(l + 1);
1926 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1927 proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1932 * Call the cleanup handler to free the string and pop the handler.
1934 CLEANUP_CALL_AND_POP;
1937 #define STRING16_MAX_DISPLAYED_LENGTH 150
1939 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1941 if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1942 for(; length > 0; offset += 2, length--) {
1943 if (tvb_get_guint8(tvb, offset))
1949 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1951 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1952 int hf, int hf_bytes,
1953 int offset, unsigned length,
1954 char **s, int *sLength,
1955 gboolean little_endian)
1957 int truncated = FALSE;
1958 unsigned l = length / 2;
1960 if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1962 int soffset = offset;
1964 if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1966 l = STRING16_MAX_DISPLAYED_LENGTH;
1968 if (*sLength < (int) l + 3) {
1970 *s = g_malloc(l + 3);
1975 if (truncated) l -= 3;
1979 *dp++ = tvb_get_guint8(tvb, soffset);
1984 /* If truncated, add an ellipsis */
1985 if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1988 proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1989 proto_registrar_get_nth(hf) -> name, *s);
1991 proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1995 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1996 int sizeIs16, int next_offset, gboolean little_endian)
2004 /* Compute total length */
2006 int scanning_offset = *offsetp; /* Scanning pointer */
2007 int l; /* Length of an individual item */
2008 int n = 0; /* Number of items */
2010 while(scanning_offset < next_offset) {
2011 l = tvb_get_guint8(tvb, scanning_offset);
2015 scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2018 ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2019 tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2022 * In case we throw an exception, clean up whatever stuff we've
2023 * allocated (if any).
2025 CLEANUP_PUSH(g_free, s);
2028 unsigned l = VALUE8(tvb, *offsetp);
2029 if (l == 255) { /* Item is a font */
2030 fid = tvb_get_ntohl(tvb, *offsetp + 1);
2031 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2033 } else { /* Item is a string */
2036 gint8 delta = VALUE8(tvb, *offsetp + 1);
2037 if (sizeIs16) l += l;
2038 if ((unsigned) allocated < l + 1) {
2039 /* g_realloc doesn't work ??? */
2041 s = g_malloc(l + 1);
2044 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2045 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2046 "textitem (string): delta = %d, \"%s\"",
2048 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2049 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2051 string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2052 hf_x11_textitem_string_string16_bytes,
2057 proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2058 *offsetp + 2, l, s, "\"%s\"", s);
2064 * Call the cleanup handler to free the string and pop the handler.
2066 CLEANUP_CALL_AND_POP;
2069 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2070 gboolean little_endian)
2072 guint32 v = VALUE8(tvb, *offsetp);
2073 header_field_info *hfi = proto_registrar_get_nth(hf);
2074 gchar *enumValue = NULL;
2077 enumValue = match_strval(v, cVALS(hfi -> strings));
2079 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2080 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2081 hfi -> name, v, enumValue);
2083 proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2088 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2089 gboolean little_endian)
2091 guint32 v = VALUE16(tvb, *offsetp);
2092 header_field_info *hfi = proto_registrar_get_nth(hf);
2093 gchar *enumValue = NULL;
2096 enumValue = match_strval(v, cVALS(hfi -> strings));
2098 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2099 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2100 hfi -> name, v, enumValue);
2102 proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2107 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2108 gboolean little_endian)
2110 guint32 v = VALUE32(tvb, *offsetp);
2111 header_field_info *hfi = proto_registrar_get_nth(hf);
2112 gchar *enumValue = NULL;
2113 gchar *nameAsChar = hfi -> name;
2116 enumValue = match_strval(v, cVALS(hfi -> strings));
2118 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2119 hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2120 nameAsChar, v, enumValue);
2122 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2123 hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2129 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2130 gboolean little_endian)
2132 BITMASK32(gc_value);
2133 BITFIELD(ENUM8, gc_value_mask, function);
2134 BITFIELD(CARD32, gc_value_mask, plane_mask);
2135 BITFIELD(CARD32, gc_value_mask, foreground);
2136 BITFIELD(CARD32, gc_value_mask, background);
2137 BITFIELD(CARD16, gc_value_mask, line_width);
2138 BITFIELD(ENUM8, gc_value_mask, line_style);
2139 BITFIELD(ENUM8, gc_value_mask, cap_style);
2140 BITFIELD(ENUM8, gc_value_mask, join_style);
2141 BITFIELD(ENUM8, gc_value_mask, fill_style);
2142 BITFIELD(ENUM8, gc_value_mask, fill_rule);
2143 BITFIELD(PIXMAP, gc_value_mask, tile);
2144 BITFIELD(PIXMAP, gc_value_mask, stipple);
2145 BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
2146 BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
2147 BITFIELD(FONT, gc_value_mask, font);
2148 BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
2149 BITFIELD(BOOL, gc_value_mask, graphics_exposures);
2150 BITFIELD(INT16, gc_value_mask, clip_x_origin);
2151 BITFIELD(INT16, gc_value_mask, clip_y_origin);
2152 BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2153 BITFIELD(CARD16, gc_value_mask, dash_offset);
2154 BITFIELD(CARD8, gc_value_mask, gc_dashes);
2155 BITFIELD(ENUM8, gc_value_mask, arc_mode);
2159 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2160 gboolean little_endian)
2162 BITMASK32(gc_value);
2163 FLAG(gc_value, function);
2164 FLAG(gc_value, plane_mask);
2165 FLAG(gc_value, foreground);
2166 FLAG(gc_value, background);
2167 FLAG(gc_value, line_width);
2168 FLAG(gc_value, line_style);
2169 FLAG(gc_value, cap_style);
2170 FLAG(gc_value, join_style);
2171 FLAG(gc_value, fill_style);
2172 FLAG(gc_value, fill_rule);
2173 FLAG(gc_value, tile);
2174 FLAG(gc_value, stipple);
2175 FLAG(gc_value, tile_stipple_x_origin);
2176 FLAG(gc_value, tile_stipple_y_origin);
2177 FLAG(gc_value, font);
2178 FLAG(gc_value, subwindow_mode);
2179 FLAG(gc_value, graphics_exposures);
2180 FLAG(gc_value, clip_x_origin);
2181 FLAG(gc_value, clip_y_origin);
2182 FLAG(gc_value, clip_mask);
2183 FLAG(gc_value, dash_offset);
2184 FLAG(gc_value, gc_dashes);
2185 FLAG(gc_value, arc_mode);
2189 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2190 gboolean little_endian)
2192 guint32 res = VALUE16(tvb, *offsetp);
2193 proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2198 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2199 gboolean little_endian)
2202 FLAG(event, KeyPress);
2203 FLAG(event, KeyRelease);
2204 FLAG(event, ButtonPress);
2205 FLAG(event, ButtonRelease);
2206 FLAG(event, EnterWindow);
2207 FLAG(event, LeaveWindow);
2208 FLAG(event, PointerMotion);
2209 FLAG(event, PointerMotionHint);
2210 FLAG(event, Button1Motion);
2211 FLAG(event, Button2Motion);
2212 FLAG(event, Button3Motion);
2213 FLAG(event, Button4Motion);
2214 FLAG(event, Button5Motion);
2215 FLAG(event, ButtonMotion);
2216 FLAG(event, KeymapState);
2217 FLAG(event, Exposure);
2218 FLAG(event, VisibilityChange);
2219 FLAG(event, StructureNotify);
2220 FLAG(event, ResizeRedirect);
2221 FLAG(event, SubstructureNotify);
2222 FLAG(event, SubstructureRedirect);
2223 FLAG(event, FocusChange);
2224 FLAG(event, PropertyChange);
2225 FLAG(event, ColormapChange);
2226 FLAG(event, OwnerGrabButton);
2227 FLAG_IF_NONZERO(event, erroneous_bits);
2231 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2232 gboolean little_endian)
2234 BITMASK32(do_not_propagate);
2235 FLAG(do_not_propagate, KeyPress);
2236 FLAG(do_not_propagate, KeyRelease);
2237 FLAG(do_not_propagate, ButtonPress);
2238 FLAG(do_not_propagate, ButtonRelease);
2239 FLAG(do_not_propagate, PointerMotion);
2240 FLAG(do_not_propagate, Button1Motion);
2241 FLAG(do_not_propagate, Button2Motion);
2242 FLAG(do_not_propagate, Button3Motion);
2243 FLAG(do_not_propagate, Button4Motion);
2244 FLAG(do_not_propagate, Button5Motion);
2245 FLAG(do_not_propagate, ButtonMotion);
2246 FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2251 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2252 gboolean little_endian, gboolean butmask)
2255 guint32 bitmask_value;
2258 proto_tree *bitmask_tree;
2260 bitmask_value = VALUE16(tvb, *offsetp);
2261 bitmask_offset = *offsetp;
2264 if (!butmask && bitmask_value == 0x8000)
2265 proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2266 "modifiers-masks: 0x8000 (AnyModifier)");
2268 ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2270 bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2271 FLAG(modifiers, Shift);
2272 FLAG(modifiers, Lock);
2273 FLAG(modifiers, Control);
2274 FLAG(modifiers, Mod1);
2275 FLAG(modifiers, Mod2);
2276 FLAG(modifiers, Mod3);
2277 FLAG(modifiers, Mod4);
2278 FLAG(modifiers, Mod5);
2281 FLAG(modifiers, Button1);
2282 FLAG(modifiers, Button2);
2283 FLAG(modifiers, Button3);
2284 FLAG(modifiers, Button4);
2285 FLAG(modifiers, Button5);
2289 FLAG_IF_NONZERO(keybut, erroneous_bits);
2291 FLAG_IF_NONZERO(modifiers, erroneous_bits);
2297 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2298 gboolean little_endian)
2300 BITMASK16(pointer_event);
2301 FLAG(pointer_event, ButtonPress);
2302 FLAG(pointer_event, ButtonRelease);
2303 FLAG(pointer_event, EnterWindow);
2304 FLAG(pointer_event, LeaveWindow);
2305 FLAG(pointer_event, PointerMotion);
2306 FLAG(pointer_event, PointerMotionHint);
2307 FLAG(pointer_event, Button1Motion);
2308 FLAG(pointer_event, Button2Motion);
2309 FLAG(pointer_event, Button3Motion);
2310 FLAG(pointer_event, Button4Motion);
2311 FLAG(pointer_event, Button5Motion);
2312 FLAG(pointer_event, ButtonMotion);
2313 FLAG(pointer_event, KeymapState);
2314 FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2318 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2319 int hf, unsigned length)
2324 p = tvb_get_ptr(tvb, *offsetp, length);
2325 s = g_malloc(length + 1);
2326 stringCopy(s, p, length);
2327 proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2332 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2334 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2335 int hf_bytes, unsigned length, gboolean little_endian)
2341 * In case we throw an exception, clean up whatever stuff we've
2342 * allocated (if any).
2344 CLEANUP_PUSH(g_free, s);
2347 string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2348 &s, &l, little_endian);
2351 * Call the cleanup handler to free the string and pop the handler.
2353 CLEANUP_CALL_AND_POP;
2358 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2359 gboolean little_endian)
2361 guint32 v = VALUE32(tvb, *offsetp);
2364 proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2365 proto_registrar_get_nth(hf) -> name);
2367 proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2371 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2372 gboolean little_endian)
2374 BITMASK32(window_value);
2375 BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2376 BITFIELD(CARD32, window_value_mask, background_pixel);
2377 BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2378 BITFIELD(CARD32, window_value_mask, border_pixel);
2379 BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2380 BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2381 BITFIELD(ENUM8, window_value_mask, backing_store);
2382 BITFIELD(CARD32, window_value_mask, backing_planes);
2383 BITFIELD(CARD32, window_value_mask, backing_pixel);
2384 BITFIELD(BOOL, window_value_mask, override_redirect);
2385 BITFIELD(BOOL, window_value_mask, save_under);
2386 BITFIELD(SETofEVENT, window_value_mask, event_mask);
2387 BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2388 BITFIELD(COLORMAP, window_value_mask, colormap);
2389 BITFIELD(CURSOR, window_value_mask, cursor);
2393 static void x11_init_protocol(void)
2395 if (x11_state_chunk != NULL)
2396 g_mem_chunk_destroy(x11_state_chunk);
2398 x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2399 sizeof (x11_conv_data_t),
2400 128 * sizeof (x11_conv_data_t),
2404 /************************************************************************
2406 *** G U E S S I N G T H E B Y T E O R D E R I N G ***
2408 ************************************************************************/
2410 /* If we can't guess, we return TRUE (that is little_endian), cause
2411 I'm developing on a Linux box :-). The (non-)guess isn't cached
2412 however, so we may have more luck next time. I'm quite conservative
2413 in my assertions, cause once it's cached, it's stay in cache, and
2414 we may be fooled up by a packet starting with the end of a request
2415 started in a previous packet...
2418 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2420 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2423 while(maskLength--) {
2424 int c = tvb_get_guint8(tvb, offset);
2426 res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2431 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2433 if (listLength > length) return FALSE;
2434 while(listLength--) {
2436 if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2437 l = tvb_get_guint8(tvb, offset);
2440 if (l > length) return FALSE;
2441 if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2445 if (length > 3) return FALSE;
2449 static int rounded4(int n)
2451 int remainder = n % 4;
2453 if (remainder) res++;
2457 /* We assume the order to be consistent, until proven wrong. */
2459 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2461 switch(tvb_get_guint8(tvb, offset)) {
2462 case X_CreateWindow:
2463 return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2465 case X_ChangeWindowAttributes:
2467 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2469 case X_GetWindowAttributes:
2470 case X_DestroyWindow:
2471 case X_DestroySubwindows:
2472 case X_ChangeSaveSet:
2474 case X_MapSubwindows:
2476 case X_UnmapSubwindows:
2477 case X_CirculateWindow:
2481 case X_ListProperties:
2482 case X_GetSelectionOwner:
2483 case X_UngrabPointer:
2484 case X_UngrabKeyboard:
2486 case X_QueryPointer:
2491 case X_FreeColormap:
2492 case X_InstallColormap:
2493 case X_UninstallColormap:
2494 case X_ListInstalledColormaps:
2496 case X_GetKeyboardMapping:
2500 case X_ReparentWindow:
2501 case X_SetSelectionOwner:
2502 case X_ChangeActivePointerGrab:
2503 case X_GrabKeyboard:
2505 case X_GetMotionEvents:
2506 case X_TranslateCoords:
2507 case X_CreatePixmap:
2510 case X_CreateColormap:
2512 case X_AllocColorPlanes:
2515 case X_ConfigureWindow:
2516 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2519 case X_QueryExtension:
2520 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2522 case X_ChangeProperty:
2524 int multiplier, type;
2525 if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2526 type = tvb_get_guint8(tvb, 16);
2527 if (type != 8 && type != 16 && type != 32) return FALSE;
2528 multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2529 if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2530 return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2533 case X_DeleteProperty:
2534 case X_UngrabButton:
2536 case X_SetInputFocus:
2537 case X_CopyColormapAndFree:
2538 case X_AllocColorCells:
2539 case X_QueryBestSize:
2540 case X_ChangePointerControl:
2541 case X_SetScreenSaver:
2545 case X_ConvertSelection:
2552 return length == 11;
2555 case X_UngrabServer:
2556 case X_GetInputFocus:
2559 case X_ListExtensions:
2560 case X_GetKeyboardControl:
2562 case X_GetPointerControl:
2563 case X_GetScreenSaver:
2565 case X_SetAccessControl:
2566 case X_SetCloseDownMode:
2567 case X_ForceScreenSaver:
2568 case X_GetPointerMapping:
2569 case X_GetModifierMapping:
2573 case X_AllocNamedColor:
2575 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2577 case X_QueryTextExtents:
2581 case X_ListFontsWithInfo:
2583 return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2586 if (length < 2) return FALSE;
2587 if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2588 return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2591 return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2594 return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2596 case X_SetClipRectangles:
2598 case X_PolyRectangle:
2599 case X_PolyFillRectangle:
2600 return length >= 3 && (length - 3) % 2 == 0;
2606 case X_CreateCursor:
2607 case X_CreateGlyphCursor:
2617 return length >= 3 && (length - 3) % 3 == 0;
2627 case X_RecolorCursor:
2631 if (length < 4) return FALSE;
2632 return TRUE; /* We don't perform many controls on this one */
2635 if (length < 4) return FALSE;
2636 return TRUE; /* We don't perform many controls on this one */
2642 return length > 2 && (length - 2) % 3 == 0;
2644 case X_StoreNamedColor:
2645 return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2650 case X_ChangeKeyboardMapping:
2651 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2653 case X_ChangeKeyboardControl:
2654 return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2656 case X_RotateProperties:
2657 return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2659 case X_SetPointerMapping:
2660 return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2662 case X_SetModifierMapping:
2663 return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2673 /* -1 means doesn't match, +1 means match, 0 means don't know */
2675 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2677 int offset, nextoffset;
2680 for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2682 length = v16(tvb, offset + 2);
2683 if (!length) return -1;
2684 nextoffset = offset + length * 4;
2685 if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2692 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2693 x11_conv_data_t *state)
2695 /* With X the client gives the byte ordering for the protocol,
2696 and the port on the server tells us we're speaking X. */
2698 int le, be, decision, decisionToCache;
2700 if (state->byte_order == BYTE_ORDER_BE)
2701 return FALSE; /* known to be big-endian */
2702 else if (state->byte_order == BYTE_ORDER_LE)
2703 return TRUE; /* known to be little-endian */
2705 if (pinfo->srcport == pinfo->match_port) {
2707 * This is a reply or event; we don't try to guess the
2708 * byte order on it for now.
2713 le = x_endian_match(tvb, tvb_get_letohs);
2714 be = x_endian_match(tvb, tvb_get_ntohs);
2716 /* remember that "decision" really means "little_endian". */
2718 /* We have no reason to believe it's little- rather than
2719 big-endian, so we guess the shortest length is the
2722 if (!tvb_bytes_exist(tvb, 0, 4))
2723 /* Not even a way to get the length. We're biased
2724 toward little endianness here (essentially the
2725 x86 world right now). Decoding won't go very far
2730 decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2732 decision = le >= be;
2734 decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2735 if (decisionToCache) {
2737 * Remember the decision.
2739 state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2743 fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2744 pinfo->fd -> num, le, be, decision, decisionToCache);
2749 /************************************************************************
2751 *** D E C O D I N G O N E P A C K E T ***
2753 ************************************************************************/
2756 * Decode an initial connection request.
2758 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2759 proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2762 int *offsetp = &offset;
2765 guint16 auth_proto_name_length, auth_proto_data_length;
2768 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2769 proto_item_append_text(ti, ", Request, Initial connection request");
2770 t = proto_item_add_subtree(ti, ett_x11);
2774 CARD16(protocol_major_version);
2775 CARD16(protocol_minor_version);
2776 auth_proto_name_length = CARD16(authorization_protocol_name_length);
2777 auth_proto_data_length = CARD16(authorization_protocol_data_length);
2780 if (auth_proto_name_length != 0) {
2781 STRING8(authorization_protocol_name, auth_proto_name_length);
2782 offset = ROUND_LENGTH(offset);
2785 if (auth_proto_data_length != 0) {
2786 STRING8(authorization_protocol_data, auth_proto_data_length);
2787 offset = ROUND_LENGTH(offset);
2790 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2791 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2795 * This is the initial connection request...
2797 state->iconn_frame = pinfo->fd->num;
2800 * ...and we're expecting a reply to it.
2802 state->sequencenumber = 0;
2803 g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
2804 (int *)INITIAL_CONN);
2807 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2808 proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2809 gboolean little_endian)
2811 int offset = 0, *offsetp = &offset, left;
2812 unsigned char success;
2813 int length_of_vendor;
2814 int length_of_reason;
2818 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2819 proto_item_append_text(ti, ", Reply, Initial connection reply");
2820 t = proto_item_add_subtree(ti, ett_x11);
2822 state->iconn_reply = pinfo->fd->num;
2823 success = INT8(success);
2826 length_of_reason = 0;
2829 length_of_reason = INT8(length_of_reason);
2832 INT16(protocol_major_version);
2833 INT16(protocol_minor_version);
2836 INT32(release_number);
2837 INT32(resource_id_base);
2838 INT32(resource_id_mask);
2839 INT32(motion_buffer_size);
2840 length_of_vendor = INT16(length_of_vendor);
2841 INT16(maximum_request_length);
2842 INT8(number_of_screens_in_roots);
2843 INT8(number_of_formats_in_pixmap_formats);
2844 INT8(image_byte_order);
2845 INT8(bitmap_format_bit_order);
2846 INT8(bitmap_format_scanline_unit);
2847 INT8(bitmap_format_scanline_pad);
2851 STRING8(vendor, length_of_vendor);
2853 STRING8(reason, length_of_reason);
2856 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2861 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2862 proto_tree *tree, const char *sep, x11_conv_data_t *state,
2863 gboolean little_endian)
2866 int *offsetp = &offset;
2871 guint8 v8, v8_2, v8_3;
2876 length = VALUE16(tvb, 2) * 4;
2879 /* Bogus message length? */
2883 next_offset = offset + length;
2885 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2886 t = proto_item_add_subtree(ti, ett_x11);
2888 if (PACKET_IS_NEW(pinfo))
2889 ++state->sequencenumber;
2893 if (check_col(pinfo->cinfo, COL_INFO))
2894 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2895 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
2897 proto_item_append_text(ti, ", Request, opcode: %d (%s)",
2898 opcode, val_to_str(opcode, opcode_vals,
2899 "<Unknown opcode %d>"));
2902 * Does this request expect a reply?
2906 case X_AllocColorCells:
2907 case X_AllocColorPlanes:
2908 case X_AllocNamedColor:
2913 case X_GetInputFocus:
2914 case X_GetKeyboardControl:
2915 case X_GetKeyboardMapping:
2916 case X_GetModifierMapping:
2917 case X_GetMotionEvents:
2918 case X_GetPointerControl:
2919 case X_GetPointerMapping:
2921 case X_GetScreenSaver:
2922 case X_GetSelectionOwner:
2923 case X_GetWindowAttributes:
2924 case X_GrabKeyboard:
2927 case X_ListExtensions:
2929 case X_ListFontsWithInfo:
2931 case X_ListInstalledColormaps:
2932 case X_ListProperties:
2934 case X_QueryBestSize:
2936 case X_QueryExtension:
2939 case X_QueryPointer:
2940 case X_QueryTextExtents:
2942 case X_SetModifierMapping:
2943 case X_SetPointerMapping:
2944 case X_TranslateCoords:
2946 * Those requests expect a reply.
2949 g_hash_table_insert(state->seqtable,
2950 (int *)state->sequencenumber, (int *)opcode);
2956 * No reply is expected from any other request.
2966 case X_CreateWindow:
2975 CARD16(border_width);
2976 ENUM16(window_class);
2978 windowAttributes(tvb, offsetp, t, little_endian);
2981 case X_ChangeWindowAttributes:
2985 windowAttributes(tvb, offsetp, t, little_endian);
2988 case X_GetWindowAttributes:
2989 case X_DestroyWindow:
2990 case X_DestroySubwindows:
2996 case X_ChangeSaveSet:
2997 ENUM8(save_set_mode);
3002 case X_ReparentWindow:
3012 case X_MapSubwindows:
3014 case X_UnmapSubwindows:
3020 case X_ConfigureWindow:
3024 BITMASK16(configure_window);
3026 BITFIELD(INT16, configure_window_mask, x);
3027 BITFIELD(INT16, configure_window_mask, y);
3028 BITFIELD(CARD16, configure_window_mask, width);
3029 BITFIELD(CARD16, configure_window_mask, height);
3030 BITFIELD(CARD16, configure_window_mask, border_width);
3031 BITFIELD(WINDOW, configure_window_mask, sibling);
3032 BITFIELD(ENUM8, configure_window_mask, stack_mode);
3037 case X_CirculateWindow:
3051 BOOL(only_if_exists);
3053 v16 = FIELD16(name_length);
3065 case X_ChangeProperty:
3073 v32 = CARD32(data_length);
3074 LISTofBYTE(data, v32);
3078 case X_DeleteProperty:
3090 ATOM(get_property_type);
3091 CARD32(long_offset);
3092 CARD32(long_length);
3095 case X_ListProperties:
3101 case X_SetSelectionOwner:
3109 case X_GetSelectionOwner:
3115 case X_ConvertSelection:
3128 WINDOW(grab_window);
3129 SETofPOINTEREVENT(pointer_event_mask);
3130 ENUM8(pointer_mode);
3131 ENUM8(keyboard_mode);
3137 case X_UngrabPointer:
3146 WINDOW(grab_window);
3147 SETofPOINTEREVENT(event_mask);
3148 ENUM8(pointer_mode);
3149 ENUM8(keyboard_mode);
3154 SETofKEYMASK(modifiers);
3157 case X_UngrabButton:
3160 WINDOW(grab_window);
3161 SETofKEYMASK(modifiers);
3165 case X_ChangeActivePointerGrab:
3170 SETofPOINTEREVENT(event_mask);
3174 case X_GrabKeyboard:
3177 WINDOW(grab_window);
3179 ENUM8(pointer_mode);
3180 ENUM8(keyboard_mode);
3184 case X_UngrabKeyboard:
3193 WINDOW(grab_window);
3194 SETofKEYMASK(modifiers);
3196 ENUM8(pointer_mode);
3197 ENUM8(keyboard_mode);
3204 WINDOW(grab_window);
3205 SETofKEYMASK(modifiers);
3210 ENUM8(allow_events_mode);
3220 case X_UngrabServer:
3225 case X_QueryPointer:
3231 case X_GetMotionEvents:
3239 case X_TranslateCoords:
3251 WINDOW(warp_pointer_src_window);
3252 WINDOW(warp_pointer_dst_window);
3261 case X_SetInputFocus:
3268 case X_GetInputFocus:
3282 v16 = FIELD16(name_length);
3300 case X_QueryTextExtents:
3301 v8 = BOOL(odd_length);
3304 STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3312 v16 = FIELD16(pattern_length);
3313 STRING8(pattern, v16);
3317 case X_ListFontsWithInfo:
3321 v16 = FIELD16(pattern_length);
3322 STRING8(pattern, v16);
3329 v16 = CARD16(str_number_in_path);
3331 LISTofSTRING8(path, v16);
3340 case X_CreatePixmap:
3360 gcAttributes(tvb, offsetp, t, little_endian);
3367 gcAttributes(tvb, offsetp, t, little_endian);
3375 gcMask(tvb, offsetp, t, little_endian);
3382 CARD16(dash_offset);
3383 v16 = FIELD16(dashes_length);
3384 LISTofCARD8(dashes, v16);
3388 case X_SetClipRectangles:
3392 INT16(clip_x_origin);
3393 INT16(clip_y_origin);
3394 LISTofRECTANGLE(rectangles);
3416 DRAWABLE(src_drawable);
3417 DRAWABLE(dst_drawable);
3430 DRAWABLE(src_drawable);
3431 DRAWABLE(dst_drawable);
3443 ENUM8(coordinate_mode);
3444 v16 = REQUEST_LENGTH();
3447 LISTofPOINT(points, v16 - 12);
3451 ENUM8(coordinate_mode);
3452 v16 = REQUEST_LENGTH();
3455 LISTofPOINT(points, v16 - 12);
3463 LISTofSEGMENT(segments);
3466 case X_PolyRectangle:
3471 LISTofRECTANGLE(rectangles);
3484 v16 = REQUEST_LENGTH();
3488 ENUM8(coordinate_mode);
3490 LISTofPOINT(points, v16 - 16);
3493 case X_PolyFillRectangle:
3498 LISTofRECTANGLE(rectangles);
3510 ENUM8(image_format);
3511 v16 = REQUEST_LENGTH();
3521 LISTofBYTE(data, v16 - 24);
3526 ENUM8(image_pixmap_format);
3538 v16 = REQUEST_LENGTH();
3543 LISTofTEXTITEM8(items);
3549 v16 = REQUEST_LENGTH();
3554 LISTofTEXTITEM16(items);
3559 v8 = FIELD8(string_length);
3565 STRING8(string, v8);
3570 v8 = FIELD8(string_length);
3576 STRING16(string16, v8);
3580 case X_CreateColormap:
3588 case X_FreeColormap:
3594 case X_CopyColormapAndFree:
3601 case X_InstallColormap:
3607 case X_UninstallColormap:
3613 case X_ListInstalledColormaps:
3629 case X_AllocNamedColor:
3633 v16 = FIELD16(name_length);
3639 case X_AllocColorCells:
3647 case X_AllocColorPlanes:
3659 v16 = REQUEST_LENGTH();
3662 LISTofCARD32(pixels, v16 - 12);
3667 v16 = REQUEST_LENGTH();
3669 LISTofCOLORITEM(color_items, v16 - 8);
3672 case X_StoreNamedColor:
3677 v16 = FIELD16(name_length);
3685 v16 = REQUEST_LENGTH();
3687 LISTofCARD32(pixels, v16 - 8);
3694 v16 = FIELD16(name_length);
3700 case X_CreateCursor:
3704 PIXMAP(source_pixmap);
3716 case X_CreateGlyphCursor:
3722 CARD16(source_char);
3738 case X_RecolorCursor:
3750 case X_QueryBestSize:
3758 case X_QueryExtension:
3761 v16 = FIELD16(name_length);
3767 case X_ListExtensions:
3772 case X_ChangeKeyboardMapping:
3773 v8 = FIELD8(keycode_count);
3775 v8_2 = KEYCODE(first_keycode);
3776 v8_3 = FIELD8(keysyms_per_keycode);
3778 LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3781 case X_GetKeyboardMapping:
3784 state->request.GetKeyboardMapping.first_keycode
3785 = KEYCODE(first_keycode);
3790 case X_ChangeKeyboardControl:
3793 BITMASK32(keyboard_value);
3794 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3795 BITFIELD(INT8, keyboard_value_mask, bell_percent);
3796 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3797 BITFIELD(INT16, keyboard_value_mask, bell_duration);
3798 BITFIELD(INT16, keyboard_value_mask, led);
3799 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3800 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3801 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3805 case X_GetKeyboardControl:
3815 case X_ChangePointerControl:
3818 INT16(acceleration_numerator);
3819 INT16(acceleration_denominator);
3821 BOOL(do_acceleration);
3825 case X_GetPointerControl:
3830 case X_SetScreenSaver:
3835 ENUM8(prefer_blanking);
3836 ENUM8(allow_exposures);
3840 case X_GetScreenSaver:
3846 ENUM8(change_host_mode);
3850 v16 = CARD16(address_length);
3851 if (v8 == FAMILY_INTERNET && v16 == 4) {
3854 * XXX - what about IPv6? Is that a family of
3855 * FAMILY_INTERNET (0) with a length of 16?
3857 LISTofCARD8(ip_address, v16);
3859 LISTofCARD8(address, v16);
3867 case X_SetAccessControl:
3872 case X_SetCloseDownMode:
3873 ENUM8(close_down_mode);
3883 case X_RotateProperties:
3885 v16 = REQUEST_LENGTH();
3887 CARD16(property_number);
3889 LISTofATOM(properties, (v16 - 12));
3892 case X_ForceScreenSaver:
3893 ENUM8(screen_saver_mode);
3897 case X_SetPointerMapping:
3898 v8 = FIELD8(map_length);
3900 LISTofCARD8(map, v8);
3904 case X_GetPointerMapping:
3909 case X_SetModifierMapping:
3910 v8 = FIELD8(keycodes_per_modifier);
3912 LISTofKEYCODE(state->modifiermap, keycodes, v8);
3915 case X_GetModifierMapping:
3926 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3930 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
3933 volatile int offset = 0;
3934 int length_remaining;
3935 volatile gboolean little_endian;
3940 volatile gboolean is_initial_creq;
3941 guint16 auth_proto_len, auth_data_len;
3942 const char *volatile sep = NULL;
3943 conversation_t *conversation;
3944 x11_conv_data_t *state;
3948 while (tvb_reported_length_remaining(tvb, offset) != 0) {
3950 * We use "tvb_ensure_length_remaining()" to make sure there
3951 * actually *is* data remaining.
3953 * This means we're guaranteed that "length_remaining" is
3956 length_remaining = tvb_ensure_length_remaining(tvb, offset);
3959 * Can we do reassembly?
3961 if (x11_desegment && pinfo->can_desegment) {
3963 * Yes - is the X11 request header split across
3964 * segment boundaries?
3966 if (length_remaining < 4) {
3968 * Yes. Tell the TCP dissector where the data
3969 * for this message starts in the data it handed
3970 * us, and how many more bytes we need, and return.
3972 pinfo->desegment_offset = offset;
3973 pinfo->desegment_len = 4 - length_remaining;
3979 * Get the state for this conversation; create the conversation
3980 * if we don't have one, and create the state if we don't have
3983 conversation = find_conversation(&pinfo->src, &pinfo->dst,
3984 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3985 if (conversation == NULL) {
3989 conversation = conversation_new(&pinfo->src,
3990 &pinfo->dst, pinfo->ptype, pinfo->srcport,
3991 pinfo->destport, 0);
3995 * Is there state attached to this conversation?
3997 if ((state = conversation_get_proto_data(conversation, proto_x11))
3999 x11_stateinit(&state, conversation);
4002 * Guess the byte order if we don't already know it.
4004 little_endian = guess_byte_ordering(tvb, pinfo, state);
4007 * Get the opcode and length of the putative X11 request.
4009 opcode = VALUE8(tvb, 0);
4010 plen = VALUE16(tvb, offset + 2);
4014 * This can't be 0, as it includes the header length.
4015 * A different choice of byte order wouldn't have
4019 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4021 t = proto_item_add_subtree(ti, ett_x11);
4022 proto_tree_add_text(t, tvb, offset, -1,
4023 "Bogus request length (0)");
4027 if (state->iconn_frame == pinfo->fd->num ||
4028 (g_hash_table_lookup(state->seqtable,
4029 (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
4030 (opcode == 'B' || opcode == 'l') &&
4031 (plen == 11 || plen == 2816))) {
4035 * we saw this on the first pass and this is
4039 * we haven't already seen any requests, the first
4040 * byte of the message is 'B' or 'l', and the 16-bit
4041 * integer 2 bytes into the data stream is either 11
4042 * or a byte-swapped 11.
4044 * This means it's probably an initial connection
4045 * request, not a message.
4047 * 'B' is decimal 66, which is the opcode for a
4048 * PolySegment request; unfortunately, 11 is a valid
4049 * length for a PolySegment request request, so we
4050 * might mis-identify that request. (Are there any
4051 * other checks we can do?)
4053 * 'l' is decimal 108, which is the opcode for a
4054 * GetScreenSaver request; the only valid length
4055 * for that request is 1.
4057 is_initial_creq = TRUE;
4060 * We now know the byte order. Override the guess.
4062 if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4063 if (opcode == 'B') {
4067 state->byte_order = BYTE_ORDER_BE;
4068 little_endian = FALSE;
4073 state->byte_order = BYTE_ORDER_LE;
4074 little_endian = TRUE;
4079 * Can we do reassembly?
4081 if (x11_desegment && pinfo->can_desegment) {
4083 * Yes - is the fixed-length portion of the
4084 * initial connection header split across
4085 * segment boundaries?
4087 if (length_remaining < 10) {
4089 * Yes. Tell the TCP dissector where the
4090 * data for this message starts in the data
4091 * it handed us, and how many more bytes we
4094 pinfo->desegment_offset = offset;
4095 pinfo->desegment_len = 10 - length_remaining;
4101 * Get the lengths of the authorization protocol and
4102 * the authorization data.
4104 auth_proto_len = VALUE16(tvb, offset + 6);
4105 auth_data_len = VALUE16(tvb, offset + 8);
4106 plen = 12 + ROUND_LENGTH(auth_proto_len) +
4107 ROUND_LENGTH(auth_data_len);
4110 * This is probably an ordinary request.
4112 is_initial_creq = FALSE;
4115 * The length of a request is in 4-byte words.
4121 * Can we do reassembly?
4123 if (x11_desegment && pinfo->can_desegment) {
4125 * Yes - is the X11 request split across segment
4128 if (length_remaining < plen) {
4130 * Yes. Tell the TCP dissector where the data
4131 * for this message starts in the data it handed
4132 * us, and how many more bytes we need, and return.
4134 pinfo->desegment_offset = offset;
4135 pinfo->desegment_len = plen - length_remaining;
4141 * Construct a tvbuff containing the amount of the payload
4142 * we have available. Make its reported length the
4143 * amount of data in the X11 request.
4145 * XXX - if reassembly isn't enabled. the subdissector
4146 * will throw a BoundsError exception, rather than a
4147 * ReportedBoundsError exception. We really want a tvbuff
4148 * where the length is "length", the reported length is "plen",
4149 * and the "if the snapshot length were infinite" length is the
4150 * minimum of the reported length of the tvbuff handed to us
4151 * and "plen", with a new type of exception thrown if the offset
4152 * is within the reported length but beyond that third length,
4153 * with that exception getting the "Unreassembled Packet" error.
4155 length = length_remaining;
4158 next_tvb = tvb_new_subset(tvb, offset, length, plen);
4161 * Set the column appropriately.
4163 if (is_initial_creq) {
4164 if (check_col(pinfo->cinfo, COL_INFO))
4165 col_set_str(pinfo->cinfo, COL_INFO,
4166 "Initial connection request");
4170 * We haven't set the column yet; set it.
4172 if (check_col(pinfo->cinfo, COL_INFO))
4173 col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4176 * Initialize the separator.
4183 * Dissect the X11 request.
4185 * Catch the ReportedBoundsError exception; if this
4186 * particular message happens to get a ReportedBoundsError
4187 * exception, that doesn't mean that we should stop
4188 * dissecting X11 requests within this frame or chunk of
4191 * If it gets a BoundsError, we can stop, as there's nothing
4192 * more to see, so we just re-throw it.
4195 if (is_initial_creq) {
4196 dissect_x11_initial_conn(next_tvb, pinfo, tree,
4197 state, little_endian);
4199 dissect_x11_request(next_tvb, pinfo, tree, sep,
4200 state, little_endian);
4203 CATCH(BoundsError) {
4206 CATCH(ReportedBoundsError) {
4207 show_reported_bounds_error(tvb, pinfo, tree);
4212 * Skip the X11 message.
4221 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4223 static x11_conv_data_t stateinit;
4225 *state = g_mem_chunk_alloc(x11_state_chunk);
4226 **state = stateinit;
4228 (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4229 g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4230 (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4231 conversation_add_proto_data(conversation, proto_x11, *state);
4236 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4238 /* Set up structures we will need to add the protocol subtree and manage it */
4239 volatile int offset, plen;
4240 tvbuff_t * volatile next_tvb;
4241 conversation_t *conversation;
4242 x11_conv_data_t *state;
4243 gboolean little_endian;
4244 int length_remaining;
4245 const char *volatile sep = NULL;
4249 * Get the state for this conversation; create the conversation
4250 * if we don't have one, and create the state if we don't have
4253 conversation = find_conversation(&pinfo->src, &pinfo->dst,
4254 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4255 if (conversation == NULL) {
4259 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4260 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4264 * Is there state attached to this conversation?
4266 if ((state = conversation_get_proto_data(conversation, proto_x11))
4269 * No - create a state structure and attach it.
4271 x11_stateinit(&state, conversation);
4275 * Guess the byte order if we don't already know it.
4277 little_endian = guess_byte_ordering(tvb, pinfo, state);
4280 while (tvb_reported_length_remaining(tvb, offset) != 0) {
4282 * We use "tvb_ensure_length_remaining()" to make sure there
4283 * actually *is* data remaining.
4285 * This means we're guaranteed that "length_remaining" is
4288 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4291 * Can we do reassembly?
4293 if (x11_desegment && pinfo->can_desegment) {
4295 * Yes - is the X11 reply header split across
4296 * segment boundaries?
4298 if (length_remaining < 8) {
4300 * Yes. Tell the TCP dissector where the data
4301 * for this message starts in the data it handed
4302 * us, and how many more bytes we need, and
4305 pinfo->desegment_offset = offset;
4306 pinfo->desegment_len = 4 - length_remaining;
4312 * Find out what kind of a reply it is.
4313 * There are four possible:
4314 * - reply to initial connection
4315 * - errorreply (a request generated an error)
4316 * - requestreply (reply to a request)
4317 * - event (some event occured)
4319 if (g_hash_table_lookup(state->seqtable,
4320 (int *)state->sequencenumber) == (int *)INITIAL_CONN
4321 || (state->iconn_reply == pinfo->fd->num)) {
4323 * Either the connection is in the "initial
4324 * connection" state, or this frame is known
4325 * to have the initial connection reply.
4326 * That means this is the initial connection
4329 plen = 8 + VALUE16(tvb, offset + 6) * 4;
4331 HANDLE_REPLY(plen, length_remaining,
4332 "Initial connection reply",
4333 dissect_x11_initial_reply);
4336 * This isn't an initial connection reply
4337 * (XXX - unless we missed the initial
4338 * connection request). Look at the first
4339 * byte to determine what it is; errors
4340 * start with a byte of 0, replies start
4341 * with a byte of 1, events start with
4342 * a byte with of 2 or greater.
4344 switch (tvb_get_guint8(tvb, offset)) {
4348 HANDLE_REPLY(plen, length_remaining,
4349 "Error", dissect_x11_error);
4353 /* replylength is in units of four. */
4354 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4356 HANDLE_REPLY(plen, length_remaining,
4357 "Reply", dissect_x11_reply);
4363 HANDLE_REPLY(plen, length_remaining,
4364 "Event", dissect_x11_event);
4376 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4377 const char *volatile sep, x11_conv_data_t *volatile state,
4378 gboolean little_endian)
4380 int offset = 0, *offsetp = &offset, length, left, opcode;
4384 ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4385 tvb_reported_length_remaining(tvb, offset),
4387 t = proto_item_add_subtree(ti, ett_x11);
4391 * XXX - this doesn't work correctly if either
4393 * 1) the request sequence number wraps in the lower 16
4396 * 2) we don't see the initial connection request and thus
4397 * don't have the right sequence numbers;
4399 * 3) we don't have all the packets in the capture and
4400 * get out of sequence.
4402 * We might, instead, want to assume that a reply is a reply to
4403 * the most recent not-already-replied-to request in the same
4404 * connection. That also might mismatch replies to requests if
4405 * packets are lost, but there's nothing you can do to fix that.
4407 * XXX - if "opcode" is 0, we shouldn't say "Unknown opcode",
4408 * we should say that we don't have the request for the reply.
4410 opcode = (int)g_hash_table_lookup(state->seqtable,
4411 (int *)VALUE16(tvb, offset + 2));
4413 if (check_col(pinfo->cinfo, COL_INFO))
4414 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4417 * don't print opcode value since if it's
4418 * unknown, we didn't know to save the
4421 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
4423 proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
4424 opcode, val_to_str(opcode, opcode_vals,
4425 "<Unknown opcode %d>"));
4432 * Requests that expect a reply.
4435 case X_GetWindowAttributes:
4440 REPLYCONTENTS_COMMON();
4446 SEQUENCENUMBER_REPLY(sequencenumber);
4447 length = REPLYLENGTH(replylength);
4448 ATOM(get_property_type);
4449 CARD32(bytes_after);
4450 CARD32(valuelength);
4454 case X_ListProperties:
4455 case X_GetSelectionOwner:
4457 case X_GrabKeyboard:
4458 case X_QueryPointer:
4459 case X_GetMotionEvents:
4460 case X_TranslateCoords:
4461 REPLYCONTENTS_COMMON();
4466 case X_QueryTextExtents:
4469 case X_ListInstalledColormaps:
4473 case X_QueryBestSize:
4474 case X_QueryExtension:
4475 case X_ListExtensions:
4476 REPLYCONTENTS_COMMON();
4479 case X_GetKeyboardMapping:
4480 state->first_keycode
4481 = state->request.GetKeyboardMapping.first_keycode,
4483 state->keysyms_per_keycode
4484 = FIELD8(keysyms_per_keycode);
4485 SEQUENCENUMBER_REPLY(sequencenumber);
4486 length = REPLYLENGTH(replylength);
4488 LISTofKEYSYM(keysyms, state->keycodemap,
4489 state->request.GetKeyboardMapping.first_keycode,
4490 length / state->keysyms_per_keycode,
4491 state->keysyms_per_keycode);
4494 case X_GetKeyboardControl:
4495 case X_GetPointerControl:
4496 case X_GetScreenSaver:
4498 case X_SetPointerMapping:
4499 case X_GetPointerMapping:
4500 case X_SetModifierMapping:
4501 REPLYCONTENTS_COMMON();
4504 case X_GetModifierMapping:
4506 state->keycodes_per_modifier
4507 = FIELD8(keycodes_per_modifier);
4508 SEQUENCENUMBER_REPLY(sequencenumber);
4509 REPLYLENGTH(replylength);
4511 LISTofKEYCODE(state->modifiermap, keycodes,
4512 state->keycodes_per_modifier);
4516 REPLYCONTENTS_COMMON();
4519 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4524 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4525 const char *volatile sep, x11_conv_data_t *volatile state,
4526 gboolean little_endian)
4528 int offset = 0, *offsetp = &offset, left;
4529 unsigned char eventcode;
4533 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4534 t = proto_item_add_subtree(ti, ett_x11);
4536 eventcode = tvb_get_guint8(tvb, offset);
4538 if (check_col(pinfo->cinfo, COL_INFO))
4539 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4540 sep, val_to_str(eventcode, eventcode_vals,
4541 "<Unknown eventcode %u>"));
4543 proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4545 "eventcode: %d (%s)",
4547 val_to_str(eventcode, eventcode_vals,
4548 "<Unknown eventcode %u>"));
4551 proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
4552 eventcode, val_to_str(eventcode, eventcode_vals,
4553 "<Unknown eventcode %u>"));
4558 switch (eventcode) {
4563 /* need to do some prefetching here ... */
4564 code = VALUE8(tvb, offset);
4565 mask = VALUE16(tvb, 28);
4567 KEYCODE_DECODED(keycode, code, mask);
4568 CARD16(event_sequencenumber);
4569 EVENTCONTENTS_COMMON();
4577 BUTTON(eventbutton);
4578 CARD16(event_sequencenumber);
4579 EVENTCONTENTS_COMMON();
4586 CARD16(event_sequencenumber);
4587 EVENTCONTENTS_COMMON();
4595 CARD16(event_sequencenumber);
4596 EVENTCONTENTS_COMMON();
4604 case GraphicsExpose:
4606 case VisibilityNotify:
4612 case ReparentNotify:
4613 case ConfigureNotify:
4614 case ConfigureRequest:
4617 case CirculateNotify:
4618 case CirculateRequest:
4619 case PropertyNotify:
4620 case SelectionClear:
4621 case SelectionRequest:
4622 case SelectionNotify:
4623 case ColormapNotify:
4630 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4637 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4638 const char *volatile sep, x11_conv_data_t *volatile state _U_,
4639 gboolean little_endian)
4641 int offset = 0, *offsetp = &offset, left;
4642 unsigned char errorcode, error;
4646 ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4647 t = proto_item_add_subtree(ti, ett_x11);
4649 error = tvb_get_guint8(tvb, offset);
4652 errorcode = tvb_get_guint8(tvb, offset);
4653 if (check_col(pinfo->cinfo, COL_INFO))
4654 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4655 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
4657 proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
4659 "errorcode: %d (%s)",
4661 val_to_str(errorcode, errorcode_vals,
4662 "<Unknown errocode %u>"));
4665 proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
4666 errorcode, val_to_str(errorcode, errorcode_vals,
4667 "<Unknown errorcode %u>"));
4672 CARD16(error_sequencenumber);
4674 switch (errorcode) {
4676 CARD32(error_badvalue);
4683 CARD16(minor_opcode);
4684 CARD8(major_opcode);
4686 if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4692 /************************************************************************
4694 *** I N I T I A L I Z A T I O N A N D M A I N ***
4696 ************************************************************************/
4699 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4701 if (check_col(pinfo->cinfo, COL_PROTOCOL))
4702 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
4704 if (pinfo->match_port == pinfo->srcport)
4705 dissect_x11_replies(tvb, pinfo, tree);
4707 dissect_x11_requests(tvb, pinfo, tree);
4710 /* Register the protocol with Ethereal */
4711 void proto_register_x11(void)
4714 /* Setup list of header fields */
4715 static hf_register_info hf[] = {
4717 { &hf_x11_FIELDABBREV,
4718 { "FIELDNAME", "x11.FIELDABBREV",
4719 FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
4720 "FIELDDESCR", HFILL }
4723 #include "x11-register-info.h"
4726 /* Setup protocol subtree array */
4727 static gint *ett[] = {
4729 &ett_x11_color_flags,
4730 &ett_x11_list_of_arc,
4732 &ett_x11_list_of_atom,
4733 &ett_x11_list_of_card32,
4734 &ett_x11_list_of_color_item,
4735 &ett_x11_color_item,
4736 &ett_x11_list_of_keycode,
4737 &ett_x11_list_of_keysyms,
4739 &ett_x11_list_of_point,
4741 &ett_x11_list_of_rectangle,
4743 &ett_x11_list_of_segment,
4745 &ett_x11_list_of_string8,
4746 &ett_x11_list_of_text_item,
4748 &ett_x11_gc_value_mask,
4749 &ett_x11_event_mask,
4750 &ett_x11_do_not_propagate_mask,
4751 &ett_x11_set_of_key_mask,
4752 &ett_x11_pointer_event_mask,
4753 &ett_x11_window_value_mask,
4754 &ett_x11_configure_window_mask,
4755 &ett_x11_keyboard_value_mask,
4757 module_t *x11_module;
4759 /* Register the protocol name and description */
4760 proto_x11 = proto_register_protocol("X11", "X11", "x11");
4762 /* Required function calls to register the header fields and subtrees used */
4763 proto_register_field_array(proto_x11, hf, array_length(hf));
4764 proto_register_subtree_array(ett, array_length(ett));
4766 register_init_routine(x11_init_protocol);
4768 x11_module = prefs_register_protocol(proto_x11, NULL);
4769 prefs_register_bool_preference(x11_module, "desegment",
4770 "Desegment all X11 messages spanning multiple TCP segments",
4771 "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
4776 proto_reg_handoff_x11(void)
4778 dissector_handle_t x11_handle;
4780 x11_handle = create_dissector_handle(dissect_x11, proto_x11);
4781 dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
4782 dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
4783 dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
4784 data_handle = find_dissector("data");