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