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

Generated by: LCOV version 2.0-1