2 * Routines for BTSNOOP File Format
4 * Copyright 2014, Michal Labedzki for Tieto Corporation
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
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <wiretap/wtap.h>
19 #include <wsutil/array.h>
21 static dissector_handle_t btsnoop_handle
;
22 static dissector_handle_t hci_h1_handle
;
23 static dissector_handle_t hci_h4_handle
;
24 static dissector_handle_t hci_mon_handle
;
26 static int proto_btsnoop
;
28 static int hf_btsnoop_header
;
29 static int hf_btsnoop_magic_bytes
;
30 static int hf_btsnoop_version
;
31 static int hf_btsnoop_datalink
;
32 static int hf_btsnoop_frame
;
33 static int hf_btsnoop_origin_length
;
34 static int hf_btsnoop_included_length
;
35 static int hf_btsnoop_flags
;
36 static int hf_btsnoop_cumulative_dropped_packets
;
37 static int hf_btsnoop_timestamp_microseconds
;
38 static int hf_btsnoop_payload
;
39 static int hf_btsnoop_flags_h1_reserved
;
40 static int hf_btsnoop_flags_h1_channel_type
;
41 static int hf_btsnoop_flags_h1_direction
;
42 static int hf_btsnoop_flags_h4_reserved
;
43 static int hf_btsnoop_flags_h4_direction
;
44 static int hf_btsnoop_flags_linux_monitor_opcode
;
45 static int hf_btsnoop_flags_linux_monitor_adapter_id
;
47 static expert_field ei_malformed_frame
;
48 static expert_field ei_not_implemented_yet
;
49 static expert_field ei_unknown_data
;
51 static int ett_btsnoop
;
52 static int ett_btsnoop_header
;
53 static int ett_btsnoop_frame
;
54 static int ett_btsnoop_payload
;
55 static int ett_btsnoop_flags
;
57 static bool pref_dissect_next_layer
;
59 extern value_string_ext hci_mon_opcode_vals_ext
;
61 static const value_string datalink_vals
[] = {
63 { 1002, "H4 (UART)" },
65 { 1004, "H5 (3 Wire)" },
66 { 2001, "Linux Monitor" },
67 { 2002, "Simulator" },
71 static const value_string flags_direction_vals
[] = {
77 static const value_string flags_h1_channel_type_vals
[] = {
83 void proto_register_btsnoop(void);
84 void proto_reg_handoff_btsnoop(void);
87 dissect_btsnoop(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
89 static const uint8_t magic
[] = { 'b', 't', 's', 'n', 'o', 'o', 'p', 0};
94 proto_tree
*main_tree
;
95 proto_item
*main_item
;
96 proto_tree
*header_tree
;
97 proto_item
*header_item
;
98 proto_tree
*frame_tree
;
99 proto_item
*frame_item
;
100 proto_tree
*flags_tree
;
101 proto_item
*flags_item
;
102 proto_tree
*payload_tree
;
103 proto_item
*payload_item
;
104 static uint32_t frame_number
= 1;
109 if (tvb_memeql(tvb
, 0, magic
, sizeof(magic
)) != 0)
112 if (offset
== 0) frame_number
= 1;
114 main_item
= proto_tree_add_item(tree
, proto_btsnoop
, tvb
, offset
, -1, ENC_NA
);
115 main_tree
= proto_item_add_subtree(main_item
, ett_btsnoop
);
117 header_item
= proto_tree_add_item(main_tree
, hf_btsnoop_header
, tvb
, offset
, sizeof(magic
) + 4 + 4, ENC_NA
);
118 header_tree
= proto_item_add_subtree(header_item
, ett_btsnoop_header
);
120 proto_tree_add_item(header_tree
, hf_btsnoop_magic_bytes
, tvb
, offset
, sizeof(magic
), ENC_ASCII
| ENC_NA
);
121 offset
+= (int)sizeof(magic
);
123 proto_tree_add_item(header_tree
, hf_btsnoop_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
126 proto_tree_add_item(header_tree
, hf_btsnoop_datalink
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
127 datalink
= tvb_get_ntohl(tvb
, offset
);
130 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
131 frame_item
= proto_tree_add_item(main_tree
, hf_btsnoop_frame
, tvb
, offset
, 0, ENC_NA
);
132 frame_tree
= proto_item_add_subtree(frame_item
, ett_btsnoop_frame
);
134 if (tvb_reported_length_remaining(tvb
, offset
) < 4 * 4 + 8) {
135 expert_add_info(pinfo
, frame_item
, &ei_malformed_frame
);
138 proto_item_append_text(frame_item
, " %u", frame_number
);
140 proto_tree_add_item(frame_tree
, hf_btsnoop_origin_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
143 proto_tree_add_item(frame_tree
, hf_btsnoop_included_length
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
144 length
= tvb_get_ntohl(tvb
, offset
);
147 flags_item
= proto_tree_add_item(frame_tree
, hf_btsnoop_flags
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
148 flags_tree
= proto_item_add_subtree(flags_item
, ett_btsnoop_flags
);
149 flags
= tvb_get_ntohl(tvb
, offset
);
152 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_h1_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
153 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_h1_channel_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
154 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_h1_direction
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
157 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_h4_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
158 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_h4_direction
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
160 case 2001: /* Linux Monitor */
161 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_linux_monitor_adapter_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
162 proto_tree_add_item(flags_tree
, hf_btsnoop_flags_linux_monitor_opcode
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
167 proto_tree_add_item(frame_tree
, hf_btsnoop_cumulative_dropped_packets
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
170 ts
= tvb_get_ntoh64(tvb
, offset
) - INT64_C(0x00dcddb30f2f8000);
171 timestamp
.secs
= (unsigned)(ts
/ 1000000);
172 timestamp
.nsecs
=(unsigned)((ts
% 1000000) * 1000);
174 proto_tree_add_time(frame_tree
, hf_btsnoop_timestamp_microseconds
, tvb
, offset
, 8, ×tamp
);
177 payload_item
= proto_tree_add_item(frame_tree
, hf_btsnoop_payload
, tvb
, offset
, length
, ENC_NA
);
178 payload_tree
= proto_item_add_subtree(payload_item
, ett_btsnoop_payload
);
180 if (pref_dissect_next_layer
) switch (datalink
) {\
182 pinfo
->num
= frame_number
;
183 pinfo
->abs_ts
= timestamp
;
185 pinfo
->pseudo_header
->bthci
.sent
= (flags
& 0x01) ? false : true;
187 if(pinfo
->pseudo_header
->bthci
.sent
)
188 pinfo
->pseudo_header
->bthci
.channel
= BTHCI_CHANNEL_COMMAND
;
190 pinfo
->pseudo_header
->bthci
.channel
= BTHCI_CHANNEL_EVENT
;
192 pinfo
->pseudo_header
->bthci
.channel
= BTHCI_CHANNEL_ACL
;
195 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
196 call_dissector(hci_h1_handle
, next_tvb
, pinfo
, payload_tree
);
199 pinfo
->num
= frame_number
;
200 pinfo
->abs_ts
= timestamp
;
201 pinfo
->p2p_dir
= (flags
& 0x01) ? P2P_DIR_RECV
: P2P_DIR_SENT
;
203 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
204 call_dissector(hci_h4_handle
, next_tvb
, pinfo
, payload_tree
);
206 case 2001: /* Linux Monitor */
207 pinfo
->num
= frame_number
;
208 pinfo
->abs_ts
= timestamp
;
210 pinfo
->pseudo_header
->btmon
.opcode
= flags
& 0xFFFF;
211 pinfo
->pseudo_header
->btmon
.adapter_id
= flags
>> 16;
213 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
214 call_dissector(hci_mon_handle
, next_tvb
, pinfo
, payload_tree
);
217 case 1003: /* BCSP */
218 case 1004: /* H5 (3 Wire) */
219 case 2002: /* Simulator */
220 /* Not implemented yet */
221 proto_tree_add_expert(payload_tree
, pinfo
, &ei_not_implemented_yet
, tvb
, offset
, length
);
225 proto_tree_add_expert(payload_tree
, pinfo
, &ei_unknown_data
, tvb
, offset
, length
);
229 proto_item_set_len(frame_item
, 4 * 4 + 8 + length
);
237 dissect_btsnoop_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
239 return dissect_btsnoop(tvb
, pinfo
, tree
, data
) > 0;
243 proto_register_btsnoop(void)
246 expert_module_t
*expert_module
;
248 static hf_register_info hf
[] = {
249 { &hf_btsnoop_header
,
250 { "Header", "btsnoop.header",
251 FT_NONE
, BASE_NONE
, NULL
, 0x00,
254 { &hf_btsnoop_magic_bytes
,
255 { "Magic Bytes", "btsnoop.header.magic_bytes",
256 FT_STRINGZ
, BASE_NONE
, NULL
, 0x00,
259 { &hf_btsnoop_version
,
260 { "Version", "btsnoop.header.version",
261 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
264 { &hf_btsnoop_datalink
,
265 { "Datalink", "btsnoop.header.datalink",
266 FT_UINT32
, BASE_DEC_HEX
, VALS(datalink_vals
), 0x00,
270 { "Frame", "btsnoop.frame",
271 FT_NONE
, BASE_NONE
, NULL
, 0x00,
274 { &hf_btsnoop_origin_length
,
275 { "Origin Length", "btsnoop.frame.origin_length",
276 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
279 { &hf_btsnoop_included_length
,
280 { "Included Length", "btsnoop.frame.included_length",
281 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
285 { "Flags", "btsnoop.frame.flags",
286 FT_UINT32
, BASE_HEX
, NULL
, 0x00,
289 { &hf_btsnoop_cumulative_dropped_packets
,
290 { "Cumulative Dropped Packets", "btsnoop.frame.cumulative_dropped_packets",
291 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
294 { &hf_btsnoop_timestamp_microseconds
,
295 { "Timestamp Microseconds", "btsnoop.frame.timestamp_microseconds",
296 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x00,
299 { &hf_btsnoop_payload
,
300 { "Payload", "btsnoop.frame.payload",
301 FT_NONE
, BASE_NONE
, NULL
, 0x00,
304 { &hf_btsnoop_flags_h1_reserved
,
305 { "Reserved", "btsnoop.frame.flags.h1.reserved",
306 FT_UINT32
, BASE_HEX
, NULL
, 0xFFFFFFFC,
309 { &hf_btsnoop_flags_h1_channel_type
,
310 { "Channel Type", "btsnoop.frame.flags.h1.channel_type",
311 FT_UINT32
, BASE_DEC
, VALS(flags_h1_channel_type_vals
), 0x02,
314 { &hf_btsnoop_flags_h1_direction
,
315 { "Direction", "btsnoop.frame.flags.h1.direction",
316 FT_UINT32
, BASE_DEC
, VALS(flags_direction_vals
), 0x01,
319 { &hf_btsnoop_flags_h4_reserved
,
320 { "Reserved", "btsnoop.frame.flags.h4.reserved",
321 FT_UINT32
, BASE_HEX
, NULL
, 0xFFFFFFFE,
324 { &hf_btsnoop_flags_h4_direction
,
325 { "Direction", "btsnoop.frame.flags.h4.direction",
326 FT_UINT32
, BASE_DEC
, VALS(flags_direction_vals
), 0x01,
329 { &hf_btsnoop_flags_linux_monitor_opcode
,
330 { "Opcode", "btsnoop.frame.flags.linux_monitor.opcode",
331 FT_UINT16
, BASE_HEX
| BASE_EXT_STRING
, &hci_mon_opcode_vals_ext
, 0x00,
334 { &hf_btsnoop_flags_linux_monitor_adapter_id
,
335 { "Adapter ID", "btsnoop.frame.flags.linux_monitor.adapter_id",
336 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
341 static ei_register_info ei
[] = {
342 { &ei_malformed_frame
, { "btsnoop.malformed_frame", PI_PROTOCOL
, PI_WARN
, "Malformed Frame", EXPFILL
}},
343 { &ei_not_implemented_yet
, { "btsnoop.not_implemented_yet", PI_PROTOCOL
, PI_WARN
, "Not implemented yet", EXPFILL
}},
344 { &ei_unknown_data
, { "btsnoop.unknown_data", PI_PROTOCOL
, PI_WARN
, "Unknown data", EXPFILL
}},
347 static int *ett
[] = {
351 &ett_btsnoop_payload
,
355 proto_btsnoop
= proto_register_protocol("Symbian OS BTSNOOP File Format", "BTSNOOP", "btsnoop");
356 proto_register_field_array(proto_btsnoop
, hf
, array_length(hf
));
357 proto_register_subtree_array(ett
, array_length(ett
));
359 btsnoop_handle
= register_dissector("btsnoop", dissect_btsnoop
, proto_btsnoop
);
361 module
= prefs_register_protocol(proto_btsnoop
, NULL
);
362 prefs_register_static_text_preference(module
, "version",
363 "BTSNOOP version: 1",
364 "Version of file-format supported by this dissector.");
366 prefs_register_bool_preference(module
, "dissect_next_layer",
367 "Dissect next layer",
368 "Dissect next layer",
369 &pref_dissect_next_layer
);
371 expert_module
= expert_register_protocol(proto_btsnoop
);
372 expert_register_field_array(expert_module
, ei
, array_length(ei
));
376 proto_reg_handoff_btsnoop(void)
378 hci_h1_handle
= find_dissector_add_dependency("hci_h1", proto_btsnoop
);
379 hci_h4_handle
= find_dissector_add_dependency("hci_h4", proto_btsnoop
);
380 hci_mon_handle
= find_dissector_add_dependency("hci_mon", proto_btsnoop
);
382 heur_dissector_add("wtap_file", dissect_btsnoop_heur
, "BTSNOOP file", "btsnoop_wtap", proto_btsnoop
, HEURISTIC_ENABLE
);
386 * Editor modelines - https://www.wireshark.org/tools/modelines.html
391 * indent-tabs-mode: nil
394 * vi: set shiftwidth=4 tabstop=8 expandtab:
395 * :indentSize=4:tabSize=8:noTabs=true: