2634faf4fdf397c188dbaf32f3ea1e1959f2d133
[obnox/wireshark/wip.git] / epan / dissectors / packet-bthci_acl.c
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 */
2
3 /* packet-btacl_acl.c
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
7  *
8  * Refactored for wireshark checkin
9  *   Ronnie Sahlberg 2006
10  *
11  * $Id$
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
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.
21  *
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.
26  *
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.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/emem.h>
39 #include <epan/prefs.h>
40 #include <etypes.h>
41 #include <packet-hci_h4.h>
42 #include <packet-bthci_acl.h>
43
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;
53
54 /* Initialize the subtree pointers */
55 static gint ett_btacl = -1;
56
57 static dissector_handle_t btl2cap_handle=NULL;
58
59 static gboolean acl_reassembly = TRUE;
60
61 typedef struct _multi_fragment_pdu_t {
62         guint32 first_frame;
63         guint32 last_frame;
64         guint16 tot_len;
65         char *reassembled;
66         int cur_off;    /* counter used by reassembly */
67 } multi_fragment_pdu_t;
68
69 typedef struct _chandle_data_t {
70         emem_tree_t *start_fragments;  /* indexed by pinfo->fd->num */
71 } chandle_data_t;
72
73 static emem_tree_t *chandle_tree=NULL;
74
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"},
79         {0, NULL }
80 };
81
82 static const value_string bc_flag_vals[] = {
83         {0, "Point-To-Point"},
84         {1, "Active Broadcast"},
85         {2, "Piconet Broadcast"},
86         {0, NULL }
87 };
88
89
90
91 /* Code to actually dissect the packets */
92 static void
93 dissect_btacl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
94 {
95         proto_item *ti=NULL;
96         proto_tree *btacl_tree=NULL;
97         guint16 flags, length;
98         gboolean fragmented;
99         int offset=0;
100         guint16 pb_flag, l2cap_length=0;
101         tvbuff_t *next_tvb;
102         bthci_acl_data_t *acl_data;
103         chandle_data_t *chandle_data;
104         void* pd_save;
105
106         col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_ACL");
107
108         if(tree){
109                 ti=proto_tree_add_item(tree, proto_btacl, tvb, offset, -1, FALSE);
110                 btacl_tree = proto_item_add_subtree(ti, ett_btacl);
111         }
112
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);
118         offset+=2;
119
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;
124
125         /* find the chandle_data structure associated with this chandle */
126         chandle_data=se_tree_lookup32(chandle_tree, acl_data->chandle);
127         if(!chandle_data){
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);
131         }
132
133         length = tvb_get_letohs(tvb, offset);
134         proto_tree_add_item(btacl_tree, hf_btacl_length, tvb, offset, 2, TRUE);
135         offset+=2;
136
137         /* determine if packet is fragmented */
138         switch(pb_flag){
139         case 0x01:      /* Continuation fragment */
140                 fragmented = TRUE;
141                 break;
142         case 0x02:      /* Start fragment */
143                 l2cap_length=tvb_get_letohs(tvb, offset);
144                 fragmented=((l2cap_length+4)!=length);
145                 break;
146         default:
147                 /* unknown pb_flag */
148                 fragmented = FALSE;
149         }
150
151
152         if((!fragmented)
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
156                  */
157                 next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
158                 if(btl2cap_handle){
159                         call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
160                 }
161                 pinfo->private_data = pd_save;
162                 return;
163         }
164
165         if(fragmented && acl_reassembly){
166                 multi_fragment_pdu_t *mfp=NULL;
167                 gint len;
168
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;
173                                 mfp->last_frame=0;
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);
179                                         mfp->cur_off=len;
180                                         se_tree_insert32(chandle_data->start_fragments, pinfo->fd->num, mfp);
181                                 }
182                         } else {
183                                 mfp=se_tree_lookup32(chandle_data->start_fragments, pinfo->fd->num);
184                         }
185                         if(mfp && mfp->last_frame){
186                                 proto_item *item;
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);
191                                 }
192                         }
193                 }
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);
200                                         mfp->cur_off+=len;
201                                         if(mfp->cur_off==mfp->tot_len){
202                                                 mfp->last_frame=pinfo->fd->num;
203                                         }
204                                 }
205                         }
206                         if(mfp){
207                                 proto_item *item;
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);
212                                 }
213                         }
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");
217
218                                 /* call L2CAP dissector */
219                                 if(btl2cap_handle){
220                                         call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
221                                 }
222                         }
223                 }
224         }
225         pinfo->private_data = pd_save;
226 }
227
228
229 void
230 proto_register_btacl(void)
231 {
232
233         /* Setup list of header fields  See Section 1.6.1 for details*/
234         static hf_register_info hf[] = {
235                 { &hf_btacl_chandle,
236                         { "Connection Handle",           "btacl.chandle",
237                                 FT_UINT16, BASE_HEX, NULL, 0x0FFF,
238                                 NULL, HFILL }
239                 },
240                 { &hf_btacl_pb_flag,
241                         { "PB Flag",           "btacl.pb_flag",
242                                 FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,
243                                 "Packet Boundary Flag", HFILL }
244                 },
245                 { &hf_btacl_bc_flag,
246                         { "BC Flag",           "btacl.bc_flag",
247                                 FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,
248                                 "Broadcast Flag", HFILL }
249                 },
250                 { &hf_btacl_length,
251                         { "Data Total Length",           "btacl.length",
252                                 FT_UINT16, BASE_DEC, NULL, 0x0,
253                                 NULL, HFILL }
254                 },
255                 { &hf_btacl_data,
256                         { "Data",           "btacl.data",
257                                 FT_NONE, BASE_NONE, NULL, 0x0,
258                                 NULL, HFILL }
259                 },
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 }},
266         };
267
268         /* Setup protocol subtree array */
269         static gint *ett[] = {
270                 &ett_btacl,
271         };
272         module_t *btacl_module;
273
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);
277
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));
281
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",
287             &acl_reassembly);
288
289         chandle_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl chandles");
290 }
291
292
293 void
294 proto_reg_handoff_btacl(void)
295 {
296         dissector_handle_t bthci_acl_handle;
297
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);
301
302
303         btl2cap_handle = find_dissector("btl2cap");
304 }
305
306