Add some additional sanity checking.
[obnox/wireshark/wip.git] / packet-quakeworld.c
index 68fa541c347aa8c8aa4ea7308ec859cf56954e1b..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.7 2001/11/27 07:13:26 guy Exp $
+ * $Id: packet-quakeworld.c,v 1.19 2003/09/21 20:06:01 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
  * 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;
@@ -86,11 +82,13 @@ static dissector_handle_t data_handle;
        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;
@@ -160,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 )
@@ -176,7 +174,7 @@ Cmd_Argv(int arg)
 }
 
 
-int
+static int
 Cmd_Argv_start(int arg)
 {
        if ( arg >= cmd_argc )
@@ -185,7 +183,7 @@ Cmd_Argv_start(int arg)
 }
 
 
-int
+static int
 Cmd_Argv_length(int arg)
 {
        if ( arg >= cmd_argc )
@@ -194,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++)
@@ -227,7 +225,7 @@ Cmd_TokenizeString(char* text)
 
                if (!*text)
                        return;
-                       
+
                text = COM_Parse (text);
                if (!text)
                        return;
@@ -243,9 +241,9 @@ Cmd_TokenizeString(char* text)
        }
 }
 
-                       
-void
-dissect_id_infostring(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, 
+
+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)
 {
@@ -267,7 +265,7 @@ dissect_id_infostring(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree,
 
                for (keylength = 0
                        ;
-                       *(keypos + keylength) != '\\' && 
+                       *(keypos + keylength) != '\\' &&
                        *(keypos + keylength) != 0
                        ;
                        keylength++) ;
@@ -276,7 +274,7 @@ dissect_id_infostring(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree,
                valuepos = keyvaluesep+1;
                for (valuelength = 0
                        ;
-                       *(valuepos + valuelength) != '\\' && 
+                       *(valuepos + valuelength) != '\\' &&
                        *(valuepos + valuelength) != 0
                        ;
                        valuelength++) ;
@@ -286,7 +284,7 @@ dissect_id_infostring(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree,
                }
                *(keyvaluesep) = '=';
                *(valueend) = 0;
-               
+
                if (tree) {
                        proto_item* sub_item = NULL;
                        proto_tree* sub_tree = NULL;
@@ -296,7 +294,7 @@ dissect_id_infostring(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree,
                                tvb,
                                offset + (keypos-infostring),
                                keylength + 1 + valuelength, keypos);
-                       if (sub_item) 
+                       if (sub_item)
                                sub_tree =
                                        proto_item_add_subtree(
                                        sub_item,
@@ -335,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 */
@@ -347,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'
@@ -361,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);
@@ -387,8 +384,7 @@ 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 (cl_tree) {
@@ -406,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");
@@ -433,11 +429,11 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                                        tvb, offset, command_len, command);
                                argument_item = proto_tree_add_string(text_tree,
                                        hf_quakeworld_connectionless_arguments,
-                                       tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), 
+                                       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,   
+                                               proto_item_add_subtree(argument_item,
                                                        ett_quakeworld_connectionless_arguments);
                                }
                                command_finished=TRUE;
@@ -470,7 +466,7 @@ 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);
-                               dissect_id_infostring(tvb, pinfo, info_tree, offset + Cmd_Argv_start(4),
+                               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,
@@ -483,7 +479,7 @@ 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");
@@ -493,11 +489,11 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
                                        tvb, offset, command_len, command);
                                argument_item = proto_tree_add_string(text_tree,
                                        hf_quakeworld_connectionless_arguments,
-                                       tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), 
+                                       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,   
+                                               proto_item_add_subtree(argument_item,
                                                        ett_quakeworld_connectionless_arguments);
                                }
                                command_finished=TRUE;
@@ -559,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);
@@ -621,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);
@@ -653,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);
@@ -669,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;
@@ -686,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);
@@ -700,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);
@@ -723,15 +717,15 @@ dissect_quakeworld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        direction = (pinfo->destport == gbl_quakeworldServerPort) ?
                        DIR_C2S : DIR_S2C;
 
-       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);
@@ -746,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,
@@ -758,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,
@@ -776,19 +770,21 @@ 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");
 }