Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-bthci_sco.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-bthci_sco.c
2
 * Routines for the Bluetooth SCO dissection
3
 * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
4
 *
5
 * Refactored for wireshark checkin
6
 *   Ronnie Sahlberg 2006
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/addr_resolv.h>
19
20
#include "packet-bluetooth.h"
21
#include "packet-bthci_sco.h"
22
23
/* Initialize the protocol and registered fields */
24
static int proto_bthci_sco;
25
static int hf_bthci_sco_reserved;
26
static int hf_bthci_sco_packet_status;
27
static int hf_bthci_sco_chandle;
28
static int hf_bthci_sco_length;
29
static int hf_bthci_sco_data;
30
31
static int hf_bthci_sco_connect_in;
32
static int hf_bthci_sco_disconnect_in;
33
static int hf_bthci_sco_stream_number;
34
35
/* Initialize the subtree pointers */
36
static int ett_bthci_sco;
37
38
wmem_tree_t *bthci_sco_stream_numbers;
39
40
static dissector_handle_t bthci_sco_handle;
41
42
static const value_string packet_status_vals[] = {
43
    { 0x00,   "Correctly Received Data"},
44
    { 0x01,   "Possibly Invalid Data"},
45
    { 0x02,   "No Data Received"},
46
    { 0x03,   "Data Partially Lost"},
47
    {0x0, NULL}
48
};
49
50
void proto_register_bthci_sco(void);
51
void proto_reg_handoff_bthci_sco(void);
52
53
/* Code to actually dissect the packets */
54
static int
55
dissect_bthci_sco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
56
1
{
57
1
    proto_item               *ti;
58
1
    proto_tree               *bthci_sco_tree;
59
1
    int                       offset = 0;
60
1
    uint16_t                  flags;
61
1
    bluetooth_data_t         *bluetooth_data;
62
1
    wmem_tree_key_t           key[6];
63
1
    uint32_t                  k_connection_handle;
64
1
    uint32_t                  k_frame_number;
65
1
    uint32_t                  k_interface_id;
66
1
    uint32_t                  k_adapter_id;
67
1
    uint32_t                  k_bd_addr_oui;
68
1
    uint32_t                  k_bd_addr_id;
69
1
    uint16_t                  packet_status;
70
1
    remote_bdaddr_t          *remote_bdaddr;
71
1
    const char               *localhost_name;
72
1
    uint8_t                  *localhost_bdaddr;
73
1
    const char               *localhost_ether_addr;
74
1
    char                     *localhost_addr_name;
75
1
    int                       localhost_length;
76
1
    localhost_bdaddr_entry_t *localhost_bdaddr_entry;
77
1
    localhost_name_entry_t   *localhost_name_entry;
78
1
    chandle_session_t        *chandle_session;
79
1
    wmem_tree_t              *subtree;
80
1
    proto_item               *sub_item;
81
1
    bthci_sco_stream_number_t  *sco_stream_number;
82
83
1
    ti = proto_tree_add_item(tree, proto_bthci_sco, tvb, offset, tvb_captured_length(tvb), ENC_NA);
84
1
    bthci_sco_tree = proto_item_add_subtree(ti, ett_bthci_sco);
85
86
1
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_SCO");
87
88
1
    switch (pinfo->p2p_dir) {
89
0
        case P2P_DIR_SENT:
90
0
            col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
91
0
            break;
92
0
        case P2P_DIR_RECV:
93
0
            col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
94
0
            break;
95
1
        default:
96
1
            col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
97
1
            break;
98
1
    }
99
100
1
    proto_tree_add_item(bthci_sco_tree, hf_bthci_sco_reserved, tvb,      offset, 2, ENC_LITTLE_ENDIAN);
101
1
    proto_tree_add_item(bthci_sco_tree, hf_bthci_sco_packet_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
102
1
    proto_tree_add_item(bthci_sco_tree, hf_bthci_sco_chandle, tvb,       offset, 2, ENC_LITTLE_ENDIAN);
103
1
    flags   = tvb_get_letohs(tvb, offset);
104
1
    offset += 2;
105
106
1
    packet_status = (flags >> 12) & 0x03;
107
1
    col_append_fstr(pinfo->cinfo, COL_INFO, "SCO - %s", val_to_str(packet_status, packet_status_vals, "%u"));
108
109
1
    proto_tree_add_item(bthci_sco_tree, hf_bthci_sco_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
110
1
    offset++;
111
112
1
    bluetooth_data = (bluetooth_data_t *) data;
113
1
    DISSECTOR_ASSERT(bluetooth_data);
114
115
1
    k_interface_id      = bluetooth_data->interface_id;
116
1
    k_adapter_id        = bluetooth_data->adapter_id;
117
1
    k_connection_handle = flags & 0x0fff;
118
1
    k_frame_number      = pinfo->num;
119
120
1
    key[0].length = 1;
121
1
    key[0].key    = &k_interface_id;
122
1
    key[1].length = 1;
123
1
    key[1].key    = &k_adapter_id;
124
1
    key[2].length = 0;
125
1
    key[2].key    = NULL;
126
127
1
    subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bthci_sco_stream_numbers, key);
128
1
    sco_stream_number = (subtree) ? (bthci_sco_stream_number_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
129
130
1
    key[2].length = 1;
131
1
    key[2].key    = &k_connection_handle;
132
1
    key[3].length = 0;
133
1
    key[3].key    = NULL;
134
135
1
    subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->chandle_sessions, key);
136
1
    chandle_session = (subtree) ? (chandle_session_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
137
1
    if (!(chandle_session &&
138
1
            chandle_session->connect_in_frame < pinfo->num &&
139
1
            chandle_session->disconnect_in_frame > pinfo->num)){
140
1
        chandle_session = NULL;
141
1
    }
142
143
1
    key[3].length = 1;
144
1
    key[3].key    = &k_frame_number;
145
1
    key[4].length = 0;
146
1
    key[4].key    = NULL;
147
148
    /* remote bdaddr and name */
149
1
    remote_bdaddr = (remote_bdaddr_t *)wmem_tree_lookup32_array_le(bluetooth_data->chandle_to_bdaddr, key);
150
1
    if (remote_bdaddr && remote_bdaddr->interface_id == bluetooth_data->interface_id &&
151
1
            remote_bdaddr->adapter_id == bluetooth_data->adapter_id &&
152
1
            remote_bdaddr->chandle == (flags & 0x0fff)) {
153
0
        uint32_t        bd_addr_oui;
154
0
        uint32_t        bd_addr_id;
155
0
        device_name_t  *device_name;
156
0
        const char     *remote_name;
157
0
        const char     *remote_ether_addr;
158
0
        char           *remote_addr_name;
159
0
        int             remote_length;
160
161
0
        bd_addr_oui = remote_bdaddr->bd_addr[0] << 16 | remote_bdaddr->bd_addr[1] << 8 | remote_bdaddr->bd_addr[2];
162
0
        bd_addr_id  = remote_bdaddr->bd_addr[3] << 16 | remote_bdaddr->bd_addr[4] << 8 | remote_bdaddr->bd_addr[5];
163
164
0
        k_bd_addr_oui  = bd_addr_oui;
165
0
        k_bd_addr_id   = bd_addr_id;
166
0
        k_frame_number = pinfo->num;
167
168
0
        key[0].length = 1;
169
0
        key[0].key    = &k_interface_id;
170
0
        key[1].length = 1;
171
0
        key[1].key    = &k_adapter_id;
172
0
        key[2].length = 1;
173
0
        key[2].key    = &k_bd_addr_id;
174
0
        key[3].length = 1;
175
0
        key[3].key    = &k_bd_addr_oui;
176
0
        key[4].length = 1;
177
0
        key[4].key    = &k_frame_number;
178
0
        key[5].length = 0;
179
0
        key[5].key    = NULL;
180
181
0
        device_name = (device_name_t *)wmem_tree_lookup32_array_le(bluetooth_data->bdaddr_to_name, key);
182
0
        if (device_name && device_name->bd_addr_oui == bd_addr_oui && device_name->bd_addr_id == bd_addr_id)
183
0
            remote_name = device_name->name;
184
0
        else
185
0
            remote_name = "";
186
187
0
        remote_ether_addr = get_ether_name(remote_bdaddr->bd_addr);
188
0
        remote_length = (int)(strlen(remote_ether_addr) + 3 + strlen(remote_name) + 1);
189
0
        remote_addr_name = (char *)wmem_alloc(pinfo->pool, remote_length);
190
191
0
        snprintf(remote_addr_name, remote_length, "%s (%s)", remote_ether_addr, remote_name);
192
193
0
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
194
0
            set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(remote_name) + 1, remote_name);
195
0
            set_address(&pinfo->dl_src, AT_ETHER, 6, remote_bdaddr->bd_addr);
196
0
            set_address(&pinfo->src, AT_STRINGZ, (int)strlen(remote_addr_name) + 1, remote_addr_name);
197
0
        } else if (pinfo->p2p_dir == P2P_DIR_SENT) {
198
0
            set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(remote_name) + 1, remote_name);
199
0
            set_address(&pinfo->dl_dst, AT_ETHER, 6, remote_bdaddr->bd_addr);
200
0
            set_address(&pinfo->dst, AT_STRINGZ, (int)strlen(remote_addr_name) + 1, remote_addr_name);
201
0
        }
202
1
    } else {
203
1
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
204
0
            set_address(&pinfo->net_src, AT_STRINGZ, 1, "");
205
0
            set_address(&pinfo->dl_src, AT_STRINGZ, 1, "");
206
0
            set_address(&pinfo->src, AT_STRINGZ, 10, "remote ()");
207
1
        } else if (pinfo->p2p_dir == P2P_DIR_SENT) {
208
0
            set_address(&pinfo->net_dst, AT_STRINGZ, 1, "");
209
0
            set_address(&pinfo->dl_dst, AT_STRINGZ, 1, "");
210
0
            set_address(&pinfo->dst, AT_STRINGZ, 10, "remote ()");
211
0
        }
212
1
    }
213
214
1
    k_interface_id      = bluetooth_data->interface_id;
215
1
    k_adapter_id        = bluetooth_data->adapter_id;
216
1
    k_frame_number      = pinfo->num;
217
218
    /* localhost bdaddr and name */
219
1
    key[0].length = 1;
220
1
    key[0].key    = &k_interface_id;
221
1
    key[1].length = 1;
222
1
    key[1].key    = &k_adapter_id;
223
1
    key[2].length = 1;
224
1
    key[2].key    = &k_frame_number;
225
1
    key[3].length = 0;
226
1
    key[3].key    = NULL;
227
228
229
1
    localhost_bdaddr_entry = (localhost_bdaddr_entry_t *)wmem_tree_lookup32_array_le(bluetooth_data->localhost_bdaddr, key);
230
1
    localhost_bdaddr = (uint8_t *) wmem_alloc(pinfo->pool, 6);
231
1
    if (localhost_bdaddr_entry && localhost_bdaddr_entry->interface_id == bluetooth_data->interface_id &&
232
1
        localhost_bdaddr_entry->adapter_id == bluetooth_data->adapter_id) {
233
234
0
        localhost_ether_addr = get_ether_name(localhost_bdaddr_entry->bd_addr);
235
0
        memcpy(localhost_bdaddr, localhost_bdaddr_entry->bd_addr, 6);
236
1
    } else {
237
1
        localhost_ether_addr = "localhost";
238
        /* XXX - is this the right value to use? */
239
1
        memset(localhost_bdaddr, 0, 6);
240
1
    }
241
242
1
    localhost_name_entry = (localhost_name_entry_t *)wmem_tree_lookup32_array_le(bluetooth_data->localhost_name, key);
243
1
    if (localhost_name_entry && localhost_name_entry->interface_id == bluetooth_data->interface_id &&
244
1
            localhost_name_entry->adapter_id == bluetooth_data->adapter_id)
245
0
        localhost_name = localhost_name_entry->name;
246
1
    else
247
1
        localhost_name = "";
248
249
1
    localhost_length = (int)(strlen(localhost_ether_addr) + 3 + strlen(localhost_name) + 1);
250
1
    localhost_addr_name = (char *)wmem_alloc(pinfo->pool, localhost_length);
251
252
1
    snprintf(localhost_addr_name, localhost_length, "%s (%s)", localhost_ether_addr, localhost_name);
253
254
1
    if (pinfo->p2p_dir == P2P_DIR_RECV) {
255
0
        set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(localhost_name) + 1, localhost_name);
256
0
        set_address(&pinfo->dl_dst, AT_ETHER, 6, localhost_bdaddr);
257
0
        set_address(&pinfo->dst, AT_STRINGZ, (int)strlen(localhost_addr_name) + 1, localhost_addr_name);
258
1
    } else if (pinfo->p2p_dir == P2P_DIR_SENT) {
259
0
        set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(localhost_name) + 1, localhost_name);
260
0
        set_address(&pinfo->dl_src, AT_ETHER, 6, localhost_bdaddr);
261
0
        set_address(&pinfo->src, AT_STRINGZ, (int)strlen(localhost_addr_name) + 1, localhost_addr_name);
262
0
    }
263
264
1
    proto_tree_add_item(bthci_sco_tree, hf_bthci_sco_data, tvb, offset, tvb_reported_length(tvb), ENC_NA);
265
266
1
    if (chandle_session) {
267
0
        sub_item = proto_tree_add_uint(bthci_sco_tree, hf_bthci_sco_connect_in, tvb, 0, 0, chandle_session->connect_in_frame);
268
0
        proto_item_set_generated(sub_item);
269
270
0
        if (chandle_session->disconnect_in_frame < UINT32_MAX) {
271
0
            sub_item = proto_tree_add_uint(bthci_sco_tree, hf_bthci_sco_disconnect_in, tvb, 0, 0, chandle_session->disconnect_in_frame);
272
0
            proto_item_set_generated(sub_item);
273
0
        }
274
0
    }
275
1
    if (sco_stream_number) {
276
0
        sub_item = proto_tree_add_uint(bthci_sco_tree, hf_bthci_sco_stream_number, tvb, 0, 0, sco_stream_number->stream_number);
277
0
        proto_item_set_generated(sub_item);
278
0
    }
279
280
1
    return tvb_reported_length(tvb);
281
1
}
282
283
284
void
285
proto_register_bthci_sco(void)
286
14
{
287
14
    static hf_register_info hf[] = {
288
14
        { &hf_bthci_sco_reserved,
289
14
            { "Reserved",                    "bthci_sco.reserved",
290
14
            FT_UINT16, BASE_HEX, NULL, 0xC000,
291
14
            NULL, HFILL }
292
14
        },
293
14
        { &hf_bthci_sco_packet_status,
294
14
            { "Packet Status",               "bthci_sco.packet_status",
295
14
            FT_UINT16, BASE_HEX, VALS(packet_status_vals), 0x3000,
296
14
            NULL, HFILL }
297
14
        },
298
14
        { &hf_bthci_sco_chandle,
299
14
            { "Connection Handle",           "bthci_sco.chandle",
300
14
            FT_UINT16, BASE_HEX, NULL, 0x0FFF,
301
14
            NULL, HFILL }
302
14
        },
303
14
        { &hf_bthci_sco_connect_in,
304
14
            { "Connect in frame",            "bthci_sco.connect_in",
305
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
306
14
            NULL, HFILL }
307
14
        },
308
14
        { &hf_bthci_sco_disconnect_in,
309
14
            { "Disconnect in frame",         "bthci_sco.disconnect_in",
310
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
311
14
            NULL, HFILL }
312
14
        },
313
14
        { &hf_bthci_sco_stream_number,
314
14
            { "Stream Number",               "bthci_sco.stream_number",
315
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
316
14
            NULL, HFILL }
317
14
        },
318
14
        { &hf_bthci_sco_length,
319
14
            { "Data Total Length",           "bthci_sco.length",
320
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
321
14
            NULL, HFILL }
322
14
        },
323
14
        { &hf_bthci_sco_data,
324
14
            { "Data",                        "bthci_sco.data",
325
14
            FT_NONE, BASE_NONE, NULL, 0x0,
326
14
            NULL, HFILL }
327
14
        },
328
14
    };
329
330
    /* Setup protocol subtree array */
331
14
    static int *ett[] = {
332
14
      &ett_bthci_sco
333
14
    };
334
335
    /* Register the protocol name and description */
336
14
    proto_bthci_sco = proto_register_protocol("Bluetooth HCI SCO Packet", "HCI_SCO", "bthci_sco");
337
14
    bthci_sco_handle = register_dissector("bthci_sco", dissect_bthci_sco, proto_bthci_sco);
338
339
14
    bthci_sco_stream_numbers = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
340
341
    /* Required function calls to register the header fields and subtrees used */
342
14
    proto_register_field_array(proto_bthci_sco, hf, array_length(hf));
343
14
    proto_register_subtree_array(ett, array_length(ett));
344
14
}
345
346
347
void
348
proto_reg_handoff_bthci_sco(void)
349
14
{
350
14
    dissector_add_uint("hci_h4.type", HCI_H4_TYPE_SCO, bthci_sco_handle);
351
14
    dissector_add_uint("hci_h1.type", BTHCI_CHANNEL_SCO, bthci_sco_handle);
352
14
}
353
354
/*
355
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
356
 *
357
 * Local variables:
358
 * c-basic-offset: 4
359
 * tab-width: 8
360
 * indent-tabs-mode: nil
361
 * End:
362
 *
363
 * vi: set shiftwidth=4 tabstop=8 expandtab:
364
 * :indentSize=4:tabSize=8:noTabs=true:
365
 */