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