1 /* eBPF example program: 2 * 3 * - Loads eBPF program 4 * 5 * The eBPF program sets the sk_bound_dev_if index in new AF_INET{6} 6 * sockets opened by processes in the cgroup. 7 * 8 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH 9 */ 10 11 #define _GNU_SOURCE 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <stddef.h> 16 #include <string.h> 17 #include <unistd.h> 18 #include <assert.h> 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <net/if.h> 22 #include <linux/bpf.h> 23 24 #include "libbpf.h" 25 26 char bpf_log_buf[BPF_LOG_BUF_SIZE]; 27 28 static int prog_load(int idx) 29 { 30 struct bpf_insn prog[] = { 31 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 32 BPF_MOV64_IMM(BPF_REG_3, idx), 33 BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)), 34 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)), 35 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */ 36 BPF_EXIT_INSN(), 37 }; 38 size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 39 40 return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt, 41 "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE); 42 } 43 44 static int usage(const char *argv0) 45 { 46 printf("Usage: %s cg-path device-index\n", argv0); 47 return EXIT_FAILURE; 48 } 49 50 int main(int argc, char **argv) 51 { 52 int cg_fd, prog_fd, ret; 53 unsigned int idx; 54 55 if (argc < 2) 56 return usage(argv[0]); 57 58 idx = if_nametoindex(argv[2]); 59 if (!idx) { 60 printf("Invalid device name\n"); 61 return EXIT_FAILURE; 62 } 63 64 cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY); 65 if (cg_fd < 0) { 66 printf("Failed to open cgroup path: '%s'\n", strerror(errno)); 67 return EXIT_FAILURE; 68 } 69 70 prog_fd = prog_load(idx); 71 printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf); 72 73 if (prog_fd < 0) { 74 printf("Failed to load prog: '%s'\n", strerror(errno)); 75 return EXIT_FAILURE; 76 } 77 78 ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE); 79 if (ret < 0) { 80 printf("Failed to attach prog to cgroup: '%s'\n", 81 strerror(errno)); 82 return EXIT_FAILURE; 83 } 84 85 return EXIT_SUCCESS; 86 } 87