aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorStephen Fisher <steve@stephen-fisher.com>2007-11-06 05:30:04 +0000
committerStephen Fisher <steve@stephen-fisher.com>2007-11-06 05:30:04 +0000
commit6785ffd7965535af8f69ad2b1eea985186190795 (patch)
tree005e191d094df8f149a1156dcb68aa37c16b8e6a /epan
parent46e6e9ea0f205debe56a8ab71a12646f46d33a1a (diff)
Wake on LAN (WOL): New dissector from Chris Maynard via -dev list and
enhancement bug #1968 Me: Added entries in epan/etypes.h and epan/dissectors/packet-ethertype.c for WOL. svn path=/trunk/; revision=23371
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-ethertype.c1
-rw-r--r--epan/dissectors/packet-wol.c366
-rw-r--r--epan/etypes.h4
4 files changed, 372 insertions, 0 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 6898594057..6b4ce2ec42 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -745,6 +745,7 @@ CLEAN_DISSECTOR_SRC = \
packet-winsrepl.c \
packet-wlancap.c \
packet-wlccp.c \
+ packet-wol.c \
packet-wsp.c \
packet-wtls.c \
packet-wtp.c \
diff --git a/epan/dissectors/packet-ethertype.c b/epan/dissectors/packet-ethertype.c
index 34f6e862e2..ce362ab4fa 100644
--- a/epan/dissectors/packet-ethertype.c
+++ b/epan/dissectors/packet-ethertype.c
@@ -53,6 +53,7 @@ const value_string etype_vals[] = {
{ETHERTYPE_XNS_IDP, "XNS Internet Datagram Protocol" },
{ETHERTYPE_X25L3, "X.25 Layer 3" },
{ETHERTYPE_ARP, "ARP" },
+ {ETHERTYPE_WOL, "Wake on LAN" },
{ETHERTYPE_WMX_M2M, "WiMax Mac-to-Mac" },
{ETHERTYPE_EPL_V1, "EPL_V1" },
{ETHERTYPE_REVARP, "RARP" },
diff --git a/epan/dissectors/packet-wol.c b/epan/dissectors/packet-wol.c
new file mode 100644
index 0000000000..5e42e999ac
--- /dev/null
+++ b/epan/dissectors/packet-wol.c
@@ -0,0 +1,366 @@
+/* packet-wol.c
+ * Routines for WOL dissection
+ * Copyright 2007, Christopher Maynard <Chris.Maynard[AT]gtech.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This dissector for "Wake On LAN" was not copied from any other existing
+ * dissector. It uses the template from SVN23520 docs/README.devloper, which
+ * was the latest one available at the time of this writing. This dissector is
+ * a heuristic one though, so appropriate changes have made to the template
+ * as needed.
+ *
+ * The "Wake On LAN" dissector was written based primarily on the AMD white
+ * paper, available from: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/20213.pdf.
+ *
+ * In addition, testing of the dissector was conducted using 2 utilities
+ * downloaded from http://www.moldaner.de/wakeonlan/wakeonlan.html and
+ * http://www.depicus.com/wake-on-lan/, as well as with the ether-wake utility
+ * on a Linux Fedora Core 4 system.
+ *
+ * From what I can tell from the tools available, even though the white paper
+ * indicates that the so-called, "MagicPacket" can be located anywhere within
+ * the Ethernet frame, in practice, there seem to be only 2 variations of the
+ * implementation of the MagicPacket. Ether-wake implements it as an Ethernet
+ * frame with ether type 0x0842 (ETHERTYPE_WOL), and the other tools all seem
+ * to implement it as a UDP packet, both with the payload as nothing but the
+ * MagicPacket.
+ *
+ * To keep things simple, this dissector will only indicate a frame as
+ * Wake-On-Lan if the MagicPacket is found for a frame marked as etherytpe
+ * 0x0842 or if it's a UDP packet. To fully support Wake-On-Lan dissection
+ * though, we would need a way to have this dissector called only if the frame
+ * hasn't already been classified as some other type of dissector ... but I
+ * don't know how to do that? The only alternative I am aware of would be to
+ * register as a heuristic dissector for pretty much every possible protocol
+ * there is, which seems unreasonable to do to me.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/addr_resolv.h>
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/etypes.h>
+
+/* 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-wol.h" */
+
+/* Forward declaration we need below */
+void proto_reg_handoff_wol(void);
+
+/* Initialize the protocol and registered fields */
+static int proto_wol = -1;
+static int hf_wol_sync = -1;
+static int hf_wol_mac = -1;
+static int hf_wol_passwd = -1;
+
+/* Global sample preference ("controls" display of numbers) */
+/* static gboolean gPREF_HEX = FALSE; */
+
+/* Initialize the subtree pointers */
+static gint ett_wol = -1;
+static gint ett_wol_macblock = -1;
+
+/* Code to actually dissect the packets */
+static int
+dissect_wol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint len;
+ gint offset;
+ guint8 sync[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ guint8 *mac;
+ guint8 *passwd;
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_item *mti;
+ proto_tree *wol_tree;
+ proto_tree *mac_tree;
+
+/* First, if at all possible, do some heuristics to check if the packet cannot
+ * possibly belong to your protocol. This is especially important for
+ * protocols directly on top of TCP or UDP where port collisions are
+ * common place (e.g., even though your protocol uses a well known port,
+ * someone else may set up, for example, a web server on that port which,
+ * if someone analyzed that web server's traffic in Wireshark, would result
+ * in Wireshark handing an HTTP packet to your dissector). For example:
+ */
+ /* Check that there's enough data */
+ len = tvb_length(tvb);
+ if ( len < 102 ) /* wol's smallest packet size is 102 */
+ return (0);
+
+ /* Get some values from the packet header, probably using tvb_get_*() */
+
+ /* Regardless of what the AMD white paper states, don't search the entire
+ * tvb for the synchronization stream. My feeling is that this could be
+ * quite expensive and seriously hinder Wireshark performance. For now,
+ * unless we need to change it later, just compare the 1st 6 bytes. */
+ if ( tvb_memeql(tvb, 0, sync, 6) != 0 )
+ return (0);
+
+ /* So far so good. Now get the next 6 bytes, which we'll assume is the
+ * target's MAC address, and do 15 memory chunk comparisons, since if this
+ * is a real MagicPacket, the target's MAC will be duplicated 16 times. */
+ mac = ep_tvb_memdup(tvb, 6, 6);
+ for ( offset = 12; offset < 102; offset += 6 )
+ if ( tvb_memeql(tvb, offset, mac, 6) != 0 )
+ return (0);
+
+ /* OK, we're going to assume it's a MagicPacket. If there's a password,
+ * grab it now, and in case there's any extra bytes after the only 3 valid
+ * and expected lengths, truncate the length so the extra byte(s) aren't
+ * included as being part of the WOL payload. */
+ if ( len >= 106 && len < 108 )
+ {
+ len = 106;
+ passwd = ip_to_str(ep_tvb_memdup(tvb, 102, 4));
+ }
+ else if ( len >= 108 )
+ {
+ len = 108;
+ passwd = ether_to_str(ep_tvb_memdup(tvb, 102, 6));
+ }
+ else
+ {
+ len = 102;
+ passwd = NULL;
+ }
+
+/* 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, "WOL");
+
+/* This field shows up as the "Info" column in the display; you should use
+ it, if possible, to summarize what's in the packet, so that a user looking
+ at the list of packets can tell what type of packet it is. See section 1.5
+ for more information.
+
+ Before changing the contents of a column you should make sure the column is
+ active by calling "check_col(pinfo->cinfo, COL_*)". If it is not active
+ don't bother setting it.
+
+ If you are setting the column to a constant string, use "col_set_str()",
+ as it's more efficient than the other "col_set_XXX()" calls.
+
+ If you're setting it to a string you've constructed, or will be
+ appending to the column later, use "col_add_str()".
+
+ "col_add_fstr()" can be used instead of "col_add_str()"; it takes
+ "printf()"-like arguments. Don't use "col_add_fstr()" with a format
+ string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
+ more efficient than "col_add_fstr()".
+
+ If you will be fetching any data from the packet before filling in
+ the Info column, clear that column first, in case the calls to fetch
+ data from the packet throw an exception because they're fetching data
+ past the end of the packet, so that the Info column doesn't have data
+ left over from the previous dissector; do
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ */
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "MagicPacket for %s (%s)",
+ get_ether_name(mac), ether_to_str(mac));
+
+ /* NOTE: ether-wake uses a dotted-decimal format for specifying a
+ * 4-byte password or an Ethernet mac address format for specifying
+ * a 6-byte password, so display them in that format, even if the
+ * password isn't really an IP or MAC address. */
+ if ( passwd )
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", password %s", passwd);
+ }
+
+/* A protocol dissector can be called in 2 different ways:
+
+ (a) Operational dissection
+
+ In this mode, Wireshark 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 Wireshark does not build a so-called "protocol
+ tree".
+
+ (b) Detailed dissection
+
+ In this mode, Wireshark is also interested in all details of
+ a given protocol, so a "protocol tree" is created.
+
+ Wireshark 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_wol, tvb, 0, len, FALSE);
+ proto_item_append_text(ti, ", MAC: %s (%s)", get_ether_name(mac),
+ ether_to_str(mac));
+ if ( passwd )
+ proto_item_append_text(ti, ", password: %s", passwd);
+ wol_tree = proto_item_add_subtree(ti, ett_wol);
+
+/* add an item to the subtree, see section 1.6 for more information */
+ proto_tree_add_item(wol_tree, hf_wol_sync, tvb, 0, 6, FALSE);
+
+/* Continue adding tree items to process the packet here */
+ mti = proto_tree_add_text(wol_tree, tvb, 6, 96, "MAC: %s (%s)",
+ get_ether_name(mac), ether_to_str(mac));
+ mac_tree = proto_item_add_subtree(mti, ett_wol_macblock);
+ for ( offset = 6; offset < 102; offset += 6 )
+ proto_tree_add_ether(mac_tree, hf_wol_mac, tvb, offset, 6, mac);
+
+ if ( len == 106 )
+ proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
+ 4, passwd, "Password: %s", passwd);
+ else if ( len == 108 )
+ proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
+ 6, passwd, "Password: %s", passwd);
+ }
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+
+/* Return the amount of data this dissector was able to dissect */
+ if ( pinfo->ethertype == ETHERTYPE_WOL )
+ return (len);
+
+ /* Heuristic dissectors return TRUE/FALSE. */
+ return (TRUE);
+}
+
+
+/* Register the protocol with Wireshark */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_wol(void)
+{
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_wol_sync,
+ { "Sync stream", "wol.sync",
+ FT_BYTES, BASE_HEX, NULL, 0, "", HFILL }},
+ { &hf_wol_mac,
+ { "MAC", "wol.mac",
+ FT_ETHER, BASE_HEX, NULL, 0, "", HFILL }},
+ { &hf_wol_passwd,
+ { "Password", "wol.passwd",
+ FT_BYTES, BASE_HEX, NULL, 0, "", HFILL }}
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_wol,
+ &ett_wol_macblock
+ };
+
+/* Register the protocol name and description */
+ proto_wol = proto_register_protocol("Wake On LAN", "WOL", "wol");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_wol, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* 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_wol(void)
+{
+ static gboolean inited = FALSE;
+
+ if ( !inited )
+ {
+ dissector_handle_t wol_handle;
+
+/* Use new_create_dissector_handle() to indicate that dissect_wol()
+ * returns the number of bytes it dissected (or 0 if it thinks the packet
+ * does not belong to PROTONAME).
+ */
+ wol_handle = new_create_dissector_handle(dissect_wol, proto_wol);
+
+ /* We don't really want to register with EVERY possible dissector,
+ * do we? I know that the AMD white paper specifies that the
+ * MagicPacket could be present in any frame, but are we seriously
+ * going to register WOL with every other dissector!? I think not.
+ *
+ * Unless anyone has a better idea, just register with only those that
+ * are in "common usage" and grow this list as needed. Yeah, I'm sure
+ * we'll miss some, but how else to do this ... add a thousand of
+ * these dissector_add()'s and heur_dissector_add()'s??? */
+ dissector_add("ethertype", ETHERTYPE_WOL, wol_handle);
+ heur_dissector_add("udp", dissect_wol, proto_wol);
+ inited = TRUE;
+ }
+}
+
diff --git a/epan/etypes.h b/epan/etypes.h
index 1898b29c01..2a55e011f6 100644
--- a/epan/etypes.h
+++ b/epan/etypes.h
@@ -71,6 +71,10 @@
#define ETHERTYPE_ARP 0x0806
#endif
+#ifndef ETHERTYPE_WOL
+#define ETHERTYPE_WOL 0x0842 /* Wake on LAN. Not offically registered. */
+#endif
+
#ifndef ETHERTYPE_WMX_M2M
#define ETHERTYPE_WMX_M2M 0x08f0
#endif