aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-05-14 10:18:29 +0000
committerRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-05-14 10:18:29 +0000
commite78afc651818549e0c1cb8e5803155cf6ce0cf9c (patch)
tree1c2f9609a3f3a34e19ddbee93edf948cae93393a
parente49fe267e61897b1404444c401981c62c873d021 (diff)
add bluetooth acl dissection
the fragment reassembly from the old patch is commented out since it has to be redone completely using emem and se_trees the proper way. but to do this i would need example captures of fragmented bluetooth traffic first. svn path=/trunk/; revision=18149
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-bthci_acl.c294
-rw-r--r--epan/dissectors/packet-bthci_evt.c4
3 files changed, 298 insertions, 1 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 65b917bd6e..5ca6bf5663 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -131,6 +131,7 @@ DISSECTOR_SRC = \
packet-brdwlk.c \
packet-bssap.c \
packet-bssgp.c \
+ packet-bthci_acl.c \
packet-bthci_cmd.c \
packet-bthci_evt.c \
packet-bvlc.c \
diff --git a/epan/dissectors/packet-bthci_acl.c b/epan/dissectors/packet-bthci_acl.c
new file mode 100644
index 0000000000..c21046b250
--- /dev/null
+++ b/epan/dissectors/packet-bthci_acl.c
@@ -0,0 +1,294 @@
+/* packet-btacl_acl.c
+ * Routines for the Bluetooth ACL dissection
+ * Copyright 2002, Christoph Scholz <scholz@cs.uni-bonn.de>
+ * From: http://affix.sourceforge.net/archive/ethereal_affix-3.patch
+ *
+ * Refactored for ethereal checkin
+ * Ronnie Sahlberg 2006
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <etypes.h>
+#include <packet-hci_h4.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_btacl = -1;
+static int hf_btacl_chandle = -1;
+static int hf_btacl_pb_flag = -1;
+static int hf_btacl_bc_flag = -1;
+static int hf_btacl_length = -1;
+static int hf_btacl_data = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_btacl = -1;
+
+dissector_handle_t btl2cap_handle=NULL;
+
+static const value_string pb_flag_vals[] = {
+ {1, "Continuing Fragment"},
+ {2, "Start Fragment"},
+ {0, NULL }
+};
+
+static const value_string bc_flag_vals[] = {
+ {0, "Point-To-Point"},
+ {1, "Active Broadcast"},
+ {2, "Piconet Broadcast"},
+ {0, NULL }
+};
+
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_btacl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti=NULL;
+ proto_tree *btacl_tree=NULL;
+ guint16 flags, length;
+ gboolean fragmented;
+ int offset=0;
+ guint16 pb_flag, l2cap_length;
+ tvbuff_t *next_tvb;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_ACL");
+ }
+
+ if(tree){
+ ti=proto_tree_add_item(tree, proto_btacl, tvb, offset, -1, FALSE);
+ btacl_tree = proto_item_add_subtree(ti, ett_btacl);
+ }
+
+ flags=tvb_get_letohs(tvb, offset);
+ pb_flag = (flags & 0x3000) >> 12;
+ proto_tree_add_item(btacl_tree, hf_btacl_chandle, tvb, offset, 2, TRUE);
+ proto_tree_add_item(btacl_tree, hf_btacl_pb_flag, tvb, offset, 2, TRUE);
+ proto_tree_add_item(btacl_tree, hf_btacl_bc_flag, tvb, offset, 2, TRUE);
+ offset+=2;
+
+
+ length = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(btacl_tree, hf_btacl_length, tvb, offset, 2, TRUE);
+ offset+=2;
+
+ /* determine if packet is fragmented */
+ switch(pb_flag){
+ case 0x01: /* Continuation fragment */
+ fragmented = TRUE;
+ break;
+ case 0x02: /* Start fragment */
+ if(length < 2){
+ fragmented=TRUE;
+ } else {
+ l2cap_length=tvb_get_letohs(tvb, offset);
+ fragmented=((l2cap_length+4)!=length);
+ }
+ break;
+ default:
+ /* unknown pb_flag */
+ fragmented = FALSE;
+ }
+
+
+ if(!fragmented){
+ /* call L2CAP dissector */
+ next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
+ if(btl2cap_handle){
+ call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
+ }
+ return;
+ }
+
+
+#ifdef REMOVED offset==4 here
+/* the code below should be rewritten from scratch once a doc explaining how fragmented bt packets work and example captures are collected.
+*/
+ guint16 chandle, handle;
+ struct l2cap_packet *l2p;
+
+ proto_tree_add_item(btacl_tree, hf_btacl_data, tvb, 4, -1, TRUE);
+
+ if (pinfo->fd->flags.visited == 0) { /* This is the first pass */
+
+ chandle = flags & 0x0FFF;
+
+ /* same connection handle but differnet direction needs to be
+ distinguished, therefore we set the highest bit of the
+ handle for outgoing packets
+ */
+ if (pinfo->p2p_dir == P2P_DIR_RECV) {
+ handle = chandle;
+ } else {
+ handle = chandle + 0x8000;
+ }
+
+ l2p = NULL;
+ if (pb_flag == 2) { /* Start Fragment */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " (Start Fragment)");
+
+ if (get_l2p(handle)) { /* Error: There is still data for the same handle */
+ fprintf(stderr, "Incomplete L2CAP packet detected: packet no. %d\n", pinfo->fd->num);
+ del_l2p(handle, 1);
+ }
+
+ /* Start reassembly */
+ if ((l2p = add_l2p(handle))) {
+ l2p->pkt_len = 65540; /* Maybe we don't know the length now */
+ /* So we have to set it to maximum */
+
+ /* memcpy the data */
+ tvb_memcpy(tvb, l2p->data, 4, length);
+ l2p->rx_count = length;
+ } else {
+ fprintf(stderr, "no more handles!\n");
+ }
+
+ } else if (pb_flag == 1) { /* Continuing Fragment */
+ if (!(l2p = get_l2p(handle))) { /* Error: Cont fragment without start */
+ fprintf(stderr, "Cont. fragment without start detected!\n");
+ } else {
+ /* OK: Continue reassembly */
+ /* memcpy the data */
+ tvb_memcpy(tvb, l2p->data + l2p->rx_count, 4, length);
+ l2p->rx_count += length;
+ }
+ }
+
+ if (l2p) {
+ if (l2p->rx_count > 1) /* We have collected enough bytes */
+ l2p->pkt_len = (l2p->data[1] << 8) + l2p->data[0] + 4;
+
+ if (l2p->rx_count > l2p->pkt_len) {
+ fprintf(stderr, "Packet too long!\n");
+ del_l2p(handle, 1);
+ l2p = NULL;
+ } else if (l2p->rx_count == l2p->pkt_len) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " (End Fragment)");
+
+ del_l2p(handle, 0);
+ /* save reassembled packet ???????? */
+ p_add_proto_data(pinfo->fd, proto_btacl, l2p);
+ } else { /* Packet is not complete */
+ l2p = NULL;
+ if (pb_flag == 1) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " (Continuation Fragment)");
+ }
+ }
+ }
+ } else { /* This is an additional pass */
+ /* Is there a reassembled packet saved ? */
+ l2p = p_get_proto_data(pinfo->fd, proto_btacl);
+ }
+
+ if (l2p) {
+ next_tvb = tvb_new_real_data(l2p->data, l2p->pkt_len, l2p->pkt_len);
+ //tvb_set_free_cb(next_tvb, g_free);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled L2CAP");
+
+ /* call L2CAP dissector */
+ if(btl2cap_handle){
+ call_dissector(btl2cap_handle, next_tvb, pinfo, tree);
+ }
+ }
+#endif
+#if 0
+ /* decrypt successful, let's set up a new data tvb. */
+ decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
+ tvb_set_free_cb(decr_tvb, g_free);
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+#endif
+}
+
+
+void
+proto_register_btacl(void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_btacl_chandle,
+ { "Connection Handle", "btacl.chandle",
+ FT_UINT16, BASE_HEX, NULL, 0x0FFF,
+ "Connection Handle", HFILL }
+ },
+ { &hf_btacl_pb_flag,
+ { "PB Flag", "btacl.pb_flag",
+ FT_UINT16, BASE_DEC, VALS(pb_flag_vals), 0x3000,
+ "Packet Boundary Flag", HFILL }
+ },
+ { &hf_btacl_bc_flag,
+ { "BC Flag", "btacl.bc_flag",
+ FT_UINT16, BASE_DEC, VALS(bc_flag_vals), 0xC000,
+ "Broadcast Flag", HFILL }
+ },
+ { &hf_btacl_length,
+ { "Data Total Length", "btacl.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Data Total Length", HFILL }
+ },
+ { &hf_btacl_data,
+ { "Data", "btacl.data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Data", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btacl,
+ };
+
+ /* Register the protocol name and description */
+ proto_btacl = proto_register_protocol("Bluetooth HCI ACL Packet", "HCI_ACL", "bthci_acl");
+ register_dissector("bthci_acl", dissect_btacl, proto_btacl);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btacl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_btacl(void)
+{
+ dissector_handle_t bthci_acl_handle;
+
+ bthci_acl_handle = find_dissector("bthci_acl");
+ dissector_add("hci_h4.type", HCI_H4_TYPE_ACL, bthci_acl_handle);
+
+
+ btl2cap_handle = find_dissector("btl2cap");
+}
+
+
diff --git a/epan/dissectors/packet-bthci_evt.c b/epan/dissectors/packet-bthci_evt.c
index e22c5ed78a..a46f502126 100644
--- a/epan/dissectors/packet-bthci_evt.c
+++ b/epan/dissectors/packet-bthci_evt.c
@@ -717,7 +717,9 @@ dissect_bthci_evt_loopback_command(tvbuff_t *tvb, int offset, packet_info *pinfo
tvbuff_t *next_tvb;
next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), -1);
-/*qqq*/ call_dissector(bthci_com_handle, next_tvb, pinfo, tree);
+ if(bthci_com_handle){
+ call_dissector(bthci_com_handle, next_tvb, pinfo, tree);
+ }
offset+=tvb_length_remaining(tvb, offset);
return offset;