epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-btavctp.c
blob81bacabafbd9689120383e621b2f531a10e30381
1 /* packet-btavctp.c
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
13 #include "config.h"
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
31 int proto_btavctp;
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 {
49 unsigned length;
50 uint8_t *data;
51 } fragment_t;
53 typedef struct _fragments_t {
54 uint32_t interface_id;
55 uint32_t adapter_id;
56 uint32_t chandle;
57 uint32_t psm;
58 uint32_t count;
59 uint32_t number_of_packets;
60 uint32_t pid;
61 wmem_tree_t *fragment;
62 } fragments_t;
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" },
72 { 0, NULL }
75 static const value_string cr_vals[] = {
76 { 0x00, "Command" },
77 { 0x01, "Response" },
78 { 0, NULL }
81 static const value_string ipid_vals[] = {
82 { 0x00, "Profile OK" },
83 { 0x01, "Invalid profile" },
84 { 0, NULL }
87 void proto_register_btavctp(void);
88 void proto_reg_handoff_btavctp(void);
90 static int
91 dissect_btavctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
93 proto_item *ti;
94 proto_tree *btavctp_tree;
95 proto_item *pitem;
96 proto_item *ipid_item = NULL;
97 btavctp_data_t *avctp_data;
98 tvbuff_t *next_tvb;
99 int offset = 0;
100 unsigned packet_type;
101 unsigned cr;
102 unsigned pid = 0;
103 unsigned transaction;
104 unsigned number_of_packets = 0;
105 unsigned length;
106 unsigned i_frame;
107 bool ipid = false;
108 uint32_t interface_id;
109 uint32_t adapter_id;
110 uint32_t chandle;
111 uint32_t psm;
112 int previous_proto;
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;
124 } else {
125 interface_id = HCI_INTERFACE_DEFAULT;
126 adapter_id = HCI_ADAPTER_DEFAULT;
127 chandle = 0;
128 psm = 0;
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) {
138 case P2P_DIR_SENT:
139 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
140 break;
141 case P2P_DIR_RECV:
142 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
143 break;
144 default:
145 col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
146 break;
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;
159 } else {
160 proto_tree_add_item(btavctp_tree, hf_btavctp_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
162 offset++;
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);
167 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) {
175 uint8_t *value_data;
176 bluetooth_uuid_t uuid;
178 uuid.size = 2;
179 uuid.bt_uuid = pid;
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);
187 offset +=2;
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"));
194 if (ipid) {
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)
198 return offset;
201 avctp_data = wmem_new(pinfo->pool, btavctp_data_t);
202 avctp_data->cr = cr;
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);
210 /* reassembling */
211 next_tvb = tvb_new_subset_length(tvb, offset, length);
212 if (packet_type == PACKET_TYPE_SINGLE) {
213 bluetooth_uuid_t uuid;
215 uuid.size = 2;
216 uuid.bt_uuid = pid;
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);
224 } else {
225 fragment_t *fragment;
226 wmem_tree_key_t key[6];
227 uint32_t frame_number;
229 frame_number = pinfo->num;
231 key[0].length = 1;
232 key[0].key = &interface_id;
233 key[1].length = 1;
234 key[1].key = &adapter_id;
235 key[2].length = 1;
236 key[2].key = &chandle;
237 key[3].length = 1;
238 key[3].key = &psm;
239 key[4].length = 1;
240 key[4].key = &frame_number;
241 key[5].length = 0;
242 key[5].key = NULL;
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);
266 } else {
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))
272 fragments = NULL;
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))
283 fragments = NULL;
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);
291 fragments->count++;
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;
301 key[0].length = 1;
302 key[0].key = &interface_id;
303 key[1].length = 1;
304 key[1].key = &adapter_id;
305 key[2].length = 1;
306 key[2].key = &chandle;
307 key[3].length = 1;
308 key[3].key = &psm;
309 key[4].length = 1;
310 key[4].key = &frame_number;
311 key[5].length = 0;
312 key[5].key = NULL;
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))
326 fragments = NULL;
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);
334 fragments->count++;
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;
344 key[0].length = 1;
345 key[0].key = &interface_id;
346 key[1].length = 1;
347 key[1].key = &adapter_id;
348 key[2].length = 1;
349 key[2].key = &chandle;
350 key[3].length = 1;
351 key[3].key = &psm;
352 key[4].length = 1;
353 key[4].key = &frame_number;
354 key[5].length = 0;
355 key[5].key = NULL;
357 wmem_tree_insert32_array(reassembling, key, fragments);
360 length = 0;
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);
364 } else {
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);
370 if (fragment) {
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");
380 uuid.size = 2;
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);
390 fragments = NULL;
391 } else {
392 call_data_dissector(next_tvb, pinfo, tree);
396 return offset;
399 void
400 proto_register_btavctp(void)
402 module_t *module;
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,
409 NULL, HFILL }
411 { &hf_btavctp_packet_type,
412 { "Packet Type", "btavctp.packet_type",
413 FT_UINT8, BASE_HEX, VALS(packet_type_vals), 0x0C,
414 NULL, HFILL }
416 { &hf_btavctp_cr,
417 { "C/R", "btavctp.cr",
418 FT_UINT8, BASE_HEX, VALS(cr_vals), 0x02,
419 NULL, HFILL }
421 { &hf_btavctp_ipid,
422 { "IPID", "btavctp.ipid",
423 FT_UINT8, BASE_HEX, VALS(ipid_vals), 0x01,
424 NULL, HFILL }
426 { &hf_btavctp_rfa,
427 { "RFA", "btavctp.rfa",
428 FT_UINT8, BASE_HEX, NULL, 0x01,
429 NULL, HFILL }
431 { &hf_btavctp_pid,
432 { "Profile Identifier", "btavctp.pid",
433 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &bluetooth_uuid_vals_ext, 0x00,
434 NULL, HFILL }
436 { &hf_btavctp_number_of_packets,
437 { "Number of packets", "btavctp.nop",
438 FT_UINT8, BASE_DEC, NULL, 0x00,
439 NULL, HFILL }
443 static int *ett[] = {
444 &ett_btavctp
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.");
470 void
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
484 * Local variables:
485 * c-basic-offset: 4
486 * tab-width: 8
487 * indent-tabs-mode: nil
488 * End:
490 * vi: set shiftwidth=4 tabstop=8 expandtab:
491 * :indentSize=4:tabSize=8:noTabs=true: