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