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/matcher.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/logger.h"
15 : #include "core/marsh.h"
16 :
17 41 : int bf_matcher_new(struct bf_matcher **matcher, enum bf_matcher_type type,
18 : enum bf_matcher_op op, const void *payload,
19 : size_t payload_len)
20 : {
21 39 : _cleanup_bf_matcher_ struct bf_matcher *_matcher = NULL;
22 :
23 41 : bf_assert(matcher);
24 40 : bf_assert((payload && payload_len) || (!payload && !payload_len));
25 :
26 39 : _matcher = malloc(sizeof(struct bf_matcher) + payload_len);
27 39 : if (!_matcher)
28 : return -ENOMEM;
29 :
30 36 : _matcher->type = type;
31 36 : _matcher->op = op;
32 36 : _matcher->len = sizeof(struct bf_matcher) + payload_len;
33 36 : bf_memcpy(_matcher->payload, payload, payload_len);
34 :
35 36 : *matcher = TAKE_PTR(_matcher);
36 :
37 36 : return 0;
38 : }
39 :
40 14 : int bf_matcher_new_from_marsh(struct bf_matcher **matcher,
41 : const struct bf_marsh *marsh)
42 : {
43 : struct bf_marsh *child = NULL;
44 : enum bf_matcher_type type;
45 : enum bf_matcher_op op;
46 : size_t payload_len;
47 : const void *payload;
48 : int r;
49 :
50 14 : bf_assert(matcher);
51 13 : bf_assert(marsh);
52 :
53 12 : if (!(child = bf_marsh_next_child(marsh, child)))
54 : return -EINVAL;
55 12 : memcpy(&type, child->data, sizeof(type));
56 :
57 12 : if (!(child = bf_marsh_next_child(marsh, child)))
58 : return -EINVAL;
59 12 : memcpy(&op, child->data, sizeof(op));
60 :
61 12 : if (!(child = bf_marsh_next_child(marsh, child)))
62 : return -EINVAL;
63 12 : memcpy(&payload_len, child->data, sizeof(payload_len));
64 12 : payload_len -= sizeof(struct bf_matcher);
65 :
66 12 : if (!(child = bf_marsh_next_child(marsh, child)))
67 : return -EINVAL;
68 12 : payload = child->data;
69 :
70 12 : r = bf_matcher_new(matcher, type, op, payload, payload_len);
71 12 : if (r)
72 1 : return bf_err_r(r, "failed to restore bf_matcher from serialised data");
73 :
74 : return 0;
75 : }
76 :
77 106 : void bf_matcher_free(struct bf_matcher **matcher)
78 : {
79 106 : bf_assert(matcher);
80 :
81 105 : if (!*matcher)
82 : return;
83 :
84 36 : free(*matcher);
85 36 : *matcher = NULL;
86 : }
87 :
88 15 : int bf_matcher_marsh(const struct bf_matcher *matcher, struct bf_marsh **marsh)
89 : {
90 13 : _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
91 : int r;
92 :
93 15 : bf_assert(matcher);
94 14 : bf_assert(marsh);
95 :
96 13 : r = bf_marsh_new(&_marsh, NULL, 0);
97 13 : if (r < 0)
98 : return r;
99 :
100 12 : r |= bf_marsh_add_child_raw(&_marsh, &matcher->type, sizeof(matcher->type));
101 12 : r |= bf_marsh_add_child_raw(&_marsh, &matcher->op, sizeof(matcher->op));
102 12 : r |= bf_marsh_add_child_raw(&_marsh, &matcher->len, sizeof(matcher->len));
103 24 : r |= bf_marsh_add_child_raw(&_marsh, matcher->payload,
104 12 : matcher->len - sizeof(struct bf_matcher));
105 12 : if (r)
106 0 : return bf_err_r(r, "failed to serialise bf_matcher object");
107 :
108 12 : *marsh = TAKE_PTR(_marsh);
109 :
110 12 : return 0;
111 : }
112 :
113 0 : void bf_matcher_dump(const struct bf_matcher *matcher, prefix_t *prefix)
114 : {
115 0 : bf_assert(matcher);
116 0 : bf_assert(prefix);
117 :
118 0 : DUMP(prefix, "struct bf_matcher at %p", matcher);
119 :
120 0 : bf_dump_prefix_push(prefix);
121 :
122 0 : DUMP(prefix, "type: %s", bf_matcher_type_to_str(matcher->type));
123 0 : DUMP(prefix, "op: %s", bf_matcher_op_to_str(matcher->op));
124 0 : DUMP(prefix, "len: %ld", matcher->len);
125 0 : DUMP(bf_dump_prefix_last(prefix), "payload:");
126 0 : bf_dump_prefix_push(prefix);
127 0 : bf_dump_hex(prefix, matcher->payload,
128 0 : matcher->len - sizeof(struct bf_matcher));
129 0 : bf_dump_prefix_pop(prefix);
130 :
131 0 : bf_dump_prefix_pop(prefix);
132 0 : }
133 :
134 : static const char *_bf_matcher_type_strs[] = {
135 : [BF_MATCHER_META_IFINDEX] = "meta.ifindex",
136 : [BF_MATCHER_META_L3_PROTO] = "meta.l3_proto",
137 : [BF_MATCHER_META_L4_PROTO] = "meta.l4_proto",
138 : [BF_MATCHER_META_SPORT] = "meta.sport",
139 : [BF_MATCHER_META_DPORT] = "meta.dport",
140 : [BF_MATCHER_IP4_SRC_ADDR] = "ip4.saddr",
141 : [BF_MATCHER_IP4_DST_ADDR] = "ip4.daddr",
142 : [BF_MATCHER_IP4_PROTO] = "ip4.proto",
143 : [BF_MATCHER_IP6_SADDR] = "ip6.saddr",
144 : [BF_MATCHER_IP6_DADDR] = "ip6.daddr",
145 : [BF_MATCHER_TCP_SPORT] = "tcp.sport",
146 : [BF_MATCHER_TCP_DPORT] = "tcp.dport",
147 : [BF_MATCHER_TCP_FLAGS] = "tcp.flags",
148 : [BF_MATCHER_UDP_SPORT] = "udp.sport",
149 : [BF_MATCHER_UDP_DPORT] = "udp.dport",
150 : [BF_MATCHER_SET_SRCIP6PORT] = "set.srcip6port",
151 : [BF_MATCHER_SET_SRCIP6] = "set.srcip6",
152 : };
153 :
154 : static_assert(ARRAY_SIZE(_bf_matcher_type_strs) == _BF_MATCHER_TYPE_MAX,
155 : "missing entries in the matcher type array");
156 :
157 19 : const char *bf_matcher_type_to_str(enum bf_matcher_type type)
158 : {
159 19 : bf_assert(0 <= type && type < _BF_MATCHER_TYPE_MAX);
160 :
161 17 : return _bf_matcher_type_strs[type];
162 : }
163 :
164 21 : int bf_matcher_type_from_str(const char *str, enum bf_matcher_type *type)
165 : {
166 21 : bf_assert(str);
167 20 : bf_assert(type);
168 :
169 189 : for (size_t i = 0; i < _BF_MATCHER_TYPE_MAX; ++i) {
170 187 : if (bf_streq(_bf_matcher_type_strs[i], str)) {
171 17 : *type = i;
172 17 : return 0;
173 : }
174 : }
175 :
176 : return -EINVAL;
177 : }
178 :
179 : static const char *_bf_matcher_ops_strs[] = {
180 : [BF_MATCHER_EQ] = "eq", [BF_MATCHER_NE] = "not",
181 : [BF_MATCHER_ANY] = "any", [BF_MATCHER_ALL] = "all",
182 : [BF_MATCHER_IN] = "in", [BF_MATCHER_RANGE] = "range",
183 : };
184 :
185 : static_assert(ARRAY_SIZE(_bf_matcher_ops_strs) == _BF_MATCHER_OP_MAX);
186 :
187 8 : const char *bf_matcher_op_to_str(enum bf_matcher_op op)
188 : {
189 8 : bf_assert(0 <= op && op < _BF_MATCHER_OP_MAX);
190 :
191 6 : return _bf_matcher_ops_strs[op];
192 : }
193 :
194 0 : int bf_matcher_op_from_str(const char *str, enum bf_matcher_op *op)
195 : {
196 0 : bf_assert(str);
197 0 : bf_assert(op);
198 :
199 0 : for (size_t i = 0; i < _BF_MATCHER_OP_MAX; ++i) {
200 0 : if (bf_streq(_bf_matcher_ops_strs[i], str)) {
201 0 : *op = i;
202 0 : return 0;
203 : }
204 : }
205 :
206 : return -EINVAL;
207 : }
208 :
209 : static const char *_bf_matcher_tcp_flags_strs[] = {
210 : [BF_MATCHER_TCP_FLAG_FIN] = "FIN", [BF_MATCHER_TCP_FLAG_SYN] = "SYN",
211 : [BF_MATCHER_TCP_FLAG_RST] = "RST", [BF_MATCHER_TCP_FLAG_PSH] = "PSH",
212 : [BF_MATCHER_TCP_FLAG_ACK] = "ACK", [BF_MATCHER_TCP_FLAG_URG] = "URG",
213 : [BF_MATCHER_TCP_FLAG_ECE] = "ECE", [BF_MATCHER_TCP_FLAG_CWR] = "CWR",
214 : };
215 :
216 0 : const char *bf_matcher_tcp_flag_to_str(enum bf_matcher_tcp_flag flag)
217 : {
218 0 : bf_assert(0 <= flag && flag < _BF_MATCHER_TCP_FLAG_MAX);
219 :
220 0 : return _bf_matcher_tcp_flags_strs[flag];
221 : }
222 :
223 0 : int bf_matcher_tcp_flag_from_str(const char *str,
224 : enum bf_matcher_tcp_flag *flag)
225 : {
226 0 : bf_assert(str);
227 0 : bf_assert(flag);
228 :
229 0 : for (size_t i = 0; i < _BF_MATCHER_TCP_FLAG_MAX; ++i) {
230 0 : if (bf_streq(_bf_matcher_tcp_flags_strs[i], str)) {
231 0 : *flag = i;
232 0 : return 0;
233 : }
234 : }
235 :
236 : return -EINVAL;
237 : }
|