Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include <errno.h>
7 : :
8 : : #include <bpfilter/chain.h>
9 : : #include <bpfilter/counter.h>
10 : : #include <bpfilter/helper.h>
11 : : #include <bpfilter/hook.h>
12 : : #include <bpfilter/io.h>
13 : : #include <bpfilter/list.h>
14 : : #include <bpfilter/logger.h>
15 : : #include <bpfilter/pack.h>
16 : : #include <bpfilter/request.h>
17 : : #include <bpfilter/response.h>
18 : :
19 : : #include "bpfilter/set.h"
20 : : #include "cgen/cgen.h"
21 : : #include "cgen/handle.h"
22 : : #include "cgen/prog/link.h"
23 : : #include "cgen/prog/map.h"
24 : : #include "cgen/program.h"
25 : : #include "ctx.h"
26 : :
27 : 6 : int _bf_cli_ruleset_flush(const struct bf_request *request,
28 : : struct bf_response **response)
29 : : {
30 : : (void)request;
31 : : (void)response;
32 : :
33 : 6 : bf_ctx_flush();
34 : :
35 : 6 : return 0;
36 : : }
37 : :
38 : 4 : static int _bf_cli_ruleset_get(const struct bf_request *request,
39 : : struct bf_response **response)
40 : : {
41 : 4 : _clean_bf_list_ bf_list cgens = bf_list_default(NULL, NULL);
42 : 4 : _clean_bf_list_ bf_list chains = bf_list_default(NULL, bf_chain_pack);
43 : 4 : _clean_bf_list_ bf_list hookopts = bf_list_default(NULL, bf_hookopts_pack);
44 : 4 : _clean_bf_list_ bf_list counters =
45 : : bf_list_default(bf_list_free, bf_list_pack);
46 : 4 : _free_bf_wpack_ bf_wpack_t *pack = NULL;
47 : : int r;
48 : :
49 : : (void)request;
50 : :
51 : 4 : r = bf_wpack_new(&pack);
52 [ + - ]: 4 : if (r)
53 : : return r;
54 : :
55 : 4 : r = bf_ctx_get_cgens(&cgens);
56 [ - + ]: 4 : if (r < 0)
57 [ # # ]: 0 : return bf_err_r(r, "failed to get cgen list");
58 : :
59 [ + - + + : 18 : bf_list_foreach (&cgens, cgen_node) {
+ + ]
60 : : struct bf_cgen *cgen = bf_list_node_get_data(cgen_node);
61 : 0 : _free_bf_list_ bf_list *cgen_counters = NULL;
62 : :
63 : 5 : r = bf_list_add_tail(&chains, cgen->chain);
64 [ - + ]: 5 : if (r)
65 [ # # ]: 0 : return bf_err_r(r, "failed to add chain to list");
66 : :
67 [ + + ]: 5 : r = bf_list_add_tail(&hookopts, cgen->handle->link ?
68 : : cgen->handle->link->hookopts :
69 : : NULL);
70 [ - + ]: 5 : if (r)
71 [ # # ]: 0 : return bf_err_r(r, "failed to add hookopts to list");
72 : :
73 : 5 : r = bf_list_new(&cgen_counters,
74 : 5 : &bf_list_ops_default(bf_counter_free, bf_counter_pack));
75 [ + - ]: 5 : if (r)
76 : : return r;
77 : :
78 : 5 : r = bf_cgen_get_counters(cgen, cgen_counters);
79 [ + - ]: 5 : if (r)
80 : : return r;
81 : :
82 : 5 : r = bf_list_add_tail(&counters, cgen_counters);
83 [ + - ]: 5 : if (r)
84 : : return r;
85 : :
86 : 5 : TAKE_PTR(cgen_counters);
87 : : }
88 : :
89 : 4 : bf_wpack_open_object(pack, "ruleset");
90 : 4 : bf_wpack_kv_list(pack, "chains", &chains);
91 : 4 : bf_wpack_kv_list(pack, "hookopts", &hookopts);
92 : 4 : bf_wpack_kv_list(pack, "counters", &counters);
93 : 4 : bf_wpack_close_object(pack);
94 : :
95 : 4 : return bf_response_new_from_pack(response, pack);
96 : : }
97 : :
98 : 8 : int _bf_cli_ruleset_set(const struct bf_request *request,
99 : : struct bf_response **response)
100 : : {
101 : 8 : _clean_bf_list_ bf_list cgens = bf_list_default(NULL, NULL);
102 : 8 : _free_bf_rpack_ bf_rpack_t *pack;
103 : : bf_rpack_node_t child, node;
104 : : int r;
105 : :
106 : : assert(request);
107 : :
108 : : (void)response;
109 : :
110 : 8 : bf_ctx_flush();
111 : :
112 : 8 : r = bf_rpack_new(&pack, bf_request_data(request),
113 : : bf_request_data_len(request));
114 [ + - ]: 8 : if (r)
115 : : return r;
116 : :
117 : 8 : r = bf_rpack_kv_array(bf_rpack_root(pack), "ruleset", &child);
118 [ + - ]: 8 : if (r)
119 : : return r;
120 [ + - + + : 36 : bf_rpack_array_foreach (child, node) {
+ + ]
121 : 12 : _free_bf_cgen_ struct bf_cgen *cgen = NULL;
122 : 12 : _free_bf_chain_ struct bf_chain *chain = NULL;
123 : 2 : _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
124 : : bf_rpack_node_t child;
125 : :
126 : 12 : r = bf_rpack_kv_obj(node, "chain", &child);
127 [ - + ]: 12 : if (r)
128 : 0 : goto err_load;
129 : :
130 : 12 : r = bf_chain_new_from_pack(&chain, child);
131 [ - + ]: 12 : if (r)
132 : 0 : goto err_load;
133 : :
134 : 12 : r = bf_rpack_kv_node(node, "hookopts", &child);
135 [ - + ]: 12 : if (r)
136 : 0 : goto err_load;
137 [ + + ]: 12 : if (!bf_rpack_is_nil(child)) {
138 : 10 : r = bf_hookopts_new_from_pack(&hookopts, child);
139 [ - + ]: 10 : if (r)
140 : 0 : goto err_load;
141 : : }
142 : :
143 : 12 : r = bf_cgen_new(&cgen, &chain);
144 [ - + ]: 12 : if (r)
145 : 0 : goto err_load;
146 : :
147 : 12 : r = bf_cgen_set(cgen, bf_request_ns(request),
148 [ + + ]: 12 : hookopts ? &hookopts : NULL);
149 [ + + ]: 12 : if (r) {
150 [ + - ]: 2 : bf_err_r(r, "failed to set chain '%s'", cgen->chain->name);
151 : 2 : goto err_load;
152 : : }
153 : :
154 : 10 : r = bf_ctx_set_cgen(cgen);
155 [ - + ]: 10 : if (r) {
156 : : /* The codegen is loaded already, if the daemon runs in persistent
157 : : * mode, cleaning the codegen won't be sufficient to discard the
158 : : * chain, it must be unpinned. */
159 : 0 : bf_cgen_unload(cgen);
160 : 0 : goto err_load;
161 : : }
162 : :
163 : 10 : TAKE_PTR(cgen);
164 : : }
165 : :
166 : : return 0;
167 : :
168 : : err_load:
169 : 2 : bf_ctx_flush();
170 : 2 : return r;
171 : : }
172 : :
173 : 62 : int _bf_cli_chain_set(const struct bf_request *request,
174 : : struct bf_response **response)
175 : : {
176 : : struct bf_cgen *old_cgen;
177 : 62 : _free_bf_cgen_ struct bf_cgen *new_cgen = NULL;
178 : 62 : _free_bf_chain_ struct bf_chain *chain = NULL;
179 : 62 : _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
180 : 62 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
181 : : bf_rpack_node_t root, child;
182 : : int r;
183 : :
184 : : assert(request);
185 : :
186 : : (void)response;
187 : :
188 : 62 : r = bf_rpack_new(&pack, bf_request_data(request),
189 : : bf_request_data_len(request));
190 [ + - ]: 62 : if (r)
191 : : return r;
192 : :
193 : 62 : root = bf_rpack_root(pack);
194 : :
195 : 62 : r = bf_rpack_kv_obj(root, "chain", &child);
196 [ + - ]: 62 : if (r)
197 : : return r;
198 : 62 : r = bf_chain_new_from_pack(&chain, child);
199 [ + - ]: 62 : if (r)
200 : : return r;
201 : :
202 : 62 : r = bf_rpack_kv_node(root, "hookopts", &child);
203 [ + - ]: 62 : if (r)
204 : : return r;
205 [ + + ]: 62 : if (!bf_rpack_is_nil(child)) {
206 : 33 : r = bf_hookopts_new_from_pack(&hookopts, child);
207 [ + - ]: 33 : if (r)
208 : : return r;
209 : : }
210 : :
211 : 62 : r = bf_cgen_new(&new_cgen, &chain);
212 [ + - ]: 62 : if (r)
213 : : return r;
214 : :
215 : 62 : old_cgen = bf_ctx_get_cgen(new_cgen->chain->name);
216 [ + + ]: 62 : if (old_cgen) {
217 : : /* bf_ctx_delete_cgen() can only fail if the codegen is not found,
218 : : * but we know this codegen exist. */
219 : 23 : (void)bf_ctx_delete_cgen(old_cgen, true);
220 : : }
221 : :
222 : 62 : r = bf_cgen_set(new_cgen, bf_request_ns(request),
223 [ + + ]: 62 : hookopts ? &hookopts : NULL);
224 [ + + ]: 62 : if (r)
225 : : return r;
226 : :
227 : 59 : r = bf_ctx_set_cgen(new_cgen);
228 [ - + ]: 59 : if (r) {
229 : 0 : bf_cgen_unload(new_cgen);
230 : 0 : return r;
231 : : }
232 : :
233 : 59 : TAKE_PTR(new_cgen);
234 : :
235 : 59 : return r;
236 : : }
237 : :
238 : 36 : static int _bf_cli_chain_get(const struct bf_request *request,
239 : : struct bf_response **response)
240 : : {
241 : 36 : _clean_bf_list_ bf_list counters =
242 : : bf_list_default(bf_counter_free, bf_counter_pack);
243 : : struct bf_cgen *cgen;
244 : 36 : _cleanup_free_ char *name = NULL;
245 : 36 : _free_bf_wpack_ bf_wpack_t *wpack = NULL;
246 : 36 : _free_bf_rpack_ bf_rpack_t *rpack = NULL;
247 : : int r;
248 : :
249 : 36 : r = bf_rpack_new(&rpack, bf_request_data(request),
250 : : bf_request_data_len(request));
251 [ + - ]: 36 : if (r)
252 : : return r;
253 : :
254 : 36 : r = bf_rpack_kv_str(bf_rpack_root(rpack), "name", &name);
255 [ + - ]: 36 : if (r)
256 : : return r;
257 : :
258 : 36 : cgen = bf_ctx_get_cgen(name);
259 [ + + ]: 36 : if (!cgen)
260 [ + - ]: 1 : return bf_err_r(-ENOENT, "chain '%s' not found", name);
261 : :
262 : 35 : r = bf_cgen_get_counters(cgen, &counters);
263 [ - + ]: 35 : if (r)
264 [ # # ]: 0 : return bf_err_r(r, "failed to request counters for '%s'", name);
265 : :
266 : 35 : r = bf_wpack_new(&wpack);
267 [ + - ]: 35 : if (r)
268 : : return r;
269 : :
270 : 35 : bf_wpack_open_object(wpack, "chain");
271 : 35 : r = bf_chain_pack(cgen->chain, wpack);
272 [ + - ]: 35 : if (r)
273 : : return r;
274 : 35 : bf_wpack_close_object(wpack);
275 : :
276 [ + + ]: 35 : if (cgen->handle->link) {
277 : 28 : bf_wpack_open_object(wpack, "hookopts");
278 : 28 : r = bf_hookopts_pack(cgen->handle->link->hookopts, wpack);
279 [ + - ]: 28 : if (r)
280 : : return r;
281 : 28 : bf_wpack_close_object(wpack);
282 : : } else {
283 : 7 : bf_wpack_kv_nil(wpack, "hookopts");
284 : : }
285 : :
286 : 35 : bf_wpack_kv_list(wpack, "counters", &counters);
287 : :
288 : 35 : return bf_response_new_from_pack(response, wpack);
289 : : }
290 : :
291 : 0 : int _bf_cli_chain_prog_fd(const struct bf_request *request,
292 : : struct bf_response **response)
293 : : {
294 : : struct bf_cgen *cgen;
295 : 0 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
296 : 0 : _cleanup_free_ char *name = NULL;
297 : : int r;
298 : :
299 : : (void)response;
300 : :
301 : 0 : r = bf_rpack_new(&pack, bf_request_data(request),
302 : : bf_request_data_len(request));
303 [ # # ]: 0 : if (r)
304 : : return r;
305 : :
306 : 0 : r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
307 [ # # ]: 0 : if (r)
308 : : return r;
309 : :
310 : 0 : cgen = bf_ctx_get_cgen(name);
311 [ # # ]: 0 : if (!cgen)
312 [ # # ]: 0 : return bf_err_r(-ENOENT, "failed to find chain '%s'", name);
313 : :
314 [ # # ]: 0 : if (cgen->handle->prog_fd == -1)
315 [ # # ]: 0 : return bf_err_r(-ENODEV, "chain '%s' has no loaded program", name);
316 : :
317 : 0 : r = bf_send_fd(bf_request_fd(request), cgen->handle->prog_fd);
318 [ # # ]: 0 : if (r < 0)
319 [ # # ]: 0 : return bf_err_r(errno, "failed to send prog FD for '%s'", name);
320 : :
321 : : return 0;
322 : : }
323 : :
324 : 0 : int _bf_cli_chain_logs_fd(const struct bf_request *request,
325 : : struct bf_response **response)
326 : : {
327 : : struct bf_cgen *cgen;
328 : 0 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
329 : 0 : _cleanup_free_ char *name = NULL;
330 : : int r;
331 : :
332 : : (void)response;
333 : :
334 : 0 : r = bf_rpack_new(&pack, bf_request_data(request),
335 : : bf_request_data_len(request));
336 [ # # ]: 0 : if (r)
337 : : return r;
338 : :
339 : 0 : r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
340 [ # # ]: 0 : if (r)
341 : : return r;
342 : :
343 : 0 : cgen = bf_ctx_get_cgen(name);
344 [ # # ]: 0 : if (!cgen)
345 [ # # ]: 0 : return bf_err_r(-ENOENT, "failed to find chain '%s'", name);
346 : :
347 [ # # ]: 0 : if (!cgen->handle->lmap)
348 [ # # ]: 0 : return bf_err_r(-ENOENT, "chain '%s' has no logs buffer", name);
349 : :
350 : 0 : r = bf_send_fd(bf_request_fd(request), cgen->handle->lmap->fd);
351 [ # # ]: 0 : if (r < 0)
352 [ # # ]: 0 : return bf_err_r(errno, "failed to send logs FD for '%s'", name);
353 : :
354 : : return 0;
355 : : }
356 : :
357 : 12 : int _bf_cli_chain_load(const struct bf_request *request,
358 : : struct bf_response **response)
359 : : {
360 : 12 : _free_bf_cgen_ struct bf_cgen *cgen = NULL;
361 : 12 : _free_bf_chain_ struct bf_chain *chain = NULL;
362 : 12 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
363 : : bf_rpack_node_t child;
364 : : int r;
365 : :
366 : : assert(request);
367 : :
368 : : (void)response;
369 : :
370 : 12 : r = bf_rpack_new(&pack, bf_request_data(request),
371 : : bf_request_data_len(request));
372 [ + - ]: 12 : if (r)
373 : : return r;
374 : :
375 : 12 : r = bf_rpack_kv_obj(bf_rpack_root(pack), "chain", &child);
376 [ + - ]: 12 : if (r)
377 : : return r;
378 : 12 : r = bf_chain_new_from_pack(&chain, child);
379 [ + - ]: 12 : if (r)
380 : : return r;
381 : :
382 [ - + ]: 12 : if (bf_ctx_get_cgen(chain->name)) {
383 [ # # ]: 0 : return bf_err_r(-EEXIST,
384 : : "_bf_cli_chain_load: chain '%s' already exists",
385 : : chain->name);
386 : : }
387 : :
388 : 12 : r = bf_cgen_new(&cgen, &chain);
389 [ + - ]: 12 : if (r)
390 : : return r;
391 : :
392 : 12 : r = bf_cgen_load(cgen);
393 [ + - ]: 12 : if (r)
394 : : return r;
395 : :
396 : 12 : r = bf_ctx_set_cgen(cgen);
397 [ - + ]: 12 : if (r) {
398 : 0 : bf_cgen_unload(cgen);
399 [ # # ]: 0 : return bf_err_r(
400 : : r, "bf_ctx_set_cgen: failed to add cgen to the runtime context");
401 : : }
402 : :
403 : 12 : TAKE_PTR(cgen);
404 : :
405 : 12 : return r;
406 : : }
407 : :
408 : 11 : int _bf_cli_chain_attach(const struct bf_request *request,
409 : : struct bf_response **response)
410 : : {
411 : 11 : _free_bf_chain_ struct bf_chain *chain = NULL;
412 : 11 : _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
413 : 11 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
414 : 11 : _cleanup_free_ char *name = NULL;
415 : : struct bf_cgen *cgen = NULL;
416 : : bf_rpack_node_t child;
417 : : int r;
418 : :
419 : : assert(request);
420 : :
421 : : (void)response;
422 : :
423 : 11 : r = bf_rpack_new(&pack, bf_request_data(request),
424 : : bf_request_data_len(request));
425 [ + - ]: 11 : if (r)
426 : : return r;
427 : :
428 : 11 : r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
429 [ + - ]: 11 : if (r)
430 : : return r;
431 : :
432 : 11 : r = bf_rpack_kv_obj(bf_rpack_root(pack), "hookopts", &child);
433 [ + - ]: 11 : if (r)
434 : : return r;
435 : 11 : r = bf_hookopts_new_from_pack(&hookopts, child);
436 [ + - ]: 11 : if (r)
437 : : return r;
438 : :
439 : 11 : cgen = bf_ctx_get_cgen(name);
440 [ - + ]: 11 : if (!cgen)
441 [ # # ]: 0 : return bf_err_r(-ENOENT, "chain '%s' does not exist", name);
442 [ - + ]: 11 : if (cgen->handle->link)
443 [ # # ]: 0 : return bf_err_r(-EBUSY, "chain '%s' is already linked to a hook", name);
444 : :
445 : 11 : r = bf_hookopts_validate(hookopts, cgen->chain->hook);
446 [ + + ]: 11 : if (r)
447 [ + - ]: 1 : return bf_err_r(r, "failed to validate hook options");
448 : :
449 : 10 : r = bf_cgen_attach(cgen, bf_request_ns(request), &hookopts);
450 [ + + ]: 10 : if (r)
451 [ + - ]: 2 : return bf_err_r(r, "failed to attach codegen to hook");
452 : :
453 : : return r;
454 : : }
455 : :
456 : 7 : int _bf_cli_chain_update(const struct bf_request *request,
457 : : struct bf_response **response)
458 : : {
459 : 7 : _free_bf_chain_ struct bf_chain *chain = NULL;
460 : : struct bf_cgen *cgen = NULL;
461 : 7 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
462 : : bf_rpack_node_t child;
463 : : int r;
464 : :
465 : : assert(request);
466 : :
467 : : (void)response;
468 : :
469 : 7 : r = bf_rpack_new(&pack, bf_request_data(request),
470 : : bf_request_data_len(request));
471 [ + - ]: 7 : if (r)
472 : : return r;
473 : :
474 : 7 : r = bf_rpack_kv_obj(bf_rpack_root(pack), "chain", &child);
475 [ + - ]: 7 : if (r)
476 : : return r;
477 : 7 : r = bf_chain_new_from_pack(&chain, child);
478 [ + - ]: 7 : if (r)
479 : : return r;
480 : :
481 : 7 : cgen = bf_ctx_get_cgen(chain->name);
482 [ + + ]: 7 : if (!cgen)
483 : : return -ENOENT;
484 : :
485 : 6 : r = bf_cgen_update(cgen, &chain, 0);
486 [ - + ]: 6 : if (r)
487 : 0 : return -EINVAL;
488 : :
489 : : return r;
490 : : }
491 : :
492 : 22 : int _bf_cli_chain_flush(const struct bf_request *request,
493 : : struct bf_response **response)
494 : : {
495 : : struct bf_cgen *cgen = NULL;
496 : 22 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
497 : 22 : _cleanup_free_ char *name = NULL;
498 : : int r;
499 : :
500 : : assert(request);
501 : :
502 : : (void)response;
503 : :
504 : 22 : r = bf_rpack_new(&pack, bf_request_data(request),
505 : : bf_request_data_len(request));
506 [ + - ]: 22 : if (r)
507 : : return r;
508 : :
509 : 22 : r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
510 [ + - ]: 22 : if (r)
511 : : return r;
512 : :
513 : 22 : cgen = bf_ctx_get_cgen(name);
514 [ + - ]: 22 : if (!cgen)
515 : : return -ENOENT;
516 : :
517 : 22 : return bf_ctx_delete_cgen(cgen, true);
518 : : }
519 : :
520 : 8 : int _bf_cli_chain_update_set(const struct bf_request *request,
521 : : struct bf_response **response)
522 : : {
523 : 8 : _free_bf_set_ struct bf_set *to_add = NULL;
524 : 8 : _free_bf_set_ struct bf_set *to_remove = NULL;
525 : 8 : _free_bf_chain_ struct bf_chain *new_chain = NULL;
526 : 8 : _free_bf_rpack_ bf_rpack_t *pack = NULL;
527 : : struct bf_set *dest_set = NULL;
528 : 8 : _cleanup_free_ char *chain_name = NULL;
529 : : struct bf_cgen *cgen = NULL;
530 : : bf_rpack_node_t child;
531 : : int r;
532 : :
533 : : assert(request);
534 : :
535 : : (void)response;
536 : :
537 : 8 : r = bf_rpack_new(&pack, bf_request_data(request),
538 : : bf_request_data_len(request));
539 [ + - ]: 8 : if (r)
540 : : return r;
541 : :
542 : 8 : r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &chain_name);
543 [ + - ]: 8 : if (r)
544 : : return r;
545 : :
546 : 8 : r = bf_rpack_kv_obj(bf_rpack_root(pack), "to_add", &child);
547 [ + - ]: 8 : if (r)
548 : : return r;
549 : 8 : r = bf_set_new_from_pack(&to_add, child);
550 [ + - ]: 8 : if (r)
551 : : return r;
552 : :
553 : 8 : r = bf_rpack_kv_obj(bf_rpack_root(pack), "to_remove", &child);
554 [ + - ]: 8 : if (r)
555 : : return r;
556 : 8 : r = bf_set_new_from_pack(&to_remove, child);
557 [ + - ]: 8 : if (r)
558 : : return r;
559 : :
560 [ - + ]: 8 : if (!bf_streq(to_add->name, to_remove->name))
561 [ # # ]: 0 : return bf_err_r(-EINVAL, "to_add->name must match to_remove->name");
562 : :
563 : 8 : cgen = bf_ctx_get_cgen(chain_name);
564 [ - + ]: 8 : if (!cgen)
565 [ # # ]: 0 : return bf_err_r(-ENOENT, "chain '%s' does not exist", chain_name);
566 : :
567 : 8 : r = bf_chain_new_from_copy(&new_chain, cgen->chain);
568 [ + - ]: 8 : if (r)
569 : : return r;
570 : :
571 : 8 : dest_set = bf_chain_get_set_by_name(new_chain, to_add->name);
572 [ - + ]: 8 : if (!dest_set)
573 [ # # ]: 0 : return bf_err_r(-ENOENT, "set '%s' does not exist", to_add->name);
574 : :
575 : 8 : r = bf_set_add_many(dest_set, &to_add);
576 [ - + ]: 8 : if (r)
577 [ # # ]: 0 : return bf_err_r(r, "failed to calculate set union");
578 : :
579 : 8 : r = bf_set_remove_many(dest_set, &to_remove);
580 [ - + ]: 8 : if (r)
581 [ # # ]: 0 : return bf_err_r(r, "failed to calculate set difference");
582 : :
583 : 8 : r = bf_cgen_update(cgen, &new_chain,
584 : : BF_FLAG(BF_CGEN_UPDATE_PRESERVE_COUNTERS));
585 [ - + ]: 8 : if (r)
586 [ # # ]: 0 : return bf_err_r(r, "failed to update chain with new set data");
587 : :
588 : : return 0;
589 : : }
590 : :
591 : 176 : int bf_request_handler(const struct bf_request *request,
592 : : struct bf_response **response)
593 : : {
594 : : int r;
595 : :
596 : : assert(request);
597 : : assert(response);
598 : :
599 [ + + + + : 176 : switch (bf_request_cmd(request)) {
+ - - + +
+ + + - ]
600 : 6 : case BF_REQ_RULESET_FLUSH:
601 : 6 : r = _bf_cli_ruleset_flush(request, response);
602 : 6 : break;
603 : 8 : case BF_REQ_RULESET_SET:
604 : 8 : r = _bf_cli_ruleset_set(request, response);
605 : 8 : break;
606 : 4 : case BF_REQ_RULESET_GET:
607 : 4 : r = _bf_cli_ruleset_get(request, response);
608 : 4 : break;
609 : 62 : case BF_REQ_CHAIN_SET:
610 : 62 : r = _bf_cli_chain_set(request, response);
611 : 62 : break;
612 : 36 : case BF_REQ_CHAIN_GET:
613 : 36 : r = _bf_cli_chain_get(request, response);
614 : 36 : break;
615 : 0 : case BF_REQ_CHAIN_PROG_FD:
616 : 0 : r = _bf_cli_chain_prog_fd(request, response);
617 : 0 : break;
618 : 0 : case BF_REQ_CHAIN_LOGS_FD:
619 : 0 : r = _bf_cli_chain_logs_fd(request, response);
620 : 0 : break;
621 : 12 : case BF_REQ_CHAIN_LOAD:
622 : 12 : r = _bf_cli_chain_load(request, response);
623 : 12 : break;
624 : 11 : case BF_REQ_CHAIN_ATTACH:
625 : 11 : r = _bf_cli_chain_attach(request, response);
626 : 11 : break;
627 : 7 : case BF_REQ_CHAIN_UPDATE:
628 : 7 : r = _bf_cli_chain_update(request, response);
629 : 7 : break;
630 : 22 : case BF_REQ_CHAIN_FLUSH:
631 : 22 : r = _bf_cli_chain_flush(request, response);
632 : 22 : break;
633 : 8 : case BF_REQ_CHAIN_UPDATE_SET:
634 : 8 : r = _bf_cli_chain_update_set(request, response);
635 : 8 : break;
636 : 0 : default:
637 [ # # ]: 0 : r = bf_err_r(-EINVAL, "unsupported command %d",
638 : : bf_request_cmd(request));
639 : : break;
640 : : }
641 : :
642 : : /* If the callback don't need to send data back to the client, it can skip
643 : : * the response creation and return a status code instead (0 on success,
644 : : * negative errno value on error). The response is created based on the
645 : : * status code. */
646 [ + + ]: 176 : if (!*response) {
647 [ + + ]: 137 : if (!r)
648 : 127 : r = bf_response_new_success(response, NULL, 0);
649 : : else
650 : 10 : r = bf_response_new_failure(response, r);
651 : : }
652 : :
653 : 176 : return r;
654 : : }
|