Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-xdmcp.c
blob9316e93af5b34b7f86d96f616f8bb72263ba9ed0
1 /* packet-xdmcp.c
2 * Routines for XDMCP message dissection
3 * Copyright 2002, Pasi Eronen <pasi.eronen@nixu.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/to_str.h>
16 #include <epan/expert.h>
18 #define UDP_PORT_XDMCP 177
20 #define XDMCP_PROTOCOL_VERSION 1
22 #define XDMCP_BROADCAST_QUERY 1
23 #define XDMCP_QUERY 2
24 #define XDMCP_INDIRECT_QUERY 3
25 #define XDMCP_FORWARD_QUERY 4
26 #define XDMCP_WILLING 5
27 #define XDMCP_UNWILLING 6
28 #define XDMCP_REQUEST 7
29 #define XDMCP_ACCEPT 8
30 #define XDMCP_DECLINE 9
31 #define XDMCP_MANAGE 10
32 #define XDMCP_REFUSE 11
33 #define XDMCP_FAILED 12
34 #define XDMCP_KEEPALIVE 13
35 #define XDMCP_ALIVE 14
37 void proto_register_xdmcp(void);
38 void proto_reg_handoff_xdmcp(void);
40 static dissector_handle_t xdmcp_handle;
42 static const value_string opcode_vals[] = {
43 { XDMCP_BROADCAST_QUERY, "Broadcast_query" },
44 { XDMCP_QUERY, "Query" },
45 { XDMCP_INDIRECT_QUERY, "Indirect_query" },
46 { XDMCP_FORWARD_QUERY, "Forward_query" },
47 { XDMCP_WILLING, "Willing" },
48 { XDMCP_UNWILLING, "Unwilling" },
49 { XDMCP_REQUEST, "Request" },
50 { XDMCP_ACCEPT, "Accept "},
51 { XDMCP_DECLINE, "Decline" },
52 { XDMCP_MANAGE, "Manage" },
53 { XDMCP_REFUSE, "Refuse" },
54 { XDMCP_FAILED, "Failed" },
55 { XDMCP_KEEPALIVE, "Keepalive" },
56 { XDMCP_ALIVE, "Alive" },
57 { 0, NULL }
60 /* Copied from packet-x11.c */
61 static const value_string family_vals[] = {
62 { 0, "Internet" },
63 { 1, "DECnet" },
64 { 2, "Chaos" },
65 { 6, "InternetV6" },
66 { 0, NULL }
69 static int proto_xdmcp;
70 static int hf_xdmcp_version;
71 static int hf_xdmcp_opcode;
72 static int hf_xdmcp_length;
73 static int hf_xdmcp_authentication_name;
74 static int hf_xdmcp_authorization_name;
75 static int hf_xdmcp_hostname;
76 static int hf_xdmcp_status;
77 static int hf_xdmcp_session_id;
78 static int hf_xdmcp_display_number;
79 static int hf_xdmcp_manufacturer_display_id;
80 static int hf_xdmcp_manufacturer_display_id_len;
81 static int hf_xdmcp_display_class;
82 static int hf_xdmcp_display_class_len;
83 static int hf_xdmcp_client_address_ipv4;
84 static int hf_xdmcp_client_address_ipv6;
85 static int hf_xdmcp_client_address_bytes;
86 static int hf_xdmcp_client_address_bytes_len;
87 static int hf_xdmcp_client_port_u16;
88 static int hf_xdmcp_client_port_bytes;
89 static int hf_xdmcp_client_port_len;
90 static int hf_xdmcp_authentication_data;
91 static int hf_xdmcp_authentication_data_len;
92 static int hf_xdmcp_authorization_data;
93 static int hf_xdmcp_authorization_data_len;
94 static int hf_xdmcp_connection_type;
95 static int hf_xdmcp_connection_address_ipv4;
96 static int hf_xdmcp_connection_address_ipv6;
97 static int hf_xdmcp_connection_address_bytes;
98 static int hf_xdmcp_session_running;
100 static int ett_xdmcp;
101 static int ett_xdmcp_authentication_names;
102 static int ett_xdmcp_authorization_names;
103 static int ett_xdmcp_connections;
104 static int ett_xdmcp_connection;
106 static expert_field ei_xdmcp_conn_address_mismatch;
108 static int xdmcp_add_string(proto_tree *tree, int hf,
109 tvbuff_t *tvb, int offset)
111 char *str;
112 unsigned len;
114 len = tvb_get_ntohs(tvb, offset);
115 str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset+2, len, ENC_ASCII);
116 proto_tree_add_string(tree, hf, tvb, offset, len+2, str);
118 return len+2;
121 static int xdmcp_add_bytes(proto_tree *tree, int hf_byte, int hf_length,
122 tvbuff_t *tvb, int offset)
124 unsigned len;
125 len = tvb_get_ntohs(tvb, offset);
127 proto_tree_add_item(tree, hf_length, tvb, offset, 2, ENC_BIG_ENDIAN);
128 proto_tree_add_item(tree, hf_byte, tvb, offset, len+2, ENC_NA);
129 return len+2;
132 static int xdmcp_add_authentication_names(proto_tree *tree,
133 tvbuff_t *tvb, int offset)
135 proto_tree *anames_tree;
136 proto_item *anames_ti;
137 int anames_len, anames_start_offset;
139 anames_start_offset = offset;
140 anames_len = tvb_get_uint8(tvb, offset);
141 anames_tree = proto_tree_add_subtree_format(tree, tvb,
142 anames_start_offset, -1,
143 ett_xdmcp_authentication_names, &anames_ti, "Authentication names (%d)",
144 anames_len);
146 anames_len = tvb_get_uint8(tvb, offset);
147 offset++;
148 while (anames_len > 0) {
149 offset += xdmcp_add_string(anames_tree, hf_xdmcp_authentication_name,
150 tvb, offset);
151 anames_len--;
153 proto_item_set_len(anames_ti, offset - anames_start_offset);
154 return offset - anames_start_offset;
157 static int xdmcp_add_authorization_names(proto_tree *tree,
158 tvbuff_t *tvb, int offset)
160 proto_tree *anames_tree;
161 proto_item *anames_ti;
162 int anames_len, anames_start_offset;
164 anames_start_offset = offset;
165 anames_len = tvb_get_uint8(tvb, offset);
166 anames_tree = proto_tree_add_subtree_format(tree, tvb,
167 anames_start_offset, -1,
168 ett_xdmcp_authorization_names, &anames_ti, "Authorization names (%d)",
169 anames_len);
171 anames_len = tvb_get_uint8(tvb, offset);
172 offset++;
173 while (anames_len > 0) {
174 offset += xdmcp_add_string(anames_tree, hf_xdmcp_authorization_name,
175 tvb, offset);
176 anames_len--;
178 proto_item_set_len(anames_ti, offset - anames_start_offset);
179 return offset - anames_start_offset;
183 * I didn't find any documentation for the XDMCP protocol, so
184 * this is reverse-engineered from XFree86 source files
185 * xc/programs/xdm/xdmcp.c and xc/programs/Xserver/os/xdmcp.c.
188 static int dissect_xdmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
190 int version = -1, opcode = -1;
191 int offset = 0;
192 proto_item *ti;
193 proto_tree *xdmcp_tree = 0;
195 version = tvb_get_ntohs(tvb, offset);
196 if (version != XDMCP_PROTOCOL_VERSION) {
197 /* Only version 1 exists, so this probably is not XDMCP at all... */
198 return offset;
201 col_set_str(pinfo->cinfo, COL_PROTOCOL, "XDMCP");
202 col_clear(pinfo->cinfo, COL_INFO);
204 ti = proto_tree_add_item(tree, proto_xdmcp, tvb, offset, -1, ENC_NA);
205 xdmcp_tree = proto_item_add_subtree(ti, ett_xdmcp);
207 proto_tree_add_uint(xdmcp_tree, hf_xdmcp_version, tvb,
208 offset, 2, version);
210 offset += 2;
212 opcode = tvb_get_ntohs(tvb, offset);
213 if (tree) {
214 proto_tree_add_uint(xdmcp_tree, hf_xdmcp_opcode, tvb,
215 offset, 2, opcode);
217 offset += 2;
219 col_add_str(pinfo->cinfo, COL_INFO,
220 val_to_str(opcode, opcode_vals, "Unknown (0x%04x)"));
222 proto_tree_add_item(xdmcp_tree, hf_xdmcp_length, tvb,
223 offset, 2, ENC_BIG_ENDIAN);
225 offset += 2;
227 switch (opcode) {
228 case XDMCP_FORWARD_QUERY:
230 int alen, plen;
231 alen = tvb_get_ntohs(tvb, offset);
232 /* I have never seen anything except IPv4 addresses here,
233 * but in theory the protocol should support other address
234 * families. */
235 if (alen == 4) {
236 proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_address_ipv4, tvb, offset+2, alen, ENC_BIG_ENDIAN);
237 offset += 6;
238 } else if (alen == 16) {
239 proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_address_ipv6, tvb, offset+2, alen, ENC_NA);
240 offset += 18;
241 } else {
242 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_client_address_bytes, hf_xdmcp_client_address_bytes_len,
243 tvb, offset);
246 plen = tvb_get_ntohs(tvb, offset);
247 if (plen == 2) {
248 proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_port_u16, tvb, offset+2, plen, ENC_BIG_ENDIAN);
249 offset += 4;
250 } else {
251 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_client_port_bytes, hf_xdmcp_client_port_len,
252 tvb, offset);
255 /* fall-through */
257 case XDMCP_BROADCAST_QUERY:
258 case XDMCP_QUERY:
259 case XDMCP_INDIRECT_QUERY:
260 offset += xdmcp_add_authentication_names(xdmcp_tree, tvb, offset);
261 break;
263 case XDMCP_WILLING:
264 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
265 tvb, offset);
266 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname,
267 tvb, offset);
268 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
269 tvb, offset);
270 break;
272 case XDMCP_UNWILLING:
273 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname,
274 tvb, offset);
275 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
276 tvb, offset);
277 break;
279 case XDMCP_REQUEST:
281 proto_tree *clist_tree;
282 proto_item *clist_ti;
283 int ctypes_len, caddrs_len, n;
284 int ctypes_start_offset, caddrs_offset;
286 ti = proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
287 offset, 2, ENC_BIG_ENDIAN);
288 offset += 2;
290 ctypes_len = tvb_get_uint8(tvb, offset);
291 ctypes_start_offset = offset;
292 caddrs_offset = offset + 1 + 2*ctypes_len;
293 caddrs_len = tvb_get_uint8(tvb, caddrs_offset);
294 if (ctypes_len != caddrs_len) {
295 expert_add_info(pinfo, ti, &ei_xdmcp_conn_address_mismatch);
296 return offset;
299 clist_tree = proto_tree_add_subtree_format(xdmcp_tree,
300 tvb, ctypes_start_offset, -1,
301 ett_xdmcp_connections, &clist_ti, "Connections (%d)",
302 ctypes_len);
304 offset++;
305 caddrs_offset++;
307 n = 1;
308 while (ctypes_len > 0) {
309 proto_item *connection_ti;
310 proto_tree *connection_tree;
312 int alen;
313 int ctype = tvb_get_ntohs(tvb, offset);
314 offset += 2;
315 alen = tvb_get_ntohs(tvb, caddrs_offset);
316 caddrs_offset += 2;
318 connection_tree = proto_tree_add_subtree_format(clist_tree, tvb, 0, 0,
319 ett_xdmcp_connection, &connection_ti, "Connection %d", n);
321 proto_tree_add_item(connection_tree, hf_xdmcp_connection_type, tvb, offset-2, 2, ENC_BIG_ENDIAN);
323 if ((ctype == 0) && (alen == 4)) {
324 proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_ipv4, tvb, caddrs_offset, alen, ENC_BIG_ENDIAN);
325 proto_item_append_text(connection_ti, ": %s", tvb_ip_to_str(pinfo->pool, tvb, caddrs_offset));
326 } else if ((ctype == 6) && (alen == 16)) {
327 proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_ipv6, tvb, caddrs_offset, alen, ENC_NA);
328 proto_item_append_text(connection_ti, ": %s", tvb_ip6_to_str(pinfo->pool, tvb, caddrs_offset));
329 } else {
330 proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_bytes, tvb, caddrs_offset, alen, ENC_NA);
333 caddrs_offset += alen;
334 ctypes_len--;
335 n++;
337 offset = caddrs_offset;
338 proto_item_set_len(clist_ti, offset - ctypes_start_offset);
340 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
341 tvb, offset);
342 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len,
343 tvb, offset);
345 offset += xdmcp_add_authorization_names(xdmcp_tree, tvb, offset);
347 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_manufacturer_display_id, hf_xdmcp_manufacturer_display_id_len,
348 tvb, offset);
349 break;
352 case XDMCP_ACCEPT:
353 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
354 offset, 4, ENC_BIG_ENDIAN);
355 offset += 4;
356 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
357 tvb, offset);
358 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len,
359 tvb, offset);
360 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authorization_name,
361 tvb, offset);
362 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authorization_data, hf_xdmcp_authorization_data_len,
363 tvb, offset);
364 break;
366 case XDMCP_DECLINE:
367 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
368 tvb, offset);
369 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
370 tvb, offset);
371 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len,
372 tvb, offset);
373 break;
375 case XDMCP_MANAGE:
376 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
377 offset, 4, ENC_BIG_ENDIAN);
378 offset += 4;
380 proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
381 offset, 2, ENC_BIG_ENDIAN);
382 offset += 2;
384 offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_display_class, hf_xdmcp_display_class_len,
385 tvb, offset);
386 break;
388 case XDMCP_REFUSE:
389 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
390 offset, 4, ENC_BIG_ENDIAN);
391 offset += 4;
392 break;
394 case XDMCP_FAILED:
395 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
396 offset, 4, ENC_BIG_ENDIAN);
397 offset += 4;
399 offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
400 tvb, offset);
401 break;
403 case XDMCP_KEEPALIVE:
404 proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
405 offset, 2, ENC_BIG_ENDIAN);
406 offset += 2;
408 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
409 offset, 4, ENC_BIG_ENDIAN);
410 offset += 4;
411 break;
413 case XDMCP_ALIVE:
415 uint8_t session_running = tvb_get_uint8(tvb, offset);
416 proto_tree_add_uint_format_value(xdmcp_tree, hf_xdmcp_session_running, tvb,
417 offset, 1, session_running, "%s", session_running ? "Yes" : "No");
418 offset++;
420 proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
421 offset, 4, ENC_BIG_ENDIAN);
422 offset += 4;
424 break;
425 default:
426 break;
428 return offset;
432 /* Register the protocol with Wireshark */
433 void proto_register_xdmcp(void)
435 /* Setup list of header fields */
436 static hf_register_info hf[] = {
437 { &hf_xdmcp_version,
438 { "Version", "xdmcp.version",
439 FT_UINT16, BASE_DEC, NULL, 0,
440 "Protocol version", HFILL }
442 { &hf_xdmcp_opcode,
443 { "Opcode", "xdmcp.opcode",
444 FT_UINT16, BASE_HEX, VALS(opcode_vals), 0,
445 NULL, HFILL }
447 { &hf_xdmcp_length,
448 { "Message length", "xdmcp.length",
449 FT_UINT16, BASE_DEC, NULL, 0,
450 "Length of the remaining message", HFILL }
452 { &hf_xdmcp_authentication_name,
453 { "Authentication name", "xdmcp.authentication_name",
454 FT_STRING, BASE_NONE, NULL, 0,
455 NULL, HFILL }
457 { &hf_xdmcp_authorization_name,
458 { "Authorization name", "xdmcp.authorization_name",
459 FT_STRING, BASE_NONE, NULL, 0,
460 NULL, HFILL }
462 { &hf_xdmcp_hostname,
463 { "Hostname", "xdmcp.hostname",
464 FT_STRING, BASE_NONE, NULL, 0,
465 NULL, HFILL }
467 { &hf_xdmcp_status,
468 { "Status", "xdmcp.status",
469 FT_STRING, BASE_NONE, NULL, 0,
470 NULL, HFILL }
472 { &hf_xdmcp_session_id,
473 { "Session ID", "xdmcp.session_id",
474 FT_UINT32, BASE_HEX, NULL, 0,
475 "Session identifier", HFILL }
477 { &hf_xdmcp_display_number,
478 { "Display number", "xdmcp.display_number",
479 FT_UINT16, BASE_DEC, NULL, 0,
480 NULL, HFILL }
482 { &hf_xdmcp_manufacturer_display_id_len,
483 { "Manufacturer display ID Length", "xdmcp.manufacturer_display_id_len",
484 FT_UINT16, BASE_DEC, NULL, 0,
485 NULL, HFILL }
487 { &hf_xdmcp_manufacturer_display_id,
488 { "Manufacturer display ID", "xdmcp.manufacturer_display_id",
489 FT_BYTES, BASE_NONE, NULL, 0,
490 NULL, HFILL }
492 { &hf_xdmcp_display_class_len,
493 { "Display class Length", "xdmcp.display_class_len",
494 FT_UINT16, BASE_DEC, NULL, 0,
495 NULL, HFILL }
497 { &hf_xdmcp_display_class,
498 { "Display class", "xdmcp.display_class",
499 FT_BYTES, BASE_NONE, NULL, 0,
500 NULL, HFILL }
502 /* XXX - the following 3 could be the same filter, but mixed types of the same filter seem to cause issues */
503 { &hf_xdmcp_client_address_ipv4,
504 { "Client Address", "xdmcp.client_address_ipv4",
505 FT_IPv4, BASE_NONE, NULL, 0,
506 NULL, HFILL }
508 { &hf_xdmcp_client_address_ipv6,
509 { "Client Address", "xdmcp.client_address_ipv6",
510 FT_IPv6, BASE_NONE, NULL, 0,
511 NULL, HFILL }
513 { &hf_xdmcp_client_address_bytes,
514 { "Client Address", "xdmcp.client_address_bytes",
515 FT_BYTES, BASE_NONE, NULL, 0,
516 NULL, HFILL }
518 { &hf_xdmcp_client_address_bytes_len,
519 { "Client Address Length", "xdmcp.client_address_bytes_len",
520 FT_UINT16, BASE_DEC, NULL, 0,
521 NULL, HFILL }
523 { &hf_xdmcp_client_port_len,
524 { "Client port Length", "xdmcp.client_port_len",
525 FT_UINT16, BASE_DEC, NULL, 0,
526 NULL, HFILL }
528 { &hf_xdmcp_client_port_bytes,
529 { "Client port", "xdmcp.client_port_bytes",
530 FT_BYTES, BASE_NONE, NULL, 0,
531 NULL, HFILL }
533 { &hf_xdmcp_client_port_u16,
534 { "Client port", "xdmcp.client_port",
535 FT_UINT16, BASE_DEC, NULL, 0,
536 NULL, HFILL }
538 { &hf_xdmcp_authentication_data_len,
539 { "Authentication data Length", "xdmcp.authentication_data_len",
540 FT_UINT16, BASE_DEC, NULL, 0,
541 NULL, HFILL }
543 { &hf_xdmcp_authentication_data,
544 { "Authentication data", "xdmcp.authentication_data",
545 FT_BYTES, BASE_NONE, NULL, 0,
546 NULL, HFILL }
548 { &hf_xdmcp_authorization_data_len,
549 { "Authorization data Length", "xdmcp.authorization_data_len",
550 FT_UINT16, BASE_DEC, NULL, 0,
551 NULL, HFILL }
553 { &hf_xdmcp_authorization_data,
554 { "Authorization data", "xdmcp.authorization_data",
555 FT_BYTES, BASE_NONE, NULL, 0,
556 NULL, HFILL }
558 /* XXX - the following 3 could be the same filter, but mixed types of the same filter seem to cause issues */
559 { &hf_xdmcp_connection_address_ipv4,
560 { "Address", "xdmcp.connection_address_ipv4",
561 FT_IPv4, BASE_NONE, NULL, 0,
562 NULL, HFILL }
564 { &hf_xdmcp_connection_address_ipv6,
565 { "Address", "xdmcp.connection_address_ipv6",
566 FT_IPv6, BASE_NONE, NULL, 0,
567 NULL, HFILL }
569 { &hf_xdmcp_connection_address_bytes,
570 { "Address", "xdmcp.connection_address_bytes",
571 FT_BYTES, BASE_NONE, NULL, 0,
572 NULL, HFILL }
574 { &hf_xdmcp_connection_type,
575 { "Type", "xdmcp.connection_type",
576 FT_UINT16, BASE_HEX, VALS(family_vals), 0,
577 NULL, HFILL }
579 { &hf_xdmcp_session_running,
580 { "Session running", "xdmcp.session_running",
581 FT_UINT8, BASE_DEC, NULL, 0,
582 NULL, HFILL }
587 /* Setup protocol subtree array */
588 static int *ett[] = {
589 &ett_xdmcp,
590 &ett_xdmcp_authentication_names,
591 &ett_xdmcp_authorization_names,
592 &ett_xdmcp_connections,
593 &ett_xdmcp_connection
596 static ei_register_info ei[] = {
597 { &ei_xdmcp_conn_address_mismatch, { "xdmcp.conn_address_mismatch", PI_PROTOCOL, PI_WARN, "Error: Connection type/address arrays don't match", EXPFILL }},
600 expert_module_t* expert_xdmcp;
602 /* Register the protocol name and description */
603 proto_xdmcp = proto_register_protocol("X Display Manager Control Protocol", "XDMCP", "xdmcp");
605 /* Required function calls to register the header fields and subtrees used */
606 proto_register_field_array(proto_xdmcp, hf, array_length(hf));
607 proto_register_subtree_array(ett, array_length(ett));
608 expert_xdmcp = expert_register_protocol(proto_xdmcp);
609 expert_register_field_array(expert_xdmcp, ei, array_length(ei));
611 /* Register the dissector handle */
612 xdmcp_handle = register_dissector("xdmcp", dissect_xdmcp, proto_xdmcp);
615 void
616 proto_reg_handoff_xdmcp(void)
618 dissector_add_uint_with_preference("udp.port", UDP_PORT_XDMCP, xdmcp_handle);
621 * Editor modelines
623 * Local Variables:
624 * c-basic-offset: 2
625 * tab-width: 8
626 * indent-tabs-mode: nil
627 * End:
629 * ex: set shiftwidth=2 tabstop=8 expandtab:
630 * :indentSize=2:tabSize=8:noTabs=true: