1 #include <linux/unistd.h> 2 #include <linux/bpf.h> 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <stdint.h> 7 #include <unistd.h> 8 #include <string.h> 9 #include <assert.h> 10 #include <errno.h> 11 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 15 #include <bpf/bpf.h> 16 17 #include <bpf/libbpf.h> 18 #include "bpf_insn.h" 19 #include "sock_example.h" 20 21 #define BPF_F_PIN (1 << 0) 22 #define BPF_F_GET (1 << 1) 23 #define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET) 24 25 #define BPF_F_KEY (1 << 2) 26 #define BPF_F_VAL (1 << 3) 27 #define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL) 28 29 #define BPF_M_UNSPEC 0 30 #define BPF_M_MAP 1 31 #define BPF_M_PROG 2 32 33 char bpf_log_buf[BPF_LOG_BUF_SIZE]; 34 35 static void usage(void) 36 { 37 printf("Usage: fds_example [...]\n"); 38 printf(" -F <file> File to pin/get object\n"); 39 printf(" -P |- pin object\n"); 40 printf(" -G `- get object\n"); 41 printf(" -m eBPF map mode\n"); 42 printf(" -k <key> |- map key\n"); 43 printf(" -v <value> `- map value\n"); 44 printf(" -p eBPF prog mode\n"); 45 printf(" -o <object> `- object file\n"); 46 printf(" -h Display this help.\n"); 47 } 48 49 static int bpf_prog_create(const char *object) 50 { 51 static struct bpf_insn insns[] = { 52 BPF_MOV64_IMM(BPF_REG_0, 1), 53 BPF_EXIT_INSN(), 54 }; 55 size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); 56 struct bpf_object *obj; 57 int err; 58 59 if (object) { 60 obj = bpf_object__open_file(object, NULL); 61 assert(!libbpf_get_error(obj)); 62 err = bpf_object__load(obj); 63 assert(!err); 64 return bpf_program__fd(bpf_object__next_program(obj, NULL)); 65 } else { 66 LIBBPF_OPTS(bpf_prog_load_opts, opts, 67 .log_buf = bpf_log_buf, 68 .log_size = BPF_LOG_BUF_SIZE, 69 ); 70 71 return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", 72 insns, insns_cnt, &opts); 73 } 74 } 75 76 static int bpf_do_map(const char *file, uint32_t flags, uint32_t key, 77 uint32_t value) 78 { 79 int fd, ret; 80 81 if (flags & BPF_F_PIN) { 82 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(uint32_t), 83 sizeof(uint32_t), 1024, NULL); 84 printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); 85 assert(fd > 0); 86 87 ret = bpf_obj_pin(fd, file); 88 printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 89 assert(ret == 0); 90 } else { 91 fd = bpf_obj_get(file); 92 printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 93 assert(fd > 0); 94 } 95 96 if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 97 ret = bpf_map_update_elem(fd, &key, &value, 0); 98 printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 99 ret, strerror(errno)); 100 assert(ret == 0); 101 } else if (flags & BPF_F_KEY) { 102 ret = bpf_map_lookup_elem(fd, &key, &value); 103 printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 104 ret, strerror(errno)); 105 assert(ret == 0); 106 } 107 108 return 0; 109 } 110 111 static int bpf_do_prog(const char *file, uint32_t flags, const char *object) 112 { 113 int fd, sock, ret; 114 115 if (flags & BPF_F_PIN) { 116 fd = bpf_prog_create(object); 117 printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); 118 assert(fd > 0); 119 120 ret = bpf_obj_pin(fd, file); 121 printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 122 assert(ret == 0); 123 } else { 124 fd = bpf_obj_get(file); 125 printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 126 assert(fd > 0); 127 } 128 129 sock = open_raw_sock("lo"); 130 assert(sock > 0); 131 132 ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd)); 133 printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd, 134 ret, strerror(errno)); 135 assert(ret == 0); 136 137 return 0; 138 } 139 140 int main(int argc, char **argv) 141 { 142 const char *file = NULL, *object = NULL; 143 uint32_t key = 0, value = 0, flags = 0; 144 int opt, mode = BPF_M_UNSPEC; 145 146 while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) { 147 switch (opt) { 148 /* General args */ 149 case 'F': 150 file = optarg; 151 break; 152 case 'P': 153 flags |= BPF_F_PIN; 154 break; 155 case 'G': 156 flags |= BPF_F_GET; 157 break; 158 /* Map-related args */ 159 case 'm': 160 mode = BPF_M_MAP; 161 break; 162 case 'k': 163 key = strtoul(optarg, NULL, 0); 164 flags |= BPF_F_KEY; 165 break; 166 case 'v': 167 value = strtoul(optarg, NULL, 0); 168 flags |= BPF_F_VAL; 169 break; 170 /* Prog-related args */ 171 case 'p': 172 mode = BPF_M_PROG; 173 break; 174 case 'o': 175 object = optarg; 176 break; 177 default: 178 goto out; 179 } 180 } 181 182 if (!(flags & BPF_F_PIN_GET) || !file) 183 goto out; 184 185 switch (mode) { 186 case BPF_M_MAP: 187 return bpf_do_map(file, flags, key, value); 188 case BPF_M_PROG: 189 return bpf_do_prog(file, flags, object); 190 } 191 out: 192 usage(); 193 return -1; 194 } 195