1 /* packet-hci_mon.c
2  * Routines for Bluetooth Linux Monitor dissection
3  *
4  * Copyright 2013, 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 <wiretap/wtap.h>
19 
20 #include "packet-bluetooth.h"
21 
22 static int proto_hci_mon = -1;
23 
24 static int hf_adapter_id = -1;
25 static int hf_opcode = -1;
26 static int hf_type = -1;
27 static int hf_bus = -1;
28 static int hf_bd_addr = -1;
29 static int hf_name = -1;
30 static int hf_manufacturer = -1;
31 static int hf_system_note = -1;
32 static int hf_priority = -1;
33 static int hf_ident_length = -1;
34 static int hf_ident = -1;
35 static int hf_cookie = -1;
36 static int hf_format = -1;
37 static int hf_version = -1;
38 static int hf_revision = -1;
39 static int hf_flags = -1;
40 static int hf_flags_trusted_socket = -1;
41 static int hf_command_length = -1;
42 static int hf_command = -1;
43 static int hf_event = -1;
44 
45 static gint ett_hci_mon = -1;
46 static gint ett_flags = -1;
47 
48 static expert_field ei_unknown_data = EI_INIT;
49 
50 static wmem_tree_t *adapter_to_disconnect_in_frame = NULL;
51 
52 static dissector_handle_t hci_mon_handle;
53 static dissector_handle_t bthci_cmd_handle;
54 static dissector_handle_t bthci_evt_handle;
55 static dissector_handle_t bthci_acl_handle;
56 static dissector_handle_t bthci_sco_handle;
57 
58 #define OPCODE_NEW_INDEX         0
59 #define OPCODE_DELETE_INDEX      1
60 #define OPCODE_HCI_COMMAND_PKT   2
61 #define OPCODE_HCI_EVENT_PKT     3
62 #define OPCODE_ACL_TX_PACKET     4
63 #define OPCODE_ACL_RX_PACKET     5
64 #define OPCODE_SCO_TX_PACKET     6
65 #define OPCODE_SCO_RX_PACKET     7
66 #define OPCODE_OPEN_INDEX        8
67 #define OPCODE_CLOSE_INDEX       9
68 #define OPCODE_INDEX_INFO        10
69 #define OPCODE_VENDOR_DIAGNOSTIC 11
70 #define OPCODE_SYSTEM_NOTE       12
71 #define OPCODE_USER_LOGGING      13
72 #define OPCODE_CONTROL_OPEN      14
73 #define OPCODE_CONTROL_CLOSE     15
74 #define OPCODE_CONTROL_COMMAND   16
75 #define OPCODE_CONTROL_EVENT     17
76 
77 static const value_string opcode_vals[] = {
78     { OPCODE_NEW_INDEX,         "New Index" },
79     { OPCODE_DELETE_INDEX,      "Delete Index" },
80     { OPCODE_HCI_COMMAND_PKT,   "HCI Command Packet" },
81     { OPCODE_HCI_EVENT_PKT,     "HCI Event Packet" },
82     { OPCODE_ACL_TX_PACKET,     "ACL Tx Packet" },
83     { OPCODE_ACL_RX_PACKET,     "ACL Rx Packet" },
84     { OPCODE_SCO_TX_PACKET,     "SCO Tx Packet" },
85     { OPCODE_SCO_RX_PACKET,     "SCO Rx Packet" },
86     { OPCODE_OPEN_INDEX,        "Open Index" },
87     { OPCODE_CLOSE_INDEX,       "Close Index" },
88     { OPCODE_INDEX_INFO,        "Index Info" },
89     { OPCODE_VENDOR_DIAGNOSTIC, "Vendor Diagnostic" },
90     { OPCODE_SYSTEM_NOTE,       "System Note" },
91     { OPCODE_USER_LOGGING,      "User Logging" },
92     { OPCODE_CONTROL_OPEN,      "Control Open" },
93     { OPCODE_CONTROL_CLOSE,     "Control Close" },
94     { OPCODE_CONTROL_COMMAND,   "Control Command" },
95     { OPCODE_CONTROL_EVENT,     "Control Event" },
96     { 0, NULL }
97 };
98 value_string_ext(hci_mon_opcode_vals_ext) = VALUE_STRING_EXT_INIT(opcode_vals);
99 
100 static const value_string type_vals[] = {
101     { 0x00,  "Virtual" },
102     { 0x01,  "USB" },
103     { 0x02,  "PC Card" },
104     { 0x03,  "UART" },
105     { 0x04,  "RS232" },
106     { 0x05,  "PCI" },
107     { 0x06,  "SDIO" },
108     { 0x00, NULL }
109 };
110 static value_string_ext(type_vals_ext) = VALUE_STRING_EXT_INIT(type_vals);
111 
112 static const value_string bus_vals[] = {
113     { 0x00,  "BR/EDR" },
114     { 0x01,  "AMP" },
115     { 0x00, NULL }
116 };
117 static value_string_ext(bus_vals_ext) = VALUE_STRING_EXT_INIT(bus_vals);
118 
119 #define CTRL_OPEN_RAW     0x0000
120 #define CTRL_OPEN_USER    0x0001
121 #define CTRL_OPEN_CONTROL 0x0002
122 
123 static const value_string format_vals[] = {
124     { CTRL_OPEN_RAW,     "Rqw" },
125     { CTRL_OPEN_USER,    "User" },
126     { CTRL_OPEN_CONTROL, "Control" },
127     { 0x00, NULL }
128 };
129 static value_string_ext(format_vals_ext) = VALUE_STRING_EXT_INIT(format_vals);
130 
131 #define EVENT_COMMAND_COMPLETE               0x0001
132 #define EVENT_COMMAND_STATUS                 0x0002
133 #define EVENT_CONTROLLER_ERROR               0x0003
134 #define EVENT_INDEX_ADDED                    0x0004
135 #define EVENT_INDEX_REMOVED                  0x0005
136 #define EVENT_NEW_SETTINGS                   0x0006
137 #define EVENT_CLASS_OF_DEVICE_CHANGED        0x0007
138 #define EVENT_LOCAL_NAME_CHANGED             0x0008
139 #define EVENT_NEW_LINK_KEY                   0x0009
140 #define EVENT_NEW_LONG_TERM_KEY              0x000a
141 #define EVENT_DEVICE_CONNECTED               0x000b
142 #define EVENT_DEVICE_DISCONNECTED            0x000c
143 #define EVENT_CONNECT_FAILED                 0x000d
144 #define EVENT_PIN_CODE_REQUEST               0x000e
145 #define EVENT_USER_CONFIRMATION_REQUEST      0x000f
146 #define EVENT_USER_PASSKEY_REQUEST           0x0010
147 #define EVENT_AUTHENTICAION_FAILED           0x0011
148 #define EVENT_DEVICE_FOUND                   0x0012
149 #define EVENT_DISCOVERING                    0x0013
150 #define EVENT_DEVICE_BLOCKED                 0x0014
151 #define EVENT_DEVICE_UNBLOCKED               0x0015
152 #define EVENT_DEVICE_UNPAIRED                0x0016
153 #define EVENT_PASSKEY_NOTIFY                 0x0017
154 #define EVENT_NEW_IRK                        0x0018
155 #define EVENT_NEW_CSRK                       0x0019
156 #define EVENT_DEVICE_ADDED                   0x001a
157 #define EVENT_DEVICE_REMOVED                 0x001b
158 #define EVENT_NEW_CONNECTION_PARAMETER       0x001c
159 #define EVENT_UNCONFIGURED_INDEX_ADDED       0x001d
160 #define EVENT_UNCONFIGURED_INDEX_REMOVED     0x001e
161 #define EVENT_NEW_CONFIGURATION_OPTIONS      0x001f
162 #define EVENT_EXTENDED_INDEX_ADDED           0x0020
163 #define EVENT_EXTENDED_INDEX_REMOVED         0x0021
164 #define EVENT_LOCAL_OUT_OF_BAND_DATA_UPDATED 0x0022
165 #define EVENT_ADVERTISING_ADDED              0x0023
166 #define EVENT_ADVERTISING_REMOVED            0x0024
167 #define EVENT_EXTENDED_INFO_CHANGED          0x0025
168 #define EVENT_PHY_CONFIGURATION_CHANGED      0x0026
169 
170 static const value_string event_vals[] = {
171     { EVENT_COMMAND_COMPLETE,               "Command complete" },
172     { EVENT_COMMAND_STATUS,                 "Command status" },
173     { EVENT_CONTROLLER_ERROR,               "Controller error" },
174     { EVENT_INDEX_ADDED,                    "Index added" },
175     { EVENT_INDEX_REMOVED,                  "Index removed" },
176     { EVENT_NEW_SETTINGS,                   "New settings" },
177     { EVENT_CLASS_OF_DEVICE_CHANGED,        "Class of device changed" },
178     { EVENT_LOCAL_NAME_CHANGED,             "Local name changed" },
179     { EVENT_NEW_LINK_KEY,                   "New link key" },
180     { EVENT_NEW_LONG_TERM_KEY,              "New long-term key" },
181     { EVENT_DEVICE_CONNECTED,               "Device connected" },
182     { EVENT_DEVICE_DISCONNECTED,            "Device disconnected" },
183     { EVENT_CONNECT_FAILED,                 "Connect failed" },
184     { EVENT_PIN_CODE_REQUEST,               "PIN code request" },
185     { EVENT_USER_CONFIRMATION_REQUEST,      "User confirmation request" },
186     { EVENT_USER_PASSKEY_REQUEST,           "User passkey request" },
187     { EVENT_AUTHENTICAION_FAILED,           "Authentication failed" },
188     { EVENT_DEVICE_FOUND,                   "Device found" },
189     { EVENT_DISCOVERING,                    "Discovering" },
190     { EVENT_DEVICE_BLOCKED,                 "Device blocked" },
191     { EVENT_DEVICE_UNBLOCKED,               "Device unblocked" },
192     { EVENT_DEVICE_UNPAIRED,                "Device unpaired" },
193     { EVENT_PASSKEY_NOTIFY,                 "Passkey notify" },
194     { EVENT_NEW_IRK,                        "New IRK" },
195     { EVENT_NEW_CSRK,                       "New CSRK" },
196     { EVENT_DEVICE_ADDED,                   "Device added" },
197     { EVENT_DEVICE_REMOVED,                 "Device removed" },
198     { EVENT_NEW_CONNECTION_PARAMETER,       "New connection parameter" },
199     { EVENT_UNCONFIGURED_INDEX_ADDED,       "Unconfigured index added" },
200     { EVENT_UNCONFIGURED_INDEX_REMOVED,     "Unconfigured index removed" },
201     { EVENT_NEW_CONFIGURATION_OPTIONS,      "New configuration options" },
202     { EVENT_EXTENDED_INDEX_ADDED,           "Extended index added" },
203     { EVENT_EXTENDED_INDEX_REMOVED,         "Extended index removed" },
204     { EVENT_LOCAL_OUT_OF_BAND_DATA_UPDATED, "Local out-of-band data updated" },
205     { EVENT_ADVERTISING_ADDED,              "Advertising added" },
206     { EVENT_ADVERTISING_REMOVED,            "Advertising removed" },
207     { EVENT_EXTENDED_INFO_CHANGED,          "Extended info changed" },
208     { EVENT_PHY_CONFIGURATION_CHANGED,      "PHY configuration changed" },
209     { 0x00, NULL }
210 };
211 static value_string_ext(event_vals_ext) = VALUE_STRING_EXT_INIT(event_vals);
212 
213 void proto_register_hci_mon(void);
214 void proto_reg_handoff_hci_mon(void);
215 
216 static gint
dissect_hci_mon(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)217 dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
218 {
219     proto_tree       *hci_mon_item;
220     proto_item       *hci_mon_tree;
221     proto_item       *sub_item;
222     gint              offset = 0;
223     guint16           opcode;
224     guint16           adapter_id;
225     bluetooth_data_t *bluetooth_data;
226     tvbuff_t         *next_tvb;
227     guint32          *adapter_disconnect_in_frame;
228     wmem_tree_t      *subtree;
229     wmem_tree_key_t  key[4];
230     guint32          k_interface_id;
231     guint32          k_adapter_id;
232     guint32          k_frame_number;
233     guint32          ident_length;
234     guint32          command_length;
235     static int * const flags_fields[] = {
236         &hf_flags_trusted_socket,
237         NULL
238     };
239 
240     bluetooth_data = (bluetooth_data_t *) data;
241 
242     /*
243      * XXX - the raw data sent to a Bluetooth monitor socket has a 6-byte
244      * header, the last 2 bytes of which are a big-endian length field,
245      * giving the length of the payload.
246      *
247      * Somehow, the length field disappears.
248      */
249     DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_BTMON);
250     adapter_id = bluetooth_data->previous_protocol_data.btmon->adapter_id;
251     opcode = bluetooth_data->previous_protocol_data.btmon->opcode;
252 
253     if (opcode == 0x00 || opcode == 0x01)
254         pinfo->p2p_dir = P2P_DIR_RECV;
255     else if (opcode % 2)
256         pinfo->p2p_dir = P2P_DIR_RECV;
257     else
258         pinfo->p2p_dir = P2P_DIR_SENT;
259 
260     hci_mon_item = proto_tree_add_item(tree, proto_hci_mon, tvb, offset, tvb_captured_length(tvb), ENC_NA);
261     hci_mon_tree = proto_item_add_subtree(hci_mon_item, ett_hci_mon);
262 
263     col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_MON");
264 
265     if (opcode == 0x00 || opcode == 0x01)
266         col_set_str(pinfo->cinfo, COL_INFO, "Info ");
267     else switch (pinfo->p2p_dir) {
268 
269     case P2P_DIR_SENT:
270         col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
271         break;
272 
273     case P2P_DIR_RECV:
274         col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
275         break;
276 
277     default:
278         col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
279         break;
280     }
281 
282     sub_item = proto_tree_add_uint(hci_mon_tree, hf_adapter_id,  tvb, offset, 0, adapter_id);
283     proto_item_set_generated(sub_item);
284 
285     sub_item = proto_tree_add_uint(hci_mon_tree, hf_opcode, tvb, offset, 0, opcode);
286     proto_item_set_generated(sub_item);
287 
288     col_append_fstr(pinfo->cinfo, COL_INFO, "Adapter Id: %u, Opcode: %s",
289             adapter_id, val_to_str_ext_const(opcode, &hci_mon_opcode_vals_ext, "Unknown (%u)"));
290 
291     bluetooth_data->adapter_id = adapter_id;
292 
293     k_interface_id = bluetooth_data->interface_id;
294     k_adapter_id   = adapter_id;
295     k_frame_number = pinfo->num;
296 
297     key[0].length = 1;
298     key[0].key    = &k_interface_id;
299     key[1].length = 1;
300     key[1].key    = &k_adapter_id;
301 
302     if (!pinfo->fd->visited && opcode == 0x01) { /* Delete Index */
303         guint32           *disconnect_in_frame;
304 
305         key[2].length = 1;
306         key[2].key    = &k_frame_number;
307         key[3].length = 0;
308         key[3].key    = NULL;
309 
310         disconnect_in_frame = wmem_new(wmem_file_scope(), guint32);
311 
312         if (disconnect_in_frame) {
313             *disconnect_in_frame = pinfo->num;
314 
315             wmem_tree_insert32_array(adapter_to_disconnect_in_frame, key, disconnect_in_frame);
316         }
317     }
318 
319     key[2].length = 0;
320     key[2].key    = NULL;
321 
322     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(adapter_to_disconnect_in_frame, key);
323     adapter_disconnect_in_frame = (subtree) ? (guint32 *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
324     if (adapter_disconnect_in_frame) {
325         bluetooth_data->adapter_disconnect_in_frame = adapter_disconnect_in_frame;
326     } else {
327         bluetooth_data->adapter_disconnect_in_frame = &max_disconnect_in_frame;
328     }
329 
330     pinfo->ptype = PT_BLUETOOTH;
331 
332     next_tvb = tvb_new_subset_remaining(tvb, offset);
333 
334     switch(opcode) {
335     case OPCODE_NEW_INDEX:
336         proto_tree_add_item(hci_mon_tree, hf_bus, tvb, offset, 1, ENC_BIG_ENDIAN);
337         offset += 1;
338 
339         proto_tree_add_item(hci_mon_tree, hf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
340         offset += 1;
341 
342         offset = dissect_bd_addr(hf_bd_addr, pinfo, hci_mon_tree, tvb, offset, TRUE, bluetooth_data->interface_id, bluetooth_data->adapter_id, NULL);
343 
344         proto_tree_add_item(hci_mon_tree, hf_name, tvb, offset, 8, ENC_NA | ENC_ASCII);
345         offset += 8;
346 
347         break;
348     case OPCODE_DELETE_INDEX:
349         /* No parameters */
350 
351         break;
352     case OPCODE_HCI_COMMAND_PKT:
353         call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data);
354         offset = tvb_reported_length(tvb);
355 
356         break;
357    case OPCODE_HCI_EVENT_PKT:
358         call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data);
359         offset = tvb_reported_length(tvb);
360 
361         break;
362    case OPCODE_ACL_TX_PACKET:
363    case OPCODE_ACL_RX_PACKET:
364         call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data);
365         offset = tvb_reported_length(tvb);
366 
367         break;
368    case OPCODE_SCO_TX_PACKET:
369    case OPCODE_SCO_RX_PACKET:
370         call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data);
371         offset = tvb_reported_length(tvb);
372 
373         break;
374 
375     case OPCODE_OPEN_INDEX:
376         /* No parameters */
377 
378         break;
379 
380     case OPCODE_CLOSE_INDEX:
381         /* No parameters */
382 
383         break;
384 
385     case OPCODE_INDEX_INFO:
386         offset = dissect_bd_addr(hf_bd_addr, pinfo, hci_mon_tree, tvb, offset, TRUE, bluetooth_data->interface_id, bluetooth_data->adapter_id, NULL);
387 
388         proto_tree_add_item(hci_mon_tree, hf_manufacturer, tvb, offset, 2, ENC_LITTLE_ENDIAN);
389         offset += 2;
390 
391         break;
392 
393     case OPCODE_VENDOR_DIAGNOSTIC:
394         /* XXX - what are the parameters, if any? */
395 
396         break;
397 
398     case OPCODE_SYSTEM_NOTE:
399         /*
400          * XXX - NUL-terminated, so that you always have a NUL at the
401          * end of the message?
402          *
403          * Or is it data from userland, which might or might not be
404          * NUL-terminated?
405          *
406          * We make it FT_STRINGZPAD, just in case.
407          */
408         proto_tree_add_item(hci_mon_tree, hf_system_note, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA | ENC_ASCII);
409         offset = tvb_reported_length(tvb);
410 
411         break;
412 
413     case OPCODE_USER_LOGGING:
414         proto_tree_add_item(hci_mon_tree, hf_priority, tvb, offset, 1, ENC_NA);
415         offset += 1;
416 
417         proto_tree_add_item_ret_uint(hci_mon_tree, hf_priority, tvb, offset, 1, ENC_NA, &ident_length);
418         offset += 1;
419 
420         /*
421          * XXX - this is both counted and NUL-terminated, so you have
422          * <length> bytes of string followed by a NUL.  We'll just
423          * treat it as counted.
424          */
425         proto_tree_add_item(hci_mon_tree, hf_priority, tvb, offset, ident_length, ENC_NA | ENC_ASCII);
426         offset += ident_length + 1; /* Skip the terminating NUL */
427 
428         break;
429 
430     case OPCODE_CONTROL_OPEN:
431         proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
432         offset += 4;
433 
434         proto_tree_add_item(hci_mon_tree, hf_format, tvb, offset, 2, ENC_LITTLE_ENDIAN);
435         offset += 2;
436 
437         proto_tree_add_item(hci_mon_tree, hf_version, tvb, offset, 1, ENC_NA);
438         proto_tree_add_item(hci_mon_tree, hf_revision, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
439         offset += 3;
440 
441         proto_tree_add_bitmask(hci_mon_tree, tvb, offset, hf_flags, ett_flags,
442                                flags_fields, ENC_LITTLE_ENDIAN);
443         offset += 4;
444 
445         proto_tree_add_item_ret_uint(hci_mon_tree, hf_command_length, tvb, offset, 1, ENC_NA, &command_length);
446         offset += 1;
447 
448         /*
449          * XXX - null-padded?  We assume so; the Linux kernel code, as of
450          * the 5.3 kernel, always copies TASK_COMM_LEN bytes and sets the
451          * command length to TASK_COMM_LEN.
452          */
453         proto_tree_add_item(hci_mon_tree, hf_command, tvb, offset, command_length, ENC_NA | ENC_ASCII);
454         offset += command_length;
455 
456         break;
457 
458     case OPCODE_CONTROL_CLOSE:
459         proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
460         offset += 4;
461 
462         break;
463 
464     case OPCODE_CONTROL_COMMAND:
465         proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
466         offset += 4;
467 
468         /* XXX - different field for this opcode? */
469         proto_tree_add_item(hci_mon_tree, hf_opcode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
470         offset += 2;
471 
472         break;
473 
474     case OPCODE_CONTROL_EVENT:
475         proto_tree_add_item(hci_mon_tree, hf_cookie, tvb, offset, 4, ENC_LITTLE_ENDIAN);
476         offset += 4;
477 
478         proto_tree_add_item(hci_mon_tree, hf_event, tvb, offset, 2, ENC_LITTLE_ENDIAN);
479         offset += 2;
480 
481         /* XXX - dissect the payload of the event */
482 
483         break;
484     }
485 
486     if (tvb_reported_length_remaining(tvb, offset) > 0) {
487         proto_tree_add_expert(hci_mon_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset));
488         offset = tvb_reported_length(tvb);
489     }
490 
491    /* NOTE: Oops... HCI_MON have special packet with length 0, but there is a pseudo-header with certain infos,
492             mark it as dissected */
493     if (opcode == 0x01)
494         return 1;
495 
496     return offset;
497 }
498 
499 void
proto_register_hci_mon(void)500 proto_register_hci_mon(void)
501 {
502     module_t *module;
503     expert_module_t  *expert_module;
504 
505     static hf_register_info hf[] = {
506         {  &hf_adapter_id,
507             { "Adapter ID",                      "hci_mon.adapter_id",
508             FT_UINT16, BASE_DEC, NULL, 0x00,
509             NULL, HFILL }
510         },
511         {  &hf_opcode,
512             { "Opcode",                          "hci_mon.opcode",
513             FT_UINT16, BASE_DEC | BASE_EXT_STRING, &hci_mon_opcode_vals_ext, 0x00,
514             NULL, HFILL }
515         },
516         {  &hf_type,
517             { "Type",                            "hci_mon.type",
518             FT_UINT8, BASE_HEX | BASE_EXT_STRING, &type_vals_ext, 0x00,
519             NULL, HFILL }
520         },
521         {  &hf_bus,
522             { "Bus",                             "hci_mon.bus",
523             FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bus_vals_ext, 0x00,
524             NULL, HFILL }
525         },
526         { &hf_bd_addr,
527           { "BD_ADDR",                           "hci_mon.bd_addr",
528             FT_ETHER, BASE_NONE, NULL, 0x0,
529             NULL, HFILL}
530         },
531         { &hf_name,
532           { "Adapter Name",                      "hci_mon.adapter_name",
533             FT_STRING, BASE_NONE, NULL, 0x0,
534             NULL, HFILL}
535         },
536         {  &hf_manufacturer,
537             { "Manufacturer",                    "hci_mon.manufacturer",
538             FT_UINT16, BASE_HEX, NULL, 0x0,
539             NULL, HFILL }
540         },
541         { &hf_system_note,
542           { "System Note",                       "hci_mon.system_note",
543             FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
544             NULL, HFILL}
545         },
546         { &hf_priority,
547           { "Priority",                          "hci_mon.priority",
548             FT_UINT8, BASE_DEC, NULL, 0x0,
549             NULL, HFILL}
550         },
551         { &hf_ident_length,
552           { "Ident Length",                      "hci_mon.ident_length",
553             FT_UINT8, BASE_DEC, NULL, 0x0,
554             NULL, HFILL}
555         },
556         { &hf_ident,
557           { "Ident",                             "hci_mon.ident",
558             FT_STRING, BASE_NONE, NULL, 0x0,
559             NULL, HFILL}
560         },
561         { &hf_cookie,
562           { "Cookie",                            "hci_mon.cookie",
563             FT_UINT32, BASE_HEX, NULL, 0x0,
564             NULL, HFILL}
565         },
566         { &hf_format,
567           { "Format",                            "hci_mon.format",
568             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &format_vals_ext, 0x00,
569             NULL, HFILL}
570         },
571         { &hf_version,
572           { "Version",                           "hci_mon.version",
573             FT_UINT8, BASE_DEC, NULL, 0x00,
574             NULL, HFILL}
575         },
576         { &hf_revision,
577           { "Revision",                          "hci_mon.version_minor",
578             FT_UINT16, BASE_DEC, NULL, 0x00,
579             NULL, HFILL}
580         },
581         { &hf_flags,
582           { "Flags",                             "hci_mon.flags",
583             FT_UINT32, BASE_HEX, NULL, 0x0,
584             NULL, HFILL}
585         },
586         { &hf_flags_trusted_socket,
587           { "Trusted Socket",                    "hci_mon.flags.trusted_socket",
588             FT_BOOLEAN, 32, NULL, 0x00000001,
589             NULL, HFILL}
590         },
591         { &hf_command_length,
592           { "Command Length",                    "hci_mon.command_length",
593             FT_UINT8, BASE_DEC, NULL, 0x0,
594             NULL, HFILL}
595         },
596         { &hf_command,
597           { "Command",                           "hci_mon.command",
598             FT_STRINGZPAD, BASE_NONE, NULL, 0x0,
599             NULL, HFILL}
600         },
601         { &hf_event,
602           { "Event",                            "hci_mon.event",
603             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &event_vals_ext, 0x0,
604             NULL, HFILL}
605         }
606     };
607 
608     static ei_register_info ei[] = {
609         { &ei_unknown_data, { "hci_mon.unknown_data", PI_PROTOCOL, PI_WARN, "Unknown data", EXPFILL }},
610     };
611 
612     static gint *ett[] = {
613         &ett_hci_mon,
614         &ett_flags
615     };
616 
617     proto_hci_mon = proto_register_protocol("Bluetooth Linux Monitor Transport", "HCI_MON", "hci_mon");
618     proto_register_field_array(proto_hci_mon, hf, array_length(hf));
619     proto_register_subtree_array(ett, array_length(ett));
620     hci_mon_handle = register_dissector("hci_mon", dissect_hci_mon, proto_hci_mon);
621 
622     expert_module = expert_register_protocol(proto_hci_mon);
623     expert_register_field_array(expert_module, ei, array_length(ei));
624 
625     adapter_to_disconnect_in_frame = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
626 
627     module = prefs_register_protocol_subtree("Bluetooth", proto_hci_mon, NULL);
628     prefs_register_static_text_preference(module, "bthci_mon.version",
629             "Bluetooth Linux Monitor Transport introduced in BlueZ 5.x",
630             "Version of protocol supported by this dissector.");
631 }
632 
633 void
proto_reg_handoff_hci_mon(void)634 proto_reg_handoff_hci_mon(void)
635 {
636     bthci_cmd_handle = find_dissector_add_dependency("bthci_cmd", proto_hci_mon);
637     bthci_evt_handle = find_dissector_add_dependency("bthci_evt", proto_hci_mon);
638     bthci_acl_handle = find_dissector_add_dependency("bthci_acl", proto_hci_mon);
639     bthci_sco_handle = find_dissector_add_dependency("bthci_sco", proto_hci_mon);
640 
641     dissector_add_uint("bluetooth.encap", WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR, hci_mon_handle);
642 }
643 
644 /*
645  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
646  *
647  * Local variables:
648  * c-basic-offset: 4
649  * tab-width: 8
650  * indent-tabs-mode: nil
651  * End:
652  *
653  * vi: set shiftwidth=4 tabstop=8 expandtab:
654  * :indentSize=4:tabSize=8:noTabs=true:
655  */
656