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 "core/rule.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/list.h"
15 : #include "core/logger.h"
16 : #include "core/marsh.h"
17 : #include "core/matcher.h"
18 : #include "core/verdict.h"
19 :
20 7 : int bf_rule_new(struct bf_rule **rule)
21 : {
22 : struct bf_rule *_rule;
23 :
24 7 : bf_assert(rule);
25 :
26 6 : _rule = calloc(1, sizeof(*_rule));
27 6 : if (!_rule)
28 : return -ENOMEM;
29 :
30 5 : bf_list_init(
31 : &_rule->matchers,
32 5 : (bf_list_ops[]) {{.free = (bf_list_ops_free)bf_matcher_free,
33 : .marsh = (bf_list_ops_marsh)bf_matcher_marsh}});
34 :
35 5 : *rule = _rule;
36 :
37 5 : return 0;
38 : }
39 :
40 10 : void bf_rule_free(struct bf_rule **rule)
41 : {
42 10 : bf_assert(rule);
43 :
44 9 : if (!*rule)
45 : return;
46 :
47 5 : bf_list_clean(&(*rule)->matchers);
48 :
49 5 : free(*rule);
50 5 : *rule = NULL;
51 : }
52 :
53 4 : int bf_rule_marsh(const struct bf_rule *rule, struct bf_marsh **marsh)
54 : {
55 2 : _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
56 : int r;
57 :
58 4 : bf_assert(rule);
59 3 : bf_assert(marsh);
60 :
61 2 : r = bf_marsh_new(&_marsh, NULL, 0);
62 2 : if (r < 0)
63 : return r;
64 :
65 1 : r = bf_marsh_add_child_raw(&_marsh, &rule->index, sizeof(rule->index));
66 1 : if (r < 0)
67 : return r;
68 :
69 : {
70 1 : _cleanup_bf_marsh_ struct bf_marsh *child = NULL;
71 :
72 1 : r = bf_list_marsh(&rule->matchers, &child);
73 1 : if (r < 0)
74 : return r;
75 :
76 1 : r = bf_marsh_add_child_obj(&_marsh, child);
77 1 : if (r)
78 : return r;
79 : }
80 :
81 1 : r |= bf_marsh_add_child_raw(&_marsh, &rule->counters,
82 : sizeof(rule->counters));
83 1 : r |= bf_marsh_add_child_raw(&_marsh, &rule->verdict,
84 : sizeof(enum bf_verdict));
85 1 : if (r)
86 0 : return bf_err_r(r, "Failed to serialize rule");
87 :
88 1 : *marsh = TAKE_PTR(_marsh);
89 :
90 1 : return 0;
91 : }
92 :
93 3 : int bf_rule_unmarsh(const struct bf_marsh *marsh, struct bf_rule **rule)
94 : {
95 1 : _cleanup_bf_rule_ struct bf_rule *_rule = NULL;
96 : struct bf_marsh *rule_elem = NULL;
97 : int r;
98 :
99 3 : bf_assert(marsh);
100 2 : bf_assert(rule);
101 :
102 1 : r = bf_rule_new(&_rule);
103 1 : if (r < 0)
104 : return r;
105 :
106 1 : if (!(rule_elem = bf_marsh_next_child(marsh, NULL)))
107 : return -EINVAL;
108 1 : memcpy(&_rule->index, rule_elem->data, sizeof(_rule->index));
109 :
110 1 : if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
111 : return -EINVAL;
112 :
113 : {
114 : struct bf_marsh *matcher_elem = NULL;
115 :
116 11 : while ((matcher_elem = bf_marsh_next_child(rule_elem, matcher_elem))) {
117 0 : _cleanup_bf_matcher_ struct bf_matcher *matcher = NULL;
118 :
119 10 : r = bf_matcher_new_from_marsh(&matcher, matcher_elem);
120 10 : if (r)
121 : return r;
122 :
123 10 : r = bf_list_add_tail(&_rule->matchers, matcher);
124 10 : if (r)
125 : return r;
126 :
127 10 : TAKE_PTR(matcher);
128 : }
129 : }
130 :
131 1 : if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
132 : return -EINVAL;
133 1 : memcpy(&_rule->counters, rule_elem->data, sizeof(_rule->counters));
134 :
135 1 : if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
136 : return -EINVAL;
137 1 : memcpy(&_rule->verdict, rule_elem->data, sizeof(_rule->verdict));
138 :
139 1 : if (bf_marsh_next_child(marsh, rule_elem))
140 0 : bf_warn("codegen marsh has more children than expected");
141 :
142 1 : *rule = TAKE_PTR(_rule);
143 :
144 1 : return 0;
145 : }
146 :
147 0 : void bf_rule_dump(const struct bf_rule *rule, prefix_t *prefix)
148 : {
149 0 : bf_assert(rule);
150 0 : bf_assert(prefix);
151 :
152 0 : DUMP(prefix, "struct bf_rule at %p", rule);
153 :
154 0 : bf_dump_prefix_push(prefix);
155 :
156 0 : DUMP(prefix, "index: %u", rule->index);
157 :
158 : // Matchers
159 0 : DUMP(prefix, "matchers: %lu", bf_list_size(&rule->matchers));
160 0 : bf_dump_prefix_push(prefix);
161 0 : bf_list_foreach (&rule->matchers, matcher_node) {
162 0 : struct bf_matcher *matcher = bf_list_node_get_data(matcher_node);
163 :
164 0 : if (bf_list_is_tail(&rule->matchers, matcher_node))
165 0 : bf_dump_prefix_last(prefix);
166 :
167 0 : bf_matcher_dump(matcher, prefix);
168 : }
169 0 : bf_dump_prefix_pop(prefix);
170 :
171 0 : DUMP(prefix, "counters: %s", rule->counters ? "yes" : "no");
172 0 : DUMP(bf_dump_prefix_last(prefix), "verdict: %s",
173 : bf_verdict_to_str(rule->verdict));
174 :
175 0 : bf_dump_prefix_pop(prefix);
176 0 : }
177 :
178 20 : int bf_rule_add_matcher(struct bf_rule *rule, enum bf_matcher_type type,
179 : enum bf_matcher_op op, const void *payload,
180 : size_t payload_len)
181 : {
182 20 : _cleanup_bf_matcher_ struct bf_matcher *matcher = NULL;
183 : int r;
184 :
185 20 : bf_assert(rule);
186 :
187 20 : r = bf_matcher_new(&matcher, type, op, payload, payload_len);
188 20 : if (r)
189 : return r;
190 :
191 20 : r = bf_list_add_tail(&rule->matchers, matcher);
192 20 : if (r)
193 : return r;
194 :
195 20 : TAKE_PTR(matcher);
196 :
197 20 : return 0;
198 : }
|