1 // SPDX-License-Identifier: GPL-2.0 2 #include <error.h> 3 #include <errno.h> 4 #include <getopt.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/stat.h> 9 #include <fcntl.h> 10 #include <unistd.h> 11 #include <bpf/bpf.h> 12 #include <bpf/libbpf.h> 13 14 #include "bpf_rlimit.h" 15 16 const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector"; 17 const char *cfg_map_name = "jmp_table"; 18 bool cfg_attach = true; 19 char *cfg_section_name; 20 char *cfg_path_name; 21 22 static void load_and_attach_program(void) 23 { 24 struct bpf_program *prog, *main_prog; 25 struct bpf_map *prog_array; 26 int i, fd, prog_fd, ret; 27 struct bpf_object *obj; 28 int prog_array_fd; 29 30 ret = bpf_prog_load(cfg_path_name, BPF_PROG_TYPE_FLOW_DISSECTOR, &obj, 31 &prog_fd); 32 if (ret) 33 error(1, 0, "bpf_prog_load %s", cfg_path_name); 34 35 main_prog = bpf_object__find_program_by_title(obj, cfg_section_name); 36 if (!main_prog) 37 error(1, 0, "bpf_object__find_program_by_title %s", 38 cfg_section_name); 39 40 prog_fd = bpf_program__fd(main_prog); 41 if (prog_fd < 0) 42 error(1, 0, "bpf_program__fd"); 43 44 prog_array = bpf_object__find_map_by_name(obj, cfg_map_name); 45 if (!prog_array) 46 error(1, 0, "bpf_object__find_map_by_name %s", cfg_map_name); 47 48 prog_array_fd = bpf_map__fd(prog_array); 49 if (prog_array_fd < 0) 50 error(1, 0, "bpf_map__fd %s", cfg_map_name); 51 52 i = 0; 53 bpf_object__for_each_program(prog, obj) { 54 fd = bpf_program__fd(prog); 55 if (fd < 0) 56 error(1, 0, "bpf_program__fd"); 57 58 if (fd != prog_fd) { 59 printf("%d: %s\n", i, bpf_program__title(prog, false)); 60 bpf_map_update_elem(prog_array_fd, &i, &fd, BPF_ANY); 61 ++i; 62 } 63 } 64 65 ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0); 66 if (ret) 67 error(1, 0, "bpf_prog_attach %s", cfg_path_name); 68 69 ret = bpf_object__pin(obj, cfg_pin_path); 70 if (ret) 71 error(1, 0, "bpf_object__pin %s", cfg_pin_path); 72 73 } 74 75 static void detach_program(void) 76 { 77 char command[64]; 78 int ret; 79 80 ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR); 81 if (ret) 82 error(1, 0, "bpf_prog_detach"); 83 84 /* To unpin, it is necessary and sufficient to just remove this dir */ 85 sprintf(command, "rm -r %s", cfg_pin_path); 86 ret = system(command); 87 if (ret) 88 error(1, errno, command); 89 } 90 91 static void parse_opts(int argc, char **argv) 92 { 93 bool attach = false; 94 bool detach = false; 95 int c; 96 97 while ((c = getopt(argc, argv, "adp:s:")) != -1) { 98 switch (c) { 99 case 'a': 100 if (detach) 101 error(1, 0, "attach/detach are exclusive"); 102 attach = true; 103 break; 104 case 'd': 105 if (attach) 106 error(1, 0, "attach/detach are exclusive"); 107 detach = true; 108 break; 109 case 'p': 110 if (cfg_path_name) 111 error(1, 0, "only one prog name can be given"); 112 113 cfg_path_name = optarg; 114 break; 115 case 's': 116 if (cfg_section_name) 117 error(1, 0, "only one section can be given"); 118 119 cfg_section_name = optarg; 120 break; 121 } 122 } 123 124 if (detach) 125 cfg_attach = false; 126 127 if (cfg_attach && !cfg_path_name) 128 error(1, 0, "must provide a path to the BPF program"); 129 130 if (cfg_attach && !cfg_section_name) 131 error(1, 0, "must provide a section name"); 132 } 133 134 int main(int argc, char **argv) 135 { 136 parse_opts(argc, argv); 137 if (cfg_attach) 138 load_and_attach_program(); 139 else 140 detach_program(); 141 return 0; 142 } 143