Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-btl2cap.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-btl2cap.c
2
 * Routines for the Bluetooth L2CAP dissection
3
 * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
4
 *  From: http://affix.sourceforge.net/archive/ethereal_affix-3.patch
5
 *
6
 * Refactored for wireshark checkin
7
 *   Ronnie Sahlberg 2006
8
 *
9
 * Added handling and reassembly of LE-Frames
10
 *   Anders Broman at ericsson dot com 2016
11
 *
12
 * Wireshark - Network traffic analyzer
13
 * By Gerald Combs <gerald@wireshark.org>
14
 * Copyright 1998 Gerald Combs
15
 *
16
 * SPDX-License-Identifier: GPL-2.0-or-later
17
 */
18
19
#include "config.h"
20
21
#include <epan/packet.h>
22
#include <epan/exceptions.h>
23
#include <epan/expert.h>
24
#include <epan/decode_as.h>
25
#include <epan/proto_data.h>
26
#include <epan/reassemble.h>
27
#include <epan/unit_strings.h>
28
29
#include <wiretap/wtap.h>
30
31
#include "packet-bluetooth.h"
32
#include "packet-bthci_acl.h"
33
#include "packet-btsdp.h"
34
#include "packet-btl2cap.h"
35
36
/* Initialize the protocol and registered fields */
37
int proto_btl2cap;
38
39
static int hf_btl2cap_length;
40
static int hf_btl2cap_cid;
41
static int hf_btl2cap_payload;
42
static int hf_btl2cap_command;
43
static int hf_btl2cap_cmd_code;
44
static int hf_btl2cap_cmd_ident;
45
static int hf_btl2cap_cmd_length;
46
static int hf_btl2cap_cmd_data;
47
static int hf_btl2cap_psm;
48
static int hf_btl2cap_psm_dynamic;
49
static int hf_btl2cap_scid;
50
static int hf_btl2cap_dcid;
51
static int hf_btl2cap_icid;
52
static int hf_btl2cap_controller;
53
static int hf_btl2cap_dcontroller;
54
static int hf_btl2cap_result;
55
static int hf_btl2cap_move_result;
56
static int hf_btl2cap_move_confirmation_result;
57
static int hf_btl2cap_status;
58
static int hf_btl2cap_rej_reason;
59
static int hf_btl2cap_sig_mtu;
60
static int hf_btl2cap_info_mtu;
61
static int hf_btl2cap_info_flowcontrol;
62
static int hf_btl2cap_info_retransmission;
63
static int hf_btl2cap_info_bidirqos;
64
static int hf_btl2cap_info_enh_retransmission;
65
static int hf_btl2cap_info_streaming;
66
static int hf_btl2cap_info_fcs;
67
static int hf_btl2cap_info_flow_spec;
68
static int hf_btl2cap_info_fixedchan;
69
static int hf_btl2cap_info_fixedchans;
70
static int hf_btl2cap_info_fixedchans_null;
71
static int hf_btl2cap_info_fixedchans_signal;
72
static int hf_btl2cap_info_fixedchans_connless;
73
static int hf_btl2cap_info_fixedchans_amp_man;
74
static int hf_btl2cap_info_fixedchans_rfu;
75
static int hf_btl2cap_info_fixedchans_smp;
76
static int hf_btl2cap_info_fixedchans_amp_test;
77
static int hf_btl2cap_info_window;
78
static int hf_btl2cap_info_unicast;
79
static int hf_btl2cap_info_type;
80
static int hf_btl2cap_info_result;
81
static int hf_btl2cap_configuration_result;
82
static int hf_btl2cap_info_extfeatures;
83
static int hf_btl2cap_option;
84
static int hf_btl2cap_option_type;
85
static int hf_btl2cap_option_length;
86
static int hf_btl2cap_option_mtu;
87
static int hf_btl2cap_option_flushTO;
88
static int hf_btl2cap_option_flush_to_us;
89
static int hf_btl2cap_option_flags;
90
static int hf_btl2cap_option_service_type;
91
static int hf_btl2cap_option_tokenrate;
92
static int hf_btl2cap_option_tokenbucketsize;
93
static int hf_btl2cap_option_peakbandwidth;
94
static int hf_btl2cap_option_latency;
95
static int hf_btl2cap_option_delayvariation;
96
static int hf_btl2cap_option_retransmissionmode;
97
static int hf_btl2cap_option_txwindow;
98
static int hf_btl2cap_option_maxtransmit;
99
static int hf_btl2cap_option_retransmittimeout;
100
static int hf_btl2cap_option_monitortimeout;
101
static int hf_btl2cap_option_mps;
102
static int hf_btl2cap_option_fcs;
103
static int hf_btl2cap_option_window;
104
static int hf_btl2cap_option_identifier;
105
static int hf_btl2cap_option_sdu_size;
106
static int hf_btl2cap_option_sdu_arrival_time;
107
static int hf_btl2cap_option_access_latency;
108
static int hf_btl2cap_control;
109
static int hf_btl2cap_control_sar;
110
static int hf_btl2cap_control_reqseq;
111
static int hf_btl2cap_control_txseq;
112
static int hf_btl2cap_control_retransmissiondisable;
113
static int hf_btl2cap_control_supervisory;
114
static int hf_btl2cap_control_type;
115
static int hf_btl2cap_fcs;
116
static int hf_btl2cap_sdulength;
117
static int hf_btl2cap_continuation_to;
118
static int hf_btl2cap_reassembled_in;
119
static int hf_btl2cap_min_interval;
120
static int hf_btl2cap_max_interval;
121
static int hf_btl2cap_peripheral_latency;
122
static int hf_btl2cap_timeout_multiplier;
123
static int hf_btl2cap_conn_param_result;
124
static int hf_btl2cap_credits;
125
static int hf_btl2cap_initial_credits;
126
static int hf_btl2cap_le_result;
127
static int hf_btl2cap_le_psm;
128
static int hf_btl2cap_flags_reserved;
129
static int hf_btl2cap_flags_continuation;
130
static int hf_btl2cap_data;
131
static int hf_btl2cap_service;
132
static int hf_btl2cap_connect_in_frame;
133
static int hf_btl2cap_disconnect_in_frame;
134
135
static int hf_btl2cap_le_sdu_fragments;
136
static int hf_btl2cap_le_sdu_fragment;
137
static int hf_btl2cap_le_sdu_fragment_overlap;
138
static int hf_btl2cap_le_sdu_fragment_overlap_conflicts;
139
static int hf_btl2cap_le_sdu_fragment_multiple_tails;
140
static int hf_btl2cap_le_sdu_fragment_too_long_fragment;
141
static int hf_btl2cap_le_sdu_fragment_error;
142
static int hf_btl2cap_le_sdu_fragment_count;
143
static int hf_btl2cap_le_sdu_reassembled_in;
144
static int hf_btl2cap_le_sdu_reassembled_length;
145
146
static int hf_btl2cap_le_sdu_length;
147
148
/* Initialize the subtree pointers */
149
static int ett_btl2cap;
150
static int ett_btl2cap_cmd;
151
static int ett_btl2cap_option;
152
static int ett_btl2cap_extfeatures;
153
static int ett_btl2cap_fixedchans;
154
static int ett_btl2cap_control;
155
static int ett_btl2cap_le_sdu_fragment;
156
static int ett_btl2cap_le_sdu_fragments;
157
158
static expert_field ei_btl2cap_parameter_mismatch;
159
static expert_field ei_btl2cap_sdulength_bad;
160
static expert_field ei_btl2cap_length_bad;
161
static expert_field ei_btl2cap_unknown_command_code;
162
163
/* Initialize dissector table */
164
static dissector_table_t l2cap_psm_dissector_table;
165
static dissector_table_t l2cap_cid_dissector_table;
166
167
/* This table maps command identity values to psm values. */
168
static wmem_tree_t *cmd_ident_to_psm_table;
169
170
/* This table maps cid values to psm values.
171
 * The same table is used both for SCID and DCID.
172
 * For Remote CIDs (Receive Request SCID or Sent Response DCID)
173
 * we 'or' the CID with 0x80000000 in this table
174
 */
175
static wmem_tree_t *cid_to_psm_table;
176
177
/* 5.4 RETRANSMISSION AND FLOW CONTROL OPTION
178
 * Table 5.2
179
 * Mode
180
 * 0x00 L2CAP Basic Mode
181
 * 0x01 Retransmission mode
182
 * 0x02 Flow control mode
183
 * 0x03 Enhanced Retransmission mode
184
 * 0x04 Streaming mode
185
 * Other values Reserved for future use
186
 */
187
188
0
#define L2CAP_BASIC_MODE 0
189
/* XXX Cheat and define a vaue for
190
 * Connection-Oriented Channels in LE Credit Based Flow Control Mode
191
 */
192
8.57k
#define L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE 0xff
193
194
typedef struct _config_data_t {
195
    uint8_t     mode;
196
    uint8_t     txwindow;
197
    wmem_tree_t *start_fragments;  /* indexed by pinfo->num */
198
    /* Used for LE frame reassembly */
199
    unsigned segmentation_started : 1;  /* 0 = No, 1 = Yes */
200
    unsigned segment_len_rem;          /* The remaining segment length, used to find last segment */
201
} config_data_t;
202
203
typedef struct _sdu_reassembly_t
204
{
205
    uint8_t *reassembled;
206
    uint8_t  seq;
207
    uint32_t first_frame;
208
    uint32_t last_frame;
209
    uint16_t tot_len;
210
    int      cur_off;           /* counter used by reassembly */
211
} sdu_reassembly_t;
212
213
typedef struct _psm_data_t {
214
    uint32_t      interface_id;
215
    uint32_t      adapter_id;
216
    uint32_t      chandle;
217
    uint32_t      local_cid;
218
    uint32_t      remote_cid;
219
    uint16_t      psm;
220
    bool          local_service;
221
    uint32_t      connect_in_frame;
222
    uint32_t      disconnect_in_frame;
223
    config_data_t in;
224
    config_data_t out;
225
} psm_data_t;
226
227
typedef struct _btl2cap_frame_data_t
228
{
229
    /* LE frames info */
230
    unsigned first_fragment : 1; /* 0 = No, 1 = First or only fragment*/
231
    unsigned more_fragments : 1; /* 0 = Last fragment, 1 = more fragments*/
232
} btl2cap_frame_data_t;
233
234
static const value_string command_code_vals[] = {
235
    { 0x01,   "Command Reject" },
236
    { 0x02,   "Connection Request" },
237
    { 0x03,   "Connection Response" },
238
    { 0x04,   "Configure Request" },
239
    { 0x05,   "Configure Response" },
240
    { 0x06,   "Disconnection Request" },
241
    { 0x07,   "Disconnection Response" },
242
    { 0x08,   "Echo Request" },
243
    { 0x09,   "Echo Response" },
244
    { 0x0A,   "Information Request" },
245
    { 0x0B,   "Information Response" },
246
    { 0x0C,   "Create Channel Request" },
247
    { 0x0D,   "Create Channel Response" },
248
    { 0x0E,   "Move Channel Request" },
249
    { 0x0F,   "Move Channel Response" },
250
    { 0x10,   "Move Channel Confirmation" },
251
    { 0x11,   "Move Channel Confirmation Response" },
252
    { 0x12,   "Connection Parameter Update Request" },
253
    { 0x13,   "Connection Parameter Update Response" },
254
    { 0x14,   "LE Credit Based Connection Request" },
255
    { 0x15,   "LE Credit Based Connection Response" },
256
    { 0x16,   "LE Flow Control Credit" },
257
    { 0x17,   "L2CAP Credit Based Connection Request" },
258
    { 0x18,   "L2CAP Credit Based Connection Response" },
259
    { 0x19,   "L2CAP Credit Based Reconfigure Request" },
260
    { 0x1A,   "L2CAP Credit Based Reconfigure Response" },
261
    { 0, NULL }
262
};
263
264
265
static const value_string psm_vals[] = {
266
    { 0x0001, "SDP" },
267
    { 0x0003, "RFCOMM" },
268
    { 0x0005, "TCS-BIN" },
269
    { 0x0007, "TCS-BIN-CORDLESS" },
270
    { 0x000F, "BNEP" },
271
    { 0x0011, "HID-Control" },
272
    { 0x0013, "HID-Interrupt" },
273
    { 0x0015, "UPnP" },
274
    { 0x0017, "AVCTP-Control" },
275
    { 0x0019, "AVDTP" },
276
    { 0x001B, "AVCTP-Browsing" },
277
    { 0x001D, "UDI_C-Plane" },
278
    { 0x001F, "ATT" },
279
    { 0x0021, "3DSP" },
280
    { 0x0023, "IPSP" },
281
    { 0x0025, "OTS" },
282
    { 0x0027, "EATT" },
283
    { 0, NULL }
284
};
285
value_string_ext ext_psm_vals = VALUE_STRING_EXT_INIT(psm_vals);
286
287
static const value_string result_vals[] = {
288
    { 0x0000, "Successful" },
289
    { 0x0001, "Pending" },
290
    { 0x0002, "Refused - PSM not supported" },
291
    { 0x0003, "Refused - security block" },
292
    { 0x0004, "Refused - no resources available" },
293
    { 0x0005, "Refused - Controller ID not supported" },
294
    { 0, NULL }
295
};
296
297
static const value_string le_result_vals[] = {
298
    { 0x0000, "Connection Successful" },
299
    { 0x0002, "Connection Refused - LE_PSM Not Supported" },
300
    { 0x0004, "Connection Refused - No Resources Available" },
301
    { 0x0005, "Connection Refused - Insufficient Authentication" },
302
    { 0x0006, "Connection Refused - Insufficient Authorization" },
303
    { 0x0007, "Connection Refused - Insufficient Encryption Key Size" },
304
    { 0x0008, "Connection Refused - Insufficient Encryption" },
305
    { 0, NULL }
306
};
307
308
static const value_string move_result_vals[] = {
309
    { 0x0000, "Success" },
310
    { 0x0001, "Pending" },
311
    { 0x0002, "Refused - Controller ID not supported" },
312
    { 0x0003, "Refused - New Controller ID is same as old" },
313
    { 0x0004, "Refused - Configuration not supported" },
314
    { 0x0005, "Refused - Move Channel collision" },
315
    { 0x0006, "Refused - Channel not allowed to be moved" },
316
    { 0, NULL }
317
};
318
319
static const value_string move_result_confirmation_vals[] = {
320
    { 0x0000,   "Success - both sides succeed" },
321
    { 0x0001,   "Failure - one or both sides refuse" },
322
    { 0, NULL }
323
};
324
325
static const value_string configuration_result_vals[] = {
326
    { 0x0000, "Success"},
327
    { 0x0001, "Failure - unacceptable parameters" },
328
    { 0x0002, "Failure - reject (no reason provided)" },
329
    { 0x0003, "Failure - unknown options" },
330
    { 0x0004, "Pending" },
331
    { 0x0005, "Failure - flow spec rejected" },
332
    { 0, NULL }
333
};
334
335
static const value_string conn_param_result_vals[] = {
336
    { 0x0000,   "Accepted" },
337
    { 0x0001,   "Rejected" },
338
    { 0, NULL }
339
};
340
341
static const value_string status_vals[] = {
342
    { 0x0000, "No further information available" },
343
    { 0x0001, "Authentication pending" },
344
    { 0x0002, "Authorization pending" },
345
    { 0, NULL }
346
};
347
348
static const value_string reason_vals[] = {
349
    { 0x0000, "Command not understood" },
350
    { 0x0001, "Signaling MTU exceeded" },
351
    { 0x0002, "Invalid CID in request" },
352
    { 0, NULL }
353
};
354
355
static const value_string info_type_vals[] = {
356
    { 0x0001, "Connectionless MTU" },
357
    { 0x0002, "Extended Features Mask" },
358
    { 0x0003, "Fixed Channels Supported" },
359
    { 0, NULL }
360
};
361
362
static const value_string info_result_vals[] = {
363
    { 0x0000, "Success" },
364
    { 0x0001, "Not Supported" },
365
    { 0, NULL }
366
};
367
368
static const value_string option_servicetype_vals[] = {
369
    { 0x00,   "No traffic" },
370
    { 0x01,   "Best effort (Default)" },
371
    { 0x02,   "Guaranteed" },
372
    { 0, NULL }
373
};
374
375
static const value_string option_type_vals[] = {
376
    { 0x01,   "Maximum Transmission Unit" },
377
    { 0x02,   "Flush Timeout" },
378
    { 0x03,   "Quality of Service" },
379
    { 0x04,   "Retransmission and Flow Control" },
380
    { 0x05,   "FCS" },
381
    { 0x06,   "Extended Flow Specification" },
382
    { 0x07,   "Extended Window Size" },
383
    { 0, NULL }
384
};
385
386
static const value_string option_retransmissionmode_vals[] = {
387
    { 0x00,   "Basic Mode" },
388
    { 0x01,   "Retransmission Mode" },
389
    { 0x02,   "Flow Control Mode" },
390
    { 0x03,   "Enhanced Retransmission Mode" },
391
    { 0x04,   "Streaming Mode" },
392
    { 0, NULL }
393
};
394
395
static const value_string control_sar_vals[] = {
396
    { 0x00,   "Unsegmented" },
397
    { 0x01,   "Start" },
398
    { 0x02,   "End" },
399
    { 0x03,   "Continuation" },
400
    { 0, NULL }
401
};
402
403
static const value_string control_supervisory_vals[] = {
404
    { 0x00,   "RR" },
405
    { 0x01,   "REJ" },
406
    { 0x02,   "RNR" },
407
    { 0x03,   "SREJ" },
408
    { 0, NULL }
409
};
410
411
static const value_string control_type_vals[] = {
412
    { 0x00,   "I-Frame" },
413
    { 0x01,   "S-Frame" },
414
    { 0, NULL }
415
};
416
417
static const value_string option_fcs_vals[] = {
418
    { 0x00,   "No FCS" },
419
    { 0x01,   "16-bit FCS" },
420
    { 0, NULL }
421
};
422
423
static const value_string ctrl_id_code_vals[] = {
424
    { 0x00,   "Bluetooth BR/EDR" },
425
    { 0x01,   "Wifi 802.11" },
426
    { 0, NULL }
427
};
428
429
static const range_string cid_rvals[] = {
430
    { 0x0000, 0x0000,  "Null identifier" },
431
    { 0x0001, 0x0001,  "L2CAP Signaling Channel" },
432
    { 0x0002, 0x0002,  "Connectionless Channel" },
433
    { 0x0003, 0x0003,  "AMP Manager Protocol" },
434
    { 0x0004, 0x0004,  "Attribute Protocol" },
435
    { 0x0005, 0x0005,  "Low Energy L2CAP Signaling Channel" },
436
    { 0x0006, 0x0006,  "Security Manager Protocol" },
437
    { 0x0007, 0x003E,  "Reserved" },
438
    { 0x003F, 0x003F,  "AMP Test Manager" },
439
    { 0x0040, 0xFFFF,  "Dynamically Allocated Channel" },
440
    { 0, 0, NULL }
441
};
442
443
static const range_string le_psm_rvals[] = {
444
    { 0x0001, 0x007F,  "Fixed, SIG Assigned" },
445
    { 0x0080, 0x00FF,  "Dynamically Allocated" },
446
    { 0x0100, 0xFFFF,  "Reserved" },
447
    { 0, 0, NULL }
448
};
449
450
static const unit_name_string units_ll_connection_event = { " LL Connection Event", " LL Connection Events" };
451
452
4.59k
#define PROTO_DATA_BTL2CAP_CID        0
453
1.02k
#define PROTO_DATA_BTL2CAP_PSM        1
454
455
void proto_register_btl2cap(void);
456
void proto_reg_handoff_btl2cap(void);
457
458
/* Reassembly */
459
static reassembly_table btl2cap_le_sdu_reassembly_table;
460
461
static const fragment_items btl2cap_le_sdu_frag_items = {
462
    /* Fragment subtrees */
463
    &ett_btl2cap_le_sdu_fragment,
464
    &ett_btl2cap_le_sdu_fragments,
465
    /* Fragment fields */
466
    &hf_btl2cap_le_sdu_fragments,
467
    &hf_btl2cap_le_sdu_fragment,
468
    &hf_btl2cap_le_sdu_fragment_overlap,
469
    &hf_btl2cap_le_sdu_fragment_overlap_conflicts,
470
    &hf_btl2cap_le_sdu_fragment_multiple_tails,
471
    &hf_btl2cap_le_sdu_fragment_too_long_fragment,
472
    &hf_btl2cap_le_sdu_fragment_error,
473
    &hf_btl2cap_le_sdu_fragment_count,
474
    /* Reassembled in field */
475
    &hf_btl2cap_le_sdu_reassembled_in,
476
    /* Reassembled length field */
477
    &hf_btl2cap_le_sdu_reassembled_length,
478
    /* Reassembled data field */
479
    NULL,
480
    /* Tag */
481
    "BTL2CAP LE SDU fragments"
482
};
483
484
485
static void btl2cap_cid_prompt(packet_info *pinfo, char* result)
486
0
{
487
0
    uint16_t *value_data;
488
489
0
    value_data = (uint16_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID);
490
0
    if (value_data)
491
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "L2CAP CID 0x%04x as", (unsigned) *value_data);
492
0
    else
493
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Unknown L2CAP CID");
494
0
}
495
496
static void *btl2cap_cid_value(packet_info *pinfo)
497
0
{
498
0
    uint16_t *value_data;
499
500
0
    value_data = (uint16_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID);
501
502
0
    if (value_data)
503
0
        return GUINT_TO_POINTER((unsigned long)*value_data);
504
505
0
    return NULL;
506
0
}
507
508
static void btl2cap_psm_prompt(packet_info *pinfo, char* result)
509
0
{
510
0
    uint16_t *value_data;
511
512
0
    value_data = (uint16_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM);
513
0
    if (value_data)
514
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "L2CAP PSM 0x%04x as", (unsigned) *value_data);
515
0
    else
516
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Unknown L2CAP PSM");
517
0
}
518
519
static void *btl2cap_psm_value(packet_info *pinfo)
520
0
{
521
0
    uint16_t *value_data;
522
523
0
    value_data = (uint16_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM);
524
525
0
    if (value_data)
526
0
        return GUINT_TO_POINTER((unsigned long)*value_data);
527
528
0
    return NULL;
529
0
}
530
531
static uint16_t
532
get_service_uuid(packet_info *pinfo, btl2cap_data_t *l2cap_data, uint16_t psm, bool is_local_psm)
533
4.50k
{
534
4.50k
    wmem_tree_key_t    key[10];
535
4.50k
    uint32_t           k_interface_id;
536
4.50k
    uint32_t           k_adapter_id;
537
4.50k
    uint32_t           k_sdp_psm;
538
4.50k
    uint32_t           k_direction;
539
4.50k
    uint32_t           k_bd_addr_oui;
540
4.50k
    uint32_t           k_bd_addr_id;
541
4.50k
    uint32_t           k_service_type;
542
4.50k
    uint32_t           k_service_channel;
543
4.50k
    uint32_t           k_frame_number;
544
4.50k
    uint32_t           interface_id;
545
4.50k
    uint32_t           adapter_id;
546
4.50k
    uint32_t           remote_bd_addr_oui;
547
4.50k
    uint32_t           remote_bd_addr_id;
548
4.50k
    service_info_t    *service_info;
549
550
4.50k
    interface_id       = l2cap_data->interface_id;
551
4.50k
    adapter_id         = l2cap_data->adapter_id;
552
553
4.50k
    k_interface_id    = interface_id;
554
4.50k
    k_adapter_id      = adapter_id;
555
4.50k
    k_sdp_psm         = SDP_PSM_DEFAULT;
556
4.50k
    k_direction       = (is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
557
4.50k
    if (k_direction == P2P_DIR_RECV) {
558
4.50k
        k_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
559
4.50k
        k_bd_addr_id  = l2cap_data->remote_bd_addr_id;
560
4.50k
    } else {
561
0
        k_bd_addr_oui = 0;
562
0
        k_bd_addr_id  = 0;
563
0
    }
564
565
4.50k
    remote_bd_addr_oui = k_bd_addr_oui;
566
4.50k
    remote_bd_addr_id  = k_bd_addr_id;
567
568
4.50k
    k_service_type    = BTSDP_L2CAP_PROTOCOL_UUID;
569
4.50k
    k_service_channel = psm;
570
4.50k
    k_frame_number    = pinfo->num;
571
572
4.50k
    key[0].length = 1;
573
4.50k
    key[0].key = &k_interface_id;
574
4.50k
    key[1].length = 1;
575
4.50k
    key[1].key = &k_adapter_id;
576
4.50k
    key[2].length = 1;
577
4.50k
    key[2].key = &k_sdp_psm;
578
4.50k
    key[3].length = 1;
579
4.50k
    key[3].key = &k_direction;
580
4.50k
    key[4].length = 1;
581
4.50k
    key[4].key = &k_bd_addr_oui;
582
4.50k
    key[5].length = 1;
583
4.50k
    key[5].key = &k_bd_addr_id;
584
4.50k
    key[6].length = 1;
585
4.50k
    key[6].key = &k_service_type;
586
4.50k
    key[7].length = 1;
587
4.50k
    key[7].key = &k_service_channel;
588
4.50k
    key[8].length = 1;
589
4.50k
    key[8].key = &k_frame_number;
590
4.50k
    key[9].length = 0;
591
4.50k
    key[9].key = NULL;
592
593
4.50k
    service_info = btsdp_get_service_info(key);
594
595
4.50k
    if (service_info &&
596
4.50k
        service_info->interface_id == interface_id &&
597
4.50k
        service_info->adapter_id == adapter_id &&
598
4.50k
        service_info->sdp_psm == SDP_PSM_DEFAULT &&
599
4.50k
        ((service_info->direction == P2P_DIR_RECV &&
600
0
          service_info->bd_addr_oui == remote_bd_addr_oui &&
601
0
          service_info->bd_addr_id == remote_bd_addr_id) ||
602
0
         (service_info->direction != P2P_DIR_RECV &&
603
0
          service_info->bd_addr_oui == 0 &&
604
0
          service_info->bd_addr_id == 0)) &&
605
4.50k
        service_info->type == BTSDP_L2CAP_PROTOCOL_UUID &&
606
4.50k
        service_info->channel == psm)
607
0
    {
608
0
        return service_info->uuid.bt_uuid;
609
0
    }
610
611
4.50k
    return 0;
612
4.50k
}
613
614
static int
615
dissect_comrej(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
616
318
{
617
318
    uint16_t reason;
618
619
318
    reason  = tvb_get_letohs(tvb, offset);
620
318
    proto_tree_add_item(tree, hf_btl2cap_rej_reason, tvb, offset, 2, ENC_LITTLE_ENDIAN);
621
318
    offset += 2;
622
623
318
    switch (reason) {
624
1
    case 0x0000: /* Command not understood */
625
1
        break;
626
627
13
    case 0x0001: /* Signaling MTU exceeded */
628
13
        proto_tree_add_item(tree, hf_btl2cap_sig_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
629
13
        offset += 2;
630
13
        break;
631
632
2
    case 0x0002: /* Invalid CID in requests */
633
2
        proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
634
2
        offset += 2;
635
636
2
        proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
637
2
        offset += 2;
638
639
2
        break;
640
641
301
    default:
642
301
        break;
643
318
    }
644
645
317
    return offset;
646
318
}
647
648
static int
649
dissect_connrequest(tvbuff_t *tvb, int offset, packet_info *pinfo,
650
        proto_tree *tree, proto_tree *command_tree, bool is_ch_request,
651
        bthci_acl_data_t *acl_data, btl2cap_data_t *l2cap_data)
652
158
{
653
158
    uint16_t           scid;
654
158
    uint16_t           psm;
655
158
    const char        *psm_str = "<NONE>";
656
657
158
    psm = tvb_get_letohs(tvb, offset);
658
659
158
    if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
660
105
        uint16_t *value_data;
661
662
105
        value_data = wmem_new(wmem_file_scope(), uint16_t);
663
105
        *value_data = psm;
664
665
105
        p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
666
105
    }
667
668
158
    if (psm < BTL2CAP_DYNAMIC_PSM_START) {
669
103
        proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
670
103
        psm_str = val_to_str_const(psm, psm_vals, "Unknown PSM");
671
103
    } else {
672
55
        proto_item  *item;
673
55
        uint16_t     uuid;
674
675
55
        item = proto_tree_add_item(command_tree, hf_btl2cap_psm_dynamic, tvb, offset, 2, ENC_LITTLE_ENDIAN);
676
677
55
        uuid = get_service_uuid(pinfo, l2cap_data, psm, (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false);
678
55
        if (uuid) {
679
0
            psm_str = val_to_str_ext_const(uuid, &bluetooth_uuid_vals_ext, "Unknown PSM");
680
0
            proto_item_append_text(item, " (%s)", psm_str);
681
0
        }
682
55
    }
683
158
    offset += 2;
684
685
158
    scid = tvb_get_letohs(tvb, offset);
686
158
    proto_tree_add_item(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
687
158
    offset += 2;
688
689
158
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, SCID: 0x%04x)", psm_str, scid);
690
691
158
    if (is_ch_request) {
692
37
        proto_tree_add_item(command_tree, hf_btl2cap_controller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
693
37
        offset += 1;
694
37
    }
695
696
158
    if (!pinfo->fd->visited) {
697
157
        wmem_tree_key_t    key[6];
698
157
        uint32_t           k_interface_id;
699
157
        uint32_t           k_adapter_id;
700
157
        uint32_t           k_chandle;
701
157
        uint32_t           k_cid;
702
157
        uint32_t           k_frame_number;
703
157
        uint32_t           interface_id;
704
157
        uint32_t           adapter_id;
705
157
        uint32_t           chandle;
706
157
        psm_data_t        *psm_data;
707
708
157
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
709
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
710
157
        else
711
157
            interface_id = HCI_INTERFACE_DEFAULT;
712
157
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
713
157
        chandle      = (acl_data) ? acl_data->chandle : 0;
714
715
157
        k_interface_id = interface_id;
716
157
        k_adapter_id   = adapter_id;
717
157
        k_chandle      = chandle;
718
157
        k_cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x80000000 : 0x00000000);
719
157
        k_frame_number = pinfo->num;
720
721
157
        psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
722
157
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
723
0
            psm_data->local_cid = BTL2CAP_UNKNOWN_CID;
724
0
            psm_data->remote_cid = scid |  0x80000000;
725
157
        } else {
726
157
            psm_data->local_cid = scid;
727
157
            psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
728
157
        }
729
157
        psm_data->psm  = psm;
730
157
        psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
731
157
        psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
732
157
        psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
733
157
        psm_data->interface_id = k_interface_id;
734
157
        psm_data->adapter_id   = k_adapter_id;
735
157
        psm_data->chandle      = k_chandle;
736
157
        psm_data->connect_in_frame = pinfo->num;
737
157
        psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
738
739
157
        key[0].length = 1;
740
157
        key[0].key    = &k_interface_id;
741
157
        key[1].length = 1;
742
157
        key[1].key    = &k_adapter_id;
743
157
        key[2].length = 1;
744
157
        key[2].key    = &k_chandle;
745
157
        key[3].length = 1;
746
157
        key[3].key    = &k_cid;
747
157
        key[4].length = 1;
748
157
        key[4].key    = &k_frame_number;
749
157
        key[5].length = 0;
750
157
        key[5].key    = NULL;
751
752
157
        wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
753
157
    }
754
755
158
    if (l2cap_data) {
756
157
        proto_item        *sub_item;
757
157
        uint32_t           bt_uuid = 0;
758
157
        uint32_t           disconnect_in_frame = 0;
759
157
        psm_data_t        *psm_data;
760
157
        wmem_tree_key_t    key[6];
761
157
        uint32_t           k_interface_id;
762
157
        uint32_t           k_adapter_id;
763
157
        uint32_t           k_chandle;
764
157
        uint32_t           k_cid;
765
157
        uint32_t           k_frame_number;
766
157
        uint32_t           interface_id;
767
157
        uint32_t           adapter_id;
768
157
        uint32_t           chandle;
769
770
157
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
771
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
772
157
        else
773
157
            interface_id = HCI_INTERFACE_DEFAULT;
774
157
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
775
157
        chandle      = (acl_data) ? acl_data->chandle : 0;
776
777
157
        k_interface_id = interface_id;
778
157
        k_adapter_id   = adapter_id;
779
157
        k_chandle      = chandle;
780
157
        k_cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x80000000 : 0x00000000);
781
157
        k_frame_number = pinfo->num;
782
783
157
        key[0].length = 1;
784
157
        key[0].key    = &k_interface_id;
785
157
        key[1].length = 1;
786
157
        key[1].key    = &k_adapter_id;
787
157
        key[2].length = 1;
788
157
        key[2].key    = &k_chandle;
789
157
        key[3].length = 1;
790
157
        key[3].key    = &k_cid;
791
157
        key[4].length = 1;
792
157
        key[4].key    = &k_frame_number;
793
157
        key[5].length = 0;
794
157
        key[5].key    = NULL;
795
796
157
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
797
157
        if (psm_data &&
798
157
            psm_data->interface_id == interface_id &&
799
157
            psm_data->adapter_id == adapter_id &&
800
157
            psm_data->chandle == chandle &&
801
157
            psm_data->local_cid == k_cid)
802
157
        {
803
157
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
804
157
            disconnect_in_frame = psm_data->disconnect_in_frame;
805
157
        }
806
807
157
        if (bt_uuid) {
808
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_service, tvb, 0, 0, bt_uuid);
809
0
            proto_item_set_generated(sub_item);
810
0
        }
811
812
157
        if (disconnect_in_frame < bluetooth_max_disconnect_in_frame) {
813
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_disconnect_in_frame, tvb, 0, 0, disconnect_in_frame);
814
0
            proto_item_set_generated(sub_item);
815
0
        }
816
157
    }
817
818
158
    return offset;
819
158
}
820
static int
821
dissect_le_credit_based_connrequest(tvbuff_t *tvb, int offset, packet_info *pinfo,
822
    proto_tree *tree, proto_tree *command_tree, uint16_t cid, uint8_t cmd_ident,
823
    bthci_acl_data_t *acl_data, btl2cap_data_t *l2cap_data)
824
221
{
825
826
221
    proto_item  *psm_item;
827
221
    uint32_t     psm;
828
221
    uint32_t     scid;
829
830
831
221
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_le_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN, &psm);
832
221
    if (psm < 0x80) {
833
44
        psm_item = proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
834
44
        proto_item_set_generated(psm_item);
835
44
    }
836
221
    offset += 2;
837
838
221
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &scid);
839
221
    offset += 2;
840
841
221
    proto_tree_add_item(command_tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
842
221
    offset += 2;
843
844
221
    proto_tree_add_item(command_tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
845
221
    offset += 2;
846
847
221
    proto_tree_add_item(command_tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
848
221
    offset += 2;
849
850
221
    if (!pinfo->fd->visited) {
851
217
        wmem_tree_key_t    key[8];
852
217
        uint32_t           k_interface_id;
853
217
        uint32_t           k_adapter_id;
854
217
        uint32_t           k_chandle;
855
217
        uint32_t           k_cid;
856
217
        uint32_t           k_cmd_ident;
857
217
        uint32_t           k_frame_number;
858
217
        uint32_t           interface_id;
859
217
        uint32_t           adapter_id;
860
217
        uint32_t           chandle;
861
217
        psm_data_t        *psm_data;
862
217
        uint32_t           key_cid;
863
217
        uint32_t           cid_index;
864
865
217
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
866
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
867
217
        else
868
217
            interface_id = HCI_INTERFACE_DEFAULT;
869
217
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
870
217
        chandle = (acl_data) ? acl_data->chandle : 0;
871
872
217
        k_interface_id = interface_id;
873
217
        k_adapter_id = adapter_id;
874
217
        k_chandle = chandle;
875
217
        k_cid = cid;
876
217
        k_cmd_ident = cmd_ident;
877
217
        k_frame_number = pinfo->num;
878
217
        cid_index = 0;
879
880
217
        psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
881
882
217
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
883
0
            key_cid = scid | 0x80000000;
884
0
            psm_data->local_cid = BTL2CAP_UNKNOWN_CID;
885
0
            psm_data->remote_cid = key_cid;
886
0
        }
887
217
        else {
888
217
            key_cid = scid;
889
217
            psm_data->local_cid = key_cid;
890
217
            psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
891
217
        }
892
893
217
        psm_data->psm = psm;
894
217
        psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
895
217
        psm_data->in.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
896
217
        psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
897
217
        psm_data->out.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
898
217
        psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
899
217
        psm_data->interface_id = k_interface_id;
900
217
        psm_data->adapter_id = k_adapter_id;
901
217
        psm_data->chandle = k_chandle;
902
217
        psm_data->connect_in_frame = pinfo->num;
903
217
        psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
904
905
217
        key[0].length = 1;
906
217
        key[0].key = &k_interface_id;
907
217
        key[1].length = 1;
908
217
        key[1].key = &k_adapter_id;
909
217
        key[2].length = 1;
910
217
        key[2].key = &k_chandle;
911
217
        key[3].length = 1;
912
217
        key[3].key = &k_cid;
913
217
        key[4].length = 1;
914
217
        key[4].key = &k_cmd_ident;
915
217
        key[5].length = 1;
916
217
        key[5].key = &k_frame_number;
917
217
        key[6].length = 1;
918
217
        key[6].key = &cid_index;
919
217
        key[7].length = 0;
920
217
        key[7].key = NULL;
921
922
217
        wmem_tree_insert32_array(cmd_ident_to_psm_table, key, psm_data);
923
924
217
        k_cid = key_cid;
925
926
217
        key[4].length = 1;
927
217
        key[4].key = &k_frame_number;
928
217
        key[5].length = 0;
929
217
        key[5].key = NULL;
930
931
217
        wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
932
217
    }
933
934
221
    if (l2cap_data) {
935
217
        proto_item        *sub_item;
936
217
        uint32_t           bt_uuid = 0;
937
217
        uint32_t           disconnect_in_frame = 0;
938
217
        psm_data_t        *psm_data;
939
217
        wmem_tree_key_t    key[6];
940
217
        uint32_t           k_interface_id;
941
217
        uint32_t           k_adapter_id;
942
217
        uint32_t           k_chandle;
943
217
        uint32_t           k_cid;
944
217
        uint32_t           k_frame_number;
945
217
        uint32_t           interface_id;
946
217
        uint32_t           adapter_id;
947
217
        uint32_t           chandle;
948
949
217
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
950
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
951
217
        else
952
217
            interface_id = HCI_INTERFACE_DEFAULT;
953
217
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
954
217
        chandle = (acl_data) ? acl_data->chandle : 0;
955
956
217
        k_interface_id = interface_id;
957
217
        k_adapter_id = adapter_id;
958
217
        k_chandle = chandle;
959
217
        k_cid = scid;
960
217
        k_frame_number = pinfo->num;
961
962
217
        key[0].length = 1;
963
217
        key[0].key = &k_interface_id;
964
217
        key[1].length = 1;
965
217
        key[1].key = &k_adapter_id;
966
217
        key[2].length = 1;
967
217
        key[2].key = &k_chandle;
968
217
        key[3].length = 1;
969
217
        key[3].key = &k_cid;
970
217
        key[4].length = 1;
971
217
        key[4].key = &k_frame_number;
972
217
        key[5].length = 0;
973
217
        key[5].key = NULL;
974
975
217
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
976
217
        if (psm_data &&
977
217
            psm_data->interface_id == interface_id &&
978
217
            psm_data->adapter_id == adapter_id &&
979
217
            psm_data->chandle == chandle &&
980
217
            psm_data->local_cid == k_cid)
981
217
        {
982
217
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
983
217
            disconnect_in_frame = psm_data->disconnect_in_frame;
984
217
        }
985
986
217
        if (bt_uuid) {
987
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_service, tvb, 0, 0, bt_uuid);
988
0
            proto_item_set_generated(sub_item);
989
0
        }
990
991
217
        if (disconnect_in_frame < bluetooth_max_disconnect_in_frame) {
992
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_disconnect_in_frame, tvb, 0, 0, disconnect_in_frame);
993
0
            proto_item_set_generated(sub_item);
994
0
        }
995
217
    }
996
997
221
    return offset;
998
221
}
999
1000
static int
1001
dissect_le_credit_based_connresponse(tvbuff_t *tvb, int offset, packet_info *pinfo,
1002
    proto_tree *tree, uint16_t cid, uint8_t cmd_ident, bthci_acl_data_t *acl_data)
1003
36
{
1004
36
    uint32_t           dcid;
1005
1006
36
    proto_tree_add_item_ret_uint(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &dcid);
1007
36
    offset += 2;
1008
1009
36
    proto_tree_add_item(tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1010
36
    offset += 2;
1011
1012
36
    proto_tree_add_item(tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1013
36
    offset += 2;
1014
1015
36
    proto_tree_add_item(tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1016
36
    offset += 2;
1017
1018
36
    proto_tree_add_item(tree, hf_btl2cap_le_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1019
36
    offset += 2;
1020
1021
1022
36
    if (pinfo->fd->visited == 0) {
1023
36
        psm_data_t        *psm_data;
1024
36
        wmem_tree_key_t    key[8];
1025
36
        uint32_t           k_interface_id;
1026
36
        uint32_t           k_adapter_id;
1027
36
        uint32_t           k_chandle;
1028
36
        uint32_t           k_cid;
1029
36
        uint32_t           k_cmd_ident;
1030
36
        uint32_t           k_frame_number;
1031
36
        uint32_t           interface_id;
1032
36
        uint32_t           adapter_id;
1033
36
        uint32_t           chandle;
1034
36
        uint32_t           key_cid;
1035
36
        uint32_t           cid_index;
1036
1037
36
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1038
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1039
36
        else
1040
36
            interface_id = HCI_INTERFACE_DEFAULT;
1041
36
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1042
36
        chandle = (acl_data) ? acl_data->chandle : 0;
1043
1044
36
        k_interface_id = interface_id;
1045
36
        k_adapter_id = adapter_id;
1046
36
        k_chandle = chandle;
1047
36
        k_cid = cid;
1048
36
        k_cmd_ident = cmd_ident;
1049
36
        k_frame_number = pinfo->num;
1050
36
        cid_index = 0;
1051
1052
36
        key[0].length = 1;
1053
36
        key[0].key = &k_interface_id;
1054
36
        key[1].length = 1;
1055
36
        key[1].key = &k_adapter_id;
1056
36
        key[2].length = 1;
1057
36
        key[2].key = &k_chandle;
1058
36
        key[3].length = 1;
1059
36
        key[3].key = &k_cid;
1060
36
        key[4].length = 1;
1061
36
        key[4].key = &k_cmd_ident;
1062
36
        key[5].length = 1;
1063
36
        key[5].key = &k_frame_number;
1064
36
        key[6].length = 1;
1065
36
        key[6].key = &cid_index;
1066
36
        key[7].length = 0;
1067
36
        key[7].key = NULL;
1068
1069
36
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table, key);
1070
36
        if (psm_data &&
1071
36
            psm_data->interface_id == interface_id &&
1072
36
            psm_data->adapter_id == adapter_id &&
1073
36
            psm_data->chandle == chandle &&
1074
36
            psm_data->disconnect_in_frame > pinfo->num)
1075
32
        {
1076
32
            key_cid = dcid | ((pinfo->p2p_dir != P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1077
1078
32
            k_interface_id = interface_id;
1079
32
            k_adapter_id = adapter_id;
1080
32
            k_chandle = chandle;
1081
32
            k_cid = key_cid;
1082
32
            k_frame_number = pinfo->num;
1083
1084
32
            key[0].length = 1;
1085
32
            key[0].key = &k_interface_id;
1086
32
            key[1].length = 1;
1087
32
            key[1].key = &k_adapter_id;
1088
32
            key[2].length = 1;
1089
32
            key[2].key = &k_chandle;
1090
32
            key[3].length = 1;
1091
32
            key[3].key = &k_cid;
1092
32
            key[4].length = 1;
1093
32
            key[4].key = &k_frame_number;
1094
32
            key[5].length = 0;
1095
32
            key[5].key = NULL;
1096
1097
32
            if (pinfo->p2p_dir == P2P_DIR_RECV)
1098
0
                psm_data->remote_cid = key_cid;
1099
32
            else
1100
32
                psm_data->local_cid = key_cid;
1101
1102
32
            wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1103
32
        }
1104
36
    }
1105
1106
36
    return offset;
1107
36
}
1108
static int
1109
dissect_l2cap_credit_based_connrequest(tvbuff_t *tvb, int offset, packet_info *pinfo,
1110
    proto_tree *tree, proto_tree *command_tree, uint16_t cid, uint8_t cmd_ident,
1111
    uint16_t length, bthci_acl_data_t *acl_data, btl2cap_data_t *l2cap_data)
1112
59
{
1113
1114
59
    proto_item  *psm_item;
1115
59
    uint32_t     psm;
1116
59
    uint32_t     scid;
1117
59
    uint32_t     cid_index;
1118
1119
59
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_le_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN, &psm);
1120
59
    if (psm < 0x80) {
1121
18
        psm_item = proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1122
18
        proto_item_set_generated(psm_item);
1123
18
    }
1124
59
    offset += 2;
1125
1126
59
    proto_tree_add_item(command_tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1127
59
    offset += 2;
1128
1129
59
    proto_tree_add_item(command_tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1130
59
    offset += 2;
1131
1132
59
    proto_tree_add_item(command_tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1133
59
    offset += 2;
1134
1135
59
    cid_index = 0;
1136
4.18k
    while (offset < length + 8) {
1137
4.12k
        proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &scid);
1138
4.12k
        offset += 2;
1139
1140
4.12k
        if (!pinfo->fd->visited) {
1141
4.07k
            wmem_tree_key_t    key[8];
1142
4.07k
            uint32_t           k_interface_id;
1143
4.07k
            uint32_t           k_adapter_id;
1144
4.07k
            uint32_t           k_chandle;
1145
4.07k
            uint32_t           k_cid;
1146
4.07k
            uint32_t           k_cmd_ident;
1147
4.07k
            uint32_t           k_frame_number;
1148
4.07k
            uint32_t           interface_id;
1149
4.07k
            uint32_t           adapter_id;
1150
4.07k
            uint32_t           chandle;
1151
4.07k
            psm_data_t        *psm_data;
1152
4.07k
            uint32_t           key_cid;
1153
1154
4.07k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1155
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1156
4.07k
            else
1157
4.07k
                interface_id = HCI_INTERFACE_DEFAULT;
1158
4.07k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1159
4.07k
            chandle = (acl_data) ? acl_data->chandle : 0;
1160
1161
4.07k
            k_interface_id = interface_id;
1162
4.07k
            k_adapter_id = adapter_id;
1163
4.07k
            k_chandle = chandle;
1164
4.07k
            k_cid = cid;
1165
4.07k
            k_cmd_ident = cmd_ident;
1166
4.07k
            k_frame_number = pinfo->num;
1167
1168
4.07k
            psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
1169
1170
4.07k
            if (pinfo->p2p_dir == P2P_DIR_RECV) {
1171
0
                key_cid = scid | 0x80000000;
1172
0
                psm_data->local_cid = BTL2CAP_UNKNOWN_CID;
1173
0
                psm_data->remote_cid = key_cid;
1174
0
            }
1175
4.07k
            else {
1176
4.07k
                key_cid = scid;
1177
4.07k
                psm_data->local_cid = key_cid;
1178
4.07k
                psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
1179
4.07k
            }
1180
1181
4.07k
            psm_data->psm = psm;
1182
4.07k
            psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
1183
4.07k
            psm_data->in.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
1184
4.07k
            psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
1185
4.07k
            psm_data->out.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
1186
4.07k
            psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
1187
4.07k
            psm_data->interface_id = k_interface_id;
1188
4.07k
            psm_data->adapter_id = k_adapter_id;
1189
4.07k
            psm_data->chandle = k_chandle;
1190
4.07k
            psm_data->connect_in_frame = pinfo->num;
1191
4.07k
            psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
1192
1193
4.07k
            key[0].length = 1;
1194
4.07k
            key[0].key = &k_interface_id;
1195
4.07k
            key[1].length = 1;
1196
4.07k
            key[1].key = &k_adapter_id;
1197
4.07k
            key[2].length = 1;
1198
4.07k
            key[2].key = &k_chandle;
1199
4.07k
            key[3].length = 1;
1200
4.07k
            key[3].key = &k_cid;
1201
4.07k
            key[4].length = 1;
1202
4.07k
            key[4].key = &k_cmd_ident;
1203
4.07k
            key[5].length = 1;
1204
4.07k
            key[5].key = &k_frame_number;
1205
4.07k
            key[6].length = 1;
1206
4.07k
            key[6].key = &cid_index;
1207
4.07k
            key[7].length = 0;
1208
4.07k
            key[7].key = NULL;
1209
1210
4.07k
            wmem_tree_insert32_array(cmd_ident_to_psm_table, key, psm_data);
1211
1212
4.07k
            k_cid = key_cid;
1213
1214
4.07k
            key[4].length = 1;
1215
4.07k
            key[4].key = &k_frame_number;
1216
4.07k
            key[5].length = 0;
1217
4.07k
            key[5].key = NULL;
1218
1219
4.07k
            wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1220
4.07k
        }
1221
1222
4.12k
        if (l2cap_data) {
1223
4.07k
            proto_item        *sub_item;
1224
4.07k
            uint32_t           bt_uuid = 0;
1225
4.07k
            uint32_t           disconnect_in_frame = 0;
1226
4.07k
            psm_data_t        *psm_data;
1227
4.07k
            wmem_tree_key_t    key[6];
1228
4.07k
            uint32_t           k_interface_id;
1229
4.07k
            uint32_t           k_adapter_id;
1230
4.07k
            uint32_t           k_chandle;
1231
4.07k
            uint32_t           k_cid;
1232
4.07k
            uint32_t           k_frame_number;
1233
4.07k
            uint32_t           interface_id;
1234
4.07k
            uint32_t           adapter_id;
1235
4.07k
            uint32_t           chandle;
1236
1237
4.07k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1238
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1239
4.07k
            else
1240
4.07k
                interface_id = HCI_INTERFACE_DEFAULT;
1241
4.07k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1242
4.07k
            chandle = (acl_data) ? acl_data->chandle : 0;
1243
1244
4.07k
            k_interface_id = interface_id;
1245
4.07k
            k_adapter_id = adapter_id;
1246
4.07k
            k_chandle = chandle;
1247
4.07k
            k_cid = scid;
1248
4.07k
            k_frame_number = pinfo->num;
1249
1250
4.07k
            key[0].length = 1;
1251
4.07k
            key[0].key = &k_interface_id;
1252
4.07k
            key[1].length = 1;
1253
4.07k
            key[1].key = &k_adapter_id;
1254
4.07k
            key[2].length = 1;
1255
4.07k
            key[2].key = &k_chandle;
1256
4.07k
            key[3].length = 1;
1257
4.07k
            key[3].key = &k_cid;
1258
4.07k
            key[4].length = 1;
1259
4.07k
            key[4].key = &k_frame_number;
1260
4.07k
            key[5].length = 0;
1261
4.07k
            key[5].key = NULL;
1262
1263
4.07k
            psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1264
4.07k
            if (psm_data &&
1265
4.07k
                psm_data->interface_id == interface_id &&
1266
4.07k
                psm_data->adapter_id == adapter_id &&
1267
4.07k
                psm_data->chandle == chandle &&
1268
4.07k
                psm_data->local_cid == k_cid)
1269
4.07k
            {
1270
4.07k
                bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
1271
4.07k
                disconnect_in_frame = psm_data->disconnect_in_frame;
1272
4.07k
            }
1273
1274
4.07k
            if (bt_uuid) {
1275
0
                sub_item = proto_tree_add_uint(tree, hf_btl2cap_service, tvb, 0, 0, bt_uuid);
1276
0
                proto_item_set_generated(sub_item);
1277
0
            }
1278
1279
4.07k
            if (disconnect_in_frame < bluetooth_max_disconnect_in_frame) {
1280
0
                sub_item = proto_tree_add_uint(tree, hf_btl2cap_disconnect_in_frame, tvb, 0, 0, disconnect_in_frame);
1281
0
                proto_item_set_generated(sub_item);
1282
0
            }
1283
4.07k
        }
1284
1285
4.12k
        cid_index++;
1286
4.12k
    }
1287
59
    return offset;
1288
59
}
1289
1290
static int
1291
dissect_l2cap_credit_based_connresponse(tvbuff_t *tvb, int offset, packet_info *pinfo,
1292
    proto_tree *tree, uint16_t cid, uint8_t cmd_ident, uint16_t length,
1293
    bthci_acl_data_t *acl_data)
1294
28
{
1295
28
    uint32_t           dcid;
1296
28
    uint32_t           cid_index;
1297
1298
28
    proto_tree_add_item(tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1299
28
    offset += 2;
1300
1301
28
    proto_tree_add_item(tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1302
28
    offset += 2;
1303
1304
28
    proto_tree_add_item(tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1305
28
    offset += 2;
1306
1307
28
    proto_tree_add_item(tree, hf_btl2cap_le_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1308
28
    offset += 2;
1309
1310
28
    cid_index = 0;
1311
2.16k
    while (offset < length + 8) {
1312
2.13k
        proto_tree_add_item_ret_uint(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &dcid);
1313
2.13k
        offset += 2;
1314
1315
2.13k
        if (pinfo->fd->visited == 0) {
1316
2.10k
            psm_data_t        *psm_data;
1317
2.10k
            wmem_tree_key_t    key[8];
1318
2.10k
            uint32_t           k_interface_id;
1319
2.10k
            uint32_t           k_adapter_id;
1320
2.10k
            uint32_t           k_chandle;
1321
2.10k
            uint32_t           k_cid;
1322
2.10k
            uint32_t           k_cmd_ident;
1323
2.10k
            uint32_t           k_frame_number;
1324
2.10k
            uint32_t           interface_id;
1325
2.10k
            uint32_t           adapter_id;
1326
2.10k
            uint32_t           chandle;
1327
2.10k
            uint32_t           key_cid;
1328
1329
2.10k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1330
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1331
2.10k
            else
1332
2.10k
                interface_id = HCI_INTERFACE_DEFAULT;
1333
2.10k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1334
2.10k
            chandle = (acl_data) ? acl_data->chandle : 0;
1335
1336
2.10k
            k_interface_id = interface_id;
1337
2.10k
            k_adapter_id = adapter_id;
1338
2.10k
            k_chandle = chandle;
1339
2.10k
            k_cid = cid;
1340
2.10k
            k_cmd_ident = cmd_ident;
1341
2.10k
            k_frame_number = pinfo->num;
1342
1343
2.10k
            key[0].length = 1;
1344
2.10k
            key[0].key = &k_interface_id;
1345
2.10k
            key[1].length = 1;
1346
2.10k
            key[1].key = &k_adapter_id;
1347
2.10k
            key[2].length = 1;
1348
2.10k
            key[2].key = &k_chandle;
1349
2.10k
            key[3].length = 1;
1350
2.10k
            key[3].key = &k_cid;
1351
2.10k
            key[4].length = 1;
1352
2.10k
            key[4].key = &k_cmd_ident;
1353
2.10k
            key[5].length = 1;
1354
2.10k
            key[5].key = &k_frame_number;
1355
2.10k
            key[6].length = 1;
1356
2.10k
            key[6].key = &cid_index;
1357
2.10k
            key[7].length = 0;
1358
2.10k
            key[7].key = NULL;
1359
1360
2.10k
            psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table, key);
1361
2.10k
            if (psm_data &&
1362
2.10k
                psm_data->interface_id == interface_id &&
1363
2.10k
                psm_data->adapter_id == adapter_id &&
1364
2.10k
                psm_data->chandle == chandle &&
1365
2.10k
                psm_data->disconnect_in_frame > pinfo->num)
1366
1.80k
            {
1367
1.80k
                key_cid = dcid | ((pinfo->p2p_dir != P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1368
1369
1.80k
                k_interface_id = interface_id;
1370
1.80k
                k_adapter_id = adapter_id;
1371
1.80k
                k_chandle = chandle;
1372
1.80k
                k_cid = key_cid;
1373
1.80k
                k_frame_number = pinfo->num;
1374
1375
1.80k
                key[0].length = 1;
1376
1.80k
                key[0].key = &k_interface_id;
1377
1.80k
                key[1].length = 1;
1378
1.80k
                key[1].key = &k_adapter_id;
1379
1.80k
                key[2].length = 1;
1380
1.80k
                key[2].key = &k_chandle;
1381
1.80k
                key[3].length = 1;
1382
1.80k
                key[3].key = &k_cid;
1383
1.80k
                key[4].length = 1;
1384
1.80k
                key[4].key = &k_frame_number;
1385
1.80k
                key[5].length = 0;
1386
1.80k
                key[5].key = NULL;
1387
1388
1.80k
                if (pinfo->p2p_dir == P2P_DIR_RECV)
1389
0
                    psm_data->remote_cid = key_cid;
1390
1.80k
                else
1391
1.80k
                    psm_data->local_cid = key_cid;
1392
1393
1.80k
                wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1394
1.80k
            }
1395
2.10k
        }
1396
2.13k
        cid_index++;
1397
2.13k
    }
1398
28
    return offset;
1399
28
}
1400
static int
1401
dissect_movechanrequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1402
103
{
1403
103
    uint16_t icid;
1404
103
    uint8_t ctrl_id;
1405
1406
103
    icid = tvb_get_letohs(tvb, offset);
1407
103
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1408
103
    offset += 2;
1409
1410
103
    ctrl_id = tvb_get_uint8(tvb, offset);
1411
103
    proto_tree_add_item(tree, hf_btl2cap_dcontroller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1412
103
    offset += 1;
1413
1414
103
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, move to %s)", icid,
1415
103
                    val_to_str_const(ctrl_id, ctrl_id_code_vals, "Unknown controller"));
1416
1417
103
    return offset;
1418
103
}
1419
1420
static int
1421
dissect_options(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length, config_data_t *config_data)
1422
78
{
1423
78
    proto_item *ti_option;
1424
78
    proto_tree *ti_option_subtree;
1425
78
    uint8_t     option_type, option_length;
1426
1427
78
    if (config_data) {
1428
0
        config_data->mode     = L2CAP_BASIC_MODE;
1429
0
        config_data->txwindow = 0;
1430
0
    }
1431
1432
1.54k
    while (length > 0) {
1433
1.46k
        option_type   = tvb_get_uint8(tvb, offset);
1434
1.46k
        option_length = tvb_get_uint8(tvb, offset + 1);
1435
1436
1.46k
        ti_option = proto_tree_add_none_format(tree,
1437
1.46k
                hf_btl2cap_option, tvb,
1438
1.46k
                offset, option_length + 2,
1439
1.46k
                "Option: ");
1440
1.46k
        ti_option_subtree = proto_item_add_subtree(ti_option, ett_btl2cap_option);
1441
1.46k
        proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1442
1.46k
        proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_length, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1443
1.46k
        offset += 2;
1444
1445
1.46k
        if (option_length != 0) {
1446
794
            switch (option_type) {
1447
122
            case 0x01: /* MTU */
1448
122
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1449
122
                offset += 2;
1450
1451
122
                proto_item_append_text(ti_option, "MTU");
1452
122
                break;
1453
1454
108
            case 0x02: /* Flush timeout */
1455
108
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flushTO, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1456
108
                offset += 2;
1457
1458
108
                proto_item_append_text(ti_option, "Flush Timeout");
1459
108
                break;
1460
1461
30
            case 0x03: /* QOS */
1462
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1463
30
                offset += 1;
1464
1465
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1466
30
                offset += 1;
1467
1468
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1469
30
                offset += 4;
1470
1471
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenbucketsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1472
30
                offset += 4;
1473
1474
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_peakbandwidth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1475
30
                offset += 4;
1476
1477
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1478
30
                offset += 4;
1479
1480
30
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_delayvariation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1481
30
                offset += 4;
1482
1483
30
                proto_item_append_text(ti_option, "QOS");
1484
30
                break;
1485
1486
32
            case 0x04: /* Retransmission and Flow Control*/
1487
32
                if (config_data)
1488
0
                {
1489
0
                    config_data->mode     = tvb_get_uint8(tvb, offset);
1490
0
                    config_data->txwindow = tvb_get_uint8(tvb, offset + 1);
1491
0
                }
1492
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmissionmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1493
32
                offset += 1;
1494
1495
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_txwindow, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1496
32
                offset += 1;
1497
1498
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_maxtransmit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1499
32
                offset += 1;
1500
1501
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmittimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1502
32
                offset += 2;
1503
1504
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_monitortimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1505
32
                offset += 2;
1506
1507
32
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1508
32
                offset += 2;
1509
1510
32
                proto_item_append_text(ti_option, "Retransmission and Flow Control");
1511
32
                break;
1512
1513
82
            case 0x05: /* FCS */
1514
82
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_fcs, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1515
82
                offset += 1;
1516
1517
82
                proto_item_append_text(ti_option, "FCS");
1518
82
                break;
1519
1520
10
            case 0x06: /* Extended Flow Specification */
1521
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_identifier, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1522
10
                offset += 1;
1523
1524
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1525
10
                offset += 1;
1526
1527
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1528
10
                offset += 2;
1529
1530
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_arrival_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1531
10
                offset += 4;
1532
1533
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_access_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1534
10
                offset += 4;
1535
1536
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flush_to_us, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1537
10
                offset += 4;
1538
1539
10
                proto_item_append_text(ti_option, "Extended Flow Specification");
1540
10
                break;
1541
1542
78
            case 0x07: /* Extended Window Size */
1543
78
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_window, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1544
78
                offset += 2;
1545
1546
78
                proto_item_append_text(ti_option, "Extended Window Size");
1547
78
                break;
1548
1549
332
            default:
1550
332
                proto_item_append_text(ti_option, "unknown");
1551
332
                offset += option_length;
1552
332
                break;
1553
794
            }
1554
794
        }
1555
1.46k
        length -= (option_length + 2);
1556
1.46k
    }
1557
76
    return offset;
1558
78
}
1559
1560
1561
1562
static int
1563
dissect_configrequest(tvbuff_t *tvb, int offset, packet_info *pinfo,
1564
        proto_tree *tree, uint16_t length, bthci_acl_data_t *acl_data)
1565
42
{
1566
42
    uint16_t dcid;
1567
1568
42
    dcid = tvb_get_letohs(tvb, offset);
1569
1570
42
    proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1571
42
    offset += 2;
1572
1573
42
    col_append_fstr(pinfo->cinfo, COL_INFO, " (DCID: 0x%04x)", dcid);
1574
1575
42
    proto_tree_add_item(tree, hf_btl2cap_flags_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1576
42
    proto_tree_add_item(tree, hf_btl2cap_flags_continuation, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1577
42
    offset += 2;
1578
1579
42
    {
1580
42
        psm_data_t        *psm_data;
1581
42
        config_data_t     *config_data;
1582
42
        wmem_tree_key_t    key[6];
1583
42
        uint32_t           k_interface_id;
1584
42
        uint32_t           k_adapter_id;
1585
42
        uint32_t           k_chandle;
1586
42
        uint32_t           k_cid;
1587
42
        uint32_t           k_frame_number;
1588
42
        uint32_t           interface_id;
1589
42
        uint32_t           adapter_id;
1590
42
        uint32_t           chandle;
1591
42
        uint32_t           cid;
1592
1593
42
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1594
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1595
42
        else
1596
42
            interface_id = HCI_INTERFACE_DEFAULT;
1597
42
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1598
42
        chandle      = (acl_data) ? acl_data->chandle : 0;
1599
42
        cid          = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1600
1601
42
        k_interface_id = interface_id;
1602
42
        k_adapter_id   = adapter_id;
1603
42
        k_chandle      = chandle;
1604
42
        k_cid          = cid;
1605
42
        k_frame_number = pinfo->num;
1606
1607
42
        key[0].length = 1;
1608
42
        key[0].key    = &k_interface_id;
1609
42
        key[1].length = 1;
1610
42
        key[1].key    = &k_adapter_id;
1611
42
        key[2].length = 1;
1612
42
        key[2].key    = &k_chandle;
1613
42
        key[3].length = 1;
1614
42
        key[3].key    = &k_cid;
1615
42
        key[4].length = 1;
1616
42
        key[4].key    = &k_frame_number;
1617
42
        key[5].length = 0;
1618
42
        key[5].key    = NULL;
1619
1620
42
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1621
42
        if (psm_data &&
1622
42
            psm_data->interface_id == interface_id &&
1623
42
            psm_data->adapter_id == adapter_id &&
1624
42
            psm_data->chandle == chandle &&
1625
42
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->remote_cid == cid) ||
1626
41
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->local_cid == cid)) &&
1627
42
            psm_data->disconnect_in_frame > pinfo->num)
1628
0
        {
1629
0
            if (pinfo->p2p_dir == P2P_DIR_RECV)
1630
0
                config_data = &(psm_data->out);
1631
0
            else
1632
0
                config_data = &(psm_data->in);
1633
42
        } else {
1634
42
            config_data = NULL;
1635
42
        }
1636
42
        if (config_data != NULL) {
1637
            /* Reset config_data that might have been set by an earlier
1638
             * Configure Request that failed.
1639
             */
1640
0
            config_data->mode     = L2CAP_BASIC_MODE;
1641
0
            config_data->txwindow = 0;
1642
0
        }
1643
42
        if (tvb_reported_length_remaining(tvb, offset) > 0) {
1644
40
            offset = dissect_options(tvb, offset, pinfo, tree, length - 4, config_data);
1645
40
        }
1646
42
    }
1647
1648
42
    return offset;
1649
42
}
1650
1651
1652
static int
1653
dissect_inforequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1654
29
{
1655
29
    uint16_t info_type;
1656
1657
29
    info_type = tvb_get_letohs(tvb, offset);
1658
29
    proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1659
29
    offset   += 2;
1660
1661
29
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(info_type, info_type_vals, "Unknown type"));
1662
29
    return offset;
1663
29
}
1664
1665
static int
1666
dissect_inforesponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1667
2
{
1668
2
    uint16_t    info_type, result;
1669
1670
2
    info_type = tvb_get_letohs(tvb, offset);
1671
2
    proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1672
2
    offset   += 2;
1673
1674
2
    result    = tvb_get_letohs(tvb, offset);
1675
2
    proto_tree_add_item(tree, hf_btl2cap_info_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1676
2
    offset   += 2;
1677
1678
2
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, %s)",
1679
2
                        val_to_str_const(info_type, info_type_vals, "Unknown type"),
1680
2
                        val_to_str_const(result, info_result_vals, "Unknown result"));
1681
1682
2
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
1683
1
        proto_item *ti_features;
1684
1
        proto_tree *ti_features_subtree;
1685
1
        uint32_t    features;
1686
1687
1
        switch (info_type) {
1688
0
        case 0x0001: /* Connectionless MTU */
1689
0
            proto_tree_add_item(tree, hf_btl2cap_info_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1690
0
            offset += 2;
1691
1692
0
            break;
1693
0
        case 0x0002: /* Extended Features */
1694
0
            ti_features = proto_tree_add_none_format(tree,
1695
0
                    hf_btl2cap_info_extfeatures, tvb,
1696
0
                    offset, 4,
1697
0
                    "Features: ");
1698
0
            ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_extfeatures);
1699
0
            features = tvb_get_letohl(tvb, offset);
1700
0
            if (features & 0x1)
1701
0
                proto_item_append_text(ti_features, "FlowControl ");
1702
0
            if (features & 0x2)
1703
0
                proto_item_append_text(ti_features, "Retransmission ");
1704
0
            if (features & 0x4)
1705
0
                proto_item_append_text(ti_features, "BiDirQOS ");
1706
0
            if (features & 0x8)
1707
0
                proto_item_append_text(ti_features, "EnhRetransmission ");
1708
0
            if (features & 0x10)
1709
0
                proto_item_append_text(ti_features, "Streaming ");
1710
0
            if (features & 0x20)
1711
0
                proto_item_append_text(ti_features, "FCS ");
1712
0
            if (features & 0x40)
1713
0
                proto_item_append_text(ti_features, "FlowSpec ");
1714
0
            if (features & 0x80)
1715
0
                proto_item_append_text(ti_features, "FixedChan ");
1716
0
            if (features & 0x100)
1717
0
                proto_item_append_text(ti_features, "WindowSize ");
1718
0
            if (features & 0x200)
1719
0
                proto_item_append_text(ti_features, "Unicast ");
1720
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flowcontrol,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
1721
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_retransmission,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
1722
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_bidirqos,            tvb, offset, 4, ENC_LITTLE_ENDIAN);
1723
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_enh_retransmission,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
1724
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_streaming,           tvb, offset, 4, ENC_LITTLE_ENDIAN);
1725
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fcs,                 tvb, offset, 4, ENC_LITTLE_ENDIAN);
1726
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flow_spec,           tvb, offset, 4, ENC_LITTLE_ENDIAN);
1727
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchan,           tvb, offset, 4, ENC_LITTLE_ENDIAN);
1728
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_window,              tvb, offset, 4, ENC_LITTLE_ENDIAN);
1729
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_unicast,             tvb, offset, 4, ENC_LITTLE_ENDIAN);
1730
0
            offset += 4;
1731
1732
0
            break;
1733
1734
0
        case 0x0003: /* Fixed Channels Supported */
1735
0
            ti_features = proto_tree_add_none_format(tree,
1736
0
                    hf_btl2cap_info_fixedchans, tvb,
1737
0
                    offset, 8,
1738
0
                    "Fixed Channels Supported:");
1739
0
            ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_fixedchans);
1740
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_null,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
1741
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_signal,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
1742
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_connless, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1743
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_man,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
1744
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_rfu,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
1745
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_smp,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
1746
0
            offset += 4;
1747
0
            proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_test, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1748
0
            offset += 4;
1749
1750
0
            break;
1751
1752
1
        default:
1753
1
            proto_tree_add_item(tree, hf_btl2cap_cmd_data, tvb, offset, -1, ENC_NA);
1754
1
            offset += tvb_reported_length_remaining(tvb, offset);
1755
1756
1
            break;
1757
1
        }
1758
1
    }
1759
1760
2
    return offset;
1761
2
}
1762
1763
static int
1764
dissect_configresponse(tvbuff_t *tvb, int offset, packet_info *pinfo,
1765
        proto_tree *tree, uint16_t length, bthci_acl_data_t *acl_data)
1766
38
{
1767
38
    uint16_t           scid;
1768
38
    uint16_t           result;
1769
1770
1771
38
    scid = tvb_get_letohs(tvb, offset);
1772
1773
38
    proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1774
38
    offset += 2;
1775
1776
38
    proto_tree_add_item(tree, hf_btl2cap_flags_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1777
38
    proto_tree_add_item(tree, hf_btl2cap_flags_continuation, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1778
38
    offset += 2;
1779
1780
38
    result = tvb_get_letohs(tvb, offset);
1781
38
    proto_tree_add_item(tree, hf_btl2cap_configuration_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1782
38
    offset += 2;
1783
1784
38
    col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
1785
38
                    val_to_str_const(result, configuration_result_vals, "Unknown"), scid);
1786
1787
38
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
1788
38
        psm_data_t        *psm_data;
1789
38
        config_data_t     *config_data;
1790
38
        wmem_tree_key_t    key[6];
1791
38
        uint32_t           k_interface_id;
1792
38
        uint32_t           k_adapter_id;
1793
38
        uint32_t           k_chandle;
1794
38
        uint32_t           k_cid;
1795
38
        uint32_t           k_frame_number;
1796
38
        uint32_t           interface_id;
1797
38
        uint32_t           adapter_id;
1798
38
        uint32_t           chandle;
1799
38
        uint32_t           cid;
1800
1801
38
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1802
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1803
38
        else
1804
38
            interface_id = HCI_INTERFACE_DEFAULT;
1805
38
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1806
38
        chandle      = (acl_data) ? acl_data->chandle : 0;
1807
38
        cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1808
1809
38
        k_interface_id = interface_id;
1810
38
        k_adapter_id   = adapter_id;
1811
38
        k_chandle      = chandle;
1812
38
        k_cid          = cid;
1813
38
        k_frame_number = pinfo->num;
1814
1815
38
        key[0].length = 1;
1816
38
        key[0].key    = &k_interface_id;
1817
38
        key[1].length = 1;
1818
38
        key[1].key    = &k_adapter_id;
1819
38
        key[2].length = 1;
1820
38
        key[2].key    = &k_chandle;
1821
38
        key[3].length = 1;
1822
38
        key[3].key    = &k_cid;
1823
38
        key[4].length = 1;
1824
38
        key[4].key    = &k_frame_number;
1825
38
        key[5].length = 0;
1826
38
        key[5].key    = NULL;
1827
1828
38
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1829
38
        if (psm_data &&
1830
38
            psm_data->interface_id == interface_id &&
1831
38
            psm_data->adapter_id == adapter_id &&
1832
38
            psm_data->chandle == chandle &&
1833
38
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->local_cid == cid) ||
1834
38
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->remote_cid == cid)) &&
1835
38
            psm_data->disconnect_in_frame > pinfo->num)
1836
0
        {
1837
0
            if (pinfo->p2p_dir == P2P_DIR_RECV)
1838
0
                config_data = &(psm_data->out);
1839
0
            else
1840
0
                config_data = &(psm_data->in);
1841
38
        } else {
1842
38
            config_data = NULL;
1843
38
        }
1844
38
        offset = dissect_options(tvb, offset, pinfo, tree, length - 6, config_data);
1845
38
    }
1846
1847
38
    return offset;
1848
38
}
1849
1850
static int
1851
dissect_connresponse(tvbuff_t *tvb, int offset, packet_info *pinfo,
1852
        proto_tree *tree, bthci_acl_data_t *acl_data)
1853
53
{
1854
53
    uint16_t           scid, dcid, result;
1855
1856
53
    dcid = tvb_get_letohs(tvb, offset);
1857
53
    proto_tree_add_item(tree, hf_btl2cap_dcid,   tvb, offset, 2, ENC_LITTLE_ENDIAN);
1858
53
    offset += 2;
1859
1860
53
    scid = tvb_get_letohs(tvb, offset);
1861
53
    proto_tree_add_item(tree, hf_btl2cap_scid,   tvb, offset, 2, ENC_LITTLE_ENDIAN);
1862
53
    offset += 2;
1863
1864
53
    result = tvb_get_letohs(tvb, offset);
1865
53
    proto_tree_add_item(tree, hf_btl2cap_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1866
53
    offset += 2;
1867
1868
53
    proto_tree_add_item(tree, hf_btl2cap_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1869
53
    offset += 2;
1870
1871
53
    if (result == 0) {
1872
4
        col_append_fstr(pinfo->cinfo, COL_INFO, " - Success (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
1873
4
    }
1874
49
    else {
1875
49
        col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
1876
49
                        val_to_str_const(result, result_vals, "Unknown"), scid);
1877
49
    }
1878
1879
53
    if (pinfo->fd->visited == 0) {
1880
52
        psm_data_t        *psm_data;
1881
52
        wmem_tree_key_t    key[6];
1882
52
        uint32_t           k_interface_id;
1883
52
        uint32_t           k_adapter_id;
1884
52
        uint32_t           k_chandle;
1885
52
        uint32_t           k_cid;
1886
52
        uint32_t           k_frame_number;
1887
52
        uint32_t           interface_id;
1888
52
        uint32_t           adapter_id;
1889
52
        uint32_t           chandle;
1890
52
        uint32_t           cid;
1891
1892
52
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1893
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1894
52
        else
1895
52
            interface_id = HCI_INTERFACE_DEFAULT;
1896
52
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1897
52
        chandle      = (acl_data) ? acl_data->chandle : 0;
1898
52
        cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1899
1900
52
        k_interface_id = interface_id;
1901
52
        k_adapter_id   = adapter_id;
1902
52
        k_chandle      = chandle;
1903
52
        k_cid          = cid;
1904
52
        k_frame_number = pinfo->num;
1905
1906
52
        key[0].length = 1;
1907
52
        key[0].key    = &k_interface_id;
1908
52
        key[1].length = 1;
1909
52
        key[1].key    = &k_adapter_id;
1910
52
        key[2].length = 1;
1911
52
        key[2].key    = &k_chandle;
1912
52
        key[3].length = 1;
1913
52
        key[3].key    = &k_cid;
1914
52
        key[4].length = 1;
1915
52
        key[4].key    = &k_frame_number;
1916
52
        key[5].length = 0;
1917
52
        key[5].key    = NULL;
1918
1919
52
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1920
52
        if (psm_data &&
1921
52
            psm_data->interface_id == interface_id &&
1922
52
            psm_data->adapter_id == adapter_id &&
1923
52
            psm_data->chandle == chandle &&
1924
52
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->remote_cid == cid) ||
1925
52
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->local_cid == cid)) &&
1926
52
            psm_data->disconnect_in_frame > pinfo->num)
1927
0
        {
1928
0
            cid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x80000000 : 0x00000000);
1929
1930
0
            k_interface_id = interface_id;
1931
0
            k_adapter_id   = adapter_id;
1932
0
            k_chandle      = chandle;
1933
0
            k_cid          = cid;
1934
0
            k_frame_number = pinfo->num;
1935
1936
0
            key[0].length = 1;
1937
0
            key[0].key    = &k_interface_id;
1938
0
            key[1].length = 1;
1939
0
            key[1].key    = &k_adapter_id;
1940
0
            key[2].length = 1;
1941
0
            key[2].key    = &k_chandle;
1942
0
            key[3].length = 1;
1943
0
            key[3].key    = &k_cid;
1944
0
            key[4].length = 1;
1945
0
            key[4].key    = &k_frame_number;
1946
0
            key[5].length = 0;
1947
0
            key[5].key    = NULL;
1948
1949
0
            if (pinfo->p2p_dir == P2P_DIR_RECV)
1950
0
                psm_data->remote_cid = cid;
1951
0
            else
1952
0
                psm_data->local_cid = cid;
1953
1954
0
            wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1955
0
        }
1956
52
    }
1957
1958
53
    return offset;
1959
53
}
1960
1961
static int
1962
dissect_chanresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, bthci_acl_data_t *acl_data)
1963
18
{
1964
18
    return dissect_connresponse(tvb, offset, pinfo, tree, acl_data);
1965
18
}
1966
1967
static int
1968
dissect_movechanresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1969
22
{
1970
22
    uint16_t icid, result;
1971
1972
22
    icid = tvb_get_letohs(tvb, offset);
1973
22
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1974
22
    offset += 2;
1975
1976
22
    result = tvb_get_letohs(tvb, offset);
1977
22
    proto_tree_add_item(tree, hf_btl2cap_move_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1978
22
    offset += 2;
1979
1980
22
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
1981
22
                    val_to_str_const(result, move_result_vals, "Unknown result"));
1982
1983
22
    return offset;
1984
22
}
1985
1986
static int
1987
dissect_movechanconfirmation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1988
82
{
1989
82
    uint16_t icid, result;
1990
1991
82
    icid = tvb_get_letohs(tvb, offset);
1992
82
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1993
82
    offset += 2;
1994
1995
82
    result = tvb_get_letohs(tvb, offset);
1996
82
    proto_tree_add_item(tree, hf_btl2cap_move_confirmation_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1997
82
    offset += 2;
1998
1999
82
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
2000
82
                    val_to_str_const(result, move_result_confirmation_vals, "Unknown result"));
2001
2002
82
    return offset;
2003
82
}
2004
2005
static int
2006
dissect_movechanconfirmationresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2007
191
{
2008
191
    uint16_t icid;
2009
2010
191
    icid = tvb_get_letohs(tvb, offset);
2011
191
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2012
191
    offset += 2;
2013
2014
191
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x)", icid);
2015
191
    return offset;
2016
191
}
2017
2018
static int
2019
dissect_connparamrequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2020
42
{
2021
42
    proto_item *item;
2022
42
    uint16_t max_interval, peripheral_latency;
2023
2024
42
    item = proto_tree_add_item(tree, hf_btl2cap_min_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2025
42
    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
2026
42
    offset += 2;
2027
42
    item = proto_tree_add_item(tree, hf_btl2cap_max_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2028
42
    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
2029
42
    max_interval = tvb_get_letohs(tvb, offset);
2030
42
    offset += 2;
2031
42
    item = proto_tree_add_item(tree, hf_btl2cap_peripheral_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2032
42
    peripheral_latency = tvb_get_letohs(tvb, offset);
2033
2034
42
    if(peripheral_latency >= 500 || max_interval == 0 ||
2035
42
       peripheral_latency > 10.0 * tvb_get_letohs(tvb, offset + 2) / (max_interval *1.25))
2036
38
        expert_add_info(pinfo, item, &ei_btl2cap_parameter_mismatch);
2037
2038
42
    offset += 2;
2039
42
    item = proto_tree_add_item(tree, hf_btl2cap_timeout_multiplier, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2040
42
    proto_item_append_text(item, " (%g sec)",  tvb_get_letohs(tvb, offset) * 0.01);
2041
42
    offset += 2;
2042
2043
42
    return offset;
2044
42
}
2045
2046
static int
2047
dissect_connparamresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2048
50
{
2049
50
    uint16_t result;
2050
2051
50
    result = tvb_get_letohs(tvb, offset);
2052
50
    proto_tree_add_item(tree, hf_btl2cap_conn_param_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2053
50
    offset += 2;
2054
2055
50
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
2056
50
                    val_to_str_const(result, conn_param_result_vals, "Unknown result"));
2057
2058
50
    return offset;
2059
50
}
2060
2061
static int
2062
dissect_disconnrequestresponse(tvbuff_t *tvb, int offset, packet_info *pinfo,
2063
        proto_tree *tree, proto_tree *command_tree, bthci_acl_data_t *acl_data, btl2cap_data_t *l2cap_data,
2064
        bool is_request)
2065
348
{
2066
348
    uint16_t      scid;
2067
348
    uint16_t      dcid;
2068
348
    unsigned      psm = 0;
2069
348
    const char   *service_name = "Unknown";
2070
2071
348
    dcid = tvb_get_letohs(tvb, offset);
2072
348
    proto_tree_add_item(command_tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2073
348
    offset += 2;
2074
2075
348
    scid = tvb_get_letohs(tvb, offset);
2076
348
    proto_tree_add_item(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2077
348
    offset += 2;
2078
2079
348
    if (!pinfo->fd->visited) {
2080
348
        psm_data_t        *psm_data;
2081
348
        wmem_tree_key_t    key[6];
2082
348
        uint32_t           k_interface_id;
2083
348
        uint32_t           k_adapter_id;
2084
348
        uint32_t           k_chandle;
2085
348
        uint32_t           k_cid;
2086
348
        uint32_t           k_frame_number;
2087
348
        uint32_t           interface_id;
2088
348
        uint32_t           adapter_id;
2089
348
        uint32_t           chandle;
2090
348
        uint32_t           key_scid;
2091
348
        uint32_t           key_dcid;
2092
2093
348
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2094
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2095
348
        else
2096
348
            interface_id = HCI_INTERFACE_DEFAULT;
2097
348
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
2098
348
        chandle      = (acl_data) ? acl_data->chandle : 0;
2099
348
        if ((is_request && pinfo->p2p_dir == P2P_DIR_SENT) ||
2100
348
                (!is_request && pinfo->p2p_dir == P2P_DIR_RECV)) {
2101
0
            key_dcid     = dcid | 0x80000000;
2102
0
            key_scid     = scid;
2103
348
        } else {
2104
348
            key_dcid     = scid | 0x80000000;
2105
348
            key_scid     = dcid;
2106
348
        }
2107
2108
348
        k_interface_id = interface_id;
2109
348
        k_adapter_id   = adapter_id;
2110
348
        k_chandle      = chandle;
2111
348
        k_cid          = key_dcid;
2112
348
        k_frame_number = pinfo->num;
2113
2114
348
        key[0].length = 1;
2115
348
        key[0].key    = &k_interface_id;
2116
348
        key[1].length = 1;
2117
348
        key[1].key    = &k_adapter_id;
2118
348
        key[2].length = 1;
2119
348
        key[2].key    = &k_chandle;
2120
348
        key[3].length = 1;
2121
348
        key[3].key    = &k_cid;
2122
348
        key[4].length = 1;
2123
348
        key[4].key    = &k_frame_number;
2124
348
        key[5].length = 0;
2125
348
        key[5].key    = NULL;
2126
2127
348
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2128
348
        if (psm_data &&
2129
348
            psm_data->interface_id == interface_id &&
2130
348
            psm_data->adapter_id == adapter_id &&
2131
348
            psm_data->chandle == chandle &&
2132
348
            psm_data->remote_cid == key_dcid &&
2133
348
            psm_data->disconnect_in_frame == bluetooth_max_disconnect_in_frame)
2134
0
        {
2135
0
            psm_data->disconnect_in_frame = pinfo->num;
2136
0
        }
2137
2138
348
        k_interface_id = interface_id;
2139
348
        k_adapter_id   = adapter_id;
2140
348
        k_chandle      = chandle;
2141
348
        k_cid          = key_scid;
2142
348
        k_frame_number = pinfo->num;
2143
2144
348
        key[0].length = 1;
2145
348
        key[0].key    = &k_interface_id;
2146
348
        key[1].length = 1;
2147
348
        key[1].key    = &k_adapter_id;
2148
348
        key[2].length = 1;
2149
348
        key[2].key    = &k_chandle;
2150
348
        key[3].length = 1;
2151
348
        key[3].key    = &k_cid;
2152
348
        key[4].length = 1;
2153
348
        key[4].key    = &k_frame_number;
2154
348
        key[5].length = 0;
2155
348
        key[5].key    = NULL;
2156
2157
348
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2158
348
        if (psm_data &&
2159
348
            psm_data->interface_id == interface_id &&
2160
348
            psm_data->adapter_id == adapter_id &&
2161
348
            psm_data->chandle == chandle &&
2162
348
            psm_data->local_cid == key_scid &&
2163
348
            psm_data->disconnect_in_frame == bluetooth_max_disconnect_in_frame)
2164
56
        {
2165
56
            psm_data->disconnect_in_frame = pinfo->num;
2166
56
        }
2167
348
    }
2168
2169
348
    if (l2cap_data) {
2170
348
        proto_item        *sub_item;
2171
348
        uint32_t           bt_uuid = 0;
2172
348
        uint32_t           connect_in_frame = 0;
2173
348
        psm_data_t        *psm_data;
2174
348
        wmem_tree_key_t    key[6];
2175
348
        uint32_t           k_interface_id;
2176
348
        uint32_t           k_adapter_id;
2177
348
        uint32_t           k_chandle;
2178
348
        uint32_t           k_cid;
2179
348
        uint32_t           k_frame_number;
2180
348
        uint32_t           interface_id;
2181
348
        uint32_t           adapter_id;
2182
348
        uint32_t           chandle;
2183
348
        uint32_t           key_dcid;
2184
2185
348
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2186
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2187
348
        else
2188
348
            interface_id = HCI_INTERFACE_DEFAULT;
2189
348
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
2190
348
        chandle      = (acl_data) ? acl_data->chandle : 0;
2191
348
        if ((is_request && pinfo->p2p_dir == P2P_DIR_SENT) ||
2192
348
                (!is_request && pinfo->p2p_dir == P2P_DIR_RECV)) {
2193
0
            key_dcid     = dcid | 0x80000000;
2194
348
        } else {
2195
348
            key_dcid     = scid | 0x80000000;
2196
348
        }
2197
2198
348
        k_interface_id = interface_id;
2199
348
        k_adapter_id   = adapter_id;
2200
348
        k_chandle      = chandle;
2201
348
        k_cid          = key_dcid;
2202
348
        k_frame_number = pinfo->num;
2203
2204
348
        key[0].length = 1;
2205
348
        key[0].key    = &k_interface_id;
2206
348
        key[1].length = 1;
2207
348
        key[1].key    = &k_adapter_id;
2208
348
        key[2].length = 1;
2209
348
        key[2].key    = &k_chandle;
2210
348
        key[3].length = 1;
2211
348
        key[3].key    = &k_cid;
2212
348
        key[4].length = 1;
2213
348
        key[4].key    = &k_frame_number;
2214
348
        key[5].length = 0;
2215
348
        key[5].key    = NULL;
2216
2217
348
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2218
348
        if (psm_data &&
2219
348
            psm_data->interface_id == interface_id &&
2220
348
            psm_data->adapter_id == adapter_id &&
2221
348
            psm_data->chandle == chandle &&
2222
348
            psm_data->remote_cid == key_dcid)
2223
0
        {
2224
0
            psm = psm_data->psm;
2225
0
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
2226
0
            connect_in_frame = psm_data->connect_in_frame;
2227
0
        }
2228
2229
348
        if (bt_uuid) {
2230
0
            bluetooth_uuid_t   uuid;
2231
2232
0
            uuid.size = 2;
2233
0
            uuid.bt_uuid = bt_uuid;
2234
0
            uuid.data[0] = bt_uuid >> 8;
2235
0
            uuid.data[1] = bt_uuid & 0xFF;
2236
2237
0
            service_name = val_to_str_ext_const(uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown");
2238
0
        }
2239
2240
348
        if (strcmp(service_name, "Unknown") == 0) {
2241
348
            service_name = val_to_str_const(psm, psm_vals, "Unknown");
2242
348
        }
2243
2244
348
        if (psm > 0) {
2245
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_psm, tvb, offset, 0, psm);
2246
0
            proto_item_set_generated(sub_item);
2247
0
        }
2248
2249
348
        if (bt_uuid) {
2250
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_service, tvb, 0, 0, bt_uuid);
2251
0
            proto_item_set_generated(sub_item);
2252
0
        }
2253
2254
348
        if (connect_in_frame > 0) {
2255
0
            sub_item = proto_tree_add_uint(tree, hf_btl2cap_connect_in_frame, tvb, 0, 0, connect_in_frame);
2256
0
            proto_item_set_generated(sub_item);
2257
0
        }
2258
348
    }
2259
2260
348
    if (psm > 0)
2261
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x, DCID: 0x%04x, PSM: 0x%04x, Service: %s)", scid, dcid, psm, service_name);
2262
348
    else
2263
348
        col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x, DCID: 0x%04x, PSM: Unknown, Service: %s)", scid, dcid, service_name);
2264
2265
2266
348
    return offset;
2267
348
}
2268
2269
static int
2270
dissect_b_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2271
        proto_tree *btl2cap_tree, uint16_t cid, uint16_t psm,
2272
        bool is_local_psm, uint16_t length, int offset, btl2cap_data_t *l2cap_data)
2273
52
{
2274
52
    tvbuff_t *next_tvb;
2275
2276
52
    next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), length);
2277
2278
52
    col_append_str(pinfo->cinfo, COL_INFO, "Connection oriented channel");
2279
2280
52
    if (psm) {
2281
0
        proto_item        *psm_item;
2282
0
        uint16_t           bt_uuid;
2283
0
        bluetooth_uuid_t   uuid;
2284
2285
0
        if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
2286
0
            uint16_t *value_data;
2287
2288
0
            value_data = wmem_new(wmem_file_scope(), uint16_t);
2289
0
            *value_data = psm;
2290
2291
0
            p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
2292
0
        }
2293
2294
0
        bt_uuid = get_service_uuid(pinfo, l2cap_data, psm, is_local_psm);
2295
2296
0
        uuid.size = 2;
2297
0
        uuid.bt_uuid = bt_uuid;
2298
0
        uuid.data[0] = bt_uuid >> 8;
2299
0
        uuid.data[1] = bt_uuid & 0xFF;
2300
2301
0
        if (bt_uuid && p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
2302
0
            char *value_data;
2303
2304
0
            value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &uuid));
2305
2306
0
            p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
2307
0
        }
2308
2309
0
        if (psm < BTL2CAP_DYNAMIC_PSM_START) {
2310
0
            psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
2311
0
        }
2312
0
        else {
2313
0
            psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
2314
0
            if (uuid.bt_uuid)
2315
0
                proto_item_append_text(psm_item, ": %s",
2316
0
                                       val_to_str_ext_const(uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown service"));
2317
0
        }
2318
0
        proto_item_set_generated(psm_item);
2319
2320
        /* call next dissector */
2321
0
        if (!dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t) cid, next_tvb, pinfo, tree, true, l2cap_data)) {
2322
0
            if (!dissector_try_uint_with_data(l2cap_psm_dissector_table, (uint32_t) psm, next_tvb, pinfo, tree, true, l2cap_data)) {
2323
                /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2324
0
                if (!dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &uuid), next_tvb, pinfo, tree, true,l2cap_data)) {
2325
                    /* unknown protocol. declare as data */
2326
0
                    proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2327
0
                }
2328
0
            }
2329
0
        }
2330
0
        offset = tvb_captured_length(tvb);
2331
52
    } else {
2332
52
        if (!dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t) cid, next_tvb, pinfo, tree, true, l2cap_data))
2333
52
            proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2334
52
        offset = tvb_captured_length(tvb);
2335
52
    }
2336
52
    return offset;
2337
52
}
2338
2339
/* An LE-frame is a PDU used in LE Credit Based Flow Control Mode. It
2340
 * contains an SDU segment and additional protocol information, encapsulated
2341
 * by a Basic L2CAP header.
2342
 */
2343
static int
2344
dissect_le_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2345
    proto_tree *btl2cap_tree, uint16_t cid, uint16_t psm, bool is_local_psm,
2346
    uint16_t length, int offset, config_data_t *config_data, btl2cap_data_t *l2cap_data,
2347
    bool is_retransmit)
2348
0
{
2349
2350
0
    tvbuff_t *new_tvb = NULL;
2351
0
    bluetooth_uuid_t   uuid;
2352
0
    btl2cap_frame_data_t *btl2cap_frame_data = NULL;
2353
0
    fragment_head *frag_btl2cap_le_sdu = NULL;
2354
2355
0
    if ((!pinfo->fd->visited) && (config_data) && !is_retransmit) {
2356
0
        btl2cap_frame_data = wmem_new0(wmem_file_scope(), btl2cap_frame_data_t);
2357
0
        if (config_data->segmentation_started == 1) {
2358
0
            config_data->segment_len_rem = config_data->segment_len_rem - length;
2359
0
            if (config_data->segment_len_rem > 0) {
2360
0
                btl2cap_frame_data->more_fragments = 1;
2361
0
            } else {
2362
0
                btl2cap_frame_data->more_fragments = 0;
2363
0
                config_data->segmentation_started = 0;
2364
0
                config_data->segment_len_rem = 0;
2365
0
            }
2366
0
        } else {
2367
            /* First Frame in this SDU, SDU length is present */
2368
0
            uint16_t sdu_length;
2369
2370
0
            sdu_length = tvb_get_letohs(tvb, offset);
2371
0
            btl2cap_frame_data->first_fragment = 1;
2372
0
            if (sdu_length == length - 2) {
2373
                /* Complete SDU no segmentation */
2374
0
                btl2cap_frame_data->more_fragments = 0;
2375
0
                config_data->segmentation_started = 0;
2376
0
                config_data->segment_len_rem = 0;
2377
0
            } else {
2378
0
                btl2cap_frame_data->more_fragments = 1;
2379
0
                config_data->segmentation_started = 1;
2380
0
                config_data->segment_len_rem = sdu_length - (length - 2);
2381
0
            }
2382
0
        }
2383
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_btl2cap, pinfo->curr_layer_num, btl2cap_frame_data);
2384
0
    } else {
2385
        /* Not the first pass */
2386
0
        btl2cap_frame_data = (btl2cap_frame_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_btl2cap, pinfo->curr_layer_num);
2387
0
    }
2388
2389
0
    col_append_str(pinfo->cinfo, COL_INFO, "Connection oriented channel, LE Information frame");
2390
2391
0
    if (!btl2cap_frame_data) {
2392
        /* Without frame data we do not have enough information to dissect the packet */
2393
0
        proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2394
0
        return tvb_captured_length(tvb);
2395
0
    }
2396
2397
2398
0
    if (psm) {
2399
0
        proto_item        *psm_item;
2400
0
        uint16_t           bt_uuid;
2401
2402
0
        if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM) == NULL) {
2403
0
            uint16_t *value_data;
2404
2405
0
            value_data = wmem_new(wmem_file_scope(), uint16_t);
2406
0
            *value_data = psm;
2407
2408
0
            p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
2409
0
        }
2410
2411
0
        bt_uuid = get_service_uuid(pinfo, l2cap_data, psm, is_local_psm);
2412
2413
0
        uuid.size = 2;
2414
0
        uuid.bt_uuid = bt_uuid;
2415
0
        uuid.data[0] = bt_uuid >> 8;
2416
0
        uuid.data[1] = bt_uuid & 0xFF;
2417
2418
0
        if (bt_uuid && p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
2419
0
            char *value_data;
2420
2421
0
            value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &uuid));
2422
2423
0
            p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
2424
0
        }
2425
2426
0
        if (psm < BTL2CAP_DYNAMIC_PSM_START) {
2427
0
            psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
2428
0
        } else {
2429
0
            psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
2430
0
            if (uuid.bt_uuid)
2431
0
                proto_item_append_text(psm_item, ": %s",
2432
0
                    val_to_str_ext_const(uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown service"));
2433
0
        }
2434
0
        proto_item_set_generated(psm_item);
2435
0
    }/*psm*/
2436
2437
0
    if (btl2cap_frame_data->first_fragment) {
2438
0
        proto_tree_add_item(btl2cap_tree, hf_btl2cap_le_sdu_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2439
0
        offset += 2;
2440
0
        length = length - 2;
2441
0
    }
2442
0
    pinfo->fragmented = true;
2443
0
    frag_btl2cap_le_sdu = fragment_add_seq_next(&btl2cap_le_sdu_reassembly_table,
2444
0
        tvb, offset,
2445
0
        pinfo,
2446
0
        cid,                                  /* uint32_t ID for fragments belonging together */
2447
0
        NULL,                                 /* data* */
2448
0
        length,                               /* Fragment length */
2449
0
        btl2cap_frame_data->more_fragments);  /* More fragments */
2450
2451
0
    new_tvb = process_reassembled_data(tvb, offset, pinfo,
2452
0
        "Reassembled SDU",
2453
0
        frag_btl2cap_le_sdu,
2454
0
        &btl2cap_le_sdu_frag_items,
2455
0
        NULL,
2456
0
        btl2cap_tree);
2457
2458
0
    if (new_tvb) {
2459
0
        if (psm) {
2460
0
            if (!dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t)cid, new_tvb, pinfo, tree, true, l2cap_data)) {
2461
0
                if (!dissector_try_uint_with_data(l2cap_psm_dissector_table, (uint32_t)psm, new_tvb, pinfo, tree, true, l2cap_data)) {
2462
                    /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2463
0
                    if (!dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &uuid), new_tvb, pinfo, tree, true, l2cap_data)) {
2464
                        /* unknown protocol. declare as data */
2465
0
                        proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2466
0
                    }
2467
0
                }
2468
0
            }
2469
0
        } else {
2470
            /* call next dissector */
2471
0
            if (!dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t)cid, new_tvb, pinfo, tree, true, l2cap_data)) {
2472
0
                proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2473
0
            }
2474
0
        }
2475
0
        return tvb_captured_length(tvb);
2476
0
    }
2477
2478
0
    col_set_str(pinfo->cinfo, COL_INFO, "L2CAP LE Fragment");
2479
0
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2480
2481
0
    return tvb_captured_length(tvb);
2482
0
}
2483
2484
static int
2485
dissect_i_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2486
        proto_tree *btl2cap_tree, psm_data_t *psm_data, uint16_t length,
2487
        int offset, config_data_t *config_data, btl2cap_data_t *l2cap_data)
2488
0
{
2489
0
    tvbuff_t         *next_tvb = NULL;
2490
0
    uint16_t          control, segment;
2491
0
    uint16_t          sdulen;
2492
0
    proto_item*       ti_control;
2493
0
    proto_tree*       ti_control_subtree;
2494
0
    sdu_reassembly_t *mfp      = NULL;
2495
0
    uint16_t          psm      = (psm_data ? psm_data->psm : 0);
2496
2497
0
    control = tvb_get_letohs(tvb, offset);
2498
0
    segment = (control & 0xC000) >> 14;
2499
0
    switch (segment) {
2500
0
    case 0:
2501
0
        col_append_str(pinfo->cinfo, COL_INFO, "[I] Unsegmented SDU");
2502
0
        break;
2503
0
    case 1:
2504
0
        col_append_str(pinfo->cinfo, COL_INFO, "[I] Start SDU");
2505
0
        break;
2506
0
    case 2:
2507
0
        col_append_str(pinfo->cinfo, COL_INFO, "[I] End SDU");
2508
0
        break;
2509
0
    case 3:
2510
0
        col_append_str(pinfo->cinfo, COL_INFO, "[I] Continuation SDU");
2511
0
        break;
2512
0
    }
2513
0
    ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
2514
0
                                            offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
2515
0
                                            val_to_str_const((control & 0xC000) >> 14, control_sar_vals, "unknown"),
2516
0
                                            (control & 0x3F00) >> 8,
2517
0
                                            (control & 0x0080) >> 7,
2518
0
                                            (control & 0x007E) >> 1);
2519
0
    ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
2520
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2521
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2522
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2523
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2524
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2525
0
    offset  +=  2;
2526
2527
    /*Segmented frames with SAR = start have an extra SDU length header field*/
2528
0
    if (segment == 0x01) {
2529
0
        proto_item *pi;
2530
2531
0
        sdulen = tvb_get_letohs(tvb, offset);
2532
0
        pi = proto_tree_add_item(btl2cap_tree, hf_btl2cap_sdulength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2533
0
        offset += 2;
2534
2535
2536
        /* Detect malformed data */
2537
2538
0
        if (length <= 6) {
2539
0
            expert_add_info_format(pinfo, pi, &ei_btl2cap_sdulength_bad,
2540
0
                    "SDU length too short: %u", length);
2541
0
            THROW(ReportedBoundsError);
2542
0
        }
2543
2544
0
        length -= 6; /*Control, SDUlength, FCS*/
2545
2546
0
        if (sdulen < length) {
2547
0
            sdulen = length;
2548
0
            expert_add_info_format(pinfo, pi, &ei_btl2cap_sdulength_bad,
2549
0
                    "SDU length less than length of first packet (%u < %u)", sdulen, length);
2550
0
        }
2551
2552
0
        if (!pinfo->fd->visited) {
2553
0
            mfp              = wmem_new(wmem_file_scope(), sdu_reassembly_t);
2554
0
            mfp->first_frame = pinfo->num;
2555
0
            mfp->last_frame  = 0;
2556
0
            mfp->tot_len     = sdulen;
2557
0
            mfp->reassembled = (uint8_t *) wmem_alloc(wmem_file_scope(), sdulen);
2558
0
            tvb_memcpy(tvb, mfp->reassembled, offset, sdulen);
2559
0
            mfp->cur_off     = sdulen;
2560
0
            wmem_tree_insert32(config_data->start_fragments, pinfo->num, mfp);
2561
0
        } else {
2562
0
            mfp              = (sdu_reassembly_t *)wmem_tree_lookup32(config_data->start_fragments, pinfo->num);
2563
0
        }
2564
0
        if (mfp != NULL && mfp->last_frame) {
2565
0
            proto_item *item;
2566
0
            item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_reassembled_in, tvb, 0, 0, mfp->last_frame);
2567
0
            proto_item_set_generated(item);
2568
0
            col_append_frame_number(pinfo, COL_INFO, "[Reassembled in #%u] ", mfp->last_frame);
2569
0
        }
2570
0
    } else {
2571
0
        if (length <= 4) {
2572
0
            expert_add_info_format(pinfo, btl2cap_tree, &ei_btl2cap_length_bad,
2573
0
                    "Control / FCS length too short: %u", length);
2574
0
            THROW(ReportedBoundsError);
2575
0
        }
2576
0
        length -= 4; /*Control, FCS*/
2577
0
    }
2578
0
    if (segment == 0x02 || segment == 0x03) {
2579
0
        mfp = (sdu_reassembly_t *)wmem_tree_lookup32_le(config_data->start_fragments, pinfo->num);
2580
0
        if (!pinfo->fd->visited) {
2581
0
            if (mfp != NULL && !mfp->last_frame && (mfp->tot_len>=mfp->cur_off + length)) {
2582
0
                tvb_memcpy(tvb, mfp->reassembled + mfp->cur_off, offset, length);
2583
0
                mfp->cur_off += length;
2584
0
                if (segment == 0x02) {
2585
0
                    mfp->last_frame = pinfo->num;
2586
0
                }
2587
0
            }
2588
0
        }
2589
0
        if (mfp) {
2590
0
            proto_item *item;
2591
0
            item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_continuation_to, tvb, 0, 0, mfp->first_frame);
2592
0
            proto_item_set_generated(item);
2593
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", mfp->first_frame);
2594
0
        }
2595
0
    }
2596
0
    if (segment == 0x02 && mfp != NULL && mfp->last_frame == pinfo->num) {
2597
0
        next_tvb = tvb_new_child_real_data(tvb, (uint8_t *)mfp->reassembled, mfp->tot_len, mfp->tot_len);
2598
0
        add_new_data_source(pinfo, next_tvb, "Reassembled L2CAP");
2599
0
    }
2600
    /*pass up to higher layer if we have a complete packet*/
2601
0
    if (segment == 0x00) {
2602
0
        next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset) - 2, length);
2603
0
    }
2604
0
    if (next_tvb) {
2605
0
        if (psm) {
2606
0
            proto_item        *psm_item;
2607
0
            uint16_t           bt_uuid;
2608
0
             bluetooth_uuid_t  uuid;
2609
2610
0
            if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
2611
0
                uint16_t *value_data;
2612
2613
0
                value_data = wmem_new(wmem_file_scope(), uint16_t);
2614
0
                *value_data = psm;
2615
2616
0
                p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
2617
0
            }
2618
2619
0
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm, psm_data->local_service);
2620
2621
0
            uuid.size = 2;
2622
0
            uuid.bt_uuid = bt_uuid;
2623
0
            uuid.data[0] = bt_uuid >> 8;
2624
0
            uuid.data[1] = bt_uuid & 0xFF;
2625
2626
0
            if (bt_uuid && p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
2627
0
                char *value_data;
2628
2629
0
                value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &uuid));
2630
2631
0
                p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
2632
0
            }
2633
2634
0
            if (psm < BTL2CAP_DYNAMIC_PSM_START) {
2635
0
                psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
2636
0
            } else {
2637
0
                psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
2638
0
                if (uuid.bt_uuid)
2639
0
                    proto_item_append_text(psm_item, " (%s)",
2640
0
                                           val_to_str_ext_const(uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown service"));
2641
0
            }
2642
0
            proto_item_set_generated(psm_item);
2643
2644
            /* call next dissector */
2645
0
            if (!dissector_try_uint_with_data(l2cap_psm_dissector_table, (uint32_t) psm, next_tvb, pinfo, tree, true, l2cap_data)) {
2646
                /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2647
0
                if (!dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &uuid), next_tvb, pinfo, tree, true,l2cap_data)) {
2648
                    /* unknown protocol. declare as data */
2649
0
                    proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_reported_length(next_tvb), ENC_NA);
2650
0
                }
2651
0
            }
2652
0
        }
2653
0
        else {
2654
0
            proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_reported_length(next_tvb), ENC_NA);
2655
0
        }
2656
0
    }
2657
0
    offset += tvb_reported_length_remaining(tvb, offset) - 2;
2658
0
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2659
0
    offset +=  2;
2660
0
    return offset;
2661
0
}
2662
2663
static int
2664
dissect_s_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, proto_tree *btl2cap_tree,
2665
                uint16_t psm _U_, uint16_t length _U_, int offset, config_data_t *config_data _U_)
2666
2
{
2667
2
    proto_item *ti_control;
2668
2
    proto_tree *ti_control_subtree;
2669
2
    uint16_t    control;
2670
2671
2
    control = tvb_get_letohs(tvb, offset);
2672
2673
2
    switch ((control & 0x000C) >> 2) {
2674
1
    case 0:
2675
1
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Receiver Ready");
2676
1
        break;
2677
0
    case 1:
2678
0
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Reject");
2679
0
        break;
2680
1
    default:
2681
1
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Unknown supervisory frame");
2682
1
        break;
2683
2
    }
2684
2685
2
    ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
2686
2
        offset, 2, "Control: %s reqseq:%d r:%d",
2687
2
        val_to_str_const((control & 0x000C) >> 2, control_supervisory_vals, "unknown"),
2688
2
        (control & 0x3F00) >> 8,
2689
2
        (control & 0x0080) >> 7);
2690
2
    ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
2691
2692
2
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2693
2
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2694
2
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_supervisory, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2695
2
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2696
2
    offset += 2;
2697
2698
2
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2699
2
    offset += 2;
2700
2701
2
    return offset;
2702
2
}
2703
2704
static int
2705
dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2706
2.51k
{
2707
2.51k
    int               offset       = 0;
2708
2.51k
    proto_item       *ti;
2709
2.51k
    proto_tree       *btl2cap_tree;
2710
2.51k
    proto_item       *length_item;
2711
2.51k
    uint16_t          length;
2712
2.51k
    uint16_t          cid;
2713
2.51k
    uint16_t          psm;
2714
2.51k
    uint16_t          control;
2715
2.51k
    tvbuff_t         *next_tvb     = NULL;
2716
2.51k
    psm_data_t       *psm_data;
2717
2.51k
    bthci_acl_data_t *acl_data;
2718
2.51k
    btl2cap_data_t   *l2cap_data;
2719
2.51k
    bool              dir_in_col = true;
2720
2721
2.51k
    acl_data = (bthci_acl_data_t *) data;
2722
2723
2.51k
    if ((acl_data) && (acl_data->is_btle)) {
2724
1
        dir_in_col = false;
2725
1
    }
2726
2.51k
    ti = proto_tree_add_item(tree, proto_btl2cap, tvb, offset, -1, ENC_NA);
2727
2.51k
    btl2cap_tree = proto_item_add_subtree(ti, ett_btl2cap);
2728
2729
2.51k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2CAP");
2730
2731
2.51k
    if (dir_in_col) {
2732
2.51k
        switch (pinfo->p2p_dir) {
2733
33
        case P2P_DIR_SENT:
2734
33
            col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
2735
33
            break;
2736
12
        case P2P_DIR_RECV:
2737
12
            col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
2738
12
            break;
2739
2.46k
        default:
2740
2.46k
            col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
2741
2.46k
            break;
2742
2.51k
        }
2743
2.51k
    } else {
2744
1
        col_clear(pinfo->cinfo, COL_INFO);
2745
1
    }
2746
2747
2.51k
    length  = tvb_get_letohs(tvb, offset);
2748
2.51k
    length_item = proto_tree_add_item(btl2cap_tree, hf_btl2cap_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2749
2.51k
    if (tvb_captured_length_remaining(tvb, offset) < length) {
2750
2.49k
        expert_add_info(pinfo, length_item, &ei_btl2cap_length_bad);
2751
        /* Try to dissect as more as possible */
2752
2.49k
        length = tvb_captured_length_remaining(tvb, offset) - 4;
2753
2.49k
    }
2754
2755
2.51k
    offset += 2;
2756
2757
2.51k
    cid = tvb_get_letohs(tvb, offset);
2758
2.51k
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2759
2.51k
    if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID ) == NULL) {
2760
2.07k
        uint16_t *value_data;
2761
2762
2.07k
        value_data = wmem_new(wmem_file_scope(), uint16_t);
2763
2.07k
        *value_data = cid;
2764
2765
2.07k
        p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID, value_data);
2766
2.07k
    }
2767
2.51k
    offset += 2;
2768
2769
2.51k
    l2cap_data = wmem_new(pinfo->pool, btl2cap_data_t);
2770
2771
2.51k
    if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2772
0
        l2cap_data->interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2773
2.51k
    else
2774
2.51k
        l2cap_data->interface_id = HCI_INTERFACE_DEFAULT;
2775
2.51k
    if (acl_data) {
2776
2
        l2cap_data->adapter_id                  = acl_data->adapter_id;
2777
2
        l2cap_data->adapter_disconnect_in_frame = acl_data->adapter_disconnect_in_frame;
2778
2
        l2cap_data->chandle                     = acl_data->chandle;
2779
2
        l2cap_data->hci_disconnect_in_frame     = acl_data->disconnect_in_frame;
2780
2
        l2cap_data->remote_bd_addr_oui          = acl_data->remote_bd_addr_oui;
2781
2
        l2cap_data->remote_bd_addr_id           = acl_data->remote_bd_addr_id;
2782
2.51k
    } else {
2783
2.51k
        l2cap_data->adapter_id                  = HCI_ADAPTER_DEFAULT;
2784
2.51k
        l2cap_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
2785
2.51k
        l2cap_data->chandle                     = 0;
2786
2.51k
        l2cap_data->hci_disconnect_in_frame     = &bluetooth_max_disconnect_in_frame;
2787
2.51k
        l2cap_data->remote_bd_addr_oui          = 0;
2788
2.51k
        l2cap_data->remote_bd_addr_id           = 0;
2789
2.51k
    }
2790
2791
2.51k
    l2cap_data->disconnect_in_frame         = &bluetooth_max_disconnect_in_frame;
2792
2793
2.51k
    l2cap_data->cid              = cid;
2794
2.51k
    l2cap_data->local_cid        = BTL2CAP_UNKNOWN_CID;
2795
2.51k
    l2cap_data->remote_cid       = BTL2CAP_UNKNOWN_CID;
2796
2.51k
    l2cap_data->is_local_psm     = false;
2797
2.51k
    l2cap_data->psm              = 0;
2798
2799
2.51k
    if (cid == BTL2CAP_FIXED_CID_SIGNAL || cid == BTL2CAP_FIXED_CID_LE_SIGNAL) {
2800
        /* This is a command packet*/
2801
2.13k
        while (offset < length + 4) {
2802
2803
1.99k
            proto_item  *ti_command;
2804
1.99k
            proto_tree  *btl2cap_cmd_tree;
2805
1.99k
            uint8_t      cmd_code;
2806
1.99k
            uint8_t      cmd_ident;
2807
1.99k
            uint16_t     cmd_length;
2808
1.99k
            const char *cmd_str;
2809
2810
1.99k
            ti_command = proto_tree_add_none_format(btl2cap_tree,
2811
1.99k
                    hf_btl2cap_command, tvb,
2812
1.99k
                    offset, length,
2813
1.99k
                    "Command: ");
2814
1.99k
            btl2cap_cmd_tree = proto_item_add_subtree(ti_command, ett_btl2cap_cmd);
2815
2816
1.99k
            cmd_code = tvb_get_uint8(tvb, offset);
2817
1.99k
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_code,   tvb, offset, 1, ENC_LITTLE_ENDIAN);
2818
1.99k
            offset += 1;
2819
2820
1.99k
            cmd_ident = tvb_get_uint8(tvb, offset);
2821
1.99k
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_ident,  tvb, offset, 1, ENC_LITTLE_ENDIAN);
2822
1.99k
            offset += 1;
2823
2824
1.99k
            cmd_length = tvb_get_letohs(tvb, offset);
2825
1.99k
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2826
1.99k
            proto_item_set_len(ti_command, cmd_length + 4);
2827
1.99k
            offset += 2;
2828
2829
1.99k
            cmd_str = val_to_str_const(cmd_code, command_code_vals, "Unknown command");
2830
1.99k
            proto_item_append_text(ti_command, "%s", cmd_str);
2831
1.99k
            col_append_str(pinfo->cinfo, COL_INFO, cmd_str);
2832
2833
1.99k
            switch (cmd_code) {
2834
318
            case 0x01: /* Command Reject */
2835
318
                offset  = dissect_comrej(tvb, offset, pinfo, btl2cap_cmd_tree);
2836
318
                break;
2837
2838
121
            case 0x02: /* Connection Request */
2839
121
                offset  = dissect_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, false, acl_data, l2cap_data);
2840
121
                break;
2841
2842
35
            case 0x03: /* Connection Response */
2843
35
                offset  = dissect_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, acl_data);
2844
35
                break;
2845
2846
42
            case 0x04: /* Configure Request */
2847
42
                offset  = dissect_configrequest(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length, acl_data);
2848
42
                break;
2849
2850
38
            case 0x05: /* Configure Response */
2851
38
                offset  = dissect_configresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length, acl_data);
2852
38
                break;
2853
2854
273
            case 0x06: /* Disconnect Request */
2855
273
                offset  = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, acl_data, l2cap_data, true);
2856
273
                break;
2857
2858
75
            case 0x07: /* Disconnect Response */
2859
75
                offset  = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, acl_data, l2cap_data, false);
2860
75
                break;
2861
2862
2
            case 0x08: /* Echo Request */
2863
2
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_data, tvb, offset, -1, ENC_NA);
2864
2
                offset = tvb_reported_length(tvb);
2865
2
                break;
2866
2867
3
            case 0x09: /* Echo Response */
2868
3
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_data, tvb, offset, -1, ENC_NA);
2869
3
                offset = tvb_reported_length(tvb);
2870
3
                break;
2871
2872
29
            case 0x0a: /* Information Request */
2873
29
                offset  = dissect_inforequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2874
29
                break;
2875
2876
2
            case 0x0b: /* Information Response */
2877
2
                offset  = dissect_inforesponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2878
2
                break;
2879
2880
37
            case 0x0c: /* Create Channel Request */
2881
37
                offset  = dissect_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, true, acl_data, l2cap_data);
2882
37
                break;
2883
2884
18
            case 0x0d: /* Create Channel Response */
2885
18
                offset  = dissect_chanresponse(tvb, offset, pinfo, btl2cap_cmd_tree, acl_data);
2886
18
                break;
2887
2888
103
            case 0x0e: /* Move Channel Request */
2889
103
                offset  = dissect_movechanrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2890
103
                break;
2891
2892
22
            case 0x0f: /* Move Channel Response */
2893
22
                offset  = dissect_movechanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2894
22
                break;
2895
2896
82
            case 0x10: /* Move Channel Confirmation */
2897
82
                offset  = dissect_movechanconfirmation(tvb, offset, pinfo, btl2cap_cmd_tree);
2898
82
                break;
2899
2900
191
            case 0x11: /* Move Channel Confirmation Response */
2901
191
                offset  = dissect_movechanconfirmationresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2902
191
                break;
2903
2904
42
            case 0x12: /* Connection Parameter Request */
2905
42
                offset  = dissect_connparamrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2906
42
                break;
2907
2908
50
            case 0x13: /* Connection Parameter Response */
2909
50
                offset  = dissect_connparamresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2910
50
                break;
2911
2912
221
            case 0x14: /* LE Credit Based Connection Request */
2913
221
                offset = dissect_le_credit_based_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, cid, cmd_ident, acl_data, l2cap_data);
2914
2915
221
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Initial Credits: %u)",
2916
221
                                tvb_get_letohs(tvb, offset - 8), tvb_get_letohs(tvb, offset - 2));
2917
221
                break;
2918
2919
36
            case 0x15: /* LE Credit Based Connection Response */
2920
36
                offset = dissect_le_credit_based_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cid, cmd_ident, acl_data);
2921
2922
36
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Initial Credits: %u)",
2923
36
                                tvb_get_letohs(tvb, offset - 10), tvb_get_letohs(tvb, offset - 4));
2924
36
                break;
2925
2926
39
            case 0x16: /* LE Flow Control Credit */
2927
39
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2928
39
                offset += 2;
2929
2930
39
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2931
39
                offset += 2;
2932
2933
39
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Credits: %u)",
2934
39
                                tvb_get_letohs(tvb, offset - 4), tvb_get_letohs(tvb, offset - 2));
2935
39
                break;
2936
2937
59
            case 0x17: /* L2CAP Credit Based Connection Request */
2938
59
                offset = dissect_l2cap_credit_based_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, cid, cmd_ident, cmd_length, acl_data, l2cap_data);
2939
59
                break;
2940
2941
28
            case 0x18: /* L2CAP Credit Based Connection Response */
2942
28
                offset = dissect_l2cap_credit_based_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cid, cmd_ident, cmd_length, acl_data);
2943
28
                break;
2944
2945
119
            default:
2946
119
                proto_tree_add_expert(btl2cap_cmd_tree, pinfo, &ei_btl2cap_unknown_command_code, tvb, offset, -1);
2947
119
                offset += tvb_reported_length_remaining(tvb, offset);
2948
119
                break;
2949
1.99k
            }
2950
1.99k
        }
2951
296
    }
2952
2.21k
    else if (cid == BTL2CAP_FIXED_CID_CONNLESS) { /* Connectionless reception channel */
2953
383
        col_append_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel");
2954
2955
383
        psm = tvb_get_letohs(tvb, offset);
2956
383
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
2957
0
            l2cap_data->local_cid = cid;
2958
0
            l2cap_data->remote_cid = BTL2CAP_UNKNOWN_CID;
2959
383
        } else {
2960
383
            l2cap_data->local_cid = BTL2CAP_UNKNOWN_CID;
2961
383
            l2cap_data->remote_cid = cid;
2962
383
        }
2963
383
        l2cap_data->psm = psm;
2964
383
        l2cap_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
2965
2966
383
        if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
2967
383
            uint16_t *value_data;
2968
2969
383
            value_data = wmem_new(wmem_file_scope(), uint16_t);
2970
383
            *value_data = psm;
2971
2972
383
            p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
2973
383
        }
2974
2975
383
        proto_tree_add_item(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2976
383
        offset += 2;
2977
2978
        /* 3.2 "For G-frames, the PDU length equals the payload size plus the
2979
         * number of octets in the PSM."
2980
         * Substract the PSM length. (Yes, technically the PSM is "at least"
2981
         * two octets in length, Little Endian where only the MSB (== Last)
2982
         * has least significant bit 0, and that's used to detect the size.
2983
         * We only use 2 octets everywhere in this dissector, though.)
2984
         */
2985
383
        if (length < 2) {
2986
2
            expert_add_info_format(pinfo, length_item, &ei_btl2cap_length_bad,
2987
2
                    "PDU length too short: %u (should include PSM)", length);
2988
2
            THROW(ReportedBoundsError);
2989
2
        }
2990
383
        length -= 2;
2991
383
        next_tvb = tvb_new_subset_length(tvb, offset, length);
2992
2993
        /* call next dissector */
2994
383
        if (!dissector_try_uint_with_data(l2cap_psm_dissector_table, (uint32_t) psm, next_tvb, pinfo, tree, true, l2cap_data)) {
2995
            /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
2996
2
            uint16_t bt_uuid;
2997
2
            bluetooth_uuid_t  uuid;
2998
2999
2
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm, (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false );
3000
3001
2
            uuid.size = 2;
3002
2
            uuid.bt_uuid = bt_uuid;
3003
2
            uuid.data[0] = bt_uuid >> 8;
3004
2
            uuid.data[1] = bt_uuid & 0xFF;
3005
3006
2
            if (bt_uuid && p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID ) == NULL) {
3007
0
                char* value_data;
3008
3009
0
                value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &uuid));
3010
3011
0
                p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
3012
0
            }
3013
3014
2
            if (!dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &uuid), next_tvb, pinfo, tree, true, l2cap_data)) {
3015
                /* unknown protocol. declare as data */
3016
2
                proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
3017
2
            }
3018
2
            offset = tvb_captured_length(tvb);
3019
2
        }
3020
383
    }
3021
1.83k
    else if (cid <= BTL2CAP_FIXED_CID_LAST) {
3022
1.78k
        if (cid == BTL2CAP_FIXED_CID_AMP_MAN) {
3023
31
            control = tvb_get_letohs(tvb, offset);
3024
31
            if (control & 0x1) {
3025
2
                offset = dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, 0 /* unused */, length, offset, NULL /* unused */);
3026
29
            } else {
3027
29
                proto_item* ti_control;
3028
29
                proto_tree* ti_control_subtree;
3029
3030
29
                ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
3031
29
                    offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
3032
29
                    val_to_str_const((control & 0xC000) >> 14, control_sar_vals, "unknown"),
3033
29
                    (control & 0x3F00) >> 8,
3034
29
                    (control & 0x0080) >> 7,
3035
29
                    (control & 0x007E) >> 1);
3036
29
                ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
3037
29
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3038
29
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3039
29
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3040
29
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3041
29
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3042
29
                offset += 2;
3043
29
                proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, tvb_reported_length(tvb) - 2, 2, ENC_LITTLE_ENDIAN);
3044
3045
29
                next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset)-2, length);
3046
29
            }
3047
31
        }
3048
1.74k
        else {
3049
1.74k
            next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), length);
3050
1.74k
        }
3051
        /* call next dissector */
3052
1.78k
        if (next_tvb && !dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t) cid,
3053
1.77k
                    next_tvb, pinfo, tree, true, l2cap_data)) {
3054
            /* unknown protocol. declare as data */
3055
12
            proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
3056
12
        }
3057
1.78k
        offset = tvb_captured_length(tvb);
3058
1.78k
    }
3059
54
    else /* if (cid > BTL2CAP_FIXED_CID_LAST) */ { /* Connection oriented channel */
3060
54
        wmem_tree_key_t    key[6];
3061
54
        uint32_t           k_interface_id;
3062
54
        uint32_t           k_adapter_id;
3063
54
        uint32_t           k_chandle;
3064
54
        uint32_t           k_cid;
3065
54
        uint32_t           k_frame_number;
3066
54
        uint32_t           interface_id;
3067
54
        uint32_t           adapter_id;
3068
54
        uint32_t           chandle;
3069
54
        uint32_t           key_cid;
3070
3071
54
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
3072
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
3073
54
        else
3074
54
            interface_id = HCI_INTERFACE_DEFAULT;
3075
54
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
3076
54
        chandle      = (acl_data) ? acl_data->chandle : 0;
3077
54
        key_cid      = cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
3078
3079
54
        k_interface_id = interface_id;
3080
54
        k_adapter_id   = adapter_id;
3081
54
        k_chandle      = chandle;
3082
54
        k_cid          = key_cid;
3083
54
        k_frame_number = pinfo->num;
3084
3085
54
        key[0].length = 1;
3086
54
        key[0].key    = &k_interface_id;
3087
54
        key[1].length = 1;
3088
54
        key[1].key    = &k_adapter_id;
3089
54
        key[2].length = 1;
3090
54
        key[2].key    = &k_chandle;
3091
54
        key[3].length = 1;
3092
54
        key[3].key    = &k_cid;
3093
54
        key[4].length = 1;
3094
54
        key[4].key    = &k_frame_number;
3095
54
        key[5].length = 0;
3096
54
        key[5].key    = NULL;
3097
3098
54
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
3099
54
        if (psm_data &&
3100
54
            psm_data->interface_id == interface_id &&
3101
54
            psm_data->adapter_id == adapter_id &&
3102
54
            psm_data->chandle == chandle &&
3103
54
            (psm_data->local_cid == key_cid ||
3104
49
             psm_data->remote_cid == key_cid) &&
3105
54
            psm_data->disconnect_in_frame > pinfo->num)
3106
0
        {
3107
0
            config_data_t  *config_data;
3108
0
            proto_item     *sub_item;
3109
0
            uint32_t        bt_uuid;
3110
3111
0
            psm = psm_data->psm;
3112
0
            l2cap_data->local_cid = psm_data->local_cid;
3113
0
            l2cap_data->remote_cid = psm_data->remote_cid;
3114
0
            l2cap_data->psm = psm;
3115
0
            l2cap_data->is_local_psm = psm_data->local_service;
3116
0
            l2cap_data->disconnect_in_frame = &psm_data->disconnect_in_frame;
3117
3118
0
            if (pinfo->p2p_dir == P2P_DIR_RECV)
3119
0
                config_data = &(psm_data->in);
3120
0
            else
3121
0
                config_data = &(psm_data->out);
3122
3123
0
            if (psm_data->connect_in_frame > 0 && psm_data->connect_in_frame < UINT32_MAX) {
3124
0
                sub_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_connect_in_frame, tvb, 0, 0, psm_data->connect_in_frame);
3125
0
                proto_item_set_generated(sub_item);
3126
0
            }
3127
3128
0
            if (psm_data->disconnect_in_frame > 0 && psm_data->disconnect_in_frame < UINT32_MAX) {
3129
0
                sub_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_disconnect_in_frame, tvb, 0, 0, psm_data->disconnect_in_frame);
3130
0
                proto_item_set_generated(sub_item);
3131
0
            }
3132
3133
0
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
3134
0
            if (bt_uuid) {
3135
0
                sub_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_service, tvb, 0, 0, bt_uuid);
3136
0
                proto_item_set_generated(sub_item);
3137
0
            }
3138
3139
0
            if (config_data->mode == L2CAP_BASIC_MODE) {
3140
0
                offset = dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, psm_data->local_service, length, offset, l2cap_data);
3141
0
            } else if (config_data->mode == L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE) {
3142
0
                bool is_retransmit = false;
3143
0
                if (acl_data) {
3144
0
                    is_retransmit = acl_data->is_btle_retransmit;
3145
0
                }
3146
0
                offset = dissect_le_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, psm_data->local_service, length, offset, config_data, l2cap_data, is_retransmit);
3147
0
            } else {
3148
0
                control = tvb_get_letohs(tvb, offset);
3149
0
                if (control & 0x1) {
3150
0
                    offset = dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, psm, length, offset, config_data);
3151
0
                } else {
3152
0
                    offset = dissect_i_frame(tvb, pinfo, tree, btl2cap_tree, psm_data, length, offset, config_data, l2cap_data);
3153
0
                }
3154
0
            }
3155
54
        } else {
3156
54
            psm = 0;
3157
54
            offset = dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, false, length, offset, l2cap_data);
3158
54
        }
3159
54
    }
3160
3161
2.35k
    return offset;
3162
2.51k
}
3163
3164
/* Register the protocol with Wireshark */
3165
void
3166
proto_register_btl2cap(void)
3167
14
{
3168
14
    expert_module_t *expert_btl2cap;
3169
    /* Setup list of header fields  See Section 1.6.1 for details*/
3170
14
    static hf_register_info hf[] = {
3171
14
        { &hf_btl2cap_length,
3172
14
          { "Length",           "btl2cap.length",
3173
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3174
14
            "L2CAP Payload Length", HFILL }
3175
14
        },
3176
14
        { &hf_btl2cap_cid,
3177
14
          { "CID",           "btl2cap.cid",
3178
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(cid_rvals), 0x0,
3179
14
            "L2CAP Channel Identifier", HFILL }
3180
14
        },
3181
14
        { &hf_btl2cap_payload,
3182
14
          { "Payload",           "btl2cap.payload",
3183
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3184
14
            "L2CAP Payload", HFILL }
3185
14
        },
3186
14
        { &hf_btl2cap_command,
3187
14
          { "Command",           "btl2cap.command",
3188
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3189
14
            "L2CAP Command", HFILL }
3190
14
        },
3191
14
        { &hf_btl2cap_cmd_code,
3192
14
          { "Command Code",           "btl2cap.cmd_code",
3193
14
            FT_UINT8, BASE_HEX, VALS(command_code_vals), 0x0,
3194
14
            "L2CAP Command Code", HFILL }
3195
14
        },
3196
14
        { &hf_btl2cap_cmd_ident,
3197
14
          { "Command Identifier",           "btl2cap.cmd_ident",
3198
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
3199
14
            "L2CAP Command Identifier", HFILL }
3200
14
        },
3201
14
        { &hf_btl2cap_cmd_length,
3202
14
          { "Command Length",           "btl2cap.cmd_length",
3203
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3204
14
            "L2CAP Command Length", HFILL }
3205
14
        },
3206
14
        { &hf_btl2cap_cmd_data,
3207
14
          { "Command Data",           "btl2cap.cmd_data",
3208
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3209
14
            "L2CAP Command Data", HFILL }
3210
14
        },
3211
14
        { &hf_btl2cap_psm,
3212
14
          { "PSM",           "btl2cap.psm",
3213
14
            FT_UINT16, BASE_HEX, VALS(psm_vals), 0x0,
3214
14
            "Protocol/Service Multiplexer", HFILL }
3215
14
        },
3216
14
        { &hf_btl2cap_psm_dynamic,
3217
14
          { "Dynamic PSM",           "btl2cap.psm",
3218
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
3219
14
            "Dynamic Protocol/Service Multiplexer", HFILL }
3220
14
        },
3221
14
        { &hf_btl2cap_scid,
3222
14
          { "Source CID",           "btl2cap.scid",
3223
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(cid_rvals), 0x0,
3224
14
            "Source Channel Identifier", HFILL }
3225
14
        },
3226
14
        { &hf_btl2cap_dcid,
3227
14
          { "Destination CID",           "btl2cap.dcid",
3228
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(cid_rvals), 0x0,
3229
14
            "Destination Channel Identifier", HFILL }
3230
14
        },
3231
14
        { &hf_btl2cap_icid,
3232
14
          { "Initiator CID",           "btl2cap.icid",
3233
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(cid_rvals), 0x0,
3234
14
            "Initiator Channel Identifier", HFILL }
3235
14
        },
3236
14
        { &hf_btl2cap_controller,
3237
14
          { "Controller ID",           "btl2cap.ctrl_id",
3238
14
            FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
3239
14
            NULL, HFILL }
3240
14
        },
3241
14
        { &hf_btl2cap_dcontroller,
3242
14
          { "Controller ID",           "btl2cap.dctrl_id",
3243
14
            FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
3244
14
            "Destination Controller ID", HFILL }
3245
14
        },
3246
14
        { &hf_btl2cap_result,
3247
14
          { "Result",           "btl2cap.result",
3248
14
            FT_UINT16, BASE_HEX, VALS(result_vals), 0x0,
3249
14
            NULL, HFILL }
3250
14
        },
3251
14
        { &hf_btl2cap_move_result,
3252
14
          { "Move Result",           "btl2cap.move_result",
3253
14
            FT_UINT16, BASE_HEX, VALS(move_result_vals), 0x0,
3254
14
            NULL, HFILL }
3255
14
        },
3256
14
        { &hf_btl2cap_move_confirmation_result,
3257
14
          { "Move Result",           "btl2cap.move_result",
3258
14
            FT_UINT16, BASE_HEX, VALS(move_result_confirmation_vals), 0x0,
3259
14
            NULL, HFILL }
3260
14
        },
3261
14
        { &hf_btl2cap_status,
3262
14
          { "Status",           "btl2cap.status",
3263
14
            FT_UINT16, BASE_HEX, VALS(status_vals), 0x0,
3264
14
            NULL, HFILL }
3265
14
        },
3266
14
        { &hf_btl2cap_rej_reason,
3267
14
          { "Reason",           "btl2cap.rej_reason",
3268
14
            FT_UINT16, BASE_HEX, VALS(reason_vals), 0x0,
3269
14
            NULL, HFILL }
3270
14
        },
3271
14
        { &hf_btl2cap_sig_mtu,
3272
14
          { "Maximum Signalling MTU",           "btl2cap.sig_mtu",
3273
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3274
14
            NULL, HFILL }
3275
14
        },
3276
14
        { &hf_btl2cap_info_mtu,
3277
14
          { "Remote Entity MTU",           "btl2cap.info_mtu",
3278
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3279
14
            "Remote entity acceptable connectionless MTU", HFILL }
3280
14
        },
3281
14
        { &hf_btl2cap_info_flowcontrol,
3282
14
          { "Flow Control Mode",           "btl2cap.info_flowcontrol",
3283
14
            FT_UINT32, BASE_DEC, NULL, 0x01,
3284
14
            "Flow Control mode support", HFILL }
3285
14
        },
3286
14
        { &hf_btl2cap_info_retransmission,
3287
14
          { "Retransmission Mode",         "btl2cap.info_retransmission",
3288
14
            FT_UINT32, BASE_DEC, NULL, 0x02,
3289
14
            "Retransmission mode support", HFILL }
3290
14
        },
3291
14
        { &hf_btl2cap_info_bidirqos,
3292
14
          { "Bi-Directional QOS",          "btl2cap.info_bidirqos",
3293
14
            FT_UINT32, BASE_DEC, NULL, 0x04,
3294
14
            "Bi-Directional QOS support", HFILL }
3295
14
        },
3296
14
        { &hf_btl2cap_info_enh_retransmission,
3297
14
          { "Enhanced Retransmission Mode", "btl2cap.info_enh_retransmission",
3298
14
            FT_UINT32, BASE_DEC, NULL, 0x08,
3299
14
            "Enhanced Retransmission mode support", HFILL }
3300
14
        },
3301
14
        { &hf_btl2cap_info_streaming,
3302
14
          { "Streaming Mode", "btl2cap.info_streaming",
3303
14
            FT_UINT32, BASE_DEC, NULL, 0x10,
3304
14
            "Streaming mode support", HFILL }
3305
14
        },
3306
14
        { &hf_btl2cap_info_fcs,
3307
14
          { "FCS", "btl2cap.info_fcs",
3308
14
            FT_UINT32, BASE_DEC, NULL, 0x20,
3309
14
            "FCS support", HFILL }
3310
14
        },
3311
14
        { &hf_btl2cap_info_flow_spec,
3312
14
          { "Extended Flow Specification for BR/EDR", "btl2cap.info_flow_spec",
3313
14
            FT_UINT32, BASE_DEC, NULL, 0x40,
3314
14
            "Extended Flow Specification for BR/EDR support", HFILL }
3315
14
        },
3316
14
        { &hf_btl2cap_info_fixedchan,
3317
14
          { "Fixed Channels", "btl2cap.info_fixedchan",
3318
14
            FT_UINT32, BASE_DEC, NULL, 0x80,
3319
14
            "Fixed Channels support", HFILL }
3320
14
        },
3321
14
        { &hf_btl2cap_info_window,
3322
14
          { "Extended Window Size", "btl2cap.info_window",
3323
14
            FT_UINT32, BASE_DEC, NULL, 0x0100,
3324
14
            "Extended Window Size support", HFILL }
3325
14
        },
3326
14
        { &hf_btl2cap_info_unicast,
3327
14
          { "Unicast Connectionless Data Reception", "btl2cap.info_unicast",
3328
14
            FT_UINT32, BASE_DEC, NULL, 0x0200,
3329
14
            "Unicast Connectionless Data Reception support", HFILL }
3330
14
        },
3331
14
        { &hf_btl2cap_info_fixedchans,
3332
14
          { "Fixed Channels", "btl2cap.info_fixedchans",
3333
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3334
14
            NULL, HFILL }
3335
14
        },
3336
14
        { &hf_btl2cap_info_fixedchans_null,
3337
14
          { "Null identifier", "btl2cap.info_fixedchans_null",
3338
14
            FT_UINT32, BASE_DEC, NULL, 0x1,
3339
14
            NULL, HFILL }
3340
14
        },
3341
14
        { &hf_btl2cap_info_fixedchans_signal,
3342
14
          { "L2CAP signaling channel", "btl2cap.info_fixedchans_signal",
3343
14
            FT_UINT32, BASE_DEC, NULL, 0x2,
3344
14
            NULL, HFILL }
3345
14
        },
3346
14
        { &hf_btl2cap_info_fixedchans_connless,
3347
14
          { "Connectionless reception", "btl2cap.info_fixedchans_connless",
3348
14
            FT_UINT32, BASE_DEC, NULL, 0x4,
3349
14
            NULL, HFILL }
3350
14
        },
3351
14
        { &hf_btl2cap_info_fixedchans_amp_man,
3352
14
          { "AMP Manager protocol", "btl2cap.info_fixedchans_amp_man",
3353
14
            FT_UINT32, BASE_DEC, NULL, 0x8,
3354
14
            NULL, HFILL }
3355
14
        },
3356
14
        { &hf_btl2cap_info_fixedchans_rfu,
3357
14
          { "Reserved for future use", "btl2cap.info_fixedchans_rfu",
3358
14
            FT_UINT32, BASE_DEC, NULL, 0x00000070,
3359
14
            NULL, HFILL }
3360
14
        },
3361
14
        { &hf_btl2cap_info_fixedchans_smp,
3362
14
          { "BR/EDR Security Manager", "btl2cap.info_fixedchans_smp",
3363
14
            FT_UINT32, BASE_DEC, NULL, 0x00000080,
3364
14
            NULL, HFILL }
3365
14
        },
3366
14
        { &hf_btl2cap_info_fixedchans_amp_test,
3367
14
          { "AMP Test Manager", "btl2cap.info_fixedchans_amp_test",
3368
14
            FT_UINT32, BASE_DEC, NULL, 0x80000000,
3369
14
            NULL, HFILL }
3370
14
        },
3371
14
        { &hf_btl2cap_info_type,
3372
14
          { "Information Type",           "btl2cap.info_type",
3373
14
            FT_UINT16, BASE_HEX, VALS(info_type_vals), 0x0,
3374
14
            "Type of implementation-specific information", HFILL }
3375
14
        },
3376
14
        { &hf_btl2cap_info_result,
3377
14
          { "Result",           "btl2cap.info_result",
3378
14
            FT_UINT16, BASE_HEX, VALS(info_result_vals), 0x0,
3379
14
            "Information about the success of the request", HFILL }
3380
14
        },
3381
14
        { &hf_btl2cap_info_extfeatures,
3382
14
          { "Extended Features",           "btl2cap.info_extfeatures",
3383
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3384
14
            "Extended Features Mask", HFILL }
3385
14
        },
3386
14
        { &hf_btl2cap_flags_reserved,
3387
14
          { "Reserved",           "btl2cap.flags.reserved",
3388
14
            FT_UINT16, BASE_HEX, NULL, 0xFFFE,
3389
14
            NULL, HFILL }
3390
14
        },
3391
14
        { &hf_btl2cap_flags_continuation,
3392
14
          { "Continuation Flag",           "btl2cap.flags.continuation",
3393
14
            FT_BOOLEAN, 16, NULL, 0x0001,
3394
14
            NULL, HFILL }
3395
14
        },
3396
14
        { &hf_btl2cap_configuration_result,
3397
14
          { "Result",           "btl2cap.conf_result",
3398
14
            FT_UINT16, BASE_HEX, VALS(configuration_result_vals), 0x0,
3399
14
            "Configuration Result", HFILL }
3400
14
        },
3401
14
        { &hf_btl2cap_option_type,
3402
14
          { "Type",           "btl2cap.option_type",
3403
14
            FT_UINT8, BASE_HEX, VALS(option_type_vals), 0x0,
3404
14
            "Type of option", HFILL }
3405
14
        },
3406
14
        { &hf_btl2cap_option_length,
3407
14
          { "Length",           "btl2cap.option_length",
3408
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3409
14
            "Number of octets in option payload", HFILL }
3410
14
        },
3411
14
        { &hf_btl2cap_option_mtu,
3412
14
          { "MTU",           "btl2cap.option_mtu",
3413
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3414
14
            "Maximum Transmission Unit", HFILL }
3415
14
        },
3416
14
        { &hf_btl2cap_option_flushTO,
3417
14
          { "Flush Timeout (ms)",           "btl2cap.option_flushto",
3418
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3419
14
            "Flush Timeout in milliseconds", HFILL }
3420
14
        },
3421
14
        { &hf_btl2cap_option_flush_to_us,
3422
14
          { "Flush Timeout (us)",           "btl2cap.option_flushto",
3423
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3424
14
            "Flush Timeout (microseconds)", HFILL }
3425
14
        },
3426
14
        { &hf_btl2cap_option_sdu_size,
3427
14
          { "Maximum SDU Size",           "btl2cap.option_sdu_size",
3428
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3429
14
            NULL, HFILL }
3430
14
        },
3431
14
        { &hf_btl2cap_option_sdu_arrival_time,
3432
14
          { "SDU Inter-arrival Time (us)",           "btl2cap.option_sdu_arrival_time",
3433
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3434
14
            "SDU Inter-arrival Time (microseconds)", HFILL }
3435
14
        },
3436
14
        { &hf_btl2cap_option_identifier,
3437
14
          { "Identifier",           "btl2cap.option_ident",
3438
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
3439
14
            "Flow Specification Identifier", HFILL }
3440
14
        },
3441
14
        { &hf_btl2cap_option_access_latency,
3442
14
          { "Access Latency (us)",           "btl2cap.option_access_latency",
3443
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3444
14
            "Access Latency (microseconds)", HFILL }
3445
14
        },
3446
14
        { &hf_btl2cap_option_flags,
3447
14
          { "Flags",           "btl2cap.option_flags",
3448
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
3449
14
            "Flags - must be set to 0 (Reserved for future use)", HFILL }
3450
14
        },
3451
14
        { &hf_btl2cap_option_service_type,
3452
14
          { "Service Type",           "btl2cap.option_servicetype",
3453
14
            FT_UINT8, BASE_HEX, VALS(option_servicetype_vals), 0x0,
3454
14
            "Level of service required", HFILL }
3455
14
        },
3456
14
        { &hf_btl2cap_option_tokenrate,
3457
14
          { "Token Rate (bytes/s)",           "btl2cap.option_tokenrate",
3458
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3459
14
            "Rate at which traffic credits are granted (bytes/s)", HFILL }
3460
14
        },
3461
14
        { &hf_btl2cap_option_tokenbucketsize,
3462
14
          { "Token Bucket Size (bytes)",           "btl2cap.option_tokenbsize",
3463
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3464
14
            "Size of the token bucket (bytes)", HFILL }
3465
14
        },
3466
14
        { &hf_btl2cap_option_peakbandwidth,
3467
14
          { "Peak Bandwidth (bytes/s)",           "btl2cap.option_peakbandwidth",
3468
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3469
14
            "Limit how fast packets may be sent (bytes/s)", HFILL }
3470
14
        },
3471
14
        { &hf_btl2cap_option_latency,
3472
14
          { "Latency (microseconds)",           "btl2cap.option_latency",
3473
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3474
14
            "Maximal acceptable delay (microseconds)", HFILL }
3475
14
        },
3476
14
        { &hf_btl2cap_option_delayvariation,
3477
14
          { "Delay Variation (microseconds)",           "btl2cap.option_delayvar",
3478
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3479
14
            "Difference between maximum and minimum delay (microseconds)", HFILL }
3480
14
        },
3481
14
        { &hf_btl2cap_option_retransmissionmode,
3482
14
          { "Mode",                               "btl2cap.retransmissionmode",
3483
14
            FT_UINT8, BASE_HEX, VALS(option_retransmissionmode_vals), 0x0,
3484
14
            "Retransmission/Flow Control mode", HFILL }
3485
14
        },
3486
14
        { &hf_btl2cap_option_txwindow,
3487
14
          { "TxWindow",                           "btl2cap.txwindow",
3488
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3489
14
            "Retransmission window size", HFILL }
3490
14
        },
3491
14
        { &hf_btl2cap_option_maxtransmit,
3492
14
          { "MaxTransmit",                        "btl2cap.maxtransmit",
3493
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3494
14
            "Maximum I-frame retransmissions", HFILL }
3495
14
        },
3496
14
        { &hf_btl2cap_option_retransmittimeout,
3497
14
          { "Retransmit timeout (ms)",            "btl2cap.retransmittimeout",
3498
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3499
14
            "Retransmission timeout (milliseconds)", HFILL }
3500
14
        },
3501
14
        { &hf_btl2cap_option_monitortimeout,
3502
14
          { "Monitor Timeout (ms)",               "btl2cap.monitortimeout",
3503
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3504
14
            "S-frame transmission interval (milliseconds)", HFILL }
3505
14
        },
3506
14
        { &hf_btl2cap_option_mps,
3507
14
          { "MPS",                                "btl2cap.mps",
3508
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3509
14
            "Maximum PDU Payload Size", HFILL }
3510
14
        },
3511
14
        { &hf_btl2cap_option_fcs,
3512
14
          { "FCS",           "btl2cap.option_fcs",
3513
14
            FT_UINT16, BASE_HEX, VALS(option_fcs_vals), 0x0,
3514
14
            "Frame Check Sequence", HFILL }
3515
14
        },
3516
14
        { &hf_btl2cap_option_window,
3517
14
          { "Extended Window Size",           "btl2cap.option_window",
3518
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3519
14
            NULL, HFILL }
3520
14
        },
3521
14
        { &hf_btl2cap_option,
3522
14
          { "Configuration Parameter Option",           "btl2cap.conf_param_option",
3523
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3524
14
            NULL, HFILL }
3525
14
        },
3526
14
        { &hf_btl2cap_control_sar,
3527
14
          { "Segmentation and reassembly",           "btl2cap.control_sar",
3528
14
            FT_UINT16, BASE_HEX, VALS(control_sar_vals), 0xC000,
3529
14
            NULL, HFILL }
3530
14
        },
3531
14
        { &hf_btl2cap_control_reqseq,
3532
14
          { "ReqSeq",           "btl2cap.control_reqseq",
3533
14
            FT_UINT16, BASE_DEC, NULL, 0x3F00,
3534
14
            "Request Sequence Number", HFILL }
3535
14
        },
3536
14
        { &hf_btl2cap_control_txseq,
3537
14
          { "TxSeq",           "btl2cap.control_txseq",
3538
14
            FT_UINT16, BASE_DEC, NULL, 0x007E,
3539
14
            "Transmitted Sequence Number", HFILL }
3540
14
        },
3541
14
        { &hf_btl2cap_control_retransmissiondisable,
3542
14
          { "R",           "btl2cap.control_retransmissiondisable",
3543
14
            FT_UINT16, BASE_HEX, NULL, 0x0080,
3544
14
            "Retransmission Disable", HFILL }
3545
14
        },
3546
14
        { &hf_btl2cap_control_supervisory,
3547
14
          { "S",           "btl2cap.control_supervisory",
3548
14
            FT_UINT16, BASE_HEX, VALS(control_supervisory_vals), 0x000C,
3549
14
            "Supervisory Function", HFILL }
3550
14
        },
3551
14
        { &hf_btl2cap_control_type,
3552
14
          { "Frame Type",           "btl2cap.control_type",
3553
14
            FT_UINT16, BASE_HEX, VALS(control_type_vals), 0x0001,
3554
14
            NULL, HFILL }
3555
14
        },
3556
14
        { &hf_btl2cap_control,
3557
14
          { "Control field",           "btl2cap.control",
3558
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3559
14
            NULL, HFILL }
3560
14
        },
3561
14
        { &hf_btl2cap_fcs,
3562
14
          { "FCS",           "btl2cap.fcs",
3563
14
            FT_UINT16, BASE_HEX, NULL, 0,
3564
14
            "Frame Check Sequence", HFILL }
3565
14
        },
3566
14
        { &hf_btl2cap_sdulength,
3567
14
          { "SDU Length",           "btl2cap.sdulength",
3568
14
            FT_UINT16, BASE_DEC, NULL, 0,
3569
14
            NULL, HFILL }
3570
14
        },
3571
14
        { &hf_btl2cap_reassembled_in,
3572
14
          { "This SDU is reassembled in frame",           "btl2cap.reassembled_in",
3573
14
            FT_FRAMENUM, BASE_NONE, NULL, 0,
3574
14
            "This SDU is reassembled in frame #", HFILL }
3575
14
        },
3576
14
        { &hf_btl2cap_continuation_to,
3577
14
          { "This is a continuation to the SDU in frame",           "btl2cap.continuation_to",
3578
14
            FT_FRAMENUM, BASE_NONE, NULL, 0,
3579
14
            "This is a continuation to the SDU in frame #", HFILL }
3580
14
        },
3581
14
        { &hf_btl2cap_min_interval,
3582
14
          { "Min. Interval",           "btl2cap.min_interval",
3583
14
            FT_UINT16, BASE_DEC, NULL, 0,
3584
14
            NULL, HFILL }
3585
14
        },
3586
14
        { &hf_btl2cap_max_interval,
3587
14
          { "Max. Interval",           "btl2cap.max_interval",
3588
14
            FT_UINT16, BASE_DEC, NULL, 0,
3589
14
            NULL, HFILL }
3590
14
        },
3591
14
        { &hf_btl2cap_peripheral_latency,
3592
14
          { "Peripheral Latency",           "btl2cap.peripheral_latency",
3593
14
            FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_ll_connection_event), 0,
3594
14
            NULL, HFILL }
3595
14
        },
3596
14
        { &hf_btl2cap_timeout_multiplier,
3597
14
          { "Timeout Multiplier",           "btl2cap.timeout_multiplier",
3598
14
            FT_UINT16, BASE_DEC, NULL, 0,
3599
14
            NULL, HFILL }
3600
14
        },
3601
14
        { &hf_btl2cap_conn_param_result,
3602
14
          { "Move Result",           "btl2cap.move_result",
3603
14
            FT_UINT16, BASE_HEX, VALS(conn_param_result_vals), 0x0,
3604
14
            NULL, HFILL }
3605
14
        },
3606
14
        { &hf_btl2cap_le_result,
3607
14
          { "LE Result",           "btl2cap.le_result",
3608
14
            FT_UINT16, BASE_HEX, VALS(le_result_vals), 0x0,
3609
14
            NULL, HFILL }
3610
14
        },
3611
14
        { &hf_btl2cap_credits,
3612
14
          { "Credits",               "btl2cap.credits",
3613
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3614
14
            "L2CAP Channel Identifier", HFILL }
3615
14
        },
3616
14
        { &hf_btl2cap_initial_credits,
3617
14
          { "Initial Credits",       "btl2cap.initial_credits",
3618
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3619
14
            "L2CAP Channel Identifier", HFILL }
3620
14
        },
3621
14
        { &hf_btl2cap_le_psm,
3622
14
          { "LE PSM",           "btl2cap.le_psm",
3623
14
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(le_psm_rvals), 0x0,
3624
14
            "Protocol/Service Multiplexer", HFILL }
3625
14
        },
3626
14
        { &hf_btl2cap_data,
3627
14
          { "Data",           "btl2cap.data",
3628
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3629
14
            NULL, HFILL }
3630
14
        },
3631
14
        { &hf_btl2cap_service,
3632
14
          { "Service",           "btl2cap.service",
3633
14
            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bluetooth_uuid_vals_ext, 0x0,
3634
14
            NULL, HFILL }
3635
14
        },
3636
14
        { &hf_btl2cap_connect_in_frame,
3637
14
            { "Connect in frame",                            "btl2cap.connect_in",
3638
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3639
14
            NULL, HFILL }
3640
14
        },
3641
14
        { &hf_btl2cap_disconnect_in_frame,
3642
14
            { "Disconnect in frame",                         "btl2cap.disconnect_in",
3643
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3644
14
            NULL, HFILL }
3645
14
        },
3646
14
        { &hf_btl2cap_le_sdu_fragments,
3647
14
        { "SDU fragments", "btl2cap.le_sdu.fragments",
3648
14
            FT_NONE, BASE_NONE, NULL, 0x00,
3649
14
            NULL, HFILL }
3650
14
        },
3651
14
        { &hf_btl2cap_le_sdu_fragment,
3652
14
        { "SDU fragment", "btl2cap.le_sdu.fragment",
3653
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3654
14
            NULL, HFILL }
3655
14
        },
3656
14
        { &hf_btl2cap_le_sdu_fragment_overlap,
3657
14
        { "SDU fragment overlap", "btl2cap.le_sdu.fragment.overlap",
3658
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3659
14
            NULL, HFILL }
3660
14
        },
3661
14
        { &hf_btl2cap_le_sdu_fragment_overlap_conflicts,
3662
14
        { "SDU fragment overlapping with conflicting data", "btl2cap.le_sdu.fragment.overlap.conflicts",
3663
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3664
14
            NULL, HFILL }
3665
14
        },
3666
14
        { &hf_btl2cap_le_sdu_fragment_multiple_tails,
3667
14
        { "SDU has multiple tail fragments", "btl2cap.le_sdu.fragment.multiple_tails",
3668
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3669
14
            NULL, HFILL }
3670
14
        },
3671
14
        { &hf_btl2cap_le_sdu_fragment_too_long_fragment,
3672
14
        { "SDU fragment too long", "btl2cap.le_sdu.fragment.too_long_fragment",
3673
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3674
14
            NULL, HFILL }
3675
14
        },
3676
14
        { &hf_btl2cap_le_sdu_fragment_error,
3677
14
        { "SDU defragmentation error", "btl2cap.le_sdu.fragment.error",
3678
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3679
14
            NULL, HFILL }
3680
14
        },
3681
14
        { &hf_btl2cap_le_sdu_fragment_count,
3682
14
        { "SDU fragment count", "btl2cap.le_sdu.fragment.count",
3683
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
3684
14
            NULL, HFILL }
3685
14
        },
3686
14
        { &hf_btl2cap_le_sdu_reassembled_in,
3687
14
        { "Reassembled in", "btl2cap.le_sdu.reassembled.in",
3688
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3689
14
            NULL, HFILL }
3690
14
        },
3691
14
        { &hf_btl2cap_le_sdu_reassembled_length,
3692
14
        { "Reassembled SDU length", "btl2cap.le_sdu.reassembled.length",
3693
14
            FT_UINT32, BASE_DEC, NULL, 0x00,
3694
14
            NULL, HFILL }
3695
14
        },
3696
14
        { &hf_btl2cap_le_sdu_length,
3697
14
        { "SDU Length", "btl2cap.le_sdu_length",
3698
14
            FT_UINT16, BASE_DEC, NULL, 0x00,
3699
14
            NULL, HFILL }
3700
14
        },
3701
3702
14
    };
3703
3704
    /* Setup protocol subtree array */
3705
14
    static int *ett[] = {
3706
14
        &ett_btl2cap,
3707
14
        &ett_btl2cap_cmd,
3708
14
        &ett_btl2cap_option,
3709
14
        &ett_btl2cap_extfeatures,
3710
14
        &ett_btl2cap_fixedchans,
3711
14
        &ett_btl2cap_control,
3712
14
        &ett_btl2cap_le_sdu_fragment,
3713
14
        &ett_btl2cap_le_sdu_fragments
3714
14
    };
3715
3716
14
    static ei_register_info ei[] = {
3717
14
        { &ei_btl2cap_parameter_mismatch, { "btl2cap.parameter_mismatch", PI_PROTOCOL, PI_WARN, "Parameter mismatch", EXPFILL }},
3718
14
        { &ei_btl2cap_sdulength_bad, { "btl2cap.sdulength.bad", PI_MALFORMED, PI_WARN, "SDU length bad", EXPFILL }},
3719
14
        { &ei_btl2cap_length_bad, { "btl2cap.length.bad", PI_MALFORMED, PI_WARN, "Length too short", EXPFILL }},
3720
14
        { &ei_btl2cap_unknown_command_code, { "btl2cap.unknown_command_code", PI_PROTOCOL, PI_WARN, "Unknown Command Code", EXPFILL }},
3721
14
    };
3722
3723
    /* Decode As handling */
3724
14
    static build_valid_func btl2cap_cid_da_build_value[1] = {btl2cap_cid_value};
3725
14
    static decode_as_value_t btl2cap_cid_da_values = {btl2cap_cid_prompt, 1, btl2cap_cid_da_build_value};
3726
14
    static decode_as_t btl2cap_cid_da = {"btl2cap", "btl2cap.cid", 1, 0, &btl2cap_cid_da_values, NULL, NULL,
3727
14
                                 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
3728
3729
14
    static build_valid_func btl2cap_psm_da_build_value[1] = {btl2cap_psm_value};
3730
14
    static decode_as_value_t btl2cap_psm_da_values = {btl2cap_psm_prompt, 1, btl2cap_psm_da_build_value};
3731
14
    static decode_as_t btl2cap_psm_da = {"btl2cap", "btl2cap.psm", 1, 0, &btl2cap_psm_da_values, NULL, NULL,
3732
14
                                 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
3733
3734
    /* Register the protocol name and description */
3735
14
    proto_btl2cap = proto_register_protocol("Bluetooth L2CAP Protocol", "BT L2CAP", "btl2cap");
3736
3737
14
    register_dissector("btl2cap", dissect_btl2cap, proto_btl2cap);
3738
3739
    /* subdissector code */
3740
14
    l2cap_psm_dissector_table = register_dissector_table("btl2cap.psm", "BT L2CAP PSM", proto_btl2cap, FT_UINT16, BASE_HEX);
3741
14
    l2cap_cid_dissector_table = register_dissector_table("btl2cap.cid", "BT L2CAP CID", proto_btl2cap, FT_UINT16, BASE_HEX);
3742
3743
    /* Required function calls to register the header fields and subtrees used */
3744
14
    proto_register_field_array(proto_btl2cap, hf, array_length(hf));
3745
14
    proto_register_subtree_array(ett, array_length(ett));
3746
14
    expert_btl2cap = expert_register_protocol(proto_btl2cap);
3747
14
    expert_register_field_array(expert_btl2cap, ei, array_length(ei));
3748
3749
14
    cmd_ident_to_psm_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3750
14
    cid_to_psm_table     = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3751
3752
14
    register_decode_as(&btl2cap_cid_da);
3753
14
    register_decode_as(&btl2cap_psm_da);
3754
3755
14
    reassembly_table_register(&btl2cap_le_sdu_reassembly_table,
3756
14
        &addresses_reassembly_table_functions);
3757
14
}
3758
3759
3760
void
3761
proto_reg_handoff_btl2cap(void)
3762
14
{
3763
14
}
3764
3765
/*
3766
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3767
 *
3768
 * Local variables:
3769
 * c-basic-offset: 4
3770
 * tab-width: 8
3771
 * indent-tabs-mode: nil
3772
 * End:
3773
 *
3774
 * vi: set shiftwidth=4 tabstop=8 expandtab:
3775
 * :indentSize=4:tabSize=8:noTabs=true:
3776
 */