The beginnings of a World of Warcraft (WoW) protocol dissector.
[metze/wireshark/wip.git] / epan / dissectors / packet-wow.c
1 /* packet-wow.c
2  * Routines for World of Warcraft (WoW) protocol dissection
3  * Copyright 2008-2009, Stephen Fisher <stephentfisher@yahoo.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
24  * USA.
25  */
26
27 /* This dissector is based on the MaNGOS project's source code, Stanford's
28  * SRP protocol documents (http://srp.stanford.edu) and RFC 2945: "The SRP
29  * Authentication and Key Exchange System." */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include <glib.h>
40
41 #include <epan/packet.h>
42 #include <epan/prefs.h>
43 #include "packet-tcp.h"
44
45 typedef enum {
46         AUTH_LOGON_CHALLENGE = 0x00,
47         AUTH_LOGON_PROOF     = 0x01,
48         REALM_LIST           = 0x10,
49         XFER_INITIATE        = 0x30,
50         XFER_DATA            = 0x31,
51         XFER_ACCEPT          = 0x32,
52         XFER_RESUME          = 0x33,
53         XFER_CANCEL          = 0x34
54 } auth_cmd_e;
55         
56 static const value_string cmd_vs[] = {
57         { AUTH_LOGON_CHALLENGE, "Authentication Logon Challenge" },
58         { AUTH_LOGON_PROOF,     "Authentication Logon Proof"     },
59         { REALM_LIST,           "Realm List"                     },
60         { XFER_INITIATE,        "Transfer Initiate"              },
61         { XFER_DATA,            "Transfer Data"                  },
62         { XFER_ACCEPT,          "Transfer Accept"                },
63         { XFER_RESUME,          "Transfer Resume"                },
64         { XFER_CANCEL,          "Transfer Cancel"                },
65         { 0, NULL                                                }
66 };
67
68 static const value_string account_type_vs[] = {
69         { 0, "Player"        },
70         { 1, "Moderator"     },
71         { 2, "Game master"   },
72         { 3, "Administrator" },
73         { 0, NULL            }
74 };
75
76 static const value_string realm_status_vs[] = {
77         { 0, "Online"  },
78         { 1, "Locked"  },
79         { 2, "Offline" },
80         { 0, NULL      }
81 };
82
83 static const value_string realm_type_vs[] = {
84         { 0, "Normal"                             },
85         { 1, "Player versus player"               },
86         { 4, "Normal (2)"                         },
87         { 6, "Role playing normal"                },
88         { 8, "Role playing player versus player)" },
89         { 0, NULL                                 }
90 };
91
92 #define WOW_PORT 3724
93
94 #define WOW_CLIENT_TO_SERVER pinfo->destport == WOW_PORT
95 #define WOW_SERVER_TO_CLIENT pinfo->srcport  == WOW_PORT
96
97 /* Forward declaration we need below */
98 void proto_reg_handoff_wow(void);
99
100 /* Initialize the protocol and registered fields */
101 static int proto_wow = -1;
102
103 static int hf_wow_command = -1;
104 static int hf_wow_error = -1;
105 static int hf_wow_pkt_size = -1;
106 static int hf_wow_gamename = -1;
107 static int hf_wow_version1 = -1;
108 static int hf_wow_version2 = -1;
109 static int hf_wow_version3 = -1;
110 static int hf_wow_build = -1;
111 static int hf_wow_platform = -1;
112 static int hf_wow_os = -1;
113 static int hf_wow_country = -1;
114 static int hf_wow_timezone_bias = -1;
115 static int hf_wow_ip = -1;
116 static int hf_wow_srp_i_len = -1;
117 static int hf_wow_srp_i = -1;
118
119 static int hf_wow_srp_b = -1;
120 static int hf_wow_srp_g_len = -1;
121 static int hf_wow_srp_g = -1;
122 static int hf_wow_srp_n_len = -1;
123 static int hf_wow_srp_n = -1;
124 static int hf_wow_srp_s = -1;
125
126 static int hf_wow_srp_a = -1;
127 static int hf_wow_srp_m1 = -1;
128 static int hf_wow_crc_hash = -1;
129 static int hf_wow_num_keys = -1;
130
131 static int hf_wow_srp_m2 = -1;
132
133 static int hf_wow_num_realms = -1;
134 static int hf_wow_realm_type = -1;
135 static int hf_wow_realm_status = -1;
136 static int hf_wow_realm_color = -1;
137 static int hf_wow_realm_name = -1;
138 static int hf_wow_realm_socket = -1;
139 static int hf_wow_realm_population_level = -1;
140 static int hf_wow_realm_num_characters = -1;
141 static int hf_wow_realm_timezone = -1;
142
143 static gboolean wow_preference_desegment = TRUE;
144
145 static gint ett_wow = -1;
146 static gint ett_wow_realms = -1;
147
148 static void dissect_wow_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
149 static guint get_wow_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset);
150
151
152 static gboolean
153 dissect_wow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
154 {
155         gint8 size_field_offset = -1;
156         guint8 cmd;
157
158         cmd = tvb_get_guint8(tvb, 0);
159
160         if(WOW_SERVER_TO_CLIENT && cmd == REALM_LIST)
161                 size_field_offset = 1;
162         if(WOW_CLIENT_TO_SERVER && cmd == AUTH_LOGON_CHALLENGE)
163                 size_field_offset = 2;
164
165         if(size_field_offset > -1) {
166                 tcp_dissect_pdus(tvb, pinfo, tree, wow_preference_desegment,
167                                  size_field_offset+2, get_wow_pdu_len,
168                                  dissect_wow_pdu);
169
170         } else {
171                 /* Doesn't have a size field, so it cannot span multiple
172                    segments.  Therefore, dissect this packet normally. */
173                 dissect_wow_pdu(tvb, pinfo, tree);
174         }
175
176         return TRUE;
177 }
178
179 static guint
180 get_wow_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
181 {
182         gint8 size_field_offset = -1;
183         guint8 cmd;
184         guint16 pkt_len;
185
186         cmd = tvb_get_guint8(tvb, offset);
187
188         if(WOW_SERVER_TO_CLIENT && cmd == REALM_LIST)
189                 size_field_offset = 1;
190         if(WOW_CLIENT_TO_SERVER && cmd == AUTH_LOGON_CHALLENGE)
191                 size_field_offset = 2;
192
193         pkt_len = tvb_get_letohs(tvb, size_field_offset);
194
195         return pkt_len + size_field_offset + 2;
196 }
197
198
199 static void
200 dissect_wow_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
201 {
202         proto_item *ti;
203         proto_tree *wow_tree, *wow_realms_tree;
204
205         gchar *string, *realm_name;
206         guint8 cmd, srp_i_len, srp_g_len, srp_n_len;
207         guint16 num_realms;
208         guint32 offset = 0;
209         gint len, i;
210
211         if(check_col(pinfo->cinfo, COL_PROTOCOL))
212                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WOW");
213
214         if(check_col(pinfo->cinfo, COL_INFO))
215                 col_clear(pinfo->cinfo, COL_INFO);
216
217         cmd = tvb_get_guint8(tvb, offset);
218
219         if(check_col(pinfo->cinfo, COL_INFO)) {
220                 col_set_str(pinfo->cinfo, COL_INFO,
221                             val_to_str(cmd, cmd_vs,
222                                        "Unrecognized packet type"));
223         }
224         
225         if(tree) {
226                 ti = proto_tree_add_item(tree, proto_wow, tvb, 0, -1, TRUE);
227                 wow_tree = proto_item_add_subtree(ti, ett_wow);
228
229                 proto_tree_add_item(wow_tree, hf_wow_command, tvb, offset, 1,
230                                     TRUE);
231                 offset += 1;
232
233                 switch(cmd) {
234
235                 case AUTH_LOGON_CHALLENGE :
236
237                         if(WOW_CLIENT_TO_SERVER) {
238                                 proto_tree_add_item(wow_tree, hf_wow_error, tvb,
239                                                     offset, 1, TRUE);
240                                 offset += 1;
241                                 
242                                 proto_tree_add_item(wow_tree, hf_wow_pkt_size,
243                                                     tvb, offset, 2, TRUE);
244                                 offset += 2;
245                                 
246                                 string = g_strreverse(tvb_get_string(tvb, offset, 4));
247                                 proto_tree_add_string(wow_tree, hf_wow_gamename,
248                                                       tvb, offset, 4, string);
249                                 g_free(string);
250                                 offset += 4;
251                                 
252                                 proto_tree_add_item(wow_tree, hf_wow_version1,
253                                                     tvb, offset, 1, TRUE);
254                                 offset += 1;
255                                 
256                                 proto_tree_add_item(wow_tree, hf_wow_version2,
257                                                     tvb, offset, 1, TRUE);
258                                 offset += 1;
259                                 
260                                 proto_tree_add_item(wow_tree, hf_wow_version3,
261                                                     tvb, offset, 1, TRUE);
262                                 offset += 1;
263                                 
264                                 proto_tree_add_item(wow_tree, hf_wow_build, tvb,
265                                                     offset, 2, TRUE);
266                                 offset += 2;
267                                 
268                                 string = g_strreverse(tvb_get_string(tvb, offset, 4));
269                                 proto_tree_add_string(wow_tree, hf_wow_platform,
270                                                       tvb, offset, 4, string);
271                                 g_free(string);
272                                 offset += 4;
273                                 
274                                 string = g_strreverse(tvb_get_string(tvb, offset, 4));
275                                 proto_tree_add_string(wow_tree, hf_wow_os, tvb,
276                                                       offset, 4, string);
277                                 g_free(string);
278                                 offset += 4;
279                                 
280                                 string = g_strreverse(tvb_get_string(tvb, offset, 4));
281                                 proto_tree_add_string(wow_tree, hf_wow_country,
282                                                       tvb, offset, 4, string);
283                                 g_free(string);
284                                 offset += 4;
285                                 
286                                 proto_tree_add_item(wow_tree,
287                                                     hf_wow_timezone_bias,
288                                                     tvb, offset, 4, TRUE);
289                                 offset += 4;
290
291                                 proto_tree_add_item(wow_tree, hf_wow_ip, tvb,
292                                                     offset, 4, FALSE);
293                                 offset += 4;
294                         
295                                 proto_tree_add_item(wow_tree,
296                                                     hf_wow_srp_i_len,
297                                                     tvb, offset, 1, TRUE);
298                                 srp_i_len = tvb_get_guint8(tvb, offset);
299                                 offset += 1;
300
301                                 proto_tree_add_item(wow_tree,
302                                                     hf_wow_srp_i, tvb,
303                                                     offset, srp_i_len,
304                                                     TRUE);
305                                 offset += srp_i_len;
306
307
308                         } else if(WOW_SERVER_TO_CLIENT) {
309                                 proto_tree_add_item(wow_tree, hf_wow_error, tvb,
310                                                     offset, 1, TRUE);
311                                 offset += 1;
312                                 
313                                 offset += 1; /* Unknown field */
314
315                                 proto_tree_add_item(wow_tree, hf_wow_srp_b, tvb,
316                                                     offset, 32, TRUE);
317                                 offset += 32;
318
319                                 proto_tree_add_item(wow_tree, hf_wow_srp_g_len,
320                                                     tvb, offset, 1, TRUE);
321                                 srp_g_len = tvb_get_guint8(tvb, offset);
322                                 offset += 1;
323
324                                 proto_tree_add_item(wow_tree, hf_wow_srp_g, tvb,
325                                                     offset, srp_g_len, TRUE);
326                                 offset += srp_g_len;
327
328                                 proto_tree_add_item(wow_tree, hf_wow_srp_n_len,
329                                                     tvb, offset, 1, TRUE);
330                                 srp_n_len = tvb_get_guint8(tvb, offset);
331                                 offset += 1;
332
333                                 proto_tree_add_item(wow_tree, hf_wow_srp_n, tvb,
334                                                     offset, srp_n_len, TRUE);
335                                 offset += srp_n_len;
336
337                                 proto_tree_add_item(wow_tree, hf_wow_srp_s, tvb,
338                                                     offset, 32, TRUE);
339                                 offset += 32;
340
341                                 offset += 16; /* Unknown field */
342                         }
343                         
344                         break;
345
346                 case AUTH_LOGON_PROOF :
347
348                         if(WOW_CLIENT_TO_SERVER) {
349                                 proto_tree_add_item(wow_tree, hf_wow_srp_a, tvb,
350                                                     offset, 32, TRUE);
351                                 offset += 32;
352
353                                 proto_tree_add_item(wow_tree, hf_wow_srp_m1,
354                                                     tvb, offset, 20, TRUE);
355                                 offset += 20;
356
357                                 proto_tree_add_item(wow_tree, hf_wow_crc_hash,
358                                                     tvb, offset, 20, TRUE);
359                                 offset += 20;
360
361                                 proto_tree_add_item(wow_tree, hf_wow_num_keys,
362                                                     tvb, offset, 1, TRUE);
363                                 offset += 1;
364
365                                 offset += 1; /* Unknown field */
366
367                         } else if(WOW_SERVER_TO_CLIENT) {
368                                 proto_tree_add_item(wow_tree, hf_wow_error, tvb,
369                                                     offset, 1, TRUE);
370                                 offset += 1;
371
372                                 proto_tree_add_item(wow_tree, hf_wow_srp_m2,
373                                                     tvb, offset, 20, TRUE);
374                                 offset += 20;
375
376                                 offset += 4; /* Unknown field */
377
378                                 offset += 2; /* Unknown field */
379                         }
380
381                         break;
382
383                 case REALM_LIST : 
384
385                         if(WOW_CLIENT_TO_SERVER) {
386
387
388                         } else if(WOW_SERVER_TO_CLIENT) {
389                                 
390                                 proto_tree_add_item(wow_tree, hf_wow_pkt_size,
391                                                     tvb, offset, 2, TRUE);
392                                 offset += 2;
393                                 
394                                 offset += 4; /* Unknown field; always 0 */
395                         
396                                 proto_tree_add_item(wow_tree, hf_wow_num_realms,
397                                                     tvb, offset, 2, TRUE);
398                                 num_realms = tvb_get_letohs(tvb, offset);
399                                 offset += 2;
400
401                                 for(i = 1; i <= num_realms; i++) {
402                                         realm_name = tvb_get_stringz(tvb,
403                                                                      offset + 3,
404                                                                      &len);
405
406                                         ti = proto_tree_add_text(wow_tree, tvb,
407                                                                  offset, 0,
408                                                                  "%s",
409                                                                  realm_name);
410                                         
411                                         wow_realms_tree = proto_item_add_subtree(ti, ett_wow_realms);
412                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_type, tvb, offset, 1, TRUE);
413                                         offset += 1;
414
415                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_status, tvb, offset, 1, TRUE);
416                                         offset += 1;
417
418                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_color, tvb, offset, 1, TRUE);
419                                         offset += 1;
420
421                                         proto_tree_add_string(wow_realms_tree, hf_wow_realm_name, tvb, offset, len, realm_name);
422                                         g_free(realm_name);
423                                         offset += len;
424
425                                         string = tvb_get_stringz(tvb, offset,
426                                                                  &len);
427                                         proto_tree_add_string(wow_realms_tree, hf_wow_realm_socket, tvb, offset, len, string);
428                                         g_free(string);
429                                         offset += len;
430
431                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_population_level, tvb, offset, 4, TRUE);
432                                         offset += 4;
433
434                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_num_characters, tvb, offset, 1, TRUE);
435                                         offset += 1;
436
437                                         proto_tree_add_item(wow_realms_tree, hf_wow_realm_timezone, tvb, offset, 1, TRUE);
438                                         offset += 1;
439
440                                         offset += 1; /* Unknown field */
441                                 }
442
443                                 break;
444                         }
445                 }
446         }
447 }
448
449
450 void
451 proto_register_wow(void)
452 {
453         module_t *wow_module; /* For our preferences */
454
455         static hf_register_info hf[] = {
456                 { &hf_wow_command,
457                   { "Command", "wow.cmd",
458                     FT_UINT8, BASE_HEX, VALS(cmd_vs), 0,
459                     "Type of packet", HFILL }
460                 },
461                 
462                 { &hf_wow_error,
463                   { "Error", "wow.error",
464                     FT_UINT8, BASE_DEC, 0, 0,
465                     "", HFILL }
466                 },
467                 { &hf_wow_pkt_size,
468                   { "Packet size", "wow.pkt_size",
469                     FT_UINT16, BASE_DEC, 0, 0,
470                     "", HFILL }
471                 },
472                 { &hf_wow_gamename,
473                   { "Game name", "wow.gamename",
474                     FT_STRING, BASE_NONE, 0, 0,
475                     "", HFILL }
476                 },
477                 { &hf_wow_version1,
478                   { "Version 1", "wow.version1",
479                     FT_UINT8, BASE_DEC, 0, 0,
480                     "", HFILL }
481                 },
482                 { &hf_wow_version2,
483                   { "Version 2", "wow.version2",
484                     FT_UINT8, BASE_DEC, 0, 0,
485                     "", HFILL }
486                 },
487                 { &hf_wow_version3,
488                   { "Version 3", "wow.version3",
489                     FT_UINT8, BASE_DEC, 0, 0,
490                     "", HFILL }
491                 },
492                 { &hf_wow_build,
493                   { "Build", "wow.build",
494                     FT_UINT16, BASE_DEC, 0, 0,
495                     "", HFILL }
496                 },
497                 { &hf_wow_platform,
498                   { "Platform", "wow.platform",
499                     FT_STRING, BASE_NONE, 0, 0,
500                     "CPU architecture of client system", HFILL }
501                 },
502                 { &hf_wow_os,
503                   { "Operating system", "wow.os",
504                     FT_STRING, BASE_NONE, 0, 0,
505                     "Operating system of client system", HFILL }
506                 },
507                 { &hf_wow_country,
508                   { "Country", "wow.country",
509                     FT_STRING, BASE_NONE, 0, 0,
510                     "Language and country of client system", HFILL }
511                 },
512                 { &hf_wow_timezone_bias,
513                   { "Timezone bias", "wow.timezone_bias",
514                     FT_UINT32, BASE_DEC, 0, 0,
515                     "", HFILL }
516                 },
517                 { &hf_wow_ip,
518                   { "IP address", "wow.ip",
519                     FT_IPv4, BASE_NONE, 0, 0,
520                     "Client's actual IP address", HFILL }
521                 },
522                 { &hf_wow_srp_i_len,
523                   { "SRP I length", "wow.srp.i_len",
524                     FT_UINT8, BASE_DEC, 0, 0,
525                     "Secure Remote Password protocol 'I' value length", HFILL }
526                 },
527                 { &hf_wow_srp_i,
528                   { "SRP I", "wow.srp.i",
529                     FT_STRING, BASE_NONE, 0, 0,
530                     "Secure Remote Password protocol 'I' value (username)", HFILL }
531                 },
532                 { &hf_wow_srp_b,
533                   { "SRP B", "wow.srp.b",
534                     FT_BYTES, BASE_NONE, 0, 0,
535                     "Secure Remote Password protocol 'B' value (one of the public ephemeral values)", HFILL }
536                 },
537                 { &hf_wow_srp_g_len,
538                   { "SRP g length", "wow.srp.g_len",
539                     FT_UINT8, BASE_DEC, 0, 0,
540                     "Secure Remote Password protocol 'g' value length",
541                     HFILL }
542                 },
543                 { &hf_wow_srp_g,
544                   { "SRP g", "wow.srp.g",
545                     FT_BYTES, BASE_NONE, 0, 0,
546                     "Secure Remote Password protocol 'g' value", HFILL }
547                 },
548                 { &hf_wow_srp_n_len,
549                   { "SRP N length", "wow.srp.n_len",
550                     FT_UINT8, BASE_DEC, 0, 0,
551                     "Secure Remote Password protocol 'N' value length",
552                     HFILL }
553                 },
554                 { &hf_wow_srp_n,
555                   { "SRP N", "wow.srp.n",
556                     FT_BYTES, BASE_NONE, 0, 0,
557                     "Secure Remote Password protocol 'N' value (a large safe prime)", HFILL }
558                 },
559                 { &hf_wow_srp_s,
560                   { "SRP s", "wow.srp.s",
561                     FT_BYTES, BASE_NONE, 0, 0,
562                     "Secure Remote Password protocol 's' (user's salt) value",
563                     HFILL }
564                 },
565                 { &hf_wow_srp_a,
566                   { "SRP A", "wow.srp.a",
567                     FT_BYTES, BASE_NONE, 0, 0,
568                     "Secure Remote Password protocol 'A' value (one of the public ephemeral values)", HFILL }
569                 },
570                 { &hf_wow_srp_m1,
571                   { "SRP M1", "wow.srp.m1",
572                     FT_BYTES, BASE_NONE, 0, 0,
573                     "Secure Remote Password protocol 'M1' value ", HFILL }
574                 },
575                 { &hf_wow_crc_hash,
576                   { "CRC hash", "wow.crc_hash",
577                     FT_BYTES, BASE_NONE, 0, 0,
578                     "", HFILL }
579                 },
580                 { &hf_wow_num_keys,
581                   { "Number of keys", "wow.num_keys",
582                     FT_UINT8, BASE_DEC, 0, 0,
583                     "", HFILL }
584                 },
585                 { &hf_wow_srp_m2,
586                   { "SRP M2", "wow.srp.m2",
587                     FT_BYTES, BASE_NONE, 0, 0,
588                     "Secure Remote Password protocol 'M2' value", HFILL }
589                 },
590                 { &hf_wow_num_realms,
591                   { "Number of realms", "wow.num_realms",
592                     FT_UINT16, BASE_DEC, 0, 0,
593                     "", HFILL }
594                 },
595                 { &hf_wow_realm_type,
596                   { "Type", "wow.realm_type",
597                     FT_UINT8, BASE_DEC, VALS(realm_type_vs), 0,
598                     "Also known as realm icon", HFILL }
599                 },
600                 { &hf_wow_realm_status,
601                   { "Status", "wow.realm_status",
602                     FT_UINT8, BASE_DEC, VALS(realm_status_vs), 0,
603                     "", HFILL }
604                 },
605                 { &hf_wow_realm_color,
606                   { "Color", "wow.realm_color",
607                     FT_UINT8, BASE_DEC, 0, 0,
608                     "", HFILL }
609                 },
610                 { &hf_wow_realm_name,
611                   {  "Name", "wow.realm_name",
612                      FT_STRINGZ, BASE_NONE, 0, 0,
613                      "", HFILL }
614                 },
615                 { &hf_wow_realm_socket,
616                   { "Server socket", "wow.realm_socket",
617                     FT_STRINGZ, BASE_NONE, 0, 0,
618                     "IP address and port to connect to on the server to reach this realm", HFILL }
619                 },
620                 { &hf_wow_realm_population_level,
621                   { "Population level", "wow.realm_population_level",
622                     FT_FLOAT, BASE_NONE, 0, 0,
623                     "", HFILL }
624                 },
625                 { &hf_wow_realm_num_characters,
626                   { "Number of characters", "wow.realm_num_characters",
627                     FT_UINT8, BASE_DEC, 0, 0,
628                     "Number of characters the user has in this realm", HFILL }
629                 },
630                 { &hf_wow_realm_timezone,
631                   { "Timezone", "wow.realm_timezone",
632                     FT_UINT8, BASE_DEC, 0, 0,
633                     "", HFILL }
634                 }
635         };
636
637         static gint *ett[] = {
638                 &ett_wow,
639                 &ett_wow_realms
640         };
641
642         proto_wow = proto_register_protocol("World of Warcraft",
643                                             "WOW", "wow");
644
645         proto_register_field_array(proto_wow, hf, array_length(hf));
646         proto_register_subtree_array(ett, array_length(ett));
647
648         wow_module = prefs_register_protocol(proto_wow, proto_reg_handoff_wow);
649
650         prefs_register_bool_preference(wow_module, "desegment", "Reassemble wow messages spanning multiple TCP segments.", "Whether the wow dissector should reassemble messages spanning multiple TCP segments.  To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &wow_preference_desegment);
651
652 }
653
654 void
655 proto_reg_handoff_wow(void)
656 {
657         static gboolean inited = FALSE;
658
659         if(!inited) {
660                 dissector_handle_t wow_handle;
661
662                 wow_handle = new_create_dissector_handle(dissect_wow,
663                                                          proto_wow);
664                 dissector_add("tcp.port", WOW_PORT, wow_handle);
665
666                 inited = TRUE;
667         }
668 }