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