2 * Routines for Bluetooth AVCTP dissection
4 * Copyright 2012, Michal Labedzki for Tieto Corporation
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/decode_as.h>
19 #include <epan/proto_data.h>
21 #include "packet-bluetooth.h"
22 #include "packet-btl2cap.h"
23 #include "packet-btsdp.h"
24 #include "packet-btavctp.h"
26 #define PACKET_TYPE_SINGLE 0x00
27 #define PACKET_TYPE_START 0x01
28 #define PACKET_TYPE_CONTINUE 0x02
29 #define PACKET_TYPE_END 0x03
33 static int hf_btavctp_transaction
;
34 static int hf_btavctp_packet_type
;
35 static int hf_btavctp_cr
;
36 static int hf_btavctp_ipid
;
37 static int hf_btavctp_rfa
;
38 static int hf_btavctp_pid
;
39 static int hf_btavctp_number_of_packets
;
41 static int ett_btavctp
;
43 static expert_field ei_btavctp_unexpected_frame
;
44 static expert_field ei_btavctp_invalid_profile
;
46 static dissector_handle_t btavctp_handle
;
48 typedef struct _fragment_t
{
53 typedef struct _fragments_t
{
54 uint32_t interface_id
;
59 uint32_t number_of_packets
;
61 wmem_tree_t
*fragment
;
64 static wmem_tree_t
*reassembling
;
65 static fragments_t
*fragments
;
67 static const value_string packet_type_vals
[] = {
68 { PACKET_TYPE_SINGLE
, "Single" },
69 { PACKET_TYPE_START
, "Start" },
70 { PACKET_TYPE_CONTINUE
, "Continue" },
71 { PACKET_TYPE_END
, "End" },
75 static const value_string cr_vals
[] = {
81 static const value_string ipid_vals
[] = {
82 { 0x00, "Profile OK" },
83 { 0x01, "Invalid profile" },
87 void proto_register_btavctp(void);
88 void proto_reg_handoff_btavctp(void);
91 dissect_btavctp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
94 proto_tree
*btavctp_tree
;
96 proto_item
*ipid_item
= NULL
;
97 btavctp_data_t
*avctp_data
;
100 unsigned packet_type
;
103 unsigned transaction
;
104 unsigned number_of_packets
= 0;
108 uint32_t interface_id
;
114 previous_proto
= (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo
->layers
)))));
115 if (previous_proto
== proto_btl2cap
) {
116 btl2cap_data_t
*l2cap_data
;
118 l2cap_data
= (btl2cap_data_t
*) data
;
120 interface_id
= l2cap_data
->interface_id
;
121 adapter_id
= l2cap_data
->adapter_id
;
122 chandle
= l2cap_data
->chandle
;
123 psm
= l2cap_data
->psm
;
125 interface_id
= HCI_INTERFACE_DEFAULT
;
126 adapter_id
= HCI_ADAPTER_DEFAULT
;
131 ti
= proto_tree_add_item(tree
, proto_btavctp
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), ENC_NA
);
132 btavctp_tree
= proto_item_add_subtree(ti
, ett_btavctp
);
134 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AVCTP");
135 col_clear(pinfo
->cinfo
, COL_INFO
);
137 switch (pinfo
->p2p_dir
) {
139 col_set_str(pinfo
->cinfo
, COL_INFO
, "Sent ");
142 col_set_str(pinfo
->cinfo
, COL_INFO
, "Rcvd ");
145 col_set_str(pinfo
->cinfo
, COL_INFO
, "UnknownDirection ");
149 proto_tree_add_item(btavctp_tree
, hf_btavctp_transaction
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
150 pitem
= proto_tree_add_item(btavctp_tree
, hf_btavctp_packet_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
151 proto_tree_add_item(btavctp_tree
, hf_btavctp_cr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
152 transaction
= tvb_get_uint8(tvb
, offset
) >> 4;
153 packet_type
= (tvb_get_uint8(tvb
, offset
) & 0x0C) >> 2;
154 cr
= (tvb_get_uint8(tvb
, offset
) & 0x02) >> 1 ;
156 if (packet_type
== PACKET_TYPE_SINGLE
|| packet_type
== PACKET_TYPE_START
) {
157 ipid_item
= proto_tree_add_item(btavctp_tree
, hf_btavctp_ipid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
158 ipid
= tvb_get_uint8(tvb
, offset
) & 0x01;
160 proto_tree_add_item(btavctp_tree
, hf_btavctp_rfa
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
164 if (packet_type
== PACKET_TYPE_START
) {
165 proto_tree_add_item(btavctp_tree
, hf_btavctp_number_of_packets
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
166 number_of_packets
= tvb_get_uint8(tvb
, offset
);
170 if (packet_type
== PACKET_TYPE_SINGLE
|| packet_type
== PACKET_TYPE_START
) {
171 proto_tree_add_item(btavctp_tree
, hf_btavctp_pid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
172 pid
= tvb_get_ntohs(tvb
, offset
);
174 if (p_get_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
) == NULL
) {
176 bluetooth_uuid_t uuid
;
180 uuid
.data
[0] = pid
>> 8;
181 uuid
.data
[1] = pid
& 0xFF;
183 value_data
= wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
));
185 p_add_proto_data(pinfo
->pool
, pinfo
, proto_bluetooth
, PROTO_DATA_BLUETOOTH_SERVICE_UUID
, value_data
);
190 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s - Transaction: %u, PacketType: %s",
191 val_to_str_const(cr
, cr_vals
, "unknown CR"), transaction
,
192 val_to_str_const(packet_type
, packet_type_vals
, "unknown packet type"));
195 expert_add_info(pinfo
, ipid_item
, &ei_btavctp_invalid_profile
);
196 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Invalid profile");
197 if (tvb_captured_length_remaining(tvb
, offset
) == 0)
201 avctp_data
= wmem_new(pinfo
->pool
, btavctp_data_t
);
203 avctp_data
->interface_id
= interface_id
;
204 avctp_data
->adapter_id
= adapter_id
;
205 avctp_data
->chandle
= chandle
;
206 avctp_data
->psm
= psm
;
208 length
= tvb_reported_length_remaining(tvb
, offset
);
211 next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
212 if (packet_type
== PACKET_TYPE_SINGLE
) {
213 bluetooth_uuid_t uuid
;
217 uuid
.data
[0] = pid
>> 8;
218 uuid
.data
[1] = pid
& 0xFF;
220 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), next_tvb
, pinfo
, tree
, true, avctp_data
)) {
221 call_data_dissector(next_tvb
, pinfo
, tree
);
225 fragment_t
*fragment
;
226 wmem_tree_key_t key
[6];
227 uint32_t frame_number
;
229 frame_number
= pinfo
->num
;
232 key
[0].key
= &interface_id
;
234 key
[1].key
= &adapter_id
;
236 key
[2].key
= &chandle
;
240 key
[4].key
= &frame_number
;
244 if (packet_type
== PACKET_TYPE_START
) {
245 if (!pinfo
->fd
->visited
) {
246 fragment
= wmem_new(wmem_file_scope(), fragment_t
);
247 fragment
->length
= length
;
248 fragment
->data
= (uint8_t *) wmem_alloc(wmem_file_scope(), fragment
->length
);
249 tvb_memcpy(tvb
, fragment
->data
, offset
, fragment
->length
);
251 fragments
= wmem_new(wmem_file_scope(), fragments_t
);
252 fragments
->number_of_packets
= number_of_packets
;
253 fragments
->pid
= pid
;
255 fragments
->count
= 1;
256 fragments
->fragment
= wmem_tree_new(wmem_file_scope());
257 wmem_tree_insert32(fragments
->fragment
, fragments
->count
, fragment
);
259 fragments
->interface_id
= interface_id
;
260 fragments
->adapter_id
= adapter_id
;
261 fragments
->chandle
= chandle
;
262 fragments
->psm
= psm
;
264 wmem_tree_insert32_array(reassembling
, key
, fragments
);
267 fragments
= (fragments_t
*)wmem_tree_lookup32_array_le(reassembling
, key
);
268 if (!(fragments
&& fragments
->interface_id
== interface_id
&&
269 fragments
->adapter_id
== adapter_id
&&
270 fragments
->chandle
== chandle
&&
271 fragments
->psm
== psm
))
275 call_data_dissector(next_tvb
, pinfo
, tree
);
277 } else if (packet_type
== PACKET_TYPE_CONTINUE
) {
278 fragments
= (fragments_t
*)wmem_tree_lookup32_array_le(reassembling
, key
);
279 if (!(fragments
&& fragments
->interface_id
== interface_id
&&
280 fragments
->adapter_id
== adapter_id
&&
281 fragments
->chandle
== chandle
&&
282 fragments
->psm
== psm
))
285 if (!pinfo
->fd
->visited
&& fragments
!= NULL
) {
286 fragment
= wmem_new(wmem_file_scope(), fragment_t
);
287 fragment
->length
= length
;
288 fragment
->data
= (uint8_t *) wmem_alloc(wmem_file_scope(), fragment
->length
);
289 tvb_memcpy(tvb
, fragment
->data
, offset
, fragment
->length
);
292 wmem_tree_insert32(fragments
->fragment
, fragments
->count
, fragment
);
294 fragments
->interface_id
= interface_id
;
295 fragments
->adapter_id
= adapter_id
;
296 fragments
->chandle
= chandle
;
297 fragments
->psm
= psm
;
299 frame_number
= pinfo
->num
;
302 key
[0].key
= &interface_id
;
304 key
[1].key
= &adapter_id
;
306 key
[2].key
= &chandle
;
310 key
[4].key
= &frame_number
;
314 wmem_tree_insert32_array(reassembling
, key
, fragments
);
317 call_data_dissector(next_tvb
, pinfo
, tree
);
319 } else if (packet_type
== PACKET_TYPE_END
) {
321 fragments
= (fragments_t
*)wmem_tree_lookup32_array_le(reassembling
, key
);
322 if (!(fragments
&& fragments
->interface_id
== interface_id
&&
323 fragments
->adapter_id
== adapter_id
&&
324 fragments
->chandle
== chandle
&&
325 fragments
->psm
== psm
))
328 if (!pinfo
->fd
->visited
&& fragments
!= NULL
) {
329 fragment
= wmem_new(wmem_file_scope(), fragment_t
);
330 fragment
->length
= length
;
331 fragment
->data
= (uint8_t *) wmem_alloc(wmem_file_scope(), fragment
->length
);
332 tvb_memcpy(tvb
, fragment
->data
, offset
, fragment
->length
);
335 wmem_tree_insert32(fragments
->fragment
, fragments
->count
, fragment
);
337 fragments
->interface_id
= interface_id
;
338 fragments
->adapter_id
= adapter_id
;
339 fragments
->chandle
= chandle
;
340 fragments
->psm
= psm
;
342 frame_number
= pinfo
->num
;
345 key
[0].key
= &interface_id
;
347 key
[1].key
= &adapter_id
;
349 key
[2].key
= &chandle
;
353 key
[4].key
= &frame_number
;
357 wmem_tree_insert32_array(reassembling
, key
, fragments
);
361 if (!fragments
|| fragments
->count
!= fragments
->number_of_packets
) {
362 expert_add_info(pinfo
, pitem
, &ei_btavctp_unexpected_frame
);
363 call_data_dissector(next_tvb
, pinfo
, tree
);
365 uint8_t *reassembled
= NULL
;
366 bluetooth_uuid_t uuid
;
368 for (i_frame
= 1; i_frame
<= fragments
->count
; ++i_frame
) {
369 fragment
= (fragment_t
*)wmem_tree_lookup32_le(fragments
->fragment
, i_frame
);
371 reassembled
= (uint8_t*)wmem_realloc(pinfo
->pool
, reassembled
, length
+ fragment
->length
);
372 memcpy(reassembled
+ length
, fragment
->data
, fragment
->length
);
373 length
+= fragment
->length
;
377 next_tvb
= tvb_new_child_real_data(tvb
, reassembled
, length
, length
);
378 add_new_data_source(pinfo
, next_tvb
, "Reassembled AVCTP");
381 uuid
.bt_uuid
= fragments
->pid
;
382 uuid
.data
[0] = fragments
->pid
>> 8;
383 uuid
.data
[1] = fragments
->pid
& 0xFF;
385 if (!dissector_try_string_with_data(bluetooth_uuid_table
, print_numeric_bluetooth_uuid(pinfo
->pool
, &uuid
), next_tvb
, pinfo
, tree
, true, avctp_data
)) {
386 call_data_dissector(next_tvb
, pinfo
, tree
);
392 call_data_dissector(next_tvb
, pinfo
, tree
);
400 proto_register_btavctp(void)
403 expert_module_t
* expert_btavctp
;
405 static hf_register_info hf
[] = {
406 { &hf_btavctp_transaction
,
407 { "Transaction", "btavctp.transaction",
408 FT_UINT8
, BASE_HEX
, NULL
, 0xF0,
411 { &hf_btavctp_packet_type
,
412 { "Packet Type", "btavctp.packet_type",
413 FT_UINT8
, BASE_HEX
, VALS(packet_type_vals
), 0x0C,
417 { "C/R", "btavctp.cr",
418 FT_UINT8
, BASE_HEX
, VALS(cr_vals
), 0x02,
422 { "IPID", "btavctp.ipid",
423 FT_UINT8
, BASE_HEX
, VALS(ipid_vals
), 0x01,
427 { "RFA", "btavctp.rfa",
428 FT_UINT8
, BASE_HEX
, NULL
, 0x01,
432 { "Profile Identifier", "btavctp.pid",
433 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &bluetooth_uuid_vals_ext
, 0x00,
436 { &hf_btavctp_number_of_packets
,
437 { "Number of packets", "btavctp.nop",
438 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
443 static int *ett
[] = {
447 static ei_register_info ei
[] = {
448 { &ei_btavctp_unexpected_frame
, { "btavctp.unexpected_frame", PI_PROTOCOL
, PI_WARN
, "Unexpected frame", EXPFILL
}},
449 { &ei_btavctp_invalid_profile
, { "btavctp.invalid_profile", PI_PROTOCOL
, PI_NOTE
, "Invalid Profile", EXPFILL
}},
452 /* Decode As handling */
453 reassembling
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
455 proto_btavctp
= proto_register_protocol("Bluetooth AVCTP Protocol", "BT AVCTP", "btavctp");
456 btavctp_handle
= register_dissector("btavctp", dissect_btavctp
, proto_btavctp
);
458 proto_register_field_array(proto_btavctp
, hf
, array_length(hf
));
459 proto_register_subtree_array(ett
, array_length(ett
));
460 expert_btavctp
= expert_register_protocol(proto_btavctp
);
461 expert_register_field_array(expert_btavctp
, ei
, array_length(ei
));
463 module
= prefs_register_protocol_subtree("Bluetooth", proto_btavctp
, NULL
);
464 prefs_register_static_text_preference(module
, "avctp.version",
465 "Bluetooth Protocol AVCTP version: 1.4",
466 "Version of protocol supported by this dissector.");
471 proto_reg_handoff_btavctp(void)
473 dissector_add_string("bluetooth.uuid", "17", btavctp_handle
);
475 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_AVCTP_CTRL
, btavctp_handle
);
476 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_AVCTP_BRWS
, btavctp_handle
);
478 dissector_add_for_decode_as("btl2cap.cid", btavctp_handle
);
482 * Editor modelines - https://www.wireshark.org/tools/modelines.html
487 * indent-tabs-mode: nil
490 * vi: set shiftwidth=4 tabstop=8 expandtab:
491 * :indentSize=4:tabSize=8:noTabs=true: