Instead of saying the "manuf" file is in "/usr/local/etc/manuf", say
[obnox/wireshark/wip.git] / packet-quake.c
1 /* packet-quake.c
2  * Routines for Quake packet dissection
3  *
4  * Uwe Girlich <uwe@planetquake.com>
5  *      http://www.idsoftware.com/q1source/q1source.zip
6  *
7  * $Id: packet-quake.c,v 1.18 2001/09/03 10:33:06 guy Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-tftp.c
14  * 
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.
19  * 
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.
24  * 
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.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #include <glib.h>
43 #include "packet.h"
44 #include "conversation.h"
45 #include "prefs.h"
46
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;
52
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;
59
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;
76
77
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;
82
83
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;
89
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                              
97
98
99 #define CCREQ_CONNECT           0x01
100 #define CCREQ_SERVER_INFO       0x02
101 #define CCREQ_PLAYER_INFO       0x03
102 #define CCREQ_RULE_INFO         0x04
103  
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
109
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" },
120         { 0, NULL }
121 };
122
123 #define CCREQ 0x00
124 #define CCREP 0x80
125
126 #define QUAKE_MAXSTRING 0x800
127
128 static const value_string names_control_direction[] = {
129         { CCREQ, "Request" },
130         { CCREP, "Reply" },
131         { 0, NULL }
132 };
133
134
135 static const value_string names_colors[] = {
136         {  0, "White" },
137         {  1, "Brown" },
138         {  2, "Lavender" },
139         {  3, "Khaki" },
140         {  4, "Red" },
141         {  5, "Lt Brown" },
142         {  6, "Peach" },
143         {  7, "Lt Peach" },
144         {  8, "Purple" },
145         {  9, "Dk Purple" },
146         { 10, "Tan" },
147         { 11, "Green" },
148         { 12, "Yellow" },
149         { 13, "Blue" },
150         { 14, "Blue" },
151         { 15, "Blue" },
152         {  0, NULL }
153 };
154
155
156 static void dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
157
158
159
160 static void
161 dissect_quake_CCREQ_CONNECT
162 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
163 {
164         gint maxbufsize;
165         char game[QUAKE_MAXSTRING];
166         guint8 version;
167         gint len;
168
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);
172
173         if (tree) {
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);
178         }
179 }
180
181
182 static void
183 dissect_quake_CCREQ_SERVER_INFO
184 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
185 {
186         gint maxbufsize;
187         char game[QUAKE_MAXSTRING];
188         guint8 version;
189         gint len;
190
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);
194
195         if (tree) {
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);
200         }
201 }
202
203
204 static void
205 dissect_quake_CCREQ_PLAYER_INFO
206 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
207 {
208         guint8 player;
209
210         player = tvb_get_guint8(tvb, 0);
211         if (tree) {
212                  proto_tree_add_uint(tree, hf_quake_CCREQ_PLAYER_INFO_player,
213                         tvb, 0, 1, player);
214         }
215 }
216
217
218 static void
219 dissect_quake_CCREQ_RULE_INFO
220 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
221 {
222         char rule[QUAKE_MAXSTRING];
223         gint maxbufsize;
224         gint len;
225
226         maxbufsize = MIN(sizeof(rule), tvb_length(tvb));
227         len = tvb_get_nstringz0(tvb, 0, maxbufsize, rule);
228         if (tree) {
229                 proto_tree_add_string(tree, hf_quake_CCREQ_RULE_INFO_lastrule,
230                         tvb, 0, len + 1, rule);
231         }
232 }
233
234
235 static void
236 dissect_quake_CCREP_ACCEPT
237 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
238 {
239         guint32 port;
240         conversation_t *c;
241
242         port = tvb_get_letohl(tvb, 0);
243         c = conversation_new( &pinfo->src, &pinfo->dst, PT_UDP, port,
244             pinfo->destport, 0);
245         if (c) {
246                 conversation_set_dissector(c, dissect_quake);
247         }
248         if (tree) {
249                 proto_tree_add_uint(tree, hf_quake_CCREP_ACCEPT_port,
250                         tvb, 0, 4, port);
251         }
252 }
253
254
255 static void
256 dissect_quake_CCREP_REJECT
257 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
258 {
259         gint maxbufsize;
260         char reason[QUAKE_MAXSTRING];
261         gint len;
262
263         maxbufsize = MIN(sizeof(reason), tvb_length(tvb));
264         len = tvb_get_nstringz0(tvb, 0, maxbufsize, reason);
265
266         if (tree) {
267                 proto_tree_add_string(tree, hf_quake_CCREP_REJECT_reason,
268                         tvb, 0, len + 1, reason);
269         }
270 }
271
272
273 static void
274 dissect_quake_CCREP_SERVER_INFO
275 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
276 {
277         gint offset;
278         gint len;
279         gint maxbufsize;
280         char address[QUAKE_MAXSTRING];
281         char server[QUAKE_MAXSTRING];
282         char map[QUAKE_MAXSTRING];
283
284         guint8 num_player;
285         guint8 max_player;
286         guint8 version;
287
288         offset = 0;
289
290         maxbufsize = MIN((int)sizeof(address), tvb_length_remaining(tvb, offset));
291         len = tvb_get_nstringz0(tvb, offset, maxbufsize, address);
292         if (tree) {
293                 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_address,
294                         tvb, offset, len + 1, address);
295         }
296         offset += len + 1;
297
298         maxbufsize = MIN((int)sizeof(server), tvb_length_remaining(tvb, offset));
299         len = tvb_get_nstringz0(tvb, offset, maxbufsize, server);
300         if (tree) {
301                 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_server,
302                         tvb, offset, len + 1, server);
303         }
304         offset += len + 1;
305         
306         maxbufsize = MIN((int)sizeof(map), tvb_length_remaining(tvb, offset));
307         len = tvb_get_nstringz0(tvb, offset, maxbufsize, map);
308         if (tree) {
309                 proto_tree_add_string(tree, hf_quake_CCREP_SERVER_INFO_map,
310                         tvb, offset, len + 1, map);
311         }
312         offset += len + 1;
313
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);
317
318         if (tree) {
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);
325         }
326 }
327
328
329 static void
330 dissect_quake_CCREP_PLAYER_INFO
331 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
332 {
333         gint offset;
334         guint8 player;
335         gint len;
336         gint maxbufsize;
337         char name[QUAKE_MAXSTRING];
338         guint32 colors;
339         guint32 color_shirt;
340         guint32 color_pants;
341         guint32 frags;
342         guint32 connect_time;
343         char address[QUAKE_MAXSTRING];
344
345         offset = 0;
346
347         player = tvb_get_guint8(tvb, offset);
348         if (tree) {
349                 proto_tree_add_uint(tree, hf_quake_CCREQ_PLAYER_INFO_player,
350                         tvb, offset, 1, player);
351         }
352         offset += 1;
353         
354         maxbufsize = MIN((int)sizeof(name), tvb_length_remaining(tvb, offset));
355         len = tvb_get_nstringz0(tvb, offset, maxbufsize, name);
356         if (tree) {
357                 proto_tree_add_string(tree, hf_quake_CCREP_PLAYER_INFO_name,
358                         tvb, offset, len + 1, name);
359         }
360         offset += len + 1;
361
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);
367         if (tree) {
368                 proto_item *colors_item;
369                 proto_tree *colors_tree;
370
371                 colors_item = proto_tree_add_uint(tree,
372                         hf_quake_CCREP_PLAYER_INFO_colors,
373                         tvb, offset + 0, 4, colors);
374                 if (colors_item) {
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);
383                 }
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);
388         }
389         offset += 3*4;
390
391         maxbufsize = MIN((int)sizeof(address), tvb_length_remaining(tvb, offset));
392         len = tvb_get_nstringz0(tvb, offset, maxbufsize, address);
393         if (tree) {
394                 proto_tree_add_string(tree, hf_quake_CCREP_PLAYER_INFO_address,
395                         tvb, offset, len + 1, address);
396         }
397         offset += len + 1;
398 }
399
400
401 static void
402 dissect_quake_CCREP_RULE_INFO
403 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
404 {
405         char rule[QUAKE_MAXSTRING];
406         char value[QUAKE_MAXSTRING];
407         gint maxbufsize;
408         gint len;
409         gint offset;
410
411         if (tvb_length(tvb) == 0) return;
412
413         offset = 0;
414
415         maxbufsize = MIN((int)sizeof(rule), tvb_length_remaining(tvb, offset));
416         len = tvb_get_nstringz0(tvb, offset, maxbufsize, rule);
417         if (tree) {
418                 proto_tree_add_string(tree, hf_quake_CCREP_RULE_INFO_rule,
419                         tvb, offset, len + 1, rule);
420         }
421         offset += len + 1;
422
423         maxbufsize = MIN((int)sizeof(value), tvb_length_remaining(tvb, offset));
424         len = tvb_get_nstringz0(tvb, offset, maxbufsize, value);
425         if (tree) {
426                 proto_tree_add_string(tree, hf_quake_CCREP_RULE_INFO_value,
427                         tvb, offset, len + 1, value);
428         }
429         offset += len + 1;
430 }
431
432
433 static void
434 dissect_quake_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
435 {
436         guint8          command;
437         int             direction;
438         proto_item      *control_item = NULL;
439         proto_tree      *control_tree = NULL;
440         guint           rest_length;
441         tvbuff_t        *next_tvb;
442         
443         command = tvb_get_guint8(tvb, 0);
444         direction = (command & 0x80) ? CCREP : CCREQ;
445
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"));
450         }
451
452         if (tree) {
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"));
457                 if (control_item)
458                         control_tree = proto_item_add_subtree(control_item,
459                                                 ett_quake_control);
460                 proto_tree_add_uint(control_tree, hf_quake_control_command,
461                                         tvb, 0, 1, command);
462         }
463
464         rest_length = tvb_reported_length(tvb) - 1;
465         next_tvb = tvb_new_subset(tvb, 1, rest_length , rest_length);
466         switch (command) {
467                 case CCREQ_CONNECT:
468                         dissect_quake_CCREQ_CONNECT
469                         (next_tvb, pinfo, control_tree);
470                 break;
471                 case CCREQ_SERVER_INFO:
472                         dissect_quake_CCREQ_SERVER_INFO
473                         (next_tvb, pinfo, control_tree);
474                 break;
475                 case CCREQ_PLAYER_INFO:
476                         dissect_quake_CCREQ_PLAYER_INFO
477                         (next_tvb, pinfo, control_tree);
478                 break;
479                 case CCREQ_RULE_INFO:
480                         dissect_quake_CCREQ_RULE_INFO
481                         (next_tvb, pinfo, control_tree);
482                 break;
483                 case CCREP_ACCEPT:
484                         dissect_quake_CCREP_ACCEPT
485                         (next_tvb, pinfo, control_tree);
486                 break;
487                 case CCREP_REJECT:
488                         dissect_quake_CCREP_REJECT
489                         (next_tvb, pinfo, control_tree);
490                 break;
491                 case CCREP_SERVER_INFO:
492                         dissect_quake_CCREP_SERVER_INFO
493                         (next_tvb, pinfo, control_tree);
494                 break;
495                 case CCREP_PLAYER_INFO:
496                         dissect_quake_CCREP_PLAYER_INFO
497                         (next_tvb, pinfo, control_tree);
498                 break;
499                 case CCREP_RULE_INFO:
500                         dissect_quake_CCREP_RULE_INFO
501                         (next_tvb, pinfo, control_tree);
502                 break;
503                 default:
504                         dissect_data(next_tvb, 0, pinfo, control_tree);
505                 break;
506         }
507 }
508
509
510 static void
511 dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
512 {
513         proto_tree      *quake_tree = NULL;
514         proto_item      *quake_item = NULL;
515         guint32         length;
516         guint32         flags;
517         guint32         sequence = 0;
518         guint           rest_length;
519         tvbuff_t        *next_tvb;
520
521         /*
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".
525          */
526         CHECK_DISPLAY_AS_DATA(proto_quake, tvb, pinfo, tree);
527
528         pinfo->current_proto = "QUAKE";
529
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);
534
535         length = tvb_get_ntohl(tvb, 0);
536         flags = length & (~NETFLAG_LENGTH_MASK);
537         length &= NETFLAG_LENGTH_MASK;
538
539         if (tree) {
540                 quake_item = proto_tree_add_item(tree, proto_quake,
541                                 tvb, 0, tvb_length(tvb), FALSE);
542                 if (quake_item)
543                         quake_tree = proto_item_add_subtree(quake_item, ett_quake);
544         }
545
546         if (quake_tree) {
547                 proto_item* flags_item = NULL;
548                 proto_tree* flags_tree = NULL;
549
550                 flags_item = proto_tree_add_uint(quake_tree, hf_quake_header_flags,
551                         tvb, 0, 2, flags);
552                 if (flags_item) {
553                         flags_tree = proto_item_add_subtree(flags_item, ett_quake_flags);
554                 }
555
556                 if (flags_tree) {
557                         proto_tree_add_text(flags_tree, tvb, 0, 2,
558                                 decode_boolean_bitfield(flags, NETFLAG_DATA, 32,
559                                 "Data","-"));
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,
571                                 "Unreliable","-"));
572                         proto_tree_add_text(flags_tree, tvb, 0, 2,
573                                 decode_boolean_bitfield(flags, NETFLAG_CTL, 32,
574                                 "Control","-"));
575                 }
576                 proto_tree_add_uint(quake_tree, hf_quake_header_length,
577                         tvb, 2, 2, length);
578         }
579
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);
584                 return;
585         }
586
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);
590         }
591         if (quake_tree) {
592                 proto_tree_add_uint(quake_tree, hf_quake_header_sequence,
593                         tvb, 4, 4, sequence);
594         }
595
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);
599 }
600
601
602 void
603 proto_reg_handoff_quake(void)
604 {
605         static int Initialized=FALSE;
606         static int ServerPort=0;
607  
608         if (Initialized) {
609                 dissector_delete("udp.port", ServerPort, dissect_quake);
610         } else {
611                 Initialized=TRUE;
612         }
613  
614         /* set port for future deletes */
615         ServerPort=gbl_quakeServerPort;
616  
617         dissector_add("udp.port", gbl_quakeServerPort,
618                         dissect_quake, proto_quake);
619 }
620
621
622 void
623 proto_register_quake(void)
624 {
625   static hf_register_info hf[] = {
626     { &hf_quake_header_flags,
627       { "Flags", "quake.header.flags",
628         FT_UINT16, BASE_HEX, NULL, 0x0,
629         "Flags", HFILL }},
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,
661         "Player", HFILL }},
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 }},
730   };
731         static gint *ett[] = {
732                 &ett_quake,
733                 &ett_quake_control,
734                 &ett_quake_control_colors,
735                 &ett_quake_flags,
736         };
737         module_t *quake_module;
738
739         proto_quake = proto_register_protocol("Quake Network Protocol",
740                                         "QUAKE", "quake");
741         proto_register_field_array(proto_quake, hf, array_length(hf));
742         proto_register_subtree_array(ett, array_length(ett));
743
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);
751 }
752
753