aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2014-02-02 19:12:55 +0100
committerMichal Labedzki <michal.labedzki@tieto.com>2014-10-22 11:25:06 +0000
commitc2f58d396212f59e1c0c572319d74107f82c4a8c (patch)
tree2cab5ab35b6dd2cecc42a2ccec9f0e1acafd4046
parent0ce3640cab2b911a6a46838df024bc52c1affb09 (diff)
Android: Add ADB dissector
Previoulsy added "adb_cs" is only for adb client <-> adb daemon communication by loopback interface (by TCP). But there is also communication between adb daemon and device (by TCP or USB). This transport protocol is different, but now support is done. ADB services are shared between ADB and ADB_CS so put them into "adb_service" dissector. There is still some services to be added. Change-Id: I754331d3dc6ccf3c17445f5563d01cf2fe1489c7 Reviewed-on: https://code.wireshark.org/review/4651 Tested-by: Michal Labedzki <michal.labedzki@tieto.com> Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
-rw-r--r--AUTHORS2
-rw-r--r--docbook/release-notes.asciidoc4
-rw-r--r--epan/CMakeLists.txt2
-rw-r--r--epan/dissectors/Makefile.common2
-rw-r--r--epan/dissectors/packet-adb.c924
-rw-r--r--epan/dissectors/packet-adb_cs.c684
-rw-r--r--epan/dissectors/packet-adb_service.c845
-rw-r--r--epan/dissectors/packet-adb_service.h49
8 files changed, 1888 insertions, 624 deletions
diff --git a/AUTHORS b/AUTHORS
index d175f49c3d..12d9bbaed6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3496,7 +3496,7 @@ Michał Łabędzki <michal.labedzki[AT]tieto.com> {
Bluetooth SDP significant improvements
Ubertooth USB firmware dissector
ELF file dissector
- Android ADB Client-Server dissector
+ Android ADB dissectors
Android Logcat binary logs support
}
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index f972ec16d2..f072b22d7c 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -68,6 +68,8 @@ Dynamic Source Routing (RFC 4728)
MCPE (Minecraft Pocket Edition)
RakNet games library
(LISP) TCP Control Message
+Android ADB
+Android Logcat text
--sort-and-group--
=== Updated Protocol Support
@@ -77,7 +79,7 @@ Too many protocols have been updated to list here.
=== New and Updated Capture File Support
--sort-and-group--
-Android logcat text files
+Android Logcat text files
Wireshark now supports nanosecond timestamp resolution in PCAP-NG files.
--sort-and-group--
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 59aa102939..e845a7e258 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -316,7 +316,9 @@ set(DISSECTOR_SRC
dissectors/packet-acn.c
dissectors/packet-acr122.c
dissectors/packet-actrace.c
+ dissectors/packet-adb.c
dissectors/packet-adb_cs.c
+ dissectors/packet-adb_service.c
dissectors/packet-adwin-config.c
dissectors/packet-adwin.c
dissectors/packet-afp.c
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 3735f22eff..58d6e2996d 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -236,7 +236,9 @@ DISSECTOR_SRC = \
packet-acn.c \
packet-acr122.c \
packet-actrace.c \
+ packet-adb.c \
packet-adb_cs.c \
+ packet-adb_service.c \
packet-adwin-config.c \
packet-adwin.c \
packet-afp.c \
diff --git a/epan/dissectors/packet-adb.c b/epan/dissectors/packet-adb.c
new file mode 100644
index 0000000000..51df9acee4
--- /dev/null
+++ b/epan/dissectors/packet-adb.c
@@ -0,0 +1,924 @@
+/* packet-adb.c
+ * Routines for Android Debug Bridge Transport Protocol
+ *
+ * Copyright 2014 Michal Labedzki for Tieto Corporation
+ *
+ * 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 thehf_class
+ * 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 <epan/wmem/wmem.h>
+#include <wiretap/wtap.h>
+
+#include "packet-adb_service.h"
+#include "packet-usb.h"
+
+static int proto_adb = -1;
+static int hf_command = -1;
+static int hf_argument_0 = -1;
+static int hf_argument_1 = -1;
+static int hf_data_length = -1;
+static int hf_data_crc32 = -1;
+static int hf_magic = -1;
+static int hf_local_id = -1;
+static int hf_remote_id = -1;
+static int hf_version = -1;
+static int hf_max_data = -1;
+static int hf_zero = -1;
+static int hf_sequence = -1;
+static int hf_online = -1;
+static int hf_auth_type = -1;
+static int hf_data = -1;
+static int hf_service = -1;
+static int hf_data_fragment = -1;
+static int hf_command_in_frame = -1;
+static int hf_completed_in_frame = -1;
+static int hf_service_start_in_frame = -1;
+static int hf_close_local_in_frame = -1;
+static int hf_close_remote_in_frame = -1;
+static int hf_connection_info = -1;
+
+static gint ett_adb = -1;
+static gint ett_adb_arg0 = -1;
+static gint ett_adb_arg1 = -1;
+static gint ett_adb_crc = -1;
+static gint ett_adb_magic = -1;
+
+static expert_field ei_invalid_magic = EI_INIT;
+static expert_field ei_invalid_crc = EI_INIT;
+
+static dissector_handle_t adb_handle;
+static dissector_handle_t adb_service_handle;
+
+static gint proto_tcp = -1;
+static gint proto_usb = -1;
+
+static wmem_tree_t *command_info = NULL;
+static wmem_tree_t *service_info = NULL;
+
+typedef struct service_data_t {
+ guint32 start_in_frame;
+
+ guint32 close_local_in_frame;
+ guint32 close_remote_in_frame;
+
+ guint32 local_id;
+ guint32 remote_id;
+
+ const guint8 *service;
+} service_data_t;
+
+typedef struct command_data_t {
+ guint32 command;
+
+ guint32 command_in_frame;
+ guint32 response_in_frame;
+
+ guint32 arg0;
+ guint32 arg1;
+
+ guint32 data_length;
+ guint32 crc32;
+
+ guint32 completed_in_frame;
+ guint32 reassemble_data_length;
+ guint8 *reassemble_data;
+} command_data_t;
+
+static guint32 max_in_frame = G_MAXUINT32;
+
+static const value_string command_vals[] = {
+ { 0x434e5953, "Synchronize" },
+ { 0x45534c43, "Close" },
+ { 0x45545257, "Write" },
+ { 0x48545541, "Authenticate" },
+ { 0x4e584e43, "Connect" },
+ { 0x4e45504f, "Open" },
+ { 0x59414b4f, "Okay" },
+ { 0, NULL }
+};
+
+static const value_string magic_vals[] = {
+ { 0xFFFFFFFF ^ 0x434e5953, "Synchronize" },
+ { 0xFFFFFFFF ^ 0x45534c43, "Close" },
+ { 0xFFFFFFFF ^ 0x45545257, "Write" },
+ { 0xFFFFFFFF ^ 0x48545541, "Authenticate" },
+ { 0xFFFFFFFF ^ 0x4e584e43, "Connect" },
+ { 0xFFFFFFFF ^ 0x4e45504f, "Open" },
+ { 0xFFFFFFFF ^ 0x59414b4f, "Okay" },
+ { 0, NULL }
+};
+
+static const value_string auth_type_vals[] = {
+ { 1, "Token" },
+ { 2, "Signature" },
+ { 3, "RSA Public Key" },
+ { 0, NULL }
+};
+
+#define A_SYNC 0x434e5953
+#define A_CLSE 0x45534c43
+#define A_WRTE 0x45545257
+#define A_AUTH 0x48545541
+#define A_CNXN 0x4e584e43
+#define A_OPEN 0x4e45504f
+#define A_OKAY 0x59414b4f
+
+#define ADB_TCP_PORT 5555
+
+void proto_register_adb(void);
+void proto_reg_handoff_adb(void);
+
+static void
+save_command(guint32 cmd, guint32 arg0, guint32 arg1, guint32 data_length,
+ guint32 crc32, service_data_t *service_data, gint proto, void *data,
+ packet_info *pinfo, service_data_t **returned_service_data,
+ command_data_t **returned_command_data)
+{
+ wmem_tree_key_t key[6];
+ guint32 interface_id;
+ guint32 bus_id;
+ guint32 device_address;
+ guint32 side_id;
+ guint32 frame_number;
+ command_data_t *command_data;
+ wmem_tree_t *wmem_tree;
+ gint direction = P2P_DIR_UNKNOWN;
+ usb_conv_info_t *usb_conv_info = (usb_conv_info_t *) data;
+
+ frame_number = pinfo->fd->num;
+
+ if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
+ interface_id = pinfo->phdr->interface_id;
+ else
+ interface_id = 0;
+
+ if (proto == proto_usb) {
+ usb_conv_info = (usb_conv_info_t *) data;
+ DISSECTOR_ASSERT(usb_conv_info);
+
+ direction = usb_conv_info->direction;
+
+ bus_id = usb_conv_info->bus_id;
+ device_address = usb_conv_info->device_address;
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &bus_id;
+ key[2].length = 1;
+ key[2].key = &device_address;
+ key[3].length = 1;
+ key[3].key = &side_id;
+ key[4].length = 1;
+ key[4].key = &frame_number;
+ key[5].length = 0;
+ key[5].key = NULL;
+ } else { /* tcp */
+ if (pinfo->destport == ADB_TCP_PORT)
+ direction = P2P_DIR_SENT;
+ else
+ direction = P2P_DIR_RECV;
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[2].length = 1;
+ if (direction == P2P_DIR_SENT) {
+ key[1].key = &pinfo->srcport;
+ key[2].key = &pinfo->destport;
+ } else {
+ key[1].key = &pinfo->destport;
+ key[2].key = &pinfo->srcport;
+ }
+ key[3].length = 1;
+ key[3].key = &side_id;
+ key[4].length = 1;
+ key[4].key = &frame_number;
+ key[5].length = 0;
+ key[5].key = NULL;
+ }
+
+ if (direction == P2P_DIR_SENT)
+ if (cmd == A_CLSE)
+ side_id = arg1; /* OUT: local id */
+ else
+ side_id = arg0; /* OUT: local id */
+ else
+ side_id = arg1; /* IN: remote id */
+
+ if (cmd == A_OPEN) {
+ service_data = wmem_new(wmem_file_scope(), service_data_t);
+
+ service_data->start_in_frame = pinfo->fd->num;
+ service_data->close_local_in_frame = max_in_frame;
+ service_data->close_remote_in_frame = max_in_frame;
+
+ service_data->local_id = arg0;
+ service_data->remote_id = arg1;
+
+ service_data->service = "unknown";
+
+ wmem_tree_insert32_array(service_info, key, service_data);
+ }
+
+ command_data = wmem_new(wmem_file_scope(), command_data_t);
+
+ command_data->command = cmd;
+ command_data->arg0 = arg0;
+ command_data->arg1 = arg1;
+
+ command_data->command_in_frame = pinfo->fd->num;
+ command_data->response_in_frame = max_in_frame;
+
+ command_data->crc32 = crc32;
+ command_data->data_length = data_length;
+ if (data_length == 0)
+ command_data->completed_in_frame = pinfo->fd->num;
+ else
+ command_data->completed_in_frame = max_in_frame;
+ command_data->reassemble_data_length = 0;
+ command_data->reassemble_data = (guint8 *) wmem_alloc(wmem_file_scope(), command_data->data_length);
+
+ key[3].length = 1;
+ key[3].key = &frame_number;
+ key[4].length = 0;
+ key[4].key = NULL;
+ wmem_tree_insert32_array(command_info, key, command_data);
+
+ if (direction == P2P_DIR_SENT)
+ if (command_data->command == A_CLSE)
+ side_id = command_data->arg1; /* OUT: local id */
+ else
+ side_id = command_data->arg0; /* OUT: local id */
+ else
+ side_id = command_data->arg1; /* IN: remote id */
+
+ key[3].length = 1;
+ key[3].key = &side_id;
+ key[4].length = 0;
+ key[4].key = NULL;
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
+ if (wmem_tree) {
+ service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
+ }
+
+ if (cmd == A_OKAY) {
+ if (!service_data) {
+ if (direction == P2P_DIR_SENT)
+ side_id = command_data->arg0; /* OUT: local id */
+ else
+ side_id = command_data->arg1; /* IN: remote id */
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
+ if (wmem_tree) {
+ service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
+ }
+ }
+
+ if (service_data && service_data->remote_id == 0 && direction == P2P_DIR_RECV) {
+ if (direction == P2P_DIR_SENT) {
+ service_data->remote_id = arg1;
+ } else {
+ service_data->remote_id = arg0;
+ }
+
+ side_id = service_data->remote_id;
+
+ key[4].length = 1;
+ key[4].key = &frame_number;
+ key[5].length = 0;
+ key[5].key = NULL;
+
+ wmem_tree_insert32_array(service_info, key, service_data);
+ }
+ } else if (cmd == A_CLSE) {
+ if (service_data) {
+ if (direction == P2P_DIR_RECV && service_data->local_id == arg1)
+ service_data->close_local_in_frame = pinfo->fd->num;
+ else if (direction == P2P_DIR_SENT && service_data->remote_id == arg1)
+ service_data->close_remote_in_frame = pinfo->fd->num;
+ }
+ }
+
+ DISSECTOR_ASSERT(returned_service_data && returned_command_data);
+ *returned_service_data = service_data;
+ *returned_command_data = command_data;
+}
+
+static gint
+dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ proto_item *main_item;
+ proto_tree *main_tree;
+ proto_item *arg0_item;
+ proto_tree *arg0_tree;
+ proto_item *arg1_item;
+ proto_tree *arg1_tree;
+ proto_item *magic_item;
+ proto_item *crc_item;
+ proto_tree *crc_tree = NULL;
+ proto_item *sub_item;
+ gint offset = 0;
+ guint32 command;
+ guint32 arg0;
+ guint32 arg1;
+ guint32 data_length = 0;
+ guint32 crc32 = 0;
+ usb_conv_info_t *usb_conv_info = NULL;
+ wmem_tree_key_t key[5];
+ guint32 interface_id;
+ guint32 bus_id;
+ guint32 device_address;
+ guint32 side_id;
+ guint32 frame_number;
+ gboolean is_command = TRUE;
+ gboolean is_next_fragment = FALSE;
+ gboolean is_service = FALSE;
+ gint proto;
+ gint direction = P2P_DIR_UNKNOWN;
+ wmem_tree_t *wmem_tree;
+ command_data_t *command_data = NULL;
+ service_data_t *service_data = NULL;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA);
+ main_tree = proto_item_add_subtree(main_item, ett_adb);
+
+ frame_number = pinfo->fd->num;
+
+ /* XXX: Why? If interface is USB only first try is correct
+ * (and seems strange...), in other cases standard check for
+ * previous protocol is correct */
+ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers))));
+ if (proto != proto_usb) {
+ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))));
+ }
+
+ if (proto == proto_usb) {
+ usb_conv_info = (usb_conv_info_t *) data;
+ DISSECTOR_ASSERT(usb_conv_info);
+
+ direction = usb_conv_info->direction;
+ } else if (proto == proto_tcp) {
+ if (pinfo->destport == ADB_TCP_PORT)
+ direction = P2P_DIR_SENT;
+ else
+ direction = P2P_DIR_RECV;
+ } else {
+ return offset;
+ }
+
+ if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
+ interface_id = pinfo->phdr->interface_id;
+ else
+ interface_id = 0;
+
+ if (proto == proto_usb) {
+ bus_id = usb_conv_info->bus_id;
+ device_address = usb_conv_info->device_address;
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &bus_id;
+ key[2].length = 1;
+ key[2].key = &device_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+ } else { /* tcp */
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[2].length = 1;
+ if (direction == P2P_DIR_SENT) {
+ key[1].key = &pinfo->srcport;
+ key[2].key = &pinfo->destport;
+ } else {
+ key[1].key = &pinfo->destport;
+ key[2].key = &pinfo->srcport;
+ }
+ key[3].length = 0;
+ key[3].key = NULL;
+ }
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key);
+ if (wmem_tree) {
+ command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
+ if (command_data && command_data->completed_in_frame >= frame_number &&
+ command_data->command_in_frame <= frame_number) {
+
+ if (command_data->command_in_frame != frame_number) {
+ is_command = FALSE;
+ is_next_fragment = TRUE;
+ }
+
+ data_length = command_data->data_length;
+ crc32 = command_data->crc32;
+
+ if (direction == P2P_DIR_SENT)
+ if (command_data->command == A_CLSE)
+ side_id = command_data->arg1; /* OUT: local id */
+ else
+ side_id = command_data->arg0; /* OUT: local id */
+ else
+ if (command_data->command == A_OKAY) {
+ side_id = command_data->arg1; /* IN: remote id */
+ } else
+ side_id = command_data->arg1; /* IN: remote id */
+
+ key[3].length = 1;
+ key[3].key = &side_id;
+ key[4].length = 0;
+ key[4].key = NULL;
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
+ if (wmem_tree) {
+ service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
+ if (service_data && command_data->command == A_OPEN) {
+ is_service = TRUE;
+ }
+ }
+ }
+ }
+
+/* Simple heuristics to check if packet is command or data */
+ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) {
+ if (tvb_reported_length(tvb) < 24) {
+ is_command = FALSE;
+ } else if (tvb_reported_length(tvb) >= 24) {
+ command = tvb_get_letohl(tvb, offset);
+
+ if (command != A_SYNC && command != A_CLSE && command != A_WRTE &&
+ command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY)
+ is_command = FALSE;
+ else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20)))
+ is_command = FALSE;
+
+ if (is_command) {
+ data_length = tvb_get_letohl(tvb, offset + 12);
+ crc32 = tvb_get_letohl(tvb, offset + 16);
+ }
+ if (command == A_OPEN) is_service = TRUE;
+ }
+ }
+
+ if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) {
+ sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+ }
+
+ if (service_data) {
+ sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+
+ if (service_data->close_local_in_frame < max_in_frame) {
+ sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+ }
+
+ if (service_data->close_remote_in_frame < max_in_frame) {
+ sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+ }
+ }
+
+ if (is_command) {
+ proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ command = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command"));
+
+ arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0);
+ arg0 = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1);
+ arg1 = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ switch (command) {
+ case A_CNXN:
+ proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4));
+ break;
+ case A_AUTH:
+ proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown"));
+ break;
+ case A_OPEN:
+ proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8));
+ break;
+ case A_WRTE:
+ proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4));
+ break;
+ case A_CLSE:
+ case A_OKAY:
+ proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4));
+ break;
+ case A_SYNC:
+ proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4));
+ break;
+ }
+
+ proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ if (data_length > 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length);
+
+ crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
+ crc32 = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) {
+ proto_tree *expert_tree;
+
+ expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic);
+ proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4);
+ }
+
+ if (!pinfo->fd->flags.visited)
+ save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data);
+ offset += 4;
+ }
+
+ if (!pinfo->fd->flags.visited && command_data) {
+ if (command_data->command_in_frame != frame_number) {
+ is_command = FALSE;
+ is_next_fragment = TRUE;
+ }
+
+ data_length = command_data->data_length;
+ crc32 = command_data->crc32;
+
+ if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) ||
+ (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24)
+ ) {
+ command_data->reassemble_data_length = command_data->data_length;
+ command_data->completed_in_frame = frame_number;
+ }
+ }
+
+ if (is_next_fragment && command_data) {
+ sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+
+ sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+
+ sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+
+ crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32);
+ crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
+ PROTO_ITEM_SET_GENERATED(crc_item);
+ }
+
+ if (command_data && command_data->completed_in_frame != frame_number) {
+ sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+ }
+
+
+ if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) {
+ guint32 crc = 0;
+ guint32 i_offset;
+
+ if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */
+ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) {
+ tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset));
+ command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset);
+
+ if (command_data->reassemble_data_length >= command_data->data_length)
+ command_data->completed_in_frame = frame_number;
+ }
+
+ proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA);
+ col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment");
+ offset = tvb_captured_length(tvb);
+
+ if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) {
+ tvbuff_t *next_tvb;
+ adb_service_data_t adb_service_data;
+
+ next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length);
+ add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data");
+
+ adb_service_data.service = service_data->service;
+ adb_service_data.direction = direction;
+
+ adb_service_data.session_key_length = 3;
+ adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
+ adb_service_data.session_key[0] = interface_id;
+
+ if (proto == proto_usb) {
+ adb_service_data.session_key[1] = usb_conv_info->bus_id;
+ adb_service_data.session_key[2] = usb_conv_info->device_address;
+ } else { /* tcp */
+ if (direction == P2P_DIR_SENT) {
+ adb_service_data.session_key[1] = pinfo->srcport;
+ adb_service_data.session_key[2] = pinfo->destport;
+ } else {
+ adb_service_data.session_key[1] = pinfo->destport;
+ adb_service_data.session_key[2] = pinfo->srcport;
+ }
+ }
+
+ call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
+ }
+ } else { /* full message */
+ for (i_offset = 0; i_offset < data_length; ++i_offset)
+ crc += tvb_get_guint8(tvb, offset + i_offset);
+
+ if (crc32 > 0 && crc32 != crc)
+ proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1);
+
+ if (is_service) {
+ proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA);
+ if (!pinfo->fd->flags.visited && service_data) {
+ service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII);
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII));
+ offset = tvb_captured_length(tvb);
+ } else if (command_data && command_data->command == A_CNXN) {
+ gchar *info;
+ gint len;
+
+ info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info);
+ proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA);
+ offset += len;
+ } else {
+ col_append_str(pinfo->cinfo, COL_INFO, "Data");
+
+ /* Decode service payload */
+ if (service_data) {
+ tvbuff_t *next_tvb;
+ adb_service_data_t adb_service_data;
+
+ adb_service_data.service = service_data->service;
+ adb_service_data.direction = direction;
+
+ adb_service_data.session_key_length = 3;
+ adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
+ adb_service_data.session_key[0] = interface_id;
+
+ if (proto == proto_usb) {
+ adb_service_data.session_key[1] = usb_conv_info->bus_id;
+ adb_service_data.session_key[2] = usb_conv_info->device_address;
+ } else { /* tcp */
+ if (direction == P2P_DIR_SENT) {
+ adb_service_data.session_key[1] = pinfo->srcport;
+ adb_service_data.session_key[2] = pinfo->destport;
+ } else {
+ adb_service_data.session_key[1] = pinfo->destport;
+ adb_service_data.session_key[2] = pinfo->srcport;
+ }
+ }
+
+ next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
+ call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
+
+ } else {
+ proto_item *data_item;
+ gchar *data_str;
+
+ data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA);
+ data_str = tvb_format_text(tvb, offset, data_length);
+ proto_item_append_text(data_item, ": %s", data_str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str);
+ }
+
+ offset = tvb_captured_length(tvb);
+ }
+ }
+ }
+
+ return offset;
+}
+
+void
+proto_register_adb(void)
+{
+ module_t *module;
+ expert_module_t *expert_module;
+
+ static hf_register_info hf[] = {
+ { &hf_command,
+ { "Command", "adb.command",
+ FT_UINT32, BASE_HEX, VALS(command_vals), 0x00,
+ NULL, HFILL }
+ },
+ { &hf_argument_0,
+ { "Argument 0", "adb.argument.0",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_argument_1,
+ { "Argument 0", "adb.argument.1",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_data_length,
+ { "Data Length", "adb.data_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_data_crc32,
+ { "Data CRC32", "adb.data_crc32",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_magic,
+ { "Magic", "adb.magic",
+ FT_UINT32, BASE_HEX, VALS(magic_vals), 0x00,
+ NULL, HFILL }
+ },
+ { &hf_version,
+ { "Version", "adb.version",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_max_data,
+ { "Max Data", "adb.max_data",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_auth_type,
+ { "Type", "adb.auth_type",
+ FT_UINT32, BASE_HEX, VALS(auth_type_vals), 0x00,
+ NULL, HFILL }
+ },
+ { &hf_online,
+ { "Online", "adb.online",
+ FT_BOOLEAN, 32, TFS(&tfs_no_yes), 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sequence,
+ { "Sequence", "adb.sequence",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_zero,
+ { "Zero", "adb.zero",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_local_id,
+ { "Local ID", "adb.local_id",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_remote_id,
+ { "Remote ID", "adb.remote_id",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_data,
+ { "Data", "adb.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_service,
+ { "Service", "adb.service",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_data_fragment,
+ { "Data Fragment", "adb.data_fragment",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_service_start_in_frame,
+ { "Service Start in Frame", "adb.service_start_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_close_local_in_frame,
+ { "Local Service Close in Frame", "adb.close_local_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_close_remote_in_frame,
+ { "Remote Service Close in Frame", "adb.close_remote_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_command_in_frame,
+ { "Command in Frame", "adb.command_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_completed_in_frame,
+ { "Completed in Frame", "adb.completed_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_connection_info,
+ { "Info", "adb.connection_info",
+ FT_STRINGZ, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_adb,
+ &ett_adb_arg0,
+ &ett_adb_arg1,
+ &ett_adb_crc,
+ &ett_adb_magic
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_invalid_magic, { "adb.expert.invalid_magic", PI_PROTOCOL, PI_WARN, "Invalid Magic", EXPFILL }},
+ { &ei_invalid_crc, { "adb.expert.crc_error", PI_PROTOCOL, PI_ERROR, "CRC32 Error", EXPFILL }},
+ };
+
+ command_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+ service_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+
+ proto_adb = proto_register_protocol("Android Debug Bridge", "ADB", "adb");
+ adb_handle = new_register_dissector("adb", dissect_adb, proto_adb);
+
+ proto_register_field_array(proto_adb, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_module = expert_register_protocol(proto_adb);
+ expert_register_field_array(expert_module, ei, array_length(ei));
+
+ module = prefs_register_protocol(proto_adb, NULL);
+ prefs_register_static_text_preference(module, "version",
+ "ADB protocol version is compatibile pior to: adb 1.0.31",
+ "Version of protocol supported by this dissector.");
+}
+
+void
+proto_reg_handoff_adb(void)
+{
+ adb_service_handle = find_dissector("adb_service");
+
+ dissector_add_handle("tcp.port", adb_handle);
+ dissector_add_handle("usb.device", adb_handle);
+ dissector_add_handle("usb.product", adb_handle);
+ dissector_add_handle("usb.protocol", adb_handle);
+
+ proto_tcp = proto_get_id_by_filter_name("tcp");
+ proto_usb = proto_get_id_by_filter_name("usb");
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/epan/dissectors/packet-adb_cs.c b/epan/dissectors/packet-adb_cs.c
index 27cb11f492..10c824e62e 100644
--- a/epan/dissectors/packet-adb_cs.c
+++ b/epan/dissectors/packet-adb_cs.c
@@ -30,97 +30,42 @@
#include <epan/wmem/wmem.h>
#include <wiretap/wtap.h>
+#include "packet-adb_service.h"
+
static int proto_adb_cs = -1;
static int hf_role = -1;
static int hf_hex_ascii_length = -1;
static int hf_length = -1;
-static int hf_hex_ascii_version = -1;
-static int hf_version = -1;
static int hf_service = -1;
static int hf_status = -1;
-static int hf_fragment = -1;
static int hf_data = -1;
static int hf_fail_reason = -1;
-static int hf_framebuffer_version = -1;
-static int hf_framebuffer_depth = -1;
-static int hf_framebuffer_size = -1;
-static int hf_framebuffer_width = -1;
-static int hf_framebuffer_height = -1;
-static int hf_framebuffer_red_offset = -1;
-static int hf_framebuffer_red_length = -1;
-static int hf_framebuffer_blue_offset = -1;
-static int hf_framebuffer_blue_length = -1;
-static int hf_framebuffer_green_offset = -1;
-static int hf_framebuffer_green_length = -1;
-static int hf_framebuffer_alpha_offset = -1;
-static int hf_framebuffer_alpha_length = -1;
-static int hf_framebuffer_pixel = -1;
-static int hf_framebuffer_red_5 = -1;
-static int hf_framebuffer_green_6 = -1;
-static int hf_framebuffer_blue_5 = -1;
-static int hf_framebuffer_red = -1;
-static int hf_framebuffer_green = -1;
-static int hf_framebuffer_blue = -1;
-static int hf_framebuffer_alpha = -1;
-static int hf_framebuffer_unused = -1;
-static int hf_devices = -1;
-static int hf_stdin = -1;
-static int hf_stdout = -1;
-static int hf_pids = -1;
-static int hf_result = -1;
static gint ett_adb_cs = -1;
static gint ett_length = -1;
-static gint ett_version = -1;
-static gint ett_pixel = -1;
-static gint ett_data = -1;
static expert_field ei_incomplete_message = EI_INIT;
static dissector_handle_t adb_cs_handle;
-static dissector_handle_t logcat_handle;
+static dissector_handle_t adb_service_handle;
static dissector_handle_t data_handle;
static wmem_tree_t *client_requests = NULL;
-static wmem_tree_t *fragments = NULL;
static guint server_port = 5037;
-static gboolean pref_dissect_more_detail_framebuffer = FALSE;
-
-typedef struct _framebuffer_data_t {
- guint32 red_offset;
- guint32 red_length;
- guint32 green_offset;
- guint32 green_length;
- guint32 blue_offset;
- guint32 blue_length;
- guint32 alpha_offset;
- guint32 alpha_length;
-} framebuffer_data_t;
typedef struct _client_request_t {
- guint16 service_length;
+ gint64 service_length;
guint8 *service;
guint32 first_in;
gint64 service_in;
- gint64 data_in;
gint64 response_frame;
guint8 status;
- gint data_length;
- union {
- void *allocated;
- framebuffer_data_t *framebuffer_data;
- } data;
+ gint64 data_length;
} client_request_t;
-typedef struct _fragment_t {
- gint64 reassembled_in_frame;
- gint length;
- guint8 *data;
-} fragment_t;
-
static const value_string role_vals[] = {
{ 0x00, "Unknown" },
{ 0x01, "Server" },
@@ -137,40 +82,20 @@ static const value_string role_vals[] = {
void proto_register_adb_cs(void);
void proto_reg_handoff_adb_cs(void);
-
-static gint
-dissect_ascii_data_length(proto_tree *tree, tvbuff_t *tvb, gint offset, gint *data_length)
-{
- proto_item *sub_item;
- proto_tree *sub_tree;
- guint8 hex_ascii[5];
-
- DISSECTOR_ASSERT(data_length);
-
- tvb_memcpy(tvb, hex_ascii, offset, 4);
- hex_ascii[4]='\0';
-
- sub_item = proto_tree_add_item(tree, hf_hex_ascii_length, tvb, offset, 4, ENC_NA | ENC_ASCII);
- sub_tree = proto_item_add_subtree(sub_item, ett_length);
- *data_length = (gint)g_ascii_strtoull(hex_ascii, NULL, 16);
- proto_tree_add_uint(sub_tree, hf_length, tvb, offset, 4, *data_length);
- offset += 4;
-
- return offset;
-}
-
static gint
dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *main_item;
proto_tree *main_tree;
proto_item *sub_item;
- proto_tree *sub_tree;
proto_item *p_item;
gint offset = 0;
- gint length = -1;
- guint8 *hex_ascii;
+ gint64 length = -1;
+ gint direction;
gboolean client_request_service = FALSE;
+ tvbuff_t *next_tvb;
+ adb_service_data_t adb_service_data;
+ guint32 wireshark_interface_id = 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB CS");
col_clear(pinfo->cinfo, COL_INFO);
@@ -178,13 +103,17 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
main_item = proto_tree_add_item(tree, proto_adb_cs, tvb, offset, -1, ENC_NA);
main_tree = proto_item_add_subtree(main_item, ett_adb_cs);
+ if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
+ wireshark_interface_id = pinfo->phdr->interface_id;
+
if (pinfo->destport == server_port) { /* Client sent to Server */
client_request_t *client_request;
guint8 *service = SERVICE_NONE;
- guint32 wireshark_interface_id = 0;
wmem_tree_t *subtree;
wmem_tree_key_t key[5];
+ direction = P2P_DIR_SENT;
+
p_item = proto_tree_add_uint(main_tree, hf_role, tvb, offset, 0, 0x02);
PROTO_ITEM_SET_GENERATED(p_item);
@@ -218,6 +147,7 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
/* heuristic to recognize type of (partial) packet */
if (tvb_reported_length_remaining(tvb, offset) >= 4) {
guint8 hex_ascii_length[5];
+ guint32 ulength;
hex_ascii_length[4] = 0;
@@ -227,19 +157,29 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
g_ascii_xdigit_value(hex_ascii_length[2]) >= 0 &&
g_ascii_xdigit_value(hex_ascii_length[3]) >= 0) {
/* probably 4 bytes ascii hex length field */
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &length);
- col_append_fstr(pinfo->cinfo, COL_INFO, " Length=%u", length);
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &ulength);
+ length = (gint64) ulength;
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Length=%u", ulength);
}
}
+
if (length == -1 && service) {
col_append_fstr(pinfo->cinfo, COL_INFO, " Service=<%s>", service);
+ length = tvb_captured_length(tvb);
- if (g_str_has_prefix(service, "shell:")) {
- proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII);
- } else {
- proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
- }
+ /* Decode services */
+ adb_service_data.service = service;
+ adb_service_data.direction = direction;
+
+ adb_service_data.session_key_length = 3;
+ adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
+ adb_service_data.session_key[0] = wireshark_interface_id;
+ adb_service_data.session_key[1] = pinfo->destport;
+ adb_service_data.session_key[2] = pinfo->srcport;
+
+ next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
+ call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
return tvb_captured_length(tvb);
}
@@ -266,8 +206,6 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
client_request->response_frame = -1;
client_request->first_in = pinfo->fd->num;
client_request->service_in = -1;
- client_request->data_in = -1;
- client_request->data.allocated = NULL;
client_request->data_length = -1;
wmem_tree_insert32_array(client_requests, key, client_request);
}
@@ -291,8 +229,8 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
}
if (client_request) {
- client_request->service = (guint8 *) wmem_alloc(wmem_file_scope(), client_request->service_length + 1);
- tvb_memcpy(tvb, client_request->service, offset, client_request->service_length);
+ client_request->service = (guint8 *) wmem_alloc(wmem_file_scope(), (const size_t)(client_request->service_length + 1));
+ tvb_memcpy(tvb, client_request->service, offset, (size_t) client_request->service_length);
client_request->service[client_request->service_length] = '\0';
client_request->service_in = pinfo->fd->num;
}
@@ -313,17 +251,14 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
offset = tvb_captured_length(tvb);
} else if (pinfo->srcport == server_port) { /* Server sent to Client */
- guint32 wireshark_interface_id = 0;
- guint8 *service = SERVICE_NONE;
- wmem_tree_t *subtree;
- wmem_tree_key_t key[5];
- client_request_t *client_request;
- gint64 response_frame = -1;
- gint64 data_in = -1;
- guint8 status = STATUS_UNKNOWN;
+ guint8 *service = SERVICE_NONE;
+ wmem_tree_t *subtree;
+ wmem_tree_key_t key[5];
+ client_request_t *client_request;
+ gint64 response_frame = -1;
+ guint8 status = STATUS_UNKNOWN;
- if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
- wireshark_interface_id = pinfo->phdr->interface_id;
+ direction = P2P_DIR_RECV;
key[0].length = 1;
key[0].key = &wireshark_interface_id;
@@ -341,7 +276,6 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
status = client_request->status;
length = client_request->data_length;
response_frame = client_request->response_frame;
- data_in = client_request->data_in;
}
p_item = proto_tree_add_uint(main_tree, hf_role, tvb, offset, 0, 0x01);
@@ -366,7 +300,10 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
offset += 4;
if (tvb_memeql(tvb, offset - 4, "FAIL", 4) == 0) {
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &length);
+ guint32 ulength;
+
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &ulength);
+ length = (gint64) ulength;
status = STATUS_FAIL;
} else if (tvb_memeql(tvb, offset - 4, "OKAY", 4) == 0) {
@@ -385,11 +322,6 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
if (tvb_reported_length_remaining(tvb, offset) <= 0) return offset;
- if (!pinfo->fd->flags.visited && client_request && client_request->data_in == -1) {
- client_request->data_in = pinfo->fd->num;
- data_in = client_request->data_in;
- }
-
if (status == STATUS_FAIL) {
sub_item = proto_tree_add_item(main_tree, hf_fail_reason, tvb, offset, -1, ENC_NA | ENC_ASCII);
if (length < tvb_reported_length_remaining(tvb, offset)) {
@@ -400,353 +332,20 @@ dissect_adb_cs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
return tvb_captured_length(tvb);
}
- if (g_strcmp0(service, "host:version") == 0) {
- guint version;
- gint data_length;
-
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &data_length);
-
- hex_ascii = (guint8 *) wmem_alloc(wmem_packet_scope(), data_length + 1);
- tvb_memcpy(tvb, hex_ascii, offset, data_length);
- hex_ascii[data_length]='\0';
-
- sub_item = proto_tree_add_item(main_tree, hf_hex_ascii_version, tvb, offset, 4, ENC_NA | ENC_ASCII);
- sub_tree = proto_item_add_subtree(sub_item, ett_version);
- version = (guint)g_ascii_strtoull(hex_ascii, NULL, 16);
- proto_tree_add_uint(sub_tree, hf_version, tvb, offset, 4, version);
- offset += 4;
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version);
- } else if (g_strcmp0(service, "host:devices") == 0 ||
- g_strcmp0(service, "host:devices-l") == 0 ||
- g_strcmp0(service, "host:track-devices") == 0) {
- gint data_length;
-
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &data_length);
-
- sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII);
- if (data_length < tvb_reported_length_remaining(tvb, offset)) {
- expert_add_info(pinfo, sub_item, &ei_incomplete_message);
- }
- } else if (g_strcmp0(service, "host:get-state") == 0 ||
- g_strcmp0(service, "host:get-serialno") == 0 ||
- g_strcmp0(service, "host:get-devpath") == 0 ||
- g_str_has_prefix(service, "connect:") ||
- g_str_has_prefix(service, "disconnect:")) {
- gint data_length;
-
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &data_length);
-
- sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
- if (data_length < tvb_reported_length_remaining(tvb, offset)) {
- expert_add_info(pinfo, sub_item, &ei_incomplete_message);
- }
- } else if (g_str_has_prefix(service, "framebuffer:")) {
- if (data_in == pinfo->fd->num) {
- if (!pinfo->fd->flags.visited && client_request && client_request->data.allocated == NULL) {
- client_request->data.framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t);
- memset(client_request->data.framebuffer_data, 0, sizeof(framebuffer_data_t));
- }
-
- proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->red_offset = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->red_length = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->blue_offset = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->blue_length = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->green_offset = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->green_length = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset);
- offset += 4;
-
- proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (!pinfo->fd->flags.visited && client_request && client_request->data.framebuffer_data)
- client_request->data.framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset);
- offset += 4;
- }
-
- if (tvb_reported_length_remaining(tvb, offset) > 0) {
- proto_item *pixel_item;
- proto_tree *pixel_tree;
-
- sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_data);
-
- if (pref_dissect_more_detail_framebuffer) {
- if (client_request && client_request->data.framebuffer_data &&
- client_request->data.framebuffer_data->red_length == 5 &&
- client_request->data.framebuffer_data->green_length == 6 &&
- client_request->data.framebuffer_data->blue_length == 5 &&
- client_request->data.framebuffer_data->red_offset == 11 &&
- client_request->data.framebuffer_data->green_offset == 5 &&
- client_request->data.framebuffer_data->blue_offset == 0) {
- while (tvb_reported_length_remaining(tvb, offset) > 0) {
- if (tvb_reported_length_remaining(tvb, offset) < 2) {
- proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
- offset += 1;
- }
-
- pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA);
- pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);
-
- proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- }
- } else if (client_request && client_request->data.framebuffer_data &&
- client_request->data.framebuffer_data->red_length == 8 &&
- client_request->data.framebuffer_data->green_length == 8 &&
- client_request->data.framebuffer_data->blue_length == 8 &&
- (client_request->data.framebuffer_data->alpha_length == 0 ||
- client_request->data.framebuffer_data->alpha_length == 8)) {
- while (tvb_reported_length_remaining(tvb, offset) > 0) {
- if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && client_request->data.framebuffer_data->alpha_offset > 0)) {
- proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
- offset = tvb_captured_length(tvb);
- break;
- }
-
- pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA);
- pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);
-
- proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + client_request->data.framebuffer_data->red_offset / 8, 1, ENC_NA);
- proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + client_request->data.framebuffer_data->green_offset / 8, 1, ENC_NA);
- proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + client_request->data.framebuffer_data->blue_offset / 8, 1, ENC_NA);
-
- if (client_request->data.framebuffer_data->alpha_offset > 0) {
- if (client_request->data.framebuffer_data->alpha_length == 0)
- proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + client_request->data.framebuffer_data->alpha_offset / 8, 1, ENC_NA);
- else
- proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + client_request->data.framebuffer_data->alpha_offset / 8, 1, ENC_NA);
- offset += 1;
- proto_item_set_len(pixel_item, 4);
- }
- offset += 3;
- }
- } else {
- offset = tvb_captured_length(tvb);
- }
- } else {
- offset = tvb_captured_length(tvb);
- }
- }
- } else if (g_strcmp0(service, "track-jdwp") == 0) {
- gint data_length;
-
- offset = dissect_ascii_data_length(main_tree, tvb, offset, &data_length);
-
- if (tvb_reported_length_remaining(tvb, offset) > 0) {
- sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII);
- if (data_length < tvb_reported_length_remaining(tvb, offset)) {
- expert_add_info(pinfo, sub_item, &ei_incomplete_message);
- }
- }
- offset = tvb_captured_length(tvb);
- } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) ||
- (g_strcmp0(service, "shell:logcat -B") == 0)) {
- tvbuff_t *next_tvb;
- tvbuff_t *new_tvb;
- guint8 *buffer = NULL;
- gint size = 0;
- gint i_offset = offset;
- gint old_offset;
- gint i_char = 0;
- guint8 c1;
- guint8 c2 = '\0';
- guint16 payload_length;
- guint16 try_header_size;
- gint logcat_length = 0;
- fragment_t *fragment;
-
- if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
- wireshark_interface_id = pinfo->phdr->interface_id;
-
- key[0].length = 1;
- key[0].key = &wireshark_interface_id;
- key[1].length = 1;
- key[1].key = &pinfo->destport;
- key[2].length = 1;
- key[2].key = &pinfo->srcport;
- key[3].length = 0;
- key[3].key = NULL;
-
- subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key);
- fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->fd->num - 1) : NULL;
- if (fragment) {
- if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1)
- fragment->reassembled_in_frame = pinfo->fd->num;
-
- if (fragment->reassembled_in_frame == pinfo->fd->num) {
- size += fragment->length;
- i_char += fragment->length;
- }
- }
-
- size += tvb_reported_length_remaining(tvb, i_offset);
- if (size > 0) {
- buffer = (guint8 *) wmem_alloc(pinfo->pool, size);
- if (fragment && i_char > 0)
- memcpy(buffer, fragment->data, i_char);
-
- if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') {
- buffer[i_char - 1] = '\n';
- i_offset += 1;
- }
-
- c1 = tvb_get_guint8(tvb, i_offset);
- i_offset += 1;
- old_offset = i_offset;
-
- while (tvb_reported_length_remaining(tvb, i_offset) > 0) {
- c2 = tvb_get_guint8(tvb, i_offset);
-
- if (c1 == '\r' && c2 == '\n') {
- buffer[i_char] = c2;
- if (tvb_reported_length_remaining(tvb, i_offset) > 1) {
- c1 = tvb_get_guint8(tvb, i_offset + 1);
- i_offset += 2;
- i_char += 1;
- } else {
- i_offset += 1;
- }
-
- continue;
- }
-
- buffer[i_char] = c1;
- c1 = c2;
- i_char += 1;
- i_offset += 1;
- }
-
- if (tvb_reported_length_remaining(tvb, old_offset) == 0) {
- buffer[i_char] = c1;
- i_char += 1;
- } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) {
- buffer[i_char] = c2;
- i_char += 1;
- }
-
- next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char);
- add_new_data_source(pinfo, next_tvb, "Logcat");
-
- i_offset = 0;
- while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) {
- if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) {
- payload_length = tvb_get_letohs(next_tvb, i_offset);
- try_header_size = tvb_get_letohs(next_tvb, i_offset + 2);
-
- if (try_header_size == 0 || try_header_size != 24)
- logcat_length = payload_length + 20;
- else
- logcat_length = payload_length + 24;
- }
-
- if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) {
- new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length);
-
- call_dissector(logcat_handle, new_tvb, pinfo, main_tree);
- i_offset += logcat_length;
- } else {
-
- if (!pinfo->fd->flags.visited) {
- if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
- wireshark_interface_id = pinfo->phdr->interface_id;
-
- key[0].length = 1;
- key[0].key = &wireshark_interface_id;
- key[1].length = 1;
- key[1].key = &pinfo->destport;
- key[2].length = 1;
- key[2].key = &pinfo->srcport;
- key[3].length = 1;
- key[3].key = &pinfo->fd->num;
- key[4].length = 0;
- key[4].key = NULL;
-
- fragment = wmem_new(wmem_file_scope(), fragment_t);
-
- fragment->length = tvb_captured_length_remaining(next_tvb, i_offset);
- fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length);
- tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length);
- fragment->reassembled_in_frame = -1;
-
- wmem_tree_insert32_array(fragments, key, fragment);
- }
-
- proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA);
- i_offset = tvb_captured_length(next_tvb);
- }
- }
- }
+ /* Decode services */
+ adb_service_data.service = service;
+ adb_service_data.direction = direction;
- offset = tvb_captured_length(tvb);
- } else if (g_str_has_prefix(service, "shell:")) {
- proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII);
- offset = tvb_captured_length(tvb);
- } else if (g_str_has_prefix(service, "jdwp:")) {
- proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
- offset = tvb_captured_length(tvb);
- } else if (g_str_has_prefix(service, "sync:")) {
- proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
- offset = tvb_captured_length(tvb);
- } else if (g_strcmp0(service, "host:list-forward") == 0 ||
- g_str_has_prefix(service, "root:") ||
- g_str_has_prefix(service, "remount:") ||
- g_str_has_prefix(service, "tcpip:") ||
- g_str_has_prefix(service, "usb:")) {
- if (tvb_reported_length_remaining(tvb, offset)) {
- proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
- offset = tvb_captured_length(tvb);
- }
- } else {
- proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
- offset = tvb_captured_length(tvb);
- }
+ adb_service_data.session_key_length = 3;
+ adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
+ adb_service_data.session_key[0] = wireshark_interface_id;
+ adb_service_data.session_key[1] = pinfo->destport;
+ adb_service_data.session_key[2] = pinfo->srcport;
+ next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
+ call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
+ offset = tvb_captured_length(tvb);
} else {
- tvbuff_t *next_tvb;
-
col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown role");
p_item = proto_tree_add_uint(main_tree, hf_role, tvb, offset, 0, 0x00);
@@ -779,16 +378,6 @@ proto_register_adb_cs(void)
},
{ &hf_length,
{ "Length", "adb_cs.length",
- FT_UINT16, BASE_DEC_HEX, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_hex_ascii_version,
- { "Hex ASCII String Version", "adb_cs.hex_ascii_version",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_version,
- { "Version", "adb_cs.version",
FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
NULL, HFILL }
},
@@ -807,159 +396,16 @@ proto_register_adb_cs(void)
FT_STRING, STR_ASCII, NULL, 0x00,
NULL, HFILL }
},
- { &hf_fragment,
- { "Fragment", "adb_cs.fragment",
- FT_NONE, BASE_NONE, NULL, 0x00,
- NULL, HFILL }
- },
{ &hf_data,
{ "Data", "adb_cs.data",
FT_BYTES, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
- { &hf_framebuffer_version,
- { "Version", "adb_cs.framebuffer.version",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_depth,
- { "Depth", "adb_cs.framebuffer.depth",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_size,
- { "Size", "adb_cs.framebuffer.size",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_width,
- { "Width", "adb_cs.framebuffer.width",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_height,
- { "Height", "adb_cs.framebuffer.height",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_red_offset,
- { "Red Offset", "adb_cs.framebuffer.red_offset",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_red_length,
- { "Red Length", "adb_cs.framebuffer.red_length",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_blue_offset,
- { "Blue Offset", "adb_cs.framebuffer.blue_offset",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_blue_length,
- { "Blue Length", "adb_cs.framebuffer.blue_length",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_green_offset,
- { "Green Offset", "adb_cs.framebuffer.green_offset",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_green_length,
- { "Green Length", "adb_cs.framebuffer.green_length",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_alpha_offset,
- { "Alpha Offset", "adb_cs.framebuffer.alpha_offset",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_alpha_length,
- { "Alpha Length", "adb_cs.framebuffer.alpha_length",
- FT_UINT32, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_pixel,
- { "Pixel", "adb_cs.framebuffer.pixel",
- FT_NONE, BASE_NONE, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_blue_5,
- { "Blue", "adb_cs.framebuffer.pixel.blue",
- FT_UINT16, BASE_DEC, NULL, 0xF800,
- NULL, HFILL }
- },
- { &hf_framebuffer_green_6,
- { "Green", "adb_cs.framebuffer.pixel.green",
- FT_UINT16, BASE_DEC, NULL, 0x07E0,
- NULL, HFILL }
- },
- { &hf_framebuffer_red_5,
- { "Red", "adb_cs.framebuffer.pixel.red",
- FT_UINT16, BASE_DEC, NULL, 0x001F,
- NULL, HFILL }
- },
- { &hf_framebuffer_blue,
- { "Blue", "adb_cs.framebuffer.pixel.blue",
- FT_UINT8, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_green,
- { "Green", "adb_cs.framebuffer.pixel.green",
- FT_UINT8, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_red,
- { "Red", "adb_cs.framebuffer.pixel.red",
- FT_UINT8, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_alpha,
- { "Alpha", "adb_cs.framebuffer.pixel.alpha",
- FT_UINT8, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_framebuffer_unused,
- { "Unused", "adb_cs.framebuffer.pixel.unused",
- FT_UINT8, BASE_DEC, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_devices,
- { "Devices", "adb_cs.devices",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_stdin,
- { "Stdin", "adb_cs.stdin",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_stdout,
- { "Stdout", "adb_cs.stdout",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_result,
- { "Result", "adb_cs.result",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
- { &hf_pids,
- { "PIDs", "adb_cs.pids",
- FT_STRING, STR_ASCII, NULL, 0x00,
- NULL, HFILL }
- },
};
static gint *ett[] = {
&ett_adb_cs,
- &ett_length,
- &ett_version,
- &ett_pixel,
- &ett_data
+ &ett_length
};
static ei_register_info ei[] = {
@@ -967,7 +413,6 @@ proto_register_adb_cs(void)
};
client_requests = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
- fragments = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
proto_adb_cs = proto_register_protocol("Android Debug Bridge Client-Server", "ADB CS", "adb_cs");
adb_cs_handle = new_register_dissector("adb_cs", dissect_adb_cs, proto_adb_cs);
@@ -983,21 +428,16 @@ proto_register_adb_cs(void)
"Version of protocol supported by this dissector.");
prefs_register_uint_preference(module, "server_port",
- "Server Port",
- "Server Port",
- 10, &server_port);
-
- prefs_register_bool_preference(module, "framebuffer_more_details",
- "Dissect more detail for framebuffer service",
- "Dissect more detail for framebuffer service",
- &pref_dissect_more_detail_framebuffer);
+ "Server Port",
+ "Server Port",
+ 10, &server_port);
}
void
proto_reg_handoff_adb_cs(void)
{
- logcat_handle = find_dissector("logcat");
data_handle = find_dissector("data");
+ adb_service_handle = find_dissector("adb_service");
dissector_add_for_decode_as("tcp.port", adb_cs_handle);
}
diff --git a/epan/dissectors/packet-adb_service.c b/epan/dissectors/packet-adb_service.c
new file mode 100644
index 0000000000..e1afb16eb5
--- /dev/null
+++ b/epan/dissectors/packet-adb_service.c
@@ -0,0 +1,845 @@
+/* packet-adb_service.c
+ * Routines for Android Debug Bridge Services
+ *
+ * Copyright 2014 Michal Labedzki for Tieto Corporation
+ *
+ * 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 thehf_class
+ * 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 <epan/wmem/wmem.h>
+#include <wiretap/wtap.h>
+
+#include "packet-adb_service.h"
+
+static int proto_adb_service = -1;
+
+static int hf_service = -1;
+static int hf_fragment = -1;
+static int hf_data = -1;
+static int hf_hex_ascii_length = -1;
+static int hf_length = -1;
+static int hf_version = -1;
+static int hf_hex_ascii_version = -1;
+static int hf_framebuffer_version = -1;
+static int hf_framebuffer_depth = -1;
+static int hf_framebuffer_size = -1;
+static int hf_framebuffer_width = -1;
+static int hf_framebuffer_height = -1;
+static int hf_framebuffer_red_offset = -1;
+static int hf_framebuffer_red_length = -1;
+static int hf_framebuffer_blue_offset = -1;
+static int hf_framebuffer_blue_length = -1;
+static int hf_framebuffer_green_offset = -1;
+static int hf_framebuffer_green_length = -1;
+static int hf_framebuffer_alpha_offset = -1;
+static int hf_framebuffer_alpha_length = -1;
+static int hf_framebuffer_pixel = -1;
+static int hf_framebuffer_red_5 = -1;
+static int hf_framebuffer_green_6 = -1;
+static int hf_framebuffer_blue_5 = -1;
+static int hf_framebuffer_red = -1;
+static int hf_framebuffer_green = -1;
+static int hf_framebuffer_blue = -1;
+static int hf_framebuffer_alpha = -1;
+static int hf_framebuffer_unused = -1;
+static int hf_devices = -1;
+static int hf_stdin = -1;
+static int hf_stdout = -1;
+static int hf_pids = -1;
+static int hf_result = -1;
+static int hf_sync_id = -1;
+static int hf_sync_length = -1;
+static int hf_sync_mode = -1;
+static int hf_sync_size = -1;
+static int hf_sync_time = -1;
+static int hf_sync_unused = -1;
+static int hf_sync_data = -1;
+
+static expert_field ei_incomplete_message = EI_INIT;
+
+static gint ett_adb_service = -1;
+static gint ett_length = -1;
+static gint ett_version = -1;
+static gint ett_pixel = -1;
+static gint ett_data = -1;
+
+static dissector_handle_t adb_service_handle;
+static dissector_handle_t logcat_handle;
+
+static gboolean pref_dissect_more_detail_framebuffer = FALSE;
+
+static wmem_tree_t *fragments = NULL;
+static wmem_tree_t *framebuffer_infos = NULL;
+static wmem_tree_t *continuation_infos = NULL;
+
+typedef struct _framebuffer_data_t {
+ guint32 data_in;
+ guint32 current_size;
+ guint32 completed_in_frame;
+
+ guint32 size;
+ guint32 red_offset;
+ guint32 red_length;
+ guint32 green_offset;
+ guint32 green_length;
+ guint32 blue_offset;
+ guint32 blue_length;
+ guint32 alpha_offset;
+ guint32 alpha_length;
+} framebuffer_data_t;
+
+typedef struct _fragment_t {
+ gint64 reassembled_in_frame;
+ gint length;
+ guint8 *data;
+} fragment_t;
+
+typedef struct _continuation_data_t {
+ guint32 length_in_frame;
+ guint32 completed_in_frame;
+ gint length;
+} continuation_data_t;
+
+void proto_register_adb_service(void);
+void proto_reg_handoff_adb_service(void);
+
+gint
+dissect_ascii_uint32(proto_tree *tree, gint hf_hex_ascii, gint ett_hex_ascii,
+ gint hf_value, tvbuff_t *tvb, gint offset, guint32 *value)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ guint8 hex_ascii[5];
+
+ DISSECTOR_ASSERT(value);
+
+ tvb_memcpy(tvb, hex_ascii, offset, 4);
+ hex_ascii[4]='\0';
+
+ sub_item = proto_tree_add_item(tree, hf_hex_ascii, tvb, offset, 4, ENC_NA | ENC_ASCII);
+ sub_tree = proto_item_add_subtree(sub_item, ett_hex_ascii);
+
+ *value = (guint32) g_ascii_strtoull(hex_ascii, NULL, 16);
+
+ proto_tree_add_uint(sub_tree, hf_value, tvb, offset, 4, *value);
+ offset += 4;
+
+ return offset;
+}
+
+static gint
+dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ proto_item *main_item;
+ proto_tree *main_tree;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ gint offset = 0;
+ adb_service_data_t *adb_service_data = (adb_service_data_t *) data;
+ const guint8 *service;
+ wmem_tree_key_t key[5];
+ wmem_tree_t *subtree;
+ guint32 i_key;
+
+ main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA);
+ main_tree = proto_item_add_subtree(main_item, ett_adb_service);
+
+ DISSECTOR_ASSERT(adb_service_data);
+
+ service = adb_service_data->service;
+
+ sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service);
+ PROTO_ITEM_SET_GENERATED(sub_item);
+
+ if (g_strcmp0(service, "host:version") == 0) {
+ guint32 version;
+ guint32 data_length;
+ continuation_data_t *continuation_data;
+
+ DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
+ for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
+ key[i_key].length = 1;
+ key[i_key].key = &adb_service_data->session_key[i_key];
+ }
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key);
+ continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->fd->num) : NULL;
+ if (continuation_data && continuation_data->completed_in_frame < pinfo->fd->num)
+ continuation_data = NULL;
+
+ if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->fd->num))
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);
+
+ if (!pinfo->fd->flags.visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) {
+ key[i_key].length = 1;
+ key[i_key++].key = &pinfo->fd->num;
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ continuation_data = wmem_new(wmem_file_scope(), continuation_data_t);
+ continuation_data->length_in_frame = pinfo->fd->num;
+ continuation_data->completed_in_frame = G_MAXUINT32;
+ continuation_data->length = data_length;
+
+ wmem_tree_insert32_array(continuation_infos, key, continuation_data);
+ continuation_data = NULL;
+ }
+
+ if (tvb_reported_length_remaining(tvb, offset) >= 4 ||
+ (continuation_data && continuation_data->completed_in_frame == pinfo->fd->num)) {
+ if (!pinfo->fd->flags.visited && continuation_data) {
+ continuation_data->completed_in_frame = pinfo->fd->num;
+ }
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version);
+ }
+
+ } else if (g_strcmp0(service, "host:devices") == 0 ||
+ g_strcmp0(service, "host:devices-l") == 0 ||
+ g_strcmp0(service, "host:track-devices") == 0) {
+ guint32 data_length;
+
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);
+
+ sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
+ expert_add_info(pinfo, sub_item, &ei_incomplete_message);
+ }
+ } else if (g_strcmp0(service, "host:get-state") == 0 ||
+ g_strcmp0(service, "host:get-serialno") == 0 ||
+ g_strcmp0(service, "host:get-devpath") == 0 ||
+ g_str_has_prefix(service, "connect:") ||
+ g_str_has_prefix(service, "disconnect:")) {
+ guint32 data_length;
+
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);
+
+ sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
+ expert_add_info(pinfo, sub_item, &ei_incomplete_message);
+ }
+ } else if (g_str_has_prefix(service, "framebuffer:")) {
+ framebuffer_data_t *framebuffer_data = NULL;
+
+ DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
+ for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
+ key[i_key].length = 1;
+ key[i_key].key = &adb_service_data->session_key[i_key];
+ }
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key);
+ framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->fd->num) : NULL;
+ if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->fd->num)
+ framebuffer_data = NULL;
+
+ if (!pinfo->fd->flags.visited && !framebuffer_data) {
+ key[i_key].length = 1;
+ key[i_key++].key = &pinfo->fd->num;
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t);
+ framebuffer_data->data_in = pinfo->fd->num;
+ framebuffer_data->current_size = 0;
+ framebuffer_data->completed_in_frame = G_MAXUINT32;
+ framebuffer_data->size = tvb_get_letohl(tvb, offset + 4 * 2);
+ framebuffer_data->red_offset = tvb_get_letohl(tvb, offset + 4 * 5);
+ framebuffer_data->red_length = tvb_get_letohl(tvb, offset + 4 * 6);
+ framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7);
+ framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8);
+ framebuffer_data->blue_offset = tvb_get_letohl(tvb, offset + 4 * 9);
+ framebuffer_data->blue_length = tvb_get_letohl(tvb, offset + 4 * 10);
+ framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11);
+ framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12);
+
+ wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data);
+ }
+
+ if (framebuffer_data && framebuffer_data->data_in == pinfo->fd->num) {
+ proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_data);
+
+ if (!pinfo->fd->flags.visited && framebuffer_data) {
+ framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset);
+ if (framebuffer_data->current_size >= framebuffer_data->size)
+ framebuffer_data->completed_in_frame = pinfo->fd->num;
+ }
+
+ if (pref_dissect_more_detail_framebuffer) {
+ proto_item *pixel_item;
+ proto_tree *pixel_tree;
+
+ if (framebuffer_data &&
+ framebuffer_data->red_length == 5 &&
+ framebuffer_data->green_length == 6 &&
+ framebuffer_data->blue_length == 5 &&
+ framebuffer_data->red_offset == 11 &&
+ framebuffer_data->green_offset == 5 &&
+ framebuffer_data->blue_offset == 0) {
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if (tvb_reported_length_remaining(tvb, offset) < 2) {
+ proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
+ offset += 1;
+ }
+
+ pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA);
+ pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);
+
+ proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
+ } else if (framebuffer_data &&
+ framebuffer_data->red_length == 8 &&
+ framebuffer_data->green_length == 8 &&
+ framebuffer_data->blue_length == 8 &&
+ (framebuffer_data->alpha_length == 0 ||
+ framebuffer_data->alpha_length == 8)) {
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) {
+ proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
+ offset = tvb_captured_length(tvb);
+ break;
+ }
+
+ pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA);
+ pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);
+
+ proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_NA);
+ proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_NA);
+ proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_NA);
+
+ if (framebuffer_data->alpha_offset > 0) {
+ if (framebuffer_data->alpha_length == 0)
+ proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_NA);
+ else
+ proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_NA);
+ offset += 1;
+ proto_item_set_len(pixel_item, 4);
+ }
+ offset += 3;
+ }
+ } else {
+ offset = tvb_captured_length(tvb);
+ }
+ } else {
+ offset = tvb_captured_length(tvb);
+ }
+ }
+ } else if (g_strcmp0(service, "track-jdwp") == 0) {
+ guint32 data_length;
+
+ offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
+ expert_add_info(pinfo, sub_item, &ei_incomplete_message);
+ }
+ }
+ offset = tvb_captured_length(tvb);
+ } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) ||
+ (g_strcmp0(service, "shell:logcat -B") == 0)) {
+ tvbuff_t *next_tvb;
+ tvbuff_t *new_tvb;
+ guint8 *buffer = NULL;
+ gint size = 0;
+ gint i_offset = offset;
+ gint old_offset;
+ gint i_char = 0;
+ guint8 c1;
+ guint8 c2 = '\0';
+ guint16 payload_length;
+ guint16 try_header_size;
+ gint logcat_length = 0;
+ fragment_t *fragment;
+
+ DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
+ for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
+ key[i_key].length = 1;
+ key[i_key].key = &adb_service_data->session_key[i_key];
+ }
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key);
+ fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->fd->num - 1) : NULL;
+ if (fragment) {
+ if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1)
+ fragment->reassembled_in_frame = pinfo->fd->num;
+
+ if (fragment->reassembled_in_frame == pinfo->fd->num) {
+ size += fragment->length;
+ i_char += fragment->length;
+ }
+ }
+
+ size += tvb_reported_length_remaining(tvb, i_offset);
+ if (size > 0) {
+ buffer = (guint8 *) wmem_alloc(pinfo->pool, size);
+ if (fragment && i_char > 0)
+ memcpy(buffer, fragment->data, i_char);
+
+ if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') {
+ buffer[i_char - 1] = '\n';
+ i_offset += 1;
+ }
+
+ c1 = tvb_get_guint8(tvb, i_offset);
+ i_offset += 1;
+ old_offset = i_offset;
+
+ while (tvb_reported_length_remaining(tvb, i_offset) > 0) {
+ c2 = tvb_get_guint8(tvb, i_offset);
+
+ if (c1 == '\r' && c2 == '\n') {
+ buffer[i_char] = c2;
+ if (tvb_reported_length_remaining(tvb, i_offset) > 1) {
+ c1 = tvb_get_guint8(tvb, i_offset + 1);
+ i_offset += 2;
+ i_char += 1;
+ } else {
+ i_offset += 1;
+ }
+
+ continue;
+ }
+
+ buffer[i_char] = c1;
+ c1 = c2;
+ i_char += 1;
+ i_offset += 1;
+ }
+
+ if (tvb_reported_length_remaining(tvb, old_offset) == 0) {
+ buffer[i_char] = c1;
+ i_char += 1;
+ } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) {
+ buffer[i_char] = c2;
+ i_char += 1;
+ }
+
+ next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char);
+ add_new_data_source(pinfo, next_tvb, "Logcat");
+
+ i_offset = 0;
+ while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) {
+ if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) {
+ payload_length = tvb_get_letohs(next_tvb, i_offset);
+ try_header_size = tvb_get_letohs(next_tvb, i_offset + 2);
+
+ if (try_header_size == 0 || try_header_size != 24)
+ logcat_length = payload_length + 20;
+ else
+ logcat_length = payload_length + 24;
+ }
+
+ if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) {
+ new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length);
+
+ call_dissector(logcat_handle, new_tvb, pinfo, main_tree);
+ i_offset += logcat_length;
+ } else {
+
+ if (!pinfo->fd->flags.visited) {
+ DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
+ for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
+ key[i_key].length = 1;
+ key[i_key].key = &adb_service_data->session_key[i_key];
+ }
+ key[i_key].length = 1;
+ key[i_key++].key = &pinfo->fd->num;
+ key[i_key].length = 0;
+ key[i_key].key = NULL;
+
+ fragment = wmem_new(wmem_file_scope(), fragment_t);
+
+ fragment->length = tvb_captured_length_remaining(next_tvb, i_offset);
+ fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length);
+ tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length);
+ fragment->reassembled_in_frame = -1;
+
+ wmem_tree_insert32_array(fragments, key, fragment);
+ }
+
+ proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA);
+ i_offset = tvb_captured_length(next_tvb);
+ }
+ }
+ }
+
+ offset = tvb_captured_length(tvb);
+ } else if (g_str_has_prefix(service, "shell:")) {
+ if (adb_service_data->direction == P2P_DIR_SENT) {
+ proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", tvb_format_text_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)));
+
+ } else {
+ proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", tvb_format_text_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)));
+ }
+ offset = tvb_captured_length(tvb);
+ } else if (g_str_has_prefix(service, "jdwp:")) {
+/* TODO */
+ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
+ offset = tvb_captured_length(tvb);
+ } else if (g_str_has_prefix(service, "sync:")) {
+/* TODO */
+ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
+ offset = tvb_captured_length(tvb);
+ } else if (g_strcmp0(service, "host:list-forward") == 0 ||
+ g_str_has_prefix(service, "root:") ||
+ g_str_has_prefix(service, "remount:") ||
+ g_str_has_prefix(service, "tcpip:") ||
+ g_str_has_prefix(service, "usb:")) {
+ if (tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", tvb_format_text_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)));
+
+ offset = tvb_captured_length(tvb);
+ }
+ } else {
+ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
+ offset = tvb_captured_length(tvb);
+ }
+
+ return offset;
+}
+
+
+void
+proto_register_adb_service(void)
+{
+ module_t *module;
+ expert_module_t *expert_module;
+
+ static hf_register_info hf[] = {
+ { &hf_service,
+ { "Service", "adb_service.service",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_fragment,
+ { "Fragment", "adb_service.fragment",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_data,
+ { "Data", "adb_service.data",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_hex_ascii_length,
+ { "Hex ASCII String Length", "adb_service.hex_ascii_length",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_length,
+ { "Length", "adb_service.length",
+ FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_version,
+ { "Version", "adb_service.framebuffer.version",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_hex_ascii_version,
+ { "Hex ASCII String Version", "adb_service.hex_ascii_version",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_version,
+ { "Version", "adb_service.version",
+ FT_UINT32, BASE_DEC_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_depth,
+ { "Depth", "adb_service.framebuffer.depth",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_size,
+ { "Size", "adb_service.framebuffer.size",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_width,
+ { "Width", "adb_service.framebuffer.width",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_height,
+ { "Height", "adb_service.framebuffer.height",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_red_offset,
+ { "Red Offset", "adb_service.framebuffer.red_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_red_length,
+ { "Red Length", "adb_service.framebuffer.red_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_blue_offset,
+ { "Blue Offset", "adb_service.framebuffer.blue_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_blue_length,
+ { "Blue Length", "adb_service.framebuffer.blue_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_green_offset,
+ { "Green Offset", "adb_service.framebuffer.green_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_green_length,
+ { "Green Length", "adb_service.framebuffer.green_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_alpha_offset,
+ { "Alpha Offset", "adb_service.framebuffer.alpha_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_alpha_length,
+ { "Alpha Length", "adb_service.framebuffer.alpha_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_pixel,
+ { "Pixel", "adb_service.framebuffer.pixel",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_blue_5,
+ { "Blue", "adb_service.framebuffer.pixel.blue",
+ FT_UINT16, BASE_DEC, NULL, 0xF800,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_green_6,
+ { "Green", "adb_service.framebuffer.pixel.green",
+ FT_UINT16, BASE_DEC, NULL, 0x07E0,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_red_5,
+ { "Red", "adb_service.framebuffer.pixel.red",
+ FT_UINT16, BASE_DEC, NULL, 0x001F,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_blue,
+ { "Blue", "adb_service.framebuffer.pixel.blue",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_green,
+ { "Green", "adb_service.framebuffer.pixel.green",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_red,
+ { "Red", "adb_service.framebuffer.pixel.red",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_alpha,
+ { "Alpha", "adb_service.framebuffer.pixel.alpha",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_framebuffer_unused,
+ { "Unused", "adb_service.framebuffer.pixel.unused",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_devices,
+ { "Devices", "adb_service.devices",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_stdin,
+ { "Stdin", "adb_service.stdin",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_stdout,
+ { "Stdout", "adb_service.stdout",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_result,
+ { "Result", "adb_service.result",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_pids,
+ { "PIDs", "adb_service.pids",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_id,
+ { "Id", "adb_service.sync.id",
+ FT_STRING, STR_ASCII, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_length,
+ { "Length", "adb_service.sync.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_mode,
+ { "Mode", "adb_service.sync.mode",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_size,
+ { "Size", "adb_service.sync.size",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_time,
+ { "Last Modification Time", "adb_service.sync.time",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_unused,
+ { "Unused", "adb_service.sync.unused",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_sync_data,
+ { "Sync Data", "adb_service.sync.data",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_adb_service,
+ &ett_length,
+ &ett_version,
+ &ett_pixel,
+ &ett_data
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_incomplete_message, { "adb_service.expert.incomplete_message", PI_PROTOCOL, PI_WARN, "Incomplete message", EXPFILL }},
+ };
+
+ fragments = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+ framebuffer_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+ continuation_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+
+ proto_adb_service = proto_register_protocol("Android Debug Bridge Service", "ADB Service", "adb_service");
+ adb_service_handle = new_register_dissector("adb_service", dissect_adb_service, proto_adb_service);
+
+ proto_register_field_array(proto_adb_service, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_module = expert_register_protocol(proto_adb_service);
+ expert_register_field_array(expert_module, ei, array_length(ei));
+
+ module = prefs_register_protocol(proto_adb_service, NULL);
+ prefs_register_static_text_preference(module, "version",
+ "ADB Service protocol version is compatibile pior to: adb 1.0.31",
+ "Version of protocol supported by this dissector.");
+
+ prefs_register_bool_preference(module, "framebuffer_more_details",
+ "Dissect more detail for framebuffer service",
+ "Dissect more detail for framebuffer service",
+ &pref_dissect_more_detail_framebuffer);
+}
+
+
+void
+proto_reg_handoff_adb_service(void)
+{
+ logcat_handle = find_dissector("logcat");
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/epan/dissectors/packet-adb_service.h b/epan/dissectors/packet-adb_service.h
new file mode 100644
index 0000000000..07108e6fd2
--- /dev/null
+++ b/epan/dissectors/packet-adb_service.h
@@ -0,0 +1,49 @@
+/* packet-adb_service.h
+ *
+ * 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_ADB_SERVICE_H__
+#define __PACKET_ADB_SERVICE_H__
+
+gint dissect_ascii_uint32(proto_tree *tree, gint hf_hex_ascii, gint ett_hex_ascii,
+ gint hf_value, tvbuff_t *tvb, gint offset, guint32 *value);
+
+typedef struct {
+ guint32 session_key_length;
+ guint32 *session_key;
+
+ const guint8 *service;
+ gint direction;
+} adb_service_data_t;
+
+#endif /* __PACKET_ADB_SERVICE_H__ */
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */ \ No newline at end of file