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 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) 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 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) 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 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) 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 @@ int load_bpf_file(char *path) 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 @@ int load_bpf_file(char *path) 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 @@ int load_bpf_file(char *path) 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); +}