2 * Routines for Quake packet dissection
4 * Uwe Girlich <uwe@planetquake.com>
5 * http://www.idsoftware.com/q1source/q1source.zip
7 * $Id: packet-quake.c,v 1.17 2001/07/03 04:56:45 guy Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
11 * Copyright 1998 Gerald Combs
13 * Copied from packet-tftp.c
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
44 #include "conversation.h"
47 static int proto_quake = -1;
48 static int hf_quake_header_flags = -1;
49 static int hf_quake_header_length = -1;
50 static int hf_quake_header_sequence = -1;
51 static int hf_quake_control_command = -1;
53 static int hf_quake_CCREQ_CONNECT_game = -1;
54 static int hf_quake_CCREQ_CONNECT_version = -1;
55 static int hf_quake_CCREQ_SERVER_INFO_game = -1;
56 static int hf_quake_CCREQ_SERVER_INFO_version = -1;
57 static int hf_quake_CCREQ_PLAYER_INFO_player = -1;
58 static int hf_quake_CCREQ_RULE_INFO_lastrule = -1;
60 static int hf_quake_CCREP_ACCEPT_port = -1;
61 static int hf_quake_CCREP_REJECT_reason = -1;
62 static int hf_quake_CCREP_SERVER_INFO_address = -1;
63 static int hf_quake_CCREP_SERVER_INFO_server = -1;
64 static int hf_quake_CCREP_SERVER_INFO_map = -1;
65 static int hf_quake_CCREP_SERVER_INFO_num_player = -1;
66 static int hf_quake_CCREP_SERVER_INFO_max_player = -1;
67 static int hf_quake_CCREP_PLAYER_INFO_name = -1;
68 static int hf_quake_CCREP_PLAYER_INFO_colors = -1;
69 static int hf_quake_CCREP_PLAYER_INFO_colors_shirt = -1;
70 static int hf_quake_CCREP_PLAYER_INFO_colors_pants = -1;
71 static int hf_quake_CCREP_PLAYER_INFO_frags = -1;
72 static int hf_quake_CCREP_PLAYER_INFO_connect_time = -1;
73 static int hf_quake_CCREP_PLAYER_INFO_address = -1;
74 static int hf_quake_CCREP_RULE_INFO_rule = -1;
75 static int hf_quake_CCREP_RULE_INFO_value = -1;
78 static gint ett_quake = -1;
79 static gint ett_quake_control = -1;
80 static gint ett_quake_control_colors = -1;
81 static gint ett_quake_flags = -1;
84 /* I took these names directly out of the Q1 source. */
85 #define NETFLAG_LENGTH_MASK 0x0000ffff
86 #define NET_HEADERSIZE 8
87 #define DEFAULTnet_hostport 26000
88 static unsigned int gbl_quakeServerPort=DEFAULTnet_hostport;
90 #define NETFLAG_LENGTH_MASK 0x0000ffff
91 #define NETFLAG_DATA 0x00010000
92 #define NETFLAG_ACK 0x00020000
93 #define NETFLAG_NAK 0x00040000
94 #define NETFLAG_EOM 0x00080000
95 #define NETFLAG_UNRELIABLE 0x00100000
96 #define NETFLAG_CTL 0x80000000
99 #define CCREQ_CONNECT 0x01
100 #define CCREQ_SERVER_INFO 0x02
101 #define CCREQ_PLAYER_INFO 0x03
102 #define CCREQ_RULE_INFO 0x04
104 #define CCREP_ACCEPT 0x81
105 #define CCREP_REJECT 0x82
106 #define CCREP_SERVER_INFO 0x83
107 #define CCREP_PLAYER_INFO 0x84
108 #define CCREP_RULE_INFO 0x85
110 static const value_string names_control_command[] = {
111 { CCREQ_CONNECT, "connect" },
112 { CCREQ_SERVER_INFO, "server_info" },
113 { CCREQ_PLAYER_INFO, "player_info" },
114 { CCREQ_RULE_INFO, "rule_info" },
115 { CCREP_ACCEPT, "accept" },
116 { CCREP_REJECT, "reject" },
117 { CCREP_SERVER_INFO, "server_info" },
118 { CCREP_PLAYER_INFO, "player_info" },
119 { CCREP_RULE_INFO, "rule_info" },
126 #define QUAKE_MAXSTRING 0x800
128 static const value_string names_control_direction[] = {
129 { CCREQ, "Request" },
135 static const value_string names_colors[] = {
156 static void dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
161 dissect_quake_CCREQ_CONNECT
162 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
165 char game[QUAKE_MAXSTRING];
169 maxbufsize = MIN(sizeof(game), tvb_length(tvb));
170 len = tvb_get_nstringz0(tvb, 0, maxbufsize, game);
171 version = tvb_get_guint8(tvb, len + 1);
174 proto_tree_add_string(tree, hf_quake_CCREQ_CONNECT_game,
175 tvb, 0, len + 1, game);
176 proto_tree_add_uint(tree, hf_quake_CCREQ_CONNECT_version,
177 tvb, len + 1, 1, version);
183 dissect_quake_CCREQ_SERVER_INFO
184 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
187 char game[QUAKE_MAXSTRING];
191 maxbufsize = MIN(sizeof(game), tvb_length(tvb));
192 len = tvb_get_nstringz0(tvb, 0, maxbufsize, game);
193 version = tvb_get_guint8(tvb, len + 1);
196 proto_tree_add_string(tree, hf_quake_CCREQ_SERVER_INFO_game,
197 tvb, 0, len + 1, game);
198 proto_tree_add_uint(tree, hf_quake_CCREQ_SERVER_INFO_version,
199 tvb, len + 1, 1, version);
205 dissect_quake_CCREQ_PLAYER_INFO
206 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
210 player = tvb_get_guint8(tvb, 0);
212 proto_tree_add_uint(tree, hf_quake_CCREQ_PLAYER_INFO_player,
219 dissect_quake_CCREQ_RULE_INFO
220 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
222 char rule[QUAKE_MAXSTRING];
226 maxbufsize = MIN(sizeof(rule), tvb_length(tvb));
227 len = tvb_get_nstringz0(tvb, 0, maxbufsize, rule);
229 proto_tree_add_string(tree, hf_quake_CCREQ_RULE_INFO_lastrule,
230 tvb, 0, len + 1, rule);
236 dissect_quake_CCREP_ACCEPT
237 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
242 port = tvb_get_letohl(tvb, 0);
243 c = conversation_new( &pinfo->src, &pinfo->dst, PT_UDP, port,
244 pinfo->destport, NULL, 0);
246 conversation_set_dissector(c, dissect_quake);
249 proto_tree_add_uint(tree, hf_quake_CCREP_ACCEPT_port,
256 dissect_quake_CCREP_REJECT
257 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
260 char reason[QUAKE_MAXSTRING];
263 maxbufsize = MIN(sizeof(reason), tvb_length(tvb));
264 len = tvb_get_nstringz0(tvb, 0, maxbufsize, reason);
267 proto_tree_add_string(tree, hf_quake_CCREP_REJECT_reason,
268 tvb, 0, len + 1, reason);
274 dissect_quake_CCREP_SERVER_INFO
275 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
280 char address[QUAKE_MAXSTRING];
281 char server[QUAKE_MAXSTRING];
282 char map[QUAKE_MAXSTRING];
290 maxbufsize = MIN((int)sizeof(address), tvb_length_remaining(tvb, offset));
291 len = tvb_get_nstringz0(tvb, offset, maxbufsize, address);
293 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_address,
294 tvb, offset, len + 1, address);
298 maxbufsize = MIN((int)sizeof(server), tvb_length_remaining(tvb, offset));
299 len = tvb_get_nstringz0(tvb, offset, maxbufsize, server);
301 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_server,
302 tvb, offset, len + 1, server);
306 maxbufsize = MIN((int)sizeof(map), tvb_length_remaining(tvb, offset));
307 len = tvb_get_nstringz0(tvb, offset, maxbufsize, map);
309 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_map,
310 tvb, offset, len + 1, map);
314 num_player = tvb_get_guint8(tvb, offset + 0);
315 max_player = tvb_get_guint8(tvb, offset + 1);
316 version = tvb_get_guint8(tvb, offset + 2);
319 proto_tree_add_uint(tree, hf_quake_CCREP_SERVER_INFO_num_player,
320 tvb, offset + 0, 1, num_player);
321 proto_tree_add_uint(tree, hf_quake_CCREP_SERVER_INFO_max_player,
322 tvb, offset + 1, 1, max_player);
323 proto_tree_add_uint(tree, hf_quake_CCREQ_SERVER_INFO_version,
324 tvb, offset + 2, 1, version);
330 dissect_quake_CCREP_PLAYER_INFO
331 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
337 char name[QUAKE_MAXSTRING];
342 guint32 connect_time;
343 char address[QUAKE_MAXSTRING];
347 player = tvb_get_guint8(tvb, offset);
349 proto_tree_add_uint(tree, hf_quake_CCREQ_PLAYER_INFO_player,
350 tvb, offset, 1, player);
354 maxbufsize = MIN((int)sizeof(name), tvb_length_remaining(tvb, offset));
355 len = tvb_get_nstringz0(tvb, offset, maxbufsize, name);
357 proto_tree_add_string(tree, hf_quake_CCREP_PLAYER_INFO_name,
358 tvb, offset, len + 1, name);
362 colors = tvb_get_letohl(tvb, offset + 0);
363 color_shirt = (colors >> 4) & 0x0f;
364 color_pants = (colors ) & 0x0f;
365 frags = tvb_get_letohl(tvb, offset + 4);
366 connect_time = tvb_get_letohl(tvb, offset + 8);
368 proto_item *colors_item;
369 proto_tree *colors_tree;
371 colors_item = proto_tree_add_uint(tree,
372 hf_quake_CCREP_PLAYER_INFO_colors,
373 tvb, offset + 0, 4, colors);
375 colors_tree = proto_item_add_subtree(colors_item,
376 ett_quake_control_colors);
377 proto_tree_add_uint(colors_tree,
378 hf_quake_CCREP_PLAYER_INFO_colors_shirt,
379 tvb, offset + 0, 1, color_shirt);
380 proto_tree_add_uint(colors_tree,
381 hf_quake_CCREP_PLAYER_INFO_colors_pants,
382 tvb, offset + 0, 1, color_pants);
384 proto_tree_add_uint(tree, hf_quake_CCREP_PLAYER_INFO_frags,
385 tvb, offset + 4, 4, frags);
386 proto_tree_add_uint(tree, hf_quake_CCREP_PLAYER_INFO_connect_time,
387 tvb, offset + 8, 4, connect_time);
391 maxbufsize = MIN((int)sizeof(address), tvb_length_remaining(tvb, offset));
392 len = tvb_get_nstringz0(tvb, offset, maxbufsize, address);
394 proto_tree_add_string(tree, hf_quake_CCREP_PLAYER_INFO_address,
395 tvb, offset, len + 1, address);
402 dissect_quake_CCREP_RULE_INFO
403 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
405 char rule[QUAKE_MAXSTRING];
406 char value[QUAKE_MAXSTRING];
411 if (tvb_length(tvb) == 0) return;
415 maxbufsize = MIN((int)sizeof(rule), tvb_length_remaining(tvb, offset));
416 len = tvb_get_nstringz0(tvb, offset, maxbufsize, rule);
418 proto_tree_add_string(tree, hf_quake_CCREP_RULE_INFO_rule,
419 tvb, offset, len + 1, rule);
423 maxbufsize = MIN((int)sizeof(value), tvb_length_remaining(tvb, offset));
424 len = tvb_get_nstringz0(tvb, offset, maxbufsize, value);
426 proto_tree_add_string(tree, hf_quake_CCREP_RULE_INFO_value,
427 tvb, offset, len + 1, value);
434 dissect_quake_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
438 proto_item *control_item = NULL;
439 proto_tree *control_tree = NULL;
443 command = tvb_get_guint8(tvb, 0);
444 direction = (command & 0x80) ? CCREP : CCREQ;
446 if (check_col(pinfo->fd, COL_INFO)) {
447 col_add_fstr(pinfo->fd, COL_INFO, "%s %s",
448 val_to_str(command,names_control_command, "%u"),
449 val_to_str(direction,names_control_direction,"%u"));
453 control_item = proto_tree_add_text(tree, tvb,
454 0, tvb_length(tvb), "Control %s: %s",
455 val_to_str(direction, names_control_direction, "%u"),
456 val_to_str(command, names_control_command, "%u"));
458 control_tree = proto_item_add_subtree(control_item,
460 proto_tree_add_uint(control_tree, hf_quake_control_command,
464 rest_length = tvb_reported_length(tvb) - 1;
465 next_tvb = tvb_new_subset(tvb, 1, rest_length , rest_length);
468 dissect_quake_CCREQ_CONNECT
469 (next_tvb, pinfo, control_tree);
471 case CCREQ_SERVER_INFO:
472 dissect_quake_CCREQ_SERVER_INFO
473 (next_tvb, pinfo, control_tree);
475 case CCREQ_PLAYER_INFO:
476 dissect_quake_CCREQ_PLAYER_INFO
477 (next_tvb, pinfo, control_tree);
479 case CCREQ_RULE_INFO:
480 dissect_quake_CCREQ_RULE_INFO
481 (next_tvb, pinfo, control_tree);
484 dissect_quake_CCREP_ACCEPT
485 (next_tvb, pinfo, control_tree);
488 dissect_quake_CCREP_REJECT
489 (next_tvb, pinfo, control_tree);
491 case CCREP_SERVER_INFO:
492 dissect_quake_CCREP_SERVER_INFO
493 (next_tvb, pinfo, control_tree);
495 case CCREP_PLAYER_INFO:
496 dissect_quake_CCREP_PLAYER_INFO
497 (next_tvb, pinfo, control_tree);
499 case CCREP_RULE_INFO:
500 dissect_quake_CCREP_RULE_INFO
501 (next_tvb, pinfo, control_tree);
504 dissect_data(next_tvb, 0, pinfo, control_tree);
511 dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
513 proto_tree *quake_tree = NULL;
514 proto_item *quake_item = NULL;
517 guint32 sequence = 0;
522 * XXX - this is a conversation dissector, and the code to
523 * call a conversation dissector doesn't check for disabled
524 * protocols or set "pinfo->current_proto".
526 CHECK_DISPLAY_AS_DATA(proto_quake, tvb, pinfo, tree);
528 pinfo->current_proto = "QUAKE";
530 if (check_col(pinfo->fd, COL_PROTOCOL))
531 col_set_str(pinfo->fd, COL_PROTOCOL, "QUAKE");
532 if (check_col(pinfo->fd, COL_INFO))
533 col_clear(pinfo->fd, COL_INFO);
535 length = tvb_get_ntohl(tvb, 0);
536 flags = length & (~NETFLAG_LENGTH_MASK);
537 length &= NETFLAG_LENGTH_MASK;
540 quake_item = proto_tree_add_item(tree, proto_quake,
541 tvb, 0, tvb_length(tvb), FALSE);
543 quake_tree = proto_item_add_subtree(quake_item, ett_quake);
547 proto_item* flags_item = NULL;
548 proto_tree* flags_tree = NULL;
550 flags_item = proto_tree_add_uint(quake_tree, hf_quake_header_flags,
553 flags_tree = proto_item_add_subtree(flags_item, ett_quake_flags);
557 proto_tree_add_text(flags_tree, tvb, 0, 2,
558 decode_boolean_bitfield(flags, NETFLAG_DATA, 32,
560 proto_tree_add_text(flags_tree, tvb, 0, 2,
561 decode_boolean_bitfield(flags, NETFLAG_ACK, 32,
562 "Acknowledgment","-"));
563 proto_tree_add_text(flags_tree, tvb, 0, 2,
564 decode_boolean_bitfield(flags, NETFLAG_NAK, 32,
565 "No Acknowledgment","-"));
566 proto_tree_add_text(flags_tree, tvb, 0, 2,
567 decode_boolean_bitfield(flags, NETFLAG_EOM, 32,
568 "End Of Message","-"));
569 proto_tree_add_text(flags_tree, tvb, 0, 2,
570 decode_boolean_bitfield(flags, NETFLAG_UNRELIABLE, 32,
572 proto_tree_add_text(flags_tree, tvb, 0, 2,
573 decode_boolean_bitfield(flags, NETFLAG_CTL, 32,
576 proto_tree_add_uint(quake_tree, hf_quake_header_length,
580 if (flags == NETFLAG_CTL) {
581 rest_length = tvb_reported_length(tvb) - 4;
582 next_tvb = tvb_new_subset(tvb, 4, rest_length , rest_length);
583 dissect_quake_control(next_tvb, pinfo, quake_tree);
587 sequence = tvb_get_ntohl(tvb, 4);
588 if (check_col(pinfo->fd, COL_INFO)) {
589 col_add_fstr(pinfo->fd, COL_INFO, "seq 0x%x", sequence);
592 proto_tree_add_uint(quake_tree, hf_quake_header_sequence,
593 tvb, 4, 4, sequence);
596 rest_length = tvb_reported_length(tvb) - 8;
597 next_tvb = tvb_new_subset(tvb, 8, rest_length , rest_length);
598 dissect_data(next_tvb, 0, pinfo, quake_tree);
603 proto_reg_handoff_quake(void)
605 static int Initialized=FALSE;
606 static int ServerPort=0;
609 dissector_delete("udp.port", ServerPort, dissect_quake);
614 /* set port for future deletes */
615 ServerPort=gbl_quakeServerPort;
617 dissector_add("udp.port", gbl_quakeServerPort,
618 dissect_quake, proto_quake);
623 proto_register_quake(void)
625 static hf_register_info hf[] = {
626 { &hf_quake_header_flags,
627 { "Flags", "quake.header.flags",
628 FT_UINT16, BASE_HEX, NULL, 0x0,
630 { &hf_quake_header_length,
631 { "Length", "quake.header.length",
632 FT_UINT16, BASE_DEC, NULL, 0x0,
633 "full data length", HFILL }},
634 { &hf_quake_header_sequence,
635 { "Sequence", "quake.header.sequence",
636 FT_UINT32, BASE_HEX, NULL, 0x0,
637 "Sequence Number", HFILL }},
638 { &hf_quake_control_command,
639 { "Command", "quake.control.command",
640 FT_UINT8, BASE_HEX, VALS(names_control_command), 0x0,
641 "Control Command", HFILL }},
642 { &hf_quake_CCREQ_CONNECT_game,
643 { "Game", "quake.control.connect.game",
644 FT_STRING, BASE_DEC, NULL, 0x0,
645 "Game Name", HFILL }},
646 { &hf_quake_CCREQ_CONNECT_version,
647 { "Version", "quake.control.connect.version",
648 FT_UINT8, BASE_DEC, NULL, 0x0,
649 "Game Protocol Version Number", HFILL }},
650 { &hf_quake_CCREQ_SERVER_INFO_game,
651 { "Game", "quake.control.server_info.game",
652 FT_STRING, BASE_DEC, NULL, 0x0,
653 "Game Name", HFILL }},
654 { &hf_quake_CCREQ_SERVER_INFO_version,
655 { "Version", "quake.control.server_info.version",
656 FT_UINT8, BASE_DEC, NULL, 0x0,
657 "Game Protocol Version Number", HFILL }},
658 { &hf_quake_CCREQ_PLAYER_INFO_player,
659 { "Player", "quake.control.player_info.player",
660 FT_UINT8, BASE_DEC, NULL, 0x0,
662 { &hf_quake_CCREQ_RULE_INFO_lastrule,
663 { "Last Rule", "quake.control.rule_info.lastrule",
664 FT_STRING, BASE_DEC, NULL, 0x0,
665 "Last Rule Name", HFILL }},
666 { &hf_quake_CCREP_ACCEPT_port,
667 { "Port", "quake.control.accept.port",
668 FT_UINT32, BASE_DEC, NULL, 0x0,
669 "Game Data Port", HFILL }},
670 { &hf_quake_CCREP_REJECT_reason,
671 { "Reason", "quake.control.reject.reason",
672 FT_STRING, BASE_DEC, NULL, 0x0,
673 "Reject Reason", HFILL }},
674 { &hf_quake_CCREP_SERVER_INFO_address,
675 { "Address", "quake.control.server_info.address",
676 FT_STRING, BASE_DEC, NULL, 0x0,
677 "Server Address", HFILL }},
678 { &hf_quake_CCREP_SERVER_INFO_server,
679 { "Server", "quake.control.server_info.server",
680 FT_STRING, BASE_DEC, NULL, 0x0,
681 "Server Name", HFILL }},
682 { &hf_quake_CCREP_SERVER_INFO_map,
683 { "Map", "quake.control.server_info.map",
684 FT_STRING, BASE_DEC, NULL, 0x0,
685 "Map Name", HFILL }},
686 { &hf_quake_CCREP_SERVER_INFO_num_player,
687 { "Number of Players", "quake.control.server_info.num_player",
688 FT_UINT8, BASE_DEC, NULL, 0x0,
689 "Current Number of Players", HFILL }},
690 { &hf_quake_CCREP_SERVER_INFO_max_player,
691 { "Maximal Number of Players", "quake.control.server_info.max_player",
692 FT_UINT8, BASE_DEC, NULL, 0x0,
693 "Maximal Number of Players", HFILL }},
694 { &hf_quake_CCREP_PLAYER_INFO_name,
695 { "Name", "quake.control.player_info.name",
696 FT_STRING, BASE_DEC, NULL, 0x0,
697 "Player Name", HFILL }},
698 { &hf_quake_CCREP_PLAYER_INFO_colors,
699 { "Colors", "quake.control.player_info.colors",
700 FT_UINT32, BASE_HEX, NULL, 0x0,
701 "Player Colors", HFILL }},
702 { &hf_quake_CCREP_PLAYER_INFO_colors_shirt,
703 { "Shirt", "quake.control.player_info.colors.shirt",
704 FT_UINT8, BASE_DEC, VALS(names_colors), 0x0,
705 "Shirt Color", HFILL }},
706 { &hf_quake_CCREP_PLAYER_INFO_colors_pants,
707 { "Pants", "quake.control.player_info.colors.pants",
708 FT_UINT8, BASE_DEC, VALS(names_colors), 0x0,
709 "Pants Color", HFILL }},
710 { &hf_quake_CCREP_PLAYER_INFO_frags,
711 { "Frags", "quake.control.player_info.frags",
712 FT_UINT32, BASE_DEC, NULL, 0x0,
713 "Player Frags", HFILL }},
714 { &hf_quake_CCREP_PLAYER_INFO_connect_time,
715 { "Connect Time", "quake.control.player_info.connect_time",
716 FT_UINT32, BASE_DEC, NULL, 0x0,
717 "Player Connect Time", HFILL }},
718 { &hf_quake_CCREP_PLAYER_INFO_address,
719 { "Address", "quake.control.player_info.address",
720 FT_STRING, BASE_DEC, NULL, 0x0,
721 "Player Address", HFILL }},
722 { &hf_quake_CCREP_RULE_INFO_rule,
723 { "Rule", "quake.control.rule_info.rule",
724 FT_STRING, BASE_DEC, NULL, 0x0,
725 "Rule Name", HFILL }},
726 { &hf_quake_CCREP_RULE_INFO_value,
727 { "Value", "quake.control.rule_info.value",
728 FT_STRING, BASE_DEC, NULL, 0x0,
729 "Rule Value", HFILL }},
731 static gint *ett[] = {
734 &ett_quake_control_colors,
737 module_t *quake_module;
739 proto_quake = proto_register_protocol("Quake Network Protocol",
741 proto_register_field_array(proto_quake, hf, array_length(hf));
742 proto_register_subtree_array(ett, array_length(ett));
744 /* Register a configuration option for port */
745 quake_module = prefs_register_protocol(proto_quake,
746 proto_reg_handoff_quake);
747 prefs_register_uint_preference(quake_module, "udp.port",
748 "Quake Server UDP Port",
749 "Set the UDP port for the Quake Server",
750 10, &gbl_quakeServerPort);