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