Coverage Report

Created: 2025-02-15 06:25

/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
6.29k
#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
2.09k
#define PROTO_DATA_BTL2CAP_CID        0
453
477
#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
3.23k
{
534
3.23k
    wmem_tree_key_t    key[10];
535
3.23k
    uint32_t           k_interface_id;
536
3.23k
    uint32_t           k_adapter_id;
537
3.23k
    uint32_t           k_sdp_psm;
538
3.23k
    uint32_t           k_direction;
539
3.23k
    uint32_t           k_bd_addr_oui;
540
3.23k
    uint32_t           k_bd_addr_id;
541
3.23k
    uint32_t           k_service_type;
542
3.23k
    uint32_t           k_service_channel;
543
3.23k
    uint32_t           k_frame_number;
544
3.23k
    uint32_t           interface_id;
545
3.23k
    uint32_t           adapter_id;
546
3.23k
    uint32_t           remote_bd_addr_oui;
547
3.23k
    uint32_t           remote_bd_addr_id;
548
3.23k
    service_info_t    *service_info;
549
550
3.23k
    interface_id       = l2cap_data->interface_id;
551
3.23k
    adapter_id         = l2cap_data->adapter_id;
552
553
3.23k
    k_interface_id    = interface_id;
554
3.23k
    k_adapter_id      = adapter_id;
555
3.23k
    k_sdp_psm         = SDP_PSM_DEFAULT;
556
3.23k
    k_direction       = (is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
557
3.23k
    if (k_direction == P2P_DIR_RECV) {
558
3.23k
        k_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
559
3.23k
        k_bd_addr_id  = l2cap_data->remote_bd_addr_id;
560
3.23k
    } else {
561
0
        k_bd_addr_oui = 0;
562
0
        k_bd_addr_id  = 0;
563
0
    }
564
565
3.23k
    remote_bd_addr_oui = k_bd_addr_oui;
566
3.23k
    remote_bd_addr_id  = k_bd_addr_id;
567
568
3.23k
    k_service_type    = BTSDP_L2CAP_PROTOCOL_UUID;
569
3.23k
    k_service_channel = psm;
570
3.23k
    k_frame_number    = pinfo->num;
571
572
3.23k
    key[0].length = 1;
573
3.23k
    key[0].key = &k_interface_id;
574
3.23k
    key[1].length = 1;
575
3.23k
    key[1].key = &k_adapter_id;
576
3.23k
    key[2].length = 1;
577
3.23k
    key[2].key = &k_sdp_psm;
578
3.23k
    key[3].length = 1;
579
3.23k
    key[3].key = &k_direction;
580
3.23k
    key[4].length = 1;
581
3.23k
    key[4].key = &k_bd_addr_oui;
582
3.23k
    key[5].length = 1;
583
3.23k
    key[5].key = &k_bd_addr_id;
584
3.23k
    key[6].length = 1;
585
3.23k
    key[6].key = &k_service_type;
586
3.23k
    key[7].length = 1;
587
3.23k
    key[7].key = &k_service_channel;
588
3.23k
    key[8].length = 1;
589
3.23k
    key[8].key = &k_frame_number;
590
3.23k
    key[9].length = 0;
591
3.23k
    key[9].key = NULL;
592
593
3.23k
    service_info = btsdp_get_service_info(key);
594
595
3.23k
    if (service_info &&
596
3.23k
        service_info->interface_id == interface_id &&
597
3.23k
        service_info->adapter_id == adapter_id &&
598
3.23k
        service_info->sdp_psm == SDP_PSM_DEFAULT &&
599
3.23k
        ((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
3.23k
        service_info->type == BTSDP_L2CAP_PROTOCOL_UUID &&
606
3.23k
        service_info->channel == psm)
607
0
    {
608
0
        return service_info->uuid.bt_uuid;
609
0
    }
610
611
3.23k
    return 0;
612
3.23k
}
613
614
static int
615
dissect_comrej(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
616
135
{
617
135
    uint16_t reason;
618
619
135
    reason  = tvb_get_letohs(tvb, offset);
620
135
    proto_tree_add_item(tree, hf_btl2cap_rej_reason, tvb, offset, 2, ENC_LITTLE_ENDIAN);
621
135
    offset += 2;
622
623
135
    switch (reason) {
624
1
    case 0x0000: /* Command not understood */
625
1
        break;
626
627
1
    case 0x0001: /* Signaling MTU exceeded */
628
1
        proto_tree_add_item(tree, hf_btl2cap_sig_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
629
1
        offset += 2;
630
1
        break;
631
632
1
    case 0x0002: /* Invalid CID in requests */
633
1
        proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
634
1
        offset += 2;
635
636
1
        proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
637
1
        offset += 2;
638
639
1
        break;
640
641
132
    default:
642
132
        break;
643
135
    }
644
645
135
    return offset;
646
135
}
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
55
{
653
55
    uint16_t           scid;
654
55
    uint16_t           psm;
655
55
    const char        *psm_str = "<NONE>";
656
657
55
    psm = tvb_get_letohs(tvb, offset);
658
659
55
    if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
660
42
        uint16_t *value_data;
661
662
42
        value_data = wmem_new(wmem_file_scope(), uint16_t);
663
42
        *value_data = psm;
664
665
42
        p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
666
42
    }
667
668
55
    if (psm < BTL2CAP_DYNAMIC_PSM_START) {
669
23
        proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
670
23
        psm_str = val_to_str_const(psm, psm_vals, "Unknown PSM");
671
32
    } else {
672
32
        proto_item  *item;
673
32
        uint16_t     uuid;
674
675
32
        item = proto_tree_add_item(command_tree, hf_btl2cap_psm_dynamic, tvb, offset, 2, ENC_LITTLE_ENDIAN);
676
677
32
        uuid = get_service_uuid(pinfo, l2cap_data, psm, (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false);
678
32
        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
32
    }
683
55
    offset += 2;
684
685
55
    scid = tvb_get_letohs(tvb, offset);
686
55
    proto_tree_add_item(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
687
55
    offset += 2;
688
689
55
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, SCID: 0x%04x)", psm_str, scid);
690
691
55
    if (is_ch_request) {
692
12
        proto_tree_add_item(command_tree, hf_btl2cap_controller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
693
12
        offset += 1;
694
12
    }
695
696
55
    if (!pinfo->fd->visited) {
697
55
        wmem_tree_key_t    key[6];
698
55
        uint32_t           k_interface_id;
699
55
        uint32_t           k_adapter_id;
700
55
        uint32_t           k_chandle;
701
55
        uint32_t           k_cid;
702
55
        uint32_t           k_frame_number;
703
55
        uint32_t           interface_id;
704
55
        uint32_t           adapter_id;
705
55
        uint32_t           chandle;
706
55
        psm_data_t        *psm_data;
707
708
55
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
709
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
710
55
        else
711
55
            interface_id = HCI_INTERFACE_DEFAULT;
712
55
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
713
55
        chandle      = (acl_data) ? acl_data->chandle : 0;
714
715
55
        k_interface_id = interface_id;
716
55
        k_adapter_id   = adapter_id;
717
55
        k_chandle      = chandle;
718
55
        k_cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x80000000 : 0x00000000);
719
55
        k_frame_number = pinfo->num;
720
721
55
        psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
722
55
        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
55
        } else {
726
55
            psm_data->local_cid = scid;
727
55
            psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
728
55
        }
729
55
        psm_data->psm  = psm;
730
55
        psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
731
55
        psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
732
55
        psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
733
55
        psm_data->interface_id = k_interface_id;
734
55
        psm_data->adapter_id   = k_adapter_id;
735
55
        psm_data->chandle      = k_chandle;
736
55
        psm_data->connect_in_frame = pinfo->num;
737
55
        psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
738
739
55
        key[0].length = 1;
740
55
        key[0].key    = &k_interface_id;
741
55
        key[1].length = 1;
742
55
        key[1].key    = &k_adapter_id;
743
55
        key[2].length = 1;
744
55
        key[2].key    = &k_chandle;
745
55
        key[3].length = 1;
746
55
        key[3].key    = &k_cid;
747
55
        key[4].length = 1;
748
55
        key[4].key    = &k_frame_number;
749
55
        key[5].length = 0;
750
55
        key[5].key    = NULL;
751
752
55
        wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
753
55
    }
754
755
55
    if (l2cap_data) {
756
55
        proto_item        *sub_item;
757
55
        uint32_t           bt_uuid = 0;
758
55
        uint32_t           disconnect_in_frame = 0;
759
55
        psm_data_t        *psm_data;
760
55
        wmem_tree_key_t    key[6];
761
55
        uint32_t           k_interface_id;
762
55
        uint32_t           k_adapter_id;
763
55
        uint32_t           k_chandle;
764
55
        uint32_t           k_cid;
765
55
        uint32_t           k_frame_number;
766
55
        uint32_t           interface_id;
767
55
        uint32_t           adapter_id;
768
55
        uint32_t           chandle;
769
770
55
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
771
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
772
55
        else
773
55
            interface_id = HCI_INTERFACE_DEFAULT;
774
55
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
775
55
        chandle      = (acl_data) ? acl_data->chandle : 0;
776
777
55
        k_interface_id = interface_id;
778
55
        k_adapter_id   = adapter_id;
779
55
        k_chandle      = chandle;
780
55
        k_cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x80000000 : 0x00000000);
781
55
        k_frame_number = pinfo->num;
782
783
55
        key[0].length = 1;
784
55
        key[0].key    = &k_interface_id;
785
55
        key[1].length = 1;
786
55
        key[1].key    = &k_adapter_id;
787
55
        key[2].length = 1;
788
55
        key[2].key    = &k_chandle;
789
55
        key[3].length = 1;
790
55
        key[3].key    = &k_cid;
791
55
        key[4].length = 1;
792
55
        key[4].key    = &k_frame_number;
793
55
        key[5].length = 0;
794
55
        key[5].key    = NULL;
795
796
55
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
797
55
        if (psm_data &&
798
55
            psm_data->interface_id == interface_id &&
799
55
            psm_data->adapter_id == adapter_id &&
800
55
            psm_data->chandle == chandle &&
801
55
            psm_data->local_cid == k_cid)
802
55
        {
803
55
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
804
55
            disconnect_in_frame = psm_data->disconnect_in_frame;
805
55
        }
806
807
55
        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
55
        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
55
    }
817
818
55
    return offset;
819
55
}
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
79
{
825
826
79
    proto_item  *psm_item;
827
79
    uint32_t     psm;
828
79
    uint32_t     scid;
829
830
831
79
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_le_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN, &psm);
832
79
    if (psm < 0x80) {
833
15
        psm_item = proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
834
15
        proto_item_set_generated(psm_item);
835
15
    }
836
79
    offset += 2;
837
838
79
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &scid);
839
79
    offset += 2;
840
841
79
    proto_tree_add_item(command_tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
842
79
    offset += 2;
843
844
79
    proto_tree_add_item(command_tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
845
79
    offset += 2;
846
847
79
    proto_tree_add_item(command_tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
848
79
    offset += 2;
849
850
79
    if (!pinfo->fd->visited) {
851
79
        wmem_tree_key_t    key[8];
852
79
        uint32_t           k_interface_id;
853
79
        uint32_t           k_adapter_id;
854
79
        uint32_t           k_chandle;
855
79
        uint32_t           k_cid;
856
79
        uint32_t           k_cmd_ident;
857
79
        uint32_t           k_frame_number;
858
79
        uint32_t           interface_id;
859
79
        uint32_t           adapter_id;
860
79
        uint32_t           chandle;
861
79
        psm_data_t        *psm_data;
862
79
        uint32_t           key_cid;
863
79
        uint32_t           cid_index;
864
865
79
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
866
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
867
79
        else
868
79
            interface_id = HCI_INTERFACE_DEFAULT;
869
79
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
870
79
        chandle = (acl_data) ? acl_data->chandle : 0;
871
872
79
        k_interface_id = interface_id;
873
79
        k_adapter_id = adapter_id;
874
79
        k_chandle = chandle;
875
79
        k_cid = cid;
876
79
        k_cmd_ident = cmd_ident;
877
79
        k_frame_number = pinfo->num;
878
79
        cid_index = 0;
879
880
79
        psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
881
882
79
        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
79
        else {
888
79
            key_cid = scid;
889
79
            psm_data->local_cid = key_cid;
890
79
            psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
891
79
        }
892
893
79
        psm_data->psm = psm;
894
79
        psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
895
79
        psm_data->in.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
896
79
        psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
897
79
        psm_data->out.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
898
79
        psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
899
79
        psm_data->interface_id = k_interface_id;
900
79
        psm_data->adapter_id = k_adapter_id;
901
79
        psm_data->chandle = k_chandle;
902
79
        psm_data->connect_in_frame = pinfo->num;
903
79
        psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
904
905
79
        key[0].length = 1;
906
79
        key[0].key = &k_interface_id;
907
79
        key[1].length = 1;
908
79
        key[1].key = &k_adapter_id;
909
79
        key[2].length = 1;
910
79
        key[2].key = &k_chandle;
911
79
        key[3].length = 1;
912
79
        key[3].key = &k_cid;
913
79
        key[4].length = 1;
914
79
        key[4].key = &k_cmd_ident;
915
79
        key[5].length = 1;
916
79
        key[5].key = &k_frame_number;
917
79
        key[6].length = 1;
918
79
        key[6].key = &cid_index;
919
79
        key[7].length = 0;
920
79
        key[7].key = NULL;
921
922
79
        wmem_tree_insert32_array(cmd_ident_to_psm_table, key, psm_data);
923
924
79
        k_cid = key_cid;
925
926
79
        key[4].length = 1;
927
79
        key[4].key = &k_frame_number;
928
79
        key[5].length = 0;
929
79
        key[5].key = NULL;
930
931
79
        wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
932
79
    }
933
934
79
    if (l2cap_data) {
935
79
        proto_item        *sub_item;
936
79
        uint32_t           bt_uuid = 0;
937
79
        uint32_t           disconnect_in_frame = 0;
938
79
        psm_data_t        *psm_data;
939
79
        wmem_tree_key_t    key[6];
940
79
        uint32_t           k_interface_id;
941
79
        uint32_t           k_adapter_id;
942
79
        uint32_t           k_chandle;
943
79
        uint32_t           k_cid;
944
79
        uint32_t           k_frame_number;
945
79
        uint32_t           interface_id;
946
79
        uint32_t           adapter_id;
947
79
        uint32_t           chandle;
948
949
79
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
950
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
951
79
        else
952
79
            interface_id = HCI_INTERFACE_DEFAULT;
953
79
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
954
79
        chandle = (acl_data) ? acl_data->chandle : 0;
955
956
79
        k_interface_id = interface_id;
957
79
        k_adapter_id = adapter_id;
958
79
        k_chandle = chandle;
959
79
        k_cid = scid;
960
79
        k_frame_number = pinfo->num;
961
962
79
        key[0].length = 1;
963
79
        key[0].key = &k_interface_id;
964
79
        key[1].length = 1;
965
79
        key[1].key = &k_adapter_id;
966
79
        key[2].length = 1;
967
79
        key[2].key = &k_chandle;
968
79
        key[3].length = 1;
969
79
        key[3].key = &k_cid;
970
79
        key[4].length = 1;
971
79
        key[4].key = &k_frame_number;
972
79
        key[5].length = 0;
973
79
        key[5].key = NULL;
974
975
79
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
976
79
        if (psm_data &&
977
79
            psm_data->interface_id == interface_id &&
978
79
            psm_data->adapter_id == adapter_id &&
979
79
            psm_data->chandle == chandle &&
980
79
            psm_data->local_cid == k_cid)
981
79
        {
982
79
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
983
79
            disconnect_in_frame = psm_data->disconnect_in_frame;
984
79
        }
985
986
79
        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
79
        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
79
    }
996
997
79
    return offset;
998
79
}
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
1
{
1004
1
    uint32_t           dcid;
1005
1006
1
    proto_tree_add_item_ret_uint(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &dcid);
1007
1
    offset += 2;
1008
1009
1
    proto_tree_add_item(tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1010
1
    offset += 2;
1011
1012
1
    proto_tree_add_item(tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1013
1
    offset += 2;
1014
1015
1
    proto_tree_add_item(tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1016
1
    offset += 2;
1017
1018
1
    proto_tree_add_item(tree, hf_btl2cap_le_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1019
1
    offset += 2;
1020
1021
1022
1
    if (pinfo->fd->visited == 0) {
1023
1
        psm_data_t        *psm_data;
1024
1
        wmem_tree_key_t    key[8];
1025
1
        uint32_t           k_interface_id;
1026
1
        uint32_t           k_adapter_id;
1027
1
        uint32_t           k_chandle;
1028
1
        uint32_t           k_cid;
1029
1
        uint32_t           k_cmd_ident;
1030
1
        uint32_t           k_frame_number;
1031
1
        uint32_t           interface_id;
1032
1
        uint32_t           adapter_id;
1033
1
        uint32_t           chandle;
1034
1
        uint32_t           key_cid;
1035
1
        uint32_t           cid_index;
1036
1037
1
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1038
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1039
1
        else
1040
1
            interface_id = HCI_INTERFACE_DEFAULT;
1041
1
        adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1042
1
        chandle = (acl_data) ? acl_data->chandle : 0;
1043
1044
1
        k_interface_id = interface_id;
1045
1
        k_adapter_id = adapter_id;
1046
1
        k_chandle = chandle;
1047
1
        k_cid = cid;
1048
1
        k_cmd_ident = cmd_ident;
1049
1
        k_frame_number = pinfo->num;
1050
1
        cid_index = 0;
1051
1052
1
        key[0].length = 1;
1053
1
        key[0].key = &k_interface_id;
1054
1
        key[1].length = 1;
1055
1
        key[1].key = &k_adapter_id;
1056
1
        key[2].length = 1;
1057
1
        key[2].key = &k_chandle;
1058
1
        key[3].length = 1;
1059
1
        key[3].key = &k_cid;
1060
1
        key[4].length = 1;
1061
1
        key[4].key = &k_cmd_ident;
1062
1
        key[5].length = 1;
1063
1
        key[5].key = &k_frame_number;
1064
1
        key[6].length = 1;
1065
1
        key[6].key = &cid_index;
1066
1
        key[7].length = 0;
1067
1
        key[7].key = NULL;
1068
1069
1
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table, key);
1070
1
        if (psm_data &&
1071
1
            psm_data->interface_id == interface_id &&
1072
1
            psm_data->adapter_id == adapter_id &&
1073
1
            psm_data->chandle == chandle &&
1074
1
            psm_data->disconnect_in_frame > pinfo->num)
1075
1
        {
1076
1
            key_cid = dcid | ((pinfo->p2p_dir != P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1077
1078
1
            k_interface_id = interface_id;
1079
1
            k_adapter_id = adapter_id;
1080
1
            k_chandle = chandle;
1081
1
            k_cid = key_cid;
1082
1
            k_frame_number = pinfo->num;
1083
1084
1
            key[0].length = 1;
1085
1
            key[0].key = &k_interface_id;
1086
1
            key[1].length = 1;
1087
1
            key[1].key = &k_adapter_id;
1088
1
            key[2].length = 1;
1089
1
            key[2].key = &k_chandle;
1090
1
            key[3].length = 1;
1091
1
            key[3].key = &k_cid;
1092
1
            key[4].length = 1;
1093
1
            key[4].key = &k_frame_number;
1094
1
            key[5].length = 0;
1095
1
            key[5].key = NULL;
1096
1097
1
            if (pinfo->p2p_dir == P2P_DIR_RECV)
1098
0
                psm_data->remote_cid = key_cid;
1099
1
            else
1100
1
                psm_data->local_cid = key_cid;
1101
1102
1
            wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1103
1
        }
1104
1
    }
1105
1106
1
    return offset;
1107
1
}
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
33
{
1113
1114
33
    proto_item  *psm_item;
1115
33
    uint32_t     psm;
1116
33
    uint32_t     scid;
1117
33
    uint32_t     cid_index;
1118
1119
33
    proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_le_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN, &psm);
1120
33
    if (psm < 0x80) {
1121
10
        psm_item = proto_tree_add_item(command_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1122
10
        proto_item_set_generated(psm_item);
1123
10
    }
1124
33
    offset += 2;
1125
1126
33
    proto_tree_add_item(command_tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1127
33
    offset += 2;
1128
1129
33
    proto_tree_add_item(command_tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1130
33
    offset += 2;
1131
1132
33
    proto_tree_add_item(command_tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1133
33
    offset += 2;
1134
1135
33
    cid_index = 0;
1136
3.12k
    while (offset < length + 8) {
1137
3.09k
        proto_tree_add_item_ret_uint(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &scid);
1138
3.09k
        offset += 2;
1139
1140
3.09k
        if (!pinfo->fd->visited) {
1141
3.06k
            wmem_tree_key_t    key[8];
1142
3.06k
            uint32_t           k_interface_id;
1143
3.06k
            uint32_t           k_adapter_id;
1144
3.06k
            uint32_t           k_chandle;
1145
3.06k
            uint32_t           k_cid;
1146
3.06k
            uint32_t           k_cmd_ident;
1147
3.06k
            uint32_t           k_frame_number;
1148
3.06k
            uint32_t           interface_id;
1149
3.06k
            uint32_t           adapter_id;
1150
3.06k
            uint32_t           chandle;
1151
3.06k
            psm_data_t        *psm_data;
1152
3.06k
            uint32_t           key_cid;
1153
1154
3.06k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1155
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1156
3.06k
            else
1157
3.06k
                interface_id = HCI_INTERFACE_DEFAULT;
1158
3.06k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1159
3.06k
            chandle = (acl_data) ? acl_data->chandle : 0;
1160
1161
3.06k
            k_interface_id = interface_id;
1162
3.06k
            k_adapter_id = adapter_id;
1163
3.06k
            k_chandle = chandle;
1164
3.06k
            k_cid = cid;
1165
3.06k
            k_cmd_ident = cmd_ident;
1166
3.06k
            k_frame_number = pinfo->num;
1167
1168
3.06k
            psm_data = wmem_new0(wmem_file_scope(), psm_data_t);
1169
1170
3.06k
            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
3.06k
            else {
1176
3.06k
                key_cid = scid;
1177
3.06k
                psm_data->local_cid = key_cid;
1178
3.06k
                psm_data->remote_cid = BTL2CAP_UNKNOWN_CID;
1179
3.06k
            }
1180
1181
3.06k
            psm_data->psm = psm;
1182
3.06k
            psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false;
1183
3.06k
            psm_data->in.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
1184
3.06k
            psm_data->in.start_fragments = wmem_tree_new(wmem_file_scope());
1185
3.06k
            psm_data->out.mode = L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE;
1186
3.06k
            psm_data->out.start_fragments = wmem_tree_new(wmem_file_scope());
1187
3.06k
            psm_data->interface_id = k_interface_id;
1188
3.06k
            psm_data->adapter_id = k_adapter_id;
1189
3.06k
            psm_data->chandle = k_chandle;
1190
3.06k
            psm_data->connect_in_frame = pinfo->num;
1191
3.06k
            psm_data->disconnect_in_frame = bluetooth_max_disconnect_in_frame;
1192
1193
3.06k
            key[0].length = 1;
1194
3.06k
            key[0].key = &k_interface_id;
1195
3.06k
            key[1].length = 1;
1196
3.06k
            key[1].key = &k_adapter_id;
1197
3.06k
            key[2].length = 1;
1198
3.06k
            key[2].key = &k_chandle;
1199
3.06k
            key[3].length = 1;
1200
3.06k
            key[3].key = &k_cid;
1201
3.06k
            key[4].length = 1;
1202
3.06k
            key[4].key = &k_cmd_ident;
1203
3.06k
            key[5].length = 1;
1204
3.06k
            key[5].key = &k_frame_number;
1205
3.06k
            key[6].length = 1;
1206
3.06k
            key[6].key = &cid_index;
1207
3.06k
            key[7].length = 0;
1208
3.06k
            key[7].key = NULL;
1209
1210
3.06k
            wmem_tree_insert32_array(cmd_ident_to_psm_table, key, psm_data);
1211
1212
3.06k
            k_cid = key_cid;
1213
1214
3.06k
            key[4].length = 1;
1215
3.06k
            key[4].key = &k_frame_number;
1216
3.06k
            key[5].length = 0;
1217
3.06k
            key[5].key = NULL;
1218
1219
3.06k
            wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1220
3.06k
        }
1221
1222
3.09k
        if (l2cap_data) {
1223
3.06k
            proto_item        *sub_item;
1224
3.06k
            uint32_t           bt_uuid = 0;
1225
3.06k
            uint32_t           disconnect_in_frame = 0;
1226
3.06k
            psm_data_t        *psm_data;
1227
3.06k
            wmem_tree_key_t    key[6];
1228
3.06k
            uint32_t           k_interface_id;
1229
3.06k
            uint32_t           k_adapter_id;
1230
3.06k
            uint32_t           k_chandle;
1231
3.06k
            uint32_t           k_cid;
1232
3.06k
            uint32_t           k_frame_number;
1233
3.06k
            uint32_t           interface_id;
1234
3.06k
            uint32_t           adapter_id;
1235
3.06k
            uint32_t           chandle;
1236
1237
3.06k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1238
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1239
3.06k
            else
1240
3.06k
                interface_id = HCI_INTERFACE_DEFAULT;
1241
3.06k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1242
3.06k
            chandle = (acl_data) ? acl_data->chandle : 0;
1243
1244
3.06k
            k_interface_id = interface_id;
1245
3.06k
            k_adapter_id = adapter_id;
1246
3.06k
            k_chandle = chandle;
1247
3.06k
            k_cid = scid;
1248
3.06k
            k_frame_number = pinfo->num;
1249
1250
3.06k
            key[0].length = 1;
1251
3.06k
            key[0].key = &k_interface_id;
1252
3.06k
            key[1].length = 1;
1253
3.06k
            key[1].key = &k_adapter_id;
1254
3.06k
            key[2].length = 1;
1255
3.06k
            key[2].key = &k_chandle;
1256
3.06k
            key[3].length = 1;
1257
3.06k
            key[3].key = &k_cid;
1258
3.06k
            key[4].length = 1;
1259
3.06k
            key[4].key = &k_frame_number;
1260
3.06k
            key[5].length = 0;
1261
3.06k
            key[5].key = NULL;
1262
1263
3.06k
            psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1264
3.06k
            if (psm_data &&
1265
3.06k
                psm_data->interface_id == interface_id &&
1266
3.06k
                psm_data->adapter_id == adapter_id &&
1267
3.06k
                psm_data->chandle == chandle &&
1268
3.06k
                psm_data->local_cid == k_cid)
1269
3.06k
            {
1270
3.06k
                bt_uuid = get_service_uuid(pinfo, l2cap_data, psm_data->psm, psm_data->local_service);
1271
3.06k
                disconnect_in_frame = psm_data->disconnect_in_frame;
1272
3.06k
            }
1273
1274
3.06k
            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
3.06k
            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
3.06k
        }
1284
1285
3.09k
        cid_index++;
1286
3.09k
    }
1287
33
    return offset;
1288
33
}
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
9
{
1295
9
    uint32_t           dcid;
1296
9
    uint32_t           cid_index;
1297
1298
9
    proto_tree_add_item(tree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1299
9
    offset += 2;
1300
1301
9
    proto_tree_add_item(tree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1302
9
    offset += 2;
1303
1304
9
    proto_tree_add_item(tree, hf_btl2cap_initial_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1305
9
    offset += 2;
1306
1307
9
    proto_tree_add_item(tree, hf_btl2cap_le_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1308
9
    offset += 2;
1309
1310
9
    cid_index = 0;
1311
1.72k
    while (offset < length + 8) {
1312
1.72k
        proto_tree_add_item_ret_uint(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &dcid);
1313
1.72k
        offset += 2;
1314
1315
1.72k
        if (pinfo->fd->visited == 0) {
1316
1.71k
            psm_data_t        *psm_data;
1317
1.71k
            wmem_tree_key_t    key[8];
1318
1.71k
            uint32_t           k_interface_id;
1319
1.71k
            uint32_t           k_adapter_id;
1320
1.71k
            uint32_t           k_chandle;
1321
1.71k
            uint32_t           k_cid;
1322
1.71k
            uint32_t           k_cmd_ident;
1323
1.71k
            uint32_t           k_frame_number;
1324
1.71k
            uint32_t           interface_id;
1325
1.71k
            uint32_t           adapter_id;
1326
1.71k
            uint32_t           chandle;
1327
1.71k
            uint32_t           key_cid;
1328
1329
1.71k
            if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1330
0
                interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1331
1.71k
            else
1332
1.71k
                interface_id = HCI_INTERFACE_DEFAULT;
1333
1.71k
            adapter_id = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1334
1.71k
            chandle = (acl_data) ? acl_data->chandle : 0;
1335
1336
1.71k
            k_interface_id = interface_id;
1337
1.71k
            k_adapter_id = adapter_id;
1338
1.71k
            k_chandle = chandle;
1339
1.71k
            k_cid = cid;
1340
1.71k
            k_cmd_ident = cmd_ident;
1341
1.71k
            k_frame_number = pinfo->num;
1342
1343
1.71k
            key[0].length = 1;
1344
1.71k
            key[0].key = &k_interface_id;
1345
1.71k
            key[1].length = 1;
1346
1.71k
            key[1].key = &k_adapter_id;
1347
1.71k
            key[2].length = 1;
1348
1.71k
            key[2].key = &k_chandle;
1349
1.71k
            key[3].length = 1;
1350
1.71k
            key[3].key = &k_cid;
1351
1.71k
            key[4].length = 1;
1352
1.71k
            key[4].key = &k_cmd_ident;
1353
1.71k
            key[5].length = 1;
1354
1.71k
            key[5].key = &k_frame_number;
1355
1.71k
            key[6].length = 1;
1356
1.71k
            key[6].key = &cid_index;
1357
1.71k
            key[7].length = 0;
1358
1.71k
            key[7].key = NULL;
1359
1360
1.71k
            psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cmd_ident_to_psm_table, key);
1361
1.71k
            if (psm_data &&
1362
1.71k
                psm_data->interface_id == interface_id &&
1363
1.71k
                psm_data->adapter_id == adapter_id &&
1364
1.71k
                psm_data->chandle == chandle &&
1365
1.71k
                psm_data->disconnect_in_frame > pinfo->num)
1366
1.71k
            {
1367
1.71k
                key_cid = dcid | ((pinfo->p2p_dir != P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1368
1369
1.71k
                k_interface_id = interface_id;
1370
1.71k
                k_adapter_id = adapter_id;
1371
1.71k
                k_chandle = chandle;
1372
1.71k
                k_cid = key_cid;
1373
1.71k
                k_frame_number = pinfo->num;
1374
1375
1.71k
                key[0].length = 1;
1376
1.71k
                key[0].key = &k_interface_id;
1377
1.71k
                key[1].length = 1;
1378
1.71k
                key[1].key = &k_adapter_id;
1379
1.71k
                key[2].length = 1;
1380
1.71k
                key[2].key = &k_chandle;
1381
1.71k
                key[3].length = 1;
1382
1.71k
                key[3].key = &k_cid;
1383
1.71k
                key[4].length = 1;
1384
1.71k
                key[4].key = &k_frame_number;
1385
1.71k
                key[5].length = 0;
1386
1.71k
                key[5].key = NULL;
1387
1388
1.71k
                if (pinfo->p2p_dir == P2P_DIR_RECV)
1389
0
                    psm_data->remote_cid = key_cid;
1390
1.71k
                else
1391
1.71k
                    psm_data->local_cid = key_cid;
1392
1393
1.71k
                wmem_tree_insert32_array(cid_to_psm_table, key, psm_data);
1394
1.71k
            }
1395
1.71k
        }
1396
1.72k
        cid_index++;
1397
1.72k
    }
1398
9
    return offset;
1399
9
}
1400
static int
1401
dissect_movechanrequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1402
2
{
1403
2
    uint16_t icid;
1404
2
    uint8_t ctrl_id;
1405
1406
2
    icid = tvb_get_letohs(tvb, offset);
1407
2
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1408
2
    offset += 2;
1409
1410
2
    ctrl_id = tvb_get_uint8(tvb, offset);
1411
2
    proto_tree_add_item(tree, hf_btl2cap_dcontroller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1412
2
    offset += 1;
1413
1414
2
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, move to %s)", icid,
1415
2
                    val_to_str_const(ctrl_id, ctrl_id_code_vals, "Unknown controller"));
1416
1417
2
    return offset;
1418
2
}
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
63
{
1423
63
    proto_item *ti_option;
1424
63
    proto_tree *ti_option_subtree;
1425
63
    uint8_t     option_type, option_length;
1426
1427
63
    if (config_data) {
1428
0
        config_data->mode     = L2CAP_BASIC_MODE;
1429
0
        config_data->txwindow = 0;
1430
0
    }
1431
1432
770
    while (length > 0) {
1433
709
        option_type   = tvb_get_uint8(tvb, offset);
1434
709
        option_length = tvb_get_uint8(tvb, offset + 1);
1435
1436
709
        ti_option = proto_tree_add_none_format(tree,
1437
709
                hf_btl2cap_option, tvb,
1438
709
                offset, option_length + 2,
1439
709
                "Option: ");
1440
709
        ti_option_subtree = proto_item_add_subtree(ti_option, ett_btl2cap_option);
1441
709
        proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1442
709
        proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_length, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1443
709
        offset += 2;
1444
1445
709
        if (option_length != 0) {
1446
471
            switch (option_type) {
1447
13
            case 0x01: /* MTU */
1448
13
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1449
13
                offset += 2;
1450
1451
13
                proto_item_append_text(ti_option, "MTU");
1452
13
                break;
1453
1454
28
            case 0x02: /* Flush timeout */
1455
28
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flushTO, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1456
28
                offset += 2;
1457
1458
28
                proto_item_append_text(ti_option, "Flush Timeout");
1459
28
                break;
1460
1461
8
            case 0x03: /* QOS */
1462
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1463
8
                offset += 1;
1464
1465
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1466
8
                offset += 1;
1467
1468
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1469
8
                offset += 4;
1470
1471
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenbucketsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1472
8
                offset += 4;
1473
1474
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_peakbandwidth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1475
8
                offset += 4;
1476
1477
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1478
8
                offset += 4;
1479
1480
8
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_delayvariation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1481
8
                offset += 4;
1482
1483
8
                proto_item_append_text(ti_option, "QOS");
1484
8
                break;
1485
1486
6
            case 0x04: /* Retransmission and Flow Control*/
1487
6
                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
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmissionmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1493
6
                offset += 1;
1494
1495
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_txwindow, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1496
6
                offset += 1;
1497
1498
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_maxtransmit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1499
6
                offset += 1;
1500
1501
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmittimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1502
6
                offset += 2;
1503
1504
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_monitortimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1505
6
                offset += 2;
1506
1507
6
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1508
6
                offset += 2;
1509
1510
6
                proto_item_append_text(ti_option, "Retransmission and Flow Control");
1511
6
                break;
1512
1513
10
            case 0x05: /* FCS */
1514
10
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_fcs, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1515
10
                offset += 1;
1516
1517
10
                proto_item_append_text(ti_option, "FCS");
1518
10
                break;
1519
1520
17
            case 0x06: /* Extended Flow Specification */
1521
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_identifier, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1522
17
                offset += 1;
1523
1524
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1525
17
                offset += 1;
1526
1527
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1528
17
                offset += 2;
1529
1530
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_arrival_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1531
17
                offset += 4;
1532
1533
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_access_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1534
17
                offset += 4;
1535
1536
17
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flush_to_us, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1537
17
                offset += 4;
1538
1539
17
                proto_item_append_text(ti_option, "Extended Flow Specification");
1540
17
                break;
1541
1542
79
            case 0x07: /* Extended Window Size */
1543
79
                proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_window, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1544
79
                offset += 2;
1545
1546
79
                proto_item_append_text(ti_option, "Extended Window Size");
1547
79
                break;
1548
1549
310
            default:
1550
310
                proto_item_append_text(ti_option, "unknown");
1551
310
                offset += option_length;
1552
310
                break;
1553
471
            }
1554
471
        }
1555
707
        length -= (option_length + 2);
1556
707
    }
1557
61
    return offset;
1558
63
}
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
19
{
1566
19
    uint16_t dcid;
1567
1568
19
    dcid = tvb_get_letohs(tvb, offset);
1569
1570
19
    proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1571
19
    offset += 2;
1572
1573
19
    col_append_fstr(pinfo->cinfo, COL_INFO, " (DCID: 0x%04x)", dcid);
1574
1575
19
    proto_tree_add_item(tree, hf_btl2cap_flags_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1576
19
    proto_tree_add_item(tree, hf_btl2cap_flags_continuation, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1577
19
    offset += 2;
1578
1579
19
    {
1580
19
        psm_data_t        *psm_data;
1581
19
        config_data_t     *config_data;
1582
19
        wmem_tree_key_t    key[6];
1583
19
        uint32_t           k_interface_id;
1584
19
        uint32_t           k_adapter_id;
1585
19
        uint32_t           k_chandle;
1586
19
        uint32_t           k_cid;
1587
19
        uint32_t           k_frame_number;
1588
19
        uint32_t           interface_id;
1589
19
        uint32_t           adapter_id;
1590
19
        uint32_t           chandle;
1591
19
        uint32_t           cid;
1592
1593
19
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1594
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1595
19
        else
1596
19
            interface_id = HCI_INTERFACE_DEFAULT;
1597
19
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1598
19
        chandle      = (acl_data) ? acl_data->chandle : 0;
1599
19
        cid          = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1600
1601
19
        k_interface_id = interface_id;
1602
19
        k_adapter_id   = adapter_id;
1603
19
        k_chandle      = chandle;
1604
19
        k_cid          = cid;
1605
19
        k_frame_number = pinfo->num;
1606
1607
19
        key[0].length = 1;
1608
19
        key[0].key    = &k_interface_id;
1609
19
        key[1].length = 1;
1610
19
        key[1].key    = &k_adapter_id;
1611
19
        key[2].length = 1;
1612
19
        key[2].key    = &k_chandle;
1613
19
        key[3].length = 1;
1614
19
        key[3].key    = &k_cid;
1615
19
        key[4].length = 1;
1616
19
        key[4].key    = &k_frame_number;
1617
19
        key[5].length = 0;
1618
19
        key[5].key    = NULL;
1619
1620
19
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1621
19
        if (psm_data &&
1622
19
            psm_data->interface_id == interface_id &&
1623
19
            psm_data->adapter_id == adapter_id &&
1624
19
            psm_data->chandle == chandle &&
1625
19
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->remote_cid == cid) ||
1626
19
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->local_cid == cid)) &&
1627
19
            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
19
        } else {
1634
19
            config_data = NULL;
1635
19
        }
1636
19
        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
19
        if (tvb_reported_length_remaining(tvb, offset) > 0) {
1644
19
            offset = dissect_options(tvb, offset, pinfo, tree, length - 4, config_data);
1645
19
        }
1646
19
    }
1647
1648
19
    return offset;
1649
19
}
1650
1651
1652
static int
1653
dissect_inforequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1654
1
{
1655
1
    uint16_t info_type;
1656
1657
1
    info_type = tvb_get_letohs(tvb, offset);
1658
1
    proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1659
1
    offset   += 2;
1660
1661
1
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(info_type, info_type_vals, "Unknown type"));
1662
1
    return offset;
1663
1
}
1664
1665
static int
1666
dissect_inforesponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1667
1
{
1668
1
    uint16_t    info_type, result;
1669
1670
1
    info_type = tvb_get_letohs(tvb, offset);
1671
1
    proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1672
1
    offset   += 2;
1673
1674
1
    result    = tvb_get_letohs(tvb, offset);
1675
1
    proto_tree_add_item(tree, hf_btl2cap_info_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1676
1
    offset   += 2;
1677
1678
1
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, %s)",
1679
1
                        val_to_str_const(info_type, info_type_vals, "Unknown type"),
1680
1
                        val_to_str_const(result, info_result_vals, "Unknown result"));
1681
1682
1
    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
1
    return offset;
1761
1
}
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
44
{
1767
44
    uint16_t           scid;
1768
44
    uint16_t           result;
1769
1770
1771
44
    scid = tvb_get_letohs(tvb, offset);
1772
1773
44
    proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1774
44
    offset += 2;
1775
1776
44
    proto_tree_add_item(tree, hf_btl2cap_flags_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1777
44
    proto_tree_add_item(tree, hf_btl2cap_flags_continuation, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1778
44
    offset += 2;
1779
1780
44
    result = tvb_get_letohs(tvb, offset);
1781
44
    proto_tree_add_item(tree, hf_btl2cap_configuration_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1782
44
    offset += 2;
1783
1784
44
    col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
1785
44
                    val_to_str_const(result, configuration_result_vals, "Unknown"), scid);
1786
1787
44
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
1788
44
        psm_data_t        *psm_data;
1789
44
        config_data_t     *config_data;
1790
44
        wmem_tree_key_t    key[6];
1791
44
        uint32_t           k_interface_id;
1792
44
        uint32_t           k_adapter_id;
1793
44
        uint32_t           k_chandle;
1794
44
        uint32_t           k_cid;
1795
44
        uint32_t           k_frame_number;
1796
44
        uint32_t           interface_id;
1797
44
        uint32_t           adapter_id;
1798
44
        uint32_t           chandle;
1799
44
        uint32_t           cid;
1800
1801
44
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1802
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1803
44
        else
1804
44
            interface_id = HCI_INTERFACE_DEFAULT;
1805
44
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1806
44
        chandle      = (acl_data) ? acl_data->chandle : 0;
1807
44
        cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1808
1809
44
        k_interface_id = interface_id;
1810
44
        k_adapter_id   = adapter_id;
1811
44
        k_chandle      = chandle;
1812
44
        k_cid          = cid;
1813
44
        k_frame_number = pinfo->num;
1814
1815
44
        key[0].length = 1;
1816
44
        key[0].key    = &k_interface_id;
1817
44
        key[1].length = 1;
1818
44
        key[1].key    = &k_adapter_id;
1819
44
        key[2].length = 1;
1820
44
        key[2].key    = &k_chandle;
1821
44
        key[3].length = 1;
1822
44
        key[3].key    = &k_cid;
1823
44
        key[4].length = 1;
1824
44
        key[4].key    = &k_frame_number;
1825
44
        key[5].length = 0;
1826
44
        key[5].key    = NULL;
1827
1828
44
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1829
44
        if (psm_data &&
1830
44
            psm_data->interface_id == interface_id &&
1831
44
            psm_data->adapter_id == adapter_id &&
1832
44
            psm_data->chandle == chandle &&
1833
44
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->local_cid == cid) ||
1834
44
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->remote_cid == cid)) &&
1835
44
            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
44
        } else {
1842
44
            config_data = NULL;
1843
44
        }
1844
44
        offset = dissect_options(tvb, offset, pinfo, tree, length - 6, config_data);
1845
44
    }
1846
1847
44
    return offset;
1848
44
}
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
19
{
1854
19
    uint16_t           scid, dcid, result;
1855
1856
19
    dcid = tvb_get_letohs(tvb, offset);
1857
19
    proto_tree_add_item(tree, hf_btl2cap_dcid,   tvb, offset, 2, ENC_LITTLE_ENDIAN);
1858
19
    offset += 2;
1859
1860
19
    scid = tvb_get_letohs(tvb, offset);
1861
19
    proto_tree_add_item(tree, hf_btl2cap_scid,   tvb, offset, 2, ENC_LITTLE_ENDIAN);
1862
19
    offset += 2;
1863
1864
19
    result = tvb_get_letohs(tvb, offset);
1865
19
    proto_tree_add_item(tree, hf_btl2cap_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1866
19
    offset += 2;
1867
1868
19
    proto_tree_add_item(tree, hf_btl2cap_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1869
19
    offset += 2;
1870
1871
19
    if (result == 0) {
1872
2
        col_append_fstr(pinfo->cinfo, COL_INFO, " - Success (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
1873
2
    }
1874
17
    else {
1875
17
        col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
1876
17
                        val_to_str_const(result, result_vals, "Unknown"), scid);
1877
17
    }
1878
1879
19
    if (pinfo->fd->visited == 0) {
1880
18
        psm_data_t        *psm_data;
1881
18
        wmem_tree_key_t    key[6];
1882
18
        uint32_t           k_interface_id;
1883
18
        uint32_t           k_adapter_id;
1884
18
        uint32_t           k_chandle;
1885
18
        uint32_t           k_cid;
1886
18
        uint32_t           k_frame_number;
1887
18
        uint32_t           interface_id;
1888
18
        uint32_t           adapter_id;
1889
18
        uint32_t           chandle;
1890
18
        uint32_t           cid;
1891
1892
18
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
1893
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
1894
18
        else
1895
18
            interface_id = HCI_INTERFACE_DEFAULT;
1896
18
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
1897
18
        chandle      = (acl_data) ? acl_data->chandle : 0;
1898
18
        cid          = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
1899
1900
18
        k_interface_id = interface_id;
1901
18
        k_adapter_id   = adapter_id;
1902
18
        k_chandle      = chandle;
1903
18
        k_cid          = cid;
1904
18
        k_frame_number = pinfo->num;
1905
1906
18
        key[0].length = 1;
1907
18
        key[0].key    = &k_interface_id;
1908
18
        key[1].length = 1;
1909
18
        key[1].key    = &k_adapter_id;
1910
18
        key[2].length = 1;
1911
18
        key[2].key    = &k_chandle;
1912
18
        key[3].length = 1;
1913
18
        key[3].key    = &k_cid;
1914
18
        key[4].length = 1;
1915
18
        key[4].key    = &k_frame_number;
1916
18
        key[5].length = 0;
1917
18
        key[5].key    = NULL;
1918
1919
18
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
1920
18
        if (psm_data &&
1921
18
            psm_data->interface_id == interface_id &&
1922
18
            psm_data->adapter_id == adapter_id &&
1923
18
            psm_data->chandle == chandle &&
1924
18
            ((pinfo->p2p_dir == P2P_DIR_SENT && psm_data->remote_cid == cid) ||
1925
18
             (pinfo->p2p_dir == P2P_DIR_RECV && psm_data->local_cid == cid)) &&
1926
18
            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
18
    }
1957
1958
19
    return offset;
1959
19
}
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
11
{
1964
11
    return dissect_connresponse(tvb, offset, pinfo, tree, acl_data);
1965
11
}
1966
1967
static int
1968
dissect_movechanresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1969
18
{
1970
18
    uint16_t icid, result;
1971
1972
18
    icid = tvb_get_letohs(tvb, offset);
1973
18
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1974
18
    offset += 2;
1975
1976
18
    result = tvb_get_letohs(tvb, offset);
1977
18
    proto_tree_add_item(tree, hf_btl2cap_move_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1978
18
    offset += 2;
1979
1980
18
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
1981
18
                    val_to_str_const(result, move_result_vals, "Unknown result"));
1982
1983
18
    return offset;
1984
18
}
1985
1986
static int
1987
dissect_movechanconfirmation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
1988
23
{
1989
23
    uint16_t icid, result;
1990
1991
23
    icid = tvb_get_letohs(tvb, offset);
1992
23
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1993
23
    offset += 2;
1994
1995
23
    result = tvb_get_letohs(tvb, offset);
1996
23
    proto_tree_add_item(tree, hf_btl2cap_move_confirmation_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1997
23
    offset += 2;
1998
1999
23
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
2000
23
                    val_to_str_const(result, move_result_confirmation_vals, "Unknown result"));
2001
2002
23
    return offset;
2003
23
}
2004
2005
static int
2006
dissect_movechanconfirmationresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2007
22
{
2008
22
    uint16_t icid;
2009
2010
22
    icid = tvb_get_letohs(tvb, offset);
2011
22
    proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2012
22
    offset += 2;
2013
2014
22
    col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x)", icid);
2015
22
    return offset;
2016
22
}
2017
2018
static int
2019
dissect_connparamrequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2020
11
{
2021
11
    proto_item *item;
2022
11
    uint16_t max_interval, peripheral_latency;
2023
2024
11
    item = proto_tree_add_item(tree, hf_btl2cap_min_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2025
11
    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
2026
11
    offset += 2;
2027
11
    item = proto_tree_add_item(tree, hf_btl2cap_max_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2028
11
    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
2029
11
    max_interval = tvb_get_letohs(tvb, offset);
2030
11
    offset += 2;
2031
11
    item = proto_tree_add_item(tree, hf_btl2cap_peripheral_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2032
11
    peripheral_latency = tvb_get_letohs(tvb, offset);
2033
2034
11
    if(peripheral_latency >= 500 || max_interval == 0 ||
2035
11
       peripheral_latency > 10.0 * tvb_get_letohs(tvb, offset + 2) / (max_interval *1.25))
2036
10
        expert_add_info(pinfo, item, &ei_btl2cap_parameter_mismatch);
2037
2038
11
    offset += 2;
2039
11
    item = proto_tree_add_item(tree, hf_btl2cap_timeout_multiplier, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2040
11
    proto_item_append_text(item, " (%g sec)",  tvb_get_letohs(tvb, offset) * 0.01);
2041
11
    offset += 2;
2042
2043
11
    return offset;
2044
11
}
2045
2046
static int
2047
dissect_connparamresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2048
0
{
2049
0
    uint16_t result;
2050
2051
0
    result = tvb_get_letohs(tvb, offset);
2052
0
    proto_tree_add_item(tree, hf_btl2cap_conn_param_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2053
0
    offset += 2;
2054
2055
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
2056
0
                    val_to_str_const(result, conn_param_result_vals, "Unknown result"));
2057
2058
0
    return offset;
2059
0
}
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
152
{
2066
152
    uint16_t      scid;
2067
152
    uint16_t      dcid;
2068
152
    unsigned      psm = 0;
2069
152
    const char   *service_name = "Unknown";
2070
2071
152
    dcid = tvb_get_letohs(tvb, offset);
2072
152
    proto_tree_add_item(command_tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2073
152
    offset += 2;
2074
2075
152
    scid = tvb_get_letohs(tvb, offset);
2076
152
    proto_tree_add_item(command_tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2077
152
    offset += 2;
2078
2079
152
    if (!pinfo->fd->visited) {
2080
151
        psm_data_t        *psm_data;
2081
151
        wmem_tree_key_t    key[6];
2082
151
        uint32_t           k_interface_id;
2083
151
        uint32_t           k_adapter_id;
2084
151
        uint32_t           k_chandle;
2085
151
        uint32_t           k_cid;
2086
151
        uint32_t           k_frame_number;
2087
151
        uint32_t           interface_id;
2088
151
        uint32_t           adapter_id;
2089
151
        uint32_t           chandle;
2090
151
        uint32_t           key_scid;
2091
151
        uint32_t           key_dcid;
2092
2093
151
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2094
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2095
151
        else
2096
151
            interface_id = HCI_INTERFACE_DEFAULT;
2097
151
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
2098
151
        chandle      = (acl_data) ? acl_data->chandle : 0;
2099
151
        if ((is_request && pinfo->p2p_dir == P2P_DIR_SENT) ||
2100
151
                (!is_request && pinfo->p2p_dir == P2P_DIR_RECV)) {
2101
0
            key_dcid     = dcid | 0x80000000;
2102
0
            key_scid     = scid;
2103
151
        } else {
2104
151
            key_dcid     = scid | 0x80000000;
2105
151
            key_scid     = dcid;
2106
151
        }
2107
2108
151
        k_interface_id = interface_id;
2109
151
        k_adapter_id   = adapter_id;
2110
151
        k_chandle      = chandle;
2111
151
        k_cid          = key_dcid;
2112
151
        k_frame_number = pinfo->num;
2113
2114
151
        key[0].length = 1;
2115
151
        key[0].key    = &k_interface_id;
2116
151
        key[1].length = 1;
2117
151
        key[1].key    = &k_adapter_id;
2118
151
        key[2].length = 1;
2119
151
        key[2].key    = &k_chandle;
2120
151
        key[3].length = 1;
2121
151
        key[3].key    = &k_cid;
2122
151
        key[4].length = 1;
2123
151
        key[4].key    = &k_frame_number;
2124
151
        key[5].length = 0;
2125
151
        key[5].key    = NULL;
2126
2127
151
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2128
151
        if (psm_data &&
2129
151
            psm_data->interface_id == interface_id &&
2130
151
            psm_data->adapter_id == adapter_id &&
2131
151
            psm_data->chandle == chandle &&
2132
151
            psm_data->remote_cid == key_dcid &&
2133
151
            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
151
        k_interface_id = interface_id;
2139
151
        k_adapter_id   = adapter_id;
2140
151
        k_chandle      = chandle;
2141
151
        k_cid          = key_scid;
2142
151
        k_frame_number = pinfo->num;
2143
2144
151
        key[0].length = 1;
2145
151
        key[0].key    = &k_interface_id;
2146
151
        key[1].length = 1;
2147
151
        key[1].key    = &k_adapter_id;
2148
151
        key[2].length = 1;
2149
151
        key[2].key    = &k_chandle;
2150
151
        key[3].length = 1;
2151
151
        key[3].key    = &k_cid;
2152
151
        key[4].length = 1;
2153
151
        key[4].key    = &k_frame_number;
2154
151
        key[5].length = 0;
2155
151
        key[5].key    = NULL;
2156
2157
151
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2158
151
        if (psm_data &&
2159
151
            psm_data->interface_id == interface_id &&
2160
151
            psm_data->adapter_id == adapter_id &&
2161
151
            psm_data->chandle == chandle &&
2162
151
            psm_data->local_cid == key_scid &&
2163
151
            psm_data->disconnect_in_frame == bluetooth_max_disconnect_in_frame)
2164
26
        {
2165
26
            psm_data->disconnect_in_frame = pinfo->num;
2166
26
        }
2167
151
    }
2168
2169
152
    if (l2cap_data) {
2170
151
        proto_item        *sub_item;
2171
151
        uint32_t           bt_uuid = 0;
2172
151
        uint32_t           connect_in_frame = 0;
2173
151
        psm_data_t        *psm_data;
2174
151
        wmem_tree_key_t    key[6];
2175
151
        uint32_t           k_interface_id;
2176
151
        uint32_t           k_adapter_id;
2177
151
        uint32_t           k_chandle;
2178
151
        uint32_t           k_cid;
2179
151
        uint32_t           k_frame_number;
2180
151
        uint32_t           interface_id;
2181
151
        uint32_t           adapter_id;
2182
151
        uint32_t           chandle;
2183
151
        uint32_t           key_dcid;
2184
2185
151
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2186
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2187
151
        else
2188
151
            interface_id = HCI_INTERFACE_DEFAULT;
2189
151
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
2190
151
        chandle      = (acl_data) ? acl_data->chandle : 0;
2191
151
        if ((is_request && pinfo->p2p_dir == P2P_DIR_SENT) ||
2192
151
                (!is_request && pinfo->p2p_dir == P2P_DIR_RECV)) {
2193
0
            key_dcid     = dcid | 0x80000000;
2194
151
        } else {
2195
151
            key_dcid     = scid | 0x80000000;
2196
151
        }
2197
2198
151
        k_interface_id = interface_id;
2199
151
        k_adapter_id   = adapter_id;
2200
151
        k_chandle      = chandle;
2201
151
        k_cid          = key_dcid;
2202
151
        k_frame_number = pinfo->num;
2203
2204
151
        key[0].length = 1;
2205
151
        key[0].key    = &k_interface_id;
2206
151
        key[1].length = 1;
2207
151
        key[1].key    = &k_adapter_id;
2208
151
        key[2].length = 1;
2209
151
        key[2].key    = &k_chandle;
2210
151
        key[3].length = 1;
2211
151
        key[3].key    = &k_cid;
2212
151
        key[4].length = 1;
2213
151
        key[4].key    = &k_frame_number;
2214
151
        key[5].length = 0;
2215
151
        key[5].key    = NULL;
2216
2217
151
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
2218
151
        if (psm_data &&
2219
151
            psm_data->interface_id == interface_id &&
2220
151
            psm_data->adapter_id == adapter_id &&
2221
151
            psm_data->chandle == chandle &&
2222
151
            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
151
        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
151
        if (strcmp(service_name, "Unknown") == 0) {
2241
151
            service_name = val_to_str_const(psm, psm_vals, "Unknown");
2242
151
        }
2243
2244
151
        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
151
        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
151
        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
151
    }
2259
2260
152
    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
152
    else
2263
152
        col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x, DCID: 0x%04x, PSM: Unknown, Service: %s)", scid, dcid, service_name);
2264
2265
2266
152
    return offset;
2267
152
}
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
32
{
2274
32
    tvbuff_t *next_tvb;
2275
2276
32
    next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), length);
2277
2278
32
    col_append_str(pinfo->cinfo, COL_INFO, "Connection oriented channel");
2279
2280
32
    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
32
    } else {
2332
32
        if (!dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t) cid, next_tvb, pinfo, tree, true, l2cap_data))
2333
32
            proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
2334
32
        offset = tvb_captured_length(tvb);
2335
32
    }
2336
32
    return offset;
2337
32
}
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
0
{
2667
0
    proto_item *ti_control;
2668
0
    proto_tree *ti_control_subtree;
2669
0
    uint16_t    control;
2670
2671
0
    control = tvb_get_letohs(tvb, offset);
2672
2673
0
    switch ((control & 0x000C) >> 2) {
2674
0
    case 0:
2675
0
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Receiver Ready");
2676
0
        break;
2677
0
    case 1:
2678
0
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Reject");
2679
0
        break;
2680
0
    default:
2681
0
        col_append_str(pinfo->cinfo, COL_INFO, "[S] Unknown supervisory frame");
2682
0
        break;
2683
0
    }
2684
2685
0
    ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
2686
0
        offset, 2, "Control: %s reqseq:%d r:%d",
2687
0
        val_to_str_const((control & 0x000C) >> 2, control_supervisory_vals, "unknown"),
2688
0
        (control & 0x3F00) >> 8,
2689
0
        (control & 0x0080) >> 7);
2690
0
    ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
2691
2692
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2693
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2694
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_supervisory, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2695
0
    proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2696
0
    offset += 2;
2697
2698
0
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2699
0
    offset += 2;
2700
2701
0
    return offset;
2702
0
}
2703
2704
static int
2705
dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2706
1.13k
{
2707
1.13k
    int               offset       = 0;
2708
1.13k
    proto_item       *ti;
2709
1.13k
    proto_tree       *btl2cap_tree;
2710
1.13k
    proto_item       *length_item;
2711
1.13k
    uint16_t          length;
2712
1.13k
    uint16_t          cid;
2713
1.13k
    uint16_t          psm;
2714
1.13k
    uint16_t          control;
2715
1.13k
    tvbuff_t         *next_tvb     = NULL;
2716
1.13k
    psm_data_t       *psm_data;
2717
1.13k
    bthci_acl_data_t *acl_data;
2718
1.13k
    btl2cap_data_t   *l2cap_data;
2719
1.13k
    bool              dir_in_col = true;
2720
2721
1.13k
    acl_data = (bthci_acl_data_t *) data;
2722
2723
1.13k
    if ((acl_data) && (acl_data->is_btle)) {
2724
1
        dir_in_col = false;
2725
1
    }
2726
1.13k
    ti = proto_tree_add_item(tree, proto_btl2cap, tvb, offset, -1, ENC_NA);
2727
1.13k
    btl2cap_tree = proto_item_add_subtree(ti, ett_btl2cap);
2728
2729
1.13k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2CAP");
2730
2731
1.13k
    if (dir_in_col) {
2732
1.13k
        switch (pinfo->p2p_dir) {
2733
15
        case P2P_DIR_SENT:
2734
15
            col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
2735
15
            break;
2736
1
        case P2P_DIR_RECV:
2737
1
            col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
2738
1
            break;
2739
1.11k
        default:
2740
1.11k
            col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
2741
1.11k
            break;
2742
1.13k
        }
2743
1.13k
    } else {
2744
1
        col_clear(pinfo->cinfo, COL_INFO);
2745
1
    }
2746
2747
1.13k
    length  = tvb_get_letohs(tvb, offset);
2748
1.13k
    length_item = proto_tree_add_item(btl2cap_tree, hf_btl2cap_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2749
1.13k
    if (tvb_captured_length_remaining(tvb, offset) < length) {
2750
1.11k
        expert_add_info(pinfo, length_item, &ei_btl2cap_length_bad);
2751
        /* Try to dissect as more as possible */
2752
1.11k
        length = tvb_captured_length_remaining(tvb, offset) - 4;
2753
1.11k
    }
2754
2755
1.13k
    offset += 2;
2756
2757
1.13k
    cid = tvb_get_letohs(tvb, offset);
2758
1.13k
    proto_tree_add_item(btl2cap_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2759
1.13k
    if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID ) == NULL) {
2760
959
        uint16_t *value_data;
2761
2762
959
        value_data = wmem_new(wmem_file_scope(), uint16_t);
2763
959
        *value_data = cid;
2764
2765
959
        p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_CID, value_data);
2766
959
    }
2767
1.13k
    offset += 2;
2768
2769
1.13k
    l2cap_data = wmem_new(pinfo->pool, btl2cap_data_t);
2770
2771
1.13k
    if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
2772
0
        l2cap_data->interface_id = pinfo->rec->rec_header.packet_header.interface_id;
2773
1.13k
    else
2774
1.13k
        l2cap_data->interface_id = HCI_INTERFACE_DEFAULT;
2775
1.13k
    if (acl_data) {
2776
1
        l2cap_data->adapter_id                  = acl_data->adapter_id;
2777
1
        l2cap_data->adapter_disconnect_in_frame = acl_data->adapter_disconnect_in_frame;
2778
1
        l2cap_data->chandle                     = acl_data->chandle;
2779
1
        l2cap_data->hci_disconnect_in_frame     = acl_data->disconnect_in_frame;
2780
1
        l2cap_data->remote_bd_addr_oui          = acl_data->remote_bd_addr_oui;
2781
1
        l2cap_data->remote_bd_addr_id           = acl_data->remote_bd_addr_id;
2782
1.13k
    } else {
2783
1.13k
        l2cap_data->adapter_id                  = HCI_ADAPTER_DEFAULT;
2784
1.13k
        l2cap_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
2785
1.13k
        l2cap_data->chandle                     = 0;
2786
1.13k
        l2cap_data->hci_disconnect_in_frame     = &bluetooth_max_disconnect_in_frame;
2787
1.13k
        l2cap_data->remote_bd_addr_oui          = 0;
2788
1.13k
        l2cap_data->remote_bd_addr_id           = 0;
2789
1.13k
    }
2790
2791
1.13k
    l2cap_data->disconnect_in_frame         = &bluetooth_max_disconnect_in_frame;
2792
2793
1.13k
    l2cap_data->cid              = cid;
2794
1.13k
    l2cap_data->local_cid        = BTL2CAP_UNKNOWN_CID;
2795
1.13k
    l2cap_data->remote_cid       = BTL2CAP_UNKNOWN_CID;
2796
1.13k
    l2cap_data->is_local_psm     = false;
2797
1.13k
    l2cap_data->psm              = 0;
2798
2799
1.13k
    if (cid == BTL2CAP_FIXED_CID_SIGNAL || cid == BTL2CAP_FIXED_CID_LE_SIGNAL) {
2800
        /* This is a command packet*/
2801
743
        while (offset < length + 4) {
2802
2803
682
            proto_item  *ti_command;
2804
682
            proto_tree  *btl2cap_cmd_tree;
2805
682
            uint8_t      cmd_code;
2806
682
            uint8_t      cmd_ident;
2807
682
            uint16_t     cmd_length;
2808
682
            const char *cmd_str;
2809
2810
682
            ti_command = proto_tree_add_none_format(btl2cap_tree,
2811
682
                    hf_btl2cap_command, tvb,
2812
682
                    offset, length,
2813
682
                    "Command: ");
2814
682
            btl2cap_cmd_tree = proto_item_add_subtree(ti_command, ett_btl2cap_cmd);
2815
2816
682
            cmd_code = tvb_get_uint8(tvb, offset);
2817
682
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_code,   tvb, offset, 1, ENC_LITTLE_ENDIAN);
2818
682
            offset += 1;
2819
2820
682
            cmd_ident = tvb_get_uint8(tvb, offset);
2821
682
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_ident,  tvb, offset, 1, ENC_LITTLE_ENDIAN);
2822
682
            offset += 1;
2823
2824
682
            cmd_length = tvb_get_letohs(tvb, offset);
2825
682
            proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2826
682
            proto_item_set_len(ti_command, cmd_length + 4);
2827
682
            offset += 2;
2828
2829
682
            cmd_str = val_to_str_const(cmd_code, command_code_vals, "Unknown command");
2830
682
            proto_item_append_text(ti_command, "%s", cmd_str);
2831
682
            col_append_str(pinfo->cinfo, COL_INFO, cmd_str);
2832
2833
682
            switch (cmd_code) {
2834
135
            case 0x01: /* Command Reject */
2835
135
                offset  = dissect_comrej(tvb, offset, pinfo, btl2cap_cmd_tree);
2836
135
                break;
2837
2838
43
            case 0x02: /* Connection Request */
2839
43
                offset  = dissect_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, false, acl_data, l2cap_data);
2840
43
                break;
2841
2842
8
            case 0x03: /* Connection Response */
2843
8
                offset  = dissect_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, acl_data);
2844
8
                break;
2845
2846
19
            case 0x04: /* Configure Request */
2847
19
                offset  = dissect_configrequest(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length, acl_data);
2848
19
                break;
2849
2850
44
            case 0x05: /* Configure Response */
2851
44
                offset  = dissect_configresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length, acl_data);
2852
44
                break;
2853
2854
61
            case 0x06: /* Disconnect Request */
2855
61
                offset  = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, acl_data, l2cap_data, true);
2856
61
                break;
2857
2858
91
            case 0x07: /* Disconnect Response */
2859
91
                offset  = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, acl_data, l2cap_data, false);
2860
91
                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
1
            case 0x09: /* Echo Response */
2868
1
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_data, tvb, offset, -1, ENC_NA);
2869
1
                offset = tvb_reported_length(tvb);
2870
1
                break;
2871
2872
1
            case 0x0a: /* Information Request */
2873
1
                offset  = dissect_inforequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2874
1
                break;
2875
2876
1
            case 0x0b: /* Information Response */
2877
1
                offset  = dissect_inforesponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2878
1
                break;
2879
2880
12
            case 0x0c: /* Create Channel Request */
2881
12
                offset  = dissect_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, true, acl_data, l2cap_data);
2882
12
                break;
2883
2884
11
            case 0x0d: /* Create Channel Response */
2885
11
                offset  = dissect_chanresponse(tvb, offset, pinfo, btl2cap_cmd_tree, acl_data);
2886
11
                break;
2887
2888
2
            case 0x0e: /* Move Channel Request */
2889
2
                offset  = dissect_movechanrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2890
2
                break;
2891
2892
18
            case 0x0f: /* Move Channel Response */
2893
18
                offset  = dissect_movechanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2894
18
                break;
2895
2896
23
            case 0x10: /* Move Channel Confirmation */
2897
23
                offset  = dissect_movechanconfirmation(tvb, offset, pinfo, btl2cap_cmd_tree);
2898
23
                break;
2899
2900
22
            case 0x11: /* Move Channel Confirmation Response */
2901
22
                offset  = dissect_movechanconfirmationresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2902
22
                break;
2903
2904
11
            case 0x12: /* Connection Parameter Request */
2905
11
                offset  = dissect_connparamrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
2906
11
                break;
2907
2908
0
            case 0x13: /* Connection Parameter Response */
2909
0
                offset  = dissect_connparamresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
2910
0
                break;
2911
2912
79
            case 0x14: /* LE Credit Based Connection Request */
2913
79
                offset = dissect_le_credit_based_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, cid, cmd_ident, acl_data, l2cap_data);
2914
2915
79
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Initial Credits: %u)",
2916
79
                                tvb_get_letohs(tvb, offset - 8), tvb_get_letohs(tvb, offset - 2));
2917
79
                break;
2918
2919
1
            case 0x15: /* LE Credit Based Connection Response */
2920
1
                offset = dissect_le_credit_based_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cid, cmd_ident, acl_data);
2921
2922
1
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Initial Credits: %u)",
2923
1
                                tvb_get_letohs(tvb, offset - 10), tvb_get_letohs(tvb, offset - 4));
2924
1
                break;
2925
2926
3
            case 0x16: /* LE Flow Control Credit */
2927
3
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2928
3
                offset += 2;
2929
2930
3
                proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_credits, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2931
3
                offset += 2;
2932
2933
3
                col_append_fstr(pinfo->cinfo, COL_INFO, " (CID: %04x, Credits: %u)",
2934
3
                                tvb_get_letohs(tvb, offset - 4), tvb_get_letohs(tvb, offset - 2));
2935
3
                break;
2936
2937
33
            case 0x17: /* L2CAP Credit Based Connection Request */
2938
33
                offset = dissect_l2cap_credit_based_connrequest(tvb, offset, pinfo, btl2cap_tree, btl2cap_cmd_tree, cid, cmd_ident, cmd_length, acl_data, l2cap_data);
2939
33
                break;
2940
2941
9
            case 0x18: /* L2CAP Credit Based Connection Response */
2942
9
                offset = dissect_l2cap_credit_based_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cid, cmd_ident, cmd_length, acl_data);
2943
9
                break;
2944
2945
51
            default:
2946
51
                proto_tree_add_expert(btl2cap_cmd_tree, pinfo, &ei_btl2cap_unknown_command_code, tvb, offset, -1);
2947
51
                offset += tvb_reported_length_remaining(tvb, offset);
2948
51
                break;
2949
682
            }
2950
682
        }
2951
131
    }
2952
1.00k
    else if (cid == BTL2CAP_FIXED_CID_CONNLESS) { /* Connectionless reception channel */
2953
190
        col_append_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel");
2954
2955
190
        psm = tvb_get_letohs(tvb, offset);
2956
190
        if (pinfo->p2p_dir == P2P_DIR_RECV) {
2957
0
            l2cap_data->local_cid = cid;
2958
0
            l2cap_data->remote_cid = BTL2CAP_UNKNOWN_CID;
2959
190
        } else {
2960
190
            l2cap_data->local_cid = BTL2CAP_UNKNOWN_CID;
2961
190
            l2cap_data->remote_cid = cid;
2962
190
        }
2963
190
        l2cap_data->psm = psm;
2964
190
        l2cap_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
2965
2966
190
        if (p_get_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM ) == NULL) {
2967
190
            uint16_t *value_data;
2968
2969
190
            value_data = wmem_new(wmem_file_scope(), uint16_t);
2970
190
            *value_data = psm;
2971
2972
190
            p_add_proto_data(pinfo->pool, pinfo, proto_btl2cap, PROTO_DATA_BTL2CAP_PSM, value_data);
2973
190
        }
2974
2975
190
        proto_tree_add_item(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2976
190
        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
190
        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
190
        length -= 2;
2991
190
        next_tvb = tvb_new_subset_length(tvb, offset, length);
2992
2993
        /* call next dissector */
2994
190
        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
1
            uint16_t bt_uuid;
2997
1
            bluetooth_uuid_t  uuid;
2998
2999
1
            bt_uuid = get_service_uuid(pinfo, l2cap_data, psm, (pinfo->p2p_dir == P2P_DIR_RECV) ? true : false );
3000
3001
1
            uuid.size = 2;
3002
1
            uuid.bt_uuid = bt_uuid;
3003
1
            uuid.data[0] = bt_uuid >> 8;
3004
1
            uuid.data[1] = bt_uuid & 0xFF;
3005
3006
1
            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
1
            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
1
                proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
3017
1
            }
3018
1
            offset = tvb_captured_length(tvb);
3019
1
        }
3020
190
    }
3021
815
    else if (cid <= BTL2CAP_FIXED_CID_LAST) {
3022
782
        if (cid == BTL2CAP_FIXED_CID_AMP_MAN) {
3023
6
            control = tvb_get_letohs(tvb, offset);
3024
6
            if (control & 0x1) {
3025
0
                offset = dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, 0 /* unused */, length, offset, NULL /* unused */);
3026
6
            } else {
3027
6
                proto_item* ti_control;
3028
6
                proto_tree* ti_control_subtree;
3029
3030
6
                ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
3031
6
                    offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
3032
6
                    val_to_str_const((control & 0xC000) >> 14, control_sar_vals, "unknown"),
3033
6
                    (control & 0x3F00) >> 8,
3034
6
                    (control & 0x0080) >> 7,
3035
6
                    (control & 0x007E) >> 1);
3036
6
                ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
3037
6
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3038
6
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3039
6
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3040
6
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3041
6
                proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3042
6
                offset += 2;
3043
6
                proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, tvb_reported_length(tvb) - 2, 2, ENC_LITTLE_ENDIAN);
3044
3045
6
                next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset)-2, length);
3046
6
            }
3047
6
        }
3048
776
        else {
3049
776
            next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), length);
3050
776
        }
3051
        /* call next dissector */
3052
782
        if (next_tvb && !dissector_try_uint_with_data(l2cap_cid_dissector_table, (uint32_t) cid,
3053
782
                    next_tvb, pinfo, tree, true, l2cap_data)) {
3054
            /* unknown protocol. declare as data */
3055
11
            proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
3056
11
        }
3057
782
        offset = tvb_captured_length(tvb);
3058
782
    }
3059
33
    else /* if (cid > BTL2CAP_FIXED_CID_LAST) */ { /* Connection oriented channel */
3060
33
        wmem_tree_key_t    key[6];
3061
33
        uint32_t           k_interface_id;
3062
33
        uint32_t           k_adapter_id;
3063
33
        uint32_t           k_chandle;
3064
33
        uint32_t           k_cid;
3065
33
        uint32_t           k_frame_number;
3066
33
        uint32_t           interface_id;
3067
33
        uint32_t           adapter_id;
3068
33
        uint32_t           chandle;
3069
33
        uint32_t           key_cid;
3070
3071
33
        if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
3072
0
            interface_id = pinfo->rec->rec_header.packet_header.interface_id;
3073
33
        else
3074
33
            interface_id = HCI_INTERFACE_DEFAULT;
3075
33
        adapter_id   = (acl_data) ? acl_data->adapter_id : HCI_ADAPTER_DEFAULT;
3076
33
        chandle      = (acl_data) ? acl_data->chandle : 0;
3077
33
        key_cid      = cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x00000000 : 0x80000000);
3078
3079
33
        k_interface_id = interface_id;
3080
33
        k_adapter_id   = adapter_id;
3081
33
        k_chandle      = chandle;
3082
33
        k_cid          = key_cid;
3083
33
        k_frame_number = pinfo->num;
3084
3085
33
        key[0].length = 1;
3086
33
        key[0].key    = &k_interface_id;
3087
33
        key[1].length = 1;
3088
33
        key[1].key    = &k_adapter_id;
3089
33
        key[2].length = 1;
3090
33
        key[2].key    = &k_chandle;
3091
33
        key[3].length = 1;
3092
33
        key[3].key    = &k_cid;
3093
33
        key[4].length = 1;
3094
33
        key[4].key    = &k_frame_number;
3095
33
        key[5].length = 0;
3096
33
        key[5].key    = NULL;
3097
3098
33
        psm_data = (psm_data_t *)wmem_tree_lookup32_array_le(cid_to_psm_table, key);
3099
33
        if (psm_data &&
3100
33
            psm_data->interface_id == interface_id &&
3101
33
            psm_data->adapter_id == adapter_id &&
3102
33
            psm_data->chandle == chandle &&
3103
33
            (psm_data->local_cid == key_cid ||
3104
32
             psm_data->remote_cid == key_cid) &&
3105
33
            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
33
        } else {
3156
33
            psm = 0;
3157
33
            offset = dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, cid, psm, false, length, offset, l2cap_data);
3158
33
        }
3159
33
    }
3160
3161
1.06k
    return offset;
3162
1.13k
}
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
 */