summaryrefslogtreecommitdiff
path: root/monitor/control.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2018-07-19 16:58:02 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2018-07-19 17:03:55 +0300
commit390b93f90189917addc4e9c0a5670f1fe797e7ba (patch)
tree68a0dd7ed05ea7868735b530af1a4c96e968bf59 /monitor/control.c
parent0a080597220a1233edd71601682263b3faa931dc (diff)
downloadbluez-390b93f90189917addc4e9c0a5670f1fe797e7ba.tar.gz
monitor: Use BPF to filter packets by index
This uses a BPF filter to filter packets to specific index.
Diffstat (limited to 'monitor/control.c')
-rw-r--r--monitor/control.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/monitor/control.c b/monitor/control.c
index 150bdcc44..991dea1c3 100644
--- a/monitor/control.c
+++ b/monitor/control.c
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdbool.h>
+#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
@@ -39,6 +40,7 @@
#include <sys/stat.h>
#include <termios.h>
#include <fcntl.h>
+#include <linux/filter.h>
#include "lib/bluetooth.h"
#include "lib/hci.h"
@@ -58,6 +60,7 @@
static struct btsnoop *btsnoop_file = NULL;
static bool hcidump_fallback = false;
static bool decode_control = true;
+static uint16_t filter_index = HCI_DEV_NONE;
struct control_data {
uint16_t channel;
@@ -1028,6 +1031,37 @@ static int open_socket(uint16_t channel)
return fd;
}
+static void attach_index_filter(int fd, uint16_t index)
+{
+ struct sock_filter filters[] = {
+ /* Load MGMT index:
+ * A <- MGMT index
+ */
+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS,
+ offsetof(struct mgmt_hdr, index)),
+ /* Accept if index is HCI_DEV_NONE:
+ * A == HCI_DEV_NONE
+ */
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, HCI_DEV_NONE, 0, 1),
+ /* return */
+ BPF_STMT(BPF_RET|BPF_K, 0x0fffffff), /* pass */
+ /* Accept if index match:
+ * A == index
+ */
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, index, 0, 1),
+ /* returns */
+ BPF_STMT(BPF_RET|BPF_K, 0x0fffffff), /* pass */
+ BPF_STMT(BPF_RET|BPF_K, 0), /* reject */
+ };
+ struct sock_fprog fprog = {
+ .len = sizeof(filters) / sizeof(filters[0]),
+ /* casting const away: */
+ .filter = filters,
+ };
+
+ setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
+}
+
static int open_channel(uint16_t channel)
{
struct control_data *data;
@@ -1045,6 +1079,9 @@ static int open_channel(uint16_t channel)
return -1;
}
+ if (filter_index != HCI_DEV_NONE)
+ attach_index_filter(data->fd, filter_index);
+
mainloop_add_fd(data->fd, EPOLLIN, data_callback, data, free_data);
return 0;
@@ -1468,3 +1505,8 @@ void control_disable_decoding(void)
{
decode_control = false;
}
+
+void control_filter_index(uint16_t index)
+{
+ filter_index = index;
+}