GSM A DTAP: add UMTS EVS to supported codecs list IE
[metze/wireshark/wip.git] / epan / dissectors / packet-bthci_acl.c
1 /* packet-bthci_acl.c
2  * Routines for the Bluetooth ACL dissection
3  * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
4  *     - from: http://affix.sourceforge.net/archive/ethereal_affix-3.patch
5  * Copyright 2006, Ronnie Sahlberg
6  *     - refactored for Wireshark checkin
7  * Copyright 2014, Michal Labedzki for Tieto Corporation
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * SPDX-License-Identifier: GPL-2.0-or-later
14  */
15
16 #include "config.h"
17
18 #include <epan/packet.h>
19 #include <epan/prefs.h>
20 #include <epan/addr_resolv.h>
21 #include <epan/expert.h>
22 #include <epan/proto_data.h>
23
24 #include "packet-bluetooth.h"
25 #include "packet-bthci_acl.h"
26
27 /* Initialize the protocol and registered fields */
28 static int proto_bthci_acl = -1;
29 static int hf_bthci_acl_chandle = -1;
30 static int hf_bthci_acl_pb_flag = -1;
31 static int hf_bthci_acl_bc_flag = -1;
32 static int hf_bthci_acl_length = -1;
33 static int hf_bthci_acl_data = -1;
34 static int hf_bthci_acl_continuation_to = -1;
35 static int hf_bthci_acl_reassembled_in = -1;
36 static int hf_bthci_acl_connect_in = -1;
37 static int hf_bthci_acl_disconnect_in = -1;
38 static int hf_bthci_acl_src_bd_addr = -1;
39 static int hf_bthci_acl_src_name = -1;
40 static int hf_bthci_acl_src_role = -1;
41 static int hf_bthci_acl_dst_bd_addr = -1;
42 static int hf_bthci_acl_dst_name = -1;
43 static int hf_bthci_acl_dst_role = -1;
44 static int hf_bthci_acl_role_last_change_in_frame = -1;
45 static int hf_bthci_acl_mode = -1;
46 static int hf_bthci_acl_mode_last_change_in_frame = -1;
47
48 /* Initialize the subtree pointers */
49 static gint ett_bthci_acl = -1;
50
51 static expert_field ei_invalid_session = EI_INIT;
52 static expert_field ei_length_bad = EI_INIT;
53
54 static dissector_handle_t bthci_acl_handle;
55 static dissector_handle_t btl2cap_handle = NULL;
56
57 static gboolean acl_reassembly = TRUE;
58
59 typedef struct _multi_fragment_pdu_t {
60     guint32  first_frame;
61     guint32  last_frame;
62     guint16  tot_len;
63     char    *reassembled;
64     int      cur_off;           /* counter used by reassembly */
65 } multi_fragment_pdu_t;
66
67 typedef struct _chandle_data_t {
68     wmem_tree_t *start_fragments;  /* indexed by pinfo->num */
69 } chandle_data_t;
70
71 static wmem_tree_t *chandle_tree = NULL;
72
73 static const value_string role_vals[] = {
74     { 0, "Unknown" },
75     { 1, "Master" },
76     { 2, "Slave" },
77     { 0, NULL }
78 };
79
80 static const value_string mode_vals[] = {
81     { 0, "Active Mode" },
82     { 1, "Hold Mode" },
83     { 2, "Sniff Mode" },
84     { 3, "Park Mode" },
85     {-1, "Unknown" },
86     { 0, NULL }
87 };
88
89 static const value_string pb_flag_vals[] = {
90     { 0, "First Non-automatically Flushable Packet" },
91     { 1, "Continuing Fragment" },
92     { 2, "First Automatically Flushable Packet" },
93     { 0, NULL }
94 };
95
96 static const value_string bc_flag_vals[] = {
97     { 0, "Point-To-Point" },
98     { 1, "Active Broadcast" },
99     { 2, "Piconet Broadcast" },
100     { 0, NULL }
101 };
102
103 static guint32 invalid_session = 0;
104
105
106 void proto_register_bthci_acl(void);
107 void proto_reg_handoff_bthci_acl(void);
108
109 /* Code to actually dissect the packets */
110 static gint
111 dissect_bthci_acl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
112 {
113     proto_item               *bthci_acl_item;
114     proto_tree               *bthci_acl_tree;
115     proto_item               *sub_item;
116     proto_item               *length_item;
117     guint16                   flags;
118     guint16                   length;
119     gboolean                  fragmented;
120     gint                      offset                = 0;
121     guint16                   pb_flag, l2cap_length = 0;
122     tvbuff_t                 *next_tvb;
123     bthci_acl_data_t         *acl_data;
124     chandle_data_t           *chandle_data;
125     bluetooth_data_t         *bluetooth_data;
126     wmem_tree_t              *subtree;
127     wmem_tree_key_t           key[6];
128     guint32                   interface_id;
129     guint32                   adapter_id;
130     guint32                   connection_handle;
131     guint32                   direction;
132     guint32                   frame_number;
133     remote_bdaddr_t          *remote_bdaddr;
134     const gchar              *localhost_name;
135     guint8                    localhost_bdaddr[6];
136     const gchar              *localhost_ether_addr;
137     gchar                    *localhost_addr_name;
138     gint                      localhost_length;
139     localhost_bdaddr_entry_t *localhost_bdaddr_entry;
140     localhost_name_entry_t   *localhost_name_entry;
141     const guint8              unknown_bd_addr[6] = {0, 0, 0, 0, 0, 0};
142     const guint8             *src_bd_addr = &unknown_bd_addr[0];
143     const gchar              *src_name = "";
144     const gchar              *src_addr_name = "";
145     const guint8             *dst_bd_addr = &unknown_bd_addr[0];
146     const gchar              *dst_name = "";
147     const gchar              *dst_addr_name = "";
148     chandle_session_t        *chandle_session;
149     guint32                   src_role = ROLE_UNKNOWN;
150     guint32                   dst_role = ROLE_UNKNOWN;
151     guint32                   role_last_change_in_frame = 0;
152     connection_mode_t        *connection_mode;
153     gint32                    mode = -1;
154     guint32                   mode_last_change_in_frame = 0;
155
156     /* Reject the packet if data is NULL */
157     if (data == NULL)
158         return 0;
159     bluetooth_data = (bluetooth_data_t *) data;
160
161     bthci_acl_item = proto_tree_add_item(tree, proto_bthci_acl, tvb, offset, -1, ENC_NA);
162     bthci_acl_tree = proto_item_add_subtree(bthci_acl_item, ett_bthci_acl);
163
164     switch (pinfo->p2p_dir) {
165         case P2P_DIR_SENT:
166             col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
167             break;
168         case P2P_DIR_RECV:
169             col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
170             break;
171         default:
172         col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
173             break;
174     }
175
176     col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_ACL");
177
178     flags   = tvb_get_letohs(tvb, offset);
179     pb_flag = (flags & 0x3000) >> 12;
180     proto_tree_add_item(bthci_acl_tree, hf_bthci_acl_chandle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
181     proto_tree_add_item(bthci_acl_tree, hf_bthci_acl_pb_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
182     proto_tree_add_item(bthci_acl_tree, hf_bthci_acl_bc_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
183     offset += 2;
184
185     interface_id      = bluetooth_data->interface_id;
186     adapter_id        = bluetooth_data->adapter_id;
187     connection_handle = flags & 0x0fff;
188     direction         = pinfo->p2p_dir;
189     frame_number      = pinfo->num;
190
191     acl_data = wmem_new(wmem_packet_scope(), bthci_acl_data_t);
192     acl_data->interface_id                = interface_id;
193     acl_data->adapter_id                  = adapter_id;
194     acl_data->adapter_disconnect_in_frame = bluetooth_data->adapter_disconnect_in_frame;
195     acl_data->chandle                     = connection_handle;
196     acl_data->is_btle                     = FALSE;
197     acl_data->is_btle_retransmit          = FALSE;
198
199     key[0].length = 1;
200     key[0].key    = &interface_id;
201     key[1].length = 1;
202     key[1].key    = &adapter_id;
203     key[2].length = 1;
204     key[2].key    = &connection_handle;
205     key[3].length = 0;
206     key[3].key    = NULL;
207
208     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->chandle_sessions, key);
209     chandle_session = (subtree) ? (chandle_session_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
210     if (chandle_session &&
211             chandle_session->connect_in_frame < pinfo->num &&
212             chandle_session->disconnect_in_frame > pinfo->num) {
213         acl_data->disconnect_in_frame = &chandle_session->disconnect_in_frame;
214     } else {
215         acl_data->disconnect_in_frame = &invalid_session;
216         chandle_session = NULL;
217     }
218
219     acl_data->remote_bd_addr_oui         = 0;
220     acl_data->remote_bd_addr_id          = 0;
221
222     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->chandle_to_mode, key);
223     connection_mode = (subtree) ? (connection_mode_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
224     if (connection_mode) {
225         mode = connection_mode->mode;
226         mode_last_change_in_frame = connection_mode->change_in_frame;
227     }
228
229     /* remote bdaddr and name */
230     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->chandle_to_bdaddr, key);
231     remote_bdaddr = (subtree) ? (remote_bdaddr_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
232     if (remote_bdaddr) {
233         guint32         k_bd_addr_oui;
234         guint32         k_bd_addr_id;
235         guint32         bd_addr_oui;
236         guint32         bd_addr_id;
237         device_name_t  *device_name;
238         device_role_t  *device_role;
239         const gchar    *remote_name;
240         const gchar    *remote_ether_addr;
241         gchar          *remote_addr_name;
242         gint            remote_length;
243
244         bd_addr_oui = remote_bdaddr->bd_addr[0] << 16 | remote_bdaddr->bd_addr[1] << 8 | remote_bdaddr->bd_addr[2];
245         bd_addr_id  = remote_bdaddr->bd_addr[3] << 16 | remote_bdaddr->bd_addr[4] << 8 | remote_bdaddr->bd_addr[5];
246
247         acl_data->remote_bd_addr_oui = bd_addr_oui;
248         acl_data->remote_bd_addr_id  = bd_addr_id;
249
250         k_bd_addr_oui  = bd_addr_oui;
251         k_bd_addr_id   = bd_addr_id;
252
253         key[0].length = 1;
254         key[0].key    = &interface_id;
255         key[1].length = 1;
256         key[1].key    = &adapter_id;
257         key[2].length = 1;
258         key[2].key    = &k_bd_addr_id;
259         key[3].length = 1;
260         key[3].key    = &k_bd_addr_oui;
261         key[4].length = 0;
262         key[4].key    = NULL;
263
264         subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->bdaddr_to_role, key);
265         device_role = (subtree) ? (device_role_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
266         if (device_role) {
267             if ((pinfo->p2p_dir == P2P_DIR_SENT && device_role->role == ROLE_MASTER) ||
268                     (pinfo->p2p_dir == P2P_DIR_RECV && device_role->role == ROLE_SLAVE)) {
269                 src_role = ROLE_SLAVE;
270                 dst_role = ROLE_MASTER;
271             } else if ((pinfo->p2p_dir == P2P_DIR_SENT && device_role->role == ROLE_SLAVE) ||
272                     (pinfo->p2p_dir == P2P_DIR_RECV && device_role->role == ROLE_MASTER)) {
273                 src_role = ROLE_MASTER;
274                 dst_role = ROLE_SLAVE;
275             }
276             role_last_change_in_frame = device_role->change_in_frame;
277         }
278
279         subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->bdaddr_to_name, key);
280         device_name = (subtree) ? (device_name_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
281         if (device_name)
282             remote_name = device_name->name;
283         else
284             remote_name = "";
285
286         remote_ether_addr = get_ether_name(remote_bdaddr->bd_addr);
287         remote_length = (gint)(strlen(remote_ether_addr) + 3 + strlen(remote_name) + 1);
288         remote_addr_name = (gchar *)wmem_alloc(pinfo->pool, remote_length);
289
290         g_snprintf(remote_addr_name, remote_length, "%s (%s)", remote_ether_addr, remote_name);
291
292         if (pinfo->p2p_dir == P2P_DIR_RECV) {
293             src_bd_addr   = remote_bdaddr->bd_addr;
294             src_name      = remote_name;
295             src_addr_name = remote_addr_name;
296         } else if (pinfo->p2p_dir == P2P_DIR_SENT) {
297             dst_bd_addr   = remote_bdaddr->bd_addr;
298             dst_name      = remote_name;
299             dst_addr_name = remote_addr_name;
300         }
301     } else {
302         if (pinfo->p2p_dir == P2P_DIR_RECV)
303             src_addr_name = "remote ()";
304         else if (pinfo->p2p_dir == P2P_DIR_SENT)
305             dst_addr_name = "remote ()";
306     }
307
308     /* localhost bdaddr and name */
309     key[0].length = 1;
310     key[0].key    = &interface_id;
311     key[1].length = 1;
312     key[1].key    = &adapter_id;
313     key[2].length = 0;
314     key[2].key    = NULL;
315
316
317     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->localhost_bdaddr, key);
318     localhost_bdaddr_entry = (subtree) ? (localhost_bdaddr_entry_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
319     if (localhost_bdaddr_entry) {
320         localhost_ether_addr = get_ether_name(localhost_bdaddr_entry->bd_addr);
321         memcpy(localhost_bdaddr, localhost_bdaddr_entry->bd_addr, 6);
322     } else {
323         localhost_ether_addr = "localhost";
324         memcpy(localhost_bdaddr, unknown_bd_addr, 6);
325     }
326
327     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(bluetooth_data->localhost_name, key);
328     localhost_name_entry = (subtree) ? (localhost_name_entry_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
329     if (localhost_name_entry)
330         localhost_name = localhost_name_entry->name;
331     else
332         localhost_name = "";
333
334     localhost_length = (gint)(strlen(localhost_ether_addr) + 3 + strlen(localhost_name) + 1);
335     localhost_addr_name = (gchar *)wmem_alloc(pinfo->pool, localhost_length);
336
337     g_snprintf(localhost_addr_name, localhost_length, "%s (%s)", localhost_ether_addr, localhost_name);
338
339     if (pinfo->p2p_dir == P2P_DIR_RECV) {
340         dst_bd_addr   = localhost_bdaddr;
341         dst_name      = localhost_name;
342         dst_addr_name = localhost_addr_name;
343     } else if (pinfo->p2p_dir == P2P_DIR_SENT) {
344         src_bd_addr   = localhost_bdaddr;
345         src_name      = localhost_name;
346         src_addr_name = localhost_addr_name;
347     }
348
349     /* find the chandle_data structure associated with this chandle */
350     key[0].length = 1;
351     key[0].key = &interface_id;
352     key[1].length = 1;
353     key[1].key = &adapter_id;
354     key[2].length = 1;
355     key[2].key = &connection_handle;
356     key[3].length = 1;
357     key[3].key = &direction;
358     key[4].length = 0;
359     key[4].key = NULL;
360
361     subtree = (wmem_tree_t *) wmem_tree_lookup32_array(chandle_tree, key);
362     chandle_data = (subtree) ? (chandle_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
363     if (!pinfo->fd->flags.visited && !chandle_data) {
364         key[0].length = 1;
365         key[0].key = &interface_id;
366         key[1].length = 1;
367         key[1].key = &adapter_id;
368         key[2].length = 1;
369         key[2].key = &connection_handle;
370         key[3].length = 1;
371         key[3].key = &direction;
372         key[4].length = 1;
373         key[4].key = &frame_number;
374         key[5].length = 0;
375         key[5].key = NULL;
376
377         chandle_data = (chandle_data_t *)wmem_alloc(wmem_file_scope(), sizeof(chandle_data_t));
378         chandle_data->start_fragments = wmem_tree_new(wmem_file_scope());
379
380         wmem_tree_insert32_array(chandle_tree, key, chandle_data);
381     } else if (pinfo->fd->flags.visited && !chandle_data) {
382         DISSECTOR_ASSERT_HINT(0, "Impossible: no previously session saved");
383     }
384
385     length = tvb_get_letohs(tvb, offset);
386     length_item = proto_tree_add_item(bthci_acl_tree, hf_bthci_acl_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
387     offset += 2;
388
389     /* determine if packet is fragmented */
390     switch(pb_flag) {
391     case 0x01:  /* Continuation fragment */
392         fragmented = TRUE;
393         break;
394     case 0x00:  /* First fragment/packet, non-auto flushable */
395     case 0x02:  /* First fragment/packet, auto flushable */
396         l2cap_length = tvb_get_letohs(tvb, offset);
397         fragmented   = (l2cap_length + 4 != length);
398         break;
399     default:
400         /* unknown pb_flag */
401         fragmented = FALSE;
402     }
403
404     alloc_address_wmem(pinfo->pool, &pinfo->net_src, AT_STRINGZ, (int)strlen(src_name) + 1, src_name);
405     alloc_address_wmem(pinfo->pool, &pinfo->dl_src, AT_ETHER, 6, src_bd_addr);
406     alloc_address_wmem(pinfo->pool, &pinfo->src, AT_STRINGZ, (int)strlen(src_addr_name) + 1, src_addr_name);
407
408     alloc_address_wmem(pinfo->pool, &pinfo->net_dst, AT_STRINGZ, (int)strlen(dst_name) + 1, dst_name);
409     alloc_address_wmem(pinfo->pool, &pinfo->dl_dst, AT_ETHER, 6, dst_bd_addr);
410     alloc_address_wmem(pinfo->pool, &pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr_name) + 1, dst_addr_name);
411
412     if (!fragmented || (!acl_reassembly && !(pb_flag & 0x01))) {
413         /* call L2CAP dissector for PDUs that are not fragmented
414          * also for the first fragment if reassembly is disabled
415          */
416         if (length < tvb_captured_length_remaining(tvb, offset)) {
417             expert_add_info(pinfo, length_item, &ei_length_bad);
418             /* Try to dissect as more as possible */
419             length = tvb_captured_length_remaining(tvb, offset);
420         }
421
422         next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), length);
423         call_dissector_with_data(btl2cap_handle, next_tvb, pinfo, tree, acl_data);
424     } else if (fragmented && acl_reassembly) {
425         multi_fragment_pdu_t *mfp = NULL;
426         gint                  len;
427
428         if (!(pb_flag & 0x01)) { /* first fragment */
429             if (!pinfo->fd->flags.visited) {
430                 mfp = (multi_fragment_pdu_t *) wmem_new(wmem_file_scope(), multi_fragment_pdu_t);
431                 mfp->first_frame = pinfo->num;
432                 mfp->last_frame  = 0;
433                 mfp->tot_len     = l2cap_length + 4;
434                 mfp->reassembled = (char *) wmem_alloc(wmem_file_scope(), mfp->tot_len);
435                 len = tvb_captured_length_remaining(tvb, offset);
436                 if (len <= mfp->tot_len) {
437                     tvb_memcpy(tvb, (guint8 *) mfp->reassembled, offset, len);
438                     mfp->cur_off = len;
439                     wmem_tree_insert32(chandle_data->start_fragments, pinfo->num, mfp);
440                 }
441             } else {
442                 mfp = (multi_fragment_pdu_t *)wmem_tree_lookup32(chandle_data->start_fragments, pinfo->num);
443             }
444             if (mfp != NULL && mfp->last_frame) {
445                 proto_item *item;
446
447                 item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_reassembled_in, tvb, 0, 0, mfp->last_frame);
448                 PROTO_ITEM_SET_GENERATED(item);
449                 col_append_frame_number(pinfo, COL_INFO, " [Reassembled in #%u]", mfp->last_frame);
450             }
451         }
452         if (pb_flag == 0x01) { /* continuation fragment */
453             mfp = (multi_fragment_pdu_t *)wmem_tree_lookup32_le(chandle_data->start_fragments, pinfo->num);
454             if (!pinfo->fd->flags.visited) {
455                 len = tvb_captured_length_remaining(tvb, offset);
456                 if (mfp != NULL && !mfp->last_frame && (mfp->tot_len >= mfp->cur_off + len)) {
457                     tvb_memcpy(tvb, (guint8 *) mfp->reassembled + mfp->cur_off, offset, len);
458                     mfp->cur_off += len;
459                     if (mfp->cur_off == mfp->tot_len) {
460                         mfp->last_frame = pinfo->num;
461                     }
462                 }
463             }
464             if (mfp) {
465                 proto_item *item;
466
467                 item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_continuation_to, tvb, 0, 0, mfp->first_frame);
468                 PROTO_ITEM_SET_GENERATED(item);
469                 col_append_frame_number(pinfo, COL_INFO, " [Continuation to #%u]", mfp->first_frame);
470                 if (mfp->last_frame && mfp->last_frame != pinfo->num) {
471                     item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_reassembled_in, tvb, 0, 0, mfp->last_frame);
472                     PROTO_ITEM_SET_GENERATED(item);
473                     col_append_frame_number(pinfo, COL_INFO, " [Reassembled in #%u]", mfp->last_frame);
474                 }
475             }
476             if (mfp != NULL && mfp->last_frame == pinfo->num) {
477                 next_tvb = tvb_new_child_real_data(tvb, (guint8 *) mfp->reassembled, mfp->tot_len, mfp->tot_len);
478                 add_new_data_source(pinfo, next_tvb, "Reassembled BTHCI ACL");
479
480                 call_dissector_with_data(btl2cap_handle, next_tvb, pinfo, tree, acl_data);
481             }
482         }
483     }
484
485     if (tvb_captured_length_remaining(tvb, offset) > 0) {
486         sub_item = proto_tree_add_item(bthci_acl_tree, hf_bthci_acl_data, tvb, offset, -1, ENC_NA);
487         if (fragmented) {
488             proto_item_append_text(sub_item, " Fragment");
489         }
490     }
491
492     if (chandle_session) {
493         sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_connect_in, tvb, 0, 0, chandle_session->connect_in_frame);
494         PROTO_ITEM_SET_GENERATED(sub_item);
495
496         if (chandle_session->disconnect_in_frame < G_MAXUINT32) {
497             sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_disconnect_in, tvb, 0, 0, chandle_session->disconnect_in_frame);
498             PROTO_ITEM_SET_GENERATED(sub_item);
499         }
500     }
501
502     if (acl_data->disconnect_in_frame == &invalid_session) {
503         expert_add_info(pinfo, bthci_acl_item, &ei_invalid_session);
504     }
505
506     if (!pinfo->fd->flags.visited) {
507         address *addr;
508
509         addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
510         addr->data =  wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
511         p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
512
513         addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
514         addr->data =  wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
515         p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
516     }
517
518     sub_item = proto_tree_add_ether(bthci_acl_tree, hf_bthci_acl_src_bd_addr, tvb, 0, 0, src_bd_addr);
519     PROTO_ITEM_SET_GENERATED(sub_item);
520
521     sub_item = proto_tree_add_string(bthci_acl_tree, hf_bthci_acl_src_name, tvb, 0, 0, src_name);
522     PROTO_ITEM_SET_GENERATED(sub_item);
523
524     sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_src_role, tvb, 0, 0, src_role);
525     PROTO_ITEM_SET_GENERATED(sub_item);
526
527     sub_item = proto_tree_add_ether(bthci_acl_tree, hf_bthci_acl_dst_bd_addr, tvb, 0, 0, dst_bd_addr);
528     PROTO_ITEM_SET_GENERATED(sub_item);
529
530     sub_item = proto_tree_add_string(bthci_acl_tree, hf_bthci_acl_dst_name, tvb, 0, 0, dst_name);
531     PROTO_ITEM_SET_GENERATED(sub_item);
532
533     sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_dst_role, tvb, 0, 0, dst_role);
534     PROTO_ITEM_SET_GENERATED(sub_item);
535
536     if (role_last_change_in_frame > 0) {
537         sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_role_last_change_in_frame, tvb, 0, 0, role_last_change_in_frame);
538         PROTO_ITEM_SET_GENERATED(sub_item);
539     }
540
541     sub_item = proto_tree_add_int(bthci_acl_tree, hf_bthci_acl_mode, tvb, 0, 0, mode);
542     PROTO_ITEM_SET_GENERATED(sub_item);
543
544     if (mode_last_change_in_frame > 0) {
545         sub_item = proto_tree_add_uint(bthci_acl_tree, hf_bthci_acl_mode_last_change_in_frame, tvb, 0, 0, mode_last_change_in_frame);
546         PROTO_ITEM_SET_GENERATED(sub_item);
547     }
548
549     return tvb_captured_length(tvb);
550 }
551
552
553 void
554 proto_register_bthci_acl(void)
555 {
556     module_t         *bthci_acl_module;
557     expert_module_t  *bthci_acl_expert_module;
558     /* Setup list of header fields  See Section 1.6.1 for details*/
559     static hf_register_info hf[] = {
560         { &hf_bthci_acl_chandle,
561           { "Connection Handle",                             "bthci_acl.chandle",
562             FT_UINT16, BASE_HEX, NULL, 0x0FFF,
563             NULL, HFILL }
564         },
565         { &hf_bthci_acl_pb_flag,
566           { "PB Flag",                                       "bthci_acl.pb_flag",
567             FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,
568             "Packet Boundary Flag", HFILL }
569         },
570         { &hf_bthci_acl_bc_flag,
571           { "BC Flag",                                       "bthci_acl.bc_flag",
572             FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,
573             "Broadcast Flag", HFILL }
574         },
575         { &hf_bthci_acl_length,
576           { "Data Total Length",                             "bthci_acl.length",
577             FT_UINT16, BASE_DEC, NULL, 0x0,
578             NULL, HFILL }
579         },
580         { &hf_bthci_acl_data,
581           { "Data",                                          "bthci_acl.data",
582             FT_NONE, BASE_NONE, NULL, 0x0,
583             NULL, HFILL }
584         },
585         { &hf_bthci_acl_continuation_to,
586           { "This is a continuation to the PDU in frame",    "bthci_acl.continuation_to",
587             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
588             "This is a continuation to the PDU in frame #", HFILL }
589         },
590         { &hf_bthci_acl_reassembled_in,
591           { "This PDU is reassembled in frame",              "bthci_acl.reassembled_in",
592             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
593             "This PDU is reassembled in frame #", HFILL }
594         },
595         { &hf_bthci_acl_connect_in,
596             { "Connect in frame",                            "bthci_acl.connect_in",
597             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
598             NULL, HFILL }
599         },
600         { &hf_bthci_acl_disconnect_in,
601             { "Disconnect in frame",                         "bthci_acl.disconnect_in",
602             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
603             NULL, HFILL }
604         },
605         { &hf_bthci_acl_src_bd_addr,
606             { "Source BD_ADDR",                              "bthci_acl.src.bd_addr",
607             FT_ETHER, BASE_NONE, NULL, 0x0,
608             NULL, HFILL }
609         },
610         { &hf_bthci_acl_src_name,
611             { "Source Device Name",                          "bthci_acl.src.name",
612             FT_STRINGZ, BASE_NONE, NULL, 0x0,
613             NULL, HFILL }
614         },
615         { &hf_bthci_acl_src_role,
616             { "Source Role",                                "bthci_acl.src.role",
617             FT_UINT32, BASE_DEC, VALS(role_vals), 0x0,
618             NULL, HFILL }
619         },
620         { &hf_bthci_acl_dst_bd_addr,
621             { "Destination BD_ADDR",                         "bthci_acl.dst.bd_addr",
622             FT_ETHER, BASE_NONE, NULL, 0x0,
623             NULL, HFILL }
624         },
625         { &hf_bthci_acl_dst_name,
626             { "Destination Device Name",                     "bthci_acl.dst.name",
627             FT_STRINGZ, BASE_NONE, NULL, 0x0,
628             NULL, HFILL }
629         },
630         { &hf_bthci_acl_dst_role,
631             { "Destination Role",                            "bthci_acl.dst.role",
632             FT_UINT32, BASE_DEC, VALS(role_vals), 0x0,
633             NULL, HFILL }
634         },
635         { &hf_bthci_acl_role_last_change_in_frame,
636             { "Last Role Change in Frame",                   "bthci_acl.last_change_in_frame.role",
637             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
638             NULL, HFILL }
639         },
640         { &hf_bthci_acl_mode,
641             { "Current Mode",                                "bthci_acl.mode",
642             FT_INT32, BASE_DEC, VALS(mode_vals), 0x0,
643             NULL, HFILL }
644         },
645         { &hf_bthci_acl_mode_last_change_in_frame,
646             { "Last Mode Change in Frame",                   "bthci_acl.last_change_in_frame.mode",
647             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
648             NULL, HFILL }
649         },
650     };
651
652     /* Setup protocol subtree array */
653     static gint *ett[] = {
654         &ett_bthci_acl,
655     };
656
657     static ei_register_info ei[] = {
658         { &ei_invalid_session, { "bthci_acl.invalid_session", PI_PROTOCOL,  PI_ERROR, "Frame is out of any \"connection handle\" session", EXPFILL }},
659         { &ei_length_bad,      { "bthci_acl.length.bad",      PI_MALFORMED, PI_WARN, "Length too short", EXPFILL }},
660     };
661
662     /* Register the protocol name and description */
663     proto_bthci_acl = proto_register_protocol("Bluetooth HCI ACL Packet", "HCI_ACL", "bthci_acl");
664     bthci_acl_handle = register_dissector("bthci_acl", dissect_bthci_acl, proto_bthci_acl);
665
666     /* Required function calls to register the header fields and subtrees used */
667     proto_register_field_array(proto_bthci_acl, hf, array_length(hf));
668     proto_register_subtree_array(ett, array_length(ett));
669
670     bthci_acl_expert_module = expert_register_protocol(proto_bthci_acl);
671     expert_register_field_array(bthci_acl_expert_module, ei, array_length(ei));
672
673     /* Register configuration preferences */
674     bthci_acl_module = prefs_register_protocol_subtree("Bluetooth", proto_bthci_acl, NULL);
675     prefs_register_bool_preference(bthci_acl_module, "hci_acl_reassembly",
676         "Reassemble ACL Fragments",
677         "Whether the ACL dissector should reassemble fragmented PDUs",
678         &acl_reassembly);
679
680     chandle_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
681 }
682
683
684 void
685 proto_reg_handoff_bthci_acl(void)
686 {
687     dissector_add_uint("hci_h4.type", HCI_H4_TYPE_ACL, bthci_acl_handle);
688     dissector_add_uint("hci_h1.type", BTHCI_CHANNEL_ACL, bthci_acl_handle);
689
690     btl2cap_handle = find_dissector_add_dependency("btl2cap", proto_bthci_acl);
691 }
692
693 /*
694  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
695  *
696  * Local variables:
697  * c-basic-offset: 4
698  * tab-width: 8
699  * indent-tabs-mode: nil
700  * End:
701  *
702  * vi: set shiftwidth=4 tabstop=8 expandtab:
703  * :indentSize=4:tabSize=8:noTabs=true:
704  */