From Michal Labedzki:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 24 Sep 2012 12:30:30 +0000 (12:30 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 24 Sep 2012 12:30:30 +0000 (12:30 +0000)
Add Bluetooth Protocol AVCTP. Supported version: 1.4.

https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7675

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@45097 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
colorfilters
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-btavctp.c [new file with mode: 0644]
epan/dissectors/packet-btavctp.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index a1b81c2c183f361f412058b0a39435250597da89..58360ad7df0454e5e44828b5b36ba39ce2832ceb 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3471,6 +3471,7 @@ Michal Labedzki           <michal.labedzki[at]tieto.com> {
        Bluetooth BNEP dissector
        Bluetooth HID dissector
        Bluetooth SAP dissector
+       Bluetooth AVCTP dissector
 }
 
 and by:
index 3a247d7bb1a602e6c26671f51417889cc93813ff..e363bb944d1b1254dcba3c61c711690d14392948 100644 (file)
@@ -22,6 +22,7 @@
 
 # Bluetooth
 @HID@bthid@[47057,38562,38562][5111,4915,4652]
+@AVCTP@btavctp@[52805,45039,37599][5111,4915,4652]
 @HFP@bthfp@[57840,49413,65535][5111,4915,4652]
 @OBEX@btobex@[15856,45391,43152][5111,4915,4652]
 @RFCOMM@btrfcomm@[64249,44202,25136][5111,4915,4652]
index b12290fdf484ec72c450056d35ffebbedab337cf..7ca83d5e4a1226e17dcab1d6bae92ef2d996233a 100644 (file)
@@ -392,6 +392,7 @@ set(DISSECTOR_SRC
        dissectors/packet-bt-utp.c
        dissectors/packet-btamp.c
        dissectors/packet-btbnep.c
+       dissectors/packet-btavctp.c
        dissectors/packet-bthci_acl.c
        dissectors/packet-bthci_cmd.c
        dissectors/packet-bthci_evt.c
index 97950ded776a7d34c42116bd1c5e85987e6352ef..1a3beda39a185fd789269cf16cf0585d2eb15b10 100644 (file)
@@ -312,6 +312,7 @@ DISSECTOR_SRC = \
        packet-bt-utp.c         \
        packet-btamp.c          \
        packet-btbnep.c         \
+       packet-btavctp.c        \
        packet-bthci_acl.c      \
        packet-bthci_cmd.c      \
        packet-bthci_evt.c      \
@@ -1220,6 +1221,7 @@ DISSECTOR_INCLUDES =      \
        packet-bpq.h    \
        packet-bssap.h  \
        packet-bssgp.h  \
+       packet-btavctp.h        \
        packet-bthci_acl.h      \
        packet-btl2cap.h        \
        packet-btrfcomm.h       \
diff --git a/epan/dissectors/packet-btavctp.c b/epan/dissectors/packet-btavctp.c
new file mode 100644 (file)
index 0000000..1c2ee08
--- /dev/null
@@ -0,0 +1,366 @@
+/* packet-btavctp.c
+ * Routines for Bluetooth AVCTP dissection
+ *
+ * Copyright 2012, Michal Labedzki for Tieto Corporation
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
+
+#include "packet-btl2cap.h"
+#include "packet-btsdp.h"
+#include "packet-btavctp.h"
+
+#define PACKET_TYPE_SINGLE    0x00
+#define PACKET_TYPE_START     0x01
+#define PACKET_TYPE_CONTINUE  0x02
+#define PACKET_TYPE_END       0x03
+
+static int proto_btavctp                        = -1;
+
+static int hf_btavctp_transaction               = -1;
+static int hf_btavctp_packet_type               = -1;
+static int hf_btavctp_cr                        = -1;
+static int hf_btavctp_ipid                      = -1;
+static int hf_btavctp_rfa                       = -1;
+static int hf_btavctp_pid                       = -1;
+static int hf_btavctp_number_of_packets         = -1;
+
+static gint ett_btavctp             = -1;
+
+static dissector_handle_t btavrcp_handle = NULL;
+static dissector_handle_t data_handle    = NULL;
+
+typedef struct _fragment_t {
+    guint32 length;
+    guint8  *data;
+} fragment_t;
+
+typedef struct _fragments_t {
+    guint32      count;
+    guint32      number_of_packets;
+    guint32      pid;
+    emem_tree_t  *fragment;
+} fragments_t;
+
+static emem_tree_t *reassembling = NULL;
+static fragments_t *fragments    = NULL;
+
+static const value_string packet_type_vals[] = {
+    { PACKET_TYPE_SINGLE,   "Single" },
+    { PACKET_TYPE_START,    "Start" },
+    { PACKET_TYPE_CONTINUE, "Continue" },
+    { PACKET_TYPE_END,      "End" },
+    { 0, NULL }
+};
+
+static const value_string cr_vals[] = {
+    { 0x00,   "Command" },
+    { 0x01,   "Response" },
+    { 0, NULL }
+};
+
+static const value_string ipid_vals[] = {
+    { 0x00,   "Profile OK" },
+    { 0x01,   "Invalid profile" },
+    { 0, NULL }
+};
+
+
+static void
+dissect_btavctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_item      *ti;
+    proto_tree      *btavctp_tree;
+    proto_item      *pitem;
+    btavctp_data_t  *avctp_data;
+    btl2cap_data_t  *l2cap_data;
+    tvbuff_t        *next_tvb;
+    gint            offset = 0;
+    unsigned int    packet_type;
+    unsigned int    cr;
+    unsigned int    pid;
+    unsigned int    transaction;
+    unsigned int    number_of_packets;
+    unsigned int    i_frame;
+    fragment_t      *fragment;
+    void            *save_private_data;
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVCTP");
+    col_clear(pinfo->cinfo, COL_INFO);
+
+    l2cap_data = (btl2cap_data_t *) pinfo->private_data;
+
+    switch (pinfo->p2p_dir) {
+
+    case P2P_DIR_SENT:
+        col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
+        break;
+
+    case P2P_DIR_RECV:
+        col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
+        break;
+
+    case P2P_DIR_UNKNOWN:
+        col_clear(pinfo->cinfo, COL_INFO);
+        break;
+
+    default:
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
+            pinfo->p2p_dir);
+        break;
+    }
+
+    ti = proto_tree_add_item(tree, proto_btavctp, tvb, offset, -1, ENC_NA);
+
+    btavctp_tree = proto_item_add_subtree(ti, ett_btavctp);
+
+    proto_tree_add_item(btavctp_tree, hf_btavctp_transaction,  tvb, offset, 1, ENC_BIG_ENDIAN);
+    pitem = proto_tree_add_item(btavctp_tree, hf_btavctp_packet_type,  tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(btavctp_tree, hf_btavctp_cr,  tvb, offset, 1, ENC_BIG_ENDIAN);
+    transaction = tvb_get_guint8(tvb, offset) >> 4;
+    packet_type = (tvb_get_guint8(tvb, offset) & 0x0C) >> 2;
+    cr = (tvb_get_guint8(tvb, offset) & 0x02) >> 1 ;
+
+    if (packet_type == PACKET_TYPE_SINGLE || packet_type == PACKET_TYPE_START)
+        proto_tree_add_item(btavctp_tree, hf_btavctp_ipid,  tvb, offset, 1, ENC_BIG_ENDIAN);
+    else
+        proto_tree_add_item(btavctp_tree, hf_btavctp_rfa,  tvb, offset, 1, ENC_BIG_ENDIAN);
+    offset++;
+
+    if (packet_type == PACKET_TYPE_START) {
+        proto_tree_add_item(btavctp_tree, hf_btavctp_number_of_packets,  tvb, offset, 1, ENC_BIG_ENDIAN);
+        number_of_packets = tvb_get_guint8(tvb, offset);
+        offset++;
+    }
+
+    if (packet_type == PACKET_TYPE_SINGLE || packet_type == PACKET_TYPE_START) {
+        proto_tree_add_item(btavctp_tree, hf_btavctp_pid,  tvb, offset, 2, ENC_BIG_ENDIAN);
+        pid = tvb_get_ntohs(tvb, offset);
+        offset +=2;
+    }
+
+    avctp_data = ep_alloc(sizeof(btavctp_data_t));
+    avctp_data->cr = cr;
+    avctp_data->psm = l2cap_data->psm;
+
+    save_private_data = pinfo->private_data;
+    pinfo->private_data = avctp_data;
+
+    col_append_fstr(pinfo->cinfo, COL_INFO, "%s - Transaction: %u, PacketType: %s",
+            val_to_str_const(cr, cr_vals, "unknown CR"), transaction,
+            val_to_str_const(packet_type, packet_type_vals, "unknown packet type"));
+
+    /* reassembling */
+    next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset));
+    if (packet_type == PACKET_TYPE_SINGLE) {
+        if (pid == BTSDP_AVRCP_SERVICE_UUID && btavrcp_handle != NULL)
+            call_dissector(btavrcp_handle, next_tvb, pinfo, tree);
+        else
+            call_dissector(data_handle, next_tvb, pinfo, tree);
+    } else {
+        if (packet_type == PACKET_TYPE_START) {
+            if(!pinfo->fd->flags.visited){
+                fragment = se_alloc(sizeof(fragment_t));
+                fragment->length = tvb_length_remaining(tvb, offset);
+                fragment->data = se_alloc(fragment->length);
+                tvb_memcpy(tvb, fragment->data, offset, fragment->length);
+
+                fragments = se_alloc(sizeof(fragments_t));
+                fragments->number_of_packets = number_of_packets;
+                fragments->pid = pid;
+
+                fragments->count = 1;
+                fragments->fragment = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btavctp fragments");
+                se_tree_insert32(fragments->fragment, fragments->count, fragment);
+
+                se_tree_insert32(reassembling, pinfo->fd->num, fragments);
+
+            } else {
+                    fragments = se_tree_lookup32_le(reassembling, pinfo->fd->num);
+            }
+
+            call_dissector(data_handle, next_tvb, pinfo, tree);
+
+        } else if (packet_type == PACKET_TYPE_CONTINUE) {
+            if(!pinfo->fd->flags.visited) {
+                if (fragments != NULL) {
+                    fragment = se_alloc(sizeof(fragment_t));
+                    fragment->length = tvb_length_remaining(tvb, offset);
+                    fragment->data = se_alloc(fragment->length);
+                    tvb_memcpy(tvb, fragment->data, offset, fragment->length);
+
+                    fragments->count++;
+                    se_tree_insert32(fragments->fragment, fragments->count, fragment);
+
+                    se_tree_insert32(reassembling, pinfo->fd->num, fragments);
+                }
+            } else {
+                    fragments = se_tree_lookup32_le(reassembling, pinfo->fd->num);
+            }
+
+            call_dissector(data_handle, next_tvb, pinfo, tree);
+
+        } else if (packet_type == PACKET_TYPE_END) {
+            unsigned int length = 0;
+            unsigned int i_length = 0;
+            guint8       *reassembled;
+
+            if(!pinfo->fd->flags.visited){
+
+                if (fragments != NULL) {
+                    fragment = se_alloc(sizeof(fragment_t));
+                    fragment->length = tvb_length_remaining(tvb, offset);
+                    fragment->data = se_alloc(fragment->length);
+                    tvb_memcpy(tvb, fragment->data, offset, fragment->length);
+
+                    fragments->count++;
+                    se_tree_insert32(fragments->fragment, fragments->count, fragment);
+
+                    se_tree_insert32(reassembling, pinfo->fd->num, fragments);
+                }
+            } else {
+                fragments = se_tree_lookup32_le(reassembling, pinfo->fd->num);
+            }
+
+
+            if (!fragments || fragments->count != fragments->number_of_packets) {
+                expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN,
+                    "Unexpected frame");
+                call_dissector(data_handle, next_tvb, pinfo, tree);
+            } else {
+                for (i_frame = 1; i_frame <= fragments->count; ++i_frame) {
+                    fragment = se_tree_lookup32_le(fragments->fragment, i_frame);
+                    length += fragment->length;
+                }
+
+                reassembled = se_alloc(length);
+
+                for (i_frame = 1; i_frame <= fragments->count; ++i_frame) {
+                    fragment = se_tree_lookup32_le(fragments->fragment, i_frame);
+                    memcpy(reassembled + i_length,
+                            fragment->data,
+                            fragment->length);
+                    i_length += fragment->length;
+                }
+
+                next_tvb = tvb_new_child_real_data(tvb, reassembled, length, length);
+                add_new_data_source(pinfo, next_tvb, "Reassembled AVCTP");
+
+                if (fragments->pid == BTSDP_AVRCP_SERVICE_UUID && btavrcp_handle != NULL) {
+                    call_dissector(btavrcp_handle, next_tvb, pinfo, tree);
+                } else {
+                    call_dissector(data_handle, next_tvb, pinfo, tree);
+                }
+            }
+
+            fragments = NULL;
+        } else {
+                call_dissector(data_handle, next_tvb, pinfo, tree);
+        }
+    }
+
+    pinfo->private_data = save_private_data;
+}
+
+void
+proto_register_btavctp(void)
+{
+    module_t *module;
+
+    static hf_register_info hf[] = {
+        { &hf_btavctp_transaction,
+            { "Transaction",          "btavctp.transaction",
+            FT_UINT8, BASE_HEX, NULL, 0xF0,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_packet_type,
+            { "Packet Type",          "btavctp.packet_type",
+            FT_UINT8, BASE_HEX, VALS(packet_type_vals), 0x0C,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_cr,
+            { "C/R",                  "btavctp.cr",
+            FT_UINT8, BASE_HEX, VALS(cr_vals), 0x02,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_ipid,
+            { "IPID",                 "btavctp.ipid",
+            FT_UINT8, BASE_HEX, VALS(ipid_vals), 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_rfa,
+            { "RFA",                  "btavctp.rfa",
+            FT_UINT8, BASE_HEX, NULL, 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_pid,
+            { "Profile Identifier",   "btavctp.pid",
+            FT_UINT16, BASE_HEX|BASE_EXT_STRING, &vs_service_classes_ext, 0x00,
+            NULL, HFILL }
+        },
+        { &hf_btavctp_number_of_packets,
+            { "Number of packets",    "btavctp.nop",
+            FT_UINT8, BASE_DEC, NULL, 0x00,
+            NULL, HFILL }
+        }
+    };
+
+    static gint *ett[] = {
+        &ett_btavctp
+    };
+
+    reassembling = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btavctp reassembling");
+
+    proto_btavctp = proto_register_protocol("Bluetooth AVCTP Protocol", "AVCTP", "btavctp");
+    register_dissector("btavctp", dissect_btavctp, proto_btavctp);
+
+    proto_register_field_array(proto_btavctp, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    module = prefs_register_protocol(proto_btavctp, NULL);
+    prefs_register_static_text_preference(module, "avctp.version",
+            "Bluetooth Protocol AVCTP version: 1.4",
+            "Version of protocol supported by this dissector.");
+}
+
+
+void
+proto_reg_handoff_btavctp(void)
+{
+    dissector_handle_t btavctp_handle;
+
+    btavctp_handle = find_dissector("btavctp");
+    btavrcp_handle = find_dissector("btavrcp");
+    data_handle    = find_dissector("data");
+
+    dissector_add_uint("btl2cap.service", BTSDP_AVCTP_PROTOCOL_UUID, btavctp_handle);
+
+    dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_AVCTP_CTRL, btavctp_handle);
+    dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_AVCTP_BRWS, btavctp_handle);
+
+    dissector_add_handle("btl2cap.cid", btavctp_handle);
+}
diff --git a/epan/dissectors/packet-btavctp.h b/epan/dissectors/packet-btavctp.h
new file mode 100644 (file)
index 0000000..bcf8b03
--- /dev/null
@@ -0,0 +1,35 @@
+/* packet-btavctp.h
+ * Headers for AVCTP
+ *
+ * Copyright 2012, Michal Labedzki for Tieto Corporation
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PACKET_BTAVCTP_H__
+#define __PACKET_BTAVCTP_H__
+
+typedef struct _btavctp_data_t {
+    guint8          cr;
+    guint16         psm;
+} btavctp_data_t;
+
+#endif