142984d7cSDaniel Borkmann #include <linux/unistd.h> 242984d7cSDaniel Borkmann #include <linux/bpf.h> 342984d7cSDaniel Borkmann 442984d7cSDaniel Borkmann #include <stdio.h> 542984d7cSDaniel Borkmann #include <stdlib.h> 642984d7cSDaniel Borkmann #include <stdint.h> 742984d7cSDaniel Borkmann #include <unistd.h> 842984d7cSDaniel Borkmann #include <string.h> 942984d7cSDaniel Borkmann #include <assert.h> 1042984d7cSDaniel Borkmann #include <errno.h> 1142984d7cSDaniel Borkmann 1242984d7cSDaniel Borkmann #include <sys/types.h> 1342984d7cSDaniel Borkmann #include <sys/socket.h> 1442984d7cSDaniel Borkmann 158d930450SJakub Kicinski #include <bpf/bpf.h> 168d930450SJakub Kicinski 171a9b268cSJakub Kicinski #include "bpf/libbpf.h" 188d930450SJakub Kicinski #include "bpf_insn.h" 199899694aSJoe Stringer #include "sock_example.h" 2042984d7cSDaniel Borkmann 2142984d7cSDaniel Borkmann #define BPF_F_PIN (1 << 0) 2242984d7cSDaniel Borkmann #define BPF_F_GET (1 << 1) 2342984d7cSDaniel Borkmann #define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET) 2442984d7cSDaniel Borkmann 2542984d7cSDaniel Borkmann #define BPF_F_KEY (1 << 2) 2642984d7cSDaniel Borkmann #define BPF_F_VAL (1 << 3) 2742984d7cSDaniel Borkmann #define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL) 2842984d7cSDaniel Borkmann 2942984d7cSDaniel Borkmann #define BPF_M_UNSPEC 0 3042984d7cSDaniel Borkmann #define BPF_M_MAP 1 3142984d7cSDaniel Borkmann #define BPF_M_PROG 2 3242984d7cSDaniel Borkmann 3342984d7cSDaniel Borkmann static void usage(void) 3442984d7cSDaniel Borkmann { 3542984d7cSDaniel Borkmann printf("Usage: fds_example [...]\n"); 3642984d7cSDaniel Borkmann printf(" -F <file> File to pin/get object\n"); 3742984d7cSDaniel Borkmann printf(" -P |- pin object\n"); 3842984d7cSDaniel Borkmann printf(" -G `- get object\n"); 3942984d7cSDaniel Borkmann printf(" -m eBPF map mode\n"); 4042984d7cSDaniel Borkmann printf(" -k <key> |- map key\n"); 4142984d7cSDaniel Borkmann printf(" -v <value> `- map value\n"); 4242984d7cSDaniel Borkmann printf(" -p eBPF prog mode\n"); 4342984d7cSDaniel Borkmann printf(" -o <object> `- object file\n"); 4442984d7cSDaniel Borkmann printf(" -h Display this help.\n"); 4542984d7cSDaniel Borkmann } 4642984d7cSDaniel Borkmann 4742984d7cSDaniel Borkmann static int bpf_map_create(void) 4842984d7cSDaniel Borkmann { 4942984d7cSDaniel Borkmann return bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(uint32_t), 5089b97607SAlexei Starovoitov sizeof(uint32_t), 1024, 0); 5142984d7cSDaniel Borkmann } 5242984d7cSDaniel Borkmann 5342984d7cSDaniel Borkmann static int bpf_prog_create(const char *object) 5442984d7cSDaniel Borkmann { 55811b4f0dSArnaldo Carvalho de Melo static struct bpf_insn insns[] = { 5642984d7cSDaniel Borkmann BPF_MOV64_IMM(BPF_REG_0, 1), 5742984d7cSDaniel Borkmann BPF_EXIT_INSN(), 5842984d7cSDaniel Borkmann }; 5943371c83SJoe Stringer size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); 601a9b268cSJakub Kicinski char bpf_log_buf[BPF_LOG_BUF_SIZE]; 611a9b268cSJakub Kicinski struct bpf_object *obj; 621a9b268cSJakub Kicinski int prog_fd; 6342984d7cSDaniel Borkmann 6442984d7cSDaniel Borkmann if (object) { 651a9b268cSJakub Kicinski assert(!bpf_prog_load(object, BPF_PROG_TYPE_UNSPEC, 661a9b268cSJakub Kicinski &obj, &prog_fd)); 671a9b268cSJakub Kicinski return prog_fd; 6842984d7cSDaniel Borkmann } else { 69d40fc181SJoe Stringer return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, 7043371c83SJoe Stringer insns, insns_cnt, "GPL", 0, 71d40fc181SJoe Stringer bpf_log_buf, BPF_LOG_BUF_SIZE); 7242984d7cSDaniel Borkmann } 7342984d7cSDaniel Borkmann } 7442984d7cSDaniel Borkmann 7542984d7cSDaniel Borkmann static int bpf_do_map(const char *file, uint32_t flags, uint32_t key, 7642984d7cSDaniel Borkmann uint32_t value) 7742984d7cSDaniel Borkmann { 7842984d7cSDaniel Borkmann int fd, ret; 7942984d7cSDaniel Borkmann 8042984d7cSDaniel Borkmann if (flags & BPF_F_PIN) { 8142984d7cSDaniel Borkmann fd = bpf_map_create(); 8242984d7cSDaniel Borkmann printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); 8342984d7cSDaniel Borkmann assert(fd > 0); 8442984d7cSDaniel Borkmann 8542984d7cSDaniel Borkmann ret = bpf_obj_pin(fd, file); 8642984d7cSDaniel Borkmann printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 8742984d7cSDaniel Borkmann assert(ret == 0); 8842984d7cSDaniel Borkmann } else { 8942984d7cSDaniel Borkmann fd = bpf_obj_get(file); 9042984d7cSDaniel Borkmann printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 9142984d7cSDaniel Borkmann assert(fd > 0); 9242984d7cSDaniel Borkmann } 9342984d7cSDaniel Borkmann 9442984d7cSDaniel Borkmann if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 95d40fc181SJoe Stringer ret = bpf_map_update_elem(fd, &key, &value, 0); 9642984d7cSDaniel Borkmann printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 9742984d7cSDaniel Borkmann ret, strerror(errno)); 9842984d7cSDaniel Borkmann assert(ret == 0); 9942984d7cSDaniel Borkmann } else if (flags & BPF_F_KEY) { 100d40fc181SJoe Stringer ret = bpf_map_lookup_elem(fd, &key, &value); 10142984d7cSDaniel Borkmann printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 10242984d7cSDaniel Borkmann ret, strerror(errno)); 10342984d7cSDaniel Borkmann assert(ret == 0); 10442984d7cSDaniel Borkmann } 10542984d7cSDaniel Borkmann 10642984d7cSDaniel Borkmann return 0; 10742984d7cSDaniel Borkmann } 10842984d7cSDaniel Borkmann 10942984d7cSDaniel Borkmann static int bpf_do_prog(const char *file, uint32_t flags, const char *object) 11042984d7cSDaniel Borkmann { 11142984d7cSDaniel Borkmann int fd, sock, ret; 11242984d7cSDaniel Borkmann 11342984d7cSDaniel Borkmann if (flags & BPF_F_PIN) { 11442984d7cSDaniel Borkmann fd = bpf_prog_create(object); 11542984d7cSDaniel Borkmann printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); 11642984d7cSDaniel Borkmann assert(fd > 0); 11742984d7cSDaniel Borkmann 11842984d7cSDaniel Borkmann ret = bpf_obj_pin(fd, file); 11942984d7cSDaniel Borkmann printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 12042984d7cSDaniel Borkmann assert(ret == 0); 12142984d7cSDaniel Borkmann } else { 12242984d7cSDaniel Borkmann fd = bpf_obj_get(file); 12342984d7cSDaniel Borkmann printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 12442984d7cSDaniel Borkmann assert(fd > 0); 12542984d7cSDaniel Borkmann } 12642984d7cSDaniel Borkmann 12742984d7cSDaniel Borkmann sock = open_raw_sock("lo"); 12842984d7cSDaniel Borkmann assert(sock > 0); 12942984d7cSDaniel Borkmann 13042984d7cSDaniel Borkmann ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd)); 13142984d7cSDaniel Borkmann printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd, 13242984d7cSDaniel Borkmann ret, strerror(errno)); 13342984d7cSDaniel Borkmann assert(ret == 0); 13442984d7cSDaniel Borkmann 13542984d7cSDaniel Borkmann return 0; 13642984d7cSDaniel Borkmann } 13742984d7cSDaniel Borkmann 13842984d7cSDaniel Borkmann int main(int argc, char **argv) 13942984d7cSDaniel Borkmann { 14042984d7cSDaniel Borkmann const char *file = NULL, *object = NULL; 14142984d7cSDaniel Borkmann uint32_t key = 0, value = 0, flags = 0; 14242984d7cSDaniel Borkmann int opt, mode = BPF_M_UNSPEC; 14342984d7cSDaniel Borkmann 14442984d7cSDaniel Borkmann while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) { 14542984d7cSDaniel Borkmann switch (opt) { 14642984d7cSDaniel Borkmann /* General args */ 14742984d7cSDaniel Borkmann case 'F': 14842984d7cSDaniel Borkmann file = optarg; 14942984d7cSDaniel Borkmann break; 15042984d7cSDaniel Borkmann case 'P': 15142984d7cSDaniel Borkmann flags |= BPF_F_PIN; 15242984d7cSDaniel Borkmann break; 15342984d7cSDaniel Borkmann case 'G': 15442984d7cSDaniel Borkmann flags |= BPF_F_GET; 15542984d7cSDaniel Borkmann break; 15642984d7cSDaniel Borkmann /* Map-related args */ 15742984d7cSDaniel Borkmann case 'm': 15842984d7cSDaniel Borkmann mode = BPF_M_MAP; 15942984d7cSDaniel Borkmann break; 16042984d7cSDaniel Borkmann case 'k': 16142984d7cSDaniel Borkmann key = strtoul(optarg, NULL, 0); 16242984d7cSDaniel Borkmann flags |= BPF_F_KEY; 16342984d7cSDaniel Borkmann break; 16442984d7cSDaniel Borkmann case 'v': 16542984d7cSDaniel Borkmann value = strtoul(optarg, NULL, 0); 16642984d7cSDaniel Borkmann flags |= BPF_F_VAL; 16742984d7cSDaniel Borkmann break; 16842984d7cSDaniel Borkmann /* Prog-related args */ 16942984d7cSDaniel Borkmann case 'p': 17042984d7cSDaniel Borkmann mode = BPF_M_PROG; 17142984d7cSDaniel Borkmann break; 17242984d7cSDaniel Borkmann case 'o': 17342984d7cSDaniel Borkmann object = optarg; 17442984d7cSDaniel Borkmann break; 17542984d7cSDaniel Borkmann default: 17642984d7cSDaniel Borkmann goto out; 17742984d7cSDaniel Borkmann } 17842984d7cSDaniel Borkmann } 17942984d7cSDaniel Borkmann 18042984d7cSDaniel Borkmann if (!(flags & BPF_F_PIN_GET) || !file) 18142984d7cSDaniel Borkmann goto out; 18242984d7cSDaniel Borkmann 18342984d7cSDaniel Borkmann switch (mode) { 18442984d7cSDaniel Borkmann case BPF_M_MAP: 18542984d7cSDaniel Borkmann return bpf_do_map(file, flags, key, value); 18642984d7cSDaniel Borkmann case BPF_M_PROG: 18742984d7cSDaniel Borkmann return bpf_do_prog(file, flags, object); 18842984d7cSDaniel Borkmann } 18942984d7cSDaniel Borkmann out: 19042984d7cSDaniel Borkmann usage(); 19142984d7cSDaniel Borkmann return -1; 19242984d7cSDaniel Borkmann } 193