Branch data 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 "bpfilter/rule.h"
7 : :
8 : : #include <errno.h>
9 : : #include <inttypes.h>
10 : : #include <stdlib.h>
11 : : #include <string.h>
12 : :
13 : : #include "bpfilter/dump.h"
14 : : #include "bpfilter/helper.h"
15 : : #include "bpfilter/list.h"
16 : : #include "bpfilter/logger.h"
17 : : #include "bpfilter/matcher.h"
18 : : #include "bpfilter/pack.h"
19 : : #include "bpfilter/runtime.h"
20 : : #include "bpfilter/verdict.h"
21 : :
22 : : static const char *_bf_pkthdr_strs[] = {
23 : : [BF_PKTHDR_LINK] = "link",
24 : : [BF_PKTHDR_INTERNET] = "internet",
25 : : [BF_PKTHDR_TRANSPORT] = "transport",
26 : : };
27 : : static_assert_enum_mapping(_bf_pkthdr_strs, _BF_PKTHDR_MAX);
28 : :
29 : 9 : const char *bf_pkthdr_to_str(enum bf_pkthdr hdr)
30 : : {
31 [ + + ]: 9 : if (hdr < 0 || hdr >= _BF_PKTHDR_MAX)
32 : : return "<bf_pkthdr unknown>";
33 : :
34 : 7 : return _bf_pkthdr_strs[hdr];
35 : : }
36 : :
37 : 52 : int bf_pkthdr_from_str(const char *str, enum bf_pkthdr *hdr)
38 : : {
39 : : bf_assert(hdr);
40 : :
41 [ + + ]: 104 : for (int i = 0; i < _BF_PKTHDR_MAX; ++i) {
42 [ + + ]: 100 : if (bf_streq_i(str, _bf_pkthdr_strs[i])) {
43 : 48 : *hdr = (enum bf_pkthdr)i;
44 : 48 : return 0;
45 : : }
46 : : }
47 : :
48 : : return -EINVAL;
49 : : }
50 : :
51 : 992 : int bf_rule_new(struct bf_rule **rule)
52 : : {
53 : : struct bf_rule *_rule;
54 : :
55 : : bf_assert(rule);
56 : :
57 : 992 : _rule = calloc(1, sizeof(*_rule));
58 [ + - ]: 992 : if (!_rule)
59 : : return -ENOMEM;
60 : :
61 : 992 : _rule->matchers = bf_list_default(bf_matcher_free, bf_matcher_pack);
62 : :
63 : 992 : *rule = _rule;
64 : :
65 : 992 : return 0;
66 : : }
67 : :
68 : 311 : int bf_rule_new_from_pack(struct bf_rule **rule, bf_rpack_node_t node)
69 : : {
70 : 311 : _free_bf_rule_ struct bf_rule *_rule = NULL;
71 : : bf_rpack_node_t m_nodes, m_node;
72 : : int r;
73 : :
74 : : bf_assert(rule);
75 : :
76 : 311 : r = bf_rule_new(&_rule);
77 [ - + ]: 311 : if (r)
78 [ # # ]: 0 : return bf_err_r(r, "failed to create bf_rule from pack");
79 : :
80 : 311 : r = bf_rpack_kv_u32(node, "index", &_rule->index);
81 [ - + ]: 311 : if (r)
82 [ # # ]: 0 : return bf_rpack_key_err(r, "bf_rule.index");
83 : :
84 : 311 : r = bf_rpack_kv_u8(node, "log", &_rule->log);
85 [ + + ]: 311 : if (r)
86 [ + - ]: 1 : return bf_rpack_key_err(r, "bf_rule.log");
87 : :
88 : 310 : r = bf_rpack_kv_bool(node, "counters", &_rule->counters);
89 [ - + ]: 310 : if (r)
90 [ # # ]: 0 : return bf_rpack_key_err(r, "bf_rule.counters");
91 : :
92 : 310 : r = bf_rpack_kv_u64(node, "mark", &_rule->mark);
93 [ - + ]: 310 : if (r)
94 [ # # ]: 0 : return bf_rpack_key_err(r, "bf_rule.mark");
95 : :
96 [ - + ]: 310 : r = bf_rpack_kv_enum(node, "verdict", &_rule->verdict);
97 : : if (r)
98 [ # # ]: 0 : return bf_rpack_key_err(r, "bf_rule.verdict");
99 : :
100 : 310 : r = bf_rpack_kv_array(node, "matchers", &m_nodes);
101 [ - + ]: 310 : if (r)
102 [ # # ]: 0 : return bf_rpack_key_err(r, "bf_rule.matchers");
103 [ + - + + : 3572 : bf_rpack_array_foreach (m_nodes, m_node) {
+ + ]
104 : 2952 : _free_bf_matcher_ struct bf_matcher *matcher = NULL;
105 : :
106 [ + - + - : 1476 : r = bf_list_emplace(&_rule->matchers, bf_matcher_new_from_pack, matcher,
- - - - ]
107 : : m_node);
108 : : if (r) {
109 [ # # ]: 0 : return bf_err_r(
110 : : r, "failed to unpack bf_matcher into bf_rule.matchers");
111 : : }
112 : : }
113 : :
114 : 310 : *rule = TAKE_PTR(_rule);
115 : :
116 : 310 : return 0;
117 : : }
118 : :
119 : 2299 : void bf_rule_free(struct bf_rule **rule)
120 : : {
121 : : bf_assert(rule);
122 : :
123 [ + + ]: 2299 : if (!*rule)
124 : : return;
125 : :
126 : 992 : bf_list_clean(&(*rule)->matchers);
127 : :
128 : 992 : free(*rule);
129 : 992 : *rule = NULL;
130 : : }
131 : :
132 : 1885 : int bf_rule_pack(const struct bf_rule *rule, bf_wpack_t *pack)
133 : : {
134 : : bf_assert(rule);
135 : : bf_assert(pack);
136 : :
137 : 1885 : bf_wpack_kv_u32(pack, "index", rule->index);
138 : 1885 : bf_wpack_kv_u8(pack, "log", rule->log);
139 : 1885 : bf_wpack_kv_bool(pack, "counters", rule->counters);
140 : 1885 : bf_wpack_kv_u64(pack, "mark", rule->mark);
141 : 1885 : bf_wpack_kv_int(pack, "verdict", rule->verdict);
142 : :
143 : 1885 : bf_wpack_kv_list(pack, "matchers", &rule->matchers);
144 : :
145 [ - + ]: 1885 : return bf_wpack_is_valid(pack) ? 0 : -EINVAL;
146 : : }
147 : :
148 : 13 : void bf_rule_dump(const struct bf_rule *rule, prefix_t *prefix)
149 : : {
150 : : bf_assert(rule);
151 : : bf_assert(prefix);
152 : :
153 [ + + ]: 13 : DUMP(prefix, "struct bf_rule at %p", rule);
154 : :
155 : 13 : bf_dump_prefix_push(prefix);
156 : :
157 [ + + ]: 13 : DUMP(prefix, "index: %u", rule->index);
158 : :
159 : : // Matchers
160 [ + + ]: 13 : DUMP(prefix, "matchers: %lu", bf_list_size(&rule->matchers));
161 : 13 : bf_dump_prefix_push(prefix);
162 [ + + + + : 92 : bf_list_foreach (&rule->matchers, matcher_node) {
+ + ]
163 : : struct bf_matcher *matcher = bf_list_node_get_data(matcher_node);
164 : :
165 [ + + ]: 33 : if (bf_list_is_tail(&rule->matchers, matcher_node))
166 : 12 : bf_dump_prefix_last(prefix);
167 : :
168 : 33 : bf_matcher_dump(matcher, prefix);
169 : : }
170 : 13 : bf_dump_prefix_pop(prefix);
171 : :
172 [ + + ]: 13 : DUMP(prefix, "log: %02x", rule->log);
173 [ + + + + ]: 14 : DUMP(prefix, "counters: %s", rule->counters ? "yes" : "no");
174 [ + + ]: 13 : DUMP(prefix, "mark: 0x%" PRIx64, rule->mark);
175 [ + + ]: 13 : DUMP(bf_dump_prefix_last(prefix), "verdict: %s",
176 : : bf_verdict_to_str(rule->verdict));
177 : :
178 : 13 : bf_dump_prefix_pop(prefix);
179 : 13 : }
180 : :
181 : 10 : int bf_rule_add_matcher(struct bf_rule *rule, enum bf_matcher_type type,
182 : : enum bf_matcher_op op, const void *payload,
183 : : size_t payload_len)
184 : : {
185 : 10 : _free_bf_matcher_ struct bf_matcher *matcher = NULL;
186 : : int r;
187 : :
188 : : bf_assert(rule);
189 : :
190 : 10 : r = bf_matcher_new(&matcher, type, op, payload, payload_len);
191 [ + - ]: 10 : if (r)
192 : : return r;
193 : :
194 : 10 : r = bf_list_add_tail(&rule->matchers, matcher);
195 [ + - ]: 10 : if (r)
196 : : return r;
197 : :
198 : 10 : TAKE_PTR(matcher);
199 : :
200 : 10 : return 0;
201 : : }
|