Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-btl2cap.c
Warning:line 1544, column 17
Value stored to 'offset' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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