LCOV - code coverage report
Current view: top level - bpfilter/xlate - cli.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 296 0
Test Date: 2025-09-30 16:37:25 Functions: 0.0 % 16 0

            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            0 : static int _bf_cli_setup(void)
      43              : {
      44            0 :     return 0;
      45              : }
      46              : 
      47            0 : static int _bf_cli_teardown(void)
      48              : {
      49            0 :     return 0;
      50              : }
      51              : 
      52            0 : int _bf_cli_ruleset_flush(const struct bf_request *request,
      53              :                           struct bf_response **response)
      54              : {
      55              :     UNUSED(request);
      56              :     UNUSED(response);
      57              : 
      58            0 :     bf_ctx_flush(BF_FRONT_CLI);
      59              : 
      60            0 :     return 0;
      61              : }
      62              : 
      63            0 : static int _bf_cli_ruleset_get(const struct bf_request *request,
      64              :                                struct bf_response **response)
      65              : {
      66            0 :     _clean_bf_list_ bf_list cgens = bf_list_default(NULL, NULL);
      67            0 :     _clean_bf_list_ bf_list chains = bf_list_default(NULL, bf_chain_pack);
      68            0 :     _clean_bf_list_ bf_list hookopts = bf_list_default(NULL, bf_hookopts_pack);
      69            0 :     _clean_bf_list_ bf_list counters =
      70              :         bf_list_default(bf_list_free, bf_list_pack);
      71            0 :     _free_bf_wpack_ bf_wpack_t *pack = NULL;
      72              :     int r;
      73              : 
      74              :     UNUSED(request);
      75              : 
      76            0 :     r = bf_wpack_new(&pack);
      77            0 :     if (r)
      78              :         return r;
      79              : 
      80            0 :     r = bf_ctx_get_cgens_for_front(&cgens, BF_FRONT_CLI);
      81            0 :     if (r < 0)
      82            0 :         return bf_err_r(r, "failed to get cgen list");
      83              : 
      84            0 :     bf_list_foreach (&cgens, cgen_node) {
      85            0 :         struct bf_cgen *cgen = bf_list_node_get_data(cgen_node);
      86            0 :         _free_bf_list_ bf_list *cgen_counters = NULL;
      87              : 
      88            0 :         r = bf_list_add_tail(&chains, cgen->chain);
      89            0 :         if (r)
      90            0 :             return bf_err_r(r, "failed to add chain to list");
      91              : 
      92            0 :         r = bf_list_add_tail(&hookopts, cgen->program->link->hookopts);
      93            0 :         if (r)
      94            0 :             return bf_err_r(r, "failed to add hookopts to list");
      95              : 
      96            0 :         r = bf_list_new(&cgen_counters,
      97            0 :                         &bf_list_ops_default(bf_counter_free, bf_counter_pack));
      98            0 :         if (r)
      99              :             return r;
     100              : 
     101            0 :         r = bf_cgen_get_counters(cgen, cgen_counters);
     102            0 :         if (r)
     103              :             return r;
     104              : 
     105            0 :         r = bf_list_add_tail(&counters, cgen_counters);
     106            0 :         if (r)
     107              :             return r;
     108              : 
     109            0 :         TAKE_PTR(cgen_counters);
     110              :     }
     111              : 
     112            0 :     bf_wpack_open_object(pack, "ruleset");
     113            0 :     bf_wpack_kv_list(pack, "chains", &chains);
     114            0 :     bf_wpack_kv_list(pack, "hookopts", &hookopts);
     115            0 :     bf_wpack_kv_list(pack, "counters", &counters);
     116            0 :     bf_wpack_close_object(pack);
     117              : 
     118            0 :     return bf_response_new_from_pack(response, pack);
     119              : }
     120              : 
     121            0 : int _bf_cli_ruleset_set(const struct bf_request *request,
     122              :                         struct bf_response **response)
     123              : {
     124            0 :     _clean_bf_list_ bf_list cgens = bf_list_default(NULL, NULL);
     125            0 :     _free_bf_rpack_ bf_rpack_t *pack;
     126              :     bf_rpack_node_t child, node;
     127              :     int r;
     128              : 
     129              :     UNUSED(response);
     130              : 
     131            0 :     bf_assert(request);
     132              : 
     133            0 :     bf_ctx_flush(BF_FRONT_CLI);
     134              : 
     135            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     136              :                      bf_request_data_len(request));
     137            0 :     if (r)
     138              :         return r;
     139              : 
     140            0 :     r = bf_rpack_kv_array(bf_rpack_root(pack), "ruleset", &child);
     141            0 :     if (r)
     142              :         return r;
     143            0 :     bf_rpack_array_foreach (child, node) {
     144            0 :         _free_bf_cgen_ struct bf_cgen *cgen = NULL;
     145            0 :         _free_bf_chain_ struct bf_chain *chain = NULL;
     146            0 :         _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
     147              :         bf_rpack_node_t child;
     148              : 
     149            0 :         r = bf_rpack_kv_obj(node, "chain", &child);
     150            0 :         if (r)
     151            0 :             goto err_load;
     152              : 
     153            0 :         r = bf_chain_new_from_pack(&chain, child);
     154            0 :         if (r)
     155            0 :             goto err_load;
     156              : 
     157            0 :         r = bf_rpack_kv_node(node, "hookopts", &child);
     158            0 :         if (r)
     159            0 :             goto err_load;
     160            0 :         if (!bf_rpack_is_nil(child)) {
     161            0 :             r = bf_hookopts_new_from_pack(&hookopts, child);
     162            0 :             if (r)
     163            0 :                 goto err_load;
     164              :         }
     165              : 
     166            0 :         r = bf_cgen_new(&cgen, BF_FRONT_CLI, &chain);
     167            0 :         if (r)
     168            0 :             goto err_load;
     169              : 
     170            0 :         r = bf_cgen_set(cgen, bf_request_ns(request),
     171            0 :                         hookopts ? &hookopts : NULL);
     172            0 :         if (r) {
     173            0 :             bf_err_r(r, "failed to set chain '%s'", cgen->chain->name);
     174            0 :             goto err_load;
     175              :         }
     176              : 
     177            0 :         r = bf_ctx_set_cgen(cgen);
     178            0 :         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            0 :         TAKE_PTR(cgen);
     187              :     }
     188              : 
     189              :     return 0;
     190              : 
     191              : err_load:
     192            0 :     bf_ctx_flush(BF_FRONT_CLI);
     193            0 :     return r;
     194              : }
     195              : 
     196            0 : int _bf_cli_chain_set(const struct bf_request *request,
     197              :                       struct bf_response **response)
     198              : {
     199              :     struct bf_cgen *old_cgen;
     200            0 :     _free_bf_cgen_ struct bf_cgen *new_cgen = NULL;
     201            0 :     _free_bf_chain_ struct bf_chain *chain = NULL;
     202            0 :     _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
     203            0 :     _free_bf_rpack_ bf_rpack_t *pack = NULL;
     204              :     bf_rpack_node_t root, child;
     205              :     int r;
     206              : 
     207              :     UNUSED(response);
     208              : 
     209            0 :     bf_assert(request);
     210              : 
     211            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     212              :                      bf_request_data_len(request));
     213            0 :     if (r)
     214              :         return r;
     215              : 
     216            0 :     root = bf_rpack_root(pack);
     217              : 
     218            0 :     r = bf_rpack_kv_obj(root, "chain", &child);
     219            0 :     if (r)
     220              :         return r;
     221            0 :     r = bf_chain_new_from_pack(&chain, child);
     222            0 :     if (r)
     223              :         return r;
     224              : 
     225            0 :     r = bf_rpack_kv_node(root, "hookopts", &child);
     226            0 :     if (r)
     227              :         return r;
     228            0 :     if (!bf_rpack_is_nil(child)) {
     229            0 :         r = bf_hookopts_new_from_pack(&hookopts, child);
     230            0 :         if (r)
     231              :             return r;
     232              :     }
     233              : 
     234            0 :     r = bf_cgen_new(&new_cgen, BF_FRONT_CLI, &chain);
     235            0 :     if (r)
     236              :         return r;
     237              : 
     238            0 :     old_cgen = bf_ctx_get_cgen(new_cgen->chain->name);
     239            0 :     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            0 :         (void)bf_ctx_delete_cgen(old_cgen, true);
     243              :     }
     244              : 
     245            0 :     r = bf_cgen_set(new_cgen, bf_request_ns(request),
     246            0 :                     hookopts ? &hookopts : NULL);
     247            0 :     if (r)
     248              :         return r;
     249              : 
     250            0 :     r = bf_ctx_set_cgen(new_cgen);
     251            0 :     if (r) {
     252            0 :         bf_cgen_unload(new_cgen);
     253            0 :         return r;
     254              :     }
     255              : 
     256            0 :     TAKE_PTR(new_cgen);
     257              : 
     258            0 :     return r;
     259              : }
     260              : 
     261            0 : static int _bf_cli_chain_get(const struct bf_request *request,
     262              :                              struct bf_response **response)
     263              : {
     264            0 :     _clean_bf_list_ bf_list counters =
     265              :         bf_list_default(bf_counter_free, bf_counter_pack);
     266              :     struct bf_cgen *cgen;
     267            0 :     _cleanup_free_ char *name = NULL;
     268            0 :     _free_bf_wpack_ bf_wpack_t *wpack = NULL;
     269            0 :     _free_bf_rpack_ bf_rpack_t *rpack = NULL;
     270              :     int r;
     271              : 
     272            0 :     r = bf_rpack_new(&rpack, bf_request_data(request),
     273              :                      bf_request_data_len(request));
     274            0 :     if (r)
     275              :         return r;
     276              : 
     277            0 :     r = bf_rpack_kv_str(bf_rpack_root(rpack), "name", &name);
     278            0 :     if (r)
     279              :         return r;
     280              : 
     281            0 :     cgen = bf_ctx_get_cgen(name);
     282            0 :     if (!cgen)
     283            0 :         return bf_err_r(-ENOENT, "chain '%s' not found", name);
     284              : 
     285            0 :     r = bf_cgen_get_counters(cgen, &counters);
     286            0 :     if (r)
     287            0 :         return bf_err_r(r, "failed to request counters for '%s'", name);
     288              : 
     289            0 :     r = bf_wpack_new(&wpack);
     290            0 :     if (r)
     291              :         return r;
     292              : 
     293            0 :     bf_wpack_open_object(wpack, "chain");
     294            0 :     r = bf_chain_pack(cgen->chain, wpack);
     295            0 :     if (r)
     296              :         return r;
     297            0 :     bf_wpack_close_object(wpack);
     298              : 
     299            0 :     if (cgen->program->link->hookopts) {
     300            0 :         bf_wpack_open_object(wpack, "hookopts");
     301            0 :         r = bf_hookopts_pack(cgen->program->link->hookopts, wpack);
     302            0 :         if (r)
     303              :             return r;
     304            0 :         bf_wpack_close_object(wpack);
     305              :     } else {
     306            0 :         bf_wpack_kv_nil(wpack, "hookopts");
     307              :     }
     308              : 
     309            0 :     bf_wpack_kv_list(wpack, "counters", &counters);
     310              : 
     311            0 :     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            0 : int _bf_cli_chain_load(const struct bf_request *request,
     381              :                        struct bf_response **response)
     382              : {
     383            0 :     _free_bf_cgen_ struct bf_cgen *cgen = NULL;
     384            0 :     _free_bf_chain_ struct bf_chain *chain = NULL;
     385            0 :     _free_bf_rpack_ bf_rpack_t *pack = NULL;
     386              :     bf_rpack_node_t child;
     387              :     int r;
     388              : 
     389              :     UNUSED(response);
     390              : 
     391            0 :     bf_assert(request);
     392              : 
     393            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     394              :                      bf_request_data_len(request));
     395            0 :     if (r)
     396              :         return r;
     397              : 
     398            0 :     r = bf_rpack_kv_obj(bf_rpack_root(pack), "chain", &child);
     399            0 :     if (r)
     400              :         return r;
     401            0 :     r = bf_chain_new_from_pack(&chain, child);
     402            0 :     if (r)
     403              :         return r;
     404              : 
     405            0 :     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            0 :     r = bf_cgen_new(&cgen, BF_FRONT_CLI, &chain);
     412            0 :     if (r)
     413              :         return r;
     414              : 
     415            0 :     r = bf_cgen_load(cgen);
     416            0 :     if (r)
     417              :         return r;
     418              : 
     419            0 :     r = bf_ctx_set_cgen(cgen);
     420            0 :     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            0 :     TAKE_PTR(cgen);
     427              : 
     428            0 :     return r;
     429              : }
     430              : 
     431            0 : int _bf_cli_chain_attach(const struct bf_request *request,
     432              :                          struct bf_response **response)
     433              : {
     434            0 :     _free_bf_chain_ struct bf_chain *chain = NULL;
     435            0 :     _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
     436            0 :     _free_bf_rpack_ bf_rpack_t *pack = NULL;
     437            0 :     _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            0 :     bf_assert(request);
     445              : 
     446            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     447              :                      bf_request_data_len(request));
     448            0 :     if (r)
     449              :         return r;
     450              : 
     451            0 :     r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
     452            0 :     if (r)
     453              :         return r;
     454              : 
     455            0 :     r = bf_rpack_kv_obj(bf_rpack_root(pack), "hookopts", &child);
     456            0 :     if (r)
     457              :         return r;
     458            0 :     r = bf_hookopts_new_from_pack(&hookopts, child);
     459            0 :     if (r)
     460              :         return r;
     461              : 
     462            0 :     cgen = bf_ctx_get_cgen(name);
     463            0 :     if (!cgen)
     464            0 :         return bf_err_r(-ENOENT, "chain '%s' does not exist", name);
     465            0 :     if (cgen->program->link->hookopts)
     466            0 :         return bf_err_r(-EBUSY, "chain '%s' is already linked to a hook", name);
     467              : 
     468            0 :     r = bf_hookopts_validate(hookopts, cgen->chain->hook);
     469            0 :     if (r)
     470            0 :         return bf_err_r(r, "failed to validate hook options");
     471              : 
     472            0 :     r = bf_cgen_attach(cgen, bf_request_ns(request), &hookopts);
     473            0 :     if (r)
     474            0 :         return bf_err_r(r, "failed to attach codegen to hook");
     475              : 
     476              :     return r;
     477              : }
     478              : 
     479            0 : int _bf_cli_chain_update(const struct bf_request *request,
     480              :                          struct bf_response **response)
     481              : {
     482            0 :     _free_bf_chain_ struct bf_chain *chain = NULL;
     483              :     struct bf_cgen *cgen = NULL;
     484            0 :     _free_bf_rpack_ bf_rpack_t *pack = NULL;
     485              :     bf_rpack_node_t child;
     486              :     int r;
     487              : 
     488              :     UNUSED(response);
     489              : 
     490            0 :     bf_assert(request);
     491              : 
     492            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     493              :                      bf_request_data_len(request));
     494            0 :     if (r)
     495              :         return r;
     496              : 
     497            0 :     r = bf_rpack_kv_obj(bf_rpack_root(pack), "chain", &child);
     498            0 :     if (r)
     499              :         return r;
     500            0 :     r = bf_chain_new_from_pack(&chain, child);
     501            0 :     if (r)
     502              :         return r;
     503              : 
     504            0 :     cgen = bf_ctx_get_cgen(chain->name);
     505            0 :     if (!cgen)
     506              :         return -ENOENT;
     507              : 
     508            0 :     if (!cgen->program->link->hookopts) {
     509            0 :         return bf_err_r(-EINVAL, "chain '%s' is not attached", chain->name);
     510              :     }
     511              : 
     512            0 :     r = bf_cgen_update(cgen, &chain);
     513            0 :     if (r)
     514              :         return -EINVAL;
     515              : 
     516              :     return r;
     517              : }
     518              : 
     519            0 : int _bf_cli_chain_flush(const struct bf_request *request,
     520              :                         struct bf_response **response)
     521              : {
     522              :     struct bf_cgen *cgen = NULL;
     523            0 :     _free_bf_rpack_ bf_rpack_t *pack = NULL;
     524            0 :     _cleanup_free_ char *name = NULL;
     525              :     int r;
     526              : 
     527              :     UNUSED(response);
     528              : 
     529            0 :     bf_assert(request);
     530              : 
     531            0 :     r = bf_rpack_new(&pack, bf_request_data(request),
     532              :                      bf_request_data_len(request));
     533            0 :     if (r)
     534              :         return r;
     535              : 
     536            0 :     r = bf_rpack_kv_str(bf_rpack_root(pack), "name", &name);
     537            0 :     if (r)
     538              :         return r;
     539              : 
     540            0 :     cgen = bf_ctx_get_cgen(name);
     541            0 :     if (!cgen)
     542              :         return -ENOENT;
     543              : 
     544            0 :     return bf_ctx_delete_cgen(cgen, true);
     545              : }
     546              : 
     547            0 : static int _bf_cli_request_handler(const struct bf_request *request,
     548              :                                    struct bf_response **response)
     549              : {
     550              :     int r;
     551              : 
     552            0 :     bf_assert(request);
     553            0 :     bf_assert(response);
     554              : 
     555            0 :     switch (bf_request_cmd(request)) {
     556            0 :     case BF_REQ_RULESET_FLUSH:
     557            0 :         r = _bf_cli_ruleset_flush(request, response);
     558            0 :         break;
     559            0 :     case BF_REQ_RULESET_SET:
     560            0 :         r = _bf_cli_ruleset_set(request, response);
     561            0 :         break;
     562            0 :     case BF_REQ_RULESET_GET:
     563            0 :         r = _bf_cli_ruleset_get(request, response);
     564            0 :         break;
     565            0 :     case BF_REQ_CHAIN_SET:
     566            0 :         r = _bf_cli_chain_set(request, response);
     567            0 :         break;
     568            0 :     case BF_REQ_CHAIN_GET:
     569            0 :         r = _bf_cli_chain_get(request, response);
     570            0 :         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            0 :     case BF_REQ_CHAIN_LOAD:
     578            0 :         r = _bf_cli_chain_load(request, response);
     579            0 :         break;
     580            0 :     case BF_REQ_CHAIN_ATTACH:
     581            0 :         r = _bf_cli_chain_attach(request, response);
     582            0 :         break;
     583            0 :     case BF_REQ_CHAIN_UPDATE:
     584            0 :         r = _bf_cli_chain_update(request, response);
     585            0 :         break;
     586            0 :     case BF_REQ_CHAIN_FLUSH:
     587            0 :         r = _bf_cli_chain_flush(request, response);
     588            0 :         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            0 :     if (!*response) {
     600            0 :         if (!r)
     601            0 :             r = bf_response_new_success(response, NULL, 0);
     602              :         else
     603            0 :             r = bf_response_new_failure(response, r);
     604              :     }
     605              : 
     606            0 :     return r;
     607              : }
     608              : 
     609            0 : static int _bf_cli_pack(bf_wpack_t *pack)
     610              : {
     611              :     UNUSED(pack);
     612              : 
     613            0 :     return 0;
     614              : }
     615              : 
     616            0 : static int _bf_cli_unpack(bf_rpack_node_t node)
     617              : {
     618              :     UNUSED(node);
     619              : 
     620            0 :     return 0;
     621              : }
        

Generated by: LCOV version 2.0-1