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