[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-bluetooth
Subject:    [PATCH 3/4] android/snoop: Add support for TCP clients
From:       Andrzej Kaczmarek <andrzej.kaczmarek () tieto ! com>
Date:       2014-05-30 16:15:55
Message-ID: 1401466556-9040-3-git-send-email-andrzej.kaczmarek () tieto ! com
[Download RAW message or body]

This patch adds support to write snoop file to client connected via
TCP. Default listen port is 4330 which is used by Bluedroid for similar
purpose.
---
 android/bluetoothd-snoop.c | 123 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 1 deletion(-)

diff --git a/android/bluetoothd-snoop.c b/android/bluetoothd-snoop.c
index 57f97f4..25b9c97 100644
--- a/android/bluetoothd-snoop.c
+++ b/android/bluetoothd-snoop.c
@@ -32,6 +32,9 @@
 #if defined(ANDROID)
 #include <sys/capability.h>
 #endif
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
@@ -41,12 +44,15 @@
 #include "src/shared/btsnoop.h"
 
 #define DEFAULT_SNOOP_FILE "/sdcard/btsnoop_hci.log"
+#define DEFAULT_TCP_PORT 4330
 
 #define MAX_PACKET_SIZE (1486 + 4)
 
 static struct btsnoop *snoop = NULL;
+static struct btsnoop *tcp_snoop = NULL;
 static uint8_t monitor_buf[MAX_PACKET_SIZE];
 static int monitor_fd = -1;
+static int server_fd = -1;
 
 static void signal_callback(int signum, void *user_data)
 {
@@ -137,8 +143,10 @@ static void data_callback(int fd, uint32_t events, void *user_data)
 			continue;
 
 		flags = get_flags_from_opcode(opcode);
-		if (flags != 0xff)
+		if (flags != 0xff) {
 			btsnoop_write(snoop, tv, flags, monitor_buf, pktlen);
+			btsnoop_write(tcp_snoop, tv, flags, monitor_buf, pktlen);
+		}
 	}
 }
 
@@ -215,6 +223,115 @@ static void set_capabilities(void)
 #endif
 }
 
+static void tcp_callback(int fd, uint32_t events, void *user_data)
+{
+	if (events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
+		mainloop_remove_fd(fd);
+
+		free(tcp_snoop);
+		tcp_snoop = NULL;
+
+		printf("TCP client disconnected\n");
+	}
+}
+
+static void accept_tcp(int fd, uint32_t events, void *user_data)
+{
+	struct sockaddr_un addr;
+	socklen_t len;
+	int nfd;
+
+	memset(&addr, 0, sizeof(addr));
+	len = sizeof(addr);
+
+	if (events & (EPOLLERR | EPOLLHUP)) {
+		mainloop_remove_fd(server_fd);
+		return;
+	}
+
+	nfd = accept(server_fd, (struct sockaddr *) &addr, &len);
+	if (nfd < 0) {
+		perror("Failed to accept incoming connection\n");
+		return;
+	}
+
+	/* We only support one client connected */
+	if (tcp_snoop) {
+		fprintf(stderr, "TCP client already connected\n");
+		close(nfd);
+		return;
+	}
+
+	if (mainloop_add_fd(nfd, EPOLLIN | EPOLLRDHUP, tcp_callback,
+							NULL, NULL) < 0) {
+		fprintf(stderr, "Failed to setup watch on client\n");
+		close(nfd);
+		return;
+	}
+
+	tcp_snoop = btsnoop_create_fd(nfd, BTSNOOP_TYPE_HCI);
+	if (!tcp_snoop) {
+		fprintf(stderr, "Failed to create snoop\n");
+		close(nfd);
+		return;
+	}
+
+	printf("TCP client connected\n");
+}
+
+static int open_tcp(void)
+{
+	struct sockaddr_in addr;
+	int fd, opt = 1;
+
+	fd = socket(PF_INET, SOCK_STREAM, 0);
+	if (fd < 0) {
+		perror("Failed to open server socket\n");
+		return -1;
+	}
+
+	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+	addr.sin_port = htons(DEFAULT_TCP_PORT);
+
+	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("Failed to bind server socket\n");
+		close(fd);
+		return -1;
+	}
+
+	if (listen(fd, 5) < 0) {
+		perror("Failed to listen server socket\n");
+		close(fd);
+		return -1;
+	}
+
+	if (mainloop_add_fd(fd, EPOLLIN, accept_tcp, NULL, NULL) < 0) {
+		fprintf(stderr, "Failed to setup watch on server socket\n");
+		close(fd);
+		return -1;
+	}
+
+	server_fd = fd;
+
+	printf("TCP server ready\n");
+
+	return 0;
+}
+
+static void close_tcp(void)
+{
+	close(server_fd);
+
+	mainloop_remove_fd(server_fd);
+
+	server_fd = -1;
+}
+
 int main(int argc, char *argv[])
 {
 	const char *path;
@@ -243,8 +360,12 @@ int main(int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
+	open_tcp();
+
 	mainloop_run();
 
+	close_tcp();
+
 	close_monitor();
 
 	return EXIT_SUCCESS;
-- 
1.9.3

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

Configure | About | News | Add a list | Sponsored by KoreLogic