Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-btrfcomm.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-btrfcomm.c
2
 * Routines for Bluetooth RFCOMM protocol dissection
3
 * and RFCOMM based profile dissection:
4
 *    - Dial-Up Networking Profile (DUN)
5
 *    - Serial Port Profile (SPP)
6
 *    - Global Navigation Satellite System (GNSS)
7
 *
8
 * Copyright 2002, Wolfgang Hansmann <hansmann@cs.uni-bonn.de>
9
 *
10
 * Refactored for wireshark checkin
11
 *   Ronnie Sahlberg 2006
12
 *
13
 * Wireshark - Network traffic analyzer
14
 * By Gerald Combs <gerald@wireshark.org>
15
 * Copyright 1998 Gerald Combs
16
 *
17
 * SPDX-License-Identifier: GPL-2.0-or-later
18
 */
19
20
#include "config.h"
21
22
#include <epan/packet.h>
23
#include <epan/prefs.h>
24
#include <epan/expert.h>
25
#include <epan/uat.h>
26
#include <epan/decode_as.h>
27
#include <epan/proto_data.h>
28
29
#include "packet-bluetooth.h"
30
#include "packet-btsdp.h"
31
#include "packet-btl2cap.h"
32
#include "packet-btrfcomm.h"
33
34
static int hf_pf;
35
static int hf_ea;
36
static int hf_len;
37
static int hf_frame_type;
38
static int hf_cr;
39
static int hf_dlci;
40
static int hf_channel;
41
static int hf_direction;
42
static int hf_priority;
43
static int hf_error_recovery_mode;
44
static int hf_max_frame_size;
45
static int hf_max_retrans;
46
static int hf_fc_credits;
47
48
static int hf_mcc_pn_parameters;
49
static int hf_pn_i14;
50
static int hf_pn_c14;
51
52
static int hf_mcc;
53
static int hf_mcc_types;
54
static int hf_mcc_len;
55
static int hf_mcc_ea;
56
static int hf_mcc_cr;
57
static int hf_mcc_cmd;
58
59
static int hf_msc_parameters;
60
static int hf_msc_fc;
61
static int hf_msc_rtc;
62
static int hf_msc_rtr;
63
static int hf_msc_ic;
64
static int hf_msc_dv;
65
static int hf_msc_l;
66
static int hf_msc_break_bits;
67
68
static int hf_fcs;
69
70
static int hf_dun_at_cmd;
71
static int hf_spp_data;
72
static int hf_gnss_data;
73
74
static int hf_mcc_dlci;
75
static int hf_mcc_channel;
76
static int hf_mcc_direction;
77
static int hf_mcc_const_1;
78
79
static int hf_mcc_pn_dlci;
80
static int hf_mcc_pn_channel;
81
static int hf_mcc_pn_direction;
82
static int hf_mcc_pn_zeros_padding;
83
84
static int hf_acknowledgement_timer_t1;
85
static int hf_address;
86
static int hf_control;
87
88
/* Initialize the protocol and registered fields */
89
int proto_btrfcomm;
90
static int proto_btdun;
91
static int proto_btspp;
92
static int proto_btgnss;
93
94
/* Initialize the subtree pointers */
95
static int ett_btrfcomm;
96
static int ett_btrfcomm_ctrl;
97
static int ett_addr;
98
static int ett_control;
99
static int ett_mcc;
100
static int ett_ctrl_pn_ci;
101
static int ett_ctrl_pn_v24;
102
static int ett_dlci;
103
static int ett_mcc_dlci;
104
105
static int ett_btdun;
106
static int ett_btspp;
107
static int ett_btgnss;
108
109
static expert_field ei_btrfcomm_mcc_length_bad;
110
111
static dissector_handle_t btrfcomm_handle;
112
static dissector_handle_t btdun_handle;
113
static dissector_handle_t btspp_handle;
114
static dissector_handle_t btgnss_handle;
115
116
static dissector_table_t rfcomm_dlci_dissector_table;
117
118
static wmem_tree_t *service_directions;
119
120
typedef struct {
121
    uint32_t direction;
122
    uint32_t end_in;
123
} service_direction_t;
124
125
typedef struct {
126
    unsigned            channel;
127
    char*              payload_proto_name;
128
    dissector_handle_t  payload_proto;
129
} uat_rfcomm_channels_t;
130
131
static bool                   rfcomm_channels_enabled;
132
static uat_t                  *uat_rfcomm_channels;
133
static uat_rfcomm_channels_t  *rfcomm_channels;
134
static unsigned               num_rfcomm_channels;
135
136
UAT_DEC_CB_DEF(rfcomm_channels, channel, uat_rfcomm_channels_t)
137
UAT_DISSECTOR_DEF(rfcomm_channels, payload_proto, payload_proto, payload_proto_name, uat_rfcomm_channels_t)
138
139
static uat_field_t uat_rfcomm_channels_fields[] = {
140
    UAT_FLD_DEC(rfcomm_channels, channel, "RFCOMM Channel",
141
            "Range: 0-32"),
142
    UAT_FLD_DISSECTOR(rfcomm_channels, payload_proto, "Payload dissector",
143
            "Dissector name used to decode RFCOMM channel"),
144
    UAT_END_FIELDS
145
};
146
147
static dissector_handle_t ppp_handle;
148
149
static const value_string vs_ctl_pn_i[] = {
150
    {0x0, "use UIH Frames"},
151
#if 0    /* specified by 07.10, but not used by RFCOMM */
152
    {0x1, "use UI Frames"},
153
    {0x2, "use I Frames"},
154
#endif
155
    {0, NULL}
156
};
157
158
static const value_string vs_ctl_pn_cl[] = {
159
160
    {0x0, "no credit based flow control scheme"},
161
    {0xe, "support of credit based flow control scheme (resp)"},
162
    {0xf, "support of credit based flow control scheme (req)"},
163
#if 0    /* specified by 07.10. Redefined by RFCOMM */
164
    {0x0, "type 1 (unstructured octet stream)"},
165
    {0x1, "type 2 (unstructured octet stream with flow control)"},
166
    {0x2, "type 3 (uninterruptible framed data)"},
167
    {0x3, "type 4 (interruptible framed data)"},
168
#endif
169
    {0, NULL}
170
};
171
172
173
static const value_string vs_frame_type[] = {
174
    /* masked 0xef */
175
    {0x2f, "Set Asynchronous Balanced Mode (SABM)"},
176
    {0x63, "Unnumbered Acknowledgement (UA)"},
177
    {0x0f, "Disconnected Mode (DM)"},
178
    {0x43, "Disconnect (DISC)"},
179
    {0xef, "Unnumbered Information with Header check (UIH)"},
180
#if 0    /* specified by 07.10, but not used by RFCOMM */
181
       {0x03, "Unnumbered Information (UI)"},
182
#endif
183
        {0, NULL}
184
};
185
186
187
static const value_string vs_frame_type_short[] = {
188
    /* masked 0xef */
189
    {0x2f, "SABM"},
190
    {0x63, "UA"},
191
    {0x0f, "DM"},
192
    {0x43, "DISC"},
193
    {0xef, "UIH"},
194
#if 0    /* specified by 07.10, but not used by RFCOMM */
195
    {0x03, "UI"},
196
#endif
197
        {0, NULL}
198
};
199
200
0
#define FRAME_TYPE_SABM  0x2F
201
2
#define FRAME_TYPE_UIH   0xEF
202
203
static const value_string vs_ctl[] = {
204
       /* masked 0xfc */
205
    {0x20, "DLC Parameter Negotiation (PN)"},
206
    {0x08, "Test Command (Test)"},
207
    {0x28, "Flow Control On Command (FCon)"},
208
    {0x18, "Flow Control Off Command (FCoff)"},
209
    {0x38, "Modem Status Command (MSC)"},
210
    {0x04, "Non Supported Command Response (NSC)"},
211
    {0x24, "Remote Port Negotiation Command (RPN)"},
212
    {0x14, "Remote Line Status Command (RLS)"},
213
#if 0    /* Specified by 07.10, but not used by RFCOMM */
214
    {0x10, "Power Saving Control (PSC)"},
215
    {0x30, "Multiplexer close down (CLD)"},
216
    {0x34, "Service Negotiation Command (SNC)"},
217
#endif
218
#if 0     /* old */
219
    {0x80, "DLC parameter negotiation (PN)"},
220
    {0x20, "Test Command (Test)"},
221
    {0xa0, "Flow Control On Command (FCon)"},
222
    {0x60, "Flow Control Off Command (FCoff)"},
223
    {0xe0, "Modem Status Command (MSC)"},
224
    {0x10, "Non Supported Command Response (NSC)"},
225
    {0x90, "Remote Port Negotiation Command (RPN)"},
226
    {0x50, "Remote Line Status Command (RLS)"},
227
    {0x40, "Power Saving Control (PSC)"},
228
    {0xc0, "Multiplexer close down (CLD)"},
229
    {0xd0, "Service Negotiation Command (SNC)"},
230
#endif
231
    {0x0, NULL}
232
};
233
234
static const value_string vs_ea[] = {
235
    {1, "Last field octet"},
236
    {0, "More field octets following"},
237
    {0, NULL}
238
};
239
240
void proto_register_btrfcomm(void);
241
void proto_reg_handoff_btrfcomm(void);
242
void proto_register_btdun(void);
243
void proto_reg_handoff_btdun(void);
244
void proto_register_btspp(void);
245
void proto_reg_handoff_btspp(void);
246
void proto_register_btgnss(void);
247
void proto_reg_handoff_btgnss(void);
248
249
4
#define PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL  0
250
251
static void btrfcomm_directed_channel_prompt(packet_info *pinfo, char* result)
252
0
{
253
0
    uint8_t *value_data;
254
255
0
    value_data = (uint8_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL);
256
0
    if (value_data)
257
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "RFCOMM Channel %d (direction: %u) as", (unsigned) (*value_data) >> 1, (unsigned) (*value_data) & 1);
258
0
    else
259
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Unknown RFCOMM Channel");
260
0
}
261
262
static void *btrfcomm_directed_channel_value(packet_info *pinfo)
263
0
{
264
0
    uint8_t *value_data;
265
266
0
    value_data = (uint8_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL);
267
268
0
    if (value_data)
269
0
        return GUINT_TO_POINTER((unsigned long)*value_data);
270
271
0
    return NULL;
272
0
}
273
274
static dissector_handle_t
275
0
find_proto_by_channel(unsigned channel) {
276
0
    unsigned i_channel;
277
278
0
    for (i_channel = 0; i_channel < num_rfcomm_channels; ++i_channel) {
279
0
        if (rfcomm_channels[i_channel].channel == channel) {
280
0
            return rfcomm_channels[i_channel].payload_proto;
281
0
        }
282
0
    }
283
0
    return NULL;
284
0
}
285
286
static int
287
get_le_multi_byte_value(tvbuff_t *tvb, int offset, proto_tree *tree, uint32_t *val_ptr, int hf_index)
288
2
{
289
2
    uint8_t byte, bc     = 0;
290
2
    uint32_t val          = 0;
291
2
    int     start_offset = offset;
292
293
4
    do {
294
4
        byte = tvb_get_uint8(tvb, offset);
295
4
        offset += 1;
296
4
        val |= ((byte >> 1) & 0xff) << (bc++ * 7);
297
4
    } while (((byte & 0x1) == 0) && (bc <= 4));
298
299
2
    *val_ptr = val;
300
301
2
    if (hf_index > 0) {
302
1
        proto_tree_add_uint(tree, hf_index, tvb, start_offset, offset - start_offset, val);
303
1
    }
304
305
2
    return offset;
306
2
}
307
308
309
static int
310
dissect_ctrl_pn(proto_tree *t, tvbuff_t *tvb, int offset, uint8_t *mcc_channel)
311
0
{
312
0
    proto_tree   *st;
313
0
    proto_item   *ti;
314
0
    proto_tree   *dlci_tree;
315
0
    proto_item   *dlci_item;
316
0
    proto_item   *item;
317
0
    int           mcc_dlci;
318
0
    uint8_t       flags;
319
320
0
    proto_tree_add_item(t, hf_mcc_pn_zeros_padding, tvb, offset, 1, ENC_LITTLE_ENDIAN);
321
322
    /* mcc dlci */
323
0
    mcc_dlci = tvb_get_uint8(tvb, offset) & 0x3f;
324
0
    *mcc_channel = mcc_dlci >> 1;
325
326
0
    dlci_item = proto_tree_add_item(t, hf_mcc_pn_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
327
0
    proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, *mcc_channel);
328
329
0
    dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
330
0
    proto_tree_add_item(dlci_tree, hf_mcc_pn_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
331
0
    proto_tree_add_item(dlci_tree, hf_mcc_pn_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
332
0
    offset += 1;
333
334
0
    flags = tvb_get_uint8(tvb, offset);
335
336
0
    ti = proto_tree_add_none_format(t, hf_mcc_pn_parameters, tvb, offset, 1, "I1-I4: 0x%x, C1-C4: 0x%x", flags & 0xf, (flags >> 4) & 0xf);
337
0
    st = proto_item_add_subtree(ti, ett_ctrl_pn_ci);
338
339
0
    proto_tree_add_item(st, hf_pn_c14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
340
0
    proto_tree_add_item(st, hf_pn_i14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
341
0
    offset += 1;
342
343
    /* priority */
344
0
    proto_tree_add_item(t, hf_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
345
0
    offset += 1;
346
347
    /* Ack timer */
348
0
    item = proto_tree_add_item(t, hf_acknowledgement_timer_t1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
349
0
    proto_item_append_text(item, "(%d ms)", (uint32_t)tvb_get_uint8(tvb, offset) * 100);
350
0
    offset += 1;
351
352
    /* max frame size */
353
0
    proto_tree_add_item(t, hf_max_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
354
0
    offset += 2;
355
356
    /* max retrans */
357
0
    proto_tree_add_item(t, hf_max_retrans, tvb, offset, 1, ENC_LITTLE_ENDIAN);
358
0
    offset += 1;
359
360
    /* error recovery mode */
361
0
    proto_tree_add_item(t, hf_error_recovery_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
362
0
    offset += 1;
363
364
0
    return offset;
365
0
}
366
367
static int
368
dissect_ctrl_msc(proto_tree *t, tvbuff_t *tvb, int offset, int length, uint8_t *mcc_channel)
369
0
{
370
371
0
    proto_tree *st;
372
0
    proto_item *it;
373
0
    proto_tree *dlci_tree;
374
0
    proto_item *dlci_item;
375
0
    uint8_t     mcc_dlci;
376
0
    uint8_t     status;
377
0
    int         start_offset;
378
379
0
    mcc_dlci = tvb_get_uint8(tvb, offset) >> 2;
380
0
    *mcc_channel = mcc_dlci >> 1;
381
382
0
    dlci_item = proto_tree_add_item(t, hf_mcc_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
383
0
    proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, *mcc_channel);
384
385
0
    dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
386
0
    proto_tree_add_item(dlci_tree, hf_mcc_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387
0
    proto_tree_add_item(dlci_tree, hf_mcc_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
388
389
0
    proto_tree_add_item(t, hf_mcc_const_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
390
0
    proto_tree_add_item(t, hf_mcc_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
391
392
0
    offset += 1;
393
394
0
    start_offset = offset;
395
0
    status       = tvb_get_uint8(tvb, offset);
396
0
    it = proto_tree_add_none_format(t, hf_msc_parameters, tvb, offset, 1, "V.24 Signals: FC = %d, RTC = %d, RTR = %d, IC = %d, DV = %d", (status >> 1) & 1,
397
0
                 (status >> 2) & 1, (status >> 3) & 1,
398
0
                 (status >> 6) & 1, (status >> 7) & 1);
399
0
    st = proto_item_add_subtree(it, ett_ctrl_pn_v24);
400
401
0
    proto_tree_add_item(st, hf_msc_fc,  tvb, offset, 1, ENC_LITTLE_ENDIAN);
402
0
    proto_tree_add_item(st, hf_msc_rtc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403
0
    proto_tree_add_item(st, hf_msc_rtr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
404
0
    proto_tree_add_item(st, hf_msc_ic,  tvb, offset, 1, ENC_LITTLE_ENDIAN);
405
0
    proto_tree_add_item(st, hf_msc_dv,  tvb, offset, 1, ENC_LITTLE_ENDIAN);
406
0
    offset += 1;
407
408
0
    if (length == 3) {
409
0
        proto_tree_add_item(t, hf_msc_break_bits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
410
0
        proto_tree_add_item(t, hf_msc_l, tvb, offset, 1, ENC_LITTLE_ENDIAN);
411
0
        offset += 1;
412
0
    }
413
414
0
    proto_item_set_len(it, offset - start_offset);
415
416
0
    return offset;
417
0
}
418
419
static int
420
dissect_btrfcomm_address(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, uint8_t *ea_flagp, uint8_t *cr_flagp, uint8_t *dlcip)
421
2
{
422
2
    proto_item *ti;
423
2
    proto_tree *addr_tree;
424
2
    proto_tree *dlci_tree = NULL;
425
2
    proto_item *dlci_item = NULL;
426
2
    uint8_t     dlci, cr_flag, ea_flag, flags, channel;
427
428
2
    flags = tvb_get_uint8(tvb, offset);
429
430
2
    ea_flag = flags & 0x01;
431
2
    if (ea_flagp) {
432
2
        *ea_flagp = ea_flag;
433
2
    }
434
435
2
    cr_flag = (flags & 0x02) ? 1 : 0;
436
2
    if (cr_flagp) {
437
2
        *cr_flagp = cr_flag;
438
2
    }
439
440
2
    dlci = flags >> 2;
441
2
    if (dlcip) {
442
2
        *dlcip = dlci;
443
2
    }
444
445
2
    ti = proto_tree_add_none_format(tree, hf_address, tvb, offset, 1, "Address: E/A flag: %d, C/R flag: %d, Direction: %d, Channel: %u", ea_flag, cr_flag, dlci & 0x01, dlci >> 1);
446
2
    addr_tree = proto_item_add_subtree(ti, ett_addr);
447
448
2
    dlci_item = proto_tree_add_item(addr_tree, hf_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
449
2
    channel = dlci >> 1;
450
2
    proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", dlci & 0x01, channel);
451
452
2
    if (p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL) == NULL) {
453
2
        uint8_t *value_data;
454
455
2
        value_data = wmem_new(wmem_file_scope(), uint8_t);
456
2
        *value_data = dlci;
457
458
2
        p_add_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL, value_data);
459
2
    }
460
461
2
    dlci_tree = proto_item_add_subtree(dlci_item, ett_dlci);
462
2
    proto_tree_add_item(dlci_tree, hf_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
463
2
    proto_tree_add_item(dlci_tree, hf_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
464
465
2
    proto_tree_add_item(addr_tree, hf_cr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
466
2
    proto_tree_add_item(addr_tree, hf_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
467
2
    offset += 1;
468
469
2
    return offset;
470
2
}
471
472
static int
473
dissect_btrfcomm_control(tvbuff_t *tvb, int offset, proto_tree *tree, uint8_t *pf_flagp, uint8_t *frame_typep)
474
2
{
475
2
    proto_item *ti;
476
2
    proto_tree *hctl_tree;
477
2
    uint8_t     frame_type, pf_flag, flags;
478
479
2
    flags = tvb_get_uint8(tvb, offset);
480
481
2
    pf_flag = (flags & 0x10) ? 1 : 0;
482
2
    if (pf_flagp) {
483
2
        *pf_flagp = pf_flag;
484
2
    }
485
486
2
    frame_type = flags & 0xef;
487
2
    if (frame_typep) {
488
2
        *frame_typep = frame_type;
489
2
    }
490
491
2
    ti = proto_tree_add_none_format(tree, hf_control, tvb, offset, 1, "Control: Frame type: %s (0x%x), P/F flag: %d",
492
2
                             val_to_str_const(frame_type, vs_frame_type, "Unknown"), frame_type, pf_flag);
493
2
    hctl_tree = proto_item_add_subtree(ti, ett_control);
494
495
2
    proto_tree_add_item(hctl_tree, hf_pf,         tvb, offset, 1, ENC_LITTLE_ENDIAN);
496
2
    proto_tree_add_item(hctl_tree, hf_frame_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
497
498
2
    offset += 1;
499
2
    return offset;
500
2
}
501
502
503
504
static int
505
dissect_btrfcomm_payload_length(tvbuff_t *tvb, int offset, proto_tree *tree, uint16_t *frame_lenp)
506
2
{
507
2
    uint16_t frame_len;
508
2
    int     start_offset = offset;
509
510
2
    frame_len = tvb_get_uint8(tvb, offset);
511
2
    offset += 1;
512
513
2
    if (frame_len & 0x01) {
514
2
        frame_len >>= 1; /* 0 - 127 */
515
2
    } else {
516
0
        frame_len >>= 1; /* 128 - ... */
517
0
        frame_len |= (tvb_get_uint8(tvb, offset)) << 7;
518
0
        offset += 1;
519
0
    }
520
521
2
    proto_tree_add_uint(tree, hf_len, tvb, start_offset, offset - start_offset, frame_len);
522
523
2
    if (frame_lenp) {
524
2
        *frame_lenp = frame_len;
525
2
    }
526
527
2
    return offset;
528
2
}
529
530
static int
531
dissect_btrfcomm_MccType(tvbuff_t *tvb, int offset, proto_tree *tree, uint8_t *mcc_cr_flagp, uint8_t *mcc_ea_flagp, uint32_t *mcc_typep)
532
1
{
533
1
    int         start_offset = offset;
534
1
    proto_item *ti;
535
1
    proto_tree *mcc_tree;
536
1
    uint8_t     flags, mcc_cr_flag, mcc_ea_flag;
537
1
    uint32_t    mcc_type;
538
539
1
    flags = tvb_get_uint8(tvb, offset);
540
541
1
    mcc_cr_flag = (flags & 0x2) ? 1 : 0;
542
1
    if (mcc_cr_flagp) {
543
1
        *mcc_cr_flagp = mcc_cr_flag;
544
1
    }
545
546
1
    mcc_ea_flag = flags & 0x1;
547
1
    if (mcc_ea_flagp) {
548
1
        *mcc_ea_flagp = mcc_ea_flag;
549
1
    }
550
551
1
    offset = get_le_multi_byte_value(tvb, offset, tree, &mcc_type, -1);
552
1
    mcc_type = (mcc_type >> 1) & 0x3f; /* shift c/r flag off */
553
1
    if (mcc_typep) {
554
1
        *mcc_typep = mcc_type;
555
1
    }
556
557
1
    ti = proto_tree_add_none_format(tree, hf_mcc_types, tvb, start_offset, offset - start_offset,
558
1
                             "Type: %s (0x%x), C/R flag = %d, E/A flag = %d",
559
1
                             val_to_str_const(mcc_type, vs_ctl, "Unknown"),
560
1
                             mcc_type, mcc_cr_flag, mcc_ea_flag);
561
1
    mcc_tree = proto_item_add_subtree(ti, ett_mcc);
562
563
1
    proto_tree_add_item(mcc_tree, hf_mcc_cmd, tvb, start_offset, offset - start_offset, ENC_LITTLE_ENDIAN);
564
1
    proto_tree_add_item(mcc_tree, hf_mcc_cr, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
565
1
    proto_tree_add_item(mcc_tree, hf_mcc_ea, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
566
567
1
    return offset;
568
1
}
569
570
static int
571
dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
572
2
{
573
2
    proto_item          *ti;
574
2
    proto_tree          *rfcomm_tree;
575
2
    int                  offset     = 0;
576
2
    int                  fcs_offset;
577
2
    uint8_t              dlci, cr_flag, ea_flag;
578
2
    uint8_t              frame_type, pf_flag;
579
2
    uint16_t             frame_len;
580
2
    btl2cap_data_t      *l2cap_data;
581
2
    service_info_t      *service_info = NULL;
582
583
    /* Reject the packet if data is NULL */
584
2
    if (data == NULL)
585
0
        return 0;
586
2
    l2cap_data = (btl2cap_data_t *) data;
587
588
2
    ti = proto_tree_add_item(tree, proto_btrfcomm, tvb, offset, tvb_captured_length(tvb), ENC_NA);
589
2
    rfcomm_tree = proto_item_add_subtree(ti, ett_btrfcomm);
590
591
2
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFCOMM");
592
593
2
    switch (pinfo->p2p_dir) {
594
0
        case P2P_DIR_SENT:
595
0
            col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
596
0
            break;
597
0
        case P2P_DIR_RECV:
598
0
            col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
599
0
            break;
600
2
        default:
601
2
            col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
602
2
            break;
603
2
    }
604
605
    /* flags and dlci */
606
2
    offset = dissect_btrfcomm_address(tvb, pinfo, offset, rfcomm_tree, &ea_flag, &cr_flag, &dlci);
607
    /* pf and frame type */
608
2
    offset = dissect_btrfcomm_control(tvb, offset, rfcomm_tree, &pf_flag, &frame_type);
609
    /* payload length */
610
2
    offset = dissect_btrfcomm_payload_length(tvb, offset, rfcomm_tree, &frame_len);
611
612
2
    if (dlci && (frame_len || (frame_type == FRAME_TYPE_UIH) || (frame_type == FRAME_TYPE_SABM))) {
613
0
        wmem_tree_key_t       key[10];
614
0
        uint32_t              k_interface_id;
615
0
        uint32_t              k_adapter_id;
616
0
        uint32_t              k_psm;
617
0
        uint32_t              k_direction;
618
0
        uint32_t              k_bd_addr_oui;
619
0
        uint32_t              k_bd_addr_id;
620
0
        uint32_t              k_service_type;
621
0
        uint32_t              k_frame_number;
622
0
        uint32_t              k_chandle;
623
0
        uint32_t              k_channel;
624
0
        uint32_t              k_dlci;
625
0
        service_direction_t  *service_direction;
626
0
        wmem_tree_t          *subtree;
627
628
0
        k_interface_id    = l2cap_data->interface_id;
629
0
        k_adapter_id      = l2cap_data->adapter_id;
630
0
        k_chandle         = l2cap_data->chandle;
631
0
        k_psm             = l2cap_data->psm;
632
0
        k_channel         = dlci >> 1;
633
0
        k_frame_number    = pinfo->num;
634
0
        k_dlci            = dlci;
635
636
0
        key[0].length = 1;
637
0
        key[0].key = &k_interface_id;
638
0
        key[1].length = 1;
639
0
        key[1].key = &k_adapter_id;
640
0
        key[2].length = 1;
641
0
        key[2].key = &k_chandle;
642
0
        key[3].length = 1;
643
0
        key[3].key = &k_psm;
644
0
        key[4].length = 1;
645
0
        key[4].key = &k_dlci;
646
647
0
        if (!pinfo->fd->visited && frame_type == FRAME_TYPE_SABM) {
648
0
            key[5].length = 0;
649
0
            key[5].key = NULL;
650
651
0
            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
652
0
            service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
653
0
            if (service_direction && service_direction->end_in == bluetooth_max_disconnect_in_frame) {
654
0
                service_direction->end_in = k_frame_number;
655
0
            }
656
657
0
            key[5].length = 1;
658
0
            key[5].key = &k_frame_number;
659
0
            key[6].length = 0;
660
0
            key[6].key = NULL;
661
662
0
            service_direction = wmem_new(wmem_file_scope(), service_direction_t);
663
0
            service_direction->direction = (pinfo->p2p_dir == P2P_DIR_RECV) ? P2P_DIR_SENT : P2P_DIR_RECV;
664
0
            service_direction->end_in = bluetooth_max_disconnect_in_frame;
665
666
0
            wmem_tree_insert32_array(service_directions, key, service_direction);
667
0
        }
668
0
        key[4].key = &k_channel;
669
0
        key[5].length = 0;
670
0
        key[5].key = NULL;
671
672
0
        subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
673
0
        service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
674
0
        if (service_direction && service_direction->end_in > k_frame_number) {
675
0
            k_direction = service_direction->direction;
676
0
        } else {
677
0
            if (dlci & 0x01)
678
0
                k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_RECV : P2P_DIR_SENT;
679
0
            else
680
0
                k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
681
0
        }
682
683
0
        k_psm = SDP_PSM_DEFAULT;
684
0
        if (k_direction == P2P_DIR_RECV) {
685
0
            k_bd_addr_oui     = l2cap_data->remote_bd_addr_oui;
686
0
            k_bd_addr_id      = l2cap_data->remote_bd_addr_id;
687
0
        } else {
688
0
            k_bd_addr_oui     = 0;
689
0
            k_bd_addr_id      = 0;
690
0
        }
691
0
        k_service_type    = BTSDP_RFCOMM_PROTOCOL_UUID;
692
693
0
        key[2].length = 1;
694
0
        key[2].key = &k_psm;
695
0
        key[3].length = 1;
696
0
        key[3].key = &k_direction;
697
0
        key[4].length = 1;
698
0
        key[4].key = &k_bd_addr_oui;
699
0
        key[5].length = 1;
700
0
        key[5].key = &k_bd_addr_id;
701
0
        key[6].length = 1;
702
0
        key[6].key = &k_service_type;
703
0
        key[7].length = 1;
704
0
        key[7].key = &k_channel;
705
0
        key[8].length = 1;
706
0
        key[8].key = &k_frame_number;
707
0
        key[9].length = 0;
708
0
        key[9].key = NULL;
709
710
0
        service_info = btsdp_get_service_info(key);
711
712
0
        if (service_info && service_info->interface_id == l2cap_data->interface_id &&
713
0
                service_info->adapter_id == l2cap_data->adapter_id &&
714
0
                service_info->sdp_psm == SDP_PSM_DEFAULT &&
715
0
                ((service_info->direction == P2P_DIR_RECV &&
716
0
                service_info->bd_addr_oui == l2cap_data->remote_bd_addr_oui &&
717
0
                service_info->bd_addr_id == l2cap_data->remote_bd_addr_id) ||
718
0
                (service_info->direction != P2P_DIR_RECV &&
719
0
                service_info->bd_addr_oui == 0 &&
720
0
                service_info->bd_addr_id == 0)) &&
721
0
                service_info->type == BTSDP_RFCOMM_PROTOCOL_UUID &&
722
0
                service_info->channel == (dlci >> 1)) {
723
724
0
        } else {
725
0
            service_info = wmem_new0(pinfo->pool, service_info_t);
726
0
        }
727
0
    }
728
729
2
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s Channel=%u ",
730
2
                    val_to_str_const(frame_type, vs_frame_type_short, "Unknown"), dlci >> 1);
731
2
    if (dlci && (frame_type == FRAME_TYPE_SABM) && service_info) {
732
0
        if (service_info->uuid.size==16)
733
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "(UUID128: %s) ", print_bluetooth_uuid(pinfo->pool, &service_info->uuid));
734
0
        else
735
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
736
0
                    val_to_str_ext_const(service_info->uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown"));
737
0
    }
738
739
    /* UID frame */
740
2
    if ((frame_type == FRAME_TYPE_UIH) && dlci && pf_flag) {
741
0
        col_append_str(pinfo->cinfo, COL_INFO, "UID ");
742
743
        /* add credit based flow control byte */
744
0
        proto_tree_add_item(rfcomm_tree, hf_fc_credits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
745
0
        offset += 1;
746
747
0
    }
748
749
2
    fcs_offset = offset + frame_len;
750
751
    /* multiplexer control command */
752
2
    if (!dlci && frame_len) {
753
1
        proto_item *mcc_ti;
754
1
        proto_tree *ctrl_tree;
755
1
        proto_tree *dlci_tree;
756
1
        proto_item *dlci_item;
757
1
        uint32_t    mcc_type, length;
758
1
        uint8_t     mcc_cr_flag, mcc_ea_flag;
759
1
        uint8_t     mcc_channel;
760
1
        uint8_t     mcc_dlci;
761
1
        int         start_offset = offset;
762
763
1
        mcc_ti = proto_tree_add_item(rfcomm_tree, hf_mcc, tvb, offset, 1, ENC_NA);
764
1
        ctrl_tree = proto_item_add_subtree(mcc_ti, ett_btrfcomm_ctrl);
765
766
        /* mcc type */
767
1
        offset = dissect_btrfcomm_MccType(tvb, offset, ctrl_tree, &mcc_cr_flag, &mcc_ea_flag, &mcc_type);
768
769
        /* len */
770
1
        offset = get_le_multi_byte_value(tvb, offset, ctrl_tree, &length, hf_mcc_len);
771
772
1
        if (length > (uint32_t) tvb_reported_length_remaining(tvb, offset)) {
773
0
            expert_add_info_format(pinfo, ctrl_tree, &ei_btrfcomm_mcc_length_bad, "Huge MCC length: %u", length);
774
0
            return offset;
775
0
        }
776
777
1
        switch(mcc_type) {
778
0
        case 0x20: /* DLC Parameter Negotiation */
779
0
            dissect_ctrl_pn(ctrl_tree, tvb, offset, &mcc_channel);
780
0
            break;
781
0
        case 0x24: /* Remote Port Negotiation */
782
0
            mcc_dlci = tvb_get_uint8(tvb, offset) >> 2;
783
0
            mcc_channel = mcc_dlci >> 1;
784
785
0
            dlci_item = proto_tree_add_item(ctrl_tree, hf_mcc_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
786
0
            proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, mcc_channel);
787
788
0
            dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
789
0
            proto_tree_add_item(dlci_tree, hf_mcc_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
790
0
            proto_tree_add_item(dlci_tree, hf_mcc_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
791
792
0
            proto_tree_add_item(ctrl_tree, hf_mcc_const_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
793
0
            proto_tree_add_item(ctrl_tree, hf_mcc_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
794
795
0
            break;
796
0
        case 0x38: /* Modem Status Command */
797
0
            dissect_ctrl_msc(ctrl_tree, tvb, offset, length, &mcc_channel);
798
0
            break;
799
1
        default:
800
1
            mcc_channel = -1;
801
1
        }
802
803
1
        if (mcc_channel > 0) {
804
1
            col_append_fstr(pinfo->cinfo, COL_INFO, "-> %d ", mcc_channel);
805
1
        }
806
807
1
        col_append_str(pinfo->cinfo, COL_INFO, "MPX_CTRL ");
808
809
1
        if(mcc_type){
810
1
            col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(mcc_type, vs_ctl, "Unknown"));
811
1
        }
812
813
1
        offset += length;
814
815
1
        proto_item_set_len(mcc_ti, offset - start_offset);
816
1
    }
817
818
    /* try to find a higher layer dissector that has registered to handle data
819
     * for this kind of service, if none is found dissect it as raw "data"
820
     */
821
2
    if (dlci && frame_len) {
822
0
        dissector_handle_t  decode_by_dissector;
823
0
        tvbuff_t           *next_tvb;
824
0
        btrfcomm_data_t    *rfcomm_data;
825
826
0
        next_tvb = tvb_new_subset_length(tvb, offset, frame_len);
827
828
0
        rfcomm_data = (btrfcomm_data_t *) wmem_new(pinfo->pool, btrfcomm_data_t);
829
0
        rfcomm_data->interface_id       = l2cap_data->interface_id;
830
0
        rfcomm_data->adapter_id         = l2cap_data->adapter_id;
831
0
        rfcomm_data->chandle            = l2cap_data->chandle;
832
0
        rfcomm_data->cid                = l2cap_data->cid;
833
0
        rfcomm_data->is_local_psm       = l2cap_data->is_local_psm;
834
0
        rfcomm_data->dlci               = dlci;
835
0
        rfcomm_data->remote_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
836
0
        rfcomm_data->remote_bd_addr_id  = l2cap_data->remote_bd_addr_id;
837
838
0
        if (service_info && service_info->uuid.size != 0 &&
839
0
                p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
840
0
            uint8_t *value_data;
841
842
0
            value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &service_info->uuid));
843
844
0
            p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
845
0
        }
846
847
0
        if (!dissector_try_uint_with_data(rfcomm_dlci_dissector_table, (uint32_t) dlci,
848
0
                next_tvb, pinfo, tree, true, rfcomm_data)) {
849
0
            if (service_info && (service_info->uuid.size == 0 ||
850
0
                !dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &service_info->uuid),
851
0
                    next_tvb, pinfo, tree, true, rfcomm_data))) {
852
0
                decode_by_dissector = find_proto_by_channel(dlci >> 1);
853
0
                if (rfcomm_channels_enabled && decode_by_dissector) {
854
0
                    call_dissector_with_data(decode_by_dissector, next_tvb, pinfo, tree, rfcomm_data);
855
0
                } else {
856
                    /* unknown service, let the data dissector handle it */
857
0
                    call_data_dissector(next_tvb, pinfo, tree);
858
0
                }
859
0
            }
860
0
        }
861
0
    }
862
863
2
    proto_tree_add_item(rfcomm_tree, hf_fcs, tvb, fcs_offset, 1, ENC_LITTLE_ENDIAN);
864
2
    offset += 1;
865
866
2
    return offset;
867
2
}
868
869
static void*
870
uat_rfcomm_channels_copy_cb(void *dest, const void *source, size_t len _U_)
871
0
{
872
0
    const uat_rfcomm_channels_t* o = (const uat_rfcomm_channels_t*)source;
873
0
    uat_rfcomm_channels_t* d = (uat_rfcomm_channels_t*)dest;
874
875
0
    d->channel = o->channel;
876
0
    d->payload_proto = o->payload_proto;
877
0
    d->payload_proto_name = g_strdup(o->payload_proto_name);
878
879
0
    return dest;
880
0
}
881
882
static void
883
uat_rfcomm_channels_free_cb(void *r)
884
0
{
885
0
    uat_rfcomm_channels_t *rec = (uat_rfcomm_channels_t *)r;
886
0
    g_free(rec->payload_proto_name);
887
0
}
888
889
void
890
proto_register_btrfcomm(void)
891
14
{
892
14
    module_t *module;
893
14
    expert_module_t *expert_btrfcomm;
894
895
14
    static hf_register_info hf[] = {
896
14
        { &hf_dlci,
897
14
          { "DLCI", "btrfcomm.dlci",
898
14
            FT_UINT8, BASE_HEX, NULL, 0xFC,
899
14
            "RFCOMM Data Link Connection Identifier", HFILL}
900
14
        },
901
14
        { &hf_channel,
902
14
           { "Channel", "btrfcomm.channel",
903
14
            FT_UINT8, BASE_DEC, NULL, 0xF8,
904
14
            "RFCOMM Channel", HFILL}
905
14
        },
906
14
        { &hf_direction,
907
14
           {"Direction", "btrfcomm.direction",
908
14
            FT_UINT8, BASE_HEX, NULL, 0x04,
909
14
            NULL, HFILL}
910
14
        },
911
14
        { &hf_priority,
912
14
          { "Priority", "btrfcomm.priority",
913
14
            FT_UINT8, BASE_DEC, NULL, 0x3f,
914
14
            NULL, HFILL}
915
14
        },
916
14
        { &hf_max_frame_size,
917
14
          { "Max Frame Size", "btrfcomm.max_frame_size",
918
14
            FT_UINT16, BASE_DEC, NULL, 0,
919
14
            "Maximum Frame Size", HFILL}
920
14
        },
921
14
        { &hf_max_retrans,
922
14
          { "Maximum number of retransmissions", "btrfcomm.max_retrans",
923
14
            FT_UINT8, BASE_DEC, NULL, 0,
924
14
            NULL, HFILL}
925
14
        },
926
14
        { &hf_error_recovery_mode,
927
14
          { "Error Recovery Mode", "btrfcomm.error_recovery_mode",
928
14
            FT_UINT8, BASE_DEC, NULL, 0x07,
929
14
            NULL, HFILL}
930
14
        },
931
14
        { &hf_ea,
932
14
          { "EA Flag", "btrfcomm.ea",
933
14
            FT_UINT8, BASE_HEX, VALS(vs_ea), 0x01,
934
14
            "EA flag (should be always 1)", HFILL}
935
14
        },
936
14
        { &hf_cr,
937
14
          { "C/R Flag", "btrfcomm.cr",
938
14
            FT_BOOLEAN, 8, TFS(&tfs_command_response), 0x02,
939
14
            "Command/Response flag", HFILL}
940
14
        },
941
14
        { &hf_mcc,
942
14
          { "Multiplexer Control Command", "btrfcomm.mcc",
943
14
            FT_NONE, BASE_NONE, NULL, 0x00,
944
14
            NULL, HFILL}
945
14
        },
946
14
        { &hf_mcc_pn_parameters,
947
14
          { "Parameters", "btrfcomm.mcc.pn_parameters",
948
14
            FT_NONE, BASE_NONE, NULL, 0x00,
949
14
            NULL, HFILL}
950
14
        },
951
14
        { &hf_mcc_types,
952
14
          { "Types", "btrfcomm.mcc.types",
953
14
            FT_NONE, BASE_NONE, NULL, 0x00,
954
14
            NULL, HFILL}
955
14
        },
956
14
        { &hf_mcc_ea,
957
14
          { "EA Flag", "btrfcomm.mcc.ea",
958
14
            FT_UINT8, BASE_HEX, VALS(vs_ea), 0x01,
959
14
            "RFCOMM MCC EA flag", HFILL}
960
14
        },
961
14
        { &hf_mcc_cr,
962
14
          { "C/R Flag", "btrfcomm.mcc.cr",
963
14
            FT_BOOLEAN, 8, TFS(&tfs_command_response), 0x02,
964
14
            "Command/Response flag", HFILL}
965
14
        },
966
14
        { &hf_mcc_const_1,
967
14
          { "Ones padding", "btrfcomm.mcc.padding",
968
14
            FT_UINT8, BASE_HEX, NULL, 0x02,
969
14
            NULL, HFILL}
970
14
        },
971
14
        { &hf_mcc_dlci,
972
14
          { "MCC DLCI", "btrfcomm.mcc.dlci",
973
14
            FT_UINT8, BASE_HEX, NULL, 0xFC,
974
14
            "RFCOMM MCC Data Link Connection Identifier", HFILL}
975
14
        },
976
14
        { &hf_mcc_channel,
977
14
          { "MCC Channel", "btrfcomm.mcc.channel",
978
14
            FT_UINT8, BASE_DEC, NULL, 0xF8,
979
14
            "RFCOMM MCC Channel", HFILL}
980
14
        },
981
14
        { &hf_mcc_direction,
982
14
          { "MCC Direction", "btrfcomm.mcc.direction",
983
14
            FT_UINT8, BASE_HEX, NULL, 0x04,
984
14
            "RFCOMM MCC Direction", HFILL}
985
14
        },
986
14
        { &hf_mcc_pn_dlci,
987
14
          { "MCC DLCI", "btrfcomm.mcc.dlci",
988
14
            FT_UINT8, BASE_HEX, NULL, 0x3F,
989
14
            "RFCOMM MCC Data Link Connection Identifier", HFILL}
990
14
        },
991
14
        { &hf_mcc_pn_channel,
992
14
          { "MCC Channel", "btrfcomm.mcc.channel",
993
14
            FT_UINT8, BASE_DEC, NULL, 0x3E,
994
14
            "RFCOMM MCC Channel", HFILL}
995
14
        },
996
14
        { &hf_mcc_pn_direction,
997
14
          { "MCC Direction", "btrfcomm.mcc.direction",
998
14
            FT_UINT8, BASE_HEX, NULL, 0x01,
999
14
            "RFCOMM MCC Direction", HFILL}
1000
14
        },
1001
14
        { &hf_mcc_pn_zeros_padding,
1002
14
          { "Zeros padding", "btrfcomm.mcc.padding",
1003
14
            FT_UINT8, BASE_HEX, NULL, 0xC0,
1004
14
            "RFCOMM MSC Zeros padding", HFILL}
1005
14
        },
1006
14
        { &hf_mcc_cmd,
1007
14
          { "MCC Command Type", "btrfcomm.mcc.cmd",
1008
14
            FT_UINT8, BASE_HEX, VALS(vs_ctl), 0xFC,
1009
14
            NULL, HFILL}
1010
14
        },
1011
14
        { &hf_frame_type,
1012
14
          { "Frame type", "btrfcomm.frame_type",
1013
14
            FT_UINT8, BASE_HEX, VALS(vs_frame_type), 0xEF,
1014
14
            NULL, HFILL}
1015
14
        },
1016
14
        { &hf_acknowledgement_timer_t1,
1017
14
          { "Acknowledgement Timer T1", "btrfcomm.acknowledgement_timer_t1",
1018
14
            FT_UINT8, BASE_DEC, NULL, 0x00,
1019
14
            NULL, HFILL}
1020
14
        },
1021
14
        { &hf_pf,
1022
14
          { "P/F flag", "btrfcomm.pf",
1023
14
            FT_UINT8, BASE_HEX, NULL, 0x10,
1024
14
            "Poll/Final bit", HFILL}
1025
14
        },
1026
14
        { &hf_pn_i14,
1027
14
          { "Type of frame", "btrfcomm.pn.i",
1028
14
            FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_i), 0x0F,
1029
14
            "Type of information frames used for that particular DLCI",
1030
14
            HFILL}
1031
14
        },
1032
14
        { &hf_pn_c14,
1033
14
          { "Convergence layer", "btrfcomm.pn.cl",
1034
14
            FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_cl), 0xF0,
1035
14
            "Convergence layer used for that particular DLCI", HFILL}
1036
14
        },
1037
14
        { &hf_len,
1038
14
          { "Payload length", "btrfcomm.len",
1039
14
            FT_UINT16, BASE_DEC, NULL, 0,
1040
14
            "Frame length", HFILL}
1041
14
        },
1042
14
        { &hf_mcc_len,
1043
14
          { "MCC Length", "btrfcomm.mcc.len",
1044
14
            FT_UINT16, BASE_DEC, NULL, 0,
1045
14
            "Length of MCC data", HFILL}
1046
14
        },
1047
14
        { &hf_fcs,
1048
14
          { "Frame Check Sequence", "btrfcomm.fcs",
1049
14
            FT_UINT8, BASE_HEX, NULL, 0,
1050
14
            "Checksum over frame", HFILL}
1051
14
        },
1052
14
        { &hf_msc_parameters,
1053
14
          { "Parameters", "btrfcomm.mcc.msc_parameters",
1054
14
            FT_NONE, BASE_NONE, NULL, 0x00,
1055
14
            NULL, HFILL}
1056
14
        },
1057
14
        { &hf_msc_fc,
1058
14
          { "Flow Control (FC)", "btrfcomm.msc.fc",
1059
14
            FT_UINT8, BASE_HEX, NULL, 0x02,
1060
14
            NULL, HFILL}
1061
14
        },
1062
14
        { &hf_msc_rtc,
1063
14
          { "Ready To Communicate (RTC)", "btrfcomm.msc.rtc",
1064
14
            FT_UINT8, BASE_HEX, NULL, 0x04,
1065
14
            NULL, HFILL}
1066
14
        },
1067
14
        { &hf_msc_rtr,
1068
14
          { "Ready To Receive (RTR)", "btrfcomm.msc.rtr",
1069
14
            FT_UINT8, BASE_HEX, NULL, 0x08,
1070
14
            NULL, HFILL}
1071
14
        },
1072
14
        { &hf_msc_ic,
1073
14
          { "Incoming Call Indicator (IC)", "btrfcomm.msc.ic",
1074
14
            FT_UINT8, BASE_HEX, NULL, 0x40,
1075
14
            NULL, HFILL}
1076
14
        },
1077
14
        { &hf_msc_dv,
1078
14
          { "Data Valid (DV)", "btrfcomm.msc.dv",
1079
14
            FT_UINT8, BASE_HEX, NULL, 0x80,
1080
14
            NULL, HFILL}
1081
14
        },
1082
14
        { &hf_msc_l,
1083
14
          { "Length of break in units of 200ms", "btrfcomm.msc.bl",
1084
14
            FT_UINT8, BASE_DEC, NULL, 0xF0,
1085
14
            NULL, HFILL}
1086
14
        },
1087
14
        { &hf_msc_break_bits,
1088
14
          { "Break Bits", "btrfcomm.msc.break_bits",
1089
14
            FT_UINT8, BASE_DEC, NULL, 0xE0,
1090
14
            NULL, HFILL}
1091
14
        },
1092
14
        { &hf_address,
1093
14
          { "Address", "btrfcomm.address",
1094
14
            FT_NONE, BASE_NONE, NULL, 0x00,
1095
14
            NULL, HFILL}
1096
14
        },
1097
14
        { &hf_control,
1098
14
          { "Control", "btrfcomm.control",
1099
14
            FT_NONE, BASE_NONE, NULL, 0x00,
1100
14
            NULL, HFILL}
1101
14
        },
1102
14
        { &hf_fc_credits,
1103
14
          { "Credits", "btrfcomm.credits",
1104
14
            FT_UINT8, BASE_DEC, NULL, 0,
1105
14
            "Flow control: number of UIH frames allowed to send", HFILL}
1106
14
        }
1107
1108
14
    };
1109
1110
    /* Setup protocol subtree array */
1111
14
    static int *ett[] = {
1112
14
        &ett_btrfcomm,
1113
14
        &ett_btrfcomm_ctrl,
1114
14
        &ett_addr,
1115
14
        &ett_control,
1116
14
        &ett_mcc,
1117
14
        &ett_ctrl_pn_ci,
1118
14
        &ett_ctrl_pn_v24,
1119
14
        &ett_dlci,
1120
14
        &ett_mcc_dlci
1121
14
    };
1122
1123
14
    static ei_register_info ei[] = {
1124
14
        { &ei_btrfcomm_mcc_length_bad, { "btrfcomm.mcc_length_bad", PI_MALFORMED, PI_ERROR, "Huge MCC length", EXPFILL }},
1125
14
    };
1126
1127
    /* Decode As handling */
1128
14
    static build_valid_func btrfcomm_directed_channel_da_build_value[1] = {btrfcomm_directed_channel_value};
1129
14
    static decode_as_value_t btrfcomm_directed_channel_da_values = {btrfcomm_directed_channel_prompt, 1, btrfcomm_directed_channel_da_build_value};
1130
14
    static decode_as_t btrfcomm_directed_channel_da = {"btrfcomm", "btrfcomm.dlci", 1, 0, &btrfcomm_directed_channel_da_values, NULL, NULL,
1131
14
                                 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
1132
1133
    /* Register the protocol name and description */
1134
14
    proto_btrfcomm = proto_register_protocol("Bluetooth RFCOMM Protocol", "BT RFCOMM", "btrfcomm");
1135
14
    btrfcomm_handle = register_dissector("btrfcomm", dissect_btrfcomm, proto_btrfcomm);
1136
1137
    /* Required function calls to register the header fields and subtrees used */
1138
14
    proto_register_field_array(proto_btrfcomm, hf, array_length(hf));
1139
14
    proto_register_subtree_array(ett, array_length(ett));
1140
14
    expert_btrfcomm = expert_register_protocol(proto_btrfcomm);
1141
14
    expert_register_field_array(expert_btrfcomm, ei, array_length(ei));
1142
1143
14
    service_directions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1144
1145
14
    rfcomm_dlci_dissector_table = register_dissector_table("btrfcomm.dlci", "BT RFCOMM Directed Channel", proto_btrfcomm, FT_UINT16, BASE_DEC);
1146
1147
14
    module = prefs_register_protocol_subtree("Bluetooth", proto_btrfcomm, NULL);
1148
14
    prefs_register_static_text_preference(module, "rfcomm.version",
1149
14
            "Bluetooth Protocol RFCOMM version: 1.1", "Version of protocol supported by this dissector.");
1150
1151
14
    prefs_register_bool_preference(module, "rfcomm.decode_by.enabled",
1152
14
            "Enable Force Decode by Channel",
1153
14
            "Turn on/off decode by next rules",
1154
14
            &rfcomm_channels_enabled);
1155
1156
14
    uat_rfcomm_channels = uat_new("Force Decode by Channel",
1157
14
            sizeof(uat_rfcomm_channels_t),
1158
14
            "rfcomm_channels",
1159
14
            true,
1160
14
            &rfcomm_channels,
1161
14
            &num_rfcomm_channels,
1162
14
            UAT_AFFECTS_DISSECTION,
1163
14
            NULL,
1164
14
            uat_rfcomm_channels_copy_cb,
1165
14
            NULL,
1166
14
            uat_rfcomm_channels_free_cb,
1167
14
            NULL,
1168
14
            NULL,
1169
14
            uat_rfcomm_channels_fields);
1170
1171
14
    prefs_register_uat_preference(module, "rfcomm.channels",
1172
14
            "Force Decode by channel",
1173
14
            "Decode by channel",
1174
14
            uat_rfcomm_channels);
1175
1176
14
    register_decode_as(&btrfcomm_directed_channel_da);
1177
14
}
1178
1179
void
1180
proto_reg_handoff_btrfcomm(void)
1181
14
{
1182
14
    dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM, btrfcomm_handle);
1183
14
    dissector_add_for_decode_as("btl2cap.cid", btrfcomm_handle);
1184
14
}
1185
1186
/* Bluetooth Dial-Up Networking (DUN) profile dissection */
1187
static int
1188
dissect_btdun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1189
6
{
1190
6
    proto_item *ti;
1191
6
    proto_tree *st;
1192
6
    bool        is_at_cmd;
1193
6
    unsigned    i, length;
1194
1195
6
    length = tvb_captured_length(tvb);
1196
1197
6
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DUN");
1198
1199
6
    ti = proto_tree_add_item(tree, proto_btdun, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1200
6
    st = proto_item_add_subtree(ti, ett_btdun);
1201
1202
6
    is_at_cmd = true;
1203
81
    for(i = 0; i < length && is_at_cmd; i++) {
1204
75
        is_at_cmd = tvb_get_uint8(tvb, i) < 0x7d;
1205
75
    }
1206
1207
6
    if (is_at_cmd) {
1208
        /* presumably an AT command */
1209
1
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
1210
1
                     (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1211
1
                     tvb_format_text(pinfo->pool, tvb, 0, length));
1212
1213
1
           proto_tree_add_item(st, hf_dun_at_cmd, tvb, 0, tvb_reported_length(tvb), ENC_ASCII);
1214
1
    }
1215
5
    else {
1216
        /* ... or raw PPP */
1217
5
        if (ppp_handle)
1218
5
            call_dissector(ppp_handle, tvb, pinfo, tree);
1219
0
        else {
1220
            /* TODO: remove the above 'if' and this 'else-body' when "ppp_raw_hdlc" is available, requires that it is
1221
                made non-anonymous in ppp dissector to use */
1222
0
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
1223
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "%s <PPP frame>", (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd");
1224
1225
0
            call_data_dissector(tvb, pinfo, tree);
1226
0
        }
1227
5
    }
1228
1229
6
    return tvb_reported_length(tvb);
1230
6
}
1231
1232
void
1233
proto_register_btdun(void)
1234
14
{
1235
14
    static hf_register_info hf[] = {
1236
14
        { &hf_dun_at_cmd,
1237
14
          { "AT Cmd", "btdun.atcmd",
1238
14
            FT_STRING, BASE_NONE, NULL, 0,
1239
14
            "AT Command", HFILL}
1240
14
        },
1241
14
    };
1242
1243
    /* Setup protocol subtree array */
1244
14
    static int *ett[] = {
1245
14
        &ett_btdun
1246
14
    };
1247
1248
14
    proto_btdun = proto_register_protocol("Bluetooth DUN Packet", "BT DUN", "btdun");
1249
14
    btdun_handle = register_dissector("btdun", dissect_btdun, proto_btdun);
1250
1251
    /* Required function calls to register the header fields and subtrees used */
1252
14
    proto_register_field_array(proto_btdun, hf, array_length(hf));
1253
14
    proto_register_subtree_array(ett, array_length(ett));
1254
14
}
1255
1256
void
1257
proto_reg_handoff_btdun(void)
1258
14
{
1259
14
    dissector_add_string("bluetooth.uuid",  "1103", btdun_handle);
1260
1261
14
    dissector_add_for_decode_as("btrfcomm.dlci", btdun_handle);
1262
1263
14
    ppp_handle = find_dissector_add_dependency("ppp_raw_hdlc", proto_btdun);
1264
14
}
1265
1266
/* Bluetooth Serial Port profile (SPP) dissection */
1267
static int
1268
dissect_btspp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1269
0
{
1270
0
    proto_item *ti;
1271
0
    proto_tree *st;
1272
0
    bool        ascii_only;
1273
0
    unsigned    i;
1274
0
    unsigned    length = tvb_captured_length(tvb);
1275
1276
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPP");
1277
1278
0
    ti = proto_tree_add_item(tree, proto_btspp, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1279
0
    st = proto_item_add_subtree(ti, ett_btspp);
1280
1281
0
    length = MIN(length, 60);
1282
0
    ascii_only = true;
1283
0
    for(i = 0; i < length && ascii_only; i++) {
1284
0
        ascii_only = tvb_get_uint8(tvb, i) < 0x80;
1285
0
    }
1286
1287
0
    if (ascii_only) {
1288
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s%s\"",
1289
0
                     (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1290
0
                     tvb_format_text(pinfo->pool, tvb, 0, length),
1291
0
                     (tvb_captured_length(tvb) > length) ? "..." : "");
1292
0
    }
1293
1294
0
    proto_tree_add_item(st, hf_spp_data, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1295
1296
0
    return tvb_reported_length(tvb);
1297
0
}
1298
1299
void
1300
proto_register_btspp(void)
1301
14
{
1302
14
    static hf_register_info hf[] = {
1303
14
        { &hf_spp_data,
1304
14
          { "Data", "btspp.data",
1305
14
            FT_BYTES, BASE_NONE, NULL, 0,
1306
14
            NULL, HFILL }
1307
14
        },
1308
14
    };
1309
1310
    /* Setup protocol subtree array */
1311
14
    static int *ett[] = {
1312
14
        &ett_btspp
1313
14
    };
1314
1315
14
    proto_btspp = proto_register_protocol("Bluetooth SPP Packet", "BT SPP", "btspp");
1316
14
    btspp_handle = register_dissector("btspp", dissect_btspp, proto_btspp);
1317
1318
    /* Required function calls to register the header fields and subtrees used */
1319
14
    proto_register_field_array(proto_btspp, hf, array_length(hf));
1320
14
    proto_register_subtree_array(ett, array_length(ett));
1321
14
}
1322
1323
void
1324
proto_reg_handoff_btspp(void)
1325
14
{
1326
14
    dissector_add_string("bluetooth.uuid",  "1101", btspp_handle);
1327
1328
14
    dissector_add_for_decode_as("btrfcomm.dlci", btspp_handle);
1329
14
}
1330
1331
1332
/* Bluetooth Global Navigation Satellite System profile (GNSS) dissection */
1333
static int
1334
dissect_btgnss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1335
0
{
1336
0
    proto_item *main_item;
1337
0
    proto_tree *main_tree;
1338
1339
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "GNSS");
1340
1341
0
    main_item = proto_tree_add_item(tree, proto_btgnss, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1342
0
    main_tree = proto_item_add_subtree(main_item, ett_btgnss);
1343
1344
0
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
1345
0
            (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1346
0
            tvb_format_text(pinfo->pool, tvb, 0, tvb_captured_length(tvb)));
1347
1348
    /* GNSS using NMEA-0183 protocol, but it is not available */
1349
0
    proto_tree_add_item(main_tree, hf_gnss_data, tvb, 0, tvb_reported_length(tvb), ENC_ASCII);
1350
1351
0
    return tvb_reported_length(tvb);
1352
0
}
1353
1354
void
1355
proto_register_btgnss(void)
1356
14
{
1357
14
    static hf_register_info hf[] = {
1358
14
        { &hf_gnss_data,
1359
14
        { "Data", "btgnss.data",
1360
14
            FT_STRING, BASE_NONE, NULL, 0,
1361
14
            NULL, HFILL }
1362
14
        },
1363
14
    };
1364
1365
14
    static int *ett[] = {
1366
14
        &ett_btgnss
1367
14
    };
1368
1369
14
    proto_btgnss = proto_register_protocol("Bluetooth GNSS Profile", "BT GNSS", "btgnss");
1370
14
    btgnss_handle = register_dissector("btgnss", dissect_btgnss, proto_btgnss);
1371
1372
14
    proto_register_field_array(proto_btgnss, hf, array_length(hf));
1373
14
    proto_register_subtree_array(ett, array_length(ett));
1374
14
}
1375
1376
void
1377
proto_reg_handoff_btgnss(void)
1378
14
{
1379
14
    dissector_add_string("bluetooth.uuid",  "1135", btgnss_handle);
1380
14
    dissector_add_string("bluetooth.uuid",  "1136", btgnss_handle);
1381
1382
14
    dissector_add_for_decode_as("btrfcomm.dlci", btgnss_handle);
1383
14
}
1384
1385
/*
1386
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1387
 *
1388
 * Local variables:
1389
 * c-basic-offset: 4
1390
 * tab-width: 8
1391
 * indent-tabs-mode: nil
1392
 * End:
1393
 *
1394
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1395
 * :indentSize=4:tabSize=8:noTabs=true:
1396
 */