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 static int prog_load(int idx) 27 { 28 struct bpf_insn prog[] = { 29 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 30 BPF_MOV64_IMM(BPF_REG_3, idx), 31 BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)), 32 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)), 33 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */ 34 BPF_EXIT_INSN(), 35 }; 36 37 return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, prog, sizeof(prog), 38 "GPL", 0); 39 } 40 41 static int usage(const char *argv0) 42 { 43 printf("Usage: %s cg-path device-index\n", argv0); 44 return EXIT_FAILURE; 45 } 46 47 int main(int argc, char **argv) 48 { 49 int cg_fd, prog_fd, ret; 50 unsigned int idx; 51 52 if (argc < 2) 53 return usage(argv[0]); 54 55 idx = if_nametoindex(argv[2]); 56 if (!idx) { 57 printf("Invalid device name\n"); 58 return EXIT_FAILURE; 59 } 60 61 cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY); 62 if (cg_fd < 0) { 63 printf("Failed to open cgroup path: '%s'\n", strerror(errno)); 64 return EXIT_FAILURE; 65 } 66 67 prog_fd = prog_load(idx); 68 printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf); 69 70 if (prog_fd < 0) { 71 printf("Failed to load prog: '%s'\n", strerror(errno)); 72 return EXIT_FAILURE; 73 } 74 75 ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE); 76 if (ret < 0) { 77 printf("Failed to attach prog to cgroup: '%s'\n", 78 strerror(errno)); 79 return EXIT_FAILURE; 80 } 81 82 return EXIT_SUCCESS; 83 } 84