Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include "opts.h"
7 : :
8 : : #include <argp.h>
9 : : #include <errno.h>
10 : : #include <limits.h>
11 : : #include <stdbool.h>
12 : : #include <stddef.h>
13 : : #include <stdint.h>
14 : : #include <stdlib.h>
15 : :
16 : : #include <bpfilter/front.h>
17 : : #include <bpfilter/helper.h>
18 : : #include <bpfilter/logger.h>
19 : :
20 : : #define BF_DEFAULT_BPFFS_PATH "/sys/fs/bpf"
21 : :
22 : : enum
23 : : {
24 : : BF_OPT_NO_IPTABLES_KEY,
25 : : BF_OPT_NO_NFTABLES_KEY,
26 : : BF_OPT_NO_CLI_KEY,
27 : : BF_OPT_WITH_BPF_TOKEN,
28 : : BF_OPT_BPFFS_PATH,
29 : : BF_OPT_VERSION,
30 : : };
31 : :
32 : : static const char *_bf_verbose_strs[] = {
33 : : [BF_VERBOSE_DEBUG] = "debug",
34 : : [BF_VERBOSE_BPF] = "bpf",
35 : : [BF_VERBOSE_BYTECODE] = "bytecode",
36 : : };
37 : :
38 : : static_assert(ARRAY_SIZE(_bf_verbose_strs) == _BF_VERBOSE_MAX,
39 : : "missing entries in _bf_verbose_strs array");
40 : :
41 : 20 : enum bf_verbose bf_verbose_from_str(const char *str)
42 : : {
43 : : bf_assert(str);
44 : :
45 [ + - ]: 20 : for (enum bf_verbose verbose = 0; verbose < _BF_VERBOSE_MAX; ++verbose) {
46 [ - + ]: 20 : if (bf_streq(_bf_verbose_strs[verbose], str))
47 : : return verbose;
48 : : }
49 : :
50 : : return -EINVAL;
51 : : }
52 : :
53 : : /**
54 : : * bpfilter runtime configuration
55 : : */
56 : : static struct bf_options
57 : : {
58 : : /** If true, bpfilter won't load or save its state to the filesystem, and
59 : : * all the loaded BPF programs will be unloaded before shuting down. Hence,
60 : : * as long as bpfilter is running, filtering rules will be applied. When
61 : : * bpfilter is stopped, everything is cleaned up.
62 : : *
63 : : * @todo Validate the daemon's behaviour when switch to and from
64 : : * ``--transient``. */
65 : : bool transient;
66 : :
67 : : /** Pass a token to BPF system calls, obtained from bpffs. */
68 : : bool with_bpf_token;
69 : :
70 : : /** Path to the bpffs to pin the BPF objects into. */
71 : : const char *bpffs_path;
72 : :
73 : : /** Bit flags for enabled fronts. */
74 : : uint16_t fronts;
75 : :
76 : : /** Verbose flags. Supported flags are:
77 : : * - @c debug Print all the debug logs.
78 : : * - @c bpf Add debug log messages in the generated BPF programs. */
79 : : uint16_t verbose;
80 : : } _bf_opts = {
81 : : .transient = false,
82 : : .with_bpf_token = false,
83 : : .bpffs_path = BF_DEFAULT_BPFFS_PATH,
84 : : .fronts = 0xffff,
85 : : .verbose = 0,
86 : : };
87 : :
88 : : static struct argp_option options[] = {
89 : : {"transient", 't', 0, 0,
90 : : "Do not load or save runtime context and remove all BPF programs on shutdown",
91 : : 0},
92 : : {"buffer-len", 'b', "BUF_LEN_POW", 0,
93 : : "DEPRECATED. Size of the BPF log buffer as a power of 2 (only used when --verbose is used). Default: 16.",
94 : : 0},
95 : : {"no-iptables", BF_OPT_NO_IPTABLES_KEY, 0, 0, "Disable iptables support",
96 : : 0},
97 : : {"no-nftables", BF_OPT_NO_NFTABLES_KEY, 0, 0, "Disable nftables support",
98 : : 0},
99 : : {"no-cli", BF_OPT_NO_CLI_KEY, 0, 0, "Disable CLI support", 0},
100 : : {"with-bpf-token", BF_OPT_WITH_BPF_TOKEN, NULL, 0,
101 : : "Use a BPF token with the bpf() system calls. The token is created from the bpffs instance mounted at /sys/fs/bpf.",
102 : : 0},
103 : : {"bpffs-path", BF_OPT_BPFFS_PATH, "BPFFS_PATH", 0,
104 : : "Path to the bpffs to pin the BPF objects into. Defaults to " BF_DEFAULT_BPFFS_PATH
105 : : ".",
106 : : 0},
107 : : {"verbose", 'v', "VERBOSE_FLAG", 0,
108 : : "Verbose flags to enable. Can be used more than once.", 0},
109 : : {0},
110 : : };
111 : :
112 : : /**
113 : : * argp callback to process command line arguments.
114 : : *
115 : : * @return 0 on succcess, non-zero on failure.
116 : : */
117 : 160 : static error_t _bf_opts_parser(int key, char *arg, struct argp_state *state)
118 : : {
119 : : UNUSED(arg);
120 : :
121 : 160 : struct bf_options *args = state->input;
122 : : enum bf_verbose opt;
123 : :
124 [ - - - - : 160 : switch (key) {
- + + +
+ ]
125 : 0 : case 't':
126 : 0 : args->transient = true;
127 : 0 : break;
128 : 0 : case 'b':
129 [ # # ]: 0 : bf_warn(
130 : : "--buffer-len is deprecated, buffer size is defined automatically");
131 : : break;
132 : 0 : case BF_OPT_NO_IPTABLES_KEY:
133 [ # # ]: 0 : bf_info("disabling iptables support");
134 : 0 : args->fronts &= ~BF_FLAG(BF_FRONT_IPT);
135 : 0 : break;
136 : 0 : case BF_OPT_NO_NFTABLES_KEY:
137 [ # # ]: 0 : bf_info("disabling nftables support");
138 : 0 : args->fronts &= ~BF_FLAG(BF_FRONT_NFT);
139 : 0 : break;
140 : 0 : case BF_OPT_NO_CLI_KEY:
141 [ # # ]: 0 : bf_info("disabling CLI support");
142 : 0 : args->fronts &= ~BF_FLAG(BF_FRONT_CLI);
143 : 0 : break;
144 : 20 : case BF_OPT_WITH_BPF_TOKEN:
145 : 20 : args->with_bpf_token = true;
146 [ - + ]: 20 : bf_info("using a BPF token");
147 : : break;
148 : 20 : case BF_OPT_BPFFS_PATH:
149 : 20 : args->bpffs_path = arg;
150 [ - + ]: 20 : bf_info("using bpffs at %s", args->bpffs_path);
151 : : break;
152 : 20 : case 'v':
153 : 20 : opt = bf_verbose_from_str(arg);
154 [ - + ]: 20 : if ((int)opt < 0) {
155 [ # # ]: 0 : return bf_err_r(
156 : : (int)opt,
157 : : "unknown --verbose option '%s', valid --verbose options: [debug, bpf, bytecode]",
158 : : arg);
159 : : }
160 [ + - ]: 20 : bf_info("enabling verbose for '%s'", arg);
161 [ + - ]: 20 : if (opt == BF_VERBOSE_DEBUG)
162 : 20 : bf_log_set_level(BF_LOG_DBG);
163 : 20 : args->verbose |= BF_FLAG(opt);
164 : 20 : break;
165 : : default:
166 : : return ARGP_ERR_UNKNOWN;
167 : : }
168 : :
169 : : return 0;
170 : : }
171 : :
172 : 20 : int bf_opts_init(int argc, char *argv[])
173 : : {
174 : 20 : struct argp argp = {options, _bf_opts_parser, NULL, NULL, 0, NULL, NULL};
175 : :
176 : 20 : return argp_parse(&argp, argc, argv, 0, 0, &_bf_opts);
177 : : }
178 : :
179 : 180 : bool bf_opts_transient(void)
180 : : {
181 : 180 : return _bf_opts.transient;
182 : : }
183 : :
184 : 196 : bool bf_opts_persist(void)
185 : : {
186 : 196 : return !_bf_opts.transient;
187 : : }
188 : :
189 : 449 : bool bf_opts_is_front_enabled(enum bf_front front)
190 : : {
191 : 449 : return _bf_opts.fronts & BF_FLAG(front);
192 : : }
193 : :
194 : 20 : bool bf_opts_with_bpf_token(void)
195 : : {
196 : 20 : return _bf_opts.with_bpf_token;
197 : : }
198 : :
199 : 205 : const char *bf_opts_bpffs_path(void)
200 : : {
201 : 205 : return _bf_opts.bpffs_path;
202 : : }
203 : :
204 : 343 : bool bf_opts_is_verbose(enum bf_verbose opt)
205 : : {
206 : 343 : return _bf_opts.verbose & BF_FLAG(opt);
207 : : }
208 : :
209 : 0 : void bf_opts_set_verbose(enum bf_verbose opt)
210 : : {
211 : 0 : _bf_opts.verbose |= BF_FLAG(opt);
212 : 0 : }
|