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