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