380f2b161d9ca7ac089c81be22916fecdfccae36
[obnox/wireshark/wip.git] / epan / dissectors / packet-wol.c
1 /* packet-wol.c
2  * Routines for WOL dissection
3  * Copyright 2007, Christopher Maynard <Chris.Maynard[AT]gtech.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This dissector for "Wake On LAN" was not copied from any other existing
12  * dissector.  It uses the template from SVN23520 docs/README.devloper, which
13  * was the latest one available at the time of this writing.  This dissector is
14  * a heuristic one though, so appropriate changes have made to the template
15  * as needed.
16  *
17  * The "Wake On LAN" dissector was written based primarily on the AMD white
18  * paper, available from: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/20213.pdf.
19  *
20  * In addition, testing of the dissector was conducted using 2 utilities
21  * downloaded from http://www.moldaner.de/wakeonlan/wakeonlan.html and
22  * http://www.depicus.com/wake-on-lan/, as well as with the ether-wake utility
23  * on a Linux Fedora Core 4 system.
24  *
25  * From what I can tell from the tools available, even though the white paper
26  * indicates that the so-called, "MagicPacket" can be located anywhere within
27  * the Ethernet frame, in practice, there seem to be only 2 variations of the
28  * implementation of the MagicPacket.  Ether-wake implements it as an Ethernet
29  * frame with ether type 0x0842 (ETHERTYPE_WOL), and the other tools all seem
30  * to implement it as a UDP packet, both with the payload as nothing but the
31  * MagicPacket.
32  *
33  * To keep things simple, this dissector will only indicate a frame as
34  * Wake-On-Lan if the MagicPacket is found for a frame marked as etherytpe
35  * 0x0842 or if it's a UDP packet.  To fully support Wake-On-Lan dissection
36  * though, we would need a way to have this dissector called only if the frame
37  * hasn't already been classified as some other type of dissector ... but I
38  * don't know how to do that?  The only alternative I am aware of would be to
39  * register as a heuristic dissector for pretty much every possible protocol
40  * there is, which seems unreasonable to do to me.
41  *
42  * This program is free software; you can redistribute it and/or
43  * modify it under the terms of the GNU General Public License
44  * as published by the Free Software Foundation; either version 2
45  * of the License, or (at your option) any later version.
46  *
47  * This program is distributed in the hope that it will be useful,
48  * but WITHOUT ANY WARRANTY; without even the implied warranty of
49  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
50  * GNU General Public License for more details.
51  *
52  * You should have received a copy of the GNU General Public License
53  * along with this program; if not, write to the Free Software
54  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
55  */
56
57 #ifdef HAVE_CONFIG_H
58 # include "config.h"
59 #endif
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64
65 #include <glib.h>
66
67 #include <epan/addr_resolv.h>
68 #include <epan/packet.h>
69 #include <epan/etypes.h>
70
71 /* IF PROTO exposes code to other dissectors, then it must be exported
72    in a header file. If not, a header file is not needed at all. */
73 /* #include "packet-wol.h" */
74
75 /* Initialize the protocol and registered fields */
76 static int proto_wol = -1;
77 static int hf_wol_sync = -1;
78 static int hf_wol_mac = -1;
79 static int hf_wol_passwd = -1;
80
81 /* Global sample preference ("controls" display of numbers) */
82 /* static gboolean gPREF_HEX = FALSE; */
83
84 /* Initialize the subtree pointers */
85 static gint ett_wol = -1;
86 static gint ett_wol_macblock = -1;
87
88 /* Code to actually dissect the packets */
89 static int
90 dissect_wol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
91 {
92     guint len;
93     gint offset;
94     guint8 sync[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
95     guint8 *mac;
96     const guint8 *passwd;
97
98 /* Set up structures needed to add the protocol subtree and manage it */
99     proto_item *ti;
100     proto_item *mti;
101     proto_tree *wol_tree;
102     proto_tree *mac_tree;
103
104 /*  First, if at all possible, do some heuristics to check if the packet cannot
105  *  possibly belong to your protocol.  This is especially important for
106  *  protocols directly on top of TCP or UDP where port collisions are
107  *  common place (e.g., even though your protocol uses a well known port,
108  *  someone else may set up, for example, a web server on that port which,
109  *  if someone analyzed that web server's traffic in Wireshark, would result
110  *  in Wireshark handing an HTTP packet to your dissector).  For example:
111  */
112     /* Check that there's enough data */
113     len = tvb_length(tvb);
114     if ( len < 102 )    /* wol's smallest packet size is 102 */
115         return (0);
116
117     /* Get some values from the packet header, probably using tvb_get_*() */
118
119     /* Regardless of what the AMD white paper states, don't search the entire
120      * tvb for the synchronization stream.  My feeling is that this could be
121      * quite expensive and seriously hinder Wireshark performance.  For now,
122      * unless we need to change it later, just compare the 1st 6 bytes. */
123     if ( tvb_memeql(tvb, 0, sync, 6) != 0 )
124         return (0);
125
126     /* So far so good.  Now get the next 6 bytes, which we'll assume is the
127      * target's MAC address, and do 15 memory chunk comparisons, since if this
128      * is a real MagicPacket, the target's MAC will be duplicated 16 times. */
129     mac = ep_tvb_memdup(tvb, 6, 6);
130     for ( offset = 12; offset < 102; offset += 6 )
131         if ( tvb_memeql(tvb, offset, mac, 6) != 0 )
132             return (0);
133
134     /* OK, we're going to assume it's a MagicPacket.  If there's a password,
135      * grab it now, and in case there's any extra bytes after the only 3 valid
136      * and expected lengths, truncate the length so the extra byte(s) aren't
137      * included as being part of the WOL payload. */
138     if ( len >= 106 && len < 108 )
139     {
140         len = 106;
141         passwd = ip_to_str(ep_tvb_memdup(tvb, 102, 4));
142     }
143     else if ( len >= 108 )
144     {
145         len = 108;
146         passwd = ether_to_str(ep_tvb_memdup(tvb, 102, 6));
147     }
148     else
149     {
150         len = 102;
151         passwd = NULL;
152     }
153
154 /* Make entries in Protocol column and Info column on summary display */
155     col_set_str(pinfo->cinfo, COL_PROTOCOL, "WOL");
156
157 /* This field shows up as the "Info" column in the display; you should use
158    it, if possible, to summarize what's in the packet, so that a user looking
159    at the list of packets can tell what type of packet it is. See section 1.5
160    for more information.
161
162    Before changing the contents of a column you should make sure the column is
163    active by calling "check_col(pinfo->cinfo, COL_*)". If it is not active
164    don't bother setting it.
165
166    If you are setting the column to a constant string, use "col_set_str()",
167    as it's more efficient than the other "col_set_XXX()" calls.
168
169    If you're setting it to a string you've constructed, or will be
170    appending to the column later, use "col_add_str()".
171
172    "col_add_fstr()" can be used instead of "col_add_str()"; it takes
173    "printf()"-like arguments.  Don't use "col_add_fstr()" with a format
174    string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
175    more efficient than "col_add_fstr()".
176
177    If you will be fetching any data from the packet before filling in
178    the Info column, clear that column first, in case the calls to fetch
179    data from the packet throw an exception because they're fetching data
180    past the end of the packet, so that the Info column doesn't have data
181    left over from the previous dissector; do
182
183     if (check_col(pinfo->cinfo, COL_INFO))
184         col_clear(pinfo->cinfo, COL_INFO);
185
186    */
187
188     if ( check_col(pinfo->cinfo, COL_INFO) )
189     {
190         col_clear(pinfo->cinfo, COL_INFO);
191         col_add_fstr(pinfo->cinfo, COL_INFO, "MagicPacket for %s (%s)",
192             get_ether_name(mac), ether_to_str(mac));
193
194         /* NOTE: ether-wake uses a dotted-decimal format for specifying a
195          * 4-byte password or an Ethernet mac address format for specifying
196          * a 6-byte password, so display them in that format, even if the
197          * password isn't really an IP or MAC address. */
198         if ( passwd )
199             col_append_fstr(pinfo->cinfo, COL_INFO, ", password %s", passwd);
200     }
201
202 /* A protocol dissector can be called in 2 different ways:
203
204     (a) Operational dissection
205
206         In this mode, Wireshark is only interested in the way protocols
207         interact, protocol conversations are created, packets are
208         reassembled and handed over to higher-level protocol dissectors.
209         In this mode Wireshark does not build a so-called "protocol
210         tree".
211
212     (b) Detailed dissection
213
214         In this mode, Wireshark is also interested in all details of
215         a given protocol, so a "protocol tree" is created.
216
217    Wireshark distinguishes between the 2 modes with the proto_tree pointer:
218     (a) <=> tree == NULL
219     (b) <=> tree != NULL
220
221    In the interest of speed, if "tree" is NULL, avoid building a
222    protocol tree and adding stuff to it, or even looking at any packet
223    data needed only if you're building the protocol tree, if possible.
224
225    Note, however, that you must fill in column information, create
226    conversations, reassemble packets, build any other persistent state
227    needed for dissection, and call subdissectors regardless of whether
228    "tree" is NULL or not.  This might be inconvenient to do without
229    doing most of the dissection work; the routines for adding items to
230    the protocol tree can be passed a null protocol tree pointer, in
231    which case they'll return a null item pointer, and
232    "proto_item_add_subtree()" returns a null tree pointer if passed a
233    null item pointer, so, if you're careful not to dereference any null
234    tree or item pointers, you can accomplish this by doing all the
235    dissection work.  This might not be as efficient as skipping that
236    work if you're not building a protocol tree, but if the code would
237    have a lot of tests whether "tree" is null if you skipped that work,
238    you might still be better off just doing all that work regardless of
239    whether "tree" is null or not. */
240     if (tree) {
241
242 /* NOTE: The offset and length values in the call to
243    "proto_tree_add_item()" define what data bytes to highlight in the hex
244    display window when the line in the protocol tree display
245    corresponding to that item is selected.
246
247    Supplying a length of -1 is the way to highlight all data from the
248    offset to the end of the packet. */
249
250 /* create display subtree for the protocol */
251         ti = proto_tree_add_item(tree, proto_wol, tvb, 0, len, FALSE);
252         proto_item_append_text(ti, ", MAC: %s (%s)", get_ether_name(mac),
253             ether_to_str(mac));
254         if ( passwd )
255             proto_item_append_text(ti, ", password: %s", passwd);
256         wol_tree = proto_item_add_subtree(ti, ett_wol);
257
258 /* add an item to the subtree, see section 1.6 for more information */
259         proto_tree_add_item(wol_tree, hf_wol_sync, tvb, 0, 6, FALSE);
260
261 /* Continue adding tree items to process the packet here */
262         mti = proto_tree_add_text(wol_tree, tvb, 6, 96, "MAC: %s (%s)",
263             get_ether_name(mac), ether_to_str(mac));
264         mac_tree = proto_item_add_subtree(mti, ett_wol_macblock);
265         for ( offset = 6; offset < 102; offset += 6 )
266             proto_tree_add_ether(mac_tree, hf_wol_mac, tvb, offset, 6, mac);
267
268         if ( len == 106 )
269             proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
270                 4, passwd, "Password: %s", passwd);
271         else if ( len == 108 )
272             proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
273                 6, passwd, "Password: %s", passwd);
274     }
275
276 /* If this protocol has a sub-dissector call it here, see section 1.8 */
277
278 /* Return the amount of data this dissector was able to dissect */
279     if ( pinfo->ethertype == ETHERTYPE_WOL )
280         return (len);
281
282     /* Heuristic dissectors return TRUE/FALSE. */
283     return (TRUE);
284 }
285
286
287 /* Register the protocol with Wireshark */
288
289 /* this format is require because a script is used to build the C function
290    that calls all the protocol registration.
291 */
292
293 void
294 proto_register_wol(void)
295 {
296 /* Setup list of header fields  See Section 1.6.1 for details*/
297     static hf_register_info hf[] = {
298         { &hf_wol_sync,
299             { "Sync stream", "wol.sync",
300             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
301         { &hf_wol_mac,
302             { "MAC", "wol.mac",
303             FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
304         { &hf_wol_passwd,
305             { "Password", "wol.passwd",
306             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
307     };
308
309 /* Setup protocol subtree array */
310     static gint *ett[] = {
311         &ett_wol,
312         &ett_wol_macblock
313     };
314
315 /* Register the protocol name and description */
316     proto_wol = proto_register_protocol("Wake On LAN", "WOL", "wol");
317
318 /* Required function calls to register the header fields and subtrees used */
319     proto_register_field_array(proto_wol, hf, array_length(hf));
320     proto_register_subtree_array(ett, array_length(ett));
321 }
322
323
324 /* If this dissector uses sub-dissector registration add a registration routine.
325    This exact format is required because a script is used to find these
326    routines and create the code that calls these routines.
327
328 */
329 void
330 proto_reg_handoff_wol(void)
331 {
332     dissector_handle_t wol_handle;
333
334 /*  Use new_create_dissector_handle() to indicate that dissect_wol()
335  *  returns the number of bytes it dissected (or 0 if it thinks the packet
336  *  does not belong to PROTONAME).
337  */
338     wol_handle = new_create_dissector_handle(dissect_wol, proto_wol);
339
340     /* We don't really want to register with EVERY possible dissector,
341      * do we?  I know that the AMD white paper specifies that the
342      * MagicPacket could be present in any frame, but are we seriously
343      * going to register WOL with every other dissector!?  I think not.
344      *
345      * Unless anyone has a better idea, just register with only those that
346      * are in "common usage" and grow this list as needed.  Yeah, I'm sure
347      * we'll miss some, but how else to do this ... add a thousand of
348      * these dissector_add()'s and heur_dissector_add()'s??? */
349     dissector_add("ethertype", ETHERTYPE_WOL, wol_handle);
350     heur_dissector_add("udp", dissect_wol, proto_wol);
351 }
352