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