Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : #include "core/set.h"
7 :
8 : #include <errno.h>
9 : #include <stdint.h>
10 : #include <stdlib.h>
11 : #include <string.h>
12 : #include <time.h>
13 :
14 : #include "core/dump.h"
15 : #include "core/helper.h"
16 : #include "core/list.h"
17 : #include "core/logger.h"
18 : #include "core/marsh.h"
19 :
20 0 : size_t _bf_set_type_elem_size(enum bf_set_type type)
21 : {
22 : static const size_t sizes[_BF_SET_MAX] = {
23 : [BF_SET_IP4] = 4,
24 : [BF_SET_SRCIP6PORT] = 18,
25 : [BF_SET_SRCIP6] = 16,
26 : };
27 :
28 : static_assert(ARRAY_SIZE(sizes) == _BF_SET_MAX,
29 : "missing entries in set elems size array");
30 :
31 0 : return sizes[type];
32 : }
33 :
34 0 : int bf_set_new(struct bf_set **set, enum bf_set_type type)
35 : {
36 0 : bf_assert(set);
37 :
38 0 : *set = malloc(sizeof(**set));
39 0 : if (!*set)
40 : return -ENOMEM;
41 :
42 0 : (*set)->type = type;
43 0 : (*set)->elem_size = _bf_set_type_elem_size(type);
44 0 : bf_list_init(&(*set)->elems,
45 0 : (bf_list_ops[]) {{.free = (bf_list_ops_free)freep}});
46 :
47 0 : return 0;
48 : }
49 :
50 0 : int bf_set_new_from_marsh(struct bf_set **set, const struct bf_marsh *marsh)
51 : {
52 0 : _cleanup_bf_set_ struct bf_set *_set = NULL;
53 : struct bf_marsh *child;
54 : enum bf_set_type type;
55 : int r;
56 :
57 0 : bf_assert(set);
58 0 : bf_assert(marsh);
59 :
60 0 : if (!(child = bf_marsh_next_child(marsh, NULL)))
61 : return -EINVAL;
62 0 : memcpy(&type, child->data, sizeof(type));
63 :
64 0 : r = bf_set_new(&_set, type);
65 0 : if (r < 0)
66 : return r;
67 :
68 0 : if (!(child = bf_marsh_next_child(marsh, child)))
69 : return -EINVAL;
70 :
71 0 : for (size_t i = 0; i < child->data_len / _set->elem_size; ++i) {
72 0 : _cleanup_free_ void *elem = malloc(_set->elem_size);
73 0 : if (!elem)
74 : return -ENOMEM;
75 :
76 0 : memcpy(elem, child->data + (i * _set->elem_size), _set->elem_size);
77 0 : r = bf_list_add_tail(&_set->elems, elem);
78 0 : if (r < 0)
79 : return r;
80 :
81 : TAKE_PTR(elem);
82 : }
83 :
84 0 : *set = TAKE_PTR(_set);
85 :
86 0 : return 0;
87 : }
88 :
89 0 : void bf_set_free(struct bf_set **set)
90 : {
91 0 : bf_assert(set);
92 :
93 0 : if (!*set)
94 : return;
95 :
96 0 : bf_list_clean(&(*set)->elems);
97 : freep((void *)set);
98 : }
99 :
100 0 : int bf_set_marsh(const struct bf_set *set, struct bf_marsh **marsh)
101 : {
102 0 : _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
103 : _cleanup_free_ uint8_t *data = NULL;
104 : size_t elem_idx = 0;
105 : int r;
106 :
107 0 : bf_assert(set);
108 0 : bf_assert(marsh);
109 :
110 0 : r = bf_marsh_new(&_marsh, NULL, 0);
111 0 : if (r < 0)
112 : return r;
113 :
114 0 : r = bf_marsh_add_child_raw(&_marsh, &set->type, sizeof(set->type));
115 0 : if (r < 0)
116 : return r;
117 :
118 0 : data = malloc(set->elem_size * bf_list_size(&set->elems));
119 0 : if (!data)
120 0 : return bf_err_r(r, "failed to allocate memory for the set's content");
121 :
122 0 : bf_list_foreach (&set->elems, elem_node) {
123 0 : memcpy(data + (elem_idx * set->elem_size),
124 0 : bf_list_node_get_data(elem_node), set->elem_size);
125 0 : ++elem_idx;
126 : }
127 :
128 0 : r = bf_marsh_add_child_raw(&_marsh, data,
129 0 : set->elem_size * bf_list_size(&set->elems));
130 0 : if (r < 0)
131 : return r;
132 :
133 0 : *marsh = TAKE_PTR(_marsh);
134 :
135 0 : return 0;
136 : }
137 :
138 0 : void bf_set_dump(const struct bf_set *set, prefix_t *prefix)
139 : {
140 0 : bf_assert(set && prefix);
141 :
142 0 : DUMP(prefix, "struct bf_set at %p", set);
143 0 : bf_dump_prefix_push(prefix);
144 :
145 0 : DUMP(prefix, "type: %s", bf_set_type_to_str(set->type));
146 0 : DUMP(prefix, "elem_size: %lu", set->elem_size);
147 0 : DUMP(bf_dump_prefix_last(prefix), "elems: bf_list<bytes>[%lu]",
148 : bf_list_size(&set->elems));
149 :
150 0 : bf_dump_prefix_push(prefix);
151 0 : bf_list_foreach (&set->elems, elem_node) {
152 0 : if (bf_list_is_tail(&set->elems, elem_node))
153 0 : bf_dump_prefix_last(prefix);
154 :
155 0 : DUMP(prefix, "void * @ %p", bf_list_node_get_data(elem_node));
156 0 : bf_dump_prefix_push(prefix);
157 0 : bf_dump_hex(prefix, bf_list_node_get_data(elem_node), set->elem_size);
158 0 : bf_dump_prefix_pop(prefix);
159 : }
160 0 : bf_dump_prefix_pop(prefix);
161 :
162 0 : bf_dump_prefix_pop(prefix);
163 0 : }
164 :
165 0 : int bf_set_add_elem(struct bf_set *set, void *elem)
166 : {
167 : _cleanup_free_ void *_elem = NULL;
168 : int r;
169 :
170 0 : bf_assert(set);
171 0 : bf_assert(elem);
172 :
173 0 : _elem = malloc(set->elem_size);
174 0 : if (!_elem)
175 : return -ENOMEM;
176 :
177 0 : memcpy(_elem, elem, set->elem_size);
178 :
179 0 : r = bf_list_add_tail(&set->elems, _elem);
180 0 : if (r < 0)
181 0 : return r;
182 :
183 : TAKE_PTR(_elem);
184 :
185 : return 0;
186 : }
187 :
188 : static const char *_bf_set_type_strs[] = {
189 : [BF_SET_IP4] = "BF_SET_IP4",
190 : [BF_SET_SRCIP6PORT] = "BF_SET_SRCIP6PORT",
191 : [BF_SET_SRCIP6] = "BF_SET_SRCIP6",
192 : };
193 :
194 : static_assert(ARRAY_SIZE(_bf_set_type_strs) == _BF_SET_MAX, "");
195 :
196 0 : const char *bf_set_type_to_str(enum bf_set_type type)
197 : {
198 0 : bf_assert(0 <= type && type < _BF_SET_MAX);
199 :
200 0 : return _bf_set_type_strs[type];
201 : }
202 :
203 0 : int bf_set_type_from_str(const char *str, enum bf_set_type *type)
204 : {
205 0 : bf_assert(str);
206 0 : bf_assert(type);
207 :
208 0 : for (size_t i = 0; i < _BF_SET_MAX; ++i) {
209 0 : if (bf_streq(_bf_set_type_strs[i], str)) {
210 0 : *type = i;
211 0 : return 0;
212 : }
213 : }
214 :
215 : return -EINVAL;
216 : }
|