As with "file_write_error_message()", so with
[obnox/wireshark/wip.git] / packet-quakeworld.c
index 448cae475cf9945df9a2f5d083fec3c1c757b26b..8455e8133f6db8ea826b95ed8170ab4123c13383 100644 (file)
@@ -4,24 +4,24 @@
  * Uwe Girlich <uwe@planetquake.com>
  *     http://www.idsoftware.com/q1source/q1source.zip
  *
- * $Id: packet-quakeworld.c,v 1.2 2001/07/21 15:34:44 girlich Exp $
+ * $Id: packet-quakeworld.c,v 1.19 2003/09/21 20:06:01 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from packet-quake.c
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 # include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
 #include <glib.h>
 #include <string.h>
-#include "packet.h"
+#include <epan/packet.h>
 #include "prefs.h"
 
 static int proto_quakeworld = -1;
@@ -49,6 +45,7 @@ static int hf_quakeworld_game = -1;
 static int hf_quakeworld_connectionless_marker = -1;
 static int hf_quakeworld_connectionless_text = -1;
 static int hf_quakeworld_connectionless_command = -1;
+static int hf_quakeworld_connectionless_arguments = -1;
 static int hf_quakeworld_connectionless_connect_version = -1;
 static int hf_quakeworld_connectionless_connect_qport = -1;
 static int hf_quakeworld_connectionless_connect_challenge = -1;
@@ -67,6 +64,7 @@ static int hf_quakeworld_game_qport = -1;
 static gint ett_quakeworld = -1;
 static gint ett_quakeworld_connectionless = -1;
 static gint ett_quakeworld_connectionless_text = -1;
+static gint ett_quakeworld_connectionless_arguments = -1;
 static gint ett_quakeworld_connectionless_connect_infostring = -1;
 static gint ett_quakeworld_connectionless_connect_infostring_key_value = -1;
 static gint ett_quakeworld_game = -1;
@@ -75,7 +73,7 @@ static gint ett_quakeworld_game_seq2 = -1;
 static gint ett_quakeworld_game_clc = -1;
 static gint ett_quakeworld_game_svc = -1;
 
-
+static dissector_handle_t data_handle;
 
 /*
    helper functions, they may ave to go somewhere else
@@ -84,11 +82,13 @@ static gint ett_quakeworld_game_svc = -1;
        quakeworldsource/client/common.c
 */
 
-static char            com_token[1024];
+#define MAX_TEXT_SIZE  2048
+
+static char            com_token[MAX_TEXT_SIZE+1];
 static int             com_token_start;
 static int             com_token_length;
 
-char *
+static char *
 COM_Parse (char *data)
 {
        int     c;
@@ -158,14 +158,14 @@ static    int             cmd_argv_length[MAX_ARGS];
 
 
 
-int
+static int
 Cmd_Argc(void)
 {
        return cmd_argc;
 }
 
 
-char*
+static char*
 Cmd_Argv(int arg)
 {
        if ( arg >= cmd_argc )
@@ -174,7 +174,7 @@ Cmd_Argv(int arg)
 }
 
 
-int
+static int
 Cmd_Argv_start(int arg)
 {
        if ( arg >= cmd_argc )
@@ -183,7 +183,7 @@ Cmd_Argv_start(int arg)
 }
 
 
-int
+static int
 Cmd_Argv_length(int arg)
 {
        if ( arg >= cmd_argc )
@@ -192,13 +192,13 @@ Cmd_Argv_length(int arg)
 }
 
 
-void
+static void
 Cmd_TokenizeString(char* text)
 {
        int i;
        int start;
        int length;
-       
+
 
        /* clear the args from the last string */
        for (i=0 ; i<cmd_argc ; i++)
@@ -225,7 +225,7 @@ Cmd_TokenizeString(char* text)
 
                if (!*text)
                        return;
-                       
+
                text = COM_Parse (text);
                if (!text)
                        return;
@@ -242,6 +242,81 @@ Cmd_TokenizeString(char* text)
 }
 
 
+static void
+dissect_id_infostring(tvbuff_t *tvb, proto_tree* tree,
+       int offset, char* infostring,
+       gint ett_key_value, int hf_key_value, int hf_key, int hf_value)
+{
+       char * newpos = infostring;
+       int end_of_info = FALSE;
+
+       /* to look at all the key/value pairs, we destroy infostring */
+       while(!end_of_info) {
+               char* keypos;
+               char* valuepos;
+               int keylength;
+               char* keyvaluesep;
+               int valuelength;
+               char* valueend;
+
+               keypos = newpos;
+               if (*keypos == 0) break;
+               if (*keypos == '\\') keypos++;
+
+               for (keylength = 0
+                       ;
+                       *(keypos + keylength) != '\\' &&
+                       *(keypos + keylength) != 0
+                       ;
+                       keylength++) ;
+               keyvaluesep = keypos + keylength;
+               if (*keyvaluesep == 0) break;
+               valuepos = keyvaluesep+1;
+               for (valuelength = 0
+                       ;
+                       *(valuepos + valuelength) != '\\' &&
+                       *(valuepos + valuelength) != 0
+                       ;
+                       valuelength++) ;
+               valueend = valuepos + valuelength;
+               if (*valueend == 0) {
+                       end_of_info = TRUE;
+               }
+               *(keyvaluesep) = '=';
+               *(valueend) = 0;
+
+               if (tree) {
+                       proto_item* sub_item = NULL;
+                       proto_tree* sub_tree = NULL;
+
+                       sub_item = proto_tree_add_string(tree,
+                               hf_key_value,
+                               tvb,
+                               offset + (keypos-infostring),
+                               keylength + 1 + valuelength, keypos);
+                       if (sub_item)
+                               sub_tree =
+                                       proto_item_add_subtree(
+                                       sub_item,
+                                       ett_key_value);
+                       *(keyvaluesep) = 0;
+                       if (sub_tree) {
+                               proto_tree_add_string(sub_tree,
+                                       hf_key,
+                                       tvb,
+                                       offset + (keypos-infostring),
+                                       keylength, keypos);
+                               proto_tree_add_string(sub_tree,
+                                       hf_value,
+                                       tvb,
+                                       offset + (valuepos-infostring),
+                                       valuelength, valuepos);
+                       }
+               }
+               newpos = valueend + 1;
+       }
+}
+
 
 static const value_string names_direction[] = {
 #define DIR_C2S 0
@@ -258,11 +333,11 @@ static unsigned int gbl_quakeworldServerPort=PORT_MASTER;
 
 
 /* out of band message id bytes (taken out of quakeworldsource/client/protocol.h */
+
 /* M = master, S = server, C = client, A = any */
 /* the second character will allways be \n if the message isn't a single */
 /* byte long (?? not true anymore?) */
+
 #define S2C_CHALLENGE          'c'
 #define S2C_CONNECTION         'j'
 #define A2A_PING               'k'     /* respond with an A2A_ACK */
@@ -270,7 +345,7 @@ static unsigned int gbl_quakeworldServerPort=PORT_MASTER;
 #define A2A_NACK               'm'     /* [+ comment] general failure */
 #define A2A_ECHO               'e'     /* for echoing */
 #define A2C_PRINT              'n'     /* print a message on client */
+
 #define S2M_HEARTBEAT          'a'     /* + serverinfo + userlist + fraglist */
 #define A2C_CLIENT_COMMAND     'B'     /* + command line */
 #define S2M_SHUTDOWN           'C'
@@ -284,19 +359,18 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
        proto_item      *cl_item = NULL;
        proto_item      *text_item = NULL;
        proto_tree      *text_tree = NULL;
-       guint8          text[2048];
-       int             maxbufsize = 0;
+       guint8          text[MAX_TEXT_SIZE+1];
        int             len;
        int             offset;
        guint32 marker;
        int command_len;
-       char command[2048];
+       char command[MAX_TEXT_SIZE+1];
        int command_finished = FALSE;
 
        marker = tvb_get_ntohl(tvb, 0);
        if (tree) {
                cl_item = proto_tree_add_text(tree, tvb,
-                               0, tvb_length(tvb), "Connectionless");
+                               0, -1, "Connectionless");
                if (cl_item)
                        cl_tree = proto_item_add_subtree(
                                cl_item, ett_quakeworld_connectionless);
@@ -310,11 +384,10 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
        /* all the rest of the packet is just text */
         offset = 4;
 
-        maxbufsize = MIN((gint)sizeof(text), tvb_length_remaining(tvb, offset));
-        len = tvb_get_nstringz0(tvb, offset, maxbufsize, text);
+        len = tvb_get_nstringz0(tvb, offset, sizeof(text), text);
        /* actually, we should look for a eol char and stop already there */
 
-        if (tree) {
+        if (cl_tree) {
                 text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text,
                         tvb, offset, len + 1, text);
                if (text_item) {
@@ -329,7 +402,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
 
                Cmd_TokenizeString(text);
                c = Cmd_Argv(0);
-               
+
                /* client to sever commands */
                if (strcmp(c,"ping") == 0) {
                        strcpy(command, "Ping");
@@ -345,6 +418,8 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                        int qport;
                        int challenge;
                        char *infostring;
+                       proto_item *argument_item = NULL;
+                       proto_tree *argument_tree = NULL;
                        proto_item *info_item = NULL;
                        proto_tree *info_tree = NULL;
                        strcpy(command, "Connect");
@@ -352,31 +427,38 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                        if (text_tree) {
                                proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
                                        tvb, offset, command_len, command);
-                                       command_finished=TRUE;
+                               argument_item = proto_tree_add_string(text_tree,
+                                       hf_quakeworld_connectionless_arguments,
+                                       tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1),
+                                       text + Cmd_Argv_start(1));
+                               if (argument_item) {
+                                       argument_tree =
+                                               proto_item_add_subtree(argument_item,
+                                                       ett_quakeworld_connectionless_arguments);
+                               }
+                               command_finished=TRUE;
                        }
                        version = atoi(Cmd_Argv(1));
                        qport = atoi(Cmd_Argv(2));
                        challenge = atoi(Cmd_Argv(3));
                        infostring = Cmd_Argv(4);
-                       if (text_tree) {
-                               char * newpos;
-                               int end_of_info;
-                               proto_tree_add_uint(text_tree,
+                       if (argument_tree) {
+                               proto_tree_add_uint(argument_tree,
                                        hf_quakeworld_connectionless_connect_version,
                                        tvb,
                                        offset + Cmd_Argv_start(1),
                                        Cmd_Argv_length(1), version);
-                               proto_tree_add_uint(text_tree,
+                               proto_tree_add_uint(argument_tree,
                                        hf_quakeworld_connectionless_connect_qport,
                                        tvb,
                                        offset + Cmd_Argv_start(2),
                                        Cmd_Argv_length(2), qport);
-                               proto_tree_add_int(text_tree,
+                               proto_tree_add_int(argument_tree,
                                        hf_quakeworld_connectionless_connect_challenge,
                                        tvb,
                                        offset + Cmd_Argv_start(3),
                                        Cmd_Argv_length(3), challenge);
-                               info_item = proto_tree_add_string(text_tree,
+                               info_item = proto_tree_add_string(argument_tree,
                                        hf_quakeworld_connectionless_connect_infostring,
                                        tvb,
                                        offset + Cmd_Argv_start(4),
@@ -384,73 +466,12 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                                if (info_item)
                                        info_tree = proto_item_add_subtree(
                                                info_item, ett_quakeworld_connectionless_connect_infostring);
-                               /* to look at all the key/value pairs, we destroy infostring */
-                               newpos = infostring;
-                               end_of_info = FALSE;
-                               while(!end_of_info) {
-                                       char* keypos;
-                                       char* valuepos;
-                                       int keylength;
-                                       char* keyvaluesep;
-                                       int valuelength;
-                                       char* valueend;
-
-                                       keypos = newpos;
-                                       if (*keypos == 0) break;
-                                       if (*keypos == '\\') keypos++;
-
-                                       for (keylength = 0
-                                               ;
-                                               *(keypos + keylength) != '\\' && 
-                                               *(keypos + keylength) != 0
-                                               ;
-                                               keylength++) ;
-                                       keyvaluesep = keypos + keylength;
-                                       if (*keyvaluesep == 0) break;
-                                       valuepos = keyvaluesep+1;
-                                       for (valuelength = 0
-                                               ;
-                                               *(valuepos + valuelength) != '\\' && 
-                                               *(valuepos + valuelength) != 0
-                                               ;
-                                               valuelength++) ;
-                                       valueend = valuepos + valuelength;
-                                       if (*valueend == 0) {
-                                               end_of_info = TRUE;
-                                       }
-                                       *(keyvaluesep) = '=';
-                                       *(valueend) = 0;
-                                       
-                                       if (info_tree) {
-                                               proto_item* sub_item = NULL;
-                                               proto_tree* sub_tree = NULL;
-
-                                               sub_item = proto_tree_add_string(info_tree,
-                                                       hf_quakeworld_connectionless_connect_infostring_key_value,
-                                                       tvb,
-                                                       offset + Cmd_Argv_start(4) + (keypos-infostring),
-                                                       keylength + 1 + valuelength, keypos);
-                                               if (sub_item) 
-                                                       sub_tree =
-                                                               proto_item_add_subtree(
-                                                               sub_item,
-                                                               ett_quakeworld_connectionless_connect_infostring_key_value);
-                                               *(keyvaluesep) = 0;
-                                               if (sub_tree) {
-                                                       proto_tree_add_string(sub_tree,
-                                                               hf_quakeworld_connectionless_connect_infostring_key,
-                                                               tvb,
-                                                               offset + Cmd_Argv_start(4) + (keypos-infostring),
-                                                               keylength, keypos);
-                                                       proto_tree_add_string(sub_tree,
-                                                               hf_quakeworld_connectionless_connect_infostring_value,
-                                                               tvb,
-                                                               offset + Cmd_Argv_start(4) + (valuepos-infostring),
-                                                               valuelength, valuepos);
-                                               }
-                                       }
-                                       newpos = valueend + 1;
-                               }
+                               dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4),
+                                       infostring,
+                                       ett_quakeworld_connectionless_connect_infostring_key_value,
+                                       hf_quakeworld_connectionless_connect_infostring_key_value,
+                                       hf_quakeworld_connectionless_connect_infostring_key,
+                                       hf_quakeworld_connectionless_connect_infostring_value);
                        }
                } else if (strcmp(c,"getchallenge") == 0) {
                        strcpy(command, "Get Challenge");
@@ -458,17 +479,28 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                } else if (strcmp(c,"rcon") == 0) {
                        char* password;
                        int i;
-                       char remaining[1024];
+                       char remaining[MAX_TEXT_SIZE+1];
+                       proto_item *argument_item = NULL;
+                       proto_tree *argument_tree = NULL;
                        strcpy(command, "Remote Command");
                        command_len = Cmd_Argv_length(0);
                        if (text_tree) {
                                proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
                                        tvb, offset, command_len, command);
-                                       command_finished=TRUE;
+                               argument_item = proto_tree_add_string(text_tree,
+                                       hf_quakeworld_connectionless_arguments,
+                                       tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1),
+                                       text + Cmd_Argv_start(1));
+                               if (argument_item) {
+                                       argument_tree =
+                                               proto_item_add_subtree(argument_item,
+                                                       ett_quakeworld_connectionless_arguments);
+                               }
+                               command_finished=TRUE;
                        }
                        password = Cmd_Argv(1);
-                       if (text_tree) {
-                               proto_tree_add_string(text_tree,
+                       if (argument_tree) {
+                               proto_tree_add_string(argument_tree,
                                        hf_quakeworld_connectionless_rcon_password,
                                        tvb,
                                        offset + Cmd_Argv_start(1),
@@ -480,7 +512,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                                strcat (remaining, " ");
                        }
                        if (text_tree) {
-                               proto_tree_add_string(text_tree,
+                               proto_tree_add_string(argument_tree,
                                        hf_quakeworld_connectionless_rcon_command,
                                        tvb, offset + Cmd_Argv_start(2),
                                        Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) -
@@ -523,11 +555,11 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                        command_len = len;
                }
        }
-               
-       if (check_col(pinfo->fd, COL_INFO)) {
-               col_append_fstr(pinfo->fd, COL_INFO, " %s", command);
+
+       if (check_col(pinfo->cinfo, COL_INFO)) {
+               col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command);
        }
-               
+
        if (text_tree && !command_finished) {
                proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
                        tvb, offset, command_len, command);
@@ -544,7 +576,7 @@ dissect_quakeworld_client_commands(tvbuff_t *tvb, packet_info *pinfo,
           the information from my QWD specs:
                http://www.planetquake.com/demospecs/qwd/
        */
-       dissect_data(tvb, 0, pinfo, tree);
+       call_dissector(data_handle,tvb, pinfo, tree);
 }
 
 
@@ -556,7 +588,7 @@ dissect_quakeworld_server_commands(tvbuff_t *tvb, packet_info *pinfo,
           the information from my QWD specs:
                http://www.planetquake.com/demospecs/qwd/
        */
-       dissect_data(tvb, 0, pinfo, tree);
+       call_dissector(data_handle,tvb, pinfo, tree);
 }
 
 
@@ -585,7 +617,7 @@ dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
 
        if (tree) {
                game_item = proto_tree_add_text(tree, tvb,
-                               0, tvb_length(tvb), "Game");
+                               0, -1, "Game");
                if (game_item)
                        game_tree = proto_item_add_subtree(
                                game_item, ett_quakeworld_game);
@@ -617,7 +649,7 @@ dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
        if (game_tree) {
                proto_item *seq2_item = proto_tree_add_text(game_tree,
                        tvb, offset, 4, "Acknowledge Sequence: %u (%s)",
-                       seq2, val_to_str(rel2,names_reliable,"%u"));;
+                       seq2, val_to_str(rel2,names_reliable,"%u"));
                if (seq2_item) {
                        proto_tree *seq2_tree = proto_item_add_subtree(
                                seq2_item, ett_quakeworld_game_seq2);
@@ -633,7 +665,7 @@ dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
                /* client to server */
                guint16 qport = tvb_get_letohs(tvb, offset);
                if (game_tree) {
-                       proto_tree_add_uint(game_tree, hf_quakeworld_game_qport, 
+                       proto_tree_add_uint(game_tree, hf_quakeworld_game_qport,
                                tvb, offset, 2, qport);
                }
                offset +=2;
@@ -650,8 +682,7 @@ dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
                        proto_tree *c_tree = NULL;
                        if (tree) {
                                c_item = proto_tree_add_text(game_tree, next_tvb,
-                               0, tvb_length(next_tvb),
-                               "Client Commands");
+                               0, -1, "Client Commands");
                                if (c_item) {
                                        c_tree = proto_item_add_subtree(
                                                c_item, ett_quakeworld_game_clc);
@@ -664,8 +695,7 @@ dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
                        proto_tree *c_tree = NULL;
                        if (tree) {
                                c_item = proto_tree_add_text(game_tree, next_tvb,
-                               0, tvb_length(next_tvb),
-                               "Server Commands");
+                               0, -1, "Server Commands");
                                if (c_item) {
                                        c_tree = proto_item_add_subtree(
                                        c_item, ett_quakeworld_game_svc);
@@ -684,27 +714,18 @@ dissect_quakeworld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        proto_item      *quakeworld_item = NULL;
        int             direction;
 
-       /*
-        * XXX - this is a conversation dissector, and the code to
-        * call a conversation dissector doesn't check for disabled
-        * protocols or set "pinfo->current_proto".
-        */
-       CHECK_DISPLAY_AS_DATA(proto_quakeworld, tvb, pinfo, tree);
-
        direction = (pinfo->destport == gbl_quakeworldServerPort) ?
                        DIR_C2S : DIR_S2C;
 
-       pinfo->current_proto = "QUAKEWORLD";
-
-       if (check_col(pinfo->fd, COL_PROTOCOL))
-               col_set_str(pinfo->fd, COL_PROTOCOL, "QUAKEWORLD");
-       if (check_col(pinfo->fd, COL_INFO))
-               col_set_str(pinfo->fd, COL_INFO, val_to_str(direction,
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUAKEWORLD");
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_set_str(pinfo->cinfo, COL_INFO, val_to_str(direction,
                        names_direction, "%u"));
 
        if (tree) {
                quakeworld_item = proto_tree_add_item(tree, proto_quakeworld,
-                               tvb, 0, tvb_length(tvb), FALSE);
+                               tvb, 0, -1, FALSE);
                if (quakeworld_item)
                        quakeworld_tree = proto_item_add_subtree(
                                quakeworld_item, ett_quakeworld);
@@ -719,8 +740,8 @@ dissect_quakeworld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
 
        if (tvb_get_ntohl(tvb, 0) == 0xffffffff) {
-               if (check_col(pinfo->fd, COL_INFO)) {
-                       col_append_str(pinfo->fd, COL_INFO, " Connectionless");
+               if (check_col(pinfo->cinfo, COL_INFO)) {
+                       col_append_str(pinfo->cinfo, COL_INFO, " Connectionless");
                }
                if (quakeworld_tree)
                        proto_tree_add_uint_format(quakeworld_tree,
@@ -731,8 +752,8 @@ dissect_quakeworld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        tvb, pinfo, quakeworld_tree, direction);
        }
        else {
-               if (check_col(pinfo->fd, COL_INFO)) {
-                       col_append_str(pinfo->fd, COL_INFO, " Game");
+               if (check_col(pinfo->cinfo, COL_INFO)) {
+                       col_append_str(pinfo->cinfo, COL_INFO, " Game");
                }
                if (quakeworld_tree)
                        proto_tree_add_uint_format(quakeworld_tree,
@@ -749,19 +770,22 @@ void
 proto_reg_handoff_quakeworld(void)
 {
        static int Initialized=FALSE;
+       static dissector_handle_t quakeworld_handle;
        static int ServerPort=0;
-       if (Initialized) {
-               dissector_delete("udp.port", ServerPort, dissect_quakeworld);
-       } else {
+
+       if (!Initialized) {
+               quakeworld_handle = create_dissector_handle(dissect_quakeworld,
+                               proto_quakeworld);
                Initialized=TRUE;
+       } else {
+               dissector_delete("udp.port", ServerPort, quakeworld_handle);
        }
+
         /* set port for future deletes */
         ServerPort=gbl_quakeworldServerPort;
-       dissector_add("udp.port", gbl_quakeworldServerPort,
-                       dissect_quakeworld, proto_quakeworld);
+
+       dissector_add("udp.port", gbl_quakeworldServerPort, quakeworld_handle);
+       data_handle = find_dissector("data");
 }
 
 
@@ -797,6 +821,10 @@ proto_register_quakeworld(void)
                        { "Command", "quakeworld.connectionless.command",
                        FT_STRING, BASE_DEC, NULL, 0x0,
                        "Command", HFILL }},
+               { &hf_quakeworld_connectionless_arguments,
+                       { "Arguments", "quakeworld.connectionless.arguments",
+                       FT_STRING, BASE_DEC, NULL, 0x0,
+                       "Arguments", HFILL }},
                { &hf_quakeworld_connectionless_connect_version,
                        { "Version", "quakeworld.connectionless.connect.version",
                        FT_UINT32, BASE_DEC, NULL, 0x0,
@@ -858,6 +886,7 @@ proto_register_quakeworld(void)
                &ett_quakeworld,
                &ett_quakeworld_connectionless,
                &ett_quakeworld_connectionless_text,
+               &ett_quakeworld_connectionless_arguments,
                &ett_quakeworld_connectionless_connect_infostring,
                &ett_quakeworld_connectionless_connect_infostring_key_value,
                &ett_quakeworld_game,