[PATCH 1/7] android: Add HCI snooping tool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This tool is intended to be run as Android service. It supports
writing HCI snoop data in old btsnoop format only. By default traffic
is stored in /sdcard/btsnoop_hci.log file (can be overridded with
option - mainly for testing on Linux host). Only index 0 is sniffed.
---
 .gitignore                 |   1 +
 android/Android.mk         |  23 +++++
 android/Makefile.am        |   6 ++
 android/bluetoothd-snoop.c | 219 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 249 insertions(+)
 create mode 100644 android/bluetoothd-snoop.c

diff --git a/.gitignore b/.gitignore
index b97546e..1447c90 100644
--- a/.gitignore
+++ b/.gitignore
@@ -109,3 +109,4 @@ android/system-emulator
 android/bluetoothd
 android/haltest
 android/android-tester
+android/bluetoothd-snoop
diff --git a/android/Android.mk b/android/Android.mk
index 7e29899..1720823 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -253,3 +253,26 @@ LOCAL_MODULE_TAGS := debug
 LOCAL_MODULE := l2test
 
 include $(BUILD_EXECUTABLE)
+
+#
+# bluetoothd-snoop
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	bluetoothd-snoop.c \
+	../monitor/mainloop.c \
+	../src/shared/btsnoop.c \
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../lib \
+
+LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bluetoothd-snoop
+
+include $(BUILD_EXECUTABLE)
diff --git a/android/Makefile.am b/android/Makefile.am
index dec81ce..36210b9 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -4,6 +4,12 @@ noinst_PROGRAMS += android/system-emulator
 android_system_emulator_SOURCES = android/system-emulator.c \
 					monitor/mainloop.h monitor/mainloop.c
 
+noinst_PROGRAMS += android/bluetoothd-snoop
+
+android_bluetoothd_snoop_SOURCES = android/bluetoothd-snoop.c \
+				monitor/mainloop.h monitor/mainloop.c \
+				src/shared/btsnoop.h src/shared/btsnoop.c
+
 noinst_PROGRAMS += android/bluetoothd
 
 android_bluetoothd_SOURCES = android/main.c \
diff --git a/android/bluetoothd-snoop.c b/android/bluetoothd-snoop.c
new file mode 100644
index 0000000..02f44e9
--- /dev/null
+++ b/android/bluetoothd-snoop.c
@@ -0,0 +1,219 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/mgmt.h"
+
+#include "monitor/mainloop.h"
+#include "src/shared/btsnoop.h"
+
+#define DEAULT_SNOOP_FILE "/sdcard/btsnoop_hci.log"
+
+#define MAX_PACKET_SIZE (1486 + 4)
+
+static struct btsnoop *snoop = NULL;
+static uint8_t monitor_buf[MAX_PACKET_SIZE];
+static int monitor_fd = -1;
+
+static void signal_callback(int signum, void *user_data)
+{
+	switch (signum) {
+	case SIGINT:
+	case SIGTERM:
+		mainloop_quit();
+		break;
+	}
+}
+
+static uint32_t get_flags_from_opcode(uint16_t opcode)
+{
+	switch (opcode) {
+	case BTSNOOP_OPCODE_NEW_INDEX:
+	case BTSNOOP_OPCODE_DEL_INDEX:
+		break;
+	case BTSNOOP_OPCODE_COMMAND_PKT:
+		return 0x02;
+	case BTSNOOP_OPCODE_EVENT_PKT:
+		return 0x03;
+	case BTSNOOP_OPCODE_ACL_TX_PKT:
+		return 0x00;
+	case BTSNOOP_OPCODE_ACL_RX_PKT:
+		return 0x01;
+	case BTSNOOP_OPCODE_SCO_TX_PKT:
+	case BTSNOOP_OPCODE_SCO_RX_PKT:
+		break;
+	}
+
+	return 0xff;
+}
+
+static void data_callback(int fd, uint32_t events, void *user_data)
+{
+	unsigned char control[32];
+	struct mgmt_hdr hdr;
+	struct msghdr msg;
+	struct iovec iov[2];
+
+	if (events & (EPOLLERR | EPOLLHUP)) {
+		mainloop_remove_fd(monitor_fd);
+		return;
+	}
+
+	iov[0].iov_base = &hdr;
+	iov[0].iov_len = MGMT_HDR_SIZE;
+	iov[1].iov_base = monitor_buf;
+	iov[1].iov_len = sizeof(monitor_buf);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 2;
+	msg.msg_control = control;
+	msg.msg_controllen = sizeof(control);
+
+	while (true) {
+		struct cmsghdr *cmsg;
+		struct timeval *tv = NULL;
+		struct timeval ctv;
+		uint16_t opcode, index, pktlen;
+		uint32_t flags;
+		ssize_t len;
+
+		len = recvmsg(monitor_fd, &msg, MSG_DONTWAIT);
+		if (len < 0)
+			break;
+
+		if (len < MGMT_HDR_SIZE)
+			break;
+
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level != SOL_SOCKET)
+				continue;
+
+			if (cmsg->cmsg_type == SCM_TIMESTAMP) {
+				memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
+				tv = &ctv;
+			}
+		}
+
+		opcode = btohs(hdr.opcode);
+		index  = btohs(hdr.index);
+		pktlen = btohs(hdr.len);
+
+		if (index)
+			continue;
+
+		flags = get_flags_from_opcode(opcode);
+		if (flags != 0xff)
+			btsnoop_write(snoop, tv, flags, monitor_buf, pktlen);
+	}
+}
+
+static int open_monitor(const char *path)
+{
+	struct sockaddr_hci addr;
+	int opt = 1;
+
+	snoop = btsnoop_create(path, BTSNOOP_TYPE_HCI);
+	if (!snoop)
+		return -1;
+
+	monitor_fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
+	if (monitor_fd < 0)
+		goto failed;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.hci_family = AF_BLUETOOTH;
+	addr.hci_dev = HCI_DEV_NONE;
+	addr.hci_channel = HCI_CHANNEL_MONITOR;
+
+	if (bind(monitor_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+		goto failed_close;
+
+	if (setsockopt(monitor_fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))
+									< 0)
+		goto failed_close;
+
+	mainloop_add_fd(monitor_fd, EPOLLIN, data_callback, NULL, NULL);
+
+	return 0;
+
+failed_close:
+	close(monitor_fd);
+	monitor_fd = -1;
+
+failed:
+	btsnoop_unref(snoop);
+	snoop = NULL;
+
+	return -1;
+}
+
+static void close_monitor(void)
+{
+	btsnoop_unref(snoop);
+	snoop = NULL;
+
+	close(monitor_fd);
+	monitor_fd = -1;
+}
+
+int main(int argc, char *argv[])
+{
+	const char *path;
+	sigset_t mask;
+
+	if (argc > 1)
+		path = argv[1];
+	else
+		path = DEAULT_SNOOP_FILE;
+
+	mainloop_init();
+
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGINT);
+	sigaddset(&mask, SIGTERM);
+
+	mainloop_set_signal(&mask, signal_callback, NULL, NULL);
+
+	if (open_monitor(path) < 0) {
+		printf("Failed to start bluetoothd_snoop\n");
+		return EXIT_FAILURE;
+	}
+
+	mainloop_run();
+
+	close_monitor();
+
+	return EXIT_SUCCESS;
+}
-- 
1.8.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux