Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-wol.c
blobd1ea56fa4fa1a1e199d0a1489e53da3db2a008e5
1 /* packet-wol.c
2 * Routines for WOL dissection
3 * Copyright 2007, Christopher Maynard <Chris.Maynard[AT]gtech.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
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.
15 * The "Wake On LAN" dissector was written based primarily on the AMD white
16 * paper, available from:
18 * https://web.archive.org/web/20100601154907/http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/20213.pdf
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.
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.
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.
42 * SPDX-License-Identifier: GPL-2.0-or-later
45 #include "config.h"
47 #include <epan/packet.h>
48 #include <epan/addr_resolv.h>
49 #include <epan/etypes.h>
51 void proto_register_wol(void);
52 void proto_reg_handoff_wol(void);
54 static dissector_handle_t wol_handle;
56 /* Initialize the protocol and registered fields */
57 static int proto_wol;
58 static int hf_wol_sync;
59 static int hf_wol_mac;
60 static int hf_wol_passwd;
62 /* Initialize the subtree pointers */
63 static int ett_wol;
64 static int ett_wol_macblock;
66 /* Code to actually dissect the packets */
67 static int
68 dissect_wol_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
70 unsigned len;
71 int offset;
72 uint8_t *mac;
73 const uint8_t *passwd;
74 uint64_t qword;
75 address mac_addr;
77 /* Set up structures needed to add the protocol subtree and manage it */
78 proto_item *ti;
79 proto_tree *wol_tree;
80 proto_tree *mac_tree;
82 /* First, if at all possible, do some heuristics to check if the packet cannot
83 * possibly belong to your protocol. This is especially important for
84 * protocols directly on top of TCP or UDP where port collisions are
85 * common place (e.g., even though your protocol uses a well known port,
86 * someone else may set up, for example, a web server on that port which,
87 * if someone analyzed that web server's traffic in Wireshark, would result
88 * in Wireshark handing an HTTP packet to your dissector). For example:
90 /* Check that there's enough data */
91 len = tvb_reported_length(tvb);
92 if ( len < 102 ) /* wol's smallest packet size is 102 */
93 return 0;
95 /* Get some values from the packet header, probably using tvb_get_*() */
97 /* Regardless of what the AMD white paper states, don't search the entire
98 * tvb for the synchronization stream. My feeling is that this could be
99 * quite expensive and seriously hinder Wireshark performance. For now,
100 * unless we need to change it later, just compare the 1st 6 bytes. */
101 qword = tvb_get_ntoh48(tvb,0);
102 if(qword != UINT64_C(0xffffffffffff))
103 return 0;
105 /* So far so good. Now get the next 6 bytes, which we'll assume is the
106 * target's MAC address, and do 15 memory chunk comparisons, since if this
107 * is a real MagicPacket, the target's MAC will be duplicated 16 times. */
108 mac = (uint8_t *)tvb_memdup(pinfo->pool, tvb, 6, 6);
109 for ( offset = 12; offset < 102; offset += 6 )
110 if ( tvb_memeql(tvb, offset, mac, 6) != 0 )
111 return 0;
113 /* OK, we're going to assume it's a MagicPacket. If there's a password,
114 * grab it now, and in case there's any extra bytes after the only 3 valid
115 * and expected lengths, truncate the length so the extra byte(s) aren't
116 * included as being part of the WOL payload. */
117 if ( len >= 106 && len < 108 )
119 len = 106;
120 passwd = tvb_ip_to_str(pinfo->pool, tvb, 102);
122 else if ( len >= 108 )
124 len = 108;
125 passwd = tvb_ether_to_str(pinfo->pool, tvb, 102);
127 else
129 len = 102;
130 passwd = NULL;
133 /* Make entries in Protocol column and Info column on summary display */
134 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WOL");
136 /* This field shows up as the "Info" column in the display; you should use
137 it, if possible, to summarize what's in the packet, so that a user looking
138 at the list of packets can tell what type of packet it is. See section 1.5
139 for more information.
141 If you are setting the column to a constant string, use "col_set_str()",
142 as it's more efficient than the other "col_set_XXX()" calls.
144 If you're setting it to a string you've constructed, or will be
145 appending to the column later, use "col_add_str()".
147 "col_add_fstr()" can be used instead of "col_add_str()"; it takes
148 "printf()"-like arguments. Don't use "col_add_fstr()" with a format
149 string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
150 more efficient than "col_add_fstr()".
152 If you will be fetching any data from the packet before filling in
153 the Info column, clear that column first, in case the calls to fetch
154 data from the packet throw an exception because they're fetching data
155 past the end of the packet, so that the Info column doesn't have data
156 left over from the previous dissector; do
158 col_clear(pinfo->cinfo, COL_INFO);
161 set_address(&mac_addr, AT_ETHER, 6, mac);
163 col_add_fstr(pinfo->cinfo, COL_INFO, "MagicPacket for %s",
164 address_with_resolution_to_str(pinfo->pool, &mac_addr));
166 /* NOTE: ether-wake uses a dotted-decimal format for specifying a
167 * 4-byte password or an Ethernet mac address format for specifying
168 * a 6-byte password, so display them in that format, even if the
169 * password isn't really an IP or MAC address. */
170 if ( passwd )
171 col_append_fstr(pinfo->cinfo, COL_INFO, ", password %s", passwd);
173 /* A protocol dissector can be called in 2 different ways:
175 (a) Operational dissection
177 In this mode, Wireshark is only interested in the way protocols
178 interact, protocol conversations are created, packets are
179 reassembled and handed over to higher-level protocol dissectors.
180 In this mode Wireshark does not build a so-called "protocol
181 tree".
183 (b) Detailed dissection
185 In this mode, Wireshark is also interested in all details of
186 a given protocol, so a "protocol tree" is created.
188 Wireshark distinguishes between the 2 modes with the proto_tree pointer:
189 (a) <=> tree == NULL
190 (b) <=> tree != NULL
192 In the interest of speed, if "tree" is NULL, avoid building a
193 protocol tree and adding stuff to it, or even looking at any packet
194 data needed only if you're building the protocol tree, if possible.
196 Note, however, that you must fill in column information, create
197 conversations, reassemble packets, build any other persistent state
198 needed for dissection, and call subdissectors regardless of whether
199 "tree" is NULL or not. This might be inconvenient to do without
200 doing most of the dissection work; the routines for adding items to
201 the protocol tree can be passed a null protocol tree pointer, in
202 which case they'll return a null item pointer, and
203 "proto_item_add_subtree()" returns a null tree pointer if passed a
204 null item pointer, so, if you're careful not to dereference any null
205 tree or item pointers, you can accomplish this by doing all the
206 dissection work. This might not be as efficient as skipping that
207 work if you're not building a protocol tree, but if the code would
208 have a lot of tests whether "tree" is null if you skipped that work,
209 you might still be better off just doing all that work regardless of
210 whether "tree" is null or not. */
211 if (tree) {
213 /* NOTE: The offset and length values in the call to
214 "proto_tree_add_item()" define what data bytes to highlight in the hex
215 display window when the line in the protocol tree display
216 corresponding to that item is selected.
218 Supplying a length of -1 is the way to highlight all data from the
219 offset to the end of the packet. */
221 /* create display subtree for the protocol */
222 ti = proto_tree_add_item(tree, proto_wol, tvb, 0, len, ENC_NA);
223 proto_item_append_text(ti, ", MAC: %s",
224 address_with_resolution_to_str(pinfo->pool, &mac_addr));
225 if ( passwd )
226 proto_item_append_text(ti, ", password: %s", passwd);
227 wol_tree = proto_item_add_subtree(ti, ett_wol);
229 /* add an item to the subtree, see section 1.6 for more information */
230 proto_tree_add_item(wol_tree, hf_wol_sync, tvb, 0, 6, ENC_NA);
232 /* Continue adding tree items to process the packet here */
233 mac_tree = proto_tree_add_subtree_format(wol_tree, tvb, 6, 96,
234 ett_wol_macblock, NULL, "MAC: %s",
235 address_with_resolution_to_str(pinfo->pool, &mac_addr));
236 for ( offset = 6; offset < 102; offset += 6 )
237 proto_tree_add_ether(mac_tree, hf_wol_mac, tvb, offset, 6, mac);
239 if ( len == 106 )
240 proto_tree_add_bytes_format_value(wol_tree, hf_wol_passwd, tvb, offset,
241 4, passwd, "%s", passwd);
242 else if ( len == 108 )
243 proto_tree_add_bytes_format_value(wol_tree, hf_wol_passwd, tvb, offset,
244 6, passwd, "%s", passwd);
247 return (len);
250 static int
251 dissect_wol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
253 return dissect_wol_pdu(tvb, pinfo, tree, data);
256 static bool
257 dissect_wolheur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
259 if (dissect_wol_pdu(tvb, pinfo, tree, data) > 0)
260 return true;
262 return false;
266 /* Register the protocol with Wireshark */
268 /* this format is require because a script is used to build the C function
269 that calls all the protocol registration.
272 void
273 proto_register_wol(void)
275 /* Setup list of header fields See Section 1.6.1 for details*/
276 static hf_register_info hf[] = {
277 { &hf_wol_sync,
278 { "Sync stream", "wol.sync",
279 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
280 { &hf_wol_mac,
281 { "MAC", "wol.mac",
282 FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
283 { &hf_wol_passwd,
284 { "Password", "wol.passwd",
285 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
288 /* Setup protocol subtree array */
289 static int *ett[] = {
290 &ett_wol,
291 &ett_wol_macblock
294 /* Register the protocol name and description */
295 proto_wol = proto_register_protocol("Wake On LAN", "WOL", "wol");
297 /* Required function calls to register the header fields and subtrees used */
298 proto_register_field_array(proto_wol, hf, array_length(hf));
299 proto_register_subtree_array(ett, array_length(ett));
301 /* Register our dissector handle */
302 wol_handle = register_dissector("wol", dissect_wol, proto_wol);
305 /* If this dissector uses sub-dissector registration add a registration routine.
306 This exact format is required because a script is used to find these
307 routines and create the code that calls these routines.
310 void
311 proto_reg_handoff_wol(void)
313 /* We don't really want to register with EVERY possible dissector,
314 * do we? I know that the AMD white paper specifies that the
315 * MagicPacket could be present in any frame, but are we seriously
316 * going to register WOL with every other dissector!? I think not.
318 * Unless anyone has a better idea, just register with only those that
319 * are in "common usage" and grow this list as needed. Yeah, I'm sure
320 * we'll miss some, but how else to do this ... add a thousand of
321 * these dissector_add_uint()'s and heur_dissector_add()'s??? */
322 dissector_add_uint("ethertype", ETHERTYPE_WOL, wol_handle);
323 heur_dissector_add("udp", dissect_wolheur, "Wake On LAN over UDP", "wol_udp", proto_wol, HEURISTIC_ENABLE);
327 * Editor modelines - https://www.wireshark.org/tools/modelines.html
329 * Local variables:
330 * c-basic-offset: 4
331 * tab-width: 8
332 * indent-tabs-mode: nil
333 * End:
335 * vi: set shiftwidth=4 tabstop=8 expandtab:
336 * :indentSize=4:tabSize=8:noTabs=true: