Coverage Report

Created: 2026-01-02 06:13

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