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 0 : enum bf_verbose bf_verbose_from_str(const char *str)
42 : {
43 0 : bf_assert(str);
44 :
45 0 : for (enum bf_verbose verbose = 0; verbose < _BF_VERBOSE_MAX; ++verbose) {
46 0 : 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 12 : static error_t _bf_opts_parser(int key, char *arg, struct argp_state *state)
118 : {
119 : UNUSED(arg);
120 :
121 12 : struct bf_options *args = state->input;
122 : enum bf_verbose opt;
123 :
124 12 : switch (key) {
125 1 : case 't':
126 1 : args->transient = true;
127 1 : 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 1 : case BF_OPT_NO_NFTABLES_KEY:
137 1 : bf_info("disabling nftables support");
138 1 : args->fronts &= ~BF_FLAG(BF_FRONT_NFT);
139 1 : 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 0 : case BF_OPT_WITH_BPF_TOKEN:
145 0 : args->with_bpf_token = true;
146 0 : bf_info("using a BPF token");
147 : break;
148 0 : case BF_OPT_BPFFS_PATH:
149 0 : args->bpffs_path = arg;
150 0 : bf_info("using bpffs at %s", args->bpffs_path);
151 : break;
152 0 : case 'v':
153 0 : opt = bf_verbose_from_str(arg);
154 0 : 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 0 : bf_info("enabling verbose for '%s'", arg);
161 0 : if (opt == BF_VERBOSE_DEBUG)
162 0 : bf_log_set_level(BF_LOG_DBG);
163 0 : args->verbose |= BF_FLAG(opt);
164 0 : break;
165 : default:
166 : return ARGP_ERR_UNKNOWN;
167 : }
168 :
169 : return 0;
170 : }
171 :
172 2 : int bf_opts_init(int argc, char *argv[])
173 : {
174 2 : struct argp argp = {options, _bf_opts_parser, NULL, NULL, 0, NULL, NULL};
175 :
176 2 : return argp_parse(&argp, argc, argv, 0, 0, &_bf_opts);
177 : }
178 :
179 0 : bool bf_opts_transient(void)
180 : {
181 0 : return _bf_opts.transient;
182 : }
183 :
184 8 : bool bf_opts_persist(void)
185 : {
186 8 : return !_bf_opts.transient;
187 : }
188 :
189 0 : bool bf_opts_is_front_enabled(enum bf_front front)
190 : {
191 0 : return _bf_opts.fronts & BF_FLAG(front);
192 : }
193 :
194 4 : bool bf_opts_with_bpf_token(void)
195 : {
196 4 : return _bf_opts.with_bpf_token;
197 : }
198 :
199 0 : const char *bf_opts_bpffs_path(void)
200 : {
201 0 : return _bf_opts.bpffs_path;
202 : }
203 :
204 0 : bool bf_opts_is_verbose(enum bf_verbose opt)
205 : {
206 0 : 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 : }
|