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 "flow_dissector_load.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_prog_name; |
20 | char *cfg_path_name; |
21 | |
22 | static void load_and_attach_program(void) |
23 | { |
24 | int prog_fd, ret; |
25 | struct bpf_object *obj; |
26 | |
27 | /* Use libbpf 1.0 API mode */ |
28 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL); |
29 | |
30 | ret = bpf_flow_load(obj: &obj, path: cfg_path_name, prog_name: cfg_prog_name, |
31 | map_name: cfg_map_name, keys_map_name: NULL, prog_fd: &prog_fd, keys_fd: NULL); |
32 | if (ret) |
33 | error(1, 0, "bpf_flow_load %s" , cfg_path_name); |
34 | |
35 | ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0); |
36 | if (ret) |
37 | error(1, 0, "bpf_prog_attach %s" , cfg_path_name); |
38 | |
39 | ret = bpf_object__pin(obj, cfg_pin_path); |
40 | if (ret) |
41 | error(1, 0, "bpf_object__pin %s" , cfg_pin_path); |
42 | } |
43 | |
44 | static void detach_program(void) |
45 | { |
46 | char command[64]; |
47 | int ret; |
48 | |
49 | ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR); |
50 | if (ret) |
51 | error(1, 0, "bpf_prog_detach" ); |
52 | |
53 | /* To unpin, it is necessary and sufficient to just remove this dir */ |
54 | sprintf(command, "rm -r %s" , cfg_pin_path); |
55 | ret = system(command); |
56 | if (ret) |
57 | error(1, errno, "%s" , command); |
58 | } |
59 | |
60 | static void parse_opts(int argc, char **argv) |
61 | { |
62 | bool attach = false; |
63 | bool detach = false; |
64 | int c; |
65 | |
66 | while ((c = getopt(argc, argv, "adp:s:" )) != -1) { |
67 | switch (c) { |
68 | case 'a': |
69 | if (detach) |
70 | error(1, 0, "attach/detach are exclusive" ); |
71 | attach = true; |
72 | break; |
73 | case 'd': |
74 | if (attach) |
75 | error(1, 0, "attach/detach are exclusive" ); |
76 | detach = true; |
77 | break; |
78 | case 'p': |
79 | if (cfg_path_name) |
80 | error(1, 0, "only one path can be given" ); |
81 | |
82 | cfg_path_name = optarg; |
83 | break; |
84 | case 's': |
85 | if (cfg_prog_name) |
86 | error(1, 0, "only one prog can be given" ); |
87 | |
88 | cfg_prog_name = optarg; |
89 | break; |
90 | } |
91 | } |
92 | |
93 | if (detach) |
94 | cfg_attach = false; |
95 | |
96 | if (cfg_attach && !cfg_path_name) |
97 | error(1, 0, "must provide a path to the BPF program" ); |
98 | |
99 | if (cfg_attach && !cfg_prog_name) |
100 | error(1, 0, "must provide a section name" ); |
101 | } |
102 | |
103 | int main(int argc, char **argv) |
104 | { |
105 | parse_opts(argc, argv); |
106 | if (cfg_attach) |
107 | load_and_attach_program(); |
108 | else |
109 | detach_program(); |
110 | return 0; |
111 | } |
112 | |