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