1 /* TODO mix direction bit into the chandle tree lookup so we can handle when fragments sent in both directions simultaneously on the same chandle */
4 * Routines for the Bluetooth ACL dissection
5 * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
6 * From: http://affix.sourceforge.net/archive/ethereal_affix-3.patch
8 * Refactored for wireshark checkin
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
38 #include <epan/emem.h>
39 #include <epan/prefs.h>
41 #include <packet-hci_h4.h>
42 #include <packet-bthci_acl.h>
44 /* Initialize the protocol and registered fields */
45 static int proto_btacl = -1;
46 static int hf_btacl_chandle = -1;
47 static int hf_btacl_pb_flag = -1;
48 static int hf_btacl_bc_flag = -1;
49 static int hf_btacl_length = -1;
50 static int hf_btacl_data = -1;
51 static int hf_btacl_continuation_to = -1;
52 static int hf_btacl_reassembled_in = -1;
54 /* Initialize the subtree pointers */
55 static gint ett_btacl = -1;
57 static dissector_handle_t btl2cap_handle=NULL;
59 static gboolean acl_reassembly = TRUE;
61 typedef struct _multi_fragment_pdu_t {
66 int cur_off; /* counter used by reassembly */
67 } multi_fragment_pdu_t;
69 typedef struct _chandle_data_t {
70 emem_tree_t *start_fragments; /* indexed by pinfo->fd->num */
73 static emem_tree_t *chandle_tree=NULL;
75 static const value_string pb_flag_vals[] = {
76 {0, "First Non-automatically Flushable Packet"},
77 {1, "Continuing Fragment"},
78 {2, "First Automatically Flushable Packet"},
82 static const value_string bc_flag_vals[] = {
83 {0, "Point-To-Point"},
84 {1, "Active Broadcast"},
85 {2, "Piconet Broadcast"},
91 /* Code to actually dissect the packets */
93 dissect_btacl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
96 proto_tree *btacl_tree=NULL;
97 guint16 flags, length;
100 guint16 pb_flag, l2cap_length=0;
102 bthci_acl_data_t *acl_data;
103 chandle_data_t *chandle_data;
106 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_ACL");
109 ti=proto_tree_add_item(tree, proto_btacl, tvb, offset, -1, FALSE);
110 btacl_tree = proto_item_add_subtree(ti, ett_btacl);
113 flags=tvb_get_letohs(tvb, offset);
114 pb_flag = (flags & 0x3000) >> 12;
115 proto_tree_add_item(btacl_tree, hf_btacl_chandle, tvb, offset, 2, TRUE);
116 proto_tree_add_item(btacl_tree, hf_btacl_pb_flag, tvb, offset, 2, TRUE);
117 proto_tree_add_item(btacl_tree, hf_btacl_bc_flag, tvb, offset, 2, TRUE);
120 acl_data=ep_alloc(sizeof(bthci_acl_data_t));
121 acl_data->chandle=flags&0x0fff;
122 pd_save = pinfo->private_data;
123 pinfo->private_data=acl_data;
125 /* find the chandle_data structure associated with this chandle */
126 chandle_data=se_tree_lookup32(chandle_tree, acl_data->chandle);
128 chandle_data=se_alloc(sizeof(chandle_data_t));
129 chandle_data->start_fragments=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl fragment starts");
130 se_tree_insert32(chandle_tree, acl_data->chandle, chandle_data);
133 length = tvb_get_letohs(tvb, offset);
134 proto_tree_add_item(btacl_tree, hf_btacl_length, tvb, offset, 2, TRUE);
137 /* determine if packet is fragmented */
139 case 0x01: /* Continuation fragment */
142 case 0x02: /* Start fragment */
143 l2cap_length=tvb_get_letohs(tvb, offset);
144 fragmented=((l2cap_length+4)!=length);
147 /* unknown pb_flag */
153 || ((!acl_reassembly)&&(pb_flag==0x02)) ){
154 /* call L2CAP dissector for PDUs that are not fragmented
155 * also for the first fragment if reassembly is disabled
157 next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
159 call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
161 pinfo->private_data = pd_save;
165 if(fragmented && acl_reassembly){
166 multi_fragment_pdu_t *mfp=NULL;
169 if(pb_flag==0x02){ /* first fragment */
170 if(!pinfo->fd->flags.visited){
171 mfp=se_alloc(sizeof(multi_fragment_pdu_t));
172 mfp->first_frame=pinfo->fd->num;
174 mfp->tot_len=l2cap_length+4;
175 mfp->reassembled=se_alloc(mfp->tot_len);
176 len = tvb_length_remaining(tvb, offset);
177 if (len <= mfp->tot_len) {
178 tvb_memcpy(tvb, (guint8*)mfp->reassembled, offset, len);
180 se_tree_insert32(chandle_data->start_fragments, pinfo->fd->num, mfp);
183 mfp=se_tree_lookup32(chandle_data->start_fragments, pinfo->fd->num);
185 if(mfp && mfp->last_frame){
187 item=proto_tree_add_uint(btacl_tree, hf_btacl_reassembled_in, tvb, 0, 0, mfp->last_frame);
188 PROTO_ITEM_SET_GENERATED(item);
189 if (check_col(pinfo->cinfo, COL_INFO)){
190 col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]", mfp->last_frame);
194 if(pb_flag==0x01){ /* continuation fragment */
195 mfp=se_tree_lookup32_le(chandle_data->start_fragments, pinfo->fd->num);
196 if(!pinfo->fd->flags.visited){
197 len = tvb_length_remaining(tvb, offset);
198 if(mfp && !mfp->last_frame && (mfp->tot_len>=mfp->cur_off+len)){
199 tvb_memcpy(tvb, (guint8*)mfp->reassembled+mfp->cur_off, offset, len);
201 if(mfp->cur_off==mfp->tot_len){
202 mfp->last_frame=pinfo->fd->num;
208 item=proto_tree_add_uint(btacl_tree, hf_btacl_continuation_to, tvb, 0, 0, mfp->first_frame);
209 PROTO_ITEM_SET_GENERATED(item);
210 if (check_col(pinfo->cinfo, COL_INFO)){
211 col_append_fstr(pinfo->cinfo, COL_INFO, " [Continuation to #%u]", mfp->first_frame);
214 if(mfp && mfp->last_frame==pinfo->fd->num){
215 next_tvb = tvb_new_child_real_data(tvb, (guint8*)mfp->reassembled, mfp->tot_len, mfp->tot_len);
216 add_new_data_source(pinfo, next_tvb, "Reassembled BTHCI ACL");
218 /* call L2CAP dissector */
220 call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
225 pinfo->private_data = pd_save;
230 proto_register_btacl(void)
233 /* Setup list of header fields See Section 1.6.1 for details*/
234 static hf_register_info hf[] = {
236 { "Connection Handle", "btacl.chandle",
237 FT_UINT16, BASE_HEX, NULL, 0x0FFF,
241 { "PB Flag", "btacl.pb_flag",
242 FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,
243 "Packet Boundary Flag", HFILL }
246 { "BC Flag", "btacl.bc_flag",
247 FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,
248 "Broadcast Flag", HFILL }
251 { "Data Total Length", "btacl.length",
252 FT_UINT16, BASE_DEC, NULL, 0x0,
256 { "Data", "btacl.data",
257 FT_NONE, BASE_NONE, NULL, 0x0,
260 { &hf_btacl_continuation_to,
261 { "This is a continuation to the PDU in frame", "btacl.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
262 "This is a continuation to the PDU in frame #", HFILL }},
263 { &hf_btacl_reassembled_in,
264 { "This PDU is reassembled in frame", "btacl.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
265 "This PDU is reassembled in frame #", HFILL }},
268 /* Setup protocol subtree array */
269 static gint *ett[] = {
272 module_t *btacl_module;
274 /* Register the protocol name and description */
275 proto_btacl = proto_register_protocol("Bluetooth HCI ACL Packet", "HCI_ACL", "bthci_acl");
276 register_dissector("bthci_acl", dissect_btacl, proto_btacl);
278 /* Required function calls to register the header fields and subtrees used */
279 proto_register_field_array(proto_btacl, hf, array_length(hf));
280 proto_register_subtree_array(ett, array_length(ett));
282 /* Register configuration preferences */
283 btacl_module = prefs_register_protocol(proto_btacl, NULL);
284 prefs_register_bool_preference(btacl_module, "btacl_reassembly",
285 "Reassemble ACL Fragments",
286 "Whether the ACL dissector should reassemble fragmented PDUs",
289 chandle_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl chandles");
294 proto_reg_handoff_btacl(void)
296 dissector_handle_t bthci_acl_handle;
298 bthci_acl_handle = find_dissector("bthci_acl");
299 dissector_add("hci_h4.type", HCI_H4_TYPE_ACL, bthci_acl_handle);
300 dissector_add("hci_h1.type", BTHCI_CHANNEL_ACL, bthci_acl_handle);
303 btl2cap_handle = find_dissector("btl2cap");