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