Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-btle_rf.c
blob453b24fc0c64c68a3ff980dec903b559fc91f07b
1 /* packet-btle_rf.c
2 * https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR.html
4 * Copyright 2014, Christopher D. Kilgour, techie at whiterocker dot com
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <wiretap/wtap.h>
18 #include "packet-btle.h"
20 #define LE_DEWHITENED 0x0001
21 #define LE_SIGPOWER_VALID 0x0002
22 #define LE_NOISEPOWER_VALID 0x0004
23 #define LE_PACKET_DECRYPTED 0x0008
24 #define LE_REF_AA_VALID 0x0010
25 #define LE_AA_OFFENSES_VALID 0x0020
26 #define LE_CHANNEL_ALIASED 0x0040
27 #define LE_PDU_TYPE 0x0380
28 #define LE_CRC_CHECKED 0x0400
29 #define LE_CRC_VALID 0x0800
30 #define LE_MIC_CHECKED 0x1000
31 #define LE_MIC_VALID 0x2000
32 #define LE_PHY 0xC000
34 #define BTLE_RF_OCTETS 10
36 static int proto_btle_rf;
38 static int hf_btle_rf_signed_byte_unused;
39 static int hf_btle_rf_unsigned_byte_unused;
40 static int hf_btle_rf_word_unused;
41 static int hf_btle_rf_channel;
42 static int hf_btle_rf_signal_dbm;
43 static int hf_btle_rf_noise_dbm;
44 static int hf_btle_rf_access_address_offenses;
45 static int hf_btle_rf_reference_access_address;
46 static int hf_btle_rf_flags;
47 static int hf_btle_rf_dewhitened_flag;
48 static int hf_btle_rf_sigpower_valid_flag;
49 static int hf_btle_rf_noisepower_valid_flag;
50 static int hf_btle_rf_packet_decrypted_flag;
51 static int hf_btle_rf_ref_aa_valid_flag;
52 static int hf_btle_rf_aa_offenses_valid_flag;
53 static int hf_btle_rf_channel_aliased_flag;
54 static int hf_btle_rf_pdu_type;
55 static int hf_btle_rf_crc_checked_flag;
56 static int hf_btle_rf_crc_valid_flag;
57 static int hf_btle_rf_mic_checked_flag;
58 static int hf_btle_rf_mic_valid_flag;
59 static int hf_btle_rf_phy;
61 static int * const hfs_btle_rf_flags[] = {
62 &hf_btle_rf_dewhitened_flag,
63 &hf_btle_rf_sigpower_valid_flag,
64 &hf_btle_rf_noisepower_valid_flag,
65 &hf_btle_rf_packet_decrypted_flag,
66 &hf_btle_rf_ref_aa_valid_flag,
67 &hf_btle_rf_aa_offenses_valid_flag,
68 &hf_btle_rf_channel_aliased_flag,
69 &hf_btle_rf_pdu_type,
70 &hf_btle_rf_crc_checked_flag,
71 &hf_btle_rf_crc_valid_flag,
72 &hf_btle_rf_mic_checked_flag,
73 &hf_btle_rf_mic_valid_flag,
74 &hf_btle_rf_phy,
75 NULL
78 static int ett_btle_rf;
79 static int ett_btle_rf_flags;
81 static dissector_handle_t btle_rf_handle;
82 static dissector_handle_t btle_handle;
84 void proto_register_btle_rf(void);
85 void proto_reg_handoff_btle_rf(void);
87 static const value_string le_phys[] =
89 { 0, "LE 1M" },
90 { 1, "LE 2M" },
91 { 2, "LE Coded" },
92 { 3, "Reserved" },
93 { 0, NULL }
96 static const value_string le_pdus[] =
98 { 0, "Advertising or Data (Unspecified Direction)" },
99 { 1, "Auxiliary Advertising" },
100 { 2, "Data, Central to Peripheral" },
101 { 3, "Data, Peripheral to Central" },
102 { 4, "Connected Isochronous, Central to Peripheral" },
103 { 5, "Connected Isochronous, Peripheral to Central" },
104 { 6, "Broadcast Isochronous" },
105 { 7, "Reserved" },
106 { 0, NULL }
109 static const char *
110 btle_rf_channel_type(uint8_t rf_channel)
112 if (rf_channel <= 39) {
113 switch(rf_channel) {
114 case 0:
115 case 12:
116 case 39:
117 return "Advertising channel";
118 default:
119 return "Data channel";
122 return "Illegal channel";
125 static uint8_t
126 btle_rf_channel_index(uint8_t rf_channel)
128 if (rf_channel <= 39) {
129 if (rf_channel == 39) {
130 return 39;
132 else if (rf_channel >= 13) {
133 return rf_channel - 2;
135 else if (rf_channel == 12) {
136 return 38;
138 else if (rf_channel >= 1) {
139 return rf_channel - 1;
141 else {
142 return 37;
145 return (uint8_t) -1;
148 static int
149 dissect_btle_rf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
151 proto_item *ti;
152 proto_tree *btle_rf_tree;
153 tvbuff_t *btle_tvb;
154 btle_context_t context;
155 uint8_t rf_channel;
156 uint8_t aa_offenses;
157 uint16_t flags;
158 bluetooth_data_t *bluetooth_data = (bluetooth_data_t *) data;
160 if (tvb_captured_length(tvb) < BTLE_RF_OCTETS)
161 return 0;
163 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BTLE RF");
164 col_clear(pinfo->cinfo, COL_INFO);
166 flags = tvb_get_letohs(tvb, 8);
168 memset(&context, 0, sizeof(context));
169 context.previous_protocol_data.bluetooth_data = bluetooth_data;
170 context.aa_category = E_AA_NO_COMMENT;
171 context.crc_checked_at_capture = !!(flags & LE_CRC_CHECKED);
172 context.crc_valid_at_capture = !!(flags & LE_CRC_VALID);
173 context.mic_checked_at_capture = !!(flags & LE_MIC_CHECKED);
174 context.mic_valid_at_capture = !!(flags & LE_MIC_VALID);
176 switch ((flags & LE_PDU_TYPE) >> 7)
178 case 0: // Advertising or Data (Unspecified Direction)
179 // backwards compatible path
180 context.pdu_type = BTLE_PDU_TYPE_UNKNOWN;
181 break;
182 case 1: // Auxiliary Advertising
183 // advertising is never encrypted, so MIC flags are repurposed
184 context.pdu_type = BTLE_PDU_TYPE_ADVERTISING;
185 context.mic_checked_at_capture = false;
186 context.mic_valid_at_capture = false;
188 // context.aux_pdu_type values defined in aux_pdu_common_vals of packet-btle.c
189 // they match with the definition for this link type
190 context.aux_pdu_type = (flags & 0x3000) >> 12;
191 context.aux_pdu_type_valid = true;
192 break;
193 case 2: // Data, Central to Peripheral
194 context.pdu_type = BTLE_PDU_TYPE_DATA;
195 context.direction = BTLE_DIR_CENTRAL_PERIPHERAL;
196 pinfo->p2p_dir = P2P_DIR_SENT;
197 break;
198 case 3: // Data, Peripheral to Central
199 context.pdu_type = BTLE_PDU_TYPE_DATA;
200 context.direction = BTLE_DIR_PERIPHERAL_CENTRAL;
201 pinfo->p2p_dir = P2P_DIR_RECV;
202 break;
203 case 4: // Connected Isochronous, Central to Peripheral
204 context.pdu_type = BTLE_PDU_TYPE_CONNECTEDISO;
205 context.direction = BTLE_DIR_CENTRAL_PERIPHERAL;
206 pinfo->p2p_dir = P2P_DIR_SENT;
207 break;
208 case 5: // Connected Isochronous, Peripheral to Central
209 context.pdu_type = BTLE_PDU_TYPE_CONNECTEDISO;
210 context.direction = BTLE_DIR_PERIPHERAL_CENTRAL;
211 pinfo->p2p_dir = P2P_DIR_RECV;
212 break;
213 case 6: // Broadcast Isochronous
214 context.pdu_type = BTLE_PDU_TYPE_BROADCASTISO;
215 break;
216 case 7: // Reserved
217 context.pdu_type = BTLE_PDU_TYPE_UNKNOWN;
218 break;
221 ti = proto_tree_add_item(tree, proto_btle_rf, tvb, 0, tvb_captured_length(tvb), ENC_NA);
222 btle_rf_tree = proto_item_add_subtree(ti, ett_btle_rf);
224 ti = proto_tree_add_item(btle_rf_tree, hf_btle_rf_channel, tvb, 0, 1, ENC_LITTLE_ENDIAN);
225 rf_channel = tvb_get_uint8(tvb, 0);
226 proto_item_append_text(ti, ", %d MHz, %s %d", 2402+2*rf_channel,
227 btle_rf_channel_type(rf_channel),
228 btle_rf_channel_index(rf_channel));
229 context.channel = btle_rf_channel_index(rf_channel);
231 if (flags & LE_CHANNEL_ALIASED) {
232 proto_item_append_text(ti, " [aliased]");
235 context.phy = (flags & LE_PHY) >> 14;
237 if (flags & LE_SIGPOWER_VALID) {
238 proto_tree_add_item(btle_rf_tree, hf_btle_rf_signal_dbm, tvb, 1, 1, ENC_LITTLE_ENDIAN);
240 else {
241 proto_tree_add_item(btle_rf_tree, hf_btle_rf_signed_byte_unused, tvb, 1, 1, ENC_LITTLE_ENDIAN);
244 if (flags & LE_NOISEPOWER_VALID) {
245 proto_tree_add_item(btle_rf_tree, hf_btle_rf_noise_dbm, tvb, 2, 1, ENC_LITTLE_ENDIAN);
247 else {
248 proto_tree_add_item(btle_rf_tree, hf_btle_rf_signed_byte_unused, tvb, 2, 1, ENC_LITTLE_ENDIAN);
251 if (flags & LE_AA_OFFENSES_VALID) {
252 proto_tree_add_item(btle_rf_tree, hf_btle_rf_access_address_offenses, tvb, 3, 1, ENC_LITTLE_ENDIAN);
253 aa_offenses = tvb_get_uint8(tvb, 3);
254 if (aa_offenses > 0) {
255 if (flags & LE_REF_AA_VALID) {
256 context.aa_category = E_AA_BIT_ERRORS;
258 else {
259 context.aa_category = E_AA_ILLEGAL;
262 else if (flags & LE_REF_AA_VALID) {
263 context.aa_category = E_AA_MATCHED;
266 else {
267 proto_tree_add_item(btle_rf_tree, hf_btle_rf_unsigned_byte_unused, tvb, 3, 1, ENC_LITTLE_ENDIAN);
270 if (flags & LE_REF_AA_VALID) {
271 proto_tree_add_item(btle_rf_tree, hf_btle_rf_reference_access_address, tvb, 4, 4, ENC_LITTLE_ENDIAN);
273 else {
274 proto_tree_add_item(btle_rf_tree, hf_btle_rf_word_unused, tvb, 4, 4, ENC_LITTLE_ENDIAN);
277 proto_tree_add_bitmask_with_flags(btle_rf_tree, tvb, 8, hf_btle_rf_flags, ett_btle_rf_flags, hfs_btle_rf_flags, ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
279 btle_tvb = tvb_new_subset_remaining(tvb, BTLE_RF_OCTETS);
280 return BTLE_RF_OCTETS+call_dissector_with_data(btle_handle, btle_tvb, pinfo, tree, &context);
283 void
284 proto_register_btle_rf(void)
286 static hf_register_info hf[] = {
287 { &hf_btle_rf_signed_byte_unused,
288 { "Unused signed byte", "btle_rf.signed_byte_unused",
289 FT_INT8, BASE_DEC,
290 NULL, 0x0,
291 NULL, HFILL }
293 { &hf_btle_rf_unsigned_byte_unused,
294 { "Unused unsigned byte", "btle_rf.unsigned_byte_unused",
295 FT_UINT8, BASE_DEC,
296 NULL, 0x0,
297 NULL, HFILL }
299 { &hf_btle_rf_word_unused,
300 { "Unused word", "btle_rf.word_unused",
301 FT_UINT32, BASE_HEX,
302 NULL, 0x0,
303 NULL, HFILL }
305 { &hf_btle_rf_channel,
306 { "RF Channel", "btle_rf.channel",
307 FT_UINT8, BASE_DEC,
308 NULL, 0x0,
309 NULL, HFILL }
311 { &hf_btle_rf_signal_dbm,
312 { "Signal dBm", "btle_rf.signal_dbm",
313 FT_INT8, BASE_DEC,
314 NULL, 0x0,
315 NULL, HFILL }
317 { &hf_btle_rf_noise_dbm,
318 { "Noise dBm", "btle_rf.noise_dbm",
319 FT_INT8, BASE_DEC,
320 NULL, 0x0,
321 NULL, HFILL }
323 { &hf_btle_rf_access_address_offenses,
324 { "Access Address Offenses", "btle_rf.access_address_offenses",
325 FT_UINT8, BASE_DEC,
326 NULL, 0x0,
327 NULL, HFILL }
329 { &hf_btle_rf_reference_access_address,
330 { "Reference Access Address", "btle_rf.reference_access_address",
331 FT_UINT32, BASE_HEX,
332 NULL, 0x0,
333 NULL, HFILL }
335 { &hf_btle_rf_flags,
336 { "Flags", "btle_rf.flags",
337 FT_UINT16, BASE_HEX,
338 NULL, 0x0,
339 NULL, HFILL }
341 { &hf_btle_rf_dewhitened_flag,
342 { "Dewhitened", "btle_rf.flags.dewhitened",
343 FT_BOOLEAN, 16,
344 NULL, LE_DEWHITENED,
345 NULL, HFILL }
347 { &hf_btle_rf_sigpower_valid_flag,
348 { "Signal Power Valid", "btle_rf.flags.signal_dbm_valid",
349 FT_BOOLEAN, 16,
350 NULL, LE_SIGPOWER_VALID,
351 NULL, HFILL }
353 { &hf_btle_rf_noisepower_valid_flag,
354 { "Noise Power Valid", "btle_rf.flags.noise_dbm_valid",
355 FT_BOOLEAN, 16,
356 NULL, LE_NOISEPOWER_VALID,
357 NULL, HFILL }
359 { &hf_btle_rf_packet_decrypted_flag,
360 { "Decrypted", "btle_rf.flags.decrypted",
361 FT_BOOLEAN, 16,
362 NULL, LE_PACKET_DECRYPTED,
363 NULL, HFILL }
365 { &hf_btle_rf_ref_aa_valid_flag,
366 { "Reference Access Address Valid",
367 "btle_rf.flags.reference_access_address_valid",
368 FT_BOOLEAN, 16,
369 NULL, LE_REF_AA_VALID,
370 NULL, HFILL }
372 { &hf_btle_rf_aa_offenses_valid_flag,
373 { "Access Address Offenses Valid",
374 "btle_rf.flags.access_address_offenses_valid",
375 FT_BOOLEAN, 16,
376 NULL, LE_AA_OFFENSES_VALID,
377 NULL, HFILL }
379 { &hf_btle_rf_channel_aliased_flag,
380 { "Channel Aliased", "btle_rf.flags.channel_aliased",
381 FT_BOOLEAN, 16,
382 NULL, LE_CHANNEL_ALIASED,
383 NULL, HFILL }
385 { &hf_btle_rf_pdu_type,
386 { "PDU Type", "btle_rf.pdu_type",
387 FT_UINT16, BASE_DEC,
388 VALS(le_pdus), LE_PDU_TYPE,
389 NULL, HFILL }
391 { &hf_btle_rf_crc_checked_flag,
392 { "CRC Checked", "btle_rf.flags.crc_checked",
393 FT_BOOLEAN, 16,
394 NULL, LE_CRC_CHECKED,
395 NULL, HFILL }
397 { &hf_btle_rf_crc_valid_flag,
398 { "CRC Valid", "btle_rf.flags.crc_valid",
399 FT_BOOLEAN, 16,
400 NULL, LE_CRC_VALID,
401 NULL, HFILL }
403 { &hf_btle_rf_mic_checked_flag,
404 { "MIC Checked", "btle_rf.flags.mic_checked",
405 FT_BOOLEAN, 16,
406 NULL, LE_MIC_CHECKED,
407 NULL, HFILL }
409 { &hf_btle_rf_mic_valid_flag,
410 { "MIC Valid", "btle_rf.flags.mic_valid",
411 FT_BOOLEAN, 16,
412 NULL, LE_MIC_VALID,
413 NULL, HFILL }
415 { &hf_btle_rf_phy,
416 { "PHY", "btle_rf.phy",
417 FT_UINT16, BASE_DEC,
418 VALS(le_phys), LE_PHY,
419 NULL, HFILL }
423 static int *ett[] = {
424 &ett_btle_rf,
425 &ett_btle_rf_flags,
428 proto_btle_rf = proto_register_protocol("Bluetooth Low Energy RF Info",
429 "BTLE RF", "btle_rf");
430 proto_register_field_array(proto_btle_rf, hf, array_length(hf));
431 proto_register_subtree_array(ett, array_length(ett));
432 btle_rf_handle = register_dissector("btle_rf", dissect_btle_rf, proto_btle_rf);
435 void
436 proto_reg_handoff_btle_rf(void)
438 dissector_add_uint("bluetooth.encap", WTAP_ENCAP_BLUETOOTH_LE_LL_WITH_PHDR, btle_rf_handle);
439 btle_handle = find_dissector_add_dependency("btle", proto_btle_rf);
443 * Editor modelines - https://www.wireshark.org/tools/modelines.html
445 * Local variables:
446 * c-basic-offset: 4
447 * tab-width: 8
448 * indent-tabs-mode: nil
449 * End:
451 * vi: set shiftwidth=4 tabstop=8 expandtab:
452 * :indentSize=4:tabSize=8:noTabs=true: