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/pack.h"
7 :
8 : #include "bpfilter/helper.h"
9 : #include "bpfilter/list.h"
10 : #include "bpfilter/logger.h"
11 : #include "mpack.h"
12 :
13 : struct bf_wpack
14 : {
15 : void *data;
16 : size_t data_len;
17 : size_t data_cap;
18 :
19 : char buffer[64];
20 : mpack_writer_t writer;
21 : };
22 :
23 40 : static void _bf_wpack_writer_flush_cb(mpack_writer_t *writer,
24 : const char *buffer, size_t count)
25 : {
26 40 : bf_wpack_t *pack = writer->context;
27 : int r;
28 :
29 40 : if (pack->data_cap <= pack->data_len + count) {
30 23 : size_t new_cap = pack->data_cap ?: 64;
31 :
32 38 : while (new_cap <= pack->data_len + count)
33 15 : new_cap <<= 1;
34 :
35 23 : r = bf_realloc(&pack->data, new_cap);
36 23 : if (r)
37 0 : mpack_writer_flag_error(writer, mpack_error_memory);
38 :
39 23 : pack->data_cap = new_cap;
40 : }
41 :
42 40 : memcpy(pack->data + pack->data_len, buffer, count);
43 40 : pack->data_len += count;
44 40 : }
45 :
46 8 : int bf_wpack_new(bf_wpack_t **pack)
47 : {
48 : bf_wpack_t *_pack = NULL;
49 :
50 8 : bf_assert(pack);
51 :
52 8 : _pack = malloc(sizeof(*_pack));
53 8 : if (!_pack)
54 : return -ENOMEM;
55 :
56 8 : _pack->data = NULL;
57 8 : _pack->data_cap = 0;
58 8 : _pack->data_len = 0;
59 :
60 8 : mpack_writer_init(&_pack->writer, _pack->buffer, 64);
61 :
62 : /* Use a custom flush function so we can control the flush
63 : * (e.g. when get_data() is called). */
64 8 : mpack_writer_set_flush(&_pack->writer, _bf_wpack_writer_flush_cb);
65 : mpack_writer_set_context(&_pack->writer, _pack);
66 :
67 8 : mpack_build_map(&_pack->writer);
68 :
69 8 : *pack = TAKE_PTR(_pack);
70 :
71 8 : return 0;
72 : }
73 :
74 8 : void bf_wpack_free(bf_wpack_t **pack)
75 : {
76 : bf_wpack_t *_pack;
77 :
78 8 : bf_assert(pack);
79 :
80 8 : _pack = *pack;
81 8 : if (!_pack)
82 : return;
83 :
84 8 : mpack_writer_destroy(&_pack->writer);
85 :
86 : freep((void *)&_pack->data);
87 : freep((void *)pack);
88 : }
89 :
90 71 : bool bf_wpack_is_valid(bf_wpack_t *pack)
91 : {
92 : mpack_error_t error;
93 :
94 71 : bf_assert(pack);
95 :
96 : error = mpack_writer_error(&pack->writer);
97 71 : if (error != mpack_ok)
98 0 : return false;
99 :
100 : return true;
101 : }
102 :
103 8 : int bf_wpack_get_data(bf_wpack_t *pack, const void **data, size_t *data_len)
104 : {
105 8 : bf_assert(pack);
106 8 : bf_assert(data);
107 8 : bf_assert(data_len);
108 :
109 8 : mpack_complete_map(&pack->writer);
110 :
111 8 : mpack_writer_flush_message(&pack->writer);
112 8 : if (!bf_wpack_is_valid(pack))
113 : return -EINVAL;
114 :
115 8 : *data_len = pack->data_len;
116 8 : *data = pack->data;
117 :
118 8 : return 0;
119 : }
120 :
121 2 : void bf_wpack_nil(bf_wpack_t *pack)
122 : {
123 2 : mpack_write_nil(&pack->writer);
124 2 : }
125 :
126 61 : void bf_wpack_int(bf_wpack_t *pack, int value)
127 : {
128 61 : mpack_write_int(&pack->writer, value);
129 61 : }
130 :
131 0 : void bf_wpack_uint(bf_wpack_t *pack, unsigned int value)
132 : {
133 0 : mpack_write_uint(&pack->writer, value);
134 0 : }
135 :
136 5 : void bf_wpack_u8(bf_wpack_t *pack, uint8_t value)
137 : {
138 5 : mpack_write_u8(&pack->writer, value);
139 5 : }
140 :
141 0 : void bf_wpack_u16(bf_wpack_t *pack, uint16_t value)
142 : {
143 0 : mpack_write_u16(&pack->writer, value);
144 0 : }
145 :
146 5 : void bf_wpack_u32(bf_wpack_t *pack, uint32_t value)
147 : {
148 5 : mpack_write_u32(&pack->writer, value);
149 5 : }
150 :
151 39 : void bf_wpack_u64(bf_wpack_t *pack, uint64_t value)
152 : {
153 39 : mpack_write_u64(&pack->writer, value);
154 39 : }
155 :
156 5 : void bf_wpack_bool(bf_wpack_t *pack, bool value)
157 : {
158 5 : mpack_write_bool(&pack->writer, value);
159 5 : }
160 :
161 179 : void bf_wpack_str(bf_wpack_t *pack, const char *value)
162 : {
163 179 : mpack_write_cstr(&pack->writer, value);
164 179 : }
165 :
166 36 : void bf_wpack_bin(bf_wpack_t *pack, const void *value, size_t len)
167 : {
168 36 : bf_assert(pack);
169 36 : bf_assert(value);
170 :
171 36 : mpack_write_bin(&pack->writer, value, len);
172 36 : }
173 :
174 10 : void bf_wpack_list(bf_wpack_t *pack, const bf_list *value)
175 : {
176 : int r;
177 :
178 10 : bf_assert(pack);
179 10 : bf_assert(value);
180 :
181 10 : bf_wpack_open_array(pack, NULL);
182 10 : r = bf_list_pack(value, pack);
183 10 : if (r)
184 0 : mpack_writer_flag_error(&pack->writer, mpack_error_invalid);
185 10 : bf_wpack_close_array(pack);
186 10 : }
187 :
188 10 : void bf_wpack_kv_list(bf_wpack_t *pack, const char *key, const bf_list *value)
189 : {
190 10 : bf_wpack_str(pack, key);
191 10 : bf_wpack_list(pack, value);
192 10 : }
193 :
194 45 : void bf_wpack_open_object(bf_wpack_t *pack, const char *key)
195 : {
196 45 : bf_assert(pack);
197 :
198 45 : if (key)
199 1 : mpack_write_cstr(&pack->writer, key);
200 :
201 45 : mpack_build_map(&pack->writer);
202 45 : }
203 :
204 45 : void bf_wpack_close_object(bf_wpack_t *pack)
205 : {
206 45 : bf_assert(pack);
207 :
208 45 : mpack_complete_map(&pack->writer);
209 45 : }
210 :
211 13 : void bf_wpack_open_array(bf_wpack_t *pack, const char *key)
212 : {
213 13 : bf_assert(pack);
214 :
215 13 : if (key)
216 3 : mpack_write_cstr(&pack->writer, key);
217 :
218 13 : mpack_build_array(&pack->writer);
219 13 : }
220 :
221 13 : void bf_wpack_close_array(bf_wpack_t *pack)
222 : {
223 13 : bf_assert(pack);
224 :
225 13 : mpack_complete_array(&pack->writer);
226 13 : }
227 :
228 : struct bf_rpack
229 : {
230 : const void *data;
231 : size_t data_len;
232 :
233 : mpack_tree_t tree;
234 : mpack_node_t root;
235 : };
236 :
237 8 : int bf_rpack_new(bf_rpack_t **pack, const void *data, size_t data_len)
238 : {
239 8 : _free_bf_rpack_ bf_rpack_t *_pack = NULL;
240 : mpack_error_t error;
241 :
242 8 : bf_assert(pack);
243 :
244 8 : _pack = calloc(1, sizeof(*_pack));
245 8 : if (!_pack)
246 : return -ENOMEM;
247 :
248 8 : _pack->data = data;
249 8 : _pack->data_len = data_len;
250 :
251 8 : mpack_tree_init_data(&_pack->tree, data, data_len);
252 :
253 8 : mpack_tree_parse(&_pack->tree);
254 8 : error = mpack_tree_error(&_pack->tree);
255 8 : if (error != mpack_ok) {
256 0 : return bf_err_r(-EINVAL, "failed to parse bf_rpack_t data: %s",
257 : mpack_error_to_string(error));
258 : }
259 :
260 8 : _pack->root = mpack_tree_root(&_pack->tree);
261 :
262 8 : *pack = TAKE_PTR(_pack);
263 :
264 8 : return 0;
265 : }
266 :
267 16 : void bf_rpack_free(bf_rpack_t **pack)
268 : {
269 : bf_rpack_t *_pack;
270 :
271 16 : bf_assert(pack);
272 :
273 16 : _pack = *pack;
274 16 : if (!_pack)
275 : return;
276 :
277 8 : mpack_tree_destroy(&_pack->tree);
278 : freep((void *)pack);
279 : }
280 :
281 : #define MP_NODE(node) (*(mpack_node_t *)&(node))
282 : #define BF_NODE(node) (*(bf_rpack_node_t *)(mpack_node_t[]) {node})
283 :
284 : _Static_assert(sizeof(bf_rpack_node_t) >= sizeof(mpack_node_t),
285 : "bf_rpack_node_t too small for mpack_node_t");
286 :
287 8 : bf_rpack_node_t bf_rpack_root(const bf_rpack_t *pack)
288 : {
289 8 : return BF_NODE(pack->root);
290 : }
291 :
292 126 : size_t bf_rpack_array_count(bf_rpack_node_t node)
293 : {
294 126 : return mpack_node_array_length(MP_NODE(node));
295 : }
296 :
297 2 : bool bf_rpack_is_nil(bf_rpack_node_t node)
298 : {
299 2 : if (mpack_node_error(MP_NODE(node)) != mpack_ok)
300 : return false;
301 :
302 2 : return mpack_node_type(MP_NODE(node)) == mpack_type_nil;
303 : }
304 :
305 0 : bool bf_rpack_is_array(bf_rpack_node_t node)
306 : {
307 0 : if (mpack_node_error(MP_NODE(node)) != mpack_ok)
308 : return false;
309 :
310 0 : return mpack_node_type(MP_NODE(node)) == mpack_type_array;
311 : }
312 :
313 50 : bf_rpack_node_t bf_rpack_array_value_at(bf_rpack_node_t node, size_t index)
314 : {
315 50 : return BF_NODE(mpack_node_array_at(MP_NODE(node), index));
316 : }
317 :
318 0 : bool bf_rpack_kv_contains(bf_rpack_node_t node, const char *key)
319 : {
320 0 : return mpack_node_map_contains_cstr(MP_NODE(node), key);
321 : }
322 :
323 172 : int bf_rpack_kv_node(bf_rpack_node_t node, const char *key,
324 : bf_rpack_node_t *child)
325 : {
326 172 : mpack_node_t _node = MP_NODE(node);
327 :
328 172 : bf_assert(key);
329 172 : bf_assert(child);
330 :
331 172 : if (mpack_node_error(_node) != mpack_ok)
332 : return -EINVAL;
333 :
334 172 : if (mpack_node_type(_node) != mpack_type_map)
335 : return -EDOM;
336 :
337 172 : if (!mpack_node_map_contains_cstr(_node, key))
338 : return -ENOENT;
339 :
340 172 : *child = BF_NODE(mpack_node_map_cstr(_node, key));
341 :
342 172 : return 0;
343 : }
344 :
345 61 : int bf_rpack_int(bf_rpack_node_t node, int *value)
346 : {
347 61 : mpack_node_t _node = MP_NODE(node);
348 : int _value;
349 :
350 : /* Signed integere are sometimes stored as unsigned integer for optimization
351 : * purposes. While not ideal, we should allow the node to be an unsigned
352 : * integer. */
353 122 : if (mpack_node_type(_node) != mpack_type_int &&
354 61 : mpack_node_type(_node) != mpack_type_uint)
355 : return -EDOM;
356 :
357 61 : _value = mpack_node_int(_node);
358 61 : if (mpack_node_error(_node) != mpack_ok)
359 : return -EINVAL;
360 :
361 61 : *value = _value;
362 :
363 61 : return 0;
364 : }
365 :
366 58 : int bf_rpack_kv_int(bf_rpack_node_t node, const char *key, int *value)
367 : {
368 : bf_rpack_node_t child;
369 : int r;
370 :
371 58 : r = bf_rpack_kv_node(node, key, &child);
372 58 : if (r)
373 : return r;
374 :
375 58 : return bf_rpack_int(child, value);
376 : }
377 :
378 0 : int bf_rpack_uint(bf_rpack_node_t node, unsigned int *value)
379 : {
380 0 : mpack_node_t _node = MP_NODE(node);
381 : unsigned int _value;
382 :
383 0 : if (mpack_node_error(_node) != mpack_ok)
384 : return -EINVAL;
385 :
386 0 : if (mpack_node_type(_node) != mpack_type_uint)
387 : return -EDOM;
388 :
389 0 : _value = mpack_node_uint(_node);
390 0 : if (mpack_node_error(_node) != mpack_ok)
391 : return -EINVAL;
392 :
393 0 : *value = _value;
394 :
395 0 : return 0;
396 : }
397 :
398 0 : int bf_rpack_kv_uint(bf_rpack_node_t node, const char *key, unsigned int *value)
399 : {
400 : bf_rpack_node_t child;
401 : int r;
402 :
403 0 : r = bf_rpack_kv_node(node, key, &child);
404 0 : if (r)
405 : return r;
406 :
407 0 : return bf_rpack_uint(child, value);
408 : }
409 :
410 5 : int bf_rpack_u8(bf_rpack_node_t node, uint8_t *value)
411 : {
412 5 : mpack_node_t _node = MP_NODE(node);
413 : uint8_t _value;
414 :
415 5 : if (mpack_node_error(_node) != mpack_ok)
416 : return -EINVAL;
417 :
418 5 : if (mpack_node_type(_node) != mpack_type_uint)
419 : return -EDOM;
420 :
421 5 : _value = mpack_node_u8(_node);
422 5 : if (mpack_node_error(_node) != mpack_ok)
423 : return -EINVAL;
424 :
425 5 : *value = _value;
426 :
427 5 : return 0;
428 : }
429 :
430 5 : int bf_rpack_kv_u8(bf_rpack_node_t node, const char *key, uint8_t *value)
431 : {
432 : bf_rpack_node_t child;
433 : int r;
434 :
435 5 : r = bf_rpack_kv_node(node, key, &child);
436 5 : if (r)
437 : return r;
438 :
439 5 : return bf_rpack_u8(child, value);
440 : }
441 :
442 0 : int bf_rpack_u16(bf_rpack_node_t node, uint16_t *value)
443 : {
444 0 : mpack_node_t _node = MP_NODE(node);
445 : uint16_t _value;
446 :
447 0 : if (mpack_node_error(_node) != mpack_ok)
448 : return -EINVAL;
449 :
450 0 : if (mpack_node_type(_node) != mpack_type_uint)
451 : return -EDOM;
452 :
453 0 : _value = mpack_node_u16(_node);
454 0 : if (mpack_node_error(_node) != mpack_ok)
455 : return -EINVAL;
456 :
457 0 : *value = _value;
458 :
459 0 : return 0;
460 : }
461 :
462 0 : int bf_rpack_kv_u16(bf_rpack_node_t node, const char *key, uint16_t *value)
463 : {
464 : bf_rpack_node_t child;
465 : int r;
466 :
467 0 : r = bf_rpack_kv_node(node, key, &child);
468 0 : if (r)
469 : return r;
470 :
471 0 : return bf_rpack_u16(child, value);
472 : }
473 :
474 5 : int bf_rpack_u32(bf_rpack_node_t node, uint32_t *value)
475 : {
476 5 : mpack_node_t _node = MP_NODE(node);
477 : uint32_t _value;
478 :
479 5 : if (mpack_node_error(_node) != mpack_ok)
480 : return -EINVAL;
481 :
482 5 : if (mpack_node_type(_node) != mpack_type_uint)
483 : return -EDOM;
484 :
485 5 : _value = mpack_node_u32(_node);
486 5 : if (mpack_node_error(_node) != mpack_ok)
487 : return -EINVAL;
488 :
489 5 : *value = _value;
490 :
491 5 : return 0;
492 : }
493 :
494 5 : int bf_rpack_kv_u32(bf_rpack_node_t node, const char *key, uint32_t *value)
495 : {
496 : bf_rpack_node_t child;
497 : int r;
498 :
499 5 : r = bf_rpack_kv_node(node, key, &child);
500 5 : if (r)
501 : return r;
502 :
503 5 : return bf_rpack_u32(child, value);
504 : }
505 :
506 39 : int bf_rpack_u64(bf_rpack_node_t node, uint64_t *value)
507 : {
508 39 : mpack_node_t _node = MP_NODE(node);
509 : uint64_t _value;
510 :
511 39 : if (mpack_node_error(_node) != mpack_ok)
512 : return -EINVAL;
513 :
514 39 : if (mpack_node_type(_node) != mpack_type_uint)
515 : return -EDOM;
516 :
517 39 : _value = mpack_node_u64(_node);
518 39 : if (mpack_node_error(_node) != mpack_ok)
519 : return -EINVAL;
520 :
521 39 : *value = _value;
522 :
523 39 : return 0;
524 : }
525 :
526 39 : int bf_rpack_kv_u64(bf_rpack_node_t node, const char *key, uint64_t *value)
527 : {
528 : bf_rpack_node_t child;
529 : int r;
530 :
531 39 : r = bf_rpack_kv_node(node, key, &child);
532 39 : if (r)
533 : return r;
534 :
535 39 : return bf_rpack_u64(child, value);
536 : }
537 :
538 11 : int bf_rpack_str(bf_rpack_node_t node, char **value)
539 : {
540 11 : mpack_node_t _node = MP_NODE(node);
541 : _cleanup_free_ char *_value = NULL;
542 :
543 11 : if (mpack_node_error(_node) != mpack_ok)
544 : return -EINVAL;
545 :
546 11 : if (mpack_node_type(_node) != mpack_type_str)
547 : return -EDOM;
548 :
549 11 : _value = mpack_node_cstr_alloc(_node, mpack_node_strlen(_node) + 1);
550 11 : if (mpack_node_error(_node) != mpack_ok)
551 : return -EINVAL;
552 :
553 11 : *value = TAKE_PTR(_value);
554 :
555 11 : return 0;
556 : }
557 :
558 11 : int bf_rpack_kv_str(bf_rpack_node_t node, const char *key, char **value)
559 : {
560 : bf_rpack_node_t child;
561 : int r;
562 :
563 11 : bf_assert(key);
564 11 : bf_assert(value);
565 :
566 11 : r = bf_rpack_kv_node(node, key, &child);
567 11 : if (r)
568 : return r;
569 :
570 11 : return bf_rpack_str(child, value);
571 : }
572 :
573 5 : int bf_rpack_bool(bf_rpack_node_t node, bool *value)
574 : {
575 5 : mpack_node_t _node = MP_NODE(node);
576 : bool _value;
577 :
578 5 : if (mpack_node_error(_node) != mpack_ok)
579 : return -EINVAL;
580 :
581 5 : if (mpack_node_type(_node) != mpack_type_bool)
582 : return -EDOM;
583 :
584 5 : _value = mpack_node_bool(_node);
585 5 : if (mpack_node_error(_node) != mpack_ok)
586 : return -EINVAL;
587 :
588 5 : *value = _value;
589 :
590 5 : return 0;
591 : }
592 :
593 5 : int bf_rpack_kv_bool(bf_rpack_node_t node, const char *key, bool *value)
594 : {
595 : bf_rpack_node_t child;
596 : int r;
597 :
598 5 : r = bf_rpack_kv_node(node, key, &child);
599 5 : if (r)
600 : return r;
601 :
602 5 : return bf_rpack_bool(child, value);
603 : }
604 :
605 36 : int bf_rpack_bin(bf_rpack_node_t node, const void **data, size_t *data_len)
606 : {
607 36 : mpack_node_t _node = MP_NODE(node);
608 : const void *_data;
609 : size_t _data_len;
610 :
611 36 : if (mpack_node_error(_node) != mpack_ok)
612 : return -EINVAL;
613 :
614 36 : if (mpack_node_type(_node) != mpack_type_bin)
615 : return -EDOM;
616 :
617 36 : _data_len = mpack_node_bin_size(_node);
618 36 : _data = mpack_node_bin_data(_node);
619 36 : if (mpack_node_error(_node) != mpack_ok)
620 : return -EINVAL;
621 :
622 36 : *data = _data;
623 36 : *data_len = _data_len;
624 :
625 36 : return 0;
626 : }
627 :
628 33 : int bf_rpack_kv_bin(bf_rpack_node_t node, const char *key, const void **data,
629 : size_t *data_len)
630 : {
631 : bf_rpack_node_t child;
632 : int r;
633 :
634 33 : r = bf_rpack_kv_node(node, key, &child);
635 33 : if (r)
636 : return r;
637 :
638 33 : return bf_rpack_bin(child, data, data_len);
639 : }
640 :
641 1 : int bf_rpack_kv_obj(bf_rpack_node_t node, const char *key,
642 : bf_rpack_node_t *child)
643 : {
644 : bf_rpack_node_t _child;
645 : int r;
646 :
647 1 : bf_assert(key);
648 1 : bf_assert(child);
649 :
650 1 : r = bf_rpack_kv_node(node, key, &_child);
651 1 : if (r)
652 : return r;
653 :
654 1 : if (mpack_node_type(MP_NODE(_child)) != mpack_type_map)
655 : return -EDOM;
656 :
657 1 : *child = _child;
658 :
659 1 : return 0;
660 : }
661 :
662 13 : int bf_rpack_kv_array(bf_rpack_node_t node, const char *key,
663 : bf_rpack_node_t *child)
664 : {
665 : bf_rpack_node_t _child;
666 : int r;
667 :
668 13 : bf_assert(key);
669 13 : bf_assert(child);
670 :
671 13 : r = bf_rpack_kv_node(node, key, &_child);
672 13 : if (r)
673 : return r;
674 :
675 13 : if (mpack_node_type(MP_NODE(_child)) != mpack_type_array)
676 : return -EDOM;
677 :
678 13 : *child = _child;
679 :
680 13 : return 0;
681 : }
|