* Routines for X11 dissection
* Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
*
- * $Id: packet-x11.c,v 1.34 2002/04/13 20:16:09 guy Exp $
+ * $Id: packet-x11.c,v 1.41 2002/04/17 08:33:08 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
/* TODO (in no particular order):
*
- * - keep track of Atom creation by server to be able to display non predefined atoms
+ * - keep track of Atom creation by server to be able to display
+ * non-predefined atoms
* - Idem for keysym <-> keycode ???
* - Idem for fonts
- * - Subtree the request ids (that is x11.create-window.window and x11.change-window.window should be
- * distinct), and add hidden fields (so we still have x11.window).
- * - add hidden fields so we can have x11.circulate-window in addition to x11.opcode == 13
+ * - Subtree the request ids (that is x11.create-window.window and
+ * x11.change-window.window should be distinct), and add hidden fields
+ * (so we still have x11.window).
+ * - add hidden fields so we can have x11.circulate-window in addition to
+ * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
+ * now)
* - add hidden fields so we have x11.listOfStuff.length
* - use a faster scheme that linear list searching for the opcode.
- * - correct display of unicode chars.
- * - Not everything is homogeneous, in particular the handling of items in list is a total mess.
+ * - correct display of Unicode chars.
+ * - Not everything is homogeneous, in particular the handling of items in
+ * list is a total mess.
*/
/* By the way, I wrote a program to generate every request and test
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "prefs.h"
+#include "packet-frame.h"
#define cVALS(x) (const value_string*)(x)
/* Initialize the subtree pointers */
static gint ett_x11 = -1;
-static gint ett_x11_request = -1;
static gint ett_x11_color_flags = -1;
static gint ett_x11_list_of_arc = -1;
static gint ett_x11_arc = -1;
static gint ett_x11_configure_window_mask = -1;
static gint ett_x11_keyboard_value_mask = -1;
+/* desegmentation of X11 messages */
+static gboolean x11_desegment = TRUE;
+
static dissector_handle_t data_handle;
#define TCP_PORT_X11 6000
#define TCP_PORT_X11_2 6001
#define TCP_PORT_X11_3 6002
+/*
+ * Round a length to a multiple of 4 bytes.
+ */
+#define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
+
/************************************************************************
*** ***
*** E N U M T A B L E S D E F I N I T I O N S ***
*** ***
************************************************************************/
+static const value_string byte_order_vals[] = {
+ { 'B', "Big-endian" },
+ { 'l', "Little-endian" },
+ { 0, NULL }
+};
+
static const value_string access_mode_vals[] = {
{ 0, "Disable" },
{ 1, "Enable" },
{ 0, NULL }
};
+#define FAMILY_INTERNET 0
+#define FAMILY_DECNET 1
+#define FAMILY_CHAOS 2
+
static const value_string family_vals[] = {
- { 0, "Internet" },
- { 1, "DECnet" },
- { 2, "Chaos" },
+ { FAMILY_INTERNET, "Internet" },
+ { FAMILY_DECNET, "DECnet" },
+ { FAMILY_CHAOS, "Chaos" },
{ 0, NULL }
};
*** ***
************************************************************************/
-static int next_offset = 0; /* Offset of the next request in the frame */
static gboolean little_endian = TRUE;
-static struct maskStruct {
- guint32 _value;
- int _offset;
- int _zone;
- proto_tree *_tree;
-} lastMask = { 0, 0, 0, NULL };
-
/************************************************************************
*** ***
*** F I E L D D E C O D I N G M A C R O S ***
#define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name))
#define BITFIELD(TYPE, position, name) {\
- if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
- int unused;\
- int save = *offsetp;\
- proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
- lastMask._zone, little_endian); \
+ int unused;\
+ int save = *offsetp;\
+ proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
+ bitmask_size, little_endian); \
+ if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
TYPE(name);\
unused = save + 4 - *offsetp;\
if (unused)\
}
#define FLAG(position, name) {\
- if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
- proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
+ proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
+
+#define FLAG_IF_NONZERO(position, name) {\
+ if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
+ proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
#define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name); }
#define BITGRAVITY(name) { gravity(tvb, offsetp, t, #name, hf_x11_##name, "Forget"); }
-#define BITMASK8(name) { bitmask(tvb, offsetp, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 1); }
-#define BITMASK16(name) { bitmask(tvb, offsetp, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 2); }
-#define BITMASK32(name) { bitmask(tvb, offsetp, t, hf_x11_##name##_mask, ett_x11_##name##_mask, 4); }
+#define BITMASK(name, size) {\
+ proto_item *ti; \
+ guint32 bitmask_value; \
+ int bitmask_offset; \
+ int bitmask_size; \
+ proto_tree *bitmask_tree; \
+ bitmask_value = ((size == 1) ? VALUE8(tvb, *offsetp) : \
+ ((size == 2) ? VALUE16(tvb, *offsetp) : \
+ VALUE32(tvb, *offsetp))); \
+ bitmask_offset = *offsetp; \
+ bitmask_size = size; \
+ ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
+ bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
+ *offsetp += size;
+#define ENDBITMASK }
+#define BITMASK8(name) BITMASK(name, 1);
+#define BITMASK16(name) BITMASK(name, 2);
+#define BITMASK32(name) BITMASK(name, 4);
#define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
#define BUTTON(name) { FIELD8(name); }
#define CARD8(name) { FIELD8(name); }
#define COLORMAP(name) { FIELD32(name); }
#define CURSOR(name) { FIELD32(name); }
#define DRAWABLE(name) { FIELD32(name); }
-#define ENUM8(name) { FIELD8(name); }
+#define ENUM8(name) (FIELD8(name))
#define ENUM16(name) { FIELD16(name); }
#define FONT(name) { FIELD32(name); }
#define FONTABLE(name) { FIELD32(name); }
#define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
#define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
#define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length)); }
-#define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE); }
-#define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE); }
+#define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset); }
+#define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset); }
#define OPCODE() { opcode = FIELD8(opcode); }
#define PIXMAP(name) { FIELD32(name); }
#define REQUEST_LENGTH() (requestLength(tvb, offsetp, t))
*offsetp += 4;
}
-static void bitmask(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf, int ett,
- int size)
-{
- proto_item *ti;
-
- lastMask._value = size == 2 ? VALUE16(tvb, *offsetp) : VALUE32(tvb, *offsetp);
- lastMask._offset = *offsetp;
- lastMask._zone = size;
- ti = proto_tree_add_uint(t, hf, tvb, *offsetp, size, lastMask._value);
- lastMask._tree = proto_item_add_subtree(ti, ett);
- *offsetp += size;
-}
-
static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
{
guint32 v = VALUE8(tvb, *offsetp);
{
proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
- while(length--) {
- if (*offsetp + 4 > next_offset) {
- /* List runs past end of message. */
- return;
- }
+ while(length--)
atom(tvb, offsetp, tt, hf_x11_properties_item);
- }
}
static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
int length)
{
- if (*offsetp + length > next_offset) {
- /* List runs past end of message. */
- length = next_offset - *offsetp;
- }
if (length <= 0) length = 1;
proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
*offsetp += length;
proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
while(length--) {
- if (*offsetp + 4 > next_offset) {
- /* List runs past end of message. */
- return;
- }
proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
*offsetp += 4;
}
char *bp;
const char *sep;
- if (*offsetp + 12 > next_offset) {
- /* List runs past end of message. */
- return;
- }
red = VALUE16(tvb, *offsetp + 4);
green = VALUE16(tvb, *offsetp + 6);
blue = VALUE16(tvb, *offsetp + 8);
const char **m;
int i;
- if (*offsetp + 8 > next_offset) {
- /* List runs past end of message. */
- return;
- }
for(i = 8, m = modifiers; i; i--, m++) {
u_char c = tvb_get_guint8(tvb, *offsetp);
*offsetp += 1;
proto_item *tti;
proto_tree *ttt;
int i;
- char buffer[128];
- char *bp;
while(keycode_count--) {
- if (*offsetp + keysyms_per_keycode * 4 > next_offset) {
- /* List runs past end of message. */
- return;
- }
- bp = buffer + sprintf(buffer, "keysyms:");
- for(i = 0; i < keysyms_per_keycode; i++) {
- bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, *offsetp + i * 4)));
- }
- *bp = '\0';
tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp, keysyms_per_keycode * 4,
- "%s", buffer);
+ "keysyms:");
ttt = proto_item_add_subtree(tti, ett_x11_keysym);
for(i = keysyms_per_keycode; i; i--) {
guint32 v = VALUE32(tvb, *offsetp);
+ proto_item_append_text(tti, " %s", keysymString(v));
proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, *offsetp, 4, v,
"keysym: 0x%08x (%s)", v, keysymString(v));
*offsetp += 4;
proto_item *tti;
proto_tree *ttt;
- if (*offsetp + 4 > next_offset) {
- /* List runs past end of message. */
- return;
- }
x = VALUE16(tvb, *offsetp);
y = VALUE16(tvb, *offsetp + 2);
proto_item *tti;
proto_tree *ttt;
- if (*offsetp + 8 > next_offset) {
- /* List runs past end of message. */
- return;
- }
x = VALUE16(tvb, *offsetp);
y = VALUE16(tvb, *offsetp + 2);
width = VALUE16(tvb, *offsetp + 4);
proto_item *tti;
proto_tree *ttt;
- if (*offsetp + 8 > next_offset) {
- /* List runs past end of message. */
- return;
- }
x1 = VALUE16(tvb, *offsetp);
y1 = VALUE16(tvb, *offsetp + 2);
x2 = VALUE16(tvb, *offsetp + 4);
ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
while(length--) {
unsigned l = VALUE8(tvb, *offsetp);
if (allocated < (l + 1)) {
proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
*offsetp += l + 1;
}
- g_free(s);
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
}
#define STRING16_MAX_DISPLAYED_LENGTH 150
}
static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
- int sizeIs16)
+ int sizeIs16, int next_offset)
{
int allocated = 0;
char *s = NULL;
ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
while(n--) {
unsigned l = VALUE8(tvb, *offsetp);
if (l == 255) { /* Item is a font */
*offsetp += l + 2;
}
}
- g_free(s);
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
}
static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
if (hfi -> strings)
enumValue = match_strval(v, cVALS(hfi -> strings));
if (enumValue)
- proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
+ hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
+ nameAsChar, v, enumValue);
else
proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
*offsetp += 1;
if (hfi -> strings)
enumValue = match_strval(v, cVALS(hfi -> strings));
if (enumValue)
- proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
+ hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
+ nameAsChar, v, enumValue);
else
proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
BITFIELD(CARD16, gc_value_mask, dash_offset);
BITFIELD(CARD8, gc_value_mask, gc_dashes);
BITFIELD(ENUM8, gc_value_mask, arc_mode);
+ ENDBITMASK;
}
static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
FLAG(gc_value, dash_offset);
FLAG(gc_value, gc_dashes);
FLAG(gc_value, arc_mode);
+ ENDBITMASK;
}
static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t)
static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
{
- struct maskStruct save = lastMask;
BITMASK32(event);
FLAG(event, KeyPress);
FLAG(event, KeyRelease);
FLAG(event, PropertyChange);
FLAG(event, ColormapChange);
FLAG(event, OwnerGrabButton);
- FLAG(event, erroneous_bits);
- lastMask = save;
+ FLAG_IF_NONZERO(event, erroneous_bits);
+ ENDBITMASK;
}
static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
{
- struct maskStruct save = lastMask;
BITMASK32(do_not_propagate);
FLAG(do_not_propagate, KeyPress);
FLAG(do_not_propagate, KeyRelease);
FLAG(do_not_propagate, Button4Motion);
FLAG(do_not_propagate, Button5Motion);
FLAG(do_not_propagate, ButtonMotion);
- FLAG(do_not_propagate, erroneous_bits);
- lastMask = save;
+ FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
+ ENDBITMASK;
}
static void setOfKeyMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
{
- struct maskStruct save = lastMask;
proto_item *ti;
-
- lastMask._value = VALUE16(tvb, *offsetp);
- lastMask._offset = *offsetp;
- lastMask._zone = 2;
- if (lastMask._value == 0x8000)
+ guint32 bitmask_value;
+ int bitmask_offset;
+ int bitmask_size;
+ proto_tree *bitmask_tree;
+
+ bitmask_value = VALUE16(tvb, *offsetp);
+ bitmask_offset = *offsetp;
+ bitmask_size = 2;
+ if (bitmask_value == 0x8000)
proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
"modifiers-masks: 0x8000 (AnyModifier)");
else {
ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
- lastMask._value);
- lastMask._tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
+ bitmask_value);
+ bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
FLAG(modifiers, Shift);
FLAG(modifiers, Lock);
FLAG(modifiers, Control);
FLAG(modifiers, Mod3);
FLAG(modifiers, Mod4);
FLAG(modifiers, Mod5);
- FLAG(modifiers, erroneous_bits);
+ FLAG_IF_NONZERO(modifiers, erroneous_bits);
}
- lastMask = save;
*offsetp += 2;
}
static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
{
- struct maskStruct save = lastMask;
BITMASK16(pointer_event);
FLAG(pointer_event, ButtonPress);
FLAG(pointer_event, ButtonRelease);
FLAG(pointer_event, Button5Motion);
FLAG(pointer_event, ButtonMotion);
FLAG(pointer_event, KeymapState);
- FLAG(pointer_event, erroneous_bits);
- lastMask = save;
+ FLAG_IF_NONZERO(pointer_event, erroneous_bits);
+ ENDBITMASK;
}
static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
{
char *s = g_malloc(length + 1);
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
stringCopy(s, tvb_get_ptr(tvb, *offsetp, length), length);
proto_tree_add_string_format(t, hf, tvb, *offsetp, length, s, "%s: %s", nameAsChar, s);
- g_free(s);
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
*offsetp += length;
}
char *s = NULL;
unsigned l = 0;
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
length += length;
string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length, &s, &l);
- g_free(s);
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
*offsetp += length;
}
BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
BITFIELD(COLORMAP, window_value_mask, colormap);
BITFIELD(CURSOR, window_value_mask, cursor);
+ ENDBITMASK;
}
-/************************************************************************
- *** ***
- *** D E C O D I N G O N E P A C K E T ***
- *** ***
- ************************************************************************/
+/*
+ * Data structure associated with a conversation; keeps track of the
+ * request for which we're expecting a reply, the frame number of
+ * the initial connection request, and the byte order of the connection.
+ *
+ * An opcode of -3 means we haven't yet seen any requests yet.
+ * An opcode of -2 means we're not expecting a reply.
+ * An opcode of -1 means means we're waiting for a reply to the initial
+ * connection request.
+ * Other values are the opcode of the request for which we're expecting
+ * a reply.
+ *
+ * XXX - assumes only one outstanding request is awaiting a reply,
+ * which should always be the case.
+ */
+#define NOTHING_SEEN -3
+#define NOTHING_EXPECTED -2
+#define INITIAL_CONN -1
-static int dissect_x11_request_loop(tvbuff_t *tvb, int *offsetp, proto_tree *root)
-{
- int left = tvb_reported_length(tvb), nextLeft;
- proto_item *ti;
- proto_tree *t;
- guint8 v8, v8_2;
- guint16 v16;
- guint32 v32;
+#define BYTE_ORDER_BE 0
+#define BYTE_ORDER_LE 1
+#define BYTE_ORDER_UNKNOWN -1
- /* The X11 data stream to the server is just a sequence of requests,
- each of which contains a length; for now, we dissect all the
- requests in this frame until we run out of data in the frame.
- Eventually, we should handle requests that cross frame
- boundaries.
-
- Note that "in this frame" refers to everything in the frame
- as it appeared in the wire, not as it was captured; we want
- an exception to be thrown if we go past the end of the
- captured data in the frame without going past the end of the
- data in the frame. */
- for(;;) {
- int length, opcode;
-
- /* fprintf(stderr, "Starting loop, left = %d, *offsetp = %d\n", left, *offsetp); */
- if (left < 4) {
- /* We ran out of data - we don't have enough data in
- the frame to get the length of this request. */
- break;
- }
- length = VALUE16(tvb, *offsetp + 2) * 4;
- /* fprintf(stderr, "length = %d\n", length);*/
- if (left < length) {
- /* We ran out of data - we don't have enough data in
- the frame for the full request. */
- break;
- }
- if (length < 4) {
- /* Bogus message length? */
- break;
- }
+typedef struct {
+ int opcode; /* opcode for which we're awaiting a reply */
+ guint32 iconn_frame; /* frame # of initial connection request */
+ int byte_order; /* byte order of connection */
+} x11_conv_data_t;
- next_offset = *offsetp + length;
- nextLeft = left - length;
-
- ti = proto_tree_add_uint(root, hf_x11_request, tvb, *offsetp, length, tvb_get_guint8(tvb, *offsetp));
- t = proto_item_add_subtree(ti, ett_x11_request);
-
- OPCODE();
-
- switch(opcode) {
- case 1: /* CreateWindow */
- CARD8(depth);
- REQUEST_LENGTH();
- WINDOW(wid);
- WINDOW(parent);
- INT16(x);
- INT16(y);
- CARD16(width);
- CARD16(height);
- CARD16(border_width);
- ENUM16(window_class);
- VISUALID(visual);
- windowAttributes(tvb, offsetp, t);
- break;
-
- case 2: /* ChangeWindowAttributes */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- windowAttributes(tvb, offsetp, t);
- break;
-
- case 3: /* GetWindowAttributes */
- case 4: /* DestroyWindow */
- case 5: /* DestroySubwindows */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 6: /* ChangeSaveSet */
- ENUM8(save_set_mode);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 7: /* ReparentWindow */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- WINDOW(parent);
- INT16(x);
- INT16(y);
- break;
-
- case 8: /* MapWindow */
- case 9: /* MapSubWindow */
- case 10: /* UnmapWindow */
- case 11: /* UnmapSubwindows */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 12: /* ConfigureWindow */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- BITMASK16(configure_window);
- UNUSED(2);
- BITFIELD(INT16, configure_window_mask, x);
- BITFIELD(INT16, configure_window_mask, y);
- BITFIELD(CARD16, configure_window_mask, width);
- BITFIELD(CARD16, configure_window_mask, height);
- BITFIELD(CARD16, configure_window_mask, border_width);
- BITFIELD(WINDOW, configure_window_mask, sibling);
- BITFIELD(ENUM8, configure_window_mask, stack_mode);
- PAD();
- break;
-
- case 13: /* CirculateWindow */
- ENUM8(direction);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 14: /* GetGeometry */
- case 15: /* QueryTree */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- break;
-
- case 16: /* InternAtom */
- BOOL(only_if_exists);
- REQUEST_LENGTH();
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 17: /* GetAtomName */
- UNUSED(1);
- REQUEST_LENGTH();
- ATOM(atom);
- break;
-
- case 18: /* ChangeProperty */
- ENUM8(mode);
- REQUEST_LENGTH();
- WINDOW(window);
- ATOM(property);
- ATOM(type);
- CARD8(format);
- UNUSED(3);
- v32 = CARD32(data_length);
- LISTofBYTE(data, v32);
- PAD();
- break;
-
- case 19: /* DeleteProperty */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- ATOM(property);
- break;
-
- case 20: /* GetProperty */
- BOOL(delete);
- REQUEST_LENGTH();
- WINDOW(window);
- ATOM(property);
- ATOM(get_property_type);
- CARD32(long_offset);
- CARD32(long_length);
- break;
-
- case 21: /* ListProperties */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 22: /* SetSelectionOwner */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(owner);
- ATOM(selection);
- TIMESTAMP(time);
- break;
-
- case 23: /* GetSelectionOwner */
- UNUSED(1);
- REQUEST_LENGTH();
- ATOM(selection);
- break;
-
- case 24: /* ConvertSelection */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(requestor);
- ATOM(selection);
- ATOM(target);
- ATOM(property);
- TIMESTAMP(time);
- break;
-
- case 26: /* GrabPointer */
- BOOL(owner_events);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- SETofPOINTEREVENT(pointer_event_mask);
- ENUM8(pointer_mode);
- ENUM8(keyboard_mode);
- WINDOW(confine_to);
- CURSOR(cursor);
- TIMESTAMP(time);
- break;
-
- case 27: /* UngrabPointer */
- UNUSED(1);
- REQUEST_LENGTH();
- TIMESTAMP(time);
- break;
-
- case 28: /* GrabButton */
- BOOL(owner_events);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- SETofPOINTEREVENT(event_mask);
- ENUM8(pointer_mode);
- ENUM8(keyboard_mode);
- WINDOW(confine_to);
- CURSOR(cursor);
- BUTTON(button);
- UNUSED(1);
- SETofKEYMASK(modifiers);
- break;
-
- case 29: /* UngrabButton */
- BUTTON(button);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- SETofKEYMASK(modifiers);
- UNUSED(2);
- break;
-
- case 30: /* ChangeActivePointerGrab */
- UNUSED(1);
- REQUEST_LENGTH();
- CURSOR(cursor);
- TIMESTAMP(time);
- SETofPOINTEREVENT(event_mask);
- UNUSED(2);
- break;
-
- case 31: /* GrabKeyboard */
- BOOL(owner_events);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- TIMESTAMP(time);
- ENUM8(pointer_mode);
- ENUM8(keyboard_mode);
- UNUSED(2);
- break;
-
- case 32: /* UngrabKeyboard */
- UNUSED(1);
- REQUEST_LENGTH();
- TIMESTAMP(time);
- break;
-
- case 33: /* GrabKey */
- BOOL(owner_events);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- SETofKEYMASK(modifiers);
- KEYCODE(key);
- ENUM8(pointer_mode);
- ENUM8(keyboard_mode);
- UNUSED(3);
- break;
-
- case 34: /* UngrabKey */
- KEYCODE(key);
- REQUEST_LENGTH();
- WINDOW(grab_window);
- SETofKEYMASK(modifiers);
- UNUSED(2);
- break;
-
- case 35: /* AllowEvents */
- ENUM8(allow_events_mode);
- REQUEST_LENGTH();
- TIMESTAMP(time);
- break;
-
- case 36: /* GrabServer */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 37: /* UngrabServer */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 38: /* QueryPointer */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 39: /* GetMotionEvents */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- TIMESTAMP(start);
- TIMESTAMP(stop);
- break;
-
- case 40: /* TranslateCoordinates */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(src_window);
- WINDOW(dst_window);
- INT16(src_x);
- INT16(src_y);
- break;
-
- case 41: /* WarpPointer */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(warp_pointer_src_window);
- WINDOW(warp_pointer_dst_window);
- INT16(src_x);
- INT16(src_y);
- CARD16(src_width);
- CARD16(src_height);
- INT16(dst_x);
- INT16(dst_y);
- break;
-
- case 42: /* SetInputFocus */
- ENUM8(revert_to);
- REQUEST_LENGTH();
- WINDOW(focus);
- TIMESTAMP(time);
- break;
-
- case 43: /* GetInputFocus */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 44: /* QueryKeymap */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 45: /* OpenFont */
- UNUSED(1);
- REQUEST_LENGTH();
- FONT(fid);
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 46: /* CloseFont */
- UNUSED(1);
- REQUEST_LENGTH();
- FONT(font);
- break;
-
- case 47: /* QueryFont */
- UNUSED(1);
- REQUEST_LENGTH();
- FONTABLE(font);
- break;
-
- case 48: /* QueryTextExtents */
- v8 = BOOL(odd_length);
- REQUEST_LENGTH();
- FONTABLE(font);
- STRING16(string16, (next_offset - *offsetp - (v8 ? 2 : 0)) / 2);
- PAD();
- break;
-
- case 49: /* ListFonts */
- UNUSED(1);
- REQUEST_LENGTH();
- CARD16(max_names);
- v16 = FIELD16(pattern_length);
- STRING8(pattern, v16);
- PAD();
- break;
-
- case 50: /* ListFontsWithInfo */
- UNUSED(1);
- REQUEST_LENGTH();
- CARD16(max_names);
- v16 = FIELD16(pattern_length);
- STRING8(pattern, v16);
- PAD();
- break;
-
- case 51: /* SetFontPath */
- UNUSED(1);
- REQUEST_LENGTH();
- v16 = CARD16(str_number_in_path);
- UNUSED(2);
- LISTofSTRING8(path, v16);
- PAD();
- break;
-
- case 52: /* GetFontPath */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 53: /* CreatePixmap */
- CARD8(depth);
- REQUEST_LENGTH();
- PIXMAP(pid);
- DRAWABLE(drawable);
- CARD16(width);
- CARD16(height);
- break;
-
- case 54: /* FreePixmap */
- UNUSED(1);
- REQUEST_LENGTH();
- PIXMAP(pixmap);
- break;
-
- case 55: /* CreateGC */
- UNUSED(1);
- REQUEST_LENGTH();
- GCONTEXT(cid);
- DRAWABLE(drawable);
- gcAttributes(tvb, offsetp, t);
- break;
-
- case 56: /* ChangeGC */
- UNUSED(1);
- REQUEST_LENGTH();
- GCONTEXT(gc);
- gcAttributes(tvb, offsetp, t);
- break;
-
- case 57: /* CopyGC */
- UNUSED(1);
- REQUEST_LENGTH();
- GCONTEXT(src_gc);
- GCONTEXT(dst_gc);
- gcMask(tvb, offsetp, t);
- break;
-
- case 58: /* SetDashes */
- UNUSED(1);
- REQUEST_LENGTH();
- GCONTEXT(gc);
- CARD16(dash_offset);
- v16 = FIELD16(dashes_length);
- LISTofCARD8(dashes, v16);
- PAD();
- break;
-
- case 59: /* SetClipRectangles */
- ENUM8(ordering);
- REQUEST_LENGTH();
- GCONTEXT(gc);
- INT16(clip_x_origin);
- INT16(clip_y_origin);
- LISTofRECTANGLE(rectangles);
- break;
-
- case 60: /* FreeGC */
- UNUSED(1);
- REQUEST_LENGTH();
- GCONTEXT(gc);
- break;
-
- case 61: /* ClearArea */
- BOOL(exposures);
- REQUEST_LENGTH();
- WINDOW(window);
- INT16(x);
- INT16(y);
- CARD16(width);
- CARD16(height);
- break;
-
- case 62: /* CopyArea */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(src_drawable);
- DRAWABLE(dst_drawable);
- GCONTEXT(gc);
- INT16(src_x);
- INT16(src_y);
- INT16(dst_x);
- INT16(dst_y);
- CARD16(width);
- CARD16(height);
- break;
-
- case 63: /* CopyPlane */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(src_drawable);
- DRAWABLE(dst_drawable);
- GCONTEXT(gc);
- INT16(src_x);
- INT16(src_y);
- INT16(dst_x);
- INT16(dst_y);
- CARD16(width);
- CARD16(height);
- CARD32(bit_plane);
- break;
-
- case 64: /* PolyPoint */
- ENUM8(coordinate_mode);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofPOINT(points, v16 - 12);
- break;
-
- case 65: /* PolyLine */
- ENUM8(coordinate_mode);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofPOINT(points, v16 - 12);
- break;
-
- case 66: /* PolySegment */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofSEGMENT(segments);
- break;
-
- case 67: /* PolyRectangle */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofRECTANGLE(rectangles);
- break;
-
- case 68: /* PolyArc */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofARC(arcs);
- break;
-
- case 69: /* FillPoly */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- ENUM8(shape);
- ENUM8(coordinate_mode);
- UNUSED(2);
- LISTofPOINT(points, v16 - 16);
- break;
-
- case 70: /* PolyFillRectangle */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofRECTANGLE(rectangles);
- break;
-
- case 71: /* PolyFillArc */
- UNUSED(1);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- LISTofARC(arcs);
- break;
-
- case 72: /* PutImage */
- ENUM8(image_format);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- CARD16(width);
- CARD16(height);
- INT16(dst_x);
- INT16(dst_y);
- CARD8(left_pad);
- CARD8(depth);
- UNUSED(2);
- LISTofBYTE(data, v16 - 24);
- PAD();
- break;
-
- case 73: /* GetImage */
- ENUM8(image_pixmap_format);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- INT16(x);
- INT16(y);
- CARD16(width);
- CARD16(height);
- CARD32(plane_mask);
- break;
-
- case 74: /* PolyText8 */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- INT16(x);
- INT16(y);
- LISTofTEXTITEM8(items);
- PAD();
- break;
-
- case 75: /* PolyText16 */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- INT16(x);
- INT16(y);
- LISTofTEXTITEM16(items);
- PAD();
- break;
-
- case 76: /* ImageText8 */
- v8 = FIELD8(string_length);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- INT16(x);
- INT16(y);
- STRING8(string, v8);
- PAD();
- break;
-
- case 77: /* ImageText16 */
- v8 = FIELD8(string_length);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- GCONTEXT(gc);
- INT16(x);
- INT16(y);
- STRING16(string16, v8);
- PAD();
- break;
-
- case 78: /* CreateColormap */
- ENUM8(alloc);
- REQUEST_LENGTH();
- COLORMAP(mid);
- WINDOW(window);
- VISUALID(visual);
- break;
-
- case 79: /* FreeColormap */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- break;
-
- case 80: /* CopyColormapAndFree */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(mid);
- COLORMAP(src_cmap);
- break;
-
- case 81: /* InstallColormap */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- break;
-
- case 82: /* UninstallColormap */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- break;
-
- case 83: /* ListInstalledColormaps */
- UNUSED(1);
- REQUEST_LENGTH();
- WINDOW(window);
- break;
-
- case 84: /* AllocColor */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- CARD16(red);
- CARD16(green);
- CARD16(blue);
- UNUSED(2);
- break;
-
- case 85: /* AllocNamedColor */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 86: /* AllocColorCells */
- BOOL(contiguous);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- CARD16(colors);
- CARD16(planes);
- break;
-
- case 87: /* AllocColorPlanes */
- BOOL(contiguous);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- CARD16(colors);
- CARD16(reds);
- CARD16(greens);
- CARD16(blues);
- break;
-
- case 88: /* FreeColors */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- COLORMAP(cmap);
- CARD32(plane_mask);
- LISTofCARD32(pixels, v16 - 12);
- break;
-
- case 89: /* StoreColors */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- COLORMAP(cmap);
- LISTofCOLORITEM(color_items, v16 - 8);
- break;
-
- case 90: /* StoreNamedColor */
- COLOR_FLAGS(color);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- CARD32(pixel);
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 91: /* QueryColors */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- COLORMAP(cmap);
- LISTofCARD32(pixels, v16 - 8);
- break;
-
- case 92: /* LookupColor */
- UNUSED(1);
- REQUEST_LENGTH();
- COLORMAP(cmap);
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 93: /* CreateCursor */
- UNUSED(1);
- REQUEST_LENGTH();
- CURSOR(cid);
- PIXMAP(source_pixmap);
- PIXMAP(mask);
- CARD16(fore_red);
- CARD16(fore_green);
- CARD16(fore_blue);
- CARD16(back_red);
- CARD16(back_green);
- CARD16(back_blue);
- CARD16(x);
- CARD16(y);
- break;
-
- case 94: /* CreateGlyphCursor */
- UNUSED(1);
- REQUEST_LENGTH();
- CURSOR(cid);
- FONT(source_font);
- FONT(mask_font);
- CARD16(source_char);
- CARD16(mask_char);
- CARD16(fore_red);
- CARD16(fore_green);
- CARD16(fore_blue);
- CARD16(back_red);
- CARD16(back_green);
- CARD16(back_blue);
- break;
-
- case 95: /* FreeCursor */
- UNUSED(1);
- REQUEST_LENGTH();
- CURSOR(cursor);
- break;
-
- case 96: /* RecolorCursor */
- UNUSED(1);
- REQUEST_LENGTH();
- CURSOR(cursor);
- CARD16(fore_red);
- CARD16(fore_green);
- CARD16(fore_blue);
- CARD16(back_red);
- CARD16(back_green);
- CARD16(back_blue);
- break;
-
- case 97: /* QueryBestSize */
- ENUM8(class);
- REQUEST_LENGTH();
- DRAWABLE(drawable);
- CARD16(width);
- CARD16(height);
- break;
-
- case 98: /* QueryExtension */
- UNUSED(1);
- REQUEST_LENGTH();
- v16 = FIELD16(name_length);
- UNUSED(2);
- STRING8(name, v16);
- PAD();
- break;
-
- case 99: /* ListExtensions */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 100: /* ChangeKeyboardMapping */
- v8 = FIELD8(keycode_count);
- REQUEST_LENGTH();
- KEYCODE(first_keycode);
- v8_2 = FIELD8(keysyms_per_keycode);
- UNUSED(2);
- LISTofKEYSYM(keysyms, v8, v8_2);
- break;
-
- case 101: /* GetKeyboardMapping */
- UNUSED(1);
- REQUEST_LENGTH();
- KEYCODE(first_keycode);
- FIELD8(count);
- UNUSED(2);
- break;
-
- case 102: /* ChangeKeyboardControl */
- UNUSED(1);
- REQUEST_LENGTH();
- BITMASK32(keyboard_value);
- BITFIELD(INT8, keyboard_value_mask, key_click_percent);
- BITFIELD(INT8, keyboard_value_mask, bell_percent);
- BITFIELD(INT16, keyboard_value_mask, bell_pitch);
- BITFIELD(INT16, keyboard_value_mask, bell_duration);
- BITFIELD(INT16, keyboard_value_mask, led);
- BITFIELD(ENUM8, keyboard_value_mask, led_mode);
- BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
- BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
- break;
-
- case 103: /* GetKeyboardControl */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 104: /* Bell */
- INT8(percent);
- REQUEST_LENGTH();
- break;
-
- case 105: /* ChangePointerControl */
- UNUSED(1);
- REQUEST_LENGTH();
- INT16(acceleration_numerator);
- INT16(acceleration_denominator);
- INT16(threshold);
- BOOL(do_acceleration);
- BOOL(do_threshold);
- break;
-
- case 106: /* GetPointerControl */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 107: /* SetScreenSaver */
- UNUSED(1);
- REQUEST_LENGTH();
- INT16(timeout);
- INT16(interval);
- ENUM8(prefer_blanking);
- ENUM8(allow_exposures);
- UNUSED(2);
- break;
-
- case 108: /* GetScreenSaver */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 109: /* ChangeHosts */
- ENUM8(change_host_mode);
- REQUEST_LENGTH();
- ENUM8(family);
- UNUSED(1);
- v16 = CARD16(address_length);
- LISTofCARD8(address, v16);
- break;
-
- case 110: /* ListHosts */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 111: /* SetAccessControl */
- ENUM8(access_mode);
- REQUEST_LENGTH();
- break;
-
- case 112: /* SetCloseDownMode */
- ENUM8(close_down_mode);
- REQUEST_LENGTH();
- break;
-
- case 113: /* KillClient */
- UNUSED(1);
- REQUEST_LENGTH();
- CARD32(resource);
- break;
-
- case 114: /* RotateProperties */
- UNUSED(1);
- v16 = REQUEST_LENGTH();
- WINDOW(window);
- CARD16(property_number);
- INT16(delta);
- LISTofATOM(properties, (v16 - 12));
- break;
-
- case 115: /* ForceScreenSaver */
- ENUM8(screen_saver_mode);
- REQUEST_LENGTH();
- break;
-
- case 116: /* SetPointerMapping */
- v8 = FIELD8(map_length);
- REQUEST_LENGTH();
- LISTofCARD8(map, v8);
- PAD();
- break;
-
- case 117: /* GetPointerMapping */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 118: /* SetModifierMapping */
- v8 = FIELD8(keycodes_per_modifier);
- REQUEST_LENGTH();
- LISTofKEYCODE(keycodes, v8);
- break;
-
- case 119: /* GetModifierMapping */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
-
- case 127: /* NoOperation */
- UNUSED(1);
- REQUEST_LENGTH();
- break;
- }
- if (*offsetp < next_offset)
- proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, next_offset - *offsetp, little_endian);
- *offsetp = next_offset;
- left = nextLeft;
- }
+static GMemChunk *x11_state_chunk = NULL;
+
+static void x11_init_protocol(void)
+{
+ if (x11_state_chunk != NULL)
+ g_mem_chunk_destroy(x11_state_chunk);
- return left;
+ x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
+ sizeof (x11_conv_data_t),
+ 128 * sizeof (x11_conv_data_t),
+ G_ALLOC_ONLY);
}
/************************************************************************
*** ***
************************************************************************/
-static GTree *byte_ordering_cache = NULL;
-static GMemChunk *address_chunk = NULL;
-static GMemChunk *ipv4_chunk = NULL;
-static GMemChunk *ipv6_chunk = NULL;
-
-static gint compareAddresses(gconstpointer aa, gconstpointer bb)
-{
- const address *a = (const address *)aa;
- const address *b = (const address *)bb;
- int c = b -> type - a -> type;
- if (c) return c;
- c = b -> len - a -> len;
- if (c) return c;
- return memcmp(b -> data, a -> data, a -> len);
-}
-
/* If we can't guess, we return TRUE (that is little_endian), cause
I'm developing on a Linux box :-). The (non-)guess isn't cached
however, so we may have more luck next time. I'm quite conservative
started in a previous packet...
*/
-int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
-int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
+static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
{
int res = 0;
while(maskLength--) {
}
static gboolean
-guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
+guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
+ x11_conv_data_t *state_info)
{
/* With X the client gives the byte ordering for the protocol,
and the port on the server tells us we're speaking X. */
int le, be, decision, decisionToCache;
- gboolean is_reply = (pinfo->srcport == pinfo->match_port);
- address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
- gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
- if (cache) return cache > 0 ? TRUE : FALSE;
- if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
+ if (state_info->byte_order == BYTE_ORDER_BE)
+ return FALSE; /* known to be big-endian */
+ else if (state_info->byte_order == BYTE_ORDER_LE)
+ return TRUE; /* known to be little-endian */
+
+ if (pinfo->srcport == pinfo->match_port) {
+ /*
+ * This is a reply or event; we don't try to guess the
+ * byte order on it for now.
+ */
+ return TRUE;
+ }
le = x_endian_match(tvb, tvb_get_letohs);
be = x_endian_match(tvb, tvb_get_ntohs);
decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
if (decisionToCache) {
- /* We encode the decision as 1 for TRUE and -1 for FALSE
- to be able to distinguish between FALSE and no value in
- the cache when recalling the value.
- */
- int address_length;
- char *address_data;
- address *cached;
- if (addr -> type == AT_IPv4) {
- address_length = 4;
- address_data = g_mem_chunk_alloc(ipv4_chunk);
- } else if (addr -> type == AT_IPv6) {
- address_length = 16;
- address_data = g_mem_chunk_alloc(ipv6_chunk);
- } else {
- address_length = addr -> len;
- address_data = g_malloc(address_length);
- }
- cached = g_mem_chunk_alloc(address_chunk);
- memcpy(address_data, addr -> data, address_length);
- SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
- g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
+ /*
+ * Remember the decision.
+ */
+ state_info->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
}
/*
/************************************************************************
*** ***
- *** I N I T I A L I Z A T I O N A N D M A I N ***
+ *** D E C O D I N G O N E P A C K E T ***
*** ***
************************************************************************/
-static void
-dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+/*
+ * Decode an initial connection request.
+ */
+static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, x11_conv_data_t *state_info)
{
-/* Set up structures we will need to add the protocol subtree and manage it */
+ int offset = 0;
+ int *offsetp = &offset;
proto_item *ti;
- proto_tree *x11_tree;
- int offset;
- int left;
-
-/* This field shows up as the "Info" column in the display; you should make
- it, if possible, summarize what's in the packet, so that a user looking
- at the list of packets can tell what type of packet it is. */
+ proto_tree *t;
+ guint16 auth_proto_name_length, auth_proto_data_length;
+ gint left;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ CARD8(byte_order);
+ UNUSED(1);
+ CARD16(protocol_major_version);
+ CARD16(protocol_minor_version);
+ auth_proto_name_length = CARD16(authorization_protocol_name_length);
+ auth_proto_data_length = CARD16(authorization_protocol_data_length);
+ UNUSED(2);
+ if (auth_proto_name_length != 0) {
+ STRING8(authorization_protocol_name, auth_proto_name_length);
+ offset = ROUND_LENGTH(offset);
+ }
+ if (auth_proto_data_length != 0) {
+ STRING8(authorization_protocol_data, auth_proto_data_length);
+ offset = ROUND_LENGTH(offset);
+ }
+ left = tvb_length_remaining(tvb, offset);
+ if (left)
+ proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
+
+ /*
+ * This is the initial connection request...
+ */
+ state_info->iconn_frame = pinfo->fd->num;
+
+ /*
+ * ...and we're expecting a reply to it.
+ */
+ state_info->opcode = INITIAL_CONN;
+}
+
+static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, const char *sep, x11_conv_data_t *state_info)
+{
+ int offset = 0;
+ int *offsetp = &offset;
+ int next_offset;
+ proto_item *ti;
+ proto_tree *t;
+ int length, opcode;
+ guint8 v8, v8_2;
+ guint16 v16;
+ guint32 v32;
+ gint left;
+
+ length = VALUE16(tvb, 2) * 4;
+
+ if (length < 4) {
+ /* Bogus message length? */
+ return;
+ }
+
+ next_offset = offset + length;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ OPCODE();
+
if (check_col(pinfo->cinfo, COL_INFO))
- col_set_str(pinfo->cinfo, COL_INFO, "X11 request");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
+ val_to_str(opcode, opcode_vals, "Unknown (%u)"));
+
+ /*
+ * Does this request expect a reply?
+ */
+ switch(opcode) {
+
+ case 3: /* GetWindowAttributes */
+ case 14: /* GetGeometry */
+ case 15: /* QueryTree */
+ case 16: /* InternAtom */
+ case 17: /* GetAtomName */
+ case 20: /* GetProperty */
+ case 21: /* ListProperties */
+ case 23: /* GetSelectionOwner */
+ case 26: /* GrabPointer */
+ case 31: /* GrabKeyboard */
+ case 38: /* QueryPointer */
+ case 39: /* GetMotionEvents */
+ case 40: /* TranslateCoordinates */
+ case 44: /* QueryKeymap */
+ case 47: /* QueryFont */
+ case 48: /* QueryTextExtents */
+ case 49: /* ListFonts */
+ case 73: /* GetImage */
+ case 83: /* ListInstalledColormaps */
+ case 84: /* AllocColor */
+ case 91: /* QueryColors */
+ case 92: /* LookupColor */
+ case 97: /* QueryBestSize */
+ case 98: /* QueryExtension */
+ case 99: /* ListExtensions */
+ case 101: /* GetKeyboardMapping */
+ case 103: /* GetKeyboardControl */
+ case 106: /* GetPointerControl */
+ case 108: /* GetScreenSaver */
+ case 110: /* ListHosts */
+ case 116: /* SetPointerMapping */
+ case 117: /* GetPointerMapping */
+ case 118: /* SetModifierMapping */
+ case 119: /* GetModifierMapping */
+ /*
+ * Those requests expect a reply.
+ */
+ state_info->opcode = opcode;
+ break;
+
+ default:
+ /*
+ * No reply is expected from any other request.
+ */
+ state_info->opcode = NOTHING_EXPECTED;
+ break;
+ }
-/* In the interest of speed, if "tree" is NULL, don't do any work not
- necessary to generate protocol tree items. */
if (!tree) return;
- ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
- x11_tree = proto_item_add_subtree(ti, ett_x11);
- offset = 0;
- little_endian = guess_byte_ordering(tvb, pinfo);
- left = dissect_x11_request_loop(tvb, &offset, x11_tree);
+ switch(opcode) {
+
+ case 1: /* CreateWindow */
+ CARD8(depth);
+ REQUEST_LENGTH();
+ WINDOW(wid);
+ WINDOW(parent);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(border_width);
+ ENUM16(window_class);
+ VISUALID(visual);
+ windowAttributes(tvb, offsetp, t);
+ break;
+
+ case 2: /* ChangeWindowAttributes */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ windowAttributes(tvb, offsetp, t);
+ break;
+
+ case 3: /* GetWindowAttributes */
+ case 4: /* DestroyWindow */
+ case 5: /* DestroySubwindows */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 6: /* ChangeSaveSet */
+ ENUM8(save_set_mode);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 7: /* ReparentWindow */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ WINDOW(parent);
+ INT16(x);
+ INT16(y);
+ break;
+
+ case 8: /* MapWindow */
+ case 9: /* MapSubWindow */
+ case 10: /* UnmapWindow */
+ case 11: /* UnmapSubwindows */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 12: /* ConfigureWindow */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ BITMASK16(configure_window);
+ UNUSED(2);
+ BITFIELD(INT16, configure_window_mask, x);
+ BITFIELD(INT16, configure_window_mask, y);
+ BITFIELD(CARD16, configure_window_mask, width);
+ BITFIELD(CARD16, configure_window_mask, height);
+ BITFIELD(CARD16, configure_window_mask, border_width);
+ BITFIELD(WINDOW, configure_window_mask, sibling);
+ BITFIELD(ENUM8, configure_window_mask, stack_mode);
+ ENDBITMASK;
+ PAD();
+ break;
+
+ case 13: /* CirculateWindow */
+ ENUM8(direction);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 14: /* GetGeometry */
+ case 15: /* QueryTree */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ break;
+
+ case 16: /* InternAtom */
+ BOOL(only_if_exists);
+ REQUEST_LENGTH();
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 17: /* GetAtomName */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ ATOM(atom);
+ break;
+
+ case 18: /* ChangeProperty */
+ ENUM8(mode);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ ATOM(type);
+ CARD8(format);
+ UNUSED(3);
+ v32 = CARD32(data_length);
+ LISTofBYTE(data, v32);
+ PAD();
+ break;
+
+ case 19: /* DeleteProperty */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ break;
+
+ case 20: /* GetProperty */
+ BOOL(delete);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ ATOM(get_property_type);
+ CARD32(long_offset);
+ CARD32(long_length);
+ break;
+
+ case 21: /* ListProperties */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 22: /* SetSelectionOwner */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(owner);
+ ATOM(selection);
+ TIMESTAMP(time);
+ break;
+
+ case 23: /* GetSelectionOwner */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ ATOM(selection);
+ break;
+
+ case 24: /* ConvertSelection */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(requestor);
+ ATOM(selection);
+ ATOM(target);
+ ATOM(property);
+ TIMESTAMP(time);
+ break;
+
+ case 26: /* GrabPointer */
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofPOINTEREVENT(pointer_event_mask);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ WINDOW(confine_to);
+ CURSOR(cursor);
+ TIMESTAMP(time);
+ break;
+
+ case 27: /* UngrabPointer */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case 28: /* GrabButton */
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofPOINTEREVENT(event_mask);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ WINDOW(confine_to);
+ CURSOR(cursor);
+ BUTTON(button);
+ UNUSED(1);
+ SETofKEYMASK(modifiers);
+ break;
+
+ case 29: /* UngrabButton */
+ BUTTON(button);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ UNUSED(2);
+ break;
+
+ case 30: /* ChangeActivePointerGrab */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ TIMESTAMP(time);
+ SETofPOINTEREVENT(event_mask);
+ UNUSED(2);
+ break;
+
+ case 31: /* GrabKeyboard */
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ TIMESTAMP(time);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ UNUSED(2);
+ break;
+
+ case 32: /* UngrabKeyboard */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case 33: /* GrabKey */
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ KEYCODE(key);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ UNUSED(3);
+ break;
+
+ case 34: /* UngrabKey */
+ KEYCODE(key);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ UNUSED(2);
+ break;
+
+ case 35: /* AllowEvents */
+ ENUM8(allow_events_mode);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case 36: /* GrabServer */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 37: /* UngrabServer */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 38: /* QueryPointer */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 39: /* GetMotionEvents */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ TIMESTAMP(start);
+ TIMESTAMP(stop);
+ break;
+
+ case 40: /* TranslateCoordinates */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(src_window);
+ WINDOW(dst_window);
+ INT16(src_x);
+ INT16(src_y);
+ break;
+
+ case 41: /* WarpPointer */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(warp_pointer_src_window);
+ WINDOW(warp_pointer_dst_window);
+ INT16(src_x);
+ INT16(src_y);
+ CARD16(src_width);
+ CARD16(src_height);
+ INT16(dst_x);
+ INT16(dst_y);
+ break;
+
+ case 42: /* SetInputFocus */
+ ENUM8(revert_to);
+ REQUEST_LENGTH();
+ WINDOW(focus);
+ TIMESTAMP(time);
+ break;
+
+ case 43: /* GetInputFocus */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 44: /* QueryKeymap */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 45: /* OpenFont */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONT(fid);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 46: /* CloseFont */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONT(font);
+ break;
+
+ case 47: /* QueryFont */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONTABLE(font);
+ break;
+
+ case 48: /* QueryTextExtents */
+ v8 = BOOL(odd_length);
+ REQUEST_LENGTH();
+ FONTABLE(font);
+ STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
+ PAD();
+ break;
+
+ case 49: /* ListFonts */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD16(max_names);
+ v16 = FIELD16(pattern_length);
+ STRING8(pattern, v16);
+ PAD();
+ break;
+
+ case 50: /* ListFontsWithInfo */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD16(max_names);
+ v16 = FIELD16(pattern_length);
+ STRING8(pattern, v16);
+ PAD();
+ break;
+
+ case 51: /* SetFontPath */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ v16 = CARD16(str_number_in_path);
+ UNUSED(2);
+ LISTofSTRING8(path, v16);
+ PAD();
+ break;
+
+ case 52: /* GetFontPath */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 53: /* CreatePixmap */
+ CARD8(depth);
+ REQUEST_LENGTH();
+ PIXMAP(pid);
+ DRAWABLE(drawable);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case 54: /* FreePixmap */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ PIXMAP(pixmap);
+ break;
+
+ case 55: /* CreateGC */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(cid);
+ DRAWABLE(drawable);
+ gcAttributes(tvb, offsetp, t);
+ break;
+
+ case 56: /* ChangeGC */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ gcAttributes(tvb, offsetp, t);
+ break;
+
+ case 57: /* CopyGC */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(src_gc);
+ GCONTEXT(dst_gc);
+ gcMask(tvb, offsetp, t);
+ break;
+
+ case 58: /* SetDashes */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ CARD16(dash_offset);
+ v16 = FIELD16(dashes_length);
+ LISTofCARD8(dashes, v16);
+ PAD();
+ break;
+
+ case 59: /* SetClipRectangles */
+ ENUM8(ordering);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ INT16(clip_x_origin);
+ INT16(clip_y_origin);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case 60: /* FreeGC */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ break;
+
+ case 61: /* ClearArea */
+ BOOL(exposures);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case 62: /* CopyArea */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(src_drawable);
+ DRAWABLE(dst_drawable);
+ GCONTEXT(gc);
+ INT16(src_x);
+ INT16(src_y);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case 63: /* CopyPlane */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(src_drawable);
+ DRAWABLE(dst_drawable);
+ GCONTEXT(gc);
+ INT16(src_x);
+ INT16(src_y);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD16(width);
+ CARD16(height);
+ CARD32(bit_plane);
+ break;
+
+ case 64: /* PolyPoint */
+ ENUM8(coordinate_mode);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofPOINT(points, v16 - 12);
+ break;
+
+ case 65: /* PolyLine */
+ ENUM8(coordinate_mode);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofPOINT(points, v16 - 12);
+ break;
+
+ case 66: /* PolySegment */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofSEGMENT(segments);
+ break;
+
+ case 67: /* PolyRectangle */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case 68: /* PolyArc */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofARC(arcs);
+ break;
+
+ case 69: /* FillPoly */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ ENUM8(shape);
+ ENUM8(coordinate_mode);
+ UNUSED(2);
+ LISTofPOINT(points, v16 - 16);
+ break;
+
+ case 70: /* PolyFillRectangle */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case 71: /* PolyFillArc */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofARC(arcs);
+ break;
+
+ case 72: /* PutImage */
+ ENUM8(image_format);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ CARD16(width);
+ CARD16(height);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD8(left_pad);
+ CARD8(depth);
+ UNUSED(2);
+ LISTofBYTE(data, v16 - 24);
+ PAD();
+ break;
+
+ case 73: /* GetImage */
+ ENUM8(image_pixmap_format);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD32(plane_mask);
+ break;
+
+ case 74: /* PolyText8 */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ LISTofTEXTITEM8(items);
+ PAD();
+ break;
+
+ case 75: /* PolyText16 */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ LISTofTEXTITEM16(items);
+ PAD();
+ break;
+
+ case 76: /* ImageText8 */
+ v8 = FIELD8(string_length);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ STRING8(string, v8);
+ PAD();
+ break;
+
+ case 77: /* ImageText16 */
+ v8 = FIELD8(string_length);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ STRING16(string16, v8);
+ PAD();
+ break;
+
+ case 78: /* CreateColormap */
+ ENUM8(alloc);
+ REQUEST_LENGTH();
+ COLORMAP(mid);
+ WINDOW(window);
+ VISUALID(visual);
+ break;
+
+ case 79: /* FreeColormap */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case 80: /* CopyColormapAndFree */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(mid);
+ COLORMAP(src_cmap);
+ break;
+
+ case 81: /* InstallColormap */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case 82: /* UninstallColormap */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case 83: /* ListInstalledColormaps */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case 84: /* AllocColor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(red);
+ CARD16(green);
+ CARD16(blue);
+ UNUSED(2);
+ break;
+
+ case 85: /* AllocNamedColor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 86: /* AllocColorCells */
+ BOOL(contiguous);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(colors);
+ CARD16(planes);
+ break;
+
+ case 87: /* AllocColorPlanes */
+ BOOL(contiguous);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(colors);
+ CARD16(reds);
+ CARD16(greens);
+ CARD16(blues);
+ break;
+
+ case 88: /* FreeColors */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD32(plane_mask);
+ LISTofCARD32(pixels, v16 - 12);
+ break;
+
+ case 89: /* StoreColors */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ LISTofCOLORITEM(color_items, v16 - 8);
+ break;
+
+ case 90: /* StoreNamedColor */
+ COLOR_FLAGS(color);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD32(pixel);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 91: /* QueryColors */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ LISTofCARD32(pixels, v16 - 8);
+ break;
+
+ case 92: /* LookupColor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 93: /* CreateCursor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cid);
+ PIXMAP(source_pixmap);
+ PIXMAP(mask);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ CARD16(x);
+ CARD16(y);
+ break;
+
+ case 94: /* CreateGlyphCursor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cid);
+ FONT(source_font);
+ FONT(mask_font);
+ CARD16(source_char);
+ CARD16(mask_char);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ break;
+
+ case 95: /* FreeCursor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ break;
+
+ case 96: /* RecolorCursor */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ break;
+
+ case 97: /* QueryBestSize */
+ ENUM8(class);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case 98: /* QueryExtension */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case 99: /* ListExtensions */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 100: /* ChangeKeyboardMapping */
+ v8 = FIELD8(keycode_count);
+ REQUEST_LENGTH();
+ KEYCODE(first_keycode);
+ v8_2 = FIELD8(keysyms_per_keycode);
+ UNUSED(2);
+ LISTofKEYSYM(keysyms, v8, v8_2);
+ break;
+
+ case 101: /* GetKeyboardMapping */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ KEYCODE(first_keycode);
+ FIELD8(count);
+ UNUSED(2);
+ break;
+
+ case 102: /* ChangeKeyboardControl */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ BITMASK32(keyboard_value);
+ BITFIELD(INT8, keyboard_value_mask, key_click_percent);
+ BITFIELD(INT8, keyboard_value_mask, bell_percent);
+ BITFIELD(INT16, keyboard_value_mask, bell_pitch);
+ BITFIELD(INT16, keyboard_value_mask, bell_duration);
+ BITFIELD(INT16, keyboard_value_mask, led);
+ BITFIELD(ENUM8, keyboard_value_mask, led_mode);
+ BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
+ BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
+ ENDBITMASK;
+ break;
+
+ case 103: /* GetKeyboardControl */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 104: /* Bell */
+ INT8(percent);
+ REQUEST_LENGTH();
+ break;
+
+ case 105: /* ChangePointerControl */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ INT16(acceleration_numerator);
+ INT16(acceleration_denominator);
+ INT16(threshold);
+ BOOL(do_acceleration);
+ BOOL(do_threshold);
+ break;
+
+ case 106: /* GetPointerControl */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 107: /* SetScreenSaver */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ INT16(timeout);
+ INT16(interval);
+ ENUM8(prefer_blanking);
+ ENUM8(allow_exposures);
+ UNUSED(2);
+ break;
+
+ case 108: /* GetScreenSaver */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 109: /* ChangeHosts */
+ ENUM8(change_host_mode);
+ REQUEST_LENGTH();
+ v8 = ENUM8(family);
+ UNUSED(1);
+ v16 = CARD16(address_length);
+ if (v8 == FAMILY_INTERNET && v16 == 4) {
+ /*
+ * IPv4 addresses.
+ * XXX - what about IPv6? Is that a family of
+ * FAMILY_INTERNET (0) with a length of 16?
+ */
+ LISTofCARD8(ip_address, v16);
+ } else
+ LISTofCARD8(address, v16);
+ break;
+
+ case 110: /* ListHosts */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 111: /* SetAccessControl */
+ ENUM8(access_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case 112: /* SetCloseDownMode */
+ ENUM8(close_down_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case 113: /* KillClient */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD32(resource);
+ break;
+
+ case 114: /* RotateProperties */
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ WINDOW(window);
+ CARD16(property_number);
+ INT16(delta);
+ LISTofATOM(properties, (v16 - 12));
+ break;
+
+ case 115: /* ForceScreenSaver */
+ ENUM8(screen_saver_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case 116: /* SetPointerMapping */
+ v8 = FIELD8(map_length);
+ REQUEST_LENGTH();
+ LISTofCARD8(map, v8);
+ PAD();
+ break;
+
+ case 117: /* GetPointerMapping */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 118: /* SetModifierMapping */
+ v8 = FIELD8(keycodes_per_modifier);
+ REQUEST_LENGTH();
+ LISTofKEYCODE(keycodes, v8);
+ break;
+
+ case 119: /* GetModifierMapping */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case 127: /* NoOperation */
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+ }
+ left = tvb_length_remaining(tvb, offset);
if (left)
- call_dissector(data_handle, tvb_new_subset(tvb, offset,-1, tvb_reported_length_remaining(tvb, offset)), pinfo, x11_tree);
+ proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
+}
+
+static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ volatile int offset = 0;
+ int length_remaining;
+ guint8 opcode;
+ volatile int plen;
+ proto_item *ti;
+ proto_tree *t;
+ volatile gboolean is_initial_creq;
+ guint16 auth_proto_len, auth_data_len;
+ const char *volatile sep = NULL;
+ conversation_t *conversation;
+ x11_conv_data_t *volatile state_info;
+ int byte_order;
+ int length;
+ tvbuff_t *next_tvb;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the X11 request header split across
+ * segment boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the state for this conversation; create the conversation
+ * if we don't have one, and create the state if we don't have
+ * any.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ /*
+ * No - create one.
+ */
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+
+ /*
+ * Is there state attached to this conversation?
+ */
+ state_info = conversation_get_proto_data(conversation, proto_x11);
+ if (state_info == NULL) {
+ /*
+ * No - create a state structure and attach it.
+ */
+ state_info = g_mem_chunk_alloc(x11_state_chunk);
+ state_info->opcode = NOTHING_SEEN; /* nothing seen yet */
+ state_info->iconn_frame = 0; /* don't know it yet */
+ state_info->byte_order = BYTE_ORDER_UNKNOWN; /* don't know it yet */
+ conversation_add_proto_data(conversation, proto_x11,
+ state_info);
+ }
+
+ /*
+ * Guess the byte order if we don't already know it.
+ */
+ little_endian = guess_byte_ordering(tvb, pinfo, state_info);
+
+ /*
+ * Get the opcode and length of the putative X11 request.
+ */
+ opcode = VALUE8(tvb, 0);
+ plen = VALUE16(tvb, offset + 2);
+
+ if (plen == 0) {
+ /*
+ * This can't be 0, as it includes the header length.
+ * A different choice of byte order wouldn't have
+ * helped.
+ * Give up.
+ */
+ ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+ proto_tree_add_text(t, tvb, offset, -1, "Bogus request length (0)");
+ return;
+ }
+
+ if (state_info->iconn_frame == pinfo->fd->num ||
+ (state_info->opcode == NOTHING_SEEN &&
+ (opcode == 'B' || opcode == 'l') &&
+ (plen == 11 || plen == 2816))) {
+ /*
+ * Either
+ *
+ * we saw this on the first pass and this is
+ * it again
+ *
+ * or
+ * we haven't already seen any requests, the first
+ * byte of the message is 'B' or 'l', and the 16-bit
+ * integer 2 bytes into the data stream is either 11
+ * or a byte-swapped 11.
+ *
+ * This means it's probably an initial connection
+ * request, not a message.
+ *
+ * 'B' is decimal 66, which is the opcode for a
+ * PolySegment request; unfortunately, 11 is a valid
+ * length for a PolySegment request request, so we
+ * might mis-identify that request. (Are there any
+ * other checks we can do?)
+ *
+ * 'l' is decimal 108, which is the opcode for a
+ * GetScreenSaver request; the only valid length
+ * for that request is 1.
+ */
+ is_initial_creq = TRUE;
+
+ /*
+ * We now know the byte order. Override the guess.
+ */
+ if (state_info->byte_order == BYTE_ORDER_UNKNOWN) {
+ if (opcode == 'B') {
+ /*
+ * Big-endian.
+ */
+ state_info->byte_order = BYTE_ORDER_BE;
+ little_endian = FALSE;
+ } else {
+ /*
+ * Little-endian.
+ */
+ state_info->byte_order = BYTE_ORDER_LE;
+ little_endian = TRUE;
+ }
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the fixed-length portion of the
+ * initial connection header split across
+ * segment boundaries?
+ */
+ if (length_remaining < 10) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 10 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the lengths of the authorization protocol and
+ * the authorization data.
+ */
+ auth_proto_len = VALUE16(tvb, offset + 6);
+ auth_data_len = VALUE16(tvb, offset + 8);
+ plen = 12 + ROUND_LENGTH(auth_proto_len) +
+ ROUND_LENGTH(auth_data_len);
+ } else {
+ /*
+ * This is probably an ordinary request.
+ */
+ is_initial_creq = FALSE;
+
+ /*
+ * The length of a request is in 4-byte words.
+ */
+ plen *= 4;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the X11 request split across segment
+ * boundaries?
+ */
+ if (length_remaining < plen) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the
+ * amount of data in the X11 request.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector
+ * will throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want a tvbuff
+ * where the length is "length", the reported length is "plen",
+ * and the "if the snapshot length were infinite" length is the
+ * minimum of the reported length of the tvbuff handed to us
+ * and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length,
+ * with that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > plen)
+ length = plen;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen);
+
+ /*
+ * Set the column appropriately.
+ */
+ if (is_initial_creq) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Initial connection request");
+ } else {
+ if (sep == NULL) {
+ /*
+ * We haven't set the column yet; set it.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "Requests");
+
+ /*
+ * Initialize the separator.
+ */
+ sep = ":";
+ }
+ }
+
+ /*
+ * Dissect the X11 request.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting X11 requests within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ if (is_initial_creq) {
+ dissect_x11_initial_conn(next_tvb, pinfo, tree,
+ state_info);
+ } else {
+ dissect_x11_request(next_tvb, pinfo, tree, sep,
+ state_info);
+ }
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Skip the X11 message.
+ */
+ offset += plen;
+
+ sep = ",";
+ }
}
static void
-dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures we will need to add the protocol subtree and manage it */
proto_item *ti;
it, if possible, summarize what's in the packet, so that a user looking
at the list of packets can tell what type of packet it is. */
if (check_col(pinfo->cinfo, COL_INFO))
- col_set_str(pinfo->cinfo, COL_INFO, "X11 event");
+ col_set_str(pinfo->cinfo, COL_INFO, "Replies/events");
/* In the interest of speed, if "tree" is NULL, don't do any work not
necessary to generate protocol tree items. */
- if (tree) {
- ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
- x11_tree = proto_item_add_subtree(ti, ett_x11);
-
-/* Code to process the packet goes here */
+ if (!tree) return;
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ x11_tree = proto_item_add_subtree(ti, ett_x11);
- call_dissector(data_handle,tvb, pinfo, x11_tree);
- }
+ /*
+ * XXX - dissect these in a loop, like the requests.
+ */
+ call_dissector(data_handle,tvb, pinfo, x11_tree);
}
+/************************************************************************
+ *** ***
+ *** I N I T I A L I Z A T I O N A N D M A I N ***
+ *** ***
+ ************************************************************************/
+
static void
dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
if (pinfo->match_port == pinfo->destport)
- dissect_x11_request(tvb, pinfo, tree);
+ dissect_x11_requests(tvb, pinfo, tree);
else
- dissect_x11_event(tvb, pinfo, tree);
+ dissect_x11_replies(tvb, pinfo, tree);
}
/* Register the protocol with Ethereal */
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_x11,
- &ett_x11_request,
&ett_x11_color_flags,
&ett_x11_list_of_arc,
&ett_x11_arc,
&ett_x11_configure_window_mask,
&ett_x11_keyboard_value_mask,
};
+ module_t *x11_module;
/* Register the protocol name and description */
proto_x11 = proto_register_protocol("X11", "X11", "x11");
proto_register_field_array(proto_x11, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- byte_ordering_cache = g_tree_new(compareAddresses);
- address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address),
- sizeof(address) * 128, G_ALLOC_ONLY);
- ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
- ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
-};
+ register_init_routine(x11_init_protocol);
+ x11_module = prefs_register_protocol(proto_x11, NULL);
+ prefs_register_bool_preference(x11_module, "desegment",
+ "Desegment all X11 messages spanning multiple TCP segments",
+ "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
+ &x11_desegment);
+}
void
proto_reg_handoff_x11(void)