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 {1, "Continuing Fragment"},
77 {2, "Start Fragment"},
81 static const value_string bc_flag_vals[] = {
82 {0, "Point-To-Point"},
83 {1, "Active Broadcast"},
84 {2, "Piconet Broadcast"},
90 /* Code to actually dissect the packets */
92 dissect_btacl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
95 proto_tree *btacl_tree=NULL;
96 guint16 flags, length;
99 guint16 pb_flag, l2cap_length=0;
101 bthci_acl_data_t *acl_data;
102 chandle_data_t *chandle_data;
104 if(check_col(pinfo->cinfo, COL_PROTOCOL)){
105 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 pinfo->private_data=acl_data;
124 /* find the chandle_data structure associated with this chandle */
125 chandle_data=se_tree_lookup32(chandle_tree, acl_data->chandle);
127 chandle_data=se_alloc(sizeof(chandle_data_t));
128 chandle_data->start_fragments=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl fragment starts");
129 se_tree_insert32(chandle_tree, acl_data->chandle, chandle_data);
132 length = tvb_get_letohs(tvb, offset);
133 proto_tree_add_item(btacl_tree, hf_btacl_length, tvb, offset, 2, TRUE);
136 /* determine if packet is fragmented */
138 case 0x01: /* Continuation fragment */
141 case 0x02: /* Start fragment */
142 l2cap_length=tvb_get_letohs(tvb, offset);
143 fragmented=((l2cap_length+4)!=length);
146 /* unknown pb_flag */
152 || ((!acl_reassembly)&&(pb_flag==0x02)) ){
153 /* call L2CAP dissector for PDUs that are not fragmented
154 * also for the first fragment if reassembly is disabled
156 next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
158 call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
163 if(fragmented && acl_reassembly){
164 multi_fragment_pdu_t *mfp=NULL;
166 if(pb_flag==0x02){ /* first fragment */
167 if(!pinfo->fd->flags.visited){
168 mfp=se_alloc(sizeof(multi_fragment_pdu_t));
169 mfp->first_frame=pinfo->fd->num;
171 mfp->tot_len=l2cap_length+4;
172 mfp->reassembled=se_alloc(l2cap_length+4);
173 tvb_memcpy(tvb, (guint8*)mfp->reassembled, offset, tvb_length_remaining(tvb, offset));
174 mfp->cur_off=tvb_length_remaining(tvb, offset);
175 se_tree_insert32(chandle_data->start_fragments, pinfo->fd->num, mfp);
177 mfp=se_tree_lookup32(chandle_data->start_fragments, pinfo->fd->num);
179 if(mfp && mfp->last_frame){
181 item=proto_tree_add_uint(btacl_tree, hf_btacl_reassembled_in, tvb, 0, 0, mfp->last_frame);
182 PROTO_ITEM_SET_GENERATED(item);
183 if (check_col(pinfo->cinfo, COL_INFO)){
184 col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembled in #%u] ", mfp->last_frame);
188 if(pb_flag==0x01){ /* continuation fragment */
189 mfp=se_tree_lookup32_le(chandle_data->start_fragments, pinfo->fd->num);
190 if(!pinfo->fd->flags.visited){
191 if(mfp && !mfp->last_frame && (mfp->tot_len>=mfp->cur_off+tvb_length_remaining(tvb, offset))){
192 tvb_memcpy(tvb, (guint8*)mfp->reassembled+mfp->cur_off, offset, tvb_length_remaining(tvb, offset));
193 mfp->cur_off+=tvb_length_remaining(tvb, offset);
194 if(mfp->cur_off==mfp->tot_len){
195 mfp->last_frame=pinfo->fd->num;
201 item=proto_tree_add_uint(btacl_tree, hf_btacl_continuation_to, tvb, 0, 0, mfp->first_frame);
202 PROTO_ITEM_SET_GENERATED(item);
203 if (check_col(pinfo->cinfo, COL_INFO)){
204 col_append_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", mfp->first_frame);
207 if(mfp && mfp->last_frame==pinfo->fd->num){
208 next_tvb = tvb_new_real_data((guint8*)mfp->reassembled, mfp->tot_len, mfp->tot_len);
209 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
210 add_new_data_source(pinfo, next_tvb, "Reassembled BTHCI ACL");
212 /* call L2CAP dissector */
214 call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
223 proto_register_btacl(void)
226 /* Setup list of header fields See Section 1.6.1 for details*/
227 static hf_register_info hf[] = {
229 { "Connection Handle", "btacl.chandle",
230 FT_UINT16, BASE_HEX, NULL, 0x0FFF,
231 "Connection Handle", HFILL }
234 { "PB Flag", "btacl.pb_flag",
235 FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,
236 "Packet Boundary Flag", HFILL }
239 { "BC Flag", "btacl.bc_flag",
240 FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,
241 "Broadcast Flag", HFILL }
244 { "Data Total Length", "btacl.length",
245 FT_UINT16, BASE_DEC, NULL, 0x0,
246 "Data Total Length", HFILL }
249 { "Data", "btacl.data",
250 FT_NONE, BASE_NONE, NULL, 0x0,
253 { &hf_btacl_continuation_to,
254 { "This is a continuation to the PDU in frame", "btacl.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
255 "This is a continuation to the PDU in frame #", HFILL }},
256 { &hf_btacl_reassembled_in,
257 { "This PDU is reassembled in frame", "btacl.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
258 "This PDU is reassembled in frame #", HFILL }},
261 /* Setup protocol subtree array */
262 static gint *ett[] = {
265 module_t *btacl_module;
267 /* Register the protocol name and description */
268 proto_btacl = proto_register_protocol("Bluetooth HCI ACL Packet", "HCI_ACL", "bthci_acl");
269 register_dissector("bthci_acl", dissect_btacl, proto_btacl);
271 /* Required function calls to register the header fields and subtrees used */
272 proto_register_field_array(proto_btacl, hf, array_length(hf));
273 proto_register_subtree_array(ett, array_length(ett));
275 /* Register configuration preferences */
276 btacl_module = prefs_register_protocol(proto_btacl, NULL);
277 prefs_register_bool_preference(btacl_module, "btacl_reassembly",
278 "Reassemble ACL Fragments",
279 "Whether the ACL dissector should reassemble fragmented PDUs",
282 chandle_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl chandles");
287 proto_reg_handoff_btacl(void)
289 dissector_handle_t bthci_acl_handle;
291 bthci_acl_handle = find_dissector("bthci_acl");
292 dissector_add("hci_h4.type", HCI_H4_TYPE_ACL, bthci_acl_handle);
295 btl2cap_handle = find_dissector("btl2cap");