LCOV - code coverage report
Current view: top level - libbpfilter - cli.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 288 0
Test Date: 2025-08-19 17:27:08 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-2.0-only */
       2              : /*
       3              :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4              :  */
       5              : 
       6              : #include <errno.h>
       7              : #include <string.h>
       8              : 
       9              : #include "core/chain.h"
      10              : #include "core/counter.h"
      11              : #include "core/front.h"
      12              : #include "core/helper.h"
      13              : #include "core/hook.h"
      14              : #include "core/io.h"
      15              : #include "core/list.h"
      16              : #include "core/logger.h"
      17              : #include "core/marsh.h"
      18              : #include "core/request.h"
      19              : #include "core/response.h"
      20              : #include "core/rule.h"
      21              : #include "libbpfilter/generic.h"
      22              : 
      23            0 : int bf_ruleset_get(bf_list *chains, bf_list *hookopts, bf_list *counters)
      24              : {
      25            0 :     _free_bf_request_ struct bf_request *request = NULL;
      26            0 :     _free_bf_response_ struct bf_response *response = NULL;
      27            0 :     _clean_bf_list_ bf_list _chains = bf_list_default_from(*chains);
      28            0 :     _clean_bf_list_ bf_list _hookopts = bf_list_default_from(*hookopts);
      29            0 :     _clean_bf_list_ bf_list _counters = bf_list_default_from(*counters);
      30              :     struct bf_marsh *marsh = NULL;
      31              :     struct bf_marsh *child = NULL;
      32              :     int r;
      33              : 
      34            0 :     r = bf_request_new(&request, NULL, 0);
      35            0 :     if (r < 0)
      36            0 :         return bf_err_r(r, "failed to init request");
      37              : 
      38            0 :     request->front = BF_FRONT_CLI;
      39            0 :     request->cmd = BF_REQ_RULESET_GET;
      40              : 
      41            0 :     r = bf_send(request, &response);
      42            0 :     if (r < 0)
      43            0 :         return bf_err_r(r, "failed to send a ruleset get request");
      44              : 
      45            0 :     if (response->type == BF_RES_FAILURE)
      46            0 :         return response->error;
      47              : 
      48            0 :     if (response->data_len == 0)
      49              :         return 0;
      50              : 
      51            0 :     marsh = (struct bf_marsh *)response->data;
      52              : 
      53            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
      54              :         return -EINVAL;
      55            0 :     for (struct bf_marsh *schild = bf_marsh_next_child(child, NULL); schild;
      56            0 :          schild = bf_marsh_next_child(child, schild)) {
      57            0 :         _free_bf_chain_ struct bf_chain *chain = NULL;
      58              : 
      59            0 :         r = bf_chain_new_from_marsh(&chain, schild);
      60            0 :         if (r)
      61              :             return r;
      62              : 
      63            0 :         r = bf_list_add_tail(&_chains, chain);
      64            0 :         if (r)
      65              :             return r;
      66              : 
      67            0 :         TAKE_PTR(chain);
      68              :     }
      69              : 
      70            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
      71              :         return -EINVAL;
      72            0 :     for (struct bf_marsh *schild = bf_marsh_next_child(child, NULL); schild;
      73            0 :          schild = bf_marsh_next_child(child, schild)) {
      74            0 :         _free_bf_hookopts_ struct bf_hookopts *hookopts = NULL;
      75              : 
      76            0 :         if (!bf_marsh_is_empty(schild)) {
      77            0 :             r = bf_hookopts_new_from_marsh(&hookopts, schild);
      78            0 :             if (r)
      79              :                 return r;
      80              :         }
      81              : 
      82            0 :         r = bf_list_add_tail(&_hookopts, hookopts);
      83            0 :         if (r)
      84              :             return r;
      85              : 
      86            0 :         TAKE_PTR(hookopts);
      87              :     }
      88              : 
      89            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
      90              :         return -EINVAL;
      91            0 :     for (struct bf_marsh *schild = bf_marsh_next_child(child, NULL); schild;
      92            0 :          schild = bf_marsh_next_child(child, schild)) {
      93            0 :         _free_bf_list_ bf_list *nested = NULL;
      94              : 
      95            0 :         r = bf_list_new(
      96            0 :             &nested, &bf_list_ops_default(bf_counter_free, bf_counter_marsh));
      97            0 :         if (r)
      98              :             return r;
      99              : 
     100            0 :         for (struct bf_marsh *counter_marsh = bf_marsh_next_child(schild, NULL);
     101            0 :              counter_marsh;
     102            0 :              counter_marsh = bf_marsh_next_child(schild, counter_marsh)) {
     103            0 :             _free_bf_counter_ struct bf_counter *counter = NULL;
     104              : 
     105            0 :             r = bf_counter_new_from_marsh(&counter, counter_marsh);
     106            0 :             if (r)
     107              :                 return r;
     108              : 
     109            0 :             r = bf_list_add_tail(nested, counter);
     110            0 :             if (r)
     111              :                 return r;
     112              : 
     113            0 :             TAKE_PTR(counter);
     114              :         }
     115              : 
     116            0 :         r = bf_list_add_tail(&_counters, nested);
     117            0 :         if (r)
     118              :             return r;
     119              : 
     120            0 :         TAKE_PTR(nested);
     121              :     }
     122              : 
     123            0 :     *chains = bf_list_move(_chains);
     124            0 :     *hookopts = bf_list_move(_hookopts);
     125            0 :     *counters = bf_list_move(_counters);
     126              : 
     127            0 :     return 0;
     128              : }
     129              : 
     130            0 : int bf_ruleset_flush(void)
     131              : {
     132            0 :     _free_bf_request_ struct bf_request *request = NULL;
     133            0 :     _free_bf_response_ struct bf_response *response = NULL;
     134              :     int r;
     135              : 
     136            0 :     r = bf_request_new(&request, NULL, 0);
     137            0 :     if (r)
     138            0 :         return bf_err_r(r, "failed to create a ruleset flush request");
     139              : 
     140            0 :     request->front = BF_FRONT_CLI;
     141            0 :     request->cmd = BF_REQ_RULESET_FLUSH;
     142              : 
     143            0 :     r = bf_send(request, &response);
     144            0 :     if (r)
     145            0 :         return bf_err_r(r, "failed to send a ruleset flush request");
     146              : 
     147            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     148              : }
     149              : 
     150            0 : int bf_ruleset_set(bf_list *chains, bf_list *hookopts)
     151              : {
     152            0 :     _free_bf_request_ struct bf_request *request = NULL;
     153            0 :     _free_bf_response_ struct bf_response *response = NULL;
     154            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     155            0 :     struct bf_list_node *chain_node = bf_list_get_head(chains);
     156            0 :     struct bf_list_node *hookopts_node = bf_list_get_head(hookopts);
     157              :     int r;
     158              : 
     159            0 :     if (bf_list_size(chains) != bf_list_size(hookopts))
     160              :         return -EINVAL;
     161              : 
     162            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     163            0 :     if (r)
     164              :         return r;
     165              : 
     166            0 :     while (chain_node && hookopts_node) {
     167            0 :         _free_bf_marsh_ struct bf_marsh *chain_marsh = NULL;
     168            0 :         _free_bf_marsh_ struct bf_marsh *hook_marsh = NULL;
     169            0 :         _free_bf_marsh_ struct bf_marsh *_marsh = NULL;
     170            0 :         struct bf_chain *chain = bf_list_node_get_data(chain_node);
     171            0 :         struct bf_hookopts *hookopts = bf_list_node_get_data(hookopts_node);
     172              : 
     173            0 :         r = bf_marsh_new(&_marsh, NULL, 0);
     174            0 :         if (r)
     175              :             return r;
     176              : 
     177            0 :         r = bf_chain_marsh(chain, &chain_marsh);
     178            0 :         if (r)
     179              :             return r;
     180              : 
     181            0 :         r = bf_marsh_add_child_obj(&_marsh, chain_marsh);
     182            0 :         if (r)
     183              :             return r;
     184              : 
     185            0 :         if (hookopts) {
     186            0 :             r = bf_hookopts_marsh(hookopts, &hook_marsh);
     187            0 :             if (r)
     188              :                 return r;
     189              : 
     190            0 :             r = bf_marsh_add_child_obj(&_marsh, hook_marsh);
     191            0 :             if (r)
     192              :                 return r;
     193              :         } else {
     194            0 :             r = bf_marsh_add_child_raw(&_marsh, NULL, 0);
     195            0 :             if (r)
     196              :                 return r;
     197              :         }
     198              : 
     199            0 :         r = bf_marsh_add_child_obj(&marsh, _marsh);
     200            0 :         if (r)
     201              :             return r;
     202              : 
     203            0 :         chain_node = bf_list_node_next(chain_node);
     204            0 :         hookopts_node = bf_list_node_next(hookopts_node);
     205              :     }
     206              : 
     207            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     208            0 :     if (r)
     209            0 :         return bf_err_r(r, "failed to create request for chain");
     210              : 
     211            0 :     request->front = BF_FRONT_CLI;
     212            0 :     request->cmd = BF_REQ_RULESET_SET;
     213              : 
     214            0 :     r = bf_send(request, &response);
     215            0 :     if (r)
     216            0 :         return bf_err_r(r, "failed to send chain to the daemon");
     217              : 
     218            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     219              : }
     220              : 
     221            0 : int bf_chain_set(struct bf_chain *chain, struct bf_hookopts *hookopts)
     222              : {
     223            0 :     _free_bf_request_ struct bf_request *request = NULL;
     224            0 :     _free_bf_response_ struct bf_response *response = NULL;
     225            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     226            0 :     _free_bf_marsh_ struct bf_marsh *chain_marsh = NULL;
     227            0 :     _free_bf_marsh_ struct bf_marsh *hook_marsh = NULL;
     228              :     int r;
     229              : 
     230            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     231            0 :     if (r)
     232              :         return r;
     233              : 
     234            0 :     r = bf_chain_marsh(chain, &chain_marsh);
     235            0 :     if (r)
     236              :         return r;
     237              : 
     238            0 :     r = bf_marsh_add_child_obj(&marsh, chain_marsh);
     239            0 :     if (r)
     240              :         return r;
     241              : 
     242            0 :     if (hookopts) {
     243            0 :         r = bf_hookopts_marsh(hookopts, &hook_marsh);
     244            0 :         if (r)
     245              :             return r;
     246              : 
     247            0 :         r = bf_marsh_add_child_obj(&marsh, hook_marsh);
     248            0 :         if (r)
     249              :             return r;
     250              :     } else {
     251            0 :         r = bf_marsh_add_child_raw(&marsh, NULL, 0);
     252            0 :         if (r)
     253              :             return r;
     254              :     }
     255              : 
     256            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     257            0 :     if (r)
     258            0 :         return bf_err_r(r, "bf_chain_set: failed to create request");
     259              : 
     260            0 :     request->front = BF_FRONT_CLI;
     261            0 :     request->cmd = BF_REQ_CHAIN_SET;
     262              : 
     263            0 :     r = bf_send(request, &response);
     264            0 :     if (r)
     265            0 :         return bf_err_r(r, "bf_chain_set: failed to send request");
     266              : 
     267            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     268              : }
     269              : 
     270            0 : int bf_chain_get(const char *name, struct bf_chain **chain,
     271              :                  struct bf_hookopts **hookopts, bf_list *counters)
     272              : {
     273            0 :     _free_bf_request_ struct bf_request *request = NULL;
     274            0 :     _free_bf_response_ struct bf_response *response = NULL;
     275            0 :     _free_bf_chain_ struct bf_chain *_chain = NULL;
     276            0 :     _free_bf_hookopts_ struct bf_hookopts *_hookopts = NULL;
     277            0 :     _clean_bf_list_ bf_list _counters = bf_list_default_from(*counters);
     278              :     struct bf_marsh *marsh, *child = NULL;
     279            0 :     _free_bf_marsh_ struct bf_marsh *req_marsh = NULL;
     280              :     int r;
     281              : 
     282            0 :     r = bf_marsh_new(&req_marsh, NULL, 0);
     283            0 :     if (r)
     284              :         return r;
     285              : 
     286            0 :     r = bf_marsh_add_child_raw(&req_marsh, name, strlen(name) + 1);
     287            0 :     if (r)
     288              :         return r;
     289              : 
     290            0 :     r = bf_request_new(&request, req_marsh, bf_marsh_size(req_marsh));
     291            0 :     if (r < 0)
     292            0 :         return bf_err_r(r, "failed to init request");
     293              : 
     294            0 :     request->front = BF_FRONT_CLI;
     295            0 :     request->cmd = BF_REQ_CHAIN_GET;
     296              : 
     297            0 :     r = bf_send(request, &response);
     298            0 :     if (r < 0)
     299            0 :         return bf_err_r(r, "failed to send a ruleset get request");
     300              : 
     301            0 :     if (response->type == BF_RES_FAILURE)
     302            0 :         return response->error;
     303              : 
     304            0 :     marsh = (struct bf_marsh *)response->data;
     305            0 :     if (bf_marsh_size(marsh) != response->data_len) {
     306            0 :         return bf_err_r(
     307              :             -EINVAL,
     308              :             "response payload is expected to have the same size as the marsh");
     309              :     }
     310              : 
     311            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
     312              :         return -EINVAL;
     313            0 :     r = bf_chain_new_from_marsh(&_chain, child);
     314            0 :     if (r)
     315              :         return r;
     316              : 
     317            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
     318              :         return -EINVAL;
     319            0 :     if (child->data_len) {
     320            0 :         r = bf_hookopts_new_from_marsh(&_hookopts, child);
     321            0 :         if (r)
     322              :             return r;
     323              :     }
     324              : 
     325            0 :     if (!(child = bf_marsh_next_child(marsh, child)))
     326              :         return -EINVAL;
     327            0 :     for (struct bf_marsh *counter_marsh = bf_marsh_next_child(child, NULL);
     328            0 :          counter_marsh;
     329            0 :          counter_marsh = bf_marsh_next_child(child, counter_marsh)) {
     330            0 :         _free_bf_counter_ struct bf_counter *counter = NULL;
     331              : 
     332            0 :         r = bf_counter_new_from_marsh(&counter, counter_marsh);
     333            0 :         if (r)
     334              :             return r;
     335              : 
     336            0 :         r = bf_list_add_tail(&_counters, counter);
     337            0 :         if (r)
     338              :             return r;
     339              : 
     340            0 :         TAKE_PTR(counter);
     341              :     }
     342              : 
     343            0 :     *chain = TAKE_PTR(_chain);
     344            0 :     *hookopts = TAKE_PTR(_hookopts);
     345            0 :     *counters = bf_list_move(_counters);
     346              : 
     347            0 :     return 0;
     348              : }
     349              : 
     350            0 : int bf_chain_logs_fd(const char *name)
     351              : {
     352            0 :     _free_bf_request_ struct bf_request *request = NULL;
     353            0 :     _free_bf_response_ struct bf_response *response = NULL;
     354            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     355            0 :     _cleanup_close_ int fd = -1;
     356              :     int r;
     357              : 
     358            0 :     if (!name)
     359              :         return -EINVAL;
     360              : 
     361            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     362            0 :     if (r)
     363              :         return r;
     364              : 
     365            0 :     r = bf_marsh_add_child_raw(&marsh, name, strlen(name) + 1);
     366            0 :     if (r)
     367              :         return r;
     368              : 
     369            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     370            0 :     if (r < 0)
     371            0 :         return bf_err_r(r, "failed to init request");
     372              : 
     373            0 :     request->front = BF_FRONT_CLI;
     374            0 :     request->cmd = BF_REQ_CHAIN_LOGS_FD;
     375              : 
     376            0 :     fd = bf_send_with_fd(request, &response);
     377            0 :     if (fd < 0)
     378            0 :         return bf_err_r(fd, "failed to request logs FD from the daemon");
     379              : 
     380            0 :     if (response->type == BF_RES_FAILURE)
     381            0 :         return bf_err_r(response->error, "BF_REQ_CHAIN_LOGS failed");
     382              : 
     383            0 :     return TAKE_FD(fd);
     384              : }
     385              : 
     386            0 : int bf_chain_load(struct bf_chain *chain)
     387              : {
     388            0 :     _free_bf_request_ struct bf_request *request = NULL;
     389            0 :     _free_bf_response_ struct bf_response *response = NULL;
     390            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     391              :     int r;
     392              : 
     393            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     394            0 :     if (r)
     395              :         return r;
     396              : 
     397              :     {
     398            0 :         _free_bf_marsh_ struct bf_marsh *child = NULL;
     399              : 
     400            0 :         r = bf_chain_marsh(chain, &child);
     401            0 :         if (r)
     402              :             return r;
     403              : 
     404            0 :         r = bf_marsh_add_child_obj(&marsh, child);
     405            0 :         if (r)
     406              :             return r;
     407              :     }
     408              : 
     409            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     410            0 :     if (r)
     411            0 :         return bf_err_r(r, "bf_chain_load: failed to create a new request");
     412              : 
     413            0 :     request->front = BF_FRONT_CLI;
     414            0 :     request->cmd = BF_REQ_CHAIN_LOAD;
     415              : 
     416            0 :     r = bf_send(request, &response);
     417            0 :     if (r)
     418            0 :         return bf_err_r(r, "bf_chain_set: failed to send request");
     419              : 
     420            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     421              : }
     422              : 
     423            0 : int bf_chain_attach(const char *name, const struct bf_hookopts *hookopts)
     424              : {
     425            0 :     _free_bf_request_ struct bf_request *request = NULL;
     426            0 :     _free_bf_response_ struct bf_response *response = NULL;
     427            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     428              :     int r;
     429              : 
     430            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     431            0 :     if (r)
     432              :         return r;
     433              : 
     434            0 :     r = bf_marsh_add_child_raw(&marsh, name, strlen(name) + 1);
     435            0 :     if (r)
     436              :         return r;
     437              : 
     438              :     {
     439            0 :         _free_bf_marsh_ struct bf_marsh *child = NULL;
     440              : 
     441            0 :         r = bf_hookopts_marsh(hookopts, &child);
     442            0 :         if (r)
     443              :             return r;
     444              : 
     445            0 :         r = bf_marsh_add_child_obj(&marsh, child);
     446            0 :         if (r)
     447              :             return r;
     448              :     }
     449              : 
     450            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     451            0 :     if (r)
     452            0 :         return bf_err_r(r, "bf_chain_attach: failed to create a new request");
     453              : 
     454            0 :     request->front = BF_FRONT_CLI;
     455            0 :     request->cmd = BF_REQ_CHAIN_ATTACH;
     456              : 
     457            0 :     r = bf_send(request, &response);
     458            0 :     if (r)
     459            0 :         return bf_err_r(r, "bf_chain_attach: failed to send request");
     460              : 
     461            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     462              : }
     463              : 
     464            0 : int bf_chain_update(const struct bf_chain *chain)
     465              : {
     466            0 :     _free_bf_request_ struct bf_request *request = NULL;
     467            0 :     _free_bf_response_ struct bf_response *response = NULL;
     468            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     469            0 :     _free_bf_marsh_ struct bf_marsh *child = NULL;
     470              :     int r;
     471              : 
     472            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     473            0 :     if (r)
     474              :         return r;
     475              : 
     476            0 :     r = bf_chain_marsh(chain, &child);
     477            0 :     if (r)
     478              :         return r;
     479              : 
     480            0 :     r = bf_marsh_add_child_obj(&marsh, child);
     481            0 :     if (r)
     482              :         return r;
     483              : 
     484            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     485            0 :     if (r)
     486            0 :         return bf_err_r(r, "bf_chain_update: failed to create a new request");
     487              : 
     488            0 :     request->front = BF_FRONT_CLI;
     489            0 :     request->cmd = BF_REQ_CHAIN_UPDATE;
     490              : 
     491            0 :     r = bf_send(request, &response);
     492            0 :     if (r)
     493            0 :         return bf_err_r(r, "bf_chain_update: failed to send request");
     494              : 
     495            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     496              : }
     497              : 
     498            0 : int bf_chain_flush(const char *name)
     499              : {
     500            0 :     _free_bf_request_ struct bf_request *request = NULL;
     501            0 :     _free_bf_response_ struct bf_response *response = NULL;
     502            0 :     _free_bf_marsh_ struct bf_marsh *marsh = NULL;
     503              :     int r;
     504              : 
     505            0 :     r = bf_marsh_new(&marsh, NULL, 0);
     506            0 :     if (r)
     507              :         return r;
     508              : 
     509            0 :     r = bf_marsh_add_child_raw(&marsh, name, strlen(name) + 1);
     510            0 :     if (r)
     511              :         return r;
     512              : 
     513            0 :     r = bf_marsh_add_child_raw(&marsh, name, strlen(name) + 1);
     514            0 :     if (r)
     515              :         return r;
     516              : 
     517            0 :     r = bf_request_new(&request, marsh, bf_marsh_size(marsh));
     518            0 :     if (r)
     519            0 :         return bf_err_r(r, "failed to create request for chain");
     520              : 
     521            0 :     request->front = BF_FRONT_CLI;
     522            0 :     request->cmd = BF_REQ_CHAIN_FLUSH;
     523              : 
     524            0 :     r = bf_send(request, &response);
     525            0 :     if (r)
     526            0 :         return bf_err_r(r, "failed to send chain to the daemon");
     527              : 
     528            0 :     return response->type == BF_RES_FAILURE ? response->error : 0;
     529              : }
        

Generated by: LCOV version 2.0-1