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 : : #pragma once
7 : :
8 : : #include <stdbool.h>
9 : : #include <stddef.h>
10 : : #include <stdint.h>
11 : :
12 : : #include <bpfilter/core/hashset.h>
13 : : #include <bpfilter/core/list.h>
14 : : #include <bpfilter/counter.h>
15 : : #include <bpfilter/dump.h>
16 : : #include <bpfilter/matcher.h>
17 : : #include <bpfilter/pack.h>
18 : : #include <bpfilter/runtime.h>
19 : : #include <bpfilter/verdict.h>
20 : :
21 : : #define BF_RULE_MARK_MASK (0x00000000ffffffffULL)
22 : :
23 : : /**
24 : : * @brief Return the string representation of a `bf_log_opt` enumeration value.
25 : : *
26 : : * @param hdr `bf_log_opt` enumeration value.
27 : : * @return A pointer to the C-string representation of `hdr`.
28 : : */
29 : : const char *bf_log_opt_to_str(enum bf_log_opt hdr);
30 : :
31 : : /**
32 : : * @brief Return the `bf_log_opt` enumeration value corresponding to a string.
33 : : *
34 : : * @pre
35 : : * - `str` is a non-NULL pointer to a C-string.
36 : : * - `hdr != NULL`
37 : : * @post
38 : : * - On failure, `hdr` is unchanged.
39 : : *
40 : : * @param str String to get the corresponding `bf_log_opt` enumeration value for.
41 : : * @param hdr On success, contains the `bf_log_opt` enumeration value
42 : : * corresponding to `str`.
43 : : * @return 0 on success, or a negative error value on failure.
44 : : */
45 : : int bf_log_opt_from_str(const char *str, enum bf_log_opt *hdr);
46 : :
47 : : #define _free_bf_rule_ __attribute__((__cleanup__(bf_rule_free)))
48 : :
49 : : /**
50 : : * @struct bf_rule
51 : : *
52 : : * Represents a rule to match against packets.
53 : : *
54 : : * @var bf_rule::index
55 : : * Rule's index. Identifies the rule's within other rules from the same chain.
56 : : */
57 : : struct bf_rule
58 : : {
59 : : uint32_t index;
60 : : bf_list matchers;
61 : : uint8_t log;
62 : :
63 : : /** Minimum interval between two log events for this rule, in nanoseconds.
64 : : * Zero means no rate limiting: every match is logged. */
65 : : uint64_t log_rate_ns;
66 : :
67 : : /** Mark to set to the packet's `sk_buff`. Only support for some hooks.
68 : : * The leftmost 32 bits are set to 1 if a mark is defined, or 0 otherwise.
69 : : * See `bf_rule_mark_is_set`. */
70 : : uint64_t mark;
71 : :
72 : : /** If set, the rule records matched elements count, and `bf_rule::counters`
73 : : * is valid. */
74 : : uint8_t has_counters:1;
75 : :
76 : : /** Element and size counters for matched traffic. Only valid if
77 : : * `has_counters == 1`. This field is used when reading a chain, not when
78 : : * creating it. This field is not serialized.
79 : : *
80 : : * @todo Use this field to allow users to initialize the rule's counters
81 : : * to a specific value. */
82 : : struct bf_counter counters;
83 : :
84 : : /** If true, skip this rule during flag calculation and code generation. */
85 : : bool disabled;
86 : :
87 : : enum bf_verdict verdict;
88 : :
89 : : /** Target interface index for REDIRECT verdict. 0 if not set. */
90 : : uint32_t redirect_ifindex;
91 : : /** Direction for REDIRECT verdict. */
92 : : enum bf_redirect_dir redirect_dir;
93 : : };
94 : :
95 : : static_assert(
96 : : _BF_LOG_OPT_MAX < 8,
97 : : "bf_log_opt has more than 8 values, it won't fit in bf_rule.log's 8 bits");
98 : :
99 : : /**
100 : : * Allocated and initialise a new rule.
101 : : *
102 : : * On failure, @p rule is left unchanged.
103 : : *
104 : : * @param rule On success, points to the allocated rule. Must be non NULL.
105 : : * @return 0 on success, or negative errno value on error.
106 : : */
107 : : int bf_rule_new(struct bf_rule **rule);
108 : :
109 : : /**
110 : : * @brief Allocate and initialize a new rule from serialized data.
111 : : *
112 : : * @param rule Rule object to allocate and initialize from the serialized
113 : : * data. The caller will own the object. On failure, `*rule` is
114 : : * unchanged. Can't be NULL.
115 : : * @param node Node containing the serialized rule. Can't be NULL.
116 : : * @param sets Sets used to resolve named matcher references. Can be NULL if
117 : : * no matcher references a named set.
118 : : * @return 0 on success, or a negative errno value on failure.
119 : : */
120 : : int bf_rule_new_from_pack(struct bf_rule **rule, bf_rpack_node_t node,
121 : : const bf_hashset *sets);
122 : :
123 : : /**
124 : : * @brief Allocate a copy of a rule and its matchers.
125 : : *
126 : : * Anonymous sets are deep-copied. Named sets remain borrowed from the same
127 : : * owner as the source rule. That owner must outlive the copied rule, including
128 : : * its destruction.
129 : : *
130 : : * Runtime counters and disabled state are reset. Adding the copy to a chain
131 : : * assigns its index, validates set references, and recalculates disabled state.
132 : : *
133 : : * @warning Before inserting the copy into another chain, replace its named-set
134 : : * matchers with matchers that borrow that chain's sets. Matching names alone
135 : : * do not rebind references. To copy a complete chain, use
136 : : * `bf_chain_new_from_copy()`, which rebinds references to the copied sets.
137 : : *
138 : : * @param dest Destination rule. Unchanged on failure. Can't be NULL.
139 : : * @param src Rule to copy. Can't be NULL.
140 : : * @return 0 on success, or a negative errno value on failure.
141 : : */
142 : : int bf_rule_new_from_copy(struct bf_rule **dest, const struct bf_rule *src);
143 : :
144 : : /**
145 : : * Free a rule.
146 : : *
147 : : * Free @p rule and set it to NULL. If @p rule is NULL, nothing is done.
148 : : *
149 : : * @param rule Rule to free. Must be non-NULL.
150 : : */
151 : : void bf_rule_free(struct bf_rule **rule);
152 : :
153 : : /**
154 : : * @brief Serialize a rule.
155 : : *
156 : : * @param rule Rule to serialize. Can't be NULL.
157 : : * @param pack `bf_wpack_t` object to serialize the matcher rule. Can't be NULL.
158 : : * @return 0 on success, or a negative error value on failure.
159 : : */
160 : : int bf_rule_pack(const struct bf_rule *rule, bf_wpack_t *pack);
161 : :
162 : : /**
163 : : * Dump a rule.
164 : : *
165 : : * @param rule Rule to dump. Must not be NULL.
166 : : * @param prefix Prefix for each printed line.
167 : : */
168 : : void bf_rule_dump(const struct bf_rule *rule, prefix_t *prefix);
169 : :
170 : : /**
171 : : * Create a new matcher and add it to the rule.
172 : : *
173 : : * @param rule Rule to add the matcher to. Can't be NULL.
174 : : * @param type Matcher type. `BF_MATCHER_SET` is not supported. Create set
175 : : * matchers with their constructors and add them to `rule->matchers`.
176 : : * @param op Comparison operator.
177 : : * @param payload Payload of the matcher, its content and size depends on @p
178 : : * type . Can be NULL but only if `payload_len` is 0, in which case
179 : : * there is no payload.
180 : : * @param payload_len Length of the input payload.
181 : : * @param negate If true, negate the matcher's comparison.
182 : : * @return 0 on success, or negative errno value on failure.
183 : : */
184 : : int bf_rule_add_matcher(struct bf_rule *rule, enum bf_matcher_type type,
185 : : enum bf_matcher_op op, const void *payload,
186 : : size_t payload_len, bool negate);
187 : :
188 : : static inline void bf_rule_mark_set(struct bf_rule *rule, uint32_t mark)
189 : : {
190 : : assert(rule);
191 : :
192 : 15 : rule->mark = ~BF_RULE_MARK_MASK | mark;
193 : : }
194 : :
195 : : static inline uint32_t bf_rule_mark_get(const struct bf_rule *rule)
196 : : {
197 : : assert(rule);
198 : :
199 : 11 : return rule->mark & BF_RULE_MARK_MASK;
200 : : }
201 : :
202 : : static inline bool bf_rule_mark_is_set(const struct bf_rule *rule)
203 : : {
204 : : assert(rule);
205 : :
206 [ + + ]: 11737 : return rule->mark >> 32;
207 : : }
208 : :
209 : : static inline void bf_rule_set_redirect(struct bf_rule *rule, uint32_t ifindex,
210 : : enum bf_redirect_dir dir)
211 : : {
212 : : assert(rule);
213 : :
214 : 14 : rule->redirect_ifindex = ifindex;
215 : 14 : rule->redirect_dir = dir;
216 : : }
217 : :
218 : : static inline bool bf_rule_has_redirect(const struct bf_rule *rule)
219 : : {
220 : : assert(rule);
221 : :
222 [ - + ]: 8 : return rule->redirect_ifindex != 0;
223 : : }
|