--- /dev/null
+/* packet-vnc.c
+ * Routines for VNC dissection (Virtual Network Computing)
+ * Copyright 2005, Ulf Lamping <ulf.lamping@web.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ */
+
+/* Dissection of the VNC (Virtual Network Computing) network traffic.
+ *
+ * Several VNC implementations available, see:
+ * http://www.realvnc.com/
+ * http://www.tightvnc.com/
+ * http://ultravnc.sourceforge.net/
+ * ...
+ *
+ * The protocol itself is known as RFB - Remote Frame Buffer Protocol.
+ *
+ * Protocol specification:
+ * http://www.realvnc.com/docs/rfbproto.pdf
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+void proto_reg_handoff_vnc(void);
+
+/* IF PROTO exposes code to other dissectors, then it must be exported
+ in a header file. If not, a header file is not needed at all. */
+/*#include "packet-PROTOABBREV.h"*/
+
+static dissector_handle_t data_handle;
+
+/* Initialize the protocol and registered fields */
+static int proto_vnc = -1;
+static int hf_vnc = -1;
+static int hf_vnc_protocol_version = -1;
+
+/* Global sample preference ("controls" display of numbers) */
+/*static gboolean gPREF_HEX = FALSE;*/
+
+/* Initialize the subtree pointers */
+static gint ett_vnc = -1;
+
+/* Code to actually dissect the packets */
+static void
+dissect_vnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint offset = 0;
+ gint length;
+ guint8 *version;
+
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *vnc_tree;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VNC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VNC");
+
+/* A protocol dissector can be called in 2 different ways:
+
+ (a) Operational dissection
+
+ In this mode, Ethereal is only interested in the way protocols
+ interact, protocol conversations are created, packets are reassembled
+ and handed over to higher-level protocol dissectors.
+ In this mode Ethereal does not build a so-called "protocol tree".
+
+ (b) Detailed dissection
+
+ In this mode, Ethereal is also interested in all details of a given
+ protocol, so a "protocol tree" is created.
+
+ Ethereal distinguishes between the 2 modes with the proto_tree pointer:
+ (a) <=> tree == NULL
+ (b) <=> tree != NULL
+
+ In the interest of speed, if "tree" is NULL, avoid building a
+ protocol tree and adding stuff to it, or even looking at any packet
+ data needed only if you're building the protocol tree, if possible.
+
+ Note, however, that you must fill in column information, create
+ conversations, reassemble packets, build any other persistent state
+ needed for dissection, and call subdissectors regardless of whether
+ "tree" is NULL or not. This might be inconvenient to do without
+ doing most of the dissection work; the routines for adding items to
+ the protocol tree can be passed a null protocol tree pointer, in
+ which case they'll return a null item pointer, and
+ "proto_item_add_subtree()" returns a null tree pointer if passed a
+ null item pointer, so, if you're careful not to dereference any null
+ tree or item pointers, you can accomplish this by doing all the
+ dissection work. This might not be as efficient as skipping that
+ work if you're not building a protocol tree, but if the code would
+ have a lot of tests whether "tree" is null if you skipped that work,
+ you might still be better off just doing all that work regardless of
+ whether "tree" is null or not. */
+ if (tree) {
+
+/* NOTE: The offset and length values in the call to
+ "proto_tree_add_item()" define what data bytes to highlight in the hex
+ display window when the line in the protocol tree display
+ corresponding to that item is selected.
+
+ Supplying a length of -1 is the way to highlight all data from the
+ offset to the end of the packet. */
+
+/* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_vnc, tvb, 0, -1, FALSE);
+ vnc_tree = proto_item_add_subtree(ti, ett_vnc);
+
+ /* this is a hideous first hack!!! */
+ if(tvb_length_remaining(tvb, offset) == 12) {
+ length = 12;
+ version = tvb_get_string(tvb, offset, length);
+ if(version[0] == 'R' && version[1] == 'F' && version[2] == 'B') {
+ /* remove trailing \n */
+ version[11] = '\0';
+ proto_tree_add_string(vnc_tree, hf_vnc_protocol_version, tvb, offset,
+ length, version);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, version);
+ g_free(version);
+ offset += length;
+ }
+ }
+
+
+/* Continue adding tree items to process the packet here */
+
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, vnc_tree);
+
+ }
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_vnc(void)
+{
+/* module_t *vnc_module;*/
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_vnc,
+ { "VNC", "vnc", FT_NONE, BASE_NONE, NULL, 0x0, "Virtual Network Computing", HFILL }},
+ { &hf_vnc_protocol_version,
+ { "ProtocolVersion", "vnc.protocol_version", FT_STRING, BASE_NONE, NULL, 0x0, "Protocol Version", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_vnc,
+ };
+
+/* Register the protocol name and description */
+ proto_vnc = proto_register_protocol("Virtual Network Computing",
+ "VNC", "vnc");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_vnc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* Register preferences module (See Section 2.6 for more on preferences) */
+/* vnc_module = prefs_register_protocol(proto_vnc, proto_reg_handoff_vnc);*/
+
+/* Register a sample preference */
+/* prefs_register_bool_preference(vnc_module, "showHex",
+ "Display numbers in Hex",
+ "Enable to display numerical values in hexidecimal.",
+ &gPREF_HEX ); */
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This exact format is required because a script is used to find these routines
+ and create the code that calls these routines.
+
+ This function is also called by preferences whenever "Apply" is pressed
+ (see prefs_register_protocol above) so it should accommodate being called
+ more than once.
+*/
+void
+proto_reg_handoff_vnc(void)
+{
+ static gboolean inited = FALSE;
+
+ if( !inited ) {
+
+ dissector_handle_t vnc_handle;
+
+ data_handle = find_dissector("data");
+
+ vnc_handle = create_dissector_handle(dissect_vnc,
+ proto_vnc);
+
+ /* XXX - we need a heuristic or at least a preference setting for this port */
+ dissector_add("tcp.port", 5901, vnc_handle);
+
+ inited = TRUE;
+ }
+
+ /*
+ If you perform registration functions which are dependant upon
+ prefs the you should de-register everything which was associated
+ with the previous settings and re-register using the new prefs settings
+ here. In general this means you need to keep track of what value the
+ preference had at the time you registered using a local static in this
+ function. ie.
+
+ static int currentPort = -1;
+
+ if( -1 != currentPort ) {
+ dissector_delete( "tcp.port", currentPort, PROTOABBREV_handle);
+ }
+
+ currentPort = gPortPref;
+
+ dissector_add("tcp.port", currentPort, PROTOABBREV_handle);
+
+ */
+}
+