Get rid of get_ber_last_reated_item() and fix dissection of wIN-TriggerList.
[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         {1, "Continuing Fragment"},
77         {2, "Start Fragment"},
78         {0, NULL }
79 };
80
81 static const value_string bc_flag_vals[] = {
82         {0, "Point-To-Point"},
83         {1, "Active Broadcast"},
84         {2, "Piconet Broadcast"},
85         {0, NULL }
86 };
87
88
89
90 /* Code to actually dissect the packets */
91 static void 
92 dissect_btacl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
93 {
94         proto_item *ti=NULL;
95         proto_tree *btacl_tree=NULL;
96         guint16 flags, length;
97         gboolean fragmented;
98         int offset=0;
99         guint16 pb_flag, l2cap_length=0;
100         tvbuff_t *next_tvb;
101         bthci_acl_data_t *acl_data;
102         chandle_data_t *chandle_data;
103
104         if(check_col(pinfo->cinfo, COL_PROTOCOL)){
105                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_ACL");
106         }
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         pinfo->private_data=acl_data;
123
124         /* find the chandle_data structure associated with this chandle */
125         chandle_data=se_tree_lookup32(chandle_tree, acl_data->chandle);
126         if(!chandle_data){
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);
130         }
131
132         length = tvb_get_letohs(tvb, offset);
133         proto_tree_add_item(btacl_tree, hf_btacl_length, tvb, offset, 2, TRUE);
134         offset+=2;
135
136         /* determine if packet is fragmented */
137         switch(pb_flag){
138         case 0x01:      /* Continuation fragment */
139                 fragmented = TRUE;
140                 break;
141         case 0x02:      /* Start fragment */
142                 l2cap_length=tvb_get_letohs(tvb, offset);
143                 fragmented=((l2cap_length+4)!=length);  
144                 break;
145         default:
146                 /* unknown pb_flag */
147                 fragmented = FALSE;
148         }
149
150
151         if((!fragmented)
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
155                  */
156                 next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
157                 if(btl2cap_handle){
158                         call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
159                 }
160                 return;
161         }
162
163         if(fragmented && acl_reassembly){
164                 multi_fragment_pdu_t *mfp=NULL;
165
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;
170                                 mfp->last_frame=0;
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);
176                         } else {
177                                 mfp=se_tree_lookup32(chandle_data->start_fragments, pinfo->fd->num);
178                         }
179                         if(mfp && mfp->last_frame){
180                                 proto_item *item;
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);
185                                 }
186                         }
187                 }
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;
196                                         }
197                                 }
198                         }
199                         if(mfp){
200                                 proto_item *item;
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);
205                                 }
206                         }
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");
211
212                                 /* call L2CAP dissector */
213                                 if(btl2cap_handle){
214                                         call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
215                                 }
216                         }
217                 }
218         }
219 }
220
221
222 void
223 proto_register_btacl(void)
224 {                 
225
226         /* Setup list of header fields  See Section 1.6.1 for details*/
227         static hf_register_info hf[] = {
228                 { &hf_btacl_chandle,
229                         { "Connection Handle",           "btacl.chandle",
230                                 FT_UINT16, BASE_HEX, NULL, 0x0FFF,          
231                                 "Connection Handle", HFILL }
232                 },
233                 { &hf_btacl_pb_flag,
234                         { "PB Flag",           "btacl.pb_flag",
235                                 FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,          
236                                 "Packet Boundary Flag", HFILL }
237                 },
238                 { &hf_btacl_bc_flag,
239                         { "BC Flag",           "btacl.bc_flag",
240                                 FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,          
241                                 "Broadcast Flag", HFILL }
242                 },
243                 { &hf_btacl_length,
244                         { "Data Total Length",           "btacl.length",
245                                 FT_UINT16, BASE_DEC, NULL, 0x0,          
246                                 "Data Total Length", HFILL }
247                 },
248                 { &hf_btacl_data,
249                         { "Data",           "btacl.data",
250                                 FT_NONE, BASE_NONE, NULL, 0x0,
251                                 "Data", HFILL }
252                 },
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 }},
259         };
260
261         /* Setup protocol subtree array */
262         static gint *ett[] = {
263                 &ett_btacl,
264         };
265         module_t *btacl_module;
266
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);
270
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));
274
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",
280             &acl_reassembly);
281
282         chandle_tree=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "bthci_acl chandles");
283 }
284
285
286 void
287 proto_reg_handoff_btacl(void)
288 {
289         dissector_handle_t bthci_acl_handle;
290
291         bthci_acl_handle = find_dissector("bthci_acl");
292         dissector_add("hci_h4.type", HCI_H4_TYPE_ACL, bthci_acl_handle);
293
294
295         btl2cap_handle = find_dissector("btl2cap");
296 }
297
298