HTTPS (almost) everywhere.
[metze/wireshark/wip.git] / epan / dissectors / file-btsnoop.c
1 /* file-btsnoop.c
2  * Routines for BTSNOOP File Format
3  *
4  * Copyright 2014, Michal Labedzki for Tieto Corporation
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12
13 #include "config.h"
14
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/wmem/wmem.h>
19
20 #include <wiretap/wtap.h>
21
22 static dissector_handle_t btsnoop_handle;
23 static dissector_handle_t hci_h1_handle;
24 static dissector_handle_t hci_h4_handle;
25 static dissector_handle_t hci_mon_handle;
26
27 static int proto_btsnoop = -1;
28
29 static int hf_btsnoop_header = -1;
30 static int hf_btsnoop_magic_bytes = -1;
31 static int hf_btsnoop_version = -1;
32 static int hf_btsnoop_datalink = -1;
33 static int hf_btsnoop_frame = -1;
34 static int hf_btsnoop_origin_length = -1;
35 static int hf_btsnoop_included_length = -1;
36 static int hf_btsnoop_flags = -1;
37 static int hf_btsnoop_cumulative_dropped_packets = -1;
38 static int hf_btsnoop_timestamp_microseconds = -1;
39 static int hf_btsnoop_payload = -1;
40 static int hf_btsnoop_flags_h1_reserved = -1;
41 static int hf_btsnoop_flags_h1_channel_type = -1;
42 static int hf_btsnoop_flags_h1_direction = -1;
43 static int hf_btsnoop_flags_h4_reserved = -1;
44 static int hf_btsnoop_flags_h4_direction = -1;
45 static int hf_btsnoop_flags_linux_monitor_opcode = -1;
46 static int hf_btsnoop_flags_linux_monitor_adapter_id = -1;
47
48 static expert_field ei_malformed_frame = EI_INIT;
49 static expert_field ei_not_implemented_yet = EI_INIT;
50 static expert_field ei_unknown_data = EI_INIT;
51
52 static gint ett_btsnoop = -1;
53 static gint ett_btsnoop_header = -1;
54 static gint ett_btsnoop_frame = -1;
55 static gint ett_btsnoop_payload = -1;
56 static gint ett_btsnoop_flags = -1;
57
58 static gboolean pref_dissect_next_layer = FALSE;
59
60 extern value_string_ext hci_mon_opcode_vals_ext;
61
62 static const value_string datalink_vals[] = {
63     { 1001,  "H1" },
64     { 1002,  "H4 (UART)" },
65     { 1003,  "BCSP" },
66     { 1004,  "H5 (3 Wire)" },
67     { 2001,  "Linux Monitor" },
68     { 2002,  "Simulator" },
69     { 0, NULL }
70 };
71
72 static const value_string flags_direction_vals[] = {
73     { 0x00,  "Received" },
74     { 0x01,  "Sent" },
75     { 0, NULL }
76 };
77
78 static const value_string flags_h1_channel_type_vals[] = {
79     { 0x00,  "ACL" },
80     { 0x01,  "HCI" },
81     { 0, NULL }
82 };
83
84 void proto_register_btsnoop(void);
85 void proto_reg_handoff_btsnoop(void);
86
87 static int
88 dissect_btsnoop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
89 {
90     static const guint8 magic[] = { 'b', 't', 's', 'n', 'o', 'o', 'p', 0};
91     gint             offset = 0;
92     guint32          datalink;
93     guint32          flags;
94     guint32          length;
95     proto_tree      *main_tree;
96     proto_item      *main_item;
97     proto_tree      *header_tree;
98     proto_item      *header_item;
99     proto_tree      *frame_tree;
100     proto_item      *frame_item;
101     proto_tree      *flags_tree;
102     proto_item      *flags_item;
103     proto_tree      *payload_tree;
104     proto_item      *payload_item;
105     static guint32   frame_number = 1;
106     tvbuff_t        *next_tvb;
107     nstime_t         timestamp;
108     guint64          ts;
109
110     if (tvb_memeql(tvb, 0, magic, sizeof(magic)) != 0)
111         return 0;
112
113     if (offset == 0) frame_number = 1;
114
115     main_item = proto_tree_add_item(tree, proto_btsnoop, tvb, offset, -1, ENC_NA);
116     main_tree = proto_item_add_subtree(main_item, ett_btsnoop);
117
118     header_item = proto_tree_add_item(main_tree, hf_btsnoop_header, tvb, offset, sizeof(magic) + 4 + 4, ENC_NA);
119     header_tree = proto_item_add_subtree(header_item, ett_btsnoop_header);
120
121     proto_tree_add_item(header_tree, hf_btsnoop_magic_bytes, tvb, offset, sizeof(magic), ENC_ASCII | ENC_NA);
122     offset += (gint)sizeof(magic);
123
124     proto_tree_add_item(header_tree, hf_btsnoop_version, tvb, offset, 4, ENC_BIG_ENDIAN);
125     offset += 4;
126
127     proto_tree_add_item(header_tree, hf_btsnoop_datalink, tvb, offset, 4, ENC_BIG_ENDIAN);
128     datalink = tvb_get_ntohl(tvb, offset);
129     offset += 4;
130
131     while (tvb_reported_length_remaining(tvb, offset) > 0) {
132         frame_item = proto_tree_add_item(main_tree, hf_btsnoop_frame, tvb, offset, 0, ENC_NA);
133         frame_tree = proto_item_add_subtree(frame_item, ett_btsnoop_frame);
134
135         if (tvb_reported_length_remaining(tvb, offset) < 4 * 4 + 8) {
136             expert_add_info(pinfo, frame_item, &ei_malformed_frame);
137         }
138
139         proto_item_append_text(frame_item, " %u", frame_number);
140
141         proto_tree_add_item(frame_tree, hf_btsnoop_origin_length, tvb, offset, 4, ENC_BIG_ENDIAN);
142         offset += 4;
143
144         proto_tree_add_item(frame_tree, hf_btsnoop_included_length, tvb, offset, 4, ENC_BIG_ENDIAN);
145         length = tvb_get_ntohl(tvb, offset);
146         offset += 4;
147
148         flags_item = proto_tree_add_item(frame_tree, hf_btsnoop_flags, tvb, offset, 4, ENC_BIG_ENDIAN);
149         flags_tree = proto_item_add_subtree(flags_item, ett_btsnoop_flags);
150         flags = tvb_get_ntohl(tvb, offset);
151         switch (datalink) {
152         case 1001: /* H1 */
153             proto_tree_add_item(flags_tree, hf_btsnoop_flags_h1_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
154             proto_tree_add_item(flags_tree, hf_btsnoop_flags_h1_channel_type, tvb, offset, 4, ENC_BIG_ENDIAN);
155             proto_tree_add_item(flags_tree, hf_btsnoop_flags_h1_direction, tvb, offset, 4, ENC_BIG_ENDIAN);
156             break;
157         case 1002: /* H4 */
158             proto_tree_add_item(flags_tree, hf_btsnoop_flags_h4_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
159             proto_tree_add_item(flags_tree, hf_btsnoop_flags_h4_direction, tvb, offset, 4, ENC_BIG_ENDIAN);
160             break;
161         case 2001: /* Linux Monitor */
162             proto_tree_add_item(flags_tree, hf_btsnoop_flags_linux_monitor_adapter_id, tvb, offset , 2, ENC_BIG_ENDIAN);
163             proto_tree_add_item(flags_tree, hf_btsnoop_flags_linux_monitor_opcode, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
164             break;
165         }
166         offset += 4;
167
168         proto_tree_add_item(frame_tree, hf_btsnoop_cumulative_dropped_packets, tvb, offset, 4, ENC_BIG_ENDIAN);
169         offset += 4;
170
171         ts =  tvb_get_ntoh64(tvb, offset) - G_GINT64_CONSTANT(0x00dcddb30f2f8000);
172         timestamp.secs = (guint)(ts / 1000000);
173         timestamp.nsecs =(guint)((ts % 1000000) * 1000);
174
175         proto_tree_add_time(frame_tree, hf_btsnoop_timestamp_microseconds, tvb, offset, 8, &timestamp);
176         offset += 8;
177
178         payload_item = proto_tree_add_item(frame_tree, hf_btsnoop_payload, tvb, offset, length, ENC_NA);
179         payload_tree = proto_item_add_subtree(payload_item, ett_btsnoop_payload);
180
181         if (pref_dissect_next_layer) switch (datalink) {\
182             case 1001: /* H1 */
183                 pinfo->num = frame_number;
184                 pinfo->abs_ts = timestamp;
185
186                 pinfo->pseudo_header->bthci.sent = (flags & 0x01) ? FALSE : TRUE;
187                 if (flags & 0x02) {
188                     if(pinfo->pseudo_header->bthci.sent)
189                         pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_COMMAND;
190                     else
191                         pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_EVENT;
192                 } else {
193                     pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL;
194                 }
195
196                 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, length);
197                 call_dissector(hci_h1_handle, next_tvb, pinfo, payload_tree);
198                 break;
199             case 1002: /* H4 */
200                 pinfo->num = frame_number;
201                 pinfo->abs_ts = timestamp;
202                 pinfo->p2p_dir = (flags & 0x01) ? P2P_DIR_RECV : P2P_DIR_SENT;
203
204                 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, length);
205                 call_dissector(hci_h4_handle, next_tvb, pinfo, payload_tree);
206                 break;
207             case 2001: /* Linux Monitor */
208                 pinfo->num = frame_number;
209                 pinfo->abs_ts = timestamp;
210
211                 pinfo->pseudo_header->btmon.opcode = flags & 0xFFFF;
212                 pinfo->pseudo_header->btmon.adapter_id = flags >> 16;
213
214                 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, length);
215                 call_dissector(hci_mon_handle, next_tvb, pinfo, payload_tree);
216                 break;
217
218             case 1003: /* BCSP */
219             case 1004: /* H5 (3 Wire) */
220             case 2002: /* Simulator */
221                 /* Not implemented yet */
222                 proto_tree_add_expert(payload_tree, pinfo, &ei_not_implemented_yet, tvb, offset, length);
223                 break;
224             default:
225                 /* Unknown */
226                 proto_tree_add_expert(payload_tree, pinfo, &ei_unknown_data, tvb, offset, length);
227         }
228         offset += length;
229
230         proto_item_set_len(frame_item, 4 * 4 + 8 + length);
231         frame_number += 1;
232     }
233
234     return offset;
235 }
236
237 static gboolean
238 dissect_btsnoop_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
239 {
240     return dissect_btsnoop(tvb, pinfo, tree, NULL) > 0;
241 }
242
243 void
244 proto_register_btsnoop(void)
245 {
246     module_t         *module;
247     expert_module_t  *expert_module;
248
249     static hf_register_info hf[] = {
250         { &hf_btsnoop_header,
251             { "Header",                                    "btsnoop.header",
252             FT_NONE, BASE_NONE, NULL, 0x00,
253             NULL, HFILL }
254         },
255         { &hf_btsnoop_magic_bytes,
256             { "Magic Bytes",                               "btsnoop.header.magic_bytes",
257             FT_STRINGZ, BASE_NONE, NULL, 0x00,
258             NULL, HFILL }
259         },
260         { &hf_btsnoop_version,
261             { "Version",                                   "btsnoop.header.version",
262             FT_UINT32, BASE_DEC, NULL, 0x00,
263             NULL, HFILL }
264         },
265         { &hf_btsnoop_datalink,
266             { "Datalink",                                  "btsnoop.header.datalink",
267             FT_UINT32, BASE_DEC_HEX, VALS(datalink_vals), 0x00,
268             NULL, HFILL }
269         },
270         { &hf_btsnoop_frame,
271             { "Frame",                                     "btsnoop.frame",
272             FT_NONE, BASE_NONE, NULL, 0x00,
273             NULL, HFILL }
274         },
275         { &hf_btsnoop_origin_length,
276             { "Origin Length",                             "btsnoop.frame.origin_length",
277             FT_UINT32, BASE_DEC, NULL, 0x00,
278             NULL, HFILL }
279         },
280         { &hf_btsnoop_included_length,
281             { "Included Length",                           "btsnoop.frame.included_length",
282             FT_UINT32, BASE_DEC, NULL, 0x00,
283             NULL, HFILL }
284         },
285         { &hf_btsnoop_flags,
286             { "Flags",                                     "btsnoop.frame.flags",
287             FT_UINT32, BASE_HEX, NULL, 0x00,
288             NULL, HFILL }
289         },
290         { &hf_btsnoop_cumulative_dropped_packets,
291             { "Cumulative Dropped Packets",                "btsnoop.frame.cumulative_dropped_packets",
292             FT_UINT32, BASE_DEC, NULL, 0x00,
293             NULL, HFILL }
294         },
295         { &hf_btsnoop_timestamp_microseconds,
296             { "Timestamp Microseconds",                    "btsnoop.frame.timestamp_microseconds",
297             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
298             NULL, HFILL }
299         },
300         { &hf_btsnoop_payload,
301             { "Payload",                                   "btsnoop.frame.payload",
302             FT_NONE, BASE_NONE, NULL, 0x00,
303             NULL, HFILL }
304         },
305         { &hf_btsnoop_flags_h1_reserved,
306             { "Reserved",                                  "btsnoop.frame.flags.h1.reserved",
307             FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFC,
308             NULL, HFILL }
309         },
310         { &hf_btsnoop_flags_h1_channel_type,
311             { "Channel Type",                              "btsnoop.frame.flags.h1.channel_type",
312             FT_UINT32, BASE_DEC, VALS(flags_h1_channel_type_vals), 0x02,
313             NULL, HFILL }
314         },
315         { &hf_btsnoop_flags_h1_direction,
316             { "Direction",                                 "btsnoop.frame.flags.h1.direction",
317             FT_UINT32, BASE_DEC, VALS(flags_direction_vals), 0x01,
318             NULL, HFILL }
319         },
320         { &hf_btsnoop_flags_h4_reserved,
321             { "Reserved",                                  "btsnoop.frame.flags.h4.reserved",
322             FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFE,
323             NULL, HFILL }
324         },
325         { &hf_btsnoop_flags_h4_direction,
326             { "Direction",                                 "btsnoop.frame.flags.h4.direction",
327             FT_UINT32, BASE_DEC, VALS(flags_direction_vals), 0x01,
328             NULL, HFILL }
329         },
330         { &hf_btsnoop_flags_linux_monitor_opcode,
331             { "Opcode",                                    "btsnoop.frame.flags.linux_monitor.opcode",
332             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &hci_mon_opcode_vals_ext, 0x00,
333             NULL, HFILL }
334         },
335         { &hf_btsnoop_flags_linux_monitor_adapter_id,
336             { "Adapter ID",                                "btsnoop.frame.flags.linux_monitor.adapter_id",
337             FT_UINT16, BASE_DEC, NULL, 0x00,
338             NULL, HFILL }
339         }
340     };
341
342     static ei_register_info ei[] = {
343         { &ei_malformed_frame,       { "btsnoop.malformed_frame", PI_PROTOCOL, PI_WARN, "Malformed Frame", EXPFILL }},
344         { &ei_not_implemented_yet,   { "btsnoop.not_implemented_yet", PI_PROTOCOL, PI_UNDECODED, "Not implemented yet", EXPFILL }},
345         { &ei_unknown_data,          { "btsnoop.unknown_data", PI_PROTOCOL, PI_WARN, "Unknown data", EXPFILL }},
346     };
347
348     static gint *ett[] = {
349         &ett_btsnoop,
350         &ett_btsnoop_header,
351         &ett_btsnoop_frame,
352         &ett_btsnoop_payload,
353         &ett_btsnoop_flags,
354     };
355
356     proto_btsnoop = proto_register_protocol("Symbian OS BTSNOOP File Format", "BTSNOOP", "btsnoop");
357     proto_register_field_array(proto_btsnoop, hf, array_length(hf));
358     proto_register_subtree_array(ett, array_length(ett));
359
360     btsnoop_handle = register_dissector("btsnoop", dissect_btsnoop, proto_btsnoop);
361
362     module = prefs_register_protocol(proto_btsnoop, NULL);
363     prefs_register_static_text_preference(module, "version",
364             "BTSNOOP version: 1",
365             "Version of file-format supported by this dissector.");
366
367     prefs_register_bool_preference(module, "dissect_next_layer",
368             "Dissect next layer",
369             "Dissect next layer",
370             &pref_dissect_next_layer);
371
372     expert_module = expert_register_protocol(proto_btsnoop);
373     expert_register_field_array(expert_module, ei, array_length(ei));
374 }
375
376 void
377 proto_reg_handoff_btsnoop(void)
378 {
379     hci_h1_handle = find_dissector_add_dependency("hci_h1", proto_btsnoop);
380     hci_h4_handle = find_dissector_add_dependency("hci_h4", proto_btsnoop);
381     hci_mon_handle = find_dissector_add_dependency("hci_mon", proto_btsnoop);
382
383     heur_dissector_add("wtap_file", dissect_btsnoop_heur, "BTSNOOP file", "btsnoop_wtap", proto_btsnoop, HEURISTIC_ENABLE);
384 }
385
386 /*
387  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
388  *
389  * Local variables:
390  * c-basic-offset: 4
391  * tab-width: 8
392  * indent-tabs-mode: nil
393  * End:
394  *
395  * vi: set shiftwidth=4 tabstop=8 expandtab:
396  * :indentSize=4:tabSize=8:noTabs=true:
397  */