LCOV - code coverage report
Current view: top level - bpfilter - xlate.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 79.9 % 318 254
Test Date: 2026-03-12 11:07:40 Functions: 84.6 % 13 11
Branches: 46.6 % 247 115

             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                 :             : }
        

Generated by: LCOV version 2.0-1