1 /*
2 * packet-ieee80211-netmon.c
3 * Decode packets with a Network Monitor 802.11 radio header
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "config.h"
13
14 #include <epan/packet.h>
15
16 #include <wiretap/wtap.h>
17
18 #include <wsutil/802_11-utils.h>
19
20 void proto_register_netmon_802_11(void);
21 void proto_reg_handoff_netmon_802_11(void);
22
23 /* protocol */
24 static int proto_netmon_802_11 = -1;
25
26 /* Dissector */
27 static dissector_handle_t netmon_802_11_handle;
28
29 #define MIN_HEADER_LEN 32
30
31 /* op_mode */
32 #define OP_MODE_STA 0x00000001 /* station mode */
33 #define OP_MODE_AP 0x00000002 /* AP mode */
34 #define OP_MODE_STA_EXT 0x00000004 /* extensible station mode */
35 #define OP_MODE_MON 0x80000000 /* monitor mode */
36
37 /* phy_type */
38 /*
39 * Augmented with phy types from
40 *
41 * https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/windot11/ne-windot11-_dot11_phy_type
42 */
43 #define PHY_TYPE_UNKNOWN 0
44 #define PHY_TYPE_FHSS 1
45 #define PHY_TYPE_DSSS 2
46 #define PHY_TYPE_IR_BASEBAND 3
47 #define PHY_TYPE_OFDM 4 /* 802.11a */
48 #define PHY_TYPE_HR_DSSS 5 /* 802.11b */
49 #define PHY_TYPE_ERP 6 /* 802.11g */
50 #define PHY_TYPE_HT 7 /* 802.11n */
51 #define PHY_TYPE_VHT 8 /* 802.11ac */
52
53 static int hf_netmon_802_11_version = -1;
54 static int hf_netmon_802_11_length = -1;
55 static int hf_netmon_802_11_op_mode = -1;
56 static int hf_netmon_802_11_op_mode_sta = -1;
57 static int hf_netmon_802_11_op_mode_ap = -1;
58 static int hf_netmon_802_11_op_mode_sta_ext = -1;
59 static int hf_netmon_802_11_op_mode_mon = -1;
60 /* static int hf_netmon_802_11_flags = -1; */
61 static int hf_netmon_802_11_phy_type = -1;
62 static int hf_netmon_802_11_channel = -1;
63 static int hf_netmon_802_11_frequency = -1;
64 static int hf_netmon_802_11_rssi = -1;
65 static int hf_netmon_802_11_datarate = -1;
66 static int hf_netmon_802_11_timestamp = -1;
67
68 static gint ett_netmon_802_11 = -1;
69 static gint ett_netmon_802_11_op_mode = -1;
70
71 static dissector_handle_t ieee80211_radio_handle;
72
73 static int
dissect_netmon_802_11(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)74 dissect_netmon_802_11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
75 {
76 struct ieee_802_11_phdr phdr;
77 proto_tree *wlan_tree = NULL, *opmode_tree;
78 proto_item *ti;
79 tvbuff_t *next_tvb;
80 int offset;
81 guint8 version;
82 guint16 length;
83 guint32 phy_type;
84 guint32 monitor_mode;
85 guint32 flags;
86 guint32 channel;
87 gint calc_channel;
88 gint32 rssi;
89 guint8 rate;
90
91 /*
92 * It appears to be the case that management frames (and control and
93 * extension frames ?) may or may not have an FCS and data frames don't.
94 * (Netmon capture files have been seen for this encapsulation
95 * management frames either completely with or without an FCS. Also:
96 * instances have been seen where both Management and Control frames
97 * do not have an FCS). An "FCS length" of -2 means "NetMon weirdness".
98 *
99 * The metadata header also has a bit indicating whether the adapter
100 * was in monitor mode or not; if it isn't, we set "decrypted" to TRUE,
101 * as, for those frames, the Protected bit is preserved in received
102 * frames, but the frame is decrypted.
103 */
104 memset(&phdr, 0, sizeof(phdr));
105 phdr.fcs_len = -2;
106 phdr.decrypted = FALSE;
107 phdr.datapad = FALSE;
108 phdr.phy = PHDR_802_11_PHY_UNKNOWN;
109
110 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
111 col_clear(pinfo->cinfo, COL_INFO);
112 offset = 0;
113
114 version = tvb_get_guint8(tvb, offset);
115 length = tvb_get_letohs(tvb, offset+1);
116 col_add_fstr(pinfo->cinfo, COL_INFO, "NetMon WLAN Capture v%u, Length %u",
117 version, length);
118 if (version != 2) {
119 /* XXX - complain */
120 goto skip;
121 }
122 if (length < MIN_HEADER_LEN) {
123 /* XXX - complain */
124 goto skip;
125 }
126
127 /* Dissect the packet */
128 ti = proto_tree_add_item(tree, proto_netmon_802_11, tvb, 0, length,
129 ENC_NA);
130 wlan_tree = proto_item_add_subtree(ti, ett_netmon_802_11);
131
132 /*
133 * XXX - is this the NDIS_OBJECT_HEADER structure:
134 *
135 * https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddndis/ns-ntddndis-_ndis_object_header
136 *
137 * at the beginning of a DOT11_EXTSTA_RECV_CONTEXT structure:
138 *
139 * https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/windot11/ns-windot11-dot11_extsta_recv_context
140 *
141 * If so, the byte at an offset of 0 would be the appropriate type for the
142 * structure following it, i.e. NDIS_OBJECT_TYPE_DEFAULT.
143 */
144 proto_tree_add_item(wlan_tree, hf_netmon_802_11_version, tvb, offset, 1,
145 ENC_LITTLE_ENDIAN);
146 offset += 1;
147 proto_tree_add_item(wlan_tree, hf_netmon_802_11_length, tvb, offset, 2,
148 ENC_LITTLE_ENDIAN);
149 offset += 2;
150
151 /*
152 * This isn't in the DOT11_EXTSTA_RECV_CONTEXT structure.
153 */
154 ti = proto_tree_add_item(wlan_tree, hf_netmon_802_11_op_mode, tvb, offset,
155 4, ENC_LITTLE_ENDIAN);
156 opmode_tree = proto_item_add_subtree(ti, ett_netmon_802_11_op_mode);
157 proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta, tvb, offset,
158 4, ENC_LITTLE_ENDIAN);
159 proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_ap, tvb, offset,
160 4, ENC_LITTLE_ENDIAN);
161 proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta_ext, tvb,
162 offset, 4, ENC_LITTLE_ENDIAN);
163 proto_tree_add_item_ret_uint(opmode_tree, hf_netmon_802_11_op_mode_mon, tvb, offset,
164 4, ENC_LITTLE_ENDIAN, &monitor_mode);
165 if (!monitor_mode) {
166 /*
167 * If a NetMon capture is not done in monitor mode, we may see frames
168 * with the Protect bit set (because they were encrypted on the air)
169 * but that aren't encrypted (because they've been decrypted before
170 * being written to the file). This wasn't done in monitor mode, as
171 * the "monitor mode" flag wasn't set, so supporess treating the
172 * Protect flag as an indication that the frame was encrypted.
173 */
174 phdr.decrypted = TRUE;
175
176 /*
177 * Furthermore, we may see frames with the A-MSDU Present flag set
178 * in the QoS Control field but that have a regular frame, nto a
179 * sequence of A-MSDUs, in the payload.
180 */
181 phdr.no_a_msdus = TRUE;
182 }
183 offset += 4;
184
185 /*
186 * uReceiveFlags?
187 */
188 flags = tvb_get_letohl(tvb, offset);
189 offset += 4;
190 if (flags != 0xffffffff) {
191 /*
192 * uPhyId?
193 */
194 phy_type = tvb_get_letohl(tvb, offset);
195 memset(&phdr.phy_info, 0, sizeof(phdr.phy_info));
196
197 /*
198 * Unlike the channel flags in radiotap, this appears
199 * to correctly indicate the modulation for this packet
200 * (no cases seen where this doesn't match the data rate).
201 */
202 switch (phy_type) {
203
204 case PHY_TYPE_UNKNOWN:
205 phdr.phy = PHDR_802_11_PHY_UNKNOWN;
206 break;
207
208 case PHY_TYPE_FHSS:
209 phdr.phy = PHDR_802_11_PHY_11_FHSS;
210 break;
211
212 case PHY_TYPE_IR_BASEBAND:
213 phdr.phy = PHDR_802_11_PHY_11_IR;
214 break;
215
216 case PHY_TYPE_DSSS:
217 phdr.phy = PHDR_802_11_PHY_11_DSSS;
218 break;
219
220 case PHY_TYPE_HR_DSSS:
221 phdr.phy = PHDR_802_11_PHY_11B;
222 break;
223
224 case PHY_TYPE_OFDM:
225 phdr.phy = PHDR_802_11_PHY_11A;
226 break;
227
228 case PHY_TYPE_ERP:
229 phdr.phy = PHDR_802_11_PHY_11G;
230 break;
231
232 case PHY_TYPE_HT:
233 phdr.phy = PHDR_802_11_PHY_11N;
234 break;
235
236 case PHY_TYPE_VHT:
237 phdr.phy = PHDR_802_11_PHY_11AC;
238 break;
239
240 default:
241 phdr.phy = PHDR_802_11_PHY_UNKNOWN;
242 break;
243 }
244 proto_tree_add_item(wlan_tree, hf_netmon_802_11_phy_type, tvb, offset, 4,
245 ENC_LITTLE_ENDIAN);
246 offset += 4;
247
248 /*
249 * uChCenterFrequency?
250 */
251 channel = tvb_get_letohl(tvb, offset);
252 if (channel < 1000) {
253 if (channel == 0) {
254 proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_channel,
255 tvb, offset, 4, channel,
256 "Unknown");
257 } else {
258 guint frequency;
259
260 phdr.has_channel = TRUE;
261 phdr.channel = channel;
262 proto_tree_add_uint(wlan_tree, hf_netmon_802_11_channel,
263 tvb, offset, 4, channel);
264 switch (phdr.phy) {
265
266 case PHDR_802_11_PHY_11B:
267 case PHDR_802_11_PHY_11G:
268 /* 2.4 GHz channel */
269 frequency = ieee80211_chan_to_mhz(channel, TRUE);
270 break;
271
272 case PHDR_802_11_PHY_11A:
273 /* 5 GHz channel */
274 frequency = ieee80211_chan_to_mhz(channel, FALSE);
275 break;
276
277 default:
278 frequency = 0;
279 break;
280 }
281 if (frequency != 0) {
282 phdr.has_frequency = TRUE;
283 phdr.frequency = frequency;
284 }
285 }
286 } else {
287 phdr.has_frequency = TRUE;
288 phdr.frequency = channel;
289 proto_tree_add_uint(wlan_tree, hf_netmon_802_11_frequency,
290 tvb, offset, 4, channel);
291 calc_channel = ieee80211_mhz_to_chan(channel);
292 if (calc_channel != -1) {
293 phdr.has_channel = TRUE;
294 phdr.channel = calc_channel;
295 }
296 }
297 offset += 4;
298
299 /*
300 * usNumberOfMPDUsReceived is missing.
301 */
302
303 /*
304 * lRSSI?
305 */
306 rssi = tvb_get_letohl(tvb, offset);
307 if (rssi == 0) {
308 proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
309 tvb, offset, 4, rssi,
310 "Unknown");
311 } else {
312 phdr.has_signal_dbm = TRUE;
313 phdr.signal_dbm = rssi;
314 proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
315 tvb, offset, 4, rssi,
316 "%d dBm", rssi);
317 }
318 offset += 4;
319
320 /*
321 * ucDataRate?
322 */
323 rate = tvb_get_guint8(tvb, offset);
324 if (rate == 0) {
325 proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
326 tvb, offset, 1, rate,
327 "Unknown");
328 } else {
329 phdr.has_data_rate = TRUE;
330 phdr.data_rate = rate;
331 proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
332 tvb, offset, 1, rate,
333 "%f Mb/s", rate*.5);
334 }
335 offset += 1;
336 } else
337 offset += 13;
338
339 /*
340 * ullTimestamp?
341 *
342 * If so, should this check the presense flag in flags?
343 */
344 phdr.has_tsf_timestamp = TRUE;
345 phdr.tsf_timestamp = tvb_get_letoh64(tvb, offset);
346 proto_tree_add_item(wlan_tree, hf_netmon_802_11_timestamp, tvb, offset, 8,
347 ENC_LITTLE_ENDIAN);
348 /*offset += 8;*/
349
350 skip:
351 offset = length;
352
353 /* dissect the 802.11 packet next */
354 next_tvb = tvb_new_subset_remaining(tvb, offset);
355 call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, tree, &phdr);
356 return offset;
357 }
358
359 void
proto_register_netmon_802_11(void)360 proto_register_netmon_802_11(void)
361 {
362 static const value_string phy_type[] = {
363 { PHY_TYPE_UNKNOWN, "Unknown" },
364 { PHY_TYPE_FHSS, "802.11 FHSS" },
365 { PHY_TYPE_DSSS, "802.11 DSSS" },
366 { PHY_TYPE_IR_BASEBAND, "802.11 IR" },
367 { PHY_TYPE_OFDM, "802.11a" },
368 { PHY_TYPE_HR_DSSS, "802.11b" },
369 { PHY_TYPE_ERP, "802.11g" },
370 { PHY_TYPE_HT, "802.11n" },
371 { PHY_TYPE_VHT, "802.11ac" },
372 { 0, NULL },
373 };
374
375 static hf_register_info hf[] = {
376 { &hf_netmon_802_11_version, { "Header revision", "netmon_802_11.version", FT_UINT8,
377 BASE_DEC, NULL, 0x0, NULL, HFILL } },
378 { &hf_netmon_802_11_length, { "Header length", "netmon_802_11.length", FT_UINT16,
379 BASE_DEC, NULL, 0x0, NULL, HFILL } },
380 { &hf_netmon_802_11_op_mode, { "Operation mode", "netmon_802_11.op_mode", FT_UINT32,
381 BASE_HEX, NULL, 0x0, NULL, HFILL } },
382 { &hf_netmon_802_11_op_mode_sta, { "Station mode", "netmon_802_11.op_mode.sta", FT_UINT32,
383 BASE_HEX, NULL, OP_MODE_STA, NULL, HFILL } },
384 { &hf_netmon_802_11_op_mode_ap, { "AP mode", "netmon_802_11.op_mode.ap", FT_UINT32,
385 BASE_HEX, NULL, OP_MODE_AP, NULL, HFILL } },
386 { &hf_netmon_802_11_op_mode_sta_ext, { "Extensible station mode", "netmon_802_11.op_mode.sta_ext", FT_UINT32,
387 BASE_HEX, NULL, OP_MODE_STA_EXT, NULL, HFILL } },
388 { &hf_netmon_802_11_op_mode_mon, { "Monitor mode", "netmon_802_11.op_mode.mon", FT_UINT32,
389 BASE_HEX, NULL, OP_MODE_MON, NULL, HFILL } },
390 #if 0
391 { &hf_netmon_802_11_flags, { "Flags", "netmon_802_11.flags", FT_UINT32,
392 BASE_HEX, NULL, 0x0, NULL, HFILL } },
393 #endif
394 { &hf_netmon_802_11_phy_type, { "PHY type", "netmon_802_11.phy_type", FT_UINT32,
395 BASE_DEC, VALS(phy_type), 0x0, NULL, HFILL } },
396 { &hf_netmon_802_11_channel, { "Channel", "netmon_802_11.channel", FT_UINT32,
397 BASE_DEC, NULL, 0x0, NULL, HFILL } },
398 { &hf_netmon_802_11_frequency, { "Center frequency", "netmon_802_11.frequency", FT_UINT32,
399 BASE_DEC|BASE_UNIT_STRING, &units_mhz, 0x0, NULL, HFILL } },
400 { &hf_netmon_802_11_rssi, { "RSSI", "netmon_802_11.rssi", FT_INT32,
401 BASE_DEC, NULL, 0x0, NULL, HFILL } },
402 { &hf_netmon_802_11_datarate, { "Data rate", "netmon_802_11.datarate", FT_UINT32,
403 BASE_DEC, NULL, 0x0, NULL, HFILL } },
404 /*
405 * XXX - is this host, or MAC, time stamp?
406 * It might be a FILETIME.
407 */
408 { &hf_netmon_802_11_timestamp, { "Timestamp", "netmon_802_11.timestamp", FT_UINT64,
409 BASE_DEC, NULL, 0x0, NULL, HFILL } },
410 };
411 static gint *ett[] = {
412 &ett_netmon_802_11,
413 &ett_netmon_802_11_op_mode
414 };
415
416 proto_netmon_802_11 = proto_register_protocol("NetMon 802.11 capture header",
417 "NetMon 802.11",
418 "netmon_802_11");
419 netmon_802_11_handle = register_dissector("netmon_802_11", dissect_netmon_802_11, proto_netmon_802_11);
420 proto_register_field_array(proto_netmon_802_11, hf, array_length(hf));
421 proto_register_subtree_array(ett, array_length(ett));
422 }
423
424 void
proto_reg_handoff_netmon_802_11(void)425 proto_reg_handoff_netmon_802_11(void)
426 {
427 /* handle for 802.11+radio information dissector */
428 ieee80211_radio_handle = find_dissector_add_dependency("wlan_radio", proto_netmon_802_11);
429 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_NETMON, netmon_802_11_handle);
430 }
431
432 /*
433 * Editor modelines - https://www.wireshark.org/tools/modelines.html
434 *
435 * Local Variables:
436 * c-basic-offset: 2
437 * tab-width: 8
438 * indent-tabs-mode: nil
439 * End:
440 *
441 * ex: set shiftwidth=2 tabstop=8 expandtab:
442 * :indentSize=2:tabSize=8:noTabs=true:
443 */
444