LCOV - code coverage report
Current view: top level - core - chain.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 60.0 % 105 63
Test Date: 2025-05-09 22:39:08 Functions: 66.7 % 6 4

            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 "chain.h"
       7              : 
       8              : #include <errno.h>
       9              : #include <stdlib.h>
      10              : #include <string.h>
      11              : 
      12              : #include "core/dump.h"
      13              : #include "core/helper.h"
      14              : #include "core/hook.h"
      15              : #include "core/list.h"
      16              : #include "core/logger.h"
      17              : #include "core/marsh.h"
      18              : #include "core/rule.h"
      19              : #include "core/set.h"
      20              : #include "core/verdict.h"
      21              : 
      22           13 : int bf_chain_new(struct bf_chain **chain, const char *name, enum bf_hook hook,
      23              :                  enum bf_verdict policy, bf_list *sets, bf_list *rules)
      24              : {
      25           12 :     _cleanup_bf_chain_ struct bf_chain *_chain = NULL;
      26              : 
      27           13 :     bf_assert(policy < _BF_TERMINAL_VERDICT_MAX);
      28              : 
      29           12 :     _chain = malloc(sizeof(*_chain));
      30           12 :     if (!_chain)
      31              :         return -ENOMEM;
      32              : 
      33           12 :     _chain->name = strdup(name);
      34           12 :     if (!_chain->name)
      35              :         return -ENOMEM;
      36              : 
      37           12 :     _chain->hook = hook;
      38           12 :     _chain->policy = policy;
      39              : 
      40           12 :     _chain->sets = bf_list_default(bf_set_free, bf_set_marsh);
      41           12 :     if (sets)
      42            0 :         _chain->sets = bf_list_move(*sets);
      43              : 
      44           12 :     _chain->rules = bf_list_default(bf_rule_free, bf_rule_marsh);
      45           12 :     if (rules)
      46            0 :         _chain->rules = bf_list_move(*rules);
      47              : 
      48           12 :     *chain = TAKE_PTR(_chain);
      49              : 
      50           12 :     return 0;
      51              : }
      52              : 
      53            1 : int bf_chain_new_from_marsh(struct bf_chain **chain,
      54              :                             const struct bf_marsh *marsh)
      55              : {
      56            1 :     _cleanup_bf_chain_ struct bf_chain *_chain = NULL;
      57              :     struct bf_marsh *child = NULL;
      58              :     struct bf_marsh *list_elem;
      59              :     enum bf_hook hook;
      60              :     enum bf_verdict policy;
      61              :     _cleanup_free_ const char *name = NULL;
      62              :     int r;
      63              : 
      64            1 :     bf_assert(chain && marsh);
      65              : 
      66            1 :     if (!(child = bf_marsh_next_child(marsh, child)))
      67              :         return -EINVAL;
      68            1 :     if (child->data_len == 0)
      69            0 :         return bf_err_r(-EINVAL, "serialized bf_chain.name is empty");
      70            1 :     name = strdup(child->data);
      71            1 :     if (!name)
      72              :         return -ENOMEM;
      73              : 
      74            1 :     if (!(child = bf_marsh_next_child(marsh, child)))
      75              :         return -EINVAL;
      76            1 :     memcpy(&hook, child->data, sizeof(hook));
      77              : 
      78            1 :     if (!(child = bf_marsh_next_child(marsh, child)))
      79              :         return -EINVAL;
      80            1 :     memcpy(&policy, child->data, sizeof(policy));
      81              : 
      82            1 :     r = bf_chain_new(&_chain, name, hook, policy, NULL, NULL);
      83            1 :     if (r)
      84              :         return r;
      85              : 
      86              :     // Unmarsh bf_chain.sets
      87              :     list_elem = NULL;
      88            1 :     if (!(child = bf_marsh_next_child(marsh, child)))
      89              :         return -EINVAL;
      90            1 :     while ((list_elem = bf_marsh_next_child(child, list_elem))) {
      91            0 :         _cleanup_bf_set_ struct bf_set *set = NULL;
      92              : 
      93            0 :         r = bf_set_new_from_marsh(&set, list_elem);
      94            0 :         if (r)
      95              :             return r;
      96              : 
      97            0 :         r = bf_list_add_tail(&_chain->sets, set);
      98            0 :         if (r)
      99              :             return r;
     100              : 
     101            0 :         TAKE_PTR(set);
     102              :     }
     103              : 
     104              :     // Unmarsh bf_chain.rules
     105              :     list_elem = NULL;
     106            1 :     if (!(child = bf_marsh_next_child(marsh, child)))
     107              :         return -EINVAL;
     108            1 :     while ((list_elem = bf_marsh_next_child(child, list_elem))) {
     109            0 :         _cleanup_bf_rule_ struct bf_rule *rule = NULL;
     110              : 
     111            0 :         r = bf_rule_unmarsh(list_elem, &rule);
     112            0 :         if (r)
     113              :             return r;
     114              : 
     115            0 :         r = bf_list_add_tail(&_chain->rules, rule);
     116            0 :         if (r)
     117              :             return r;
     118              : 
     119            0 :         TAKE_PTR(rule);
     120              :     }
     121              : 
     122            1 :     *chain = TAKE_PTR(_chain);
     123              : 
     124            1 :     return 0;
     125              : }
     126              : 
     127           29 : void bf_chain_free(struct bf_chain **chain)
     128              : {
     129           29 :     bf_assert(chain);
     130              : 
     131           29 :     if (!*chain)
     132              :         return;
     133              : 
     134           12 :     bf_list_clean(&(*chain)->sets);
     135           12 :     bf_list_clean(&(*chain)->rules);
     136           12 :     freep((void *)&(*chain)->name);
     137              :     freep((void *)chain);
     138              : }
     139              : 
     140            1 : int bf_chain_marsh(const struct bf_chain *chain, struct bf_marsh **marsh)
     141              : {
     142            1 :     _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
     143              :     int r;
     144              : 
     145            1 :     bf_assert(chain && marsh);
     146              : 
     147            1 :     r = bf_marsh_new(&_marsh, NULL, 0);
     148            1 :     if (r)
     149              :         return r;
     150              : 
     151            1 :     r = bf_marsh_add_child_raw(&_marsh, chain->name, strlen(chain->name) + 1);
     152            1 :     if (r < 0)
     153              :         return r;
     154              : 
     155            1 :     r = bf_marsh_add_child_raw(&_marsh, &chain->hook, sizeof(chain->hook));
     156            1 :     if (r < 0)
     157              :         return r;
     158              : 
     159            1 :     r = bf_marsh_add_child_raw(&_marsh, &chain->policy, sizeof(chain->policy));
     160            1 :     if (r)
     161              :         return r;
     162              : 
     163              :     {
     164              :         // Serialize bf_chain.sets
     165            1 :         _cleanup_bf_marsh_ struct bf_marsh *child = NULL;
     166              : 
     167            1 :         r = bf_list_marsh(&chain->sets, &child);
     168            1 :         if (r < 0)
     169              :             return r;
     170              : 
     171            1 :         r = bf_marsh_add_child_obj(&_marsh, child);
     172            1 :         if (r < 0)
     173              :             return r;
     174              :     }
     175              : 
     176              :     {
     177              :         // Serialize bf_chain.rules
     178            1 :         _cleanup_bf_marsh_ struct bf_marsh *child = NULL;
     179              : 
     180            1 :         r = bf_list_marsh(&chain->rules, &child);
     181            1 :         if (r < 0)
     182              :             return r;
     183              : 
     184            1 :         r = bf_marsh_add_child_obj(&_marsh, child);
     185            1 :         if (r < 0)
     186              :             return r;
     187              :     }
     188              : 
     189            1 :     *marsh = TAKE_PTR(_marsh);
     190              : 
     191            1 :     return 0;
     192              : }
     193              : 
     194            0 : void bf_chain_dump(const struct bf_chain *chain, prefix_t *prefix)
     195              : {
     196            0 :     bf_assert(chain && prefix);
     197              : 
     198            0 :     DUMP(prefix, "struct bf_chain at %p", chain);
     199            0 :     bf_dump_prefix_push(prefix);
     200              : 
     201            0 :     DUMP(prefix, "name: %s", chain->name);
     202            0 :     DUMP(prefix, "hook: %s", bf_hook_to_str(chain->hook));
     203            0 :     DUMP(prefix, "policy: %s", bf_verdict_to_str(chain->policy));
     204              : 
     205            0 :     DUMP(prefix, "sets: bf_list<bf_set>[%lu]", bf_list_size(&chain->sets));
     206            0 :     bf_dump_prefix_push(prefix);
     207            0 :     bf_list_foreach (&chain->sets, set_node) {
     208            0 :         if (bf_list_is_tail(&chain->sets, set_node))
     209            0 :             bf_dump_prefix_last(prefix);
     210              : 
     211            0 :         bf_set_dump(bf_list_node_get_data(set_node), prefix);
     212              :     }
     213            0 :     bf_dump_prefix_pop(prefix);
     214              : 
     215            0 :     DUMP(bf_dump_prefix_last(prefix), "rules: bf_list<bf_rule>[%lu]",
     216              :          bf_list_size(&chain->rules));
     217            0 :     bf_dump_prefix_push(prefix);
     218            0 :     bf_list_foreach (&chain->rules, rule_node) {
     219            0 :         if (bf_list_is_tail(&chain->rules, rule_node))
     220            0 :             bf_dump_prefix_last(prefix);
     221              : 
     222            0 :         bf_rule_dump(bf_list_node_get_data(rule_node), prefix);
     223              :     }
     224            0 :     bf_dump_prefix_pop(prefix);
     225              : 
     226            0 :     bf_dump_prefix_pop(prefix);
     227            0 : }
     228              : 
     229            0 : int bf_chain_add_rule(struct bf_chain *chain, struct bf_rule *rule)
     230              : {
     231            0 :     bf_assert(chain && rule);
     232              : 
     233            0 :     rule->index = bf_list_size(&chain->rules);
     234              : 
     235            0 :     return bf_list_add_tail(&chain->rules, rule);
     236              : }
        

Generated by: LCOV version 2.0-1