wifimon example program
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index d42b495..99ba2af 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -36,6 +36,7 @@
hostprogs-y += xdp_tx_iptunnel
hostprogs-y += test_map_in_map
hostprogs-y += per_socket_stats_example
+hostprogs-y += wifimon
# Libbpf dependencies
LIBBPF := ../../tools/lib/bpf/bpf.o
@@ -76,6 +77,7 @@
xdp_tx_iptunnel-objs := bpf_load.o $(LIBBPF) xdp_tx_iptunnel_user.o
test_map_in_map-objs := bpf_load.o $(LIBBPF) test_map_in_map_user.o
per_socket_stats_example-objs := $(LIBBPF) cookie_uid_helper_example.o
+wifimon-objs := bpf_load.o $(LIBBPF) wifimon_user.o
# Tell kbuild to always build the programs
always := $(hostprogs-y)
@@ -111,7 +113,9 @@
always += xdp_tx_iptunnel_kern.o
always += test_map_in_map_kern.o
always += cookie_uid_helper_example.o
+always += wifimon_kern.o
+HOSTCFLAGS += -I$(srctree)/include/uapi/ -D__EXPORTED_HEADERS__
HOSTCFLAGS += -I$(objtree)/usr/include
HOSTCFLAGS += -I$(srctree)/tools/lib/
HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
@@ -146,6 +150,7 @@
HOSTLOADLIBES_lwt_len_hist += -l elf
HOSTLOADLIBES_xdp_tx_iptunnel += -lelf
HOSTLOADLIBES_test_map_in_map += -lelf
+HOSTLOADLIBES_wifimon += -lelf
# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index dcdce12..d692044 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -68,6 +68,7 @@
bool is_perf_event = strncmp(event, "perf_event", 10) == 0;
bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0;
bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0;
+ bool is_wifimon_sk = strncmp(event, "wifimon", 7) == 0;
size_t insns_cnt = size / sizeof(struct bpf_insn);
enum bpf_prog_type prog_type;
char buf[256];
@@ -93,6 +94,8 @@
prog_type = BPF_PROG_TYPE_CGROUP_SKB;
} else if (is_cgroup_sk) {
prog_type = BPF_PROG_TYPE_CGROUP_SOCK;
+ } else if (is_wifimon_sk) {
+ prog_type = BPF_PROG_TYPE_WIFIMON;
} else {
printf("Unknown event '%s'\n", event);
return -1;
@@ -107,7 +110,7 @@
prog_fd[prog_cnt++] = fd;
- if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk)
+ if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk || is_wifimon_sk)
return 0;
if (is_socket) {
@@ -310,7 +313,7 @@
return 1;
/* clear all kprobes */
- i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events");
+// i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events");
/* scan over all elf sections to get license and map info */
for (i = 1; i < ehdr.e_shnum; i++) {
@@ -375,14 +378,14 @@
memcmp(shname_prog, "xdp", 3) == 0 ||
memcmp(shname_prog, "perf_event", 10) == 0 ||
memcmp(shname_prog, "socket", 6) == 0 ||
- memcmp(shname_prog, "cgroup/", 7) == 0)
+ memcmp(shname_prog, "cgroup/", 7) == 0 ||
+ memcmp(shname_prog, "wifimon", 7) == 0)
load_and_attach(shname_prog, insns, data_prog->d_size);
}
}
/* load programs that don't use maps */
for (i = 1; i < ehdr.e_shnum; i++) {
-
if (processed_sec[i])
continue;
@@ -395,7 +398,8 @@
memcmp(shname, "xdp", 3) == 0 ||
memcmp(shname, "perf_event", 10) == 0 ||
memcmp(shname, "socket", 6) == 0 ||
- memcmp(shname, "cgroup/", 7) == 0)
+ memcmp(shname, "cgroup/", 7) == 0 ||
+ memcmp(shname, "wifimon", 7) == 0)
load_and_attach(shname, data->d_buf, data->d_size);
}
diff --git a/samples/bpf/wifimon_kern.c b/samples/bpf/wifimon_kern.c
new file mode 100644
index 0000000..9f16b83
--- /dev/null
+++ b/samples/bpf/wifimon_kern.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2017 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#define KBUILD_MODNAME "wifimon_test"
+#include <uapi/linux/bpf.h>
+#include <linux/ieee80211.h>
+#include "bpf_helpers.h"
+
+SEC("wifimon_no_data")
+int wifimon_no_data(struct __sk_buff *skb)
+{
+ u8 fc1;
+ int ret = bpf_skb_load_bytes(skb, 0, &fc1, sizeof(fc1));
+
+ /* reject data frames */
+ if ((fc1 & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+ return 0;
+
+ /* reject beacon frames */
+ if ((fc1 & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON))
+ return 0;
+
+ /* accept */
+ return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/wifimon_user.c b/samples/bpf/wifimon_user.c
new file mode 100644
index 0000000..557bc6b
--- /dev/null
+++ b/samples/bpf/wifimon_user.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2017 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <linux/bpf.h>
+#include "bpf_load.h"
+
+int main(int argc, char **argv)
+{
+ char filename[256];
+ char fdstr[100];
+ char *args[] = {
+ "iw",
+ "dev",
+ argv[1],
+ "set",
+ "filter",
+ fdstr,
+ NULL,
+ };
+
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+ if (argc != 2) {
+ printf("usage: %s <ifname>\n", argv[0]);
+ return 1;
+ }
+
+ if (load_bpf_file(filename)) {
+ printf("%s", bpf_log_buf);
+ return 1;
+ }
+
+ if (!prog_cnt) {
+ printf("load_bpf_file: nothing loaded\n");
+ return 1;
+ }
+
+ snprintf(fdstr, sizeof(fdstr), "%d", prog_fd[0]);
+
+ if (fcntl(prog_fd[0], F_SETFD, 0) < 0) {
+ printf("fcntl error: %d: %s\n", errno, strerror(errno));
+ return 1;
+ }
+
+ return execve("/root/iw", args, NULL);
+}