The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
value.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Boxed value structures and functions to manipulate them
18 *
19 * @file src/lib/util/value.c
20 *
21 * There are three notional data formats used in the server:
22 *
23 * - #fr_value_box_t are the INTERNAL format. This is usually close to the in-memory representation
24 * of the data, though uint32s and IPs are always converted to/from octets with BIG ENDIAN
25 * uint8 ordering for consistency.
26 * - #fr_value_box_cast is used to convert (cast) #fr_value_box_t between INTERNAL formats.
27 * - #fr_value_box_strdup* is used to ingest nul terminated strings into the INTERNAL format.
28 * - #fr_value_box_memdup* is used to ingest binary data into the INTERNAL format.
29 *
30 * - NETWORK format is the format we send/receive on the wire. It is not a perfect representation
31 * of data packing for all protocols, so you will likely need to overload conversion for some types.
32 * - fr_value_box_to_network is used to convert INTERNAL format data to generic NETWORK format data.
33 * For uint32s, IP addresses etc... This means BIG ENDIAN uint8 ordering.
34 * - fr_value_box_from_network is used to convert packet buffer fragments in NETWORK format to
35 * INTERNAL format.
36 *
37 * - PRESENTATION format is what we print to the screen, and what we get from the user, databases
38 * and configuration files.
39 * - #fr_value_box_aprint is used to convert from INTERNAL to PRESENTATION format.
40 * - #fr_value_box_from_substr is used to convert from PRESENTATION to INTERNAL format.
41 *
42 * @copyright 2014-2017 The FreeRADIUS server project
43 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
44 */
45RCSID("$Id: 48d549c33ffc8ec9d6205e84899bfd98e0aeafc2 $")
46
47#define _VALUE_PRIVATE
48#include <freeradius-devel/util/value.h>
49#undef _VALUE_PRIVATE
50
51#include <freeradius-devel/util/base16.h>
52#include <freeradius-devel/util/size.h>
53
54#include <math.h>
55#include <float.h>
56
57/** Sanity checks
58 *
59 * There should never be an instance where these fail.
60 */
61static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ipv4addr) == 4,
62 "in_addr.s_addr has unexpected length");
63static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ipv6addr) == 16,
64 "in6_addr.s6_addr has unexpected length");
65static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ifid) == 8,
66 "vb_ifid has unexpected length");
67static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ether) == 6,
68 "vb_ether has unexpected length");
69
70static_assert(SIZEOF_MEMBER(fr_value_box_t, datum.boolean) == 1,
71 "datum.boolean has unexpected length");
72static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint8) == 1,
73 "vb_uint8 has unexpected length");
74static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint16) == 2,
75 "vb_uint16 has unexpected length");
76static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint32) == 4,
77 "vb_uint32 has unexpected length");
78static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint64) == 8,
79 "vb_uint64 has unexpected length");
80
81static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int8) == 1,
82 "vb_int8 has unexpected length");
83static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int16) == 2,
84 "vb_int16 has unexpected length");
85static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int32) == 4,
86 "vb_int32 has unexpected length");
87static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int64) == 8,
88 "vb_int64 has unexpected length");
89
90static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float32) == 4,
91 "vb_float32 has unexpected length");
92static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float64) == 8,
93 "vb_float64 has unexpected length");
94
95/** How many bytes on-the-wire would a #fr_value_box_t value consume
96 *
97 * This is for the generic NETWORK format. For field sizes in the in-memory
98 * structure use #fr_value_box_field_sizes.
99 *
100 * @note Don't use this array directly when determining the length
101 * that would be consumed by the on-the-wire representation.
102 * Use #fr_value_box_network_length instead, as that deals with variable
103 * length attributes too.
104 */
105#define network_min_size(_x) (fr_value_box_network_sizes[_x][0])
106#define network_max_size(_x) (fr_value_box_network_sizes[_x][1])
107static size_t const fr_value_box_network_sizes[FR_TYPE_MAX + 1][2] = {
108 [FR_TYPE_NULL] = {~0, 0},
109
110 [FR_TYPE_STRING] = {0, ~0},
111 [FR_TYPE_OCTETS] = {0, ~0},
112
113 [FR_TYPE_IPV4_ADDR] = {4, 4},
114 [FR_TYPE_IPV4_PREFIX] = {5, 5},
115 [FR_TYPE_IPV6_ADDR] = {16, 17},
116 [FR_TYPE_IPV6_PREFIX] = {17, 18},
117 [FR_TYPE_COMBO_IP_ADDR] = {4, 17},
118 [FR_TYPE_COMBO_IP_PREFIX] = {16, 18},
119 [FR_TYPE_IFID] = {8, 8},
120 [FR_TYPE_ETHERNET] = {6, 6},
121
122 [FR_TYPE_BOOL] = {1, 1},
123 [FR_TYPE_UINT8] = {1, 1},
124 [FR_TYPE_UINT16] = {2, 2},
125 [FR_TYPE_UINT32] = {4, 4},
126 [FR_TYPE_UINT64] = {8, 8},
127
128 [FR_TYPE_INT8] = {1, 1},
129 [FR_TYPE_INT16] = {2, 2},
130 [FR_TYPE_INT32] = {4, 4},
131 [FR_TYPE_INT64] = {8, 8},
132
133 [FR_TYPE_SIZE] = {8, 8},
134
135 [FR_TYPE_FLOAT32] = {4, 4},
136 [FR_TYPE_FLOAT64] = {8, 8},
137
138 [FR_TYPE_DATE] = {2, 8}, //!< 2, 4, or 8 only
139 [FR_TYPE_TIME_DELTA] = {2, 8}, //!< 2, 4, or 8 only
140
141 [FR_TYPE_ATTR] = {1, ~0},
142
143 [FR_TYPE_MAX] = {~0, 0} //!< Ensure array covers all types.
144};
145
146/** How many bytes wide each of the value data fields are
147 *
148 * This is useful when copying a value from a fr_value_box_t to a memory
149 * location passed as a void *.
150 */
151size_t const fr_value_box_field_sizes[] = {
154
163
164 [FR_TYPE_BOOL] = SIZEOF_MEMBER(fr_value_box_t, datum.boolean),
169
174
177
179
180 [FR_TYPE_TIME_DELTA] = SIZEOF_MEMBER(fr_value_box_t, datum.time_delta),
182
184
186
187 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
188};
189
190/** Where the value starts in the #fr_value_box_t
191 *
192 */
193size_t const fr_value_box_offsets[] = {
196
203 [FR_TYPE_IFID] = offsetof(fr_value_box_t, vb_ifid),
205
206 [FR_TYPE_BOOL] = offsetof(fr_value_box_t, vb_bool),
211
212 [FR_TYPE_INT8] = offsetof(fr_value_box_t, vb_int8),
216
219
220 [FR_TYPE_DATE] = offsetof(fr_value_box_t, vb_date),
221
223 [FR_TYPE_SIZE] = offsetof(fr_value_box_t, vb_size),
224 [FR_TYPE_ATTR] = offsetof(fr_value_box_t, vb_attr),
225
226 [FR_TYPE_VALUE_BOX] = 0,
227
228 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
229};
230
231static uint64_t const fr_value_box_integer_max[] = {
232 [FR_TYPE_BOOL] = true,
234 [FR_TYPE_UINT16] = UINT16_MAX,
235 [FR_TYPE_UINT32] = UINT32_MAX,
236 [FR_TYPE_UINT64] = UINT64_MAX,
237
238 [FR_TYPE_INT8] = INT8_MAX,
239 [FR_TYPE_INT16] = INT16_MAX,
240 [FR_TYPE_INT32] = INT32_MAX,
241 [FR_TYPE_INT64] = INT64_MAX,
242
243 [FR_TYPE_DATE] = UINT64_MAX,
244 [FR_TYPE_TIME_DELTA] = INT64_MAX,
245
246 [FR_TYPE_SIZE] = SIZE_MAX,
247
248 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
249};
250
251static int64_t const fr_value_box_integer_min[] = {
252 [FR_TYPE_BOOL] = false,
253 [FR_TYPE_UINT8] = 0,
254 [FR_TYPE_UINT16] = 0,
255 [FR_TYPE_UINT32] = 0,
256 [FR_TYPE_UINT64] = 0,
257
258 [FR_TYPE_INT8] = INT8_MIN,
259 [FR_TYPE_INT16] = INT16_MIN,
260 [FR_TYPE_INT32] = INT32_MIN,
261 [FR_TYPE_INT64] = INT64_MIN,
262
263 [FR_TYPE_DATE] = 0,
264 [FR_TYPE_TIME_DELTA] = INT64_MIN,
265
266 [FR_TYPE_SIZE] = 0,
267
268 [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
269};
270
272 .name = "double",
273 .chr = '\\',
274 .subs = {
275 ['"'] = '"', /* Quoting char */
276 ['%'] = '%', /* xlat expansions */
277 ['\\'] = '\\',
278 ['a'] = '\a',
279 ['b'] = '\b',
280 ['e'] = '\\',
281 ['n'] = '\n',
282 ['r'] = '\r',
283 ['t'] = '\t',
284 ['v'] = '\v'
285 },
286 .do_hex = true,
287 .do_oct = true
288};
289
291 .name = "single",
292 .chr = '\\',
293 .subs = {
294 ['\''] = '\'', /* Quoting char */
295 ['\\'] = '\\'
296 },
297 .do_hex = false,
298 .do_oct = false
299};
300
302 .name = "solidus",
303 .chr = '\\',
304 .subs = {
305 ['%'] = '%', /* xlat expansions */
306 ['/'] = '/', /* Quoting char */
307 ['a'] = '\a',
308 ['b'] = '\b',
309 ['e'] = '\\',
310 ['n'] = '\n',
311 ['r'] = '\r',
312 ['t'] = '\t',
313 ['v'] = '\v'
314 },
315 .skip = {
316 ['\\'] = '\\' /* Leave this for the regex library */
317 },
318 .do_hex = true,
319 .do_oct = true
320};
321
323 .name = "backtick",
324 .chr = '\\',
325 .subs = {
326 ['%'] = '%', /* xlat expansions */
327 ['\\'] = '\\',
328 ['`'] = '`', /* Quoting char */
329 ['a'] = '\a',
330 ['b'] = '\b',
331 ['e'] = '\\',
332 ['n'] = '\n',
333 ['r'] = '\r',
334 ['t'] = '\t',
335 ['v'] = '\v'
336 },
337 .do_hex = true,
338 .do_oct = true
339};
340
347
354
356 .name = "double",
357 .chr = '\\',
358 .subs = {
359 ['"'] = '"', /* Quoting char */
360 ['%'] = '%', /* xlat expansions */
361 ['\\'] = '\\',
362 ['\a'] = 'a',
363 ['\b'] = 'b',
364 ['\n'] = 'n',
365 ['\r'] = 'r',
366 ['\t'] = 't',
367 ['\v'] = 'v'
368 },
369 .esc = {
372 },
373 .do_utf8 = true,
374 .do_oct = true
375};
376
377#ifdef __clang__
378#pragma clang diagnostic ignored "-Wgnu-designator"
379#endif
380
381/** Escape secret fields by simply mashing all data to '.'
382 *
383 * The length of the secret still leaks, but that is likely fine. Fixing that is more work.
384 *
385 */
387 .name = "secret",
388 .subs = {
389 [ 0 ... 255 ] = '.',
390 },
391};
392
394 .name = "single",
395 .chr = '\\',
396 .subs = {
397 ['\''] = '\'', /* Quoting char */
398 ['\\'] = '\\'
399 },
400 .do_utf8 = true,
401};
402
404 .name = "solidus",
405 .chr = '\\',
406 .subs = {
407 ['%'] = '%', /* xlat expansions */
408 ['/'] = '/', /* Quoting char */
409 ['\a'] = 'a',
410 ['\b'] = 'b',
411 ['\n'] = 'n',
412 ['\r'] = 'r',
413 ['\t'] = 't',
414 ['\v'] = 'v'
415 },
416 .esc = {
419 },
420 .do_utf8 = true,
421 .do_oct = true
422};
423
425 .name = "backtick",
426 .chr = '\\',
427 .subs = {
428 ['%'] = '%', /* xlat expansions */
429 ['\\'] = '\\',
430 ['`'] = '`', /* Quoting char */
431 ['\a'] = 'a',
432 ['\b'] = 'b',
433 ['\n'] = 'n',
434 ['\r'] = 'r',
435 ['\t'] = 't',
436 ['\v'] = 'v'
437 },
438 .esc = {
441 },
442 .do_utf8 = true,
443 .do_oct = true
444};
445
452
459
461 .name = "unprintables",
462 .chr = '\\',
463 .subs = {
464 ['\\'] = '\\',
465 },
466 .esc = {
469 },
470 .do_utf8 = true,
471 .do_oct = true
472};
473
474
475/** @name Produce a #tmpl_t from a string or substring
476 *
477 * @{
478 */
479
480/* clang-format off */
481/** Default formatting rules
482 *
483 * Control token termination, escaping and how the tmpl is printed.
484 */
485fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted = {
486
487};
488
489fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted = {
490 .escapes = &fr_value_unescape_double
491};
492
493fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted = {
494 .escapes = &fr_value_unescape_single
495};
496
497fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted = {
498 .escapes = &fr_value_unescape_solidus
499};
500
501fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted = {
503};
504
505/** Parse rules for non-quoted strings
506 *
507 * These parse rules should be used for processing escape sequences in
508 * data from external data sources like SQL databases and REST APIs.
509 *
510 * They do not include terminals to stop parsing as it assumes the values
511 * are discrete, and not wrapped in quotes.
512 */
520
528
529fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted = {
530 .escapes = &(fr_sbuff_unescape_rules_t){
531 .chr = '\\',
532 /*
533 * Allow barewords to contain whitespace
534 * if they're escaped.
535 */
536 .subs = {
537 ['\t'] = '\t',
538 ['\n'] = '\n',
539 [' '] = ' '
540 },
541 .do_hex = false,
542 .do_oct = false
543 },
544 .terminals = &FR_SBUFF_TERMS(
545 L(""),
546 L("\t"),
547 L("\n"),
548 L(" ")
549 )
550};
551
552fr_sbuff_parse_rules_t const value_parse_rules_double_quoted = {
553 .escapes = &fr_value_unescape_double,
554 .terminals = &FR_SBUFF_TERMS(
555 L(""), L("\n"), L("\r"), L("\""))
556};
557
558fr_sbuff_parse_rules_t const value_parse_rules_single_quoted = {
559 .escapes = &fr_value_unescape_single,
560 .terminals = &FR_SBUFF_TERMS(
561 L(""), L("\n"), L("\r"), L("'"))
562};
563
564fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted = {
565 .escapes = &fr_value_unescape_solidus,
566 .terminals = &FR_SBUFF_TERMS(
567 L(""), L("\n"), L("\r"), L("/"))
568};
569
570fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted = {
571 .escapes = &fr_value_unescape_backtick,
572 .terminals = &FR_SBUFF_TERMS(
573 L(""), L("\n"), L("\r"), L("`"))
574};
575
576/*
577 * And triple-quoted versions of the above.
578 */
579fr_sbuff_parse_rules_t const value_parse_rules_double_3quoted = {
580 .escapes = &fr_value_unescape_double,
581 .terminals = &FR_SBUFF_TERMS(
582 L(""), L("\n"), L("\r"), L("\"\"\""))
583};
584
585fr_sbuff_parse_rules_t const value_parse_rules_single_3quoted = {
586 .escapes = &fr_value_unescape_single,
587 .terminals = &FR_SBUFF_TERMS(
588 L(""), L("\n"), L("\r"), L("'''"))
589};
590
591fr_sbuff_parse_rules_t const value_parse_rules_solidus_3quoted = {
592 .escapes = &fr_value_unescape_solidus,
593 .terminals = &FR_SBUFF_TERMS(
594 L(""), L("\n"), L("\r"), L("///"))
595};
596
597fr_sbuff_parse_rules_t const value_parse_rules_backtick_3quoted = {
598 .escapes = &fr_value_unescape_backtick,
599 .terminals = &FR_SBUFF_TERMS(
600 L(""), L("\n"), L("\r"), L("```"))
601};
602
603/** Parse rules for quoted strings
604 *
605 * These parse rules should be used for internal parsing functions that
606 * are working with configuration files.
607 *
608 * They include appropriate quote terminals to force functions parsing
609 * quoted strings to return when they reach a quote character.
610 */
618
626
634
635/* clang-format on */
636/** @} */
637
638/** Copy flags and type data from one value box to another
639 *
640 * @param[in] dst to copy flags to
641 * @param[in] src of data.
642 */
643static inline void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t const *src)
644{
645 switch (src->type) {
647 dst->vb_length = src->vb_length;
648 break;
649 /*
650 * Not 100% sure this should be done here
651 * but if the intent is to make a null
652 * box usable, then we need to do this
653 * somewhere.
654 */
655 case FR_TYPE_GROUP:
656 fr_value_box_list_init(&dst->vb_group);
657 break;
658
659 case FR_TYPE_NUMERIC:
660 case FR_TYPE_IP:
661 case FR_TYPE_IFID:
662 case FR_TYPE_ETHERNET:
663 case FR_TYPE_ATTR:
664 case FR_TYPE_NULL:
665 case FR_TYPE_VOID:
669 break;
670
671 case FR_TYPE_TLV:
672 case FR_TYPE_STRUCT:
673 case FR_TYPE_VSA:
674 case FR_TYPE_VENDOR:
675 case FR_TYPE_UNION:
676 case FR_TYPE_MAX:
677 fr_assert(0);
678 break;
679 }
680
681#ifndef NDEBUG
682 dst->magic = FR_VALUE_BOX_MAGIC;
683#endif
684#if defined(WITH_VERIFY_PTR) || !defined(NDEBUG)
685 dst->file = src->file;
686 dst->line = src->line;
687#endif
688
689 dst->enumv = src->enumv;
690 dst->type = src->type;
691 dst->tainted = src->tainted;
692 dst->vb_safefor = src->vb_safefor;
693 dst->vb_secret = src->vb_secret;
694 fr_value_box_list_entry_init(dst);
695
696 /*
697 * We have no idea if this is true, but we can't _guarantee_ it. So we clear the flag.
698 */
699 dst->talloced = false;
700}
701
702/** Compare two floating point numbers for equality.
703 *
704 * We're not _quite_ supposed to use DBL_EPSILON here, and are instead supposed to choose our own epsilon.
705 * But this is good enough for most purposed.
706 */
707static int8_t float_cmp(double a, double b)
708{
709 double sum, diff;
710
711 /*
712 * Handles the best cast scenario.
713 */
714DIAG_OFF(float-equal)
715 if (a == b) return 0;
716DIAG_ON(float-equal)
717
718 diff = fabs(a - b);
719
720 /*
721 * One of the numbers is zero. The other might be close to zero, in which case it might as well
722 * be zero.
723 *
724 * Otherwise, the non-zero number is far from zero, and we can just compare them.
725 */
726 if ((fpclassify(a) == FP_ZERO) || (fpclassify(b) == FP_ZERO)) {
727 check:
728 if (diff < DBL_EPSILON) return 0;
729
730 return CMP(a, b);
731 }
732
733 /*
734 * Get the rough scale of the two numbers.
735 */
736 sum = fabs(a) + fabs(b);
737
738 /*
739 * The two numbers are not zero, but both are close to it.
740 */
741 if (sum < DBL_MIN) goto check;
742
743 /*
744 * Get the relative differences. This check also handles overflow of sum.
745 */
746 if ((diff / fmin(sum, DBL_MAX)) < DBL_EPSILON) return 0;
747
748 return CMP(a, b);
749}
750
751/** Compare two values
752 *
753 * @param[in] a Value to compare.
754 * @param[in] b Value to compare.
755 * @return
756 * - CMP_LT if a is less than b.
757 * - CMP_EQ if both are equal.
758 * - CMP_GT if a is more than b.
759 * - CMP_ERR if the values are not comparable, retrieve the error with fr_strerror.
760 */
762{
763 if (a->type != b->type) {
764 fr_strerror_printf("%s: Can't compare values of different types", __FUNCTION__);
765 return CMP_ERR;
766 }
767
768 /*
769 * After doing the previous check for special comparisons,
770 * do the per-type comparison here.
771 */
772 switch (a->type) {
774 /*
775 * Note that we do NOT check a->vb_secret or b->vb_secret. This function is used to sort pairs
776 * and sets of value-boxes. The fr_digest_cmp() function returns 0..255 no matter what
777 * the two inputs are. So it can't be used in a stable sort.
778 */
779 return MEMCMP_FIELDS(a, b, datum.ptr, vb_length);
780
781 /*
782 * Short-hand for simplicity.
783 */
784#define RETURN(_type) return CMP(a->datum._type, b->datum._type)
785#define COMPARE(_type) return CMP(memcmp(&a->datum._type, &b->datum._type, sizeof(a->datum._type)), 0)
786
787 case FR_TYPE_BOOL:
788 RETURN(boolean);
789
790 case FR_TYPE_DATE:
791 return fr_unix_time_cmp(a->datum.date, b->datum.date);
792
793 case FR_TYPE_UINT8:
794 RETURN(uint8);
795
796 case FR_TYPE_UINT16:
797 RETURN(uint16);
798
799 case FR_TYPE_UINT32:
800 RETURN(uint32);
801
802 case FR_TYPE_UINT64:
803 RETURN(uint64);
804
805 case FR_TYPE_INT8:
806 RETURN(int8);
807
808 case FR_TYPE_INT16:
809 RETURN(int16);
810
811 case FR_TYPE_INT32:
812 RETURN(int32);
813
814 case FR_TYPE_INT64:
815 RETURN(int64);
816
817 case FR_TYPE_SIZE:
818 RETURN(size);
819
821 return fr_time_delta_cmp(a->datum.time_delta, b->datum.time_delta);
822
823 case FR_TYPE_FLOAT32:
824 return float_cmp(a->vb_float32, b->vb_float32);
825
826 case FR_TYPE_FLOAT64:
827 return float_cmp(a->vb_float64, b->vb_float64);
828
829 case FR_TYPE_ETHERNET:
830 COMPARE(ether);
831
838 return fr_ipaddr_cmp(&a->vb_ip, &b->vb_ip);
839
840 case FR_TYPE_IFID:
841 COMPARE(ifid);
842
843 case FR_TYPE_NULL: /* NULLs are not comparable */
844 fr_strerror_const("NULL values are not comparable");
845 return CMP_ERR;
846
847 case FR_TYPE_ATTR:
848 /*
849 * @todo - this makes things _distinct_, but doesn't provide a _full_ order. We
850 * generally don't need a full ordering for attributes.
851 *
852 * The need to call fr_dict_attr_cmp() here is for comparing raw / unknown attributes
853 * which come from xlats. Unknown / raw attributes which are in policies are added to
854 * the dictionaries when the server starts, and are thus known.
855 */
856 return fr_dict_attr_cmp(a->vb_attr, b->vb_attr);
857
858 case FR_TYPE_VOID:
859 return CMP(a->vb_void, b->vb_void);
860
865 case FR_TYPE_MAX:
866 break;
867
868 /*
869 * Do NOT add a default here, as new types are added
870 * static analysis will warn us they're not handled
871 */
872 }
873
874 (void)fr_cond_assert(0); /* invalud type for leaf comparison */
875 fr_strerror_printf("Invalid type %s for leaf comparison", fr_type_to_str(a->type));
876 return CMP_ERR;
877}
878
879/*
880 * We leverage the fact that IPv4 and IPv6 prefixes both
881 * have the same format:
882 *
883 * reserved, prefix-len, data...
884 */
885static int fr_value_box_cidr_cmp_op(fr_token_t op, int bytes,
886 uint8_t a_net, uint8_t const *a,
887 uint8_t b_net, uint8_t const *b)
888{
889 int i, common;
891
892 /*
893 * Handle the case of netmasks being identical.
894 */
895 if (a_net == b_net) {
896 int compare;
897
898 compare = memcmp(a, b, bytes);
899
900 /*
901 * If they're identical return true for
902 * identical.
903 */
904 if ((compare == 0) &&
905 ((op == T_OP_CMP_EQ) ||
906 (op == T_OP_LE) ||
907 (op == T_OP_GE))) {
908 return true;
909 }
910
911 /*
912 * Everything else returns false.
913 *
914 * 10/8 == 24/8 --> false
915 * 10/8 <= 24/8 --> false
916 * 10/8 >= 24/8 --> false
917 */
918 return false;
919 }
920
921 /*
922 * Netmasks are different. That limits the
923 * possible results, based on the operator.
924 */
925 switch (op) {
926 case T_OP_CMP_EQ:
927 return false;
928
929 case T_OP_NE:
930 return true;
931
932 case T_OP_LE:
933 case T_OP_LT: /* 192/8 < 192.168/16 --> false */
934 if (a_net < b_net) {
935 return false;
936 }
937 break;
938
939 case T_OP_GE:
940 case T_OP_GT: /* 192/16 > 192.168/8 --> false */
941 if (a_net > b_net) {
942 return false;
943 }
944 break;
945
946 default:
947 return false;
948 }
949
950 if (a_net < b_net) {
951 common = a_net;
952 } else {
953 common = b_net;
954 }
955
956 /*
957 * Do the check uint8 by uint8. If the bytes are
958 * identical, it MAY be a match. If they're different,
959 * it is NOT a match.
960 */
961 i = 0;
962 while (i < bytes) {
963 /*
964 * All leading bytes are identical.
965 */
966 if (common == 0) return true;
967
968 /*
969 * Doing bitmasks takes more work.
970 */
971 if (common < 8) break;
972
973 if (a[i] != b[i]) return false;
974
975 common -= 8;
976 i++;
977 continue;
978 }
979
980 mask = 1;
981 mask <<= (8 - common);
982 mask--;
983 mask = ~mask;
984
985 if ((a[i] & mask) == ((b[i] & mask))) {
986 return true;
987 }
988
989 return false;
990}
991
992/*
993 * So we don't have to include <util/regex.h> in a recursive fashion.
994 */
995extern int fr_regex_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b);
996
997/** Compare two attributes using an operator
998 *
999 * @param[in] op to use in comparison.
1000 * @param[in] a Value to compare.
1001 * @param[in] b Value to compare.
1002 * @return
1003 * - 1 if true
1004 * - 0 if false
1005 * - -1 on failure.
1006 * - < -1 on failure.
1007 */
1009{
1010 int compare = 0;
1011
1012 if (unlikely((op == T_OP_REG_EQ) || (op == T_OP_REG_NE))) return fr_regex_cmp_op(op, a, b);
1013
1016
1017 switch (a->type) {
1018 case FR_TYPE_IPV4_ADDR:
1019 switch (b->type) {
1021 if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1023
1024 case FR_TYPE_IPV4_ADDR: /* IPv4 and IPv4 */
1025 goto cmp;
1026
1028 if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1030
1031 case FR_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
1032 return fr_value_box_cidr_cmp_op(op, 4, 32, (uint8_t const *) &a->vb_ipv4addr,
1033 b->vb_ip.prefix, (uint8_t const *) &b->vb_ipv4addr);
1034
1035 default:
1036 fail_cmp_v4:
1037 fr_strerror_const("Cannot compare IPv4 with IPv6 address");
1038 return -1;
1039 }
1040
1041 case FR_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
1042 cmp_prefix_v4:
1043 switch (b->type) {
1045 if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1047
1048 case FR_TYPE_IPV4_ADDR:
1049 return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
1050 (uint8_t const *) &a->vb_ipv4addr,
1051 32, (uint8_t const *) &b->vb_ip.addr.v4);
1052
1054 if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1056
1057 case FR_TYPE_IPV4_PREFIX: /* IPv4 Prefix and IPv4 Prefix */
1058 return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
1059 (uint8_t const *) &a->vb_ipv4addr,
1060 b->vb_ip.prefix, (uint8_t const *) &b->vb_ipv4addr);
1061
1062 default:
1063 fr_strerror_const("Cannot compare IPv4 with IPv6 address");
1064 return -1;
1065 }
1066
1067 case FR_TYPE_IPV6_ADDR:
1068 switch (b->type) {
1070 if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1072
1073 case FR_TYPE_IPV6_ADDR: /* IPv6 and IPv6 */
1074 goto cmp;
1075
1077 if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1079
1080 case FR_TYPE_IPV6_PREFIX: /* IPv6 and IPv6 Preifx */
1081 return fr_value_box_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->vb_ip.addr.v6,
1082 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1083
1084 default:
1085 fail_cmp_v6:
1086 fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1087 return -1;
1088 }
1089
1091 cmp_prefix_v6:
1092 switch (b->type) {
1094 if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1096
1097 case FR_TYPE_IPV6_ADDR: /* IPv6 Prefix and IPv6 */
1098 return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1099 (uint8_t const *) &a->vb_ip.addr.v6,
1100 128, (uint8_t const *) &b->vb_ip.addr.v6);
1101
1103 if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1105
1106 case FR_TYPE_IPV6_PREFIX: /* IPv6 Prefix and IPv6 */
1107 return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1108 (uint8_t const *) &a->vb_ip.addr.v6,
1109 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1110
1111 default:
1112 fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1113 return -1;
1114 }
1115
1117 if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1118
1119 goto cmp;
1120
1122 if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1123
1124 if (a->vb_ip.af == AF_INET) goto cmp_prefix_v4;
1125
1126 goto cmp_prefix_v6;
1127
1128 case FR_TYPE_NUMERIC:
1129 case FR_TYPE_IFID:
1130 case FR_TYPE_ETHERNET:
1132 case FR_TYPE_ATTR:
1133 case FR_TYPE_NULL:
1134 cmp:
1135 compare = fr_value_box_cmp(a, b);
1136 if (unlikely(compare == CMP_ERR)) return -1;
1137 break;
1138
1139 case FR_TYPE_GROUP:
1140 case FR_TYPE_TLV:
1141 case FR_TYPE_STRUCT:
1142 case FR_TYPE_VSA:
1143 case FR_TYPE_VENDOR:
1144 case FR_TYPE_UNION:
1145 case FR_TYPE_INTERNAL:
1146 fr_assert(0);
1147 return -1;
1148 }
1149
1150 /*
1151 * Now do the operator comparison.
1152 */
1153 switch (op) {
1154 case T_OP_CMP_EQ:
1155 return (compare == 0);
1156
1157 case T_OP_NE:
1158 return (compare != 0);
1159
1160 case T_OP_LT:
1161 return (compare < 0);
1162
1163 case T_OP_GT:
1164 return (compare > 0);
1165
1166 case T_OP_LE:
1167 return (compare <= 0);
1168
1169 case T_OP_GE:
1170 return (compare >= 0);
1171
1172 default:
1173 return 0;
1174 }
1175}
1176
1177/** Convert a string value with escape sequences into its binary form
1178 *
1179 * The quote character determines the escape sequences recognised.
1180 *
1181 * - Literal mode ("'" quote char) will unescape:
1182 @verbatim
1183 - \\ - Literal backslash.
1184 - <quote> - The quotation char.
1185 @endverbatim
1186 * - Expanded mode ('"' quote char) will also unescape:
1187 @verbatim
1188 - \a - Alert.
1189 - \b - Backspace.
1190 - \e - Escape character i.e. (\‍)
1191 - \r - Carriage return.
1192 - \n - Newline.
1193 - \t - Tab.
1194 - \v - Vertical tab
1195 - <oct> - An octal escape sequence.
1196 - \x<hex> - A hex escape sequence.
1197 @endverbatim
1198 * - Backtick mode ('`' quote char) identical to expanded mode.
1199 * - Regex mode ('/') identical to expanded mode but two successive
1200 * backslashes will be interpreted as an escape sequence, but not
1201 * unescaped, so that they will be passed to the underlying regex
1202 * library.
1203 * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1204 *
1205 * @note The resulting output may contain embedded \0s.
1206 * @note Unrecognised escape sequences will be copied verbatim.
1207 * @note In and out may point to the same underlying buffer.
1208 * @note Copying will stop early if an unescaped instance of the
1209 * quoting char is found in the input buffer.
1210 *
1211 * @param[out] len Number of bytes written to out. May be NULL.
1212 * @param[out] out Where to write the unescaped string.
1213 * @param[in] in The string to unescape.
1214 * @param[in] max Maximum number of input bytes to consume. Pass SIZE_MAX
1215 * to consume all data in the input buffer.
1216 * @param[in] quote Character around the string, determines unescaping mode.
1217 *
1218 * @return
1219 * - FR_SBUFF_OK on success, including when the input was empty.
1220 * - FR_SBUFF_ERR_NO_SPACE out filled before the input was consumed.
1221 * - FR_SBUFF_ERR_EXTEND in's extend callback failed.
1222 */
1224{
1225 switch (quote) {
1226 default:
1227 break;
1228
1229 case '"':
1231
1232 case '\'':
1234
1235 case '`':
1237
1238 case '/':
1240 }
1241
1242 return fr_sbuff_out_bstrncpy(len, out, in, max);
1243}
1244
1245/** Convert a string value with escape sequences into its binary form
1246 *
1247 * The quote character determines the escape sequences recognised.
1248 *
1249 * - Literal mode ("'" quote char) will unescape:
1250 @verbatim
1251 - \\ - Literal backslash.
1252 - <quote> - The quotation char.
1253 @endverbatim
1254 * - Expanded mode ('"' quote char) will also unescape:
1255 @verbatim
1256 - \a - Alert.
1257 - \b - Backspace.
1258 - \e - Escape character i.e. (\‍)
1259 - \r - Carriage return.
1260 - \n - Newline.
1261 - \t - Tab.
1262 - \v - Vertical tab
1263 - <oct> - An octal escape sequence.
1264 - \x<hex> - A hex escape sequence.
1265 @endverbatim
1266 * - Backtick mode ('`' quote char) identical to expanded mode.
1267 * - Regex mode ('/') identical to expanded mode but two successive
1268 * backslashes will be interpreted as an escape sequence, but not
1269 * unescaped, so that they will be passed to the underlying regex
1270 * library.
1271 * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1272 *
1273 * @note The resulting output may contain embedded \0s.
1274 * @note Unrecognised escape sequences will be copied verbatim.
1275 * @note In and out may point to the same underlying buffer.
1276 * @note Copying will stop early if an unescaped instance of the
1277 * quoting char is found in the input buffer.
1278 *
1279 * @param[out] len Number of bytes written to out. May be NULL.
1280 * @param[out] out Where to write the unescaped string.
1281 * @param[in] in The string to unescape.
1282 * @param[in] max Maximum number of input bytes to consume. Pass SIZE_MAX
1283 * to consume all data in the input buffer.
1284 * @param[in] quote Character around the string, determines unescaping mode.
1285 *
1286 * @return
1287 * - FR_SBUFF_OK on success, including when the input was empty.
1288 * - FR_SBUFF_ERR_NO_SPACE out filled before the input was consumed.
1289 * - FR_SBUFF_ERR_EXTEND in's extend callback failed.
1290 */
1292{
1293 switch (quote) {
1294 default:
1295 break;
1296
1297 case '"':
1299
1300 case '\'':
1302
1303 case '`':
1305
1306 case '/':
1308 }
1309
1310 return fr_sbuff_out_bstrncpy(len, out, in, max);
1311}
1312
1313/** Performs byte order reversal for types that need it
1314 *
1315 * @param[in] dst Where to write the result. May be the same as src.
1316 * @param[in] src #fr_value_box_t containing an uint32 value.
1317 * @return
1318 * - 0 on success.
1319 * - -1 on failure.
1320 */
1322{
1323 switch (src->type) {
1324 case FR_TYPE_INT16:
1325 case FR_TYPE_INT32:
1326 case FR_TYPE_INT64:
1327 case FR_TYPE_UINT16:
1328 case FR_TYPE_UINT32:
1329 case FR_TYPE_UINT64:
1330 case FR_TYPE_FLOAT32:
1331 case FR_TYPE_FLOAT64:
1332 case FR_TYPE_DATE:
1333 case FR_TYPE_TIME_DELTA:
1334 break;
1335
1336 case FR_TYPE_BOOL:
1337 case FR_TYPE_UINT8:
1338 case FR_TYPE_INT8:
1339 case FR_TYPE_IPV4_ADDR:
1341 case FR_TYPE_IPV6_ADDR:
1345 case FR_TYPE_IFID:
1346 case FR_TYPE_ETHERNET:
1347 case FR_TYPE_SIZE:
1348 if (unlikely(fr_value_box_copy(NULL, dst, src) < 0)) return -1;
1349 return 0;
1350
1351 case FR_TYPE_NULL:
1353 return 0;
1354
1355 case FR_TYPE_ATTR:
1356 case FR_TYPE_OCTETS:
1357 case FR_TYPE_STRING:
1358 case FR_TYPE_INTERNAL:
1359 case FR_TYPE_STRUCTURAL:
1360 fr_assert_fail(NULL);
1361 return -1; /* shouldn't happen */
1362 }
1363
1364 /*
1365 * If we're not just flipping in place
1366 * initialise the destination box
1367 * with similar meta data as the src.
1368 *
1369 * Don't use the copy meta data function
1370 * here as that doesn't initialise the
1371 * destination box.
1372 */
1373 if (dst != src) fr_value_box_init(dst, src->type, src->enumv, src->tainted);
1374
1375 switch (src->type) {
1376 case FR_TYPE_UINT16:
1377 dst->vb_uint16 = htons(src->vb_uint16);
1378 break;
1379
1380 case FR_TYPE_UINT32:
1381 case FR_TYPE_FLOAT32: /* same offset and size as uint32 */
1382 dst->vb_uint32 = htonl(src->vb_uint32);
1383 break;
1384
1385 case FR_TYPE_UINT64:
1386 case FR_TYPE_FLOAT64: /* same offset and size as uint64 */
1387 dst->vb_uint64 = htonll(src->vb_uint64);
1388 break;
1389
1390 case FR_TYPE_INT16:
1391 dst->vb_int16 = htons(src->vb_int16);
1392 break;
1393
1394 case FR_TYPE_INT32:
1395 dst->vb_int32 = htonl(src->vb_int32);
1396 break;
1397
1398 case FR_TYPE_INT64:
1399 dst->vb_int64 = htonll(src->vb_int64);
1400 break;
1401
1402 case FR_TYPE_DATE:
1403 dst->vb_date = fr_unix_time_wrap(htonll(fr_unix_time_unwrap(src->vb_date)));
1404 break;
1405
1406 case FR_TYPE_TIME_DELTA:
1407 dst->vb_time_delta = fr_time_delta_wrap(htonll(fr_time_delta_unwrap(src->vb_time_delta)));
1408 break;
1409
1410 default:
1411 fr_assert_fail(NULL);
1412 return -1; /* shouldn't happen */
1413 }
1414
1415 return 0;
1416}
1417
1418/** Get the size of the value held by the fr_value_box_t
1419 *
1420 * This is the length of the NETWORK presentation
1421 */
1423{
1424 switch (value->type) {
1426 if (value->enumv) {
1427 /*
1428 * Fixed-width fields.
1429 */
1430 if (value->enumv->flags.length) {
1431 return value->enumv->flags.length;
1432 }
1433
1434 /*
1435 * Clamp length at maximum we're allowed to encode.
1436 */
1437 if (da_is_length_field8(value->enumv)) {
1438 if (value->vb_length > UINT8_MAX) return UINT8_MAX;
1439
1440 } else if (da_is_length_field16(value->enumv)) {
1441 if (value->vb_length > UINT16_MAX) return UINT16_MAX;
1442 }
1443 }
1444 return value->vb_length;
1445
1446 /*
1447 * These can have different encodings, depending on the underlying protocol.
1448 */
1449 case FR_TYPE_DATE:
1450 case FR_TYPE_TIME_DELTA:
1451 if (value->enumv) return value->enumv->flags.length;
1453
1454 default:
1455 fr_assert(network_min_size(value->type) != 0);
1456 return network_min_size(value->type);
1457
1458 case FR_TYPE_TLV:
1459 case FR_TYPE_STRUCT:
1460 case FR_TYPE_VSA:
1461 case FR_TYPE_VENDOR:
1462 case FR_TYPE_INTERNAL:
1463 fr_assert(0);
1464 return -1;
1465 }
1466}
1467
1468/** Encode a single value box, serializing its contents in generic network format
1469 *
1470 * The serialized form of #fr_value_box_t may not match the requirements of your protocol
1471 * completely. In cases where they do not, you should overload specific types in the
1472 * function calling #fr_value_box_to_network.
1473 *
1474 * The general serialization rules are:
1475 *
1476 * - Octets are encoded in binary form (not hex).
1477 * - Strings are encoded without the trailing \0 byte.
1478 * - Integers are encoded big-endian.
1479 * - Bools are encoded using one byte, with value 0x00 (false) or 0x01 (true).
1480 * - Signed integers are encoded two's complement, with the MSB as the sign bit.
1481 * Byte order is big-endian.
1482 * - Network addresses are encoded big-endian.
1483 * - IPv4 prefixes are encoded with 1 byte for the prefix, then 4 bytes of address.
1484 * - IPv6 prefixes are encoded with 1 byte for the scope_id, 1 byte for the prefix,
1485 * and 16 bytes of address.
1486 * - Floats are encoded in IEEE-754 format with a big-endian byte order. We rely
1487 * on the fact that the C standards require floats to be represented in IEEE-754
1488 * format in memory.
1489 * - Dates are encoded as 16/32/64-bit unsigned UNIX timestamps.
1490 * - time_deltas are encoded as 16/32/64-bit signed integers.
1491 *
1492 * #FR_TYPE_SIZE is not encodable, as it is system specific.
1493 *
1494 * This function will not encode structural types (TLVs, VSAs etc...). These are usually
1495 * specific to the protocol anyway.
1496 *
1497 * All of the dictionary rules are respected. string/octets can have
1498 * a fixed length (which is zero-padded if necessary), or can have an
1499 * 8/16-bit "length" prefix.
1500 *
1501 * @param[out] dbuff Where to write serialized data.
1502 * @param[in] value to encode.
1503 * @return
1504 * - 0 no bytes were written.
1505 * - >0 the number of bytes written to out.
1506 * - <0 the number of bytes we'd need in dbuff to complete the operation.
1507 */
1509{
1510 size_t min, max;
1511 fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1512
1513 /*
1514 * We cannot encode structural types here.
1515 */
1516 if (!fr_type_is_leaf(value->type)) {
1517 unsupported:
1518 fr_strerror_printf("%s: Cannot encode type \"%s\"",
1519 __FUNCTION__,
1520 fr_type_to_str(value->type));
1522 }
1523
1524 /*
1525 * Variable length types
1526 */
1527 switch (value->type) {
1528 case FR_TYPE_OCTETS:
1529 case FR_TYPE_STRING:
1530 max = value->vb_length;
1531
1532 /*
1533 * Sometimes variable length *inside* the server
1534 * has maximum length on the wire.
1535 */
1536 if (value->enumv) {
1537 if (value->enumv->flags.length) {
1538 /*
1539 * The field is fixed size, and the data is smaller than that, We zero-pad the field.
1540 */
1541 if (max < value->enumv->flags.length) {
1542 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1543 FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, value->enumv->flags.length - max);
1544 return fr_dbuff_set(dbuff, &work_dbuff);
1545
1546 } else if (max > value->enumv->flags.length) {
1547 /*
1548 * Truncate the input to the maximum allowed length.
1549 */
1550 max = value->enumv->flags.length;
1551 }
1552
1553 } else if (da_is_length_field8(value->enumv)) {
1554 /*
1555 * Truncate the output to the max allowed for this field and encode the length.
1556 */
1557 if (max > UINT8_MAX) max = UINT8_MAX;
1558 FR_DBUFF_IN_RETURN(&work_dbuff, (uint8_t) max);
1559
1560 } else if (da_is_length_field16(value->enumv)) {
1561
1562 if (max > UINT16_MAX) max = UINT16_MAX;
1563 FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) max);
1564 }
1565 }
1566
1567 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1568 return fr_dbuff_set(dbuff, &work_dbuff);
1569
1570 /*
1571 * The data can be encoded in a variety of widths.
1572 */
1573 case FR_TYPE_DATE:
1574 case FR_TYPE_TIME_DELTA:
1575 if (value->enumv) {
1576 min = value->enumv->flags.length;
1577 } else {
1578 min = 4;
1579 }
1580 break;
1581
1582 default:
1583 fr_assert(network_min_size(value->type) != 0);
1584 min = network_min_size(value->type);
1585 break;
1586
1587 case FR_TYPE_TLV:
1588 case FR_TYPE_STRUCT:
1589 case FR_TYPE_VSA:
1590 case FR_TYPE_VENDOR:
1591 case FR_TYPE_INTERNAL:
1592 fr_assert(0);
1593 return -1;
1594 }
1595
1596 /*
1597 * We have to encode actual data here.
1598 */
1599 fr_assert(min > 0);
1600
1601 switch (value->type) {
1602 case FR_TYPE_IPV4_ADDR:
1603 ipv4addr:
1604 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1605 (uint8_t const *)&value->vb_ipv4addr,
1606 sizeof(value->vb_ipv4addr));
1607 break;
1608 /*
1609 * Needs special mangling
1610 */
1612 ipv4prefix:
1613 FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1614 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1615 (uint8_t const *)&value->vb_ipv4addr,
1616 sizeof(value->vb_ipv4addr));
1617 break;
1618
1619 case FR_TYPE_IPV6_ADDR:
1620 ipv6addr:
1621 if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1622 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ipv6addr, sizeof(value->vb_ipv6addr));
1623 break;
1624
1626 ipv6prefix:
1627 if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1628 FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1629 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ipv6addr, sizeof(value->vb_ipv6addr));
1630 break;
1631
1632 case FR_TYPE_BOOL:
1633 FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, value->datum.boolean);
1634 break;
1635
1637 switch (value->vb_ip.af) {
1638 case AF_INET:
1639 goto ipv4addr;
1640
1641 case AF_INET6:
1642 goto ipv6addr;
1643
1644 default:
1645 break;
1646 }
1647
1648 fr_strerror_const("Combo IP value missing af");
1649 return 0;
1650
1652 switch (value->vb_ip.af) {
1653 case AF_INET:
1654 goto ipv4prefix;
1655
1656 case AF_INET6:
1657 goto ipv6prefix;
1658
1659 default:
1660 break;
1661 }
1662
1663 fr_strerror_const("Combo IP value missing af");
1664 return 0;
1665
1666 /*
1667 * Already in network byte-order
1668 */
1669 case FR_TYPE_IFID:
1670 case FR_TYPE_ETHERNET:
1671 case FR_TYPE_UINT8:
1672 case FR_TYPE_INT8:
1674 break;
1675
1676 /*
1677 * Needs a bytesex operation
1678 */
1679 case FR_TYPE_UINT16:
1680 case FR_TYPE_UINT32:
1681 case FR_TYPE_UINT64:
1682 case FR_TYPE_INT16:
1683 case FR_TYPE_INT32:
1684 case FR_TYPE_INT64:
1685 case FR_TYPE_FLOAT32:
1686 case FR_TYPE_FLOAT64:
1687 {
1688 fr_value_box_t tmp;
1689
1690 fr_value_box_hton(&tmp, value);
1691
1692 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, value->type), min);
1693 }
1694 break;
1695
1696 case FR_TYPE_ATTR:
1697 {
1698 fr_value_box_t tmp, base;
1699
1700 /*
1701 * For now, we only encode at depth 1. The protocol-specific encoders need to do
1702 * something special for attributes at other depths.
1703 */
1704 if (value->vb_attr->depth != 1) {
1705 fr_strerror_printf("Unsupported depth '%u' for encoding attribute %s",
1706 value->vb_attr->depth, value->vb_attr->name);
1707 return 0;
1708 }
1709
1710 switch (value->vb_attr->flags.length) {
1711 case 1:
1712 fr_value_box_init(&base, FR_TYPE_UINT8, NULL, false);
1713 base.vb_uint8 = value->vb_attr->attr;
1714 break;
1715
1716 case 2:
1717 fr_value_box_init(&base, FR_TYPE_UINT16, NULL, false);
1718 base.vb_uint16 = value->vb_attr->attr;
1719 break;
1720
1721 case 4:
1722 fr_value_box_init(&base, FR_TYPE_UINT32, NULL, false);
1723 base.vb_uint32 = value->vb_attr->attr;
1724 break;
1725
1726 default:
1727 fr_strerror_printf("Unsupported length '%d' for decoding attribute %s",
1728 value->vb_attr->flags.length, value->vb_attr->name);
1729 return 0;
1730 }
1731
1732 fr_value_box_hton(&tmp, &base);
1733
1734 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, tmp.type), min);
1735 }
1736 break;
1737
1738 /*
1739 * Dates and deltas are stored internally as
1740 * 64-bit nanoseconds. We have to convert to the
1741 * network format. First by resolution (ns, us,
1742 * ms, s), and then by size (16/32/64-bit).
1743 */
1744 case FR_TYPE_DATE:
1745 {
1746 uint64_t date = 0;
1747 fr_time_res_t res;
1748
1749 if (!value->enumv) {
1750 res = FR_TIME_RES_SEC;
1751 } else {
1752 res = value->enumv->flags.flag_time_res;
1753 }
1754 date = fr_unix_time_to_integer(value->vb_date, res);
1755
1756 if (!value->enumv) {
1757 goto date_size4;
1758
1759 } else switch (value->enumv->flags.length) {
1760 case 2:
1761 if (date > UINT16_MAX) date = UINT16_MAX;
1762 FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) date);
1763 break;
1764
1765 date_size4:
1766 case 4:
1767 if (date > UINT32_MAX) date = UINT32_MAX;
1768 FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t) date);
1769 break;
1770
1771 case 8:
1772 FR_DBUFF_IN_RETURN(&work_dbuff, date);
1773 break;
1774
1775 default:
1776 goto unsupported;
1777 }
1778
1779 }
1780 break;
1781
1782 case FR_TYPE_TIME_DELTA:
1783 {
1784 int64_t date = 0; /* may be negative */
1786 if (value->enumv) res = value->enumv->flags.flag_time_res;
1787
1788 date = fr_time_delta_to_integer(value->vb_time_delta, res);
1789
1790 if (!value->enumv) {
1791 goto delta_size4;
1792
1793 } else if (!value->enumv->flags.is_unsigned) {
1794 switch (value->enumv->flags.length) {
1795 case 2:
1796 if (date < INT16_MIN) {
1797 date = INT16_MIN;
1798 } else if (date > INT16_MAX) {
1799 date = INT16_MAX;
1800 }
1801 FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t)date);
1802 break;
1803
1804 delta_size4:
1805 case 4:
1806 if (date < INT32_MIN) {
1807 date = INT32_MIN;
1808 } else if (date > INT32_MAX) {
1809 date = INT32_MAX;
1810 }
1811 FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t)date);
1812 break;
1813
1814 case 8:
1815 FR_DBUFF_IN_RETURN(&work_dbuff, (int64_t)date);
1816 break;
1817
1818 default:
1819 goto unsupported;
1820 }
1821 } else { /* time delta is unsigned! */
1822 switch (value->enumv->flags.length) {
1823 case 2:
1824 if (date < 0) {
1825 date = 0;
1826 } else if (date > UINT16_MAX) {
1827 date = UINT16_MAX;
1828 }
1829 FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t)date);
1830 break;
1831
1832 case 4:
1833 if (date < 0) {
1834 date = 0;
1835 } else if (date > UINT32_MAX) {
1836 date = UINT32_MAX;
1837 }
1838 FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)date);
1839 break;
1840
1841 case 8:
1842 FR_DBUFF_IN_RETURN(&work_dbuff, (uint64_t)date);
1843 break;
1844
1845 default:
1846 goto unsupported;
1847 }
1848 }
1849 }
1850 break;
1851
1852 case FR_TYPE_OCTETS:
1853 case FR_TYPE_STRING:
1854 case FR_TYPE_SIZE:
1855 case FR_TYPE_NON_LEAF:
1856 goto unsupported;
1857 }
1858
1859 return fr_dbuff_set(dbuff, &work_dbuff);
1860}
1861
1862/** Decode a #fr_value_box_t from serialized binary data
1863 *
1864 * The general deserialization rules are:
1865 *
1866 * - Octets are decoded in binary form (not hex).
1867 * - Strings are decoded without the trailing \0 byte. Strings must consist only of valid UTF8 chars.
1868 * - Integers are decoded big-endian.
1869 * - Bools are decoded using one byte, with value 0x00 (false) or 0x01 (true).
1870 * - Signed integers are decoded two's complement, with the MSB as the sign bit.
1871 * Byte order is big-endian.
1872 * - Network addresses are decoded big-endian.
1873 * - IPv4 prefixes are decoded with 1 byte for the prefix, then 4 bytes of address.
1874 * - IPv6 prefixes are decoded with 1 byte for the scope_id, 1 byte for the prefix,
1875 * and 16 bytes of address.
1876 * - Floats are decoded in IEEE-754 format with a big-endian byte order. We rely
1877 * on the fact that the C standards require floats to be represented in IEEE-754
1878 * format in memory.
1879 * - Dates are decoded as 32bit unsigned UNIX timestamps.
1880 *
1881 * All of the dictionary rules are respected. string/octets can have
1882 * a fixed length, or can have an 8/16-bit "length" prefix. If the
1883 * enumv is not an array, then the input # len MUST be the correct size
1884 * (not too large or small), otherwise an error is returned.
1885 *
1886 * If the enumv is an array, then the input must have the minimum
1887 * length, and the number of bytes decoded is capped at the maximum
1888 * length allowed to be decoded. This behavior allows the caller to
1889 * decode an array of values simply by calling this function in a
1890 * loop.
1891 *
1892 * @param[in] ctx Where to allocate any talloc buffers required.
1893 * @param[out] dst value_box to write the result to.
1894 * @param[in] type to decode data to.
1895 * @param[in] enumv Aliases for values.
1896 * @param[in] dbuff Binary data to decode.
1897 * @param[in] len Length of data to decode. For fixed length types we only
1898 * decode complete values.
1899 * @param[in] tainted Whether the value came from a trusted source.
1900 * @return
1901 * - >= 0 The number of bytes consumed.
1902 * - <0 - The negative offset where the error occurred.
1903 * - FR_VALUE_BOX_NET_OOM (negative value) - Out of memory.
1904 */
1906 fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv,
1907 fr_dbuff_t *dbuff, size_t len,
1908 bool tainted)
1909{
1910 size_t min, max;
1911 fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1912
1915
1916 fr_assert(max > 0);
1917
1918 if (len < min) {
1919 fr_strerror_printf("Got truncated value parsing type \"%s\". "
1920 "Expected length >= %zu bytes, got %zu bytes",
1922 min, len);
1923 return -(min);
1924 }
1925
1926 /*
1927 * For array entries, we only decode one value at a time.
1928 */
1929 if (len > max) {
1930 if (enumv && !enumv->flags.array) {
1931 fr_strerror_printf("Found trailing garbage parsing type \"%s\". "
1932 "Expected length <= %zu bytes, got %zu bytes",
1934 max, len);
1935 return -(max);
1936 }
1937
1938 len = max;
1939 }
1940
1941 /*
1942 * String / octets are special.
1943 */
1945 size_t newlen = len;
1946 size_t offset = 0;
1947
1948 /*
1949 * Decode fixed-width fields.
1950 */
1951 if (enumv) {
1952 if (enumv->flags.length) {
1953 newlen = enumv->flags.length;
1954
1955 } else if (da_is_length_field8(enumv)) {
1956 uint8_t num = 0;
1957
1958 FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1959 newlen = num;
1960 offset = 1;
1961
1962 } else if (da_is_length_field16(enumv)) {
1963 uint16_t num = 0;
1964
1965 FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1966 newlen = num;
1967 offset = 2;
1968 }
1969 }
1970
1971 /*
1972 * If we need more data than exists, that's an error.
1973 *
1974 * Otherwise, bound the decoding to the count we found.
1975 */
1976 if (newlen > len) return -(newlen + offset);
1977 len = newlen;
1978
1979 switch (type) {
1980 case FR_TYPE_STRING:
1981 if (fr_value_box_bstrndup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1982 return FR_VALUE_BOX_NET_OOM;
1983 }
1984 return fr_dbuff_set(dbuff, &work_dbuff);
1985
1986 case FR_TYPE_OCTETS:
1987 if (fr_value_box_memdup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1988 return FR_VALUE_BOX_NET_OOM;
1989 }
1990 return fr_dbuff_set(dbuff, &work_dbuff);
1991
1992 default:
1993 return -1;
1994 }
1995 }
1996
1997 /*
1998 * Pre-Initialise box for non-variable types
1999 */
2000 fr_value_box_init(dst, type, enumv, tainted);
2001 switch (type) {
2002 /*
2003 * Already in network byte order
2004 */
2005 case FR_TYPE_IPV4_ADDR:
2006 ipv4addr:
2007 dst->vb_ip = (fr_ipaddr_t){
2008 .af = AF_INET,
2009 .prefix = 32,
2010 };
2011 FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len);
2012 break;
2013
2015 ipv4prefix:
2016 dst->vb_ip = (fr_ipaddr_t){
2017 .af = AF_INET,
2018 };
2019 FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
2020 FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len - 1);
2021 break;
2022
2023 case FR_TYPE_IPV6_ADDR:
2024 ipv6addr:
2025 dst->vb_ip = (fr_ipaddr_t){
2026 .af = AF_INET6,
2027 .scope_id = 0,
2028 .prefix = 128
2029 };
2030 if (len == max) {
2031 uint8_t scope_id = 0;
2032
2033 FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
2034 dst->vb_ip.scope_id = scope_id;
2035 len--;
2036 }
2037 FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len);
2038 break;
2039
2041 ipv6prefix:
2042 dst->vb_ip = (fr_ipaddr_t){
2043 .af = AF_INET6,
2044 .scope_id = 0,
2045 };
2046 if (len == max) {
2047 uint8_t scope_id = 0;
2048
2049 FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
2050 dst->vb_ip.scope_id = scope_id;
2051 len--;
2052 }
2053 FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
2054 FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len - 1);
2055 break;
2056
2059 (len <= network_max_size(FR_TYPE_IPV6_ADDR))) goto ipv6addr; /* scope is optional */
2060 else if ((len >= network_min_size(FR_TYPE_IPV4_ADDR)) &&
2061 (len <= network_max_size(FR_TYPE_IPV4_ADDR))) goto ipv4addr;
2062
2063 fr_strerror_const("Invalid combo ip address value");
2064 return -1;
2065
2068 (len <= network_max_size(FR_TYPE_IPV6_PREFIX))) goto ipv6prefix; /* scope is optional */
2069 else if ((len >= network_min_size(FR_TYPE_IPV4_PREFIX)) &&
2070 (len <= network_max_size(FR_TYPE_IPV4_PREFIX))) goto ipv4prefix;
2071
2072 fr_strerror_const("Invalid combo ip prefix value");
2073 return -1;
2074
2075 case FR_TYPE_BOOL:
2076 {
2077 uint8_t val = 0;
2078
2079 FR_DBUFF_OUT_RETURN(&val, &work_dbuff);
2080 dst->datum.boolean = (val != 0);
2081 }
2082 break;
2083
2084 case FR_TYPE_IFID:
2085 case FR_TYPE_ETHERNET:
2087 break;
2088
2089 case FR_TYPE_UINT8:
2090 FR_DBUFF_OUT_RETURN(&dst->vb_uint8, &work_dbuff);
2091 break;
2092
2093 case FR_TYPE_UINT16:
2094 FR_DBUFF_OUT_RETURN(&dst->vb_uint16, &work_dbuff);
2095 break;
2096
2097 case FR_TYPE_UINT32:
2098 FR_DBUFF_OUT_RETURN(&dst->vb_uint32, &work_dbuff);
2099 break;
2100
2101 case FR_TYPE_UINT64:
2102 FR_DBUFF_OUT_RETURN(&dst->vb_uint64, &work_dbuff);
2103 break;
2104
2105 case FR_TYPE_INT8:
2106 FR_DBUFF_OUT_RETURN(&dst->vb_int8, &work_dbuff);
2107 break;
2108
2109 case FR_TYPE_INT16:
2110 FR_DBUFF_OUT_RETURN(&dst->vb_int16, &work_dbuff);
2111 break;
2112
2113 case FR_TYPE_INT32:
2114 FR_DBUFF_OUT_RETURN(&dst->vb_int32, &work_dbuff);
2115 break;
2116
2117 case FR_TYPE_INT64:
2118 FR_DBUFF_OUT_RETURN(&dst->vb_int64, &work_dbuff);
2119 break;
2120
2121 case FR_TYPE_FLOAT32:
2122 FR_DBUFF_OUT_RETURN(&dst->vb_float32, &work_dbuff);
2123 break;
2124
2125 case FR_TYPE_FLOAT64:
2126 FR_DBUFF_OUT_RETURN(&dst->vb_float64, &work_dbuff);
2127 break;
2128
2129 case FR_TYPE_ATTR:
2130 if (!enumv) {
2131 fr_strerror_const("No enumv (i.e. root) passed to fr_value_box_from_network for type 'attribute'");
2132 return -1;
2133 }
2134
2135 /*
2136 * Decode the number, and see if we can create a
2137 * matching attribute.
2138 */
2139 {
2140 unsigned int num;
2141 uint8_t num8;
2142 uint16_t num16;
2143 uint32_t num32;
2144
2145 switch (enumv->flags.length) {
2146 case 1:
2147 FR_DBUFF_OUT_RETURN(&num8, &work_dbuff);
2148 num = num8;
2149 break;
2150
2151 case 2:
2152 FR_DBUFF_OUT_RETURN(&num16, &work_dbuff);
2153 num = num16;
2154 break;
2155
2156 case 4:
2157 FR_DBUFF_OUT_RETURN(&num32, &work_dbuff);
2158 num = num32;
2159 break;
2160
2161 default:
2162 fr_strerror_const("Unsupported parent length");
2163 return -1;
2164 }
2165
2166 dst->vb_attr = fr_dict_attr_child_by_num(enumv, num);
2167 if (!dst->vb_attr) {
2168 dst->vb_attr = fr_dict_attr_unknown_raw_afrom_num(ctx, enumv, num);
2169 if (!dst->vb_attr) return -1;
2170 }
2171
2172 break;
2173 }
2174
2175 /*
2176 * Dates and deltas are stored internally as
2177 * 64-bit nanoseconds. We have to convert from
2178 * the network format. First by size
2179 * (16/32/64-bit), and then by resolution (ns,
2180 * us, ms, s).
2181 */
2182 case FR_TYPE_DATE:
2183 {
2184 size_t length = 4;
2185 fr_time_res_t precision = FR_TIME_RES_SEC;
2186 uint64_t date;
2187
2188 if (enumv) {
2189 length = enumv->flags.length;
2190 precision = (fr_time_res_t)enumv->flags.flag_time_res;
2191 }
2192
2193 /*
2194 * Input data doesn't match what we were told we
2195 * need.
2196 */
2197 if (len > length) return -(length);
2198
2199 dst->enumv = enumv;
2200
2201 FR_DBUFF_OUT_UINT64V_RETURN(&date, &work_dbuff, length);
2202
2203 if (!fr_multiply(&date, date, fr_time_multiplier_by_res[precision])) {
2204 fr_strerror_const("date would overflow");
2205 return -1;
2206 }
2207
2208 dst->vb_date = fr_unix_time_wrap(date);
2209 }
2210 break;
2211
2212 case FR_TYPE_TIME_DELTA:
2213 {
2214 size_t length = 4;
2215 fr_time_res_t precision = FR_TIME_RES_SEC;
2216 int64_t date;
2217
2218 if (enumv) {
2219 length = enumv->flags.length;
2220 precision = (fr_time_res_t)enumv->flags.flag_time_res;
2221 }
2222
2223 /*
2224 * Input data doesn't match what we were told we
2225 * need.
2226 */
2227 if (len > length) return -(length);
2228
2229 dst->enumv = enumv;
2230
2231 if (!enumv || !enumv->flags.is_unsigned) {
2232 FR_DBUFF_OUT_INT64V_RETURN(&date, &work_dbuff, length);
2233 } else {
2234 uint64_t tmp;
2235
2236 /*
2237 * Else it's an unsigned time delta, but
2238 * we do have to clamp it at the max
2239 * value for a signed 64-bit integer.
2240 */
2241 FR_DBUFF_OUT_UINT64V_RETURN(&tmp, &work_dbuff, length);
2242
2243 if (tmp > INT64_MAX) tmp = INT64_MAX;
2244
2245 date = tmp;
2246 }
2247
2248 dst->vb_time_delta = fr_time_delta_wrap(fr_time_scale(date, precision));
2249 }
2250 break;
2251
2252 case FR_TYPE_STRING:
2253 case FR_TYPE_OCTETS:
2254 break; /* Already dealt with */
2255
2256 case FR_TYPE_SIZE:
2257 case FR_TYPE_NON_LEAF:
2258 fr_strerror_printf("Cannot decode type \"%s\" - Is not a value",
2260 return -1;
2261 }
2262
2263 return fr_dbuff_set(dbuff, &work_dbuff);
2264}
2265
2273
2275 [FR_TYPE_IPV4_ADDR] = {
2276 AF_INET, 32, 32, 0, 4,
2277 },
2278
2280 AF_INET, 0, 32, 0, 4,
2281 },
2282
2283 [FR_TYPE_IPV6_ADDR] = {
2284 AF_INET6, 128, 128, 16, 16,
2285 },
2286
2288 AF_INET6, 0, 128, 0, 16,
2289 },
2290};
2291
2292/** Decode a #fr_value_box_t of type IP address / prefix.
2293 *
2294 * This function also gets passed a prefix length, and is a bit more
2295 * forgiving that fr_value_box_from_network().
2296 *
2297 * @param[out] dst value_box to write the result to.
2298 * @param[in] type to decode data to.
2299 * @param[in] enumv Aliases for values.
2300 * @param[in] prefix_len for prefix types
2301 * @param[in] data Binary data to decode.
2302 * @param[in] data_len Length of data to decode.
2303 * @param[in] fixed is this a fixed size, or a variable one?
2304 * @param[in] tainted Whether the value came from a trusted source.
2305 * @return
2306 * - >= 0 The number of bytes consumed.
2307 * - <0 - an error occurred.
2308 */
2310 int prefix_len, uint8_t const *data, size_t data_len,
2311 bool fixed, bool tainted)
2312{
2313 switch (type) {
2314 case FR_TYPE_IPV4_ADDR:
2316 case FR_TYPE_IPV6_ADDR:
2318 break;
2319
2320 default:
2321 fr_strerror_printf("Invalid data type '%s' passed to IP address decode function",
2323 return -1;
2324 }
2325
2326 /*
2327 * Check the allowed values for prefix length.
2328 */
2329 if (prefix_len < ipaddr_sizes[type].prefix_min) {
2330 fr_strerror_printf("Invalid prefix length %d, expected at least %d",
2331 prefix_len, ipaddr_sizes[type].prefix_min);
2332 return -1;
2333 }
2334
2335 if (prefix_len > ipaddr_sizes[type].prefix_max) {
2336 fr_strerror_printf("Invalid prefix length '%d', expected no more than %d",
2337 prefix_len, ipaddr_sizes[type].prefix_max);
2338 return -1;
2339 }
2340
2341 /*
2342 * It's a prefix data type. Verify that the prefix length doesn't require more bytes than we
2343 * have.
2344 *
2345 * @todo - some protocols allow a larger prefix, and then set the extra bytes to zero. <sigh>
2346 */
2347 if (!ipaddr_sizes[type].addr_min) {
2348 if (fr_bytes_from_bits(prefix_len) > data_len) {
2349 fr_strerror_printf("Invalid prefix length '%d' - it requires %u bytes of data, and there are only %zu bytes of data",
2350 prefix_len, fr_bytes_from_bits(prefix_len), data_len);
2351 return -1;
2352 }
2353 }
2354
2355 /*
2356 * Check how much data is in the buffer.
2357 */
2358 if (data_len < ipaddr_sizes[type].addr_min) {
2359 fr_strerror_printf("Invalid address length '%zu', expected at least %zu",
2360 data_len, ipaddr_sizes[type].addr_min);
2361 return -1;
2362 }
2363
2364 /*
2365 * Do various checks for the size.
2366 */
2367 if (enumv && enumv->flags.array) {
2368 /*
2369 * If this field is part of an array, then it has to be fixed size.
2370 */
2371 data_len = ipaddr_sizes[type].addr_max;
2372
2373 } else if (fixed) {
2374 /*
2375 * If it's fixed size, it must be the maximum size.
2376 */
2377 if (data_len != ipaddr_sizes[type].addr_max) {
2378 fr_strerror_printf("Invalid address length '%zu', expected at exactly %zu",
2379 data_len, ipaddr_sizes[type].addr_max);
2380 return -1;
2381 }
2382
2383 /*
2384 * There is more data in the array - limit what we read to the size of the address.
2385 */
2386 data_len = ipaddr_sizes[type].addr_max;
2387
2388 } else if (data_len > ipaddr_sizes[type].addr_max) {
2389 fr_strerror_printf("Invalid address length '%zu', expected no more than %zu",
2390 data_len, ipaddr_sizes[type].addr_max);
2391 return -1;
2392 }
2393
2394 fr_value_box_init(dst, type, enumv, tainted);
2395 dst->vb_ip = (fr_ipaddr_t) {
2396 .af = ipaddr_sizes[type].af,
2397 .prefix = prefix_len,
2398 /* automatically initialize vp_ip.addr to all zeros */
2399 };
2400
2401 if (!data_len) return 0;
2402
2403 fr_assert(data_len <= sizeof(dst->vb_ip.addr));
2404
2405 memcpy((uint8_t *) &dst->vb_ip.addr, data, data_len);
2406
2407 /*
2408 * @todo - maybe it's an error to have bits set outsize of the prefix length.
2409 */
2410 fr_ipaddr_mask(&dst->vb_ip, prefix_len);
2411
2412 return data_len;
2413}
2414
2415/** Decode a #fr_value_box_t from a C type in memory
2416 *
2417 * We ignore arrays
2418 *
2419 * @param[in] ctx Where to allocate any talloc buffers required.
2420 * @param[out] dst value_box to write the result to.
2421 * @param[in] type to decode data to.
2422 * @param[in] enumv Aliases for values.
2423 * @param[in] src raw pointer to the (possibly unaligned) source
2424 * @param[in] len Length of data to decode. For fixed length types we only
2425 * decode complete values.
2426 * @return
2427 * - >= 0 The number of bytes consumed.
2428 * - <0 an error occured
2429 */
2431 fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv,
2432 void const *src, size_t len)
2433{
2434 switch (type) {
2436 case FR_TYPE_FLOAT32:
2437 case FR_TYPE_FLOAT64:
2439 fr_strerror_printf("Invalid size passed for type %s - expected %zu got %zu",
2441 return -1;
2442 }
2443
2444 fr_value_box_init(dst, type, enumv, false);
2445 memcpy(&dst->datum, src, len);
2446 break;
2447
2448 case FR_TYPE_IPV4_ADDR:
2449 if (len != sizeof(struct in_addr)) {
2450 fr_strerror_printf("Invalid size passed for type %s - expected %zu got %zu",
2451 fr_type_to_str(type), sizeof(struct in_addr), len);
2452 return -1;
2453 }
2454
2455 fr_value_box_init(dst, type, enumv, false);
2456 memcpy(&dst->vb_ipv4addr, src, len);
2457 break;
2458
2459 case FR_TYPE_IPV6_ADDR:
2460 if (len != sizeof(struct in6_addr)) {
2461 fr_strerror_printf("Invalid size passed for type %s - expected %zu got %zu",
2462 fr_type_to_str(type), sizeof(struct in6_addr), len);
2463 return -1;
2464 }
2465
2466 fr_value_box_init(dst, type, enumv, false);
2467 memcpy(&dst->vb_ipv6addr, src, len);
2468 break;
2469
2470 case FR_TYPE_STRING:
2471 return fr_value_box_bstrndup(ctx, dst, enumv, src, len, false);
2472
2473 case FR_TYPE_OCTETS:
2474 return fr_value_box_memdup(ctx, dst, enumv, src, len, false);
2475
2476 default:
2477 fr_strerror_printf("Unsupported data type %s",
2479 return -1;
2480 }
2481
2482 return len;
2483}
2484
2485
2486/** Get a key from a value box
2487 *
2488 * @param[in,out] out - set to a small buffer on input. If the callback has more data
2489 * than is available here, the callback can update "out" to point elsewhere
2490 * @param[in,out] outlen The number of bits available in the initial buffer. On output,
2491 * the number of bits available in the key
2492 * @param[in] value the value box which contains the key
2493 * @return
2494 * - <0 on error
2495 * - 0 on success
2496 */
2498{
2499 ssize_t slen;
2500 fr_dbuff_t dbuff;
2501
2502 switch (value->type) {
2503 case FR_TYPE_BOOL:
2504 if (*outlen < 8) return -1;
2505
2506 *out[0] = (value->vb_bool) << 7;
2507 *outlen = 1;
2508 break;
2509
2511 if (*outlen < (fr_value_box_network_sizes[value->type][1] * 8)) return -1;
2512
2513 /*
2514 * Integers are put into network byte order.
2515 */
2516 fr_dbuff_init(&dbuff, *out, *outlen >> 3);
2517
2518 slen = fr_value_box_to_network(&dbuff, value);
2519 if (slen < 0) return -1;
2520 *outlen = slen * 8; /* bits not bytes */
2521 break;
2522
2523 case FR_TYPE_IP:
2524 /*
2525 * IPs are already in network byte order.
2526 */
2527 *out = UNCONST(uint8_t *, &value->vb_ip.addr);
2528 *outlen = value->vb_ip.prefix;
2529 break;
2530
2531 case FR_TYPE_STRING:
2532 case FR_TYPE_OCTETS:
2533 *out = value->datum.ptr;
2534 *outlen = value->vb_length * 8;
2535 break;
2536
2537 case FR_TYPE_ETHERNET:
2538 *out = UNCONST(uint8_t *, &value->vb_ether[0]);
2539 *outlen = sizeof(value->vb_ether) * 8;
2540 break;
2541
2542 default:
2543 fr_strerror_printf("Invalid data type '%s' for getting key",
2544 fr_type_to_str(value->type));
2545 return -1;
2546 }
2547
2548 return 0;
2549}
2550
2551/** Convert octets to a fixed size value box value
2552 *
2553 * All fixed size types are allowed.
2554 *
2555 * @param dst Where to write result of casting.
2556 * @param dst_type to cast to.
2557 * @param dst_enumv enumeration values.
2558 * @param src Input data.
2559 */
2561 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2562 fr_value_box_t const *src)
2563{
2564 uint8_t *ptr;
2565
2566 if (!fr_type_is_fixed_size(dst_type)) if (!fr_cond_assert(false)) return -1;
2567
2568 if (src->vb_length > network_max_size(dst_type)) {
2569 fr_strerror_printf("Invalid cast from %s to %s. Source length %zu is greater than "
2570 "destination type size %zu",
2571 fr_type_to_str(src->type),
2572 fr_type_to_str(dst_type),
2573 src->vb_length,
2574 network_max_size(dst_type));
2575 return -1;
2576 }
2577
2578 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2579
2580 /*
2581 * No data to copy means just reset it to zero.
2582 */
2583 if (!src->vb_length) return 0;
2584
2585 ptr = (uint8_t *) &dst->datum;
2586
2587 /*
2588 * If the source is too small, just left-fill with zeroes.
2589 */
2590 if (src->vb_length < network_min_size(dst_type)) {
2591 ptr += network_min_size(dst_type) - src->vb_length;
2592 }
2593
2594 /*
2595 * Copy the raw octets into the datum of a value_box
2596 * inverting bytesex for uint32s (if LE).
2597 */
2598 switch (dst->type) {
2599 default:
2600 memcpy(ptr, src->vb_octets, src->vb_length);
2601 fr_value_box_hton(dst, dst);
2602 break;
2603
2604 case FR_TYPE_BOOL:
2605 dst->vb_bool = (src->vb_octets[0] != 0);
2606 break;
2607 }
2608
2609 return 0;
2610}
2611
2612/** v4 to v6 mapping prefix
2613 *
2614 * Part of the IPv6 range is allocated to represent IPv4 addresses.
2615 */
2616static uint8_t const v4_v6_map[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2617 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
2618
2619
2620/** Convert any supported type to a string
2621 *
2622 * All non-structural types are allowed.
2623 *
2624 * @param ctx unused.
2625 * @param dst Where to write result of casting.
2626 * @param dst_type to cast to.
2627 * @param dst_enumv enumeration values.
2628 * @param src Input data.
2629 */
2630static inline int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t *dst,
2631 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2632 fr_value_box_t const *src)
2633{
2634 if (!fr_cond_assert(dst_type == FR_TYPE_STRING)) return -1;
2635
2636 fr_value_box_init(dst, FR_TYPE_STRING, dst_enumv, false);
2637
2638 switch (src->type) {
2639 /*
2640 * An explicit `null` has no representation to cast from.
2641 * Refuse rather than silently coerce to an empty string.
2642 */
2643 case FR_TYPE_NULL:
2644 fr_strerror_const("Cannot cast null to a string");
2645 return -1;
2646
2647 /*
2648 * The presentation format of octets is hex
2649 * What we actually want here is the raw string
2650 */
2651 case FR_TYPE_OCTETS:
2652 if (fr_value_box_bstrndup(ctx, dst, dst_enumv,
2653 (char const *)src->vb_octets, src->vb_length, src->tainted) < 0) return -1;
2654 fr_value_box_safety_copy(dst, src); /* After bstrndup, which resets the safety */
2655 return 0;
2656
2657 case FR_TYPE_GROUP:
2659 dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2662 SIZE_MAX);
2663
2664 /*
2665 * Get the presentation format
2666 */
2667 default:
2668 {
2669 char *str;
2670
2671 fr_value_box_aprint(ctx, &str, src, NULL);
2672 if (unlikely(!str)) return -1;
2673
2675 return fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, str, src->tainted);
2676 }
2677 }
2678}
2679
2680/** Convert any supported type to octets
2681 *
2682 * All non-structural types are allowed.
2683 *
2684 * @param ctx unused.
2685 * @param dst Where to write result of casting.
2686 * @param dst_type to cast to.
2687 * @param dst_enumv enumeration values.
2688 * @param src Input data.
2689 */
2690static inline int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *dst,
2691 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2692 fr_value_box_t const *src)
2693{
2694 if (!fr_cond_assert(dst_type == FR_TYPE_OCTETS)) return -1;
2695
2696 fr_value_box_init(dst, FR_TYPE_OCTETS, dst_enumv, false);
2698
2699 switch (src->type) {
2700 /*
2701 * An explicit `null` has no representation to cast from.
2702 * Refuse rather than silently coerce to zero-length octets.
2703 */
2704 case FR_TYPE_NULL:
2705 fr_strerror_const("Cannot cast null to octets");
2706 return -1;
2707
2708 /*
2709 * <string> (excluding terminating \0)
2710 */
2711 case FR_TYPE_STRING:
2712 if (fr_value_box_memdup(ctx, dst, dst_enumv,
2713 (uint8_t const *)src->vb_strvalue, src->vb_length, src->tainted) < 0) return -1;
2714 fr_value_box_safety_copy(dst, src); /* After memdup, which resets the safety */
2715 return 0;
2716
2717 case FR_TYPE_GROUP:
2719 dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2722 SIZE_MAX);
2723 /*
2724 * <4 bytes address>
2725 */
2726 case FR_TYPE_IPV4_ADDR:
2727 return fr_value_box_memdup(ctx, dst, dst_enumv,
2728 (uint8_t const *)&src->vb_ipv4addr,
2729 sizeof(src->vb_ipv4addr), src->tainted);
2730
2731 /*
2732 * <1 uint8 prefix> + <4 bytes address>
2733 */
2735 {
2736 uint8_t *bin;
2737
2738 if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2739 sizeof(src->vb_ipv4addr) + 1, src->tainted) < 0) return -1;
2740
2741 bin[0] = src->vb_ip.prefix;
2742 memcpy(&bin[1], (uint8_t const *)&src->vb_ipv4addr, sizeof(src->vb_ipv4addr));
2743 }
2744 return 0;
2745
2746 /*
2747 * <16 bytes address>
2748 */
2749 case FR_TYPE_IPV6_ADDR:
2750 return fr_value_box_memdup(ctx, dst, dst_enumv,
2751 (uint8_t const *)src->vb_ipv6addr,
2752 sizeof(src->vb_ipv6addr), src->tainted);
2753
2754 /*
2755 * <1 uint8 prefix> + <1 uint8 scope> + <16 bytes address>
2756 */
2758 {
2759 uint8_t *bin;
2760
2761 if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2762 sizeof(src->vb_ipv6addr) + 2, src->tainted) < 0) return -1;
2763 bin[0] = src->vb_ip.scope_id;
2764 bin[1] = src->vb_ip.prefix;
2765 memcpy(&bin[2], src->vb_ipv6addr, sizeof(src->vb_ipv6addr));
2766 }
2767 return 0;
2768
2769 /*
2770 * Get the raw binary in memory representation
2771 */
2772 case FR_TYPE_NUMERIC:
2773 {
2774 fr_value_box_t tmp;
2775
2776 fr_value_box_hton(&tmp, src); /* Flip any numeric representations */
2777 return fr_value_box_memdup(ctx, dst, dst_enumv,
2778 fr_value_box_raw(&tmp, src->type),
2779 fr_value_box_field_sizes[src->type], src->tainted);
2780 }
2781
2782 case FR_TYPE_TLV:
2783 case FR_TYPE_STRUCT:
2784 case FR_TYPE_VSA:
2785 case FR_TYPE_VENDOR:
2786 case FR_TYPE_UNION:
2787 case FR_TYPE_INTERNAL:
2788 case FR_TYPE_ATTR:
2789 case FR_TYPE_COMBO_IP_ADDR: /* the types should have been realized to ipv4 / ipv6 */
2791 case FR_TYPE_OCTETS: /* handled above*/
2792 break;
2793
2794
2795 /* Not the same talloc_memdup call as above. The above memdup reads data from the dst */
2796 case FR_TYPE_IFID:
2797 case FR_TYPE_ETHERNET:
2798 return fr_value_box_memdup(ctx, dst, dst_enumv,
2799 fr_value_box_raw(src, src->type),
2800 fr_value_box_field_sizes[src->type], src->tainted);
2801 }
2802
2803 fr_assert(0);
2804 return -1;
2805}
2806
2807#define CAST_IP_FIX_COMBO \
2808 case FR_TYPE_COMBO_IP_ADDR: \
2809 if (src->vb_ip.af == AF_INET) { \
2810 src_type = FR_TYPE_IPV4_ADDR; \
2811 } else if (src->vb_ip.af == AF_INET6) { \
2812 src_type = FR_TYPE_IPV6_ADDR; \
2813 } \
2814 break; \
2815 case FR_TYPE_COMBO_IP_PREFIX: \
2816 if (src->vb_ip.af == AF_INET) { \
2817 src_type = FR_TYPE_IPV4_PREFIX; \
2818 } else if (src->vb_ip.af == AF_INET6) { \
2819 src_type = FR_TYPE_IPV6_PREFIX; \
2820 } \
2821 break
2822
2823
2825{
2826 fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2827 fr_type_to_str(src),
2828 fr_type_to_str(dst));
2829 return -1;
2830}
2831
2832
2833/** Convert any supported type to an IPv4 address
2834 *
2835 * Allowed input types are:
2836 * - FR_TYPE_IPV6_ADDR (with v4 prefix).
2837 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2838 * - FR_TYPE_IPV6_PREFIX (with v4 prefix and 128bit mask).
2839 * - FR_TYPE_OCTETS (of length 4).
2840 * - FR_TYPE_UINT32
2841 *
2842 * @param ctx unused.
2843 * @param dst Where to write result of casting.
2844 * @param dst_type to cast to.
2845 * @param dst_enumv enumeration values.
2846 * @param src Input data.
2847 */
2848static inline int fr_value_box_cast_to_ipv4addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
2849 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2850 fr_value_box_t const *src)
2851{
2852 fr_type_t src_type = src->type;
2853
2854 fr_assert(dst_type == FR_TYPE_IPV4_ADDR);
2856
2857 switch (src_type) {
2858 case FR_TYPE_STRING:
2859 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2860 src->vb_strvalue, src->vb_length,
2861 NULL);
2862
2864
2865 default:
2866 break;
2867 }
2868
2869 /*
2870 * Pre-initialise box for non-variable types
2871 */
2872 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2873 dst->vb_ip.af = AF_INET;
2874 dst->vb_ip.prefix = 32;
2875 dst->vb_ip.scope_id = 0;
2876
2877 switch (src_type) {
2878 case FR_TYPE_IPV6_ADDR:
2879 if (memcmp(src->vb_ipv6addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
2880 bad_v6_prefix_map:
2881 fr_strerror_printf("Invalid cast from %s to %s. No IPv4-IPv6 mapping prefix",
2882 fr_type_to_str(src->type),
2883 fr_type_to_str(dst_type));
2884 return -1;
2885 }
2886
2887 memcpy(&dst->vb_ip.addr.v4, &src->vb_ipv6addr[sizeof(v4_v6_map)],
2888 sizeof(dst->vb_ip.addr.v4));
2889
2890 break;
2891
2893 if (src->vb_ip.prefix != 32) {
2894 fr_strerror_printf("Invalid cast from %s to %s. Only /32 (not %i/) prefixes may be "
2895 "cast to IP address types",
2896 fr_type_to_str(src->type),
2897 fr_type_to_str(dst_type),
2898 src->vb_ip.prefix);
2899 return -1;
2900 }
2902
2903 case FR_TYPE_IPV4_ADDR: /* Needed for handling combo addresses */
2904 memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v4, sizeof(dst->vb_ip.addr.v4));
2905 break;
2906
2908 if (src->vb_ip.prefix != 128) {
2909 fr_strerror_printf("Invalid cast from %s to %s. Only /128 (not /%i) prefixes may be "
2910 "cast to IP address types",
2911 fr_type_to_str(src->type),
2912 fr_type_to_str(dst_type),
2913 src->vb_ip.prefix);
2914 return -1;
2915 }
2916 if (memcmp(&src->vb_ipv6addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
2917 memcpy(&dst->vb_ip.addr.v4, &src->vb_ipv6addr[sizeof(v4_v6_map)],
2918 sizeof(dst->vb_ip.addr.v4));
2919 break;
2920
2921 case FR_TYPE_OCTETS:
2922 if (src->vb_length != sizeof(dst->vb_ipv4addr)) {
2923 fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
2924 fr_type_to_str(src->type),
2925 fr_type_to_str(dst_type),
2926 sizeof(dst->vb_ipv4addr), src->vb_length);
2927 return -1;
2928 }
2929 memcpy(&dst->vb_ip.addr.v4, src->vb_octets, sizeof(dst->vb_ipv4addr));
2930 break;
2931
2932 case FR_TYPE_UINT32:
2933 {
2934 uint32_t net;
2935
2936 net = ntohl(src->vb_uint32);
2937 memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ipv4addr));
2938 }
2939 break;
2940
2941 default:
2942 return fr_value_box_cast_unsupported(dst_type, src->type);
2943 }
2944
2945 return 0;
2946}
2947
2948/** Convert any supported type to an IPv6 address
2949 *
2950 * Allowed input types are:
2951 * - FR_TYPE_IPV4_ADDR
2952 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2953 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2954 * - FR_TYPE_OCTETS (of length 16).
2955 *
2956 * @param ctx unused.
2957 * @param dst Where to write result of casting.
2958 * @param dst_type to cast to.
2959 * @param dst_enumv enumeration values.
2960 * @param src Input data.
2961 */
2962static inline int fr_value_box_cast_to_ipv4prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
2963 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2964 fr_value_box_t const *src)
2965{
2966 fr_type_t src_type = src->type;
2967
2968 fr_assert(dst_type == FR_TYPE_IPV4_PREFIX);
2970
2971 switch (src_type) {
2972 case FR_TYPE_STRING:
2973 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2974 src->vb_strvalue, src->vb_length,
2975 NULL);
2976
2978
2979 default:
2980 break;
2981 }
2982
2983 /*
2984 * Pre-initialise box for non-variable types
2985 */
2986 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2987 dst->vb_ip.af = AF_INET;
2988 dst->vb_ip.scope_id = 0;
2989
2990 switch (src_type) {
2991 case FR_TYPE_IPV4_PREFIX: /* Needed for handling combo prefixes */
2992 dst->vb_ip.prefix = src->vb_ip.prefix;
2994
2995 case FR_TYPE_IPV4_ADDR:
2996 memcpy(&dst->vb_ip, &src->vb_ip, sizeof(dst->vb_ip));
2997 break;
2998
2999 /*
3000 * Copy the last four bytes, to make an IPv4prefix
3001 */
3002 case FR_TYPE_IPV6_ADDR:
3003 if (memcmp(src->vb_ipv6addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
3004 bad_v6_prefix_map:
3005 fr_strerror_printf("Invalid cast from %s to %s. No IPv4-IPv6 mapping prefix",
3006 fr_type_to_str(src->type),
3007 fr_type_to_str(dst_type));
3008 return -1;
3009 }
3010 memcpy(&dst->vb_ipv4addr, &src->vb_ipv6addr[sizeof(v4_v6_map)],
3011 sizeof(dst->vb_ipv4addr));
3012 dst->vb_ip.prefix = 32;
3013 break;
3014
3016 if (memcmp(src->vb_ipv6addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
3017
3018 if (src->vb_ip.prefix < (sizeof(v4_v6_map) << 3)) {
3019 fr_strerror_printf("Invalid cast from %s to %s. Expected prefix >= %u bits got %u bits",
3020 fr_type_to_str(src->type),
3021 fr_type_to_str(dst_type),
3022 (unsigned int)(sizeof(v4_v6_map) << 3), src->vb_ip.prefix);
3023 return -1;
3024 }
3025 memcpy(&dst->vb_ipv4addr, &src->vb_ipv6addr[sizeof(v4_v6_map)],
3026 sizeof(dst->vb_ipv4addr));
3027
3028 /*
3029 * Subtract the bits used by the v4_v6_map to get the v4 prefix bits
3030 */
3031 dst->vb_ip.prefix = src->vb_ip.prefix - (sizeof(v4_v6_map) << 3);
3032 break;
3033
3034 case FR_TYPE_OCTETS:
3035 if (src->vb_length != sizeof(dst->vb_ipv4addr) + 1) {
3036 fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
3037 fr_type_to_str(src->type),
3038 fr_type_to_str(dst_type),
3039 sizeof(dst->vb_ipv4addr) + 1, src->vb_length);
3040 return -1;
3041 }
3042 dst->vb_ip.prefix = src->vb_octets[0];
3043 memcpy(&dst->vb_ip.addr.v4, &src->vb_octets[1], sizeof(dst->vb_ipv4addr));
3044 break;
3045
3046 case FR_TYPE_UINT32:
3047 {
3048 uint32_t net;
3049
3050 net = ntohl(src->vb_uint32);
3051 memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ipv4addr));
3052 dst->vb_ip.prefix = 32;
3053 break;
3054 }
3055
3056 default:
3057 return fr_value_box_cast_unsupported(dst_type, src->type);
3058 }
3059
3060 return 0;
3061}
3062
3063/** Convert any supported type to an IPv6 address
3064 *
3065 * Allowed input types are:
3066 * - FR_TYPE_IPV4_ADDR
3067 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
3068 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
3069 * - FR_TYPE_OCTETS (of length 16).
3070 *
3071 * @param ctx unused.
3072 * @param dst Where to write result of casting.
3073 * @param dst_type to cast to.
3074 * @param dst_enumv enumeration values.
3075 * @param src Input data.
3076 */
3077static inline int fr_value_box_cast_to_ipv6addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
3078 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3079 fr_value_box_t const *src)
3080{
3081 fr_type_t src_type = src->type;
3082
3083 static_assert((sizeof(v4_v6_map) + sizeof(src->vb_ip.addr.v4)) <=
3084 sizeof(src->vb_ip.addr.v6), "IPv6 storage too small");
3085
3086 fr_assert(dst_type == FR_TYPE_IPV6_ADDR);
3088
3089 switch (src_type) {
3090 case FR_TYPE_STRING:
3091 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3092 src->vb_strvalue, src->vb_length,
3093 NULL);
3094
3096
3097 default:
3098 break;
3099 }
3100
3101 /*
3102 * Pre-initialise box for non-variable types
3103 */
3104 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3105 dst->vb_ip.af = AF_INET6;
3106 dst->vb_ip.prefix = 128;
3107
3108 switch (src_type) {
3109 case FR_TYPE_IPV4_ADDR:
3110 {
3111 uint8_t *p = dst->vb_ipv6addr;
3112
3113 /* Add the v4/v6 mapping prefix */
3114 memcpy(p, v4_v6_map, sizeof(v4_v6_map));
3115 p += sizeof(v4_v6_map);
3116 memcpy(p, (uint8_t const *)&src->vb_ipv4addr, sizeof(src->vb_ipv4addr));
3117 dst->vb_ip.scope_id = 0;
3118 }
3119 break;
3120
3122 {
3123 uint8_t *p = dst->vb_ipv6addr;
3124
3125 if (src->vb_ip.prefix != 32) {
3126 fr_strerror_printf("Invalid cast from %s to %s. Only /32 (not /%i) prefixes may be "
3127 "cast to IP address types",
3128 fr_type_to_str(src->type),
3129 fr_type_to_str(dst_type),
3130 src->vb_ip.prefix);
3131 return -1;
3132 }
3133
3134 /* Add the v4/v6 mapping prefix */
3135 memcpy(p, v4_v6_map, sizeof(v4_v6_map));
3136 p += sizeof(v4_v6_map);
3137 memcpy(p, (uint8_t const *)&src->vb_ipv4addr, sizeof(src->vb_ipv4addr));
3138 dst->vb_ip.scope_id = 0;
3139 }
3140 break;
3141
3143 if (src->vb_ip.prefix != 128) {
3144 fr_strerror_printf("Invalid cast from %s to %s. Only /128 (not /%i) prefixes may be "
3145 "cast to IP address types",
3146 fr_type_to_str(src->type),
3147 fr_type_to_str(dst_type),
3148 src->vb_ip.prefix);
3149 return -1;
3150 }
3152
3153 case FR_TYPE_IPV6_ADDR: /* Needed for handling combo addresses */
3154 memcpy(dst->vb_ipv6addr, src->vb_ipv6addr,
3155 sizeof(dst->vb_ipv6addr));
3156 dst->vb_ip.scope_id = src->vb_ip.scope_id;
3157 break;
3158
3159 case FR_TYPE_OCTETS:
3160 if (src->vb_length != sizeof(dst->vb_ipv6addr)) {
3161 fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
3162 fr_type_to_str(src->type),
3163 fr_type_to_str(dst_type),
3164 sizeof(dst->vb_ipv6addr), src->vb_length);
3165 return -1;
3166 }
3167 memcpy(&dst->vb_ipv6addr, src->vb_octets, sizeof(dst->vb_ipv6addr));
3168 break;
3169
3170 default:
3171 return fr_value_box_cast_unsupported(dst_type, src->type);
3172 }
3173
3174 return 0;
3175}
3176
3177/** Convert any supported type to an IPv6 address
3178 *
3179 * Allowed input types are:
3180 * - FR_TYPE_IPV4_ADDR
3181 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
3182 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
3183 * - FR_TYPE_OCTETS (of length 16).
3184 *
3185 * @param ctx unused.
3186 * @param dst Where to write result of casting.
3187 * @param dst_type to cast to.
3188 * @param dst_enumv enumeration values.
3189 * @param src Input data.
3190 */
3191static inline int fr_value_box_cast_to_ipv6prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
3192 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3193 fr_value_box_t const *src)
3194{
3195 fr_type_t src_type = src->type;
3196
3197 fr_assert(dst_type == FR_TYPE_IPV6_PREFIX);
3199
3200 switch (src_type) {
3201 case FR_TYPE_STRING:
3202 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3203 src->vb_strvalue, src->vb_length,
3204 NULL);
3205
3207
3208 default:
3209 break;
3210 }
3211
3212 /*
3213 * Pre-initialise box for non-variable types
3214 */
3215 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3216 dst->vb_ip.af = AF_INET6;
3217
3218 switch (src_type) {
3219 case FR_TYPE_IPV4_ADDR:
3220 {
3221 uint8_t *p = dst->vb_ipv6addr;
3222
3223 /* Add the v4/v6 mapping prefix */
3224 memcpy(p, v4_v6_map, sizeof(v4_v6_map));
3225 p += sizeof(v4_v6_map);
3226 memcpy(p, (uint8_t const *)&src->vb_ipv4addr, sizeof(src->vb_ipv4addr));
3227 dst->vb_ip.prefix = 128;
3228 dst->vb_ip.scope_id = 0;
3229 }
3230 break;
3231
3233 {
3234 uint8_t *p = dst->vb_ipv6addr;
3235
3236 /* Add the v4/v6 mapping prefix */
3237 memcpy(p, v4_v6_map, sizeof(v4_v6_map));
3238 p += sizeof(v4_v6_map);
3239 memcpy(p, (uint8_t const *)&src->vb_ipv4addr, sizeof(src->vb_ipv4addr));
3240 dst->vb_ip.prefix = (sizeof(v4_v6_map) << 3) + src->vb_ip.prefix;
3241 dst->vb_ip.scope_id = 0;
3242 }
3243 break;
3244
3245 case FR_TYPE_IPV6_PREFIX: /* Needed for handling combo prefixes */
3246 dst->vb_ip.prefix = src->vb_ip.prefix;
3247 goto v6_common;
3248
3249 case FR_TYPE_IPV6_ADDR:
3250 dst->vb_ip.prefix = 128;
3251 v6_common:
3252 memcpy(dst->vb_ipv6addr, src->vb_ipv6addr,
3253 sizeof(dst->vb_ipv6addr));
3254 dst->vb_ip.scope_id = src->vb_ip.scope_id;
3255 break;
3256
3257 case FR_TYPE_OCTETS:
3258 if (src->vb_length != (sizeof(dst->vb_ipv6addr) + 2)) {
3259 fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
3260 fr_type_to_str(src->type),
3261 fr_type_to_str(dst_type),
3262 sizeof(dst->vb_ipv6addr) + 2, src->vb_length);
3263 return -1;
3264 }
3265 dst->vb_ip.scope_id = src->vb_octets[0];
3266 dst->vb_ip.prefix = src->vb_octets[1];
3267 memcpy(&dst->vb_ipv6addr, src->vb_octets + 2, sizeof(dst->vb_ipv6addr));
3268 break;
3269
3270 default:
3271 return fr_value_box_cast_unsupported(dst_type, src->type);
3272 }
3273 return 0;
3274}
3275
3276/** Convert any supported type to an ethernet address
3277 *
3278 * Allowed input types are:
3279 * - FR_TYPE_STRING ("00:11:22:33:44:55")
3280 * - FR_TYPE_OCTETS (0x001122334455)
3281 *
3282 *
3283 * @param ctx unused.
3284 * @param dst Where to write result of casting.
3285 * @param dst_type to cast to.
3286 * @param dst_enumv enumeration values.
3287 * @param src Input data.
3288 */
3289static inline int fr_value_box_cast_to_ethernet(TALLOC_CTX *ctx, fr_value_box_t *dst,
3290 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3291 fr_value_box_t const *src)
3292{
3293 fr_assert(dst_type == FR_TYPE_ETHERNET);
3295
3296 switch (src->type) {
3297 case FR_TYPE_STRING:
3298 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3299 src->vb_strvalue, src->vb_length,
3300 NULL);
3301
3302 case FR_TYPE_OCTETS:
3303 return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3304
3305 default:
3306 break;
3307 }
3308
3309 /*
3310 * Pre-initialise box for non-variable types
3311 */
3312 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3313
3314 switch (src->type) {
3315 case FR_TYPE_UINT64: {
3316 uint8_t array[8];
3317
3318 fr_nbo_from_uint64(array, src->vb_uint64);
3319
3320 /*
3321 * For OUIs in the DB.
3322 */
3323 if ((array[0] != 0) || (array[1] != 0)) return -1;
3324
3325 memcpy(dst->vb_ether, &array[2], 6);
3326 break;
3327 }
3328
3329 default:
3330 return fr_value_box_cast_unsupported(dst_type, src->type);
3331 }
3332
3333 return 0;
3334}
3335
3336/** Convert any supported type to a bool
3337 *
3338 * Allowed input types are:
3339 * - FR_TYPE_STRING ("yes", "true", "no", "false")
3340 *
3341 * @param ctx unused.
3342 * @param dst Where to write result of casting.
3343 * @param dst_type to cast to.
3344 * @param dst_enumv enumeration values.
3345 * @param src Input data.
3346 */
3347static inline int fr_value_box_cast_to_bool(TALLOC_CTX *ctx, fr_value_box_t *dst,
3348 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3349 fr_value_box_t const *src)
3350{
3351 fr_assert(dst_type == FR_TYPE_BOOL);
3353
3354 switch (src->type) {
3355 case FR_TYPE_STRING:
3356 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3357 src->vb_strvalue, src->vb_length,
3358 NULL);
3359
3360 case FR_TYPE_OCTETS:
3361 /*
3362 * This is really "bool from network"
3363 */
3364 return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3365
3366 default:
3367 break;
3368 }
3369
3370 /*
3371 * Pre-initialise box for non-variable types
3372 */
3373 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3374
3375 switch (src->type) {
3376 case FR_TYPE_INT8:
3377 dst->vb_bool = (src->vb_int8 != 0);
3378 break;
3379
3380 case FR_TYPE_UINT8:
3381 dst->vb_bool = (src->vb_uint8 != 0);
3382 break;
3383
3384 case FR_TYPE_INT16:
3385 dst->vb_bool = (src->vb_int16 != 0);
3386 break;
3387
3388 case FR_TYPE_UINT16:
3389 dst->vb_bool = (src->vb_uint16 != 0);
3390 break;
3391
3392 case FR_TYPE_INT32:
3393 dst->vb_bool = (src->vb_int32 != 0);
3394 break;
3395
3396 case FR_TYPE_UINT32:
3397 dst->vb_bool = (src->vb_uint32 != 0);
3398 break;
3399
3400 case FR_TYPE_INT64:
3401 dst->vb_bool = (src->vb_int64 != 0);
3402 break;
3403
3404 case FR_TYPE_UINT64:
3405 dst->vb_bool = (src->vb_uint64 != 0);
3406 break;
3407
3408 case FR_TYPE_SIZE:
3409 dst->vb_bool = (src->vb_size != 0);
3410 break;
3411
3412 case FR_TYPE_TIME_DELTA:
3413 dst->vb_bool = (fr_time_delta_unwrap(src->vb_time_delta) != 0);
3414 break;
3415
3416 case FR_TYPE_FLOAT32:
3417 dst->vb_bool = (fpclassify(src->vb_float32) != FP_ZERO);
3418 break;
3419
3420 case FR_TYPE_FLOAT64:
3421 dst->vb_bool = (fpclassify(src->vb_float64) != FP_ZERO);
3422 break;
3423
3424 default:
3425 return fr_value_box_cast_unsupported(dst_type, src->type);
3426 }
3427
3428 return 0;
3429}
3430
3431/** Convert any signed or unsigned integer type to any other signed or unsigned integer type
3432 *
3433 */
3434static inline int fr_value_box_cast_integer_to_integer(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
3435 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3436 fr_value_box_t const *src)
3437{
3438 uint64_t tmp = 0;
3439 size_t len = fr_value_box_field_sizes[src->type];
3440 int64_t min;
3441
3443
3444#define SIGN_BIT_HIGH(_int, _len) ((((uint64_t)1) << (((_len) << 3) - 1)) & (_int))
3445#define SIGN_PROMOTE(_int, _len) ((_len) < sizeof(_int) ? \
3446 (_int) | (~((__typeof__(_int))0)) << ((_len) << 3) : (_int))
3447
3448#if !defined(NDEBUG) || defined(STATIC_ANALYZER)
3449 /*
3450 * Helps catch invalid fr_value_box_field_sizes
3451 * entries, and shuts up clang analyzer.
3452 */
3453 if (!fr_cond_assert_msg(len > 0, "Invalid cast from %s to %s. "
3454 "invalid source type len, expected > 0, got %zu",
3455 fr_type_to_str(src->type),
3456 fr_type_to_str(dst_type),
3457 len)) return -1;
3458
3459 if (!fr_cond_assert_msg(len <= sizeof(uint64_t),
3460 "Invalid cast from %s to %s. "
3461 "invalid source type len, expected <= %zu, got %zu",
3462 fr_type_to_str(src->type),
3463 fr_type_to_str(dst_type),
3464 sizeof(uint64_t), len)) return -1;
3465#endif
3466
3467 switch (src->type) {
3468 /*
3469 * Dates are always represented in nanoseconds
3470 * internally, but when we convert to another
3471 * integer type, we scale appropriately.
3472 *
3473 * i.e. if the attribute value resolution is
3474 * seconds, then the integer value is
3475 * nanoseconds -> seconds.
3476 */
3477 case FR_TYPE_DATE:
3478 {
3480 if (src->enumv) res = src->enumv->flags.flag_time_res;
3481
3482 tmp = fr_unix_time_to_integer(src->vb_date, res);
3483 }
3484 break;
3485
3486 /*
3487 * Same deal with time deltas. Note that
3488 * even though we store the value as an
3489 * unsigned integer, it'll be cast to a
3490 * signed integer for comparisons.
3491 */
3492 case FR_TYPE_TIME_DELTA:
3493 {
3495
3496 if (src->enumv) res = src->enumv->flags.flag_time_res;
3497
3498 tmp = (uint64_t)fr_time_delta_to_integer(src->vb_time_delta, res);
3499 }
3500 break;
3501
3502 default:
3503#ifdef WORDS_BIGENDIAN
3504 memcpy(((uint8_t *)&tmp) + (sizeof(tmp) - len),
3505 fr_value_box_raw(src, src->type), len);
3506#else
3507 memcpy(&tmp, fr_value_box_raw(src, src->type), len);
3508#endif
3509 break;
3510 }
3511
3512 min = fr_value_box_integer_min[dst_type];
3513
3514 /*
3515 * Sign promote the input if the source type is
3516 * signed, and the high bit is set.
3517 */
3518 if (fr_value_box_integer_min[src->type] < 0) {
3519 if (SIGN_BIT_HIGH(tmp, len)) tmp = SIGN_PROMOTE(tmp, len);
3520
3521 if ((int64_t)tmp < min) {
3522 fr_strerror_printf("Invalid cast from %s to %s. %"PRId64" "
3523 "outside value range %"PRId64"-%"PRIu64,
3524 fr_type_to_str(src->type),
3525 fr_type_to_str(dst_type),
3526 (int64_t)tmp,
3527 min, fr_value_box_integer_max[dst_type]);
3528 return -1;
3529 }
3530 } else if (tmp > fr_value_box_integer_max[dst_type]) {
3531 fr_strerror_printf("Invalid cast from %s to %s. %"PRIu64" "
3532 "outside value range 0-%"PRIu64,
3533 fr_type_to_str(src->type),
3534 fr_type_to_str(dst_type),
3535 tmp, fr_value_box_integer_max[dst_type]);
3536 return -1;
3537 }
3538
3539 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3540 switch (dst_type) {
3541 case FR_TYPE_DATE:
3542 {
3543 bool overflow;
3545 if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3546
3547 dst->vb_date = fr_unix_time_from_integer(&overflow, tmp, res);
3548 if (overflow) {
3549 fr_strerror_const("Input to date type would overflow");
3550 return -1;
3551 }
3552 }
3553 break;
3554
3555 case FR_TYPE_TIME_DELTA:
3556 {
3557 bool overflow;
3559 if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3560
3561 dst->vb_time_delta = fr_time_delta_from_integer(&overflow, tmp, res);
3562 if (overflow) {
3563 fr_strerror_const("Input to time_delta type would overflow");
3564 return -1;
3565 }
3566 }
3567 break;
3568
3569 default:
3570#ifdef WORDS_BIGENDIAN
3571 memcpy(fr_value_box_raw(dst, dst->type),
3572 ((uint8_t *)&tmp) + (sizeof(tmp) - len), fr_value_box_field_sizes[dst_type]);
3573#else
3574 memcpy(fr_value_box_raw(dst, dst->type),
3575 &tmp, fr_value_box_field_sizes[dst_type]);
3576#endif
3577 break;
3578 }
3579
3580 return 0;
3581}
3582
3583/** Convert any value to a signed or unsigned integer
3584 *
3585 * @param ctx unused.
3586 * @param dst Where to write result of casting.
3587 * @param dst_type to cast to.
3588 * @param dst_enumv enumeration values.
3589 * @param src Input data.
3590 */
3591static inline int fr_value_box_cast_to_integer(TALLOC_CTX *ctx, fr_value_box_t *dst,
3592 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3593 fr_value_box_t const *src)
3594{
3595 switch (src->type) {
3596 case FR_TYPE_STRING:
3597 return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3598 src->vb_strvalue, src->vb_length,
3599 NULL);
3600
3601 case FR_TYPE_OCTETS:
3602 return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3603
3604 case FR_TYPE_INTEGER:
3605 fr_value_box_init(dst, dst_type, dst_enumv, false);
3606 return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, src);
3607
3608 case FR_TYPE_IPV4_ADDR:
3610 {
3611 fr_value_box_t tmp;
3612
3613 switch (dst_type) {
3614 case FR_TYPE_UINT32:
3615 case FR_TYPE_INT64:
3616 case FR_TYPE_UINT64:
3617 case FR_TYPE_DATE:
3618 case FR_TYPE_TIME_DELTA:
3619 break;
3620
3621 default:
3622 goto bad_cast;
3623 }
3624
3625 fr_value_box_init(&tmp, FR_TYPE_UINT32, src->enumv, src->tainted);
3626 memcpy(&tmp.vb_uint32, &src->vb_ip.addr.v4, sizeof(tmp.vb_uint32));
3627 fr_value_box_hton(&tmp, &tmp);
3628 return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3629 }
3630
3631 case FR_TYPE_ETHERNET:
3632 {
3633 fr_value_box_t tmp;
3634
3635 switch (dst_type) {
3636 case FR_TYPE_INT64:
3637 case FR_TYPE_UINT64:
3638 case FR_TYPE_DATE:
3639 case FR_TYPE_TIME_DELTA:
3640 break;
3641
3642 default:
3643 goto bad_cast;
3644 }
3645
3646 fr_value_box_init(&tmp, FR_TYPE_UINT64, src->enumv, src->tainted);
3647 memcpy(((uint8_t *)&tmp.vb_uint64) + (sizeof(tmp.vb_uint64) - sizeof(src->vb_ether)),
3648 &src->vb_ether, sizeof(src->vb_ether));
3649#ifndef WORDS_BIGENDIAN
3650 /*
3651 * Ethernet addresses are always stored bigendian,
3652 * convert to native on little endian systems
3653 */
3654 fr_value_box_hton(&tmp, &tmp);
3655#endif
3656 return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3657 }
3658
3659 case FR_TYPE_IFID:
3660 {
3661 switch (dst_type) {
3662 case FR_TYPE_UINT64:
3663 break;
3664
3665 default:
3666 goto bad_cast;
3667 }
3668
3669 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3670 dst->vb_uint64 = fr_nbo_to_uint64(&src->vb_ifid[0]);
3671 return 0;
3672 }
3673
3674 case FR_TYPE_FLOAT32:
3675 if (src->vb_float32 < (double) fr_value_box_integer_min[dst_type]) {
3676 underflow:
3677 fr_strerror_const("Source value for cast would underflow destination type");
3678 return -1;
3679 }
3680
3681 if (src->vb_float32 > (double) fr_value_box_integer_max[dst_type]) {
3682 overflow:
3683 fr_strerror_const("Source value for cast would overflow destination type");
3684 return -1;
3685 }
3686
3687 switch (dst_type) {
3688 case FR_TYPE_UINT8:
3689 dst->vb_uint8 = src->vb_float32;
3690 break;
3691
3692 case FR_TYPE_UINT16:
3693 dst->vb_uint16 = src->vb_float32;
3694 break;
3695
3696 case FR_TYPE_UINT32:
3697 dst->vb_uint32 = src->vb_float32;
3698 break;
3699
3700 case FR_TYPE_UINT64:
3701 dst->vb_uint64 = src->vb_float32;
3702 break;
3703
3704 case FR_TYPE_INT8:
3705 dst->vb_int8 = src->vb_float32;
3706 break;
3707
3708 case FR_TYPE_INT16:
3709 dst->vb_int16 = src->vb_float32;
3710 break;
3711
3712 case FR_TYPE_INT32:
3713 dst->vb_int32 = src->vb_float32;
3714 break;
3715
3716 case FR_TYPE_INT64:
3717 dst->vb_int64 = src->vb_float32;
3718 break;
3719
3720 case FR_TYPE_SIZE:
3721 dst->vb_size = src->vb_float32;
3722 break;
3723
3724 case FR_TYPE_DATE: {
3725 int64_t sec, nsec;
3726
3727 sec = src->vb_float32;
3728 sec *= NSEC;
3729 nsec = ((src->vb_float32 * NSEC) - ((float) sec));
3730
3731 dst->vb_date = fr_unix_time_from_nsec(sec + nsec);
3732 }
3733 break;
3734
3735 case FR_TYPE_TIME_DELTA: {
3736 int64_t sec, nsec;
3737 int64_t res = NSEC;
3738 bool fail = false;
3739
3740 if (dst->enumv) res = fr_time_multiplier_by_res[dst->enumv->flags.flag_time_res];
3741
3742 sec = src->vb_float32;
3743 sec *= res;
3744 nsec = ((src->vb_float32 * res) - ((double) sec));
3745
3746 dst->vb_time_delta = fr_time_delta_from_integer(&fail, sec + nsec,
3747 dst->enumv ? dst->enumv->flags.flag_time_res : FR_TIME_RES_NSEC);
3748 if (fail) goto overflow;
3749 }
3750 break;
3751
3752 default:
3753 goto bad_cast;
3754 }
3755 return 0;
3756
3757 case FR_TYPE_FLOAT64:
3758 if (src->vb_float64 < (double) fr_value_box_integer_min[dst_type]) goto underflow;
3759
3760 if (src->vb_float64 > (double) fr_value_box_integer_max[dst_type]) goto overflow;
3761
3762 switch (dst_type) {
3763 case FR_TYPE_UINT8:
3764 dst->vb_uint8 = src->vb_float64;
3765 break;
3766
3767 case FR_TYPE_UINT16:
3768 dst->vb_uint16 = src->vb_float64;
3769 break;
3770
3771 case FR_TYPE_UINT32:
3772 dst->vb_uint32 = src->vb_float64;
3773 break;
3774
3775 case FR_TYPE_UINT64:
3776 dst->vb_uint64 = src->vb_float64;
3777 break;
3778
3779 case FR_TYPE_INT8:
3780 dst->vb_int8 = src->vb_float64;
3781 break;
3782
3783 case FR_TYPE_INT16:
3784 dst->vb_int16 = src->vb_float64;
3785 break;
3786
3787 case FR_TYPE_INT32:
3788 dst->vb_int32 = src->vb_float64;
3789 break;
3790
3791 case FR_TYPE_INT64:
3792 dst->vb_int64 = src->vb_float64;
3793 break;
3794
3795 case FR_TYPE_SIZE:
3796 dst->vb_size = src->vb_float64;
3797 break;
3798
3799 case FR_TYPE_DATE: {
3800 int64_t sec, nsec;
3801
3802 sec = src->vb_float64;
3803
3804 if (unlikely((sec > INT64_MAX / NSEC) || (sec < INT64_MIN / NSEC))) goto overflow;
3805 sec *= NSEC;
3806 nsec = ((src->vb_float64 * NSEC) - ((double) sec));
3807
3808 dst->vb_date = fr_unix_time_from_nsec(sec + nsec);
3809 }
3810 break;
3811
3812 case FR_TYPE_TIME_DELTA: {
3813 int64_t sec, nsec;
3814 int64_t res = NSEC;
3815 bool fail = false;
3816
3817 if (dst->enumv) res = fr_time_multiplier_by_res[dst->enumv->flags.flag_time_res];
3818
3819 sec = src->vb_float64;
3820
3821 if (unlikely((sec > INT64_MAX / res) || (sec < INT64_MIN / res))) goto overflow;
3822 sec *= res;
3823 nsec = ((src->vb_float64 * res) - ((double) sec));
3824
3825 dst->vb_time_delta = fr_time_delta_from_integer(&fail, sec + nsec,
3826 dst->enumv ? dst->enumv->flags.flag_time_res : FR_TIME_RES_NSEC);
3827 if (fail) goto overflow;
3828 }
3829 break;
3830
3831 default:
3832 goto bad_cast;
3833 }
3834 return 0;
3835
3836 default:
3837 break;
3838 }
3839
3840bad_cast:
3841 return fr_value_box_cast_unsupported(dst_type, src->type);
3842}
3843
3844/** Convert any value to a floating point value
3845 *
3846 * @param ctx unused.
3847 * @param dst Where to write result of casting.
3848 * @param dst_type to cast to.
3849 * @param dst_enumv enumeration values.
3850 * @param src Input data.
3851 */
3852static inline int fr_value_box_cast_to_float(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
3853 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3854 fr_value_box_t const *src)
3855{
3856 double num;
3857
3858 switch (src->type) {
3859 case FR_TYPE_FLOAT32:
3860 if (dst_type == FR_TYPE_FLOAT64) {
3861 num = (double) src->vb_float32;
3862 goto good_cast;
3863 }
3864
3865 goto bad_cast;
3866
3867 case FR_TYPE_FLOAT64:
3868 if (dst_type == FR_TYPE_FLOAT32) {
3869 num = src->vb_float64;
3870 goto good_cast;
3871 }
3872
3873 goto bad_cast;
3874
3875 case FR_TYPE_BOOL:
3876 num = src->vb_bool;
3877 goto good_cast;
3878
3879 case FR_TYPE_INT8:
3880 num = src->vb_int8;
3881 goto good_cast;
3882
3883 case FR_TYPE_INT16:
3884 num = src->vb_int16;
3885 goto good_cast;
3886
3887 case FR_TYPE_INT32:
3888 num = src->vb_int32;
3889 goto good_cast;
3890
3891 case FR_TYPE_INT64:
3892 num = src->vb_int64;
3893 goto good_cast;
3894
3895 case FR_TYPE_UINT8:
3896 num = src->vb_uint8;
3897 goto good_cast;
3898
3899 case FR_TYPE_UINT16:
3900 num = src->vb_uint16;
3901 goto good_cast;
3902
3903 case FR_TYPE_UINT32:
3904 num = src->vb_uint32;
3905 goto good_cast;
3906
3907 case FR_TYPE_UINT64:
3908 num = src->vb_uint64;
3909 goto good_cast;
3910
3911 case FR_TYPE_DATE:
3912 /*
3913 * Unix times are in nanoseconds
3914 */
3915 num = fr_unix_time_unwrap(src->vb_date);
3916 num /= NSEC;
3917 goto good_cast;
3918
3919 case FR_TYPE_TIME_DELTA:
3920 /*
3921 * Time deltas are in nanoseconds, but scaled.
3922 */
3923 num = fr_time_delta_unwrap(src->vb_time_delta);
3924 if (src->enumv) {
3925 num /= fr_time_multiplier_by_res[src->enumv->flags.flag_time_res];
3926 } else {
3927 num /= NSEC;
3928 }
3929 goto good_cast;
3930
3931 case FR_TYPE_SIZE:
3932 num = src->vb_size;
3933
3934 good_cast:
3935 fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3937
3938 if (dst_type == FR_TYPE_FLOAT32) {
3939 dst->vb_float32 = num;
3940 } else {
3941 dst->vb_float64 = num;
3942 }
3943 return 0;
3944
3945 default:
3946 break;
3947 }
3948
3949bad_cast:
3950 return fr_value_box_cast_unsupported(dst_type, src->type);
3951}
3952
3953
3954/** Convert one type of fr_value_box_t to another
3955 *
3956 * This should be the canonical function used to convert between INTERNAL data formats.
3957 *
3958 * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
3959 *
3960 * @note src and dst must not be the same box. We do not support casting in place.
3961 *
3962 * @param ctx to allocate buffers in (usually the same as dst)
3963 * @param dst Where to write result of casting.
3964 * @param dst_type to cast to.
3965 * @param dst_enumv Aliases for values contained within this fr_value_box_t.
3966 * If #fr_value_box_t is passed to #fr_value_box_aprint
3967 * names will be printed instead of actual value.
3968 * @param src Input data.
3969 * @return
3970 * - 0 on success.
3971 * - -1 on failure.
3972 */
3973int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst,
3974 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3975 fr_value_box_t const *src)
3976{
3977 if (!fr_cond_assert(src != dst)) return -1;
3978
3979 if (fr_type_is_non_leaf(dst_type)) {
3980 fr_strerror_printf("Invalid cast from %s to %s. Can only cast simple data types",
3981 fr_type_to_str(src->type),
3982 fr_type_to_str(dst_type));
3983 return -1;
3984 }
3985
3986 /*
3987 * If it's the same type, copy, but set the enumv
3988 * in the destination box to be the one provided.
3989 *
3990 * The theory here is that the attribute value isn't
3991 * being converted into its presentation format and
3992 * re-parsed, and the enumv names only get applied
3993 * when converting internal values to/from strings,
3994 * so it's OK just to swap out the enumv.
3995 *
3996 * If there's a compelling case in the future we
3997 * might revisit this, but it'd likely mean fixing
3998 * all the casting functions to treat any value
3999 * with an enumv as a string, which seems weird.
4000 */
4001 if (dst_type == src->type) {
4002 int ret;
4003
4004 ret = fr_value_box_copy(ctx, dst, src);
4005 if (ret < 0) return ret;
4006
4007 if (dst_enumv) dst->enumv = dst_enumv;
4008
4009 return ret;
4010 }
4011
4012 /*
4013 * Initialise dst
4014 */
4015 fr_value_box_init(dst, dst_type, NULL, src->tainted);
4016
4017 /*
4018 * Dispatch to specialised cast functions
4019 */
4020 switch (dst_type) {
4021 case FR_TYPE_STRING:
4022 return fr_value_box_cast_to_strvalue(ctx, dst, dst_type, dst_enumv, src);
4023
4024 case FR_TYPE_OCTETS:
4025 return fr_value_box_cast_to_octets(ctx, dst, dst_type, dst_enumv, src);
4026
4027 case FR_TYPE_IPV4_ADDR:
4028 return fr_value_box_cast_to_ipv4addr(ctx, dst, dst_type, dst_enumv, src);
4029
4031 return fr_value_box_cast_to_ipv4prefix(ctx, dst, dst_type, dst_enumv, src);
4032
4033 case FR_TYPE_IPV6_ADDR:
4034 return fr_value_box_cast_to_ipv6addr(ctx, dst, dst_type, dst_enumv, src);
4035
4037 return fr_value_box_cast_to_ipv6prefix(ctx, dst, dst_type, dst_enumv, src);
4038
4041 break;
4042 /*
4043 * Need func
4044 */
4045 case FR_TYPE_IFID:
4046 break;
4047
4048 case FR_TYPE_ETHERNET:
4049 return fr_value_box_cast_to_ethernet(ctx, dst, dst_type, dst_enumv, src);
4050
4051 case FR_TYPE_BOOL:
4052 return fr_value_box_cast_to_bool(ctx, dst, dst_type, dst_enumv, src);
4053
4054 case FR_TYPE_DATE:
4055 if (src->type != FR_TYPE_TIME_DELTA) return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
4056
4057 if (fr_time_delta_isneg(src->vb_time_delta)) {
4058 fr_strerror_const("Input to data type would underflow");
4059 return -1;
4060 }
4061
4063 dst->enumv = dst_enumv;
4064 dst->vb_date = fr_unix_time_wrap(fr_time_delta_unwrap(src->vb_time_delta));
4065 return 0;
4066
4067 case FR_TYPE_TIME_DELTA:
4068 /*
4069 * Unix time cast to time_delta is just nanoseconds since the epoch.
4070 *
4071 * Note that we do NOT change time resolution, but we DO change enumv. Both unix time
4072 * and time_delta are tracked internally as nanoseconds, and the only use of precision is
4073 * for printing / parsing.
4074 */
4075 if (src->type == FR_TYPE_DATE) {
4076 uint64_t when;
4077
4078 when = fr_unix_time_unwrap(src->vb_date);
4079 if (when > INT64_MAX) {
4080 fr_strerror_const("Input to data type would overflow");
4081 return -1;
4082 }
4083
4085 dst->enumv = dst_enumv;
4086 dst->vb_time_delta = fr_time_delta_wrap((int64_t) when);
4087 return 0;
4088 }
4090
4091 case FR_TYPE_UINT8:
4092 case FR_TYPE_UINT16:
4093 case FR_TYPE_UINT32:
4094 case FR_TYPE_UINT64:
4095 case FR_TYPE_INT8:
4096 case FR_TYPE_INT16:
4097 case FR_TYPE_INT32:
4098 case FR_TYPE_INT64:
4099 case FR_TYPE_SIZE:
4100 return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
4101
4102 case FR_TYPE_FLOAT32:
4103 case FR_TYPE_FLOAT64:
4104 if (fr_type_is_fixed_size(src->type)) {
4105 return fr_value_box_cast_to_float(ctx, dst, dst_type, dst_enumv, src);
4106 }
4107 break; /* use generic string/octets stuff below */
4108
4109#if 0
4110 case FR_TYPE_ATTR:
4111 /*
4112 * Convert it to an integer of the correct length. Then, cast it in place.
4113 */
4114 switch (src->vb_attr->flags.length) {
4115 case 1:
4116 fr_value_box_init(dst, FR_TYPE_UINT8, NULL, false);
4117 dst->vb_uint8 = src->vb_attr->attr;
4118 break;
4119
4120 case 2:
4121 fr_value_box_init(dst, FR_TYPE_UINT16, NULL, false);
4122 dst->vb_uint16 = src->vb_attr->attr;
4123 break;
4124
4125 case 4:
4126 fr_value_box_init(dst, FR_TYPE_UINT32, NULL, false);
4127 dst->vb_uint32 = src->vb_attr->attr;
4128 break;
4129
4130 default:
4131 fr_strerror_printf("Unsupported length '%d' for attribute %s",
4132 src->vb_attr->flags.length, src->vb_attr->name);
4133 return 0;
4134 }
4135
4136 return fr_value_box_cast_in_place(ctx, dst, dst_type, dst_enumv);
4137#else
4138 case FR_TYPE_ATTR:
4139 if (src->type == FR_TYPE_STRING) break;
4140
4142
4143#endif
4144 /*
4145 * Invalid types for casting (were caught earlier)
4146 */
4147 case FR_TYPE_NON_LEAF:
4148 fr_strerror_printf("Invalid cast from %s to %s. Invalid destination type",
4149 fr_type_to_str(src->type),
4150 fr_type_to_str(dst_type));
4151 return -1;
4152 }
4153
4154 /*
4155 * Deserialise a fr_value_box_t
4156 */
4157 if (src->type == FR_TYPE_STRING) return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
4158 src->vb_strvalue, src->vb_length,
4159 NULL);
4160
4161 if (src->type == FR_TYPE_OCTETS) {
4162 fr_value_box_t tmp;
4163
4164 if (src->vb_length < network_min_size(dst_type)) {
4165 fr_strerror_printf("Invalid cast from %s to %s. Source is length %zu is smaller than "
4166 "destination type size %zu",
4167 fr_type_to_str(src->type),
4168 fr_type_to_str(dst_type),
4169 src->vb_length,
4170 network_min_size(dst_type));
4171 return -1;
4172 }
4173
4174 if (src->vb_length > network_max_size(dst_type)) {
4175 fr_strerror_printf("Invalid cast from %s to %s. Source length %zu is greater than "
4176 "destination type size %zu",
4177 fr_type_to_str(src->type),
4178 fr_type_to_str(dst_type),
4179 src->vb_length,
4180 network_max_size(dst_type));
4181 return -1;
4182 }
4183
4184 fr_value_box_init(&tmp, dst_type, NULL, false);
4185
4186 /*
4187 * Copy the raw octets into the datum of a value_box
4188 * inverting bytesex for uint32s (if LE).
4189 */
4190 memcpy(&tmp.datum, src->vb_octets, fr_value_box_field_sizes[dst_type]);
4191 tmp.type = dst_type;
4192 dst->enumv = dst_enumv;
4193
4194 fr_value_box_hton(dst, &tmp);
4195 fr_value_box_safety_copy(dst, src);
4196 return 0;
4197 }
4198
4199 memcpy(&dst->datum, &src->datum, fr_value_box_field_sizes[src->type]);
4200
4202 dst->enumv = dst_enumv;
4203
4204 return 0;
4205}
4206
4207/** Convert one type of fr_value_box_t to another in place
4208 *
4209 * This should be the canonical function used to convert between INTERNAL data formats.
4210 *
4211 * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
4212 *
4213 * @param ctx to allocate buffers in (usually the same as dst)
4214 * @param vb to cast.
4215 * @param dst_type to cast to.
4216 * @param dst_enumv Aliases for values contained within this fr_value_box_t.
4217 * If #fr_value_box_t is passed to #fr_value_box_aprint
4218 * names will be printed instead of actual value.
4219 * @return
4220 * - 0 on success.
4221 * - -1 on failure.
4222 */
4224 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
4225{
4226 fr_value_box_t tmp;
4227 /*
4228 * Store list pointers to restore later - fr_value_box_cast clears them
4229 */
4230 fr_value_box_entry_t entry = vb->entry;
4231
4232 /*
4233 * Simple case, destination type and current
4234 * type are the same.
4235 */
4236 if (vb->type == dst_type) {
4237 vb->enumv = dst_enumv; /* Update the enumv as this may be different */
4238 return 0;
4239 }
4240
4241 /*
4242 * Copy meta data and any existing buffers to
4243 * a temporary box. We then clear that value
4244 * box after the cast has been completed,
4245 * freeing any old buffers.
4246 */
4247 fr_value_box_copy_shallow(NULL, &tmp, vb);
4248
4249 if (fr_value_box_cast(ctx, vb, dst_type, dst_enumv, &tmp) < 0) {
4250 /*
4251 * On error, make sure the original
4252 * box is left in a consistent state.
4253 */
4254 fr_value_box_copy_shallow(NULL, vb, &tmp);
4255 vb->entry = entry;
4256 return -1;
4257 }
4258 fr_value_box_clear_value(&tmp); /* Clear out any old buffers */
4259
4260 /*
4261 * Restore list pointers
4262 */
4263 vb->entry = entry;
4264
4265 return 0;
4266}
4267
4268/** Return a uint64_t from a #fr_value_box_t
4269 *
4270 * @param[in] vb the value-box. Must be an unsigned integer data type.
4271 * @return the value as uint64_t.
4272 */
4274{
4275#undef O
4276#define O(_x, _y) case FR_TYPE_##_x: return vb->vb_##_y
4277
4278
4279 switch (vb->type) {
4280 O(BOOL, bool);
4281 O(UINT8, uint8);
4282 O(UINT16, uint16);
4283 O(UINT32, uint32);
4284 O(UINT64, uint64);
4285 O(SIZE, size);
4286
4287 default:
4288 fr_assert(0);
4289 return 0;
4290 }
4291}
4292
4293
4294/** Assign a #fr_value_box_t value from an #fr_ipaddr_t
4295 *
4296 * Automatically determines the type of the value box from the ipaddr address family
4297 * and the length of the prefix field.
4298 *
4299 * @param[in] dst to assign ipaddr to.
4300 * @param[in] enumv Aliases for values.
4301 * @param[in] ipaddr to copy address from.
4302 * @param[in] tainted Whether the value came from a trusted source.
4303 * @return
4304 * - 0 on success.
4305 * - -1 on failure.
4306 */
4307int fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ipaddr_t const *ipaddr, bool tainted)
4308{
4310
4311 switch (ipaddr->af) {
4312 case AF_INET:
4314 break;
4315
4316 case AF_INET6:
4318 break;
4319
4320 default:
4321 fr_strerror_printf("Invalid address family %i", ipaddr->af);
4322 return -1;
4323 }
4324
4325 fr_value_box_init(dst, type, enumv, tainted);
4326 memcpy(&dst->vb_ip, ipaddr, sizeof(dst->vb_ip));
4327
4328 return 0;
4329}
4330
4331/** Unbox an IP address performing a type check
4332 *
4333 * @param[out] dst Where to copy the IP address to.
4334 * @param[in] src Where to copy the IP address from.
4335 * @return
4336 * - 0 on success.
4337 * - -1 on type mismatch.
4338 */
4340{
4341 if (!fr_type_is_ip(src->type)) {
4342 fr_strerror_printf("Unboxing failed. Needed IPv4/6 addr/prefix, had type %s",
4343 fr_type_to_str(src->type));
4344 return -1;
4345 }
4346
4347 memcpy(dst, &src->vb_ip, sizeof(*dst));
4348
4349 return 0;
4350}
4351
4352/** Clear/free any existing value
4353 *
4354 * @note Do not use on uninitialised memory.
4355 *
4356 * @param[in] data to clear.
4357 */
4359{
4360 switch (data->type) {
4361 case FR_TYPE_OCTETS:
4362 case FR_TYPE_STRING:
4363 if (data->vb_secret) memset_explicit(data->datum.ptr, 0, data->vb_length);
4364 talloc_free(data->datum.ptr);
4365 break;
4366
4367 case FR_TYPE_GROUP:
4368 /*
4369 * Depth first freeing of children
4370 *
4371 * This ensures orderly freeing, regardless
4372 * of talloc hierarchy.
4373 */
4374 {
4375 fr_value_box_t *vb;
4376
4377 while ((vb = fr_value_box_list_pop_head(&data->vb_group)) != NULL) {
4379 talloc_free(vb);
4380 }
4381 }
4382 return;
4383
4384 case FR_TYPE_NULL:
4385 return;
4386
4388 talloc_free(data->vb_cursor);
4389 break;
4390
4391 default:
4392 break;
4393 }
4394
4395 memset(&data->datum, 0, sizeof(data->datum));
4396}
4397
4398/** Clear/free any existing value and metadata
4399 *
4400 * @note Do not use on uninitialised memory.
4401 *
4402 * @param[in] data to clear.
4403 */
4409
4410/** Copy value data verbatim duplicating any buffers
4411 *
4412 * @note Will free any exiting buffers associated with the dst #fr_value_box_t.
4413 *
4414 * @param ctx To allocate buffers in.
4415 * @param dst Where to copy value_box to.
4416 * @param src Where to copy value_box from.
4417 * @return
4418 * - 0 on success.
4419 * - -1 on failure.
4420 */
4421int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
4422{
4423 switch (src->type) {
4424 case FR_TYPE_NUMERIC:
4425 case FR_TYPE_IP:
4426 case FR_TYPE_IFID:
4427 case FR_TYPE_ETHERNET:
4428 fr_value_box_memcpy_out(fr_value_box_raw(dst, src->type), src);
4429 fr_value_box_copy_meta(dst, src);
4430 break;
4431
4432 case FR_TYPE_NULL:
4433 fr_value_box_copy_meta(dst, src);
4434 break;
4435
4436 case FR_TYPE_STRING:
4437 {
4438 char *str = NULL;
4439
4440 /*
4441 * Zero length strings still have a one uint8 buffer
4442 */
4443 str = talloc_bstrndup(ctx, src->vb_strvalue, src->vb_length);
4444 if (!str) {
4445 fr_strerror_const("Failed allocating string buffer");
4446 return -1;
4447 }
4448 dst->vb_strvalue = str;
4449 fr_value_box_copy_meta(dst, src);
4450 }
4451 break;
4452
4453 case FR_TYPE_OCTETS:
4454 {
4455 uint8_t *bin;
4456
4457 if (src->vb_length) {
4458 bin = talloc_memdup(ctx, src->vb_octets, src->vb_length);
4459 if (!bin) {
4460 fr_strerror_const("Failed allocating octets buffer");
4461 return -1;
4462 }
4463 talloc_set_type(bin, uint8_t);
4464 } else {
4465 bin = talloc_array(ctx, uint8_t, 0);
4466 }
4467 dst->vb_octets = bin;
4468 fr_value_box_copy_meta(dst, src);
4469 }
4470 break;
4471
4472 case FR_TYPE_GROUP:
4473 {
4474 fr_value_box_t *child = NULL;
4475
4476 fr_value_box_copy_meta(dst, src); /* Initialises group child dlist */
4477
4478 while ((child = fr_value_box_list_next(&src->vb_group, child))) {
4479 fr_value_box_t *new;
4480
4481 /*
4482 * Build out the child
4483 */
4484 new = fr_value_box_alloc_null(ctx);
4485 if (unlikely(!new)) {
4486 group_error:
4487 fr_strerror_const("Failed duplicating group child");
4488 fr_value_box_list_talloc_free(&dst->vb_group);
4489 return -1;
4490 }
4491
4492 /*
4493 * Populate it with the data from the original child.
4494 *
4495 * We do NOT update the dst safety. The individual boxes have safety. A group
4496 * doesn't.
4497 */
4498 if (unlikely(fr_value_box_copy(new, new, child) < 0)) goto group_error;
4499 fr_value_box_list_insert_tail(&dst->vb_group, new);
4500 }
4501 }
4502 break;
4503
4504 case FR_TYPE_ATTR:
4505 fr_value_box_copy_meta(dst, src);
4506
4507 /* raw also sets is_unknown */
4508 if (src->vb_attr->flags.is_unknown) {
4509 dst->vb_attr = fr_dict_attr_unknown_copy(ctx, src->vb_attr);
4510 if (!dst->vb_attr) return -1;
4511 break;
4512 }
4513 dst->vb_attr = src->vb_attr;
4514 break;
4515
4516 case FR_TYPE_TLV:
4517 case FR_TYPE_STRUCT:
4518 case FR_TYPE_VSA:
4519 case FR_TYPE_VENDOR:
4520 case FR_TYPE_UNION:
4521 case FR_TYPE_VOID:
4522 case FR_TYPE_VALUE_BOX:
4525 case FR_TYPE_MAX:
4526 fr_assert(0);
4527 fr_strerror_printf("Cannot copy data type '%s'", fr_type_to_str(src->type));
4528 return -1;
4529 }
4530
4531 return 0;
4532}
4533
4534/** Perform a shallow copy of a value_box
4535 *
4536 * Like #fr_value_box_copy, but does not duplicate the buffers of the src value_box.
4537 *
4538 * For #FR_TYPE_STRING and #FR_TYPE_OCTETS adds a reference from ctx so that the
4539 * buffer cannot be freed until the ctx is freed.
4540 *
4541 * @param[in] ctx to add reference from. If NULL no reference will be added.
4542 * @param[in] dst to copy value to.
4543 * @param[in] src to copy value from.
4544 */
4545void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
4546{
4547 switch (src->type) {
4548 default:
4549 if (unlikely(fr_value_box_copy(NULL, dst, src) < 0)) return;
4550 break;
4551
4552 case FR_TYPE_STRING:
4553 case FR_TYPE_OCTETS:
4554 dst->datum.ptr = ctx ? talloc_reference(ctx, src->datum.ptr) : src->datum.ptr;
4555 fr_value_box_copy_meta(dst, src);
4556 break;
4557
4558 case FR_TYPE_ATTR:
4559 dst->vb_attr = src->vb_attr;
4560 fr_value_box_copy_meta(dst, src);
4561 break;
4562
4563 case FR_TYPE_VOID:
4564 dst->vb_void = src->vb_void;
4565 fr_value_box_copy_meta(dst, src);
4566 break;
4567 }
4568}
4569
4570/** Copy value data verbatim moving any buffers to the specified context
4571 *
4572 * @param[in] ctx to allocate any new buffers in.
4573 * @param[in] dst to copy value to.
4574 * @param[in] src to copy value from.
4575 * @return
4576 * - 0 on success.
4577 * - -1 on failure.
4578 */
4579int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
4580{
4581 VALUE_BOX_VERIFY(src);
4582
4583 switch (src->type) {
4584 default:
4585 return fr_value_box_copy(ctx, dst, src);
4586
4587 case FR_TYPE_STRING:
4588 {
4589 char const *str;
4590
4591 str = talloc_steal(ctx, src->vb_strvalue);
4592 if (!str) {
4593 fr_strerror_const("Failed stealing string buffer");
4594 return -1;
4595 }
4596 talloc_set_type(str, char);
4597 dst->vb_strvalue = str;
4598 fr_value_box_copy_meta(dst, src);
4599 memset(&src->datum, 0, sizeof(src->datum));
4600 }
4601 return 0;
4602
4603 case FR_TYPE_OCTETS:
4604 {
4605 uint8_t const *bin;
4606
4607 bin = talloc_steal(ctx, src->vb_octets);
4608 if (!bin) {
4609 fr_strerror_const("Failed stealing octets buffer");
4610 return -1;
4611 }
4612 talloc_set_type(bin, uint8_t);
4613
4614 dst->vb_octets = bin;
4615 fr_value_box_copy_meta(dst, src);
4616 memset(&src->datum, 0, sizeof(src->datum));
4617 }
4618 return 0;
4619
4620 case FR_TYPE_GROUP:
4621 {
4622 fr_value_box_t *child;
4623
4624 while ((child = fr_value_box_list_pop_head(&src->vb_group))) {
4625 child = talloc_steal(ctx, child);
4626 if (unlikely(!child)) {
4627 fr_strerror_const("Failed stealing child");
4628 return -1;
4629 }
4630 fr_value_box_list_insert_tail(&dst->vb_group, child);
4631 }
4632 }
4633 return 0;
4634 }
4635}
4636
4637/** Copy a nul terminated string to a #fr_value_box_t
4638 *
4639 * @param[in] ctx to allocate any new buffers in.
4640 * @param[in] dst to assign new buffer to.
4641 * @param[in] enumv Aliases for values.
4642 * @param[in] src a nul terminated buffer.
4643 * @param[in] tainted Whether the value came from a trusted source.
4644 * @return
4645 * - 0 on success.
4646 * - -1 on failure.
4647 */
4648int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4649 char const *src, bool tainted)
4650{
4651 char const *str;
4652
4653 str = talloc_strdup(ctx, src);
4654 if (!str) {
4655 fr_strerror_const("Failed allocating string buffer");
4656 return -1;
4657 }
4658
4659 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4660 dst->vb_strvalue = str;
4661 dst->vb_length = talloc_strlen(str);
4662
4663 return 0;
4664}
4665
4666/** Trim the length of the string buffer to match the length of the C string
4667 *
4668 * @param[in] ctx to re-alloc the buffer in.
4669 * @param[in,out] vb to trim.
4670 * @return
4671 * - 0 on success.
4672 * - -1 on failure.
4673 */
4674int fr_value_box_strtrim(TALLOC_CTX *ctx, fr_value_box_t *vb)
4675{
4676 size_t len;
4677 char *str;
4678
4679 if (!fr_cond_assert(vb->type == FR_TYPE_STRING)) return -1;
4680
4681 len = strlen(vb->vb_strvalue);
4682 str = talloc_realloc(ctx, UNCONST(char *, vb->vb_strvalue), char, len + 1);
4683 if (!str) {
4684 fr_strerror_const("Failed re-allocing string buffer");
4685 return -1;
4686 }
4687 vb->vb_strvalue = str;
4688 vb->vb_length = len;
4689
4690 return 0;
4691}
4692
4693/** Print a formatted string using our internal printf wrapper and assign it to a value box
4694 *
4695 * @param[in] ctx to allocate any new buffers in.
4696 * @param[in] dst to assign new buffer to.
4697 * @param[in] enumv Aliases for values.
4698 * @param[in] fmt The printf format string to process.
4699 * @param[in] tainted Whether the value came from a trusted source.
4700 * @param[in] ap Substitution arguments.
4701 * @return
4702 * - 0 on success.
4703 * - -1 on failure.
4704 */
4705int fr_value_box_vasprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
4706 char const *fmt, va_list ap)
4707{
4708 va_list aq;
4709 char *str;
4710
4711 va_copy(aq, ap); /* See vlog_module_failure_msg for why */
4712 str = fr_vasprintf(ctx, fmt, aq);
4713 va_end(aq);
4714
4715 if (!str) return -1;
4716
4717 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4718 dst->vb_strvalue = str;
4719 dst->vb_length = talloc_strlen(str);
4720
4721 return 0;
4722}
4723
4724/** Print a formatted string using our internal printf wrapper and assign it to a value box
4725 *
4726 * @param[in] ctx to allocate any new buffers in.
4727 * @param[in] dst to assign new buffer to.
4728 * @param[in] enumv Aliases for values.
4729 * @param[in] tainted Whether the value came from a trusted source.
4730 * @param[in] fmt The printf format string to process.
4731 * @param[in] ... Substitution arguments.
4732 * @return
4733 * - 0 on success.
4734 * - -1 on failure.
4735 */
4736int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
4737 char const *fmt, ...)
4738{
4739 va_list ap;
4740 int ret;
4741
4742 va_start(ap, fmt);
4743 ret = fr_value_box_vasprintf(ctx, dst, enumv, tainted, fmt, ap);
4744 va_end(ap);
4745
4746 return ret;
4747}
4748
4749/** Assign a buffer containing a nul terminated string to a box, but don't copy it
4750 *
4751 * @note Input string will not be duplicated.
4752 *
4753 * @param[in] dst to assign string to.
4754 * @param[in] enumv Aliases for values.
4755 * @param[in] src to copy string from.
4756 * @param[in] tainted Whether the value came from a trusted source.
4757 */
4759 char const *src, bool tainted)
4760{
4761 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4762 dst->vb_strvalue = src;
4763 dst->vb_length = strlen(src);
4764}
4765
4766/** Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one
4767 *
4768 * @note Input string will not be duplicated.
4769 *
4770 * @param[in] vb to replace string in.
4771 * @param[in] src to assign string from.
4772 * @param[in] len of src.
4773 */
4775{
4777 vb->vb_strvalue = src;
4778 vb->vb_length = len < 0 ? strlen(src) : (size_t)len;
4779}
4780
4781/** Free the existing buffer (if talloced) associated with the valuebox, and replace it with a copy of a new one
4782 *
4783 * The box's flags are left as they were. src may alias the existing value,
4784 * the copy is taken before the existing value is freed.
4785 *
4786 * @param[in] ctx to allocate the copy in.
4787 * @param[in] vb to replace string in.
4788 * @param[in] src to copy string from.
4789 * @param[in] len of src. If negative, src must be NUL terminated.
4790 * @return
4791 * - 0 on success.
4792 * - -1 on allocation failure.
4793 */
4794int fr_value_box_bstrndup_replace(TALLOC_CTX *ctx, fr_value_box_t *vb, char const *src, ssize_t len)
4795{
4796 char *str;
4797
4798 if (len < 0) len = strlen(src);
4799
4800 str = talloc_bstrndup(ctx, src, (size_t)len);
4801 if (unlikely(!str)) {
4802 fr_strerror_const("Failed allocating string buffer");
4803 return -1;
4804 }
4805
4807 vb->vb_strvalue = str;
4808 vb->vb_length = (size_t)len;
4809
4810 return 0;
4811}
4812
4813/** Alloc and assign an empty \0 terminated string to a #fr_value_box_t
4814 *
4815 * @param[in] ctx to allocate any new buffers in.
4816 * @param[out] out if non-null where to write a pointer to the new buffer.
4817 * @param[in] dst to assign new buffer to.
4818 * @param[in] enumv Aliases for values.
4819 * @param[in] len of buffer to allocate.
4820 * @param[in] tainted Whether the value came from a trusted source.
4821 * @return
4822 * - 0 on success.
4823 * - -1 on failure.
4824 */
4825int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4826 size_t len, bool tainted)
4827{
4828 char *str;
4829
4830 str = talloc_zero_array(ctx, char, len + 1);
4831 if (!str) {
4832 fr_strerror_const("Failed allocating string buffer");
4833 return -1;
4834 }
4835 str[len] = '\0';
4836
4837 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4838 dst->vb_strvalue = str;
4839 dst->vb_length = len;
4840
4841 if (out) *out = str;
4842
4843 return 0;
4844}
4845
4846/** Change the length of a buffer already allocated to a value box
4847 *
4848 * @note Do not use on an uninitialised box.
4849 *
4850 * @param[in] ctx to realloc buffer in.
4851 * @param[out] out if non-null where to write a pointer to the new buffer.
4852 * @param[in] dst to realloc buffer for.
4853 * @param[in] len to realloc to (don't include nul byte).
4854 * @return
4855 * - 0 on success.
4856 * - -1 on failure.
4857 */
4858int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
4859{
4860 size_t dstlen;
4861 char *str;
4862
4863 fr_assert(dst->type == FR_TYPE_STRING);
4864
4865 dstlen = talloc_strlen(dst->vb_strvalue);
4866 if (dstlen == len) return 0; /* No change */
4867
4868 str = talloc_realloc(ctx, UNCONST(char *, dst->vb_strvalue), char, len + 1);
4869 if (!str) {
4870 fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len + 1);
4871 return -1;
4872 }
4873
4874 /*
4875 * Zero out the additional bytes
4876 */
4877 if (dstlen < len) {
4878 memset(str + dstlen, '\0', (len - dstlen) + 1);
4879 } else {
4880 str[len] = '\0';
4881 }
4882 dst->vb_strvalue = str;
4883 dst->vb_length = len;
4884
4885 if (out) *out = str;
4886
4887 return 0;
4888}
4889
4890/** Copy a string to to a #fr_value_box_t
4891 *
4892 * @param[in] ctx to allocate any new buffers in.
4893 * @param[in] dst to assign buffer to.
4894 * @param[in] enumv Aliases for values.
4895 * @param[in] src a string. May be NULL only if len == 0.
4896 * @param[in] len of src.
4897 * @param[in] tainted Whether the value came from a trusted source.
4898 */
4899int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4900 char const *src, size_t len, bool tainted)
4901{
4902 char const *str;
4903
4904 if (unlikely((len > 0) && !src)) {
4905 fr_strerror_printf("Invalid arguments to %s. Len > 0 (%zu) but src string was NULL",
4906 __FUNCTION__, len);
4907 return -1;
4908 }
4909
4910 str = talloc_bstrndup(ctx, src, len);
4911 if (!str) {
4912 fr_strerror_const("Failed allocating string buffer");
4913 return -1;
4914 }
4915
4916 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4917 dst->vb_strvalue = str;
4918 dst->vb_length = len;
4919
4920 return 0;
4921}
4922
4923int fr_value_box_bstrndup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4924 fr_dbuff_t *dbuff, size_t len, bool tainted)
4925{
4926 char *str;
4927
4928 str = talloc_array(ctx, char, len + 1);
4929 if (!str) {
4930 fr_strerror_printf("Failed allocating string buffer");
4931 return -1;
4932 }
4933
4934 if (fr_dbuff_out_memcpy((uint8_t *)str, dbuff, len) < 0) {
4935 talloc_free(str);
4936 return -1;
4937 }
4938 str[len] = '\0';
4939
4940 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4941 dst->vb_strvalue = str;
4942 dst->vb_length = len;
4943
4944 return 0;
4945}
4946
4947/** Copy a nul terminated talloced buffer to a #fr_value_box_t
4948 *
4949 * Copy a talloced nul terminated buffer, setting fields in the dst value box appropriately.
4950 *
4951 * The buffer must be \0 terminated, or an error will be returned.
4952 *
4953 * @param[in] ctx to allocate any new buffers in.
4954 * @param[in] dst to assign new buffer to.
4955 * @param[in] enumv Aliases for values.
4956 * @param[in] src a talloced nul terminated buffer.
4957 * @param[in] tainted Whether the value came from a trusted source.
4958 * @return
4959 * - 0 on success.
4960 * - -1 on failure.
4961 */
4962int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4963 char const *src, bool tainted)
4964{
4965 size_t len;
4966
4967 (void)talloc_get_type_abort_const(src, char);
4968
4969 len = talloc_array_length(src);
4970 if ((len == 0) || (src[len - 1] != '\0')) {
4971 fr_strerror_const("Input buffer not \\0 terminated");
4972 return -1;
4973 }
4974
4975 return fr_value_box_bstrndup(ctx, dst, enumv, src, len - 1, tainted);
4976}
4977
4978/** Assign a string to to a #fr_value_box_t
4979 *
4980 * @param[in] dst to assign new buffer to.
4981 * @param[in] enumv Aliases for values.
4982 * @param[in] src a string.
4983 * @param[in] len of src.
4984 * @param[in] tainted Whether the value came from a trusted source.
4985 */
4987 char const *src, size_t len, bool tainted)
4988{
4989 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4990 dst->vb_strvalue = src;
4991 dst->vb_length = len;
4992}
4993
4994/** Assign a talloced buffer containing a nul terminated string to a box, but don't copy it
4995 *
4996 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4997 *
4998 * @param[in] ctx to add reference from. If NULL no reference will be added.
4999 * @param[in] dst to assign string to.
5000 * @param[in] enumv Aliases for values.
5001 * @param[in] src to copy string from.
5002 * @param[in] tainted Whether the value came from a trusted source.
5003 * @return
5004 * - 0 on success.
5005 * - -1 on failure.
5006 */
5008 char const *src, bool tainted)
5009{
5010 size_t len;
5011
5012 (void) talloc_get_type_abort_const(src, char);
5013
5014 len = talloc_array_length(src);
5015 if ((len == 0) || (src[len - 1] != '\0')) {
5016 fr_strerror_const("Input buffer not \\0 terminated");
5017 return -1;
5018 }
5019
5020 fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
5021 dst->vb_strvalue = ctx ? talloc_reference(ctx, src) : src;
5022 dst->vb_length = len - 1;
5023
5024 return 0;
5025}
5026
5027/** Pre-allocate an octets buffer for filling by the caller
5028 *
5029 * @note Buffer will not be zeroed, as it's assumed the caller will be filling it.
5030 *
5031 * @param[in] ctx to allocate any new buffers in.
5032 * @param[out] out If non-null will be filled with a pointer to the
5033 * new buffer.
5034 * @param[in] dst to assign new buffer to.
5035 * @param[in] enumv Aliases for values.
5036 * @param[in] len of data in the buffer. If 0, a zero length
5037 * talloc buffer will be alloced. dst->vb_octets
5038 * will *NOT* be NULL. You should use the length
5039 * field of the box to determine if any value
5040 * is assigned.
5041 * @param[in] tainted Whether the value came from a trusted source.
5042 * @return
5043 * - 0 on success.
5044 * - -1 on failure.
5045 */
5046int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
5047 size_t len, bool tainted)
5048{
5049 uint8_t *bin;
5050
5051 bin = talloc_array(ctx, uint8_t, len);
5052 if (!bin) {
5053 fr_strerror_const("Failed allocating octets buffer");
5054 return -1;
5055 }
5056 talloc_set_type(bin, uint8_t);
5057
5058 fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
5059 dst->vb_octets = bin;
5060 dst->vb_length = len;
5061
5062 if (out) *out = bin;
5063
5064 return 0;
5065}
5066
5067/** Change the length of a buffer already allocated to a value box
5068 *
5069 * @note Do not use on an uninitialised box.
5070 *
5071 * @param[in] ctx to realloc buffer in.
5072 * @param[out] out if non-null where to write a pointer to the new buffer.
5073 * @param[in] dst to realloc buffer for.
5074 * @param[in] len to realloc to.
5075 * @return
5076 * - 0 on success.
5077 * - -1 on failure.
5078 */
5079int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
5080{
5081 size_t dstlen;
5082 uint8_t *bin;
5083
5084 fr_assert(dst->type == FR_TYPE_OCTETS);
5085
5086 dstlen = talloc_array_length(dst->vb_octets);
5087 if (dstlen == len) return 0; /* No change */
5088
5089 /*
5090 * Realloc the buffer. If the new length is 0, we
5091 * need to call talloc_array() instead of talloc_realloc()
5092 * as talloc_realloc() will fail.
5093 */
5094 if (len > 0) {
5095 bin = talloc_realloc(ctx, UNCONST(uint8_t *, dst->vb_octets), uint8_t, len);
5096 } else {
5097 bin = talloc_array(ctx, uint8_t, 0);
5098 }
5099 if (!bin) {
5100 fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len);
5101 return -1;
5102 }
5103
5104 /*
5105 * Only free the original buffer once we've allocated
5106 * a new empty array.
5107 */
5108 if (len == 0) talloc_const_free(dst->vb_octets);
5109
5110 /*
5111 * Zero out the additional bytes
5112 */
5113 if (dstlen < len) memset(bin + dstlen, 0x00, len - dstlen);
5114 dst->vb_octets = bin;
5115 dst->vb_length = len;
5116
5117 if (out) *out = bin;
5118
5119 return 0;
5120}
5121
5122/** Copy a buffer to a fr_value_box_t
5123 *
5124 * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
5125 *
5126 * @param[in] ctx to allocate any new buffers in.
5127 * @param[in] dst to assign new buffer to.
5128 * @param[in] enumv Aliases for values.
5129 * @param[in] src a buffer.
5130 * @param[in] len of data in the buffer. If 0, a zero length
5131 * talloc buffer will be alloced. dst->vb_octets
5132 * will *NOT* be NULL. You should use the length
5133 * field of the box to determine if any value
5134 * is assigned.
5135 * @param[in] tainted Whether the value came from a trusted source.
5136 * @return
5137 * - 0 on success.
5138 * - -1 on failure.
5139 */
5140int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
5141 uint8_t const *src, size_t len, bool tainted)
5142{
5143 uint8_t *bin;
5144
5145 if (unlikely((len > 0) && !src)) {
5146 fr_strerror_printf("Invalid arguments to %s. Len > 0 (%zu) but src was NULL",
5147 __FUNCTION__, len);
5148 return -1;
5149 }
5150
5151 bin = talloc_memdup(ctx, src, len);
5152 if (!bin) {
5153 fr_strerror_const("Failed allocating octets buffer");
5154 return -1;
5155 }
5156 talloc_set_type(bin, uint8_t);
5157
5158 fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
5159 dst->vb_octets = bin;
5160 dst->vb_length = len;
5161
5162 return 0;
5163}
5164
5165int fr_value_box_memdup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
5166 fr_dbuff_t *dbuff, size_t len, bool tainted)
5167{
5168 uint8_t *bin;
5169
5170 bin = talloc_size(ctx, len);
5171 if (!bin) {
5172 fr_strerror_printf("Failed allocating octets buffer");
5173 return -1;
5174 }
5175
5176 if (fr_dbuff_out_memcpy(bin, dbuff, len) < (ssize_t) len) {
5177 talloc_free(bin);
5178 return -1;
5179 }
5180 talloc_set_type(bin, uint8_t);
5181
5182 fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
5183 dst->vb_octets = bin;
5184 dst->vb_length = len;
5185
5186 return 0;
5187}
5188
5189/** Copy a talloced buffer to a fr_value_box_t
5190 *
5191 * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
5192 *
5193 * @param[in] ctx to allocate any new buffers in.
5194 * @param[in] dst to assign new buffer to.
5195 * @param[in] enumv Aliases for values.
5196 * @param[in] src a buffer.
5197 * @param[in] tainted Whether the value came from a trusted source.
5198 * @return
5199 * - 0 on success.
5200 * - -1 on failure.
5201 */
5202int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
5203 uint8_t const *src, bool tainted)
5204{
5206
5207 return fr_value_box_memdup(ctx, dst, enumv, src, talloc_array_length(src), tainted);
5208}
5209
5210/** Assign a buffer to a box, but don't copy it
5211 *
5212 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
5213 *
5214 * Caller should set dst->taint = true, where the value was acquired from an untrusted source.
5215 *
5216 * @note Will free any exiting buffers associated with the value box.
5217 *
5218 * @param[in] dst to assign buffer to.
5219 * @param[in] enumv Aliases for values.
5220 * @param[in] src a talloced buffer.
5221 * @param[in] len of buffer.
5222 * @param[in] tainted Whether the value came from a trusted source.
5223 */
5225 uint8_t const *src, size_t len, bool tainted)
5226{
5227 fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
5228 dst->vb_octets = src;
5229 dst->vb_length = len;
5230}
5231
5232/** Assign a talloced buffer to a box, but don't copy it
5233 *
5234 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
5235 *
5236 * @param[in] ctx to allocate any new buffers in.
5237 * @param[in] dst to assign buffer to.
5238 * @param[in] enumv Aliases for values.
5239 * @param[in] src a talloced buffer.
5240 * @param[in] tainted Whether the value came from a trusted source.
5241 */
5243 uint8_t const *src, bool tainted)
5244{
5246
5247 fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
5248 dst->vb_octets = ctx ? talloc_reference(ctx, src) : src;
5249 dst->vb_length = talloc_array_length(src);
5250}
5251
5252/*
5253 * Assign a cursor to the data type.
5254 */
5256{
5258
5259 fr_value_box_init(dst, type, NULL, false);
5260 dst->vb_cursor = cursor;
5261 dst->vb_cursor_name = name;
5262}
5263
5264
5265/** Assign a void pointer to a box
5266 *
5267 * @param[in] dst to assign void pointer to.
5268 * @param[in] ptr to assign.
5269 */
5271{
5272 fr_value_box_init(dst, FR_TYPE_VOID, NULL, false);
5273 dst->vb_void = UNCONST(void *, ptr);
5274}
5275
5277{
5279
5280 /*
5281 * If the DA points to a root (e.g. OID-Tree), then use that.
5282 *
5283 * Otherwise if it doesn't have ENUMs defined, then point it at the dict root.
5284 *
5285 * If it does have enums, then the enumv is itself.
5286 */
5288 if (ext) {
5290 fr_assert(!da->flags.has_value);
5291
5292 return ext->ref;
5293 }
5294
5295 if (!da->flags.has_value) {
5296 return fr_dict_root(da->dict);
5297 }
5298
5299 return da;
5300}
5301
5303{
5304 fr_value_box_init(dst, FR_TYPE_ATTR, NULL, false);
5305 dst->vb_attr = da;
5306
5307 dst->enumv = fr_value_box_attr_enumv(da);
5308}
5309
5310/** Increment a boxed value
5311 *
5312 * Implements safe integer overflow.
5313 *
5314 * @param[in] vb to increment.
5315 */
5317{
5318 switch (vb->type) {
5319 case FR_TYPE_UINT8:
5320 vb->vb_uint8 = vb->vb_uint8 == UINT8_MAX ? 0 : vb->vb_uint8 + 1;
5321 return;
5322
5323 case FR_TYPE_UINT16:
5324 vb->vb_uint16 = vb->vb_uint16 == UINT16_MAX ? 0 : vb->vb_uint16 + 1;
5325 return;
5326
5327 case FR_TYPE_UINT32:
5328 vb->vb_uint32 = vb->vb_uint32 == UINT32_MAX ? 0 : vb->vb_uint32 + 1;
5329 return;
5330
5331 case FR_TYPE_UINT64:
5332 vb->vb_uint64 = vb->vb_uint64 == UINT64_MAX ? 0 : vb->vb_uint64 + 1;
5333 return;
5334
5335 case FR_TYPE_INT8:
5336 vb->vb_int8 = vb->vb_int8 == INT8_MAX ? INT8_MIN : vb->vb_int8 + 1;
5337 return;
5338
5339 case FR_TYPE_INT16:
5340 vb->vb_int16 = vb->vb_int16 == INT16_MAX ? INT16_MIN : vb->vb_int16 + 1;
5341 return;
5342
5343 case FR_TYPE_INT32:
5344 vb->vb_int32 = vb->vb_int32 == INT32_MAX ? INT32_MIN : vb->vb_int32 + 1;
5345 return;
5346
5347 case FR_TYPE_INT64:
5348 vb->vb_int64 = vb->vb_int64 == INT64_MAX ? INT64_MIN : vb->vb_int64 + 1;
5349 return;
5350
5351 default:
5352 fr_assert_fail(NULL);
5353 return;
5354 }
5355}
5356
5357/** Convert integer encoded as string to a fr_value_box_t type
5358 *
5359 * @param[out] dst where to write parsed value.
5360 * @param[in] dst_type type of integer to convert string to.
5361 * @param[in] dst_enumv Enumeration values.
5362 * @param[in] in String to convert to integer.
5363 * @param[in] rules for parsing string.
5364 * @param[in] tainted Whether the value came from a trusted source.
5365 * @return
5366 * - >= 0 on success (number of bytes parsed).
5367 * - < 0 on error (where the parse error occurred).
5368 */
5369static inline CC_HINT(always_inline)
5371 fr_dict_attr_t const *dst_enumv,
5372 fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules, bool tainted)
5373{
5374 fr_sbuff_t our_in = FR_SBUFF(in);
5376
5377 fr_value_box_init(dst, dst_type, dst_enumv, tainted);
5378
5379 switch (dst_type) {
5380 case FR_TYPE_UINT8:
5381 err = fr_sbuff_out(&dst->vb_uint8, &our_in);
5382 break;
5383
5384 case FR_TYPE_UINT16:
5385 err = fr_sbuff_out(&dst->vb_uint16, &our_in);
5386 break;
5387
5388 case FR_TYPE_UINT32:
5389 err = fr_sbuff_out(&dst->vb_uint32, &our_in);
5390 break;
5391
5392 case FR_TYPE_UINT64:
5393 err = fr_sbuff_out(&dst->vb_uint64, &our_in);
5394 break;
5395
5396 case FR_TYPE_INT8:
5397 err = fr_sbuff_out(&dst->vb_int8, &our_in);
5398 break;
5399
5400 case FR_TYPE_INT16:
5401 err = fr_sbuff_out(&dst->vb_int16, &our_in);
5402 break;
5403
5404 case FR_TYPE_INT32:
5405 err = fr_sbuff_out(&dst->vb_int32, &our_in);
5406 break;
5407
5408 case FR_TYPE_INT64:
5409 err = fr_sbuff_out(&dst->vb_int64, &our_in);
5410 break;
5411
5412 case FR_TYPE_SIZE:
5413 err = fr_sbuff_out(&dst->vb_size, &our_in);
5414 break;
5415
5416 case FR_TYPE_FLOAT32:
5417 err = fr_sbuff_out(&dst->vb_float32, &our_in);
5418 break;
5419
5420 case FR_TYPE_FLOAT64:
5421 err = fr_sbuff_out(&dst->vb_float64, &our_in);
5422 break;
5423
5424 default:
5425 fr_assert_fail(NULL);
5426 return -1;
5427 }
5428
5429 if (err < 0) {
5430 /*
5431 * If an enumeration attribute is provided and we
5432 * don't find an integer, assume this is an enumv
5433 * lookup fail, and produce a better error.
5434 */
5435 if (dst_enumv && dst_enumv->flags.has_value && (err == FR_SBUFF_ERR_NOT_FOUND)) {
5436 fr_sbuff_adv_until(&our_in, SIZE_MAX, rules->terminals,
5437 rules->escapes ? rules->escapes->chr : '\0');
5438
5439 fr_strerror_printf("Invalid enumeration value \"%pV\" for attribute %s",
5441 dst_enumv->name);
5442 return -1;
5443 }
5444
5445 if (err == FR_SBUFF_ERR_NOT_FOUND) {
5446 fr_strerror_printf("Failed parsing string as type '%s'",
5447 fr_type_to_str(dst_type));
5448 } else {
5449 fr_sbuff_err_to_strerror(err);
5450 }
5451 FR_SBUFF_ERROR_RETURN(&our_in);
5452 }
5453
5454 FR_SBUFF_SET_RETURN(in, &our_in);
5455}
5456
5457/** Convert string value to a fr_value_box_t type
5458 *
5459 * @param[in] ctx to alloc strings in.
5460 * @param[out] dst where to write parsed value.
5461 * @param[in,out] dst_type of value data to create/dst_type of value created.
5462 * @param[in] dst_enumv fr_dict_attr_t with string names for uint32 values.
5463 * @param[in] in sbuff to read data from.
5464 * @param[in] rules unescape and termination rules.
5465 * @return
5466 * - >0 on success.
5467 * - <= 0 on parse error.
5468 */
5470 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
5471 fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules)
5472{
5473 static fr_sbuff_parse_rules_t default_rules;
5474 fr_sbuff_t *unescaped = NULL;
5475 fr_sbuff_t our_in = FR_SBUFF(in);
5476 fr_ipaddr_t addr;
5477 fr_slen_t slen;
5478 char buffer[256];
5479
5480 if (!rules) rules = &default_rules;
5481
5483 fr_value_box_init(dst, dst_type, NULL, false);
5484
5485 /*
5486 * Lookup any names before continuing
5487 */
5488 if (dst_enumv && dst_enumv->flags.has_value && (dst_type != FR_TYPE_ATTR)) {
5489 size_t name_len;
5490 fr_dict_enum_value_t const *enumv;
5491
5492 /*
5493 * @todo - allow enum names for IPv6 addresses and prefixes. See also
5494 * tmpl_afrom_enum().
5495 */
5496 (void) fr_sbuff_adv_past_str_literal(&our_in, "::");
5497
5498 /*
5499 * If there is no escaping, then we ignore the terminals. The list of allowed characters
5500 * in enum names will ensure that the parsing doesn't go too far. i.e. to '\r', '\n'. '}', etc.
5501 *
5502 * The reason is that the list of terminals may include things like '-', which is also a
5503 * valid character in enum names. We don't want to parse "Framed-User" as "Framed - User".
5504 */
5505 if (!rules->escapes) {
5506 size_t len;
5508
5509 fr_sbuff_marker(&m, &our_in);
5510
5513 fr_sbuff_set(&our_in, &m);
5514 fr_sbuff_marker_release(&m);
5515
5516 if (!len) goto parse; /* Zero length name can't match enum */
5517
5518 enumv = fr_dict_enum_by_name(dst_enumv, fr_sbuff_current(&our_in), len);
5519 if (!enumv) {
5520 goto parse; /* No enumeration matches escaped string */
5521 }
5522
5523 (void) fr_sbuff_advance(&our_in, len);
5524 goto cast_enum;
5525 }
5526
5527 /*
5528 * Create a thread-local extensible buffer to
5529 * store unescaped data.
5530 *
5531 * This is created once per-thread (the first time
5532 * this function is called), and freed when the
5533 * thread exits.
5534 */
5535 FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096);
5536
5537 /*
5538 * This function only does escaping until a terminal character, such as '-'. So
5539 * Framed-User will get parsed as "Framed - User".
5540 *
5541 * Pretty much no other enum has this problem. For Service-Type, it defines "Framed" ss
5542 * an equivalent name to "Framed-User". The parser sees "Framed-User", stops at the '-',
5543 * and then finds the enum named "Framed". It then returns the trailing "-User" as
5544 * something more to parse.
5545 *
5546 * As a result, when the user passes in "Framed-User", the output is "Framed-User -
5547 * User", which is more than a bit surprising.
5548 */
5549 if (fr_sbuff_out_unescape_until(&name_len, unescaped, &our_in, SIZE_MAX,
5550 rules->terminals, rules->escapes) < 0) {
5551 fr_strerror_const("Failed reading enumeration name");
5552 FR_SBUFF_ERROR_RETURN(&our_in);
5553 }
5554 if (!name_len) {
5555 fr_sbuff_set_to_start(&our_in);
5556 goto parse; /* Zero length name can't match enum */
5557 }
5558
5559 enumv = fr_dict_enum_by_name(dst_enumv, fr_sbuff_start(unescaped), fr_sbuff_used(unescaped));
5560 if (!enumv) {
5561 fr_sbuff_set_to_start(&our_in);
5562 goto parse; /* No enumeration matches escaped string */
5563 }
5564
5565 cast_enum:
5566 /*
5567 * dst_type may not match enumv type
5568 */
5569 if (fr_value_box_cast(ctx, dst, dst_type, dst_enumv, enumv->value) < 0) return -1;
5570
5571 FR_SBUFF_SET_RETURN(in, &our_in);
5572 }
5573
5574parse:
5575 /*
5576 * It's a variable ret src->dst_type so we just alloc a new buffer
5577 * of size len and copy.
5578 */
5579 switch (dst_type) {
5580 case FR_TYPE_STRING:
5581 /*
5582 * We've not unescaped the string yet, produce an unescaped version
5583 */
5584 if (!dst_enumv || !unescaped) {
5585 char *buff;
5586
5587 if (unlikely(fr_sbuff_out_aunescape_until(ctx, &buff, NULL, &our_in, SIZE_MAX,
5588 rules->terminals, rules->escapes) < 0)) {
5589 return -1;
5590 }
5591 fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, buff, false);
5592 /*
5593 * We already have an unescaped version, just use that
5594 */
5595 } else {
5596 fr_value_box_bstrndup(ctx, dst, dst_enumv,
5597 fr_sbuff_start(unescaped), fr_sbuff_used(unescaped), false);
5598 }
5599 FR_SBUFF_SET_RETURN(in, &our_in);
5600
5601 /* raw octets: 0x01020304... */
5602 case FR_TYPE_OCTETS:
5603 {
5604 fr_sbuff_marker_t hex_start;
5605 size_t hex_len;
5606 uint8_t *bin_buff;
5607
5608 /*
5609 * If there's escape sequences that need to be processed
5610 * or the string doesn't start with 0x, then assume this
5611 * is literal data, not hex encoded data.
5612 */
5613 if (rules->escapes || !fr_sbuff_adv_past_strcase_literal(&our_in, "0x")) {
5614 if (!dst_enumv || !unescaped) {
5615 char *buff = NULL;
5616 uint8_t *bin;
5617 size_t len;
5618
5619 if (fr_sbuff_extend(&our_in)) {
5620 if (fr_sbuff_out_aunescape_until(ctx, &buff, &len, &our_in, SIZE_MAX,
5621 rules->terminals, rules->escapes) < 0) {
5622 return -1;
5623 }
5624
5625 if (len == 0) {
5627 goto zero;
5628 }
5629
5630 /*
5631 * Trim off the trailing '\0', and change the data type.
5632 */
5634 if (unlikely(!bin)) {
5635 fr_strerror_const("Failed trimming string buffer");
5637 return -1;
5638 }
5639
5640 /*
5641 * Input data is zero
5642 *
5643 * talloc realloc will refuse to realloc to
5644 * a zero length buffer. This is probably
5645 * a bug, because we can create zero length
5646 * arrays normally
5647 */
5648 } else {
5649 zero:
5650 bin = talloc_zero_array(ctx, uint8_t, 0);
5651 }
5652
5653 fr_value_box_memdup_buffer_shallow(NULL, dst, dst_enumv, bin, false);
5654 /*
5655 * We already have an unescaped version, just use that
5656 */
5657 } else {
5658 fr_value_box_memdup(ctx, dst, dst_enumv,
5659 (uint8_t *)fr_sbuff_start(unescaped),
5660 fr_sbuff_used(unescaped), false);
5661 }
5662 FR_SBUFF_SET_RETURN(in, &our_in);
5663 }
5664
5665 fr_sbuff_marker(&hex_start, &our_in); /* Record where the hexits start */
5666
5667 /*
5668 * Find the end of the hex sequence.
5669 *
5670 * We don't technically need to do this, fr_base16_decode
5671 * will find the end on its own.
5672 *
5673 * We do this so we can alloc the correct sized
5674 * output buffer.
5675 */
5676 hex_len = fr_sbuff_adv_past_allowed(&our_in, SIZE_MAX, sbuff_char_class_hex, rules->terminals);
5677 if (hex_len == 0) {
5678 if (fr_value_box_memdup(ctx, dst, dst_enumv, (uint8_t[]){ 0x00 }, 0, false) < 0) return -1;
5679 FR_SBUFF_SET_RETURN(in, &our_in);
5680 }
5681
5682 if ((hex_len & 0x01) != 0) {
5683 fr_strerror_printf("Length of hex string is not even, got %zu bytes", hex_len);
5684 FR_SBUFF_ERROR_RETURN(&our_in);
5685 }
5686
5687 /*
5688 * Pre-allocate the bin buff and initialise the box
5689 */
5690 if (fr_value_box_mem_alloc(ctx, &bin_buff, dst, dst_enumv, (hex_len >> 1), false) < 0) return -1;
5691
5692 /*
5693 * Reset to the start of the hex string
5694 */
5695 fr_sbuff_set(&our_in, &hex_start);
5696
5697 if (unlikely(fr_base16_decode(NULL, &FR_DBUFF_TMP(bin_buff, hex_len), &our_in, false) < 0)) {
5698 talloc_free(bin_buff);
5699 FR_SBUFF_ERROR_RETURN(&our_in);
5700 }
5701
5702 FR_SBUFF_SET_RETURN(in, &our_in);
5703 }
5704
5705 case FR_TYPE_IPV4_ADDR:
5706 {
5707 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5708 if (!name_len) goto empty_is_invalid;
5709
5710 if (fr_inet_pton4(&addr, fr_sbuff_current(in), name_len,
5711 fr_hostname_lookups, false, true) < 0) return -1;
5712
5713 /*
5714 * We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
5715 * print them this way.
5716 */
5717 if (addr.prefix != 32) {
5718 fail_ipv4_prefix:
5719 fr_strerror_printf("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted "
5720 "for non-prefix types", addr.prefix);
5721 return -1;
5722 }
5723
5724 memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5725 }
5726 goto finish;
5727
5729 {
5730 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5731 if (!name_len) goto empty_is_invalid;
5732
5733 if (fr_inet_pton4(&dst->vb_ip, fr_sbuff_current(in), name_len,
5734 fr_hostname_lookups, false, true) < 0) return -1;
5735 }
5736 goto finish;
5737
5738 case FR_TYPE_IPV6_ADDR:
5739 {
5740 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5741 if (!name_len) goto empty_is_invalid;
5742
5743 /*
5744 * Parse scope, too.
5745 */
5746 if (fr_sbuff_next_if_char(&our_in, '%')) {
5747 name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5748 }
5749
5750 if (fr_inet_pton6(&addr, fr_sbuff_current(in), name_len,
5751 fr_hostname_lookups, false, true) < 0) return -1;
5752
5753 /*
5754 * We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
5755 * print them this way.
5756 */
5757 if (addr.prefix != 128) {
5758 fail_ipv6_prefix:
5759 fr_strerror_printf("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted "
5760 "for non-prefix types", addr.prefix);
5761 return -1;
5762 }
5763
5764 memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5765 }
5766 goto finish;
5767
5769 {
5770 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5771 if (!name_len) goto empty_is_invalid;
5772
5773 if (fr_inet_pton6(&dst->vb_ip, fr_sbuff_current(in), name_len,
5774 fr_hostname_lookups, false, true) < 0) return -1;
5775 }
5776 goto finish;
5777
5779 {
5780 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5781 if (!name_len) goto empty_is_invalid;
5782
5783 /*
5784 * Parse scope, too.
5785 */
5786 if (fr_sbuff_next_if_char(&our_in, '%')) {
5787 name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5788 }
5789
5790 if (fr_inet_pton(&addr, fr_sbuff_current(in), name_len, AF_UNSPEC,
5791 fr_hostname_lookups, true) < 0) return -1;
5792
5793 if ((addr.af == AF_INET) && (addr.prefix != 32)) {
5794 goto fail_ipv4_prefix;
5795 }
5796
5797 if ((addr.af == AF_INET6) && (addr.prefix != 128)) {
5798 goto fail_ipv6_prefix;
5799 }
5800
5801 memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5802 }
5803 goto finish;
5804
5806 {
5807 size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5808 if (!name_len) goto empty_is_invalid;
5809
5810 if (fr_inet_pton(&dst->vb_ip, fr_sbuff_current(in), name_len, AF_UNSPEC,
5811 fr_hostname_lookups, true) < 0) return -1;
5812 }
5813 goto finish;
5814
5815 case FR_TYPE_UINT8:
5816 case FR_TYPE_UINT16:
5817 case FR_TYPE_UINT32:
5818 case FR_TYPE_UINT64:
5819 case FR_TYPE_INT8:
5820 case FR_TYPE_INT16:
5821 case FR_TYPE_INT32:
5822 case FR_TYPE_INT64:
5823 case FR_TYPE_FLOAT32:
5824 case FR_TYPE_FLOAT64:
5825 return fr_value_box_from_numeric_substr(dst, dst_type, dst_enumv, in, rules, false);
5826
5827 case FR_TYPE_SIZE:
5828 if (fr_size_from_str(&dst->datum.size, &our_in) < 0) return -1;
5829 goto finish;
5830
5831 case FR_TYPE_BOOL:
5832 {
5833 fr_sbuff_t bool_in = FR_SBUFF(in);
5834
5835 fr_value_box_init(dst, dst_type, dst_enumv, false);
5836
5837 /*
5838 * Quoted boolean values are "yes", "no", "true", "false"
5839 */
5840 if (fr_sbuff_out(&dst->vb_bool, &bool_in) >= 0) FR_SBUFF_SET_RETURN(in, &bool_in);
5841
5842 /*
5843 * For barewords we also allow 0 for false and any other
5844 * integer value for true.
5845 */
5846 if (!rules->escapes) {
5847 int64_t stmp;
5848 uint64_t utmp;
5849
5850 if (fr_sbuff_out(&stmp, &bool_in) >= 0) {
5851 dst->vb_bool = (stmp != 0);
5852 FR_SBUFF_SET_RETURN(in, &bool_in);
5853 }
5854
5855 if (fr_sbuff_out(&utmp, &bool_in) >= 0) {
5856 dst->vb_bool = (utmp != 0);
5857 FR_SBUFF_SET_RETURN(in, &bool_in);
5858 }
5859 }
5860
5861 fr_strerror_const("Invalid boolean value. Accepted values are "
5862 "\"yes\", \"no\", \"true\", \"false\" or any unquoted integer");
5863
5864 FR_SBUFF_ERROR_RETURN(&bool_in);
5865 }
5866
5867 case FR_TYPE_ETHERNET:
5868 {
5869 uint64_t num;
5870 fr_ethernet_t ether;
5871 fr_dbuff_t dbuff;
5873
5874 fr_dbuff_init(&dbuff, ether.addr, sizeof(ether.addr));
5875
5876 /*
5877 * Convert things which are obviously integers to Ethernet addresses
5878 *
5879 * We assume the number is the decimal
5880 * representation of the ethernet address.
5881 * i.e. the ethernet address converted to a
5882 * number, and printed.
5883 *
5884 * The string gets converted to a network-order
5885 * 8-byte number, and then the lower bytes of
5886 * that get copied to the ethernet address.
5887 *
5888 * Note: We need to check for a terminal sequence
5889 * after the number, else we may just end up
5890 * parsing the first hexit and returning.
5891 *
5892 * i.e. 1c:00:00:00:00 -> 1
5893 */
5894 if ((fr_sbuff_out(&num, &our_in) >= 0) && fr_sbuff_is_terminal(&our_in, rules->terminals)) {
5895 num = htonll(num);
5896
5897 FR_DBUFF_IN_MEMCPY_RETURN(&dbuff, ((uint8_t *) &num) + 2, sizeof(dst->vb_ether));
5898 fr_value_box_ethernet_addr(dst, dst_enumv, &ether, false);
5899
5900 FR_SBUFF_SET_RETURN(in, &our_in);
5901 }
5902
5903 fr_sbuff_set_to_start(&our_in);
5904
5905 fr_base16_decode(&err, &dbuff, &our_in, true);
5906 if (err != FR_SBUFF_OK) {
5907 ether_error:
5908 fr_sbuff_err_to_strerror(err);
5909 FR_SBUFF_ERROR_RETURN(&our_in);
5910 }
5911
5912 if (!fr_sbuff_next_if_char(&our_in, ':')) {
5913 ether_sep_error:
5914 fr_strerror_const("Missing separator, expected ':'");
5915 FR_SBUFF_ERROR_RETURN(&our_in);
5916 }
5917
5918 fr_base16_decode(&err, &dbuff, &our_in, true);
5919 if (err != FR_SBUFF_OK) goto ether_error;
5920
5921 if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5922
5923 fr_base16_decode(&err, &dbuff, &our_in, true);
5924 if (err != FR_SBUFF_OK) goto ether_error;
5925
5926 if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5927
5928 fr_base16_decode(&err, &dbuff, &our_in, true);
5929 if (err != FR_SBUFF_OK) goto ether_error;
5930
5931 if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5932
5933 fr_base16_decode(&err, &dbuff, &our_in, true);
5934 if (err != FR_SBUFF_OK) goto ether_error;
5935
5936 if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5937
5938 fr_base16_decode(&err, &dbuff, &our_in, true);
5939 if (err != FR_SBUFF_OK) goto ether_error;
5940
5941 fr_value_box_ethernet_addr(dst, dst_enumv, (fr_ethernet_t * const)fr_dbuff_start(&dbuff), false);
5942
5943 FR_SBUFF_SET_RETURN(in, &our_in);
5944 }
5945
5946 case FR_TYPE_TIME_DELTA:
5947 fr_value_box_init(dst, FR_TYPE_TIME_DELTA, dst_enumv, false);
5948
5949 slen = fr_time_delta_from_substr(&dst->datum.time_delta, &our_in,
5950 dst_enumv ? dst_enumv->flags.flag_time_res : FR_TIME_RES_SEC,
5951 false, rules->terminals);
5952 if (slen < 0) return slen;
5953 if (!slen) {
5954 empty_is_invalid:
5955 fr_strerror_const("Empty input is invalid");
5956 return -1;
5957 }
5958 FR_SBUFF_SET_RETURN(in, &our_in);
5959
5960 case FR_TYPE_NULL:
5961 if (!rules->escapes && fr_sbuff_adv_past_str_literal(&our_in, "NULL")) {
5962 fr_value_box_init(dst, dst_type, dst_enumv, false);
5963 FR_SBUFF_SET_RETURN(in, &our_in);
5964 }
5965
5966 fr_strerror_const("Unexpected value for data type NULL");
5967 return -1;
5968
5969 case FR_TYPE_ATTR:
5970 if (!dst_enumv) {
5971 fr_strerror_const("No dictionary passed for data type 'attr'");
5972 return -1;
5973 }
5974
5975 /*
5976 * @todo - have attributes of FR_TYPE_ATTR also
5977 * carry a ref to where their values are taken from.
5978 */
5979 if (dst_enumv->type == FR_TYPE_ATTR) {
5980 dst_enumv = fr_value_box_attr_enumv(dst_enumv);
5981
5982 } else if (dst_enumv->type != FR_TYPE_TLV) {
5983 fr_strerror_printf("Can only start from data type 'tlv' for data type 'attribute', and not from %s", dst_enumv->name);
5984 return -1;
5985 }
5986
5987 fr_value_box_init(dst, dst_type, dst_enumv, false);
5988
5989 (void) fr_sbuff_adv_past_str_literal(&our_in, "::");
5990
5991 /*
5992 * Allow '@' references in values.
5993 */
5994 if (fr_sbuff_is_char(&our_in, '@')) {
5995 size_t len;
5997
5998 fr_sbuff_marker(&m, &our_in);
5999 fr_sbuff_advance(&our_in, 1); /* '@' is not an allowed character for dictionary names */
6000
6003 fr_sbuff_set(&our_in, &m);
6004 fr_sbuff_marker_release(&m);
6005
6006 len++; /* account for '@' */
6007
6008 /*
6009 * This function needs the '@'.
6010 */
6011 if (fr_dict_protocol_reference(&dst->vb_attr, fr_dict_root(dst_enumv->dict), &FR_SBUFF_IN(fr_sbuff_current(&our_in), len)) < 0) {
6012 return -1;
6013 }
6014
6015 if (!dst->vb_attr) {
6016 fr_strerror_printf("Failed to find attribute reference %.*s", (int) len, fr_sbuff_current(&our_in));
6017 return -1;
6018 }
6019
6020 fr_assert(dst->vb_attr != NULL);
6021
6022 if (dst->vb_attr->dict != dst_enumv->dict) {
6023 fr_strerror_const("Type 'attribute' cannot reference a different protocol");
6024 return -1;
6025 }
6026
6027 fr_sbuff_advance(&our_in, len);
6028 FR_SBUFF_SET_RETURN(in, &our_in);
6029
6030 } else {
6031 fr_dict_attr_t const *da;
6032
6033 fr_assert(dst_enumv != NULL);
6034
6035 slen = fr_dict_attr_by_oid_substr(NULL, &dst->vb_attr, dst_enumv, &our_in, rules->terminals);
6036 if (slen > 0) {
6037 fr_assert(dst->vb_attr != NULL);
6038
6039 if (!fr_sbuff_next_if_char(&our_in, '.')) {
6040 FR_SBUFF_SET_RETURN(in, &our_in);
6041 }
6042
6043 /*
6044 * The next bit MUST be an unknown attribute.
6045 */
6046 }
6047
6048 if (!fr_sbuff_is_digit(&our_in)) {
6049 invalid_attr:
6050 fr_strerror_printf_push("Failed to find the attribute in %s", dst_enumv->name);
6051 return -2;
6052 }
6053
6054 slen = fr_dict_attr_unknown_afrom_oid_substr(ctx, &da, dst->vb_attr, &our_in, FR_TYPE_OCTETS);
6055 if (slen <= 0) goto invalid_attr;
6056
6057 dst->vb_attr = da;
6058 FR_SBUFF_SET_RETURN(in, &our_in);
6059 }
6060
6061 /*
6062 * Dealt with below
6063 */
6064 default:
6065 break;
6066 }
6067
6068 /*
6069 * We may have terminals. If so, respect them.
6070 */
6071 if (rules && rules->terminals) {
6072 size_t len;
6073 fr_sbuff_err_t sberr;
6074
6075 sberr = fr_sbuff_out_unescape_until(&len, &FR_SBUFF_OUT(buffer, sizeof(buffer)), &our_in, SIZE_MAX,
6076 rules->terminals, rules->escapes);
6077 if (sberr < 0) {
6078 fr_strerror_printf("Failed reading value: %s", fr_sbuff_err_to_str(sberr));
6079 return -1;
6080 }
6081
6082 buffer[len] = '\0';
6083
6084 } else {
6085 /*
6086 * It's a fixed size src->dst_type, copy to a temporary buffer and
6087 * \0 terminate.
6088 *
6089 * @todo - note that this brute-force copy means that the input sbuff
6090 * is NOT advanced, and this function will return 0, even though it parsed data!
6091 */
6092 if (fr_sbuff_remaining(in) >= sizeof(buffer)) {
6093 fr_strerror_const("Temporary buffer too small");
6094 return -1;
6095 }
6096
6098 buffer[fr_sbuff_remaining(in)] = '\0';
6099 }
6100
6101 switch (dst_type) {
6102 case FR_TYPE_DATE:
6103 {
6104 if (dst_enumv) {
6105 if (fr_unix_time_from_str(&dst->vb_date, buffer, dst_enumv->flags.flag_time_res) < 0) return -1;
6106 } else {
6107 if (fr_unix_time_from_str(&dst->vb_date, buffer, FR_TIME_RES_SEC) < 0) return -1;
6108 }
6109
6110 dst->enumv = dst_enumv;
6111 }
6112 break;
6113
6114 case FR_TYPE_IFID:
6115 if (fr_inet_ifid_pton((void *) dst->vb_ifid, buffer) == NULL) {
6116 fr_strerror_printf("Failed to parse interface-id string \"%s\"", buffer);
6117 return -1;
6118 }
6119 break;
6120
6121 default:
6122 fr_strerror_printf("Cannot parse input as data type %s", fr_type_to_str(dst_type));
6123 return -1;
6124 }
6125
6126finish:
6127 dst->type = dst_type;
6128 dst->tainted = false;
6130
6131 /*
6132 * Fixup enumvs
6133 */
6134 dst->enumv = dst_enumv;
6135 fr_value_box_list_entry_init(dst);
6136 VALUE_BOX_VERIFY(dst);
6137
6138 FR_SBUFF_SET_RETURN(in, &our_in);
6139}
6140
6142 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
6143 char const *in, size_t inlen,
6144 fr_sbuff_unescape_rules_t const *erules)
6145{
6146 fr_slen_t slen;
6147 fr_sbuff_parse_rules_t prules = { .escapes = erules };
6148
6149 slen = fr_value_box_from_substr(ctx, dst, dst_type, dst_enumv, &FR_SBUFF_IN(in, inlen), &prules);
6150 if (slen <= 0) return slen;
6151
6152 if (slen != (ssize_t)inlen) {
6153 fr_strerror_printf("Failed parsing '%s'. %zu bytes of trailing data after string value \"%pV\"",
6154 fr_type_to_str(dst_type),
6155 inlen - slen,
6156 fr_box_strvalue_len(in + slen, inlen - slen));
6157 return (slen - inlen) - 1;
6158 }
6159
6160 return slen;
6161}
6162
6163/** Print one boxed value to a string
6164 *
6165 * This function should primarily be used when a #fr_value_box_t is being
6166 * serialized in some non-standard way, i.e. as a value for a field
6167 * in a database, in all other instances it's better to use
6168 * #fr_value_box_print_quoted.
6169 *
6170 * @note - this function does NOT respect tainting! The escaping rules
6171 * are ONLY for escaping quotation characters, CR, LF, etc.
6172 *
6173 * @param[in] out Where to write the printed string.
6174 * @param[in] data Value box to print.
6175 * @param[in] e_rules To apply to FR_TYPE_STRING types, for escaping quotation characters _only_.
6176 * Is not currently applied to any other box type.
6177 */
6179{
6180 fr_sbuff_t our_out = FR_SBUFF(out);
6181
6182 char buf[1024]; /* Interim buffer to use with poorly behaved printing functions */
6183
6184 if (data->enumv && data->enumv->flags.has_value) {
6185 char const *name;
6186
6188 if (name) {
6189 FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(&our_out, name, NULL);
6190 goto done;
6191 }
6192 }
6193
6194 switch (data->type) {
6195 case FR_TYPE_STRING:
6196 if (data->vb_length) FR_SBUFF_IN_ESCAPE_RETURN(&our_out,
6197 data->vb_strvalue, data->vb_length, e_rules);
6198 break;
6199
6200 case FR_TYPE_OCTETS:
6201 FR_SBUFF_IN_CHAR_RETURN(&our_out, '0', 'x');
6202 if (data->vb_length) FR_SBUFF_RETURN(fr_base16_encode, &our_out,
6203 &FR_DBUFF_TMP(data->vb_octets, data->vb_length));
6204 break;
6205
6206 /*
6207 * We need to use the proper inet_ntop functions for IP
6208 * addresses, else the output might not match output of
6209 * other functions, which makes testing difficult.
6210 *
6211 * An example is tunneled ipv4 in ipv6 addresses.
6212 */
6213 case FR_TYPE_IPV4_ADDR:
6214 case FR_TYPE_IPV6_ADDR:
6216 if (!fr_inet_ntop(buf, sizeof(buf), &data->vb_ip)) return 0;
6217 FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
6218 break;
6219
6223 if (!fr_inet_ntop_prefix(buf, sizeof(buf), &data->vb_ip)) return 0;
6224 FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
6225 break;
6226
6227 case FR_TYPE_IFID:
6228 if (!fr_inet_ifid_ntop(buf, sizeof(buf), data->vb_ifid)) return 0;
6229 FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
6230 break;
6231
6232 case FR_TYPE_ETHERNET:
6233 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%02x:%02x:%02x:%02x:%02x:%02x",
6234 data->vb_ether[0], data->vb_ether[1],
6235 data->vb_ether[2], data->vb_ether[3],
6236 data->vb_ether[4], data->vb_ether[5]);
6237 break;
6238
6239 case FR_TYPE_BOOL:
6240 FR_SBUFF_IN_STRCPY_RETURN(&our_out, data->vb_uint8 ? "yes" : "no");
6241 break;
6242
6243 case FR_TYPE_UINT8:
6244 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint8);
6245 break;
6246
6247 case FR_TYPE_UINT16:
6248 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint16);
6249 break;
6250
6251 case FR_TYPE_UINT32:
6252 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint32);
6253 break;
6254
6255 case FR_TYPE_UINT64:
6256 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRIu64, data->vb_uint64);
6257 break;
6258
6259 case FR_TYPE_INT8:
6260 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int8);
6261 break;
6262
6263 case FR_TYPE_INT16:
6264 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int16);
6265 break;
6266
6267 case FR_TYPE_INT32:
6268 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int32);
6269 break;
6270
6271 case FR_TYPE_INT64:
6272 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRId64, data->vb_int64);
6273 break;
6274
6275 case FR_TYPE_FLOAT32:
6276 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%f", (double) data->vb_float32);
6277 break;
6278
6279 case FR_TYPE_FLOAT64:
6280 FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%g", data->vb_float64);
6281 break;
6282
6283 case FR_TYPE_DATE:
6284 {
6286
6287 if (data->enumv) res = data->enumv->flags.flag_time_res;
6288
6289 FR_SBUFF_RETURN(fr_unix_time_to_str, &our_out, data->vb_date, res, true);
6290 break;
6291 }
6292
6293 case FR_TYPE_SIZE:
6294 FR_SBUFF_RETURN(fr_size_to_str, &our_out, data->datum.size);
6295 break;
6296
6297 case FR_TYPE_TIME_DELTA:
6298 {
6300 bool is_unsigned = false;
6301
6302 if (data->enumv) {
6303 res = data->enumv->flags.flag_time_res;
6304 is_unsigned = data->enumv->flags.is_unsigned;
6305 }
6306
6307
6308 FR_SBUFF_RETURN(fr_time_delta_to_str, &our_out, data->vb_time_delta, res, is_unsigned);
6309 }
6310 break;
6311
6312 case FR_TYPE_GROUP:
6313 /*
6314 * If the caller didn't ask to escape binary data
6315 * in 'octets' types, then we force that now.
6316 * Otherwise any 'octets' type which is buried
6317 * inside of a 'group' will get copied verbatim
6318 * from input to output, with no escaping!
6319 */
6320 if (!e_rules || (!e_rules->do_oct && !e_rules->do_hex)) {
6321 e_rules = &fr_value_escape_double;
6322 }
6323
6324 /*
6325 * Represent groups as:
6326 *
6327 * { <value0>, <value1>, { <sub-value0>, <sub-value1>, <sub-valueN> }}
6328 */
6329 FR_SBUFF_IN_CHAR_RETURN(&our_out, '{');
6331 NULL, &our_out, UNCONST(fr_value_box_list_t *, &data->vb_group),
6332 ", ", (sizeof(", ") - 1), e_rules,
6334 FR_SBUFF_IN_CHAR_RETURN(&our_out, '}');
6335 break;
6336
6337 case FR_TYPE_ATTR: {
6338 fr_dict_attr_t const *parent = NULL;
6339 fr_sbuff_t *unescaped = NULL;
6340
6341 FR_SBUFF_IN_CHAR_RETURN(&our_out, ':', ':');
6342
6343 if (!data->enumv) {
6344 fr_strerror_const("Value of type 'attribute' is missing the enum");
6345 return -1;
6346 }
6347
6348 switch (data->enumv->type) {
6349 case FR_TYPE_TLV:
6350 parent = data->enumv;
6351 break;
6352
6353 case FR_TYPE_ATTR: /* will print from the root */
6354 break;
6355
6356 default:
6357 fr_assert_msg(0, "Invalid data type for 'attr' enumv");
6358 break;
6359 }
6360
6361 /*
6362 * No escaping, just dump the name as-is.
6363 */
6364 if (!e_rules) {
6365 FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, parent, data->vb_attr, false);
6366 break;
6367 }
6368
6369 /*
6370 * Escaping, use an intermediate buffer. Because
6371 * we can't pipe sbuffs together.
6372 */
6373 FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096);
6374
6375 FR_DICT_ATTR_OID_PRINT_RETURN(unescaped, parent, data->vb_attr, false);
6376
6377 FR_SBUFF_IN_ESCAPE_RETURN(&our_out, fr_sbuff_start(unescaped),
6378 fr_sbuff_used(unescaped), e_rules);
6379 }
6380 break;
6381
6382 case FR_TYPE_NULL:
6383 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "NULL");
6384 break;
6385
6386 /*
6387 * Don't add default here
6388 */
6389 case FR_TYPE_TLV: /* Not a box type */
6390 case FR_TYPE_STRUCT: /* Not a box type */
6391 case FR_TYPE_VSA: /* Not a box type */
6392 case FR_TYPE_VENDOR: /* Not a box type */
6393 case FR_TYPE_UNION: /* Not a box type */
6394 case FR_TYPE_VALUE_BOX:
6395 case FR_TYPE_VOID:
6396 case FR_TYPE_MAX:
6397 (void)fr_cond_assert(0);
6398 return 0;
6399
6402 FR_SBUFF_IN_STRCPY_RETURN(&our_out, data->vb_cursor_name);
6403 break;
6404 }
6405
6406done:
6407 FR_SBUFF_SET_RETURN(out, &our_out);
6408}
6409
6410/** Print one boxed value to a string with quotes (where needed)
6411 *
6412 * @param[in] out Where to write the printed string.
6413 * @param[in] data Value box to print.
6414 * @param[in] quote To apply to FR_TYPE_STRING types.
6415 * Is not currently applied to any
6416 * other box type.
6417 */
6419{
6420 fr_sbuff_t our_out = FR_SBUFF(out);
6421
6422 if (quote == T_BARE_WORD) return fr_value_box_print(out, data, NULL);
6423
6424 switch (data->type) {
6425 case FR_TYPE_QUOTED:
6426 FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
6428 FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
6429 break;
6430
6431 default:
6432 return fr_value_box_print(out, data, NULL);
6433 }
6434
6435 FR_SBUFF_SET_RETURN(out, &our_out);
6436}
6437
6438/** Concatenate a list of value boxes together
6439 *
6440 * All boxes will be removed from the list.
6441 *
6442 * @param[out] safety if !NULL, the results of tainted / secret / safe_for will be stored here.
6443 * @param[out] sbuff to write the result of the concatenation to.
6444 * @param[in] list to concatenate.
6445 * @param[in] sep Insert a separator between the values.
6446 * @param[in] sep_len Length of the separator.
6447 * @param[in] e_rules To apply to FR_TYPE_STRING types.
6448 * Is not currently applied to any other box type.
6449 * @param[in] proc_action What to do with the boxes in the list once
6450 * they've been processed.
6451 * @param[in] safe_for if value has this safe_for value, don't apply the escape rules.
6452 * for values which are escaped, mash the safe_for value to this.
6453 * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
6454 * we concat the contents of its children together.
6455 * If false, the contents will be cast to #FR_TYPE_STRING.
6456 * @return
6457 * - >=0 the number of bytes written to the sbuff.
6458 * - <0 how many additional bytes we would have needed to
6459 * concat the next box.
6460 */
6462 char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules,
6463 fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
6464{
6465 fr_sbuff_t our_sbuff = FR_SBUFF(sbuff);
6466 ssize_t slen;
6467
6468 if (fr_value_box_list_empty(list)) return 0;
6469
6470 fr_value_box_list_foreach(list, vb) {
6471 fr_value_box_safe_for_t box_safe_for = vb->vb_safefor;
6472
6473 switch (vb->type) {
6474 case FR_TYPE_GROUP:
6475 if (!flatten) goto print;
6476 slen = fr_value_box_list_concat_as_string(safety, &our_sbuff, &vb->vb_group,
6477 sep, sep_len, e_rules,
6478 proc_action, safe_for, flatten);
6479 break;
6480
6481 case FR_TYPE_OCTETS:
6482
6483 /*
6484 * Copy the raw string over, if necessary with escaping.
6485 */
6486 if (e_rules && (!fr_value_box_is_safe_for(vb, safe_for) || e_rules->do_oct || e_rules->do_hex)) {
6487 box_safe_for = safe_for;
6488
6489 slen = fr_sbuff_in_escape(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length, e_rules);
6490 } else {
6491 slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
6492 }
6493 break;
6494
6495 case FR_TYPE_STRING:
6496 if (!fr_value_box_is_safe_for(vb, safe_for) && e_rules) goto print;
6497
6498 slen = fr_sbuff_in_bstrncpy(&our_sbuff, vb->vb_strvalue, vb->vb_length);
6499 break;
6500
6501 case FR_TYPE_NULL: /* Skip null */
6502 continue;
6503
6504 default:
6505 print:
6506 /*
6507 * If we escaped it, set the output safe_for value.
6508 */
6509 if (e_rules) box_safe_for = safe_for;
6510 slen = fr_value_box_print(&our_sbuff, vb, e_rules);
6511 break;
6512 }
6513 if (slen < 0) return slen;
6514
6515 /*
6516 * Add in the separator
6517 */
6518 if (sep && fr_value_box_list_next(list, vb)) {
6519 slen = fr_sbuff_in_bstrncpy(&our_sbuff, sep, sep_len);
6520 if (slen < 0) return slen;
6521 }
6522
6523 /*
6524 * Merge in the safety rules.
6525 */
6526 if (!safety || (vb->type == FR_TYPE_GROUP)) continue;
6527
6528 /*
6529 * We can't call fr_box_safety_merge(), as we may have escaped the input box.
6530 */
6531 if ((safety->safe_for != FR_VALUE_BOX_SAFE_FOR_NONE) &&
6532 (safety->safe_for != box_safe_for)) {
6533 if (safety->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) {
6534 safety->safe_for = box_safe_for;
6535 } else if (box_safe_for != FR_VALUE_BOX_SAFE_FOR_ANY) {
6537 }
6538 }
6539
6540 safety->secret |= vb->vb_secret;
6541 }
6542
6543 /*
6544 * Free the boxes last so if there's
6545 * an issue concatenating them, everything
6546 * is still in a known state.
6547 */
6548 fr_value_box_list_foreach(list, vb) {
6549 if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
6550 if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
6551 if (vb_should_free(proc_action)) talloc_free(vb);
6552 }
6553
6554 FR_SBUFF_SET_RETURN(sbuff, &our_sbuff);
6555}
6556
6558
6559/** Concatenate a list of value boxes together
6560 *
6561 * All boxes will be removed from the list.
6562 *
6563 * @param[out] safety if !NULL, the results of tainted / secret / safe_for will be stored here.
6564 * @param[out] dbuff to write the result of the concatenation to.
6565 * @param[in] list to concatenate.
6566 * @param[in] sep Insert a separator between the values.
6567 * @param[in] sep_len Length of the separator.
6568 * @param[in] proc_action What to do with the boxes in the list once
6569 * they've been processed.
6570 * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
6571 * we concat the contents of its children together.
6572 * If false, the contents will be cast to #FR_TYPE_OCTETS.
6573 * @return
6574 * - >=0 the number of bytes written to the sbuff.
6575 * - <0 how many additional bytes we would have needed to
6576 * concat the next box.
6577 */
6579 uint8_t const *sep, size_t sep_len,
6580 fr_value_box_list_action_t proc_action, bool flatten)
6581{
6582 fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
6583 TALLOC_CTX *tmp_ctx = NULL;
6584 ssize_t slen;
6585
6586 if (fr_value_box_list_empty(list)) return 0;
6587
6588 fr_value_box_list_foreach(list, vb) {
6589 switch (vb->type) {
6590 case FR_TYPE_GROUP:
6591 if (!flatten) goto cast;
6592 slen = fr_value_box_list_concat_as_octets(safety, &our_dbuff, &vb->vb_group,
6593 sep, sep_len,
6594 proc_action, flatten);
6595 break;
6596
6597 case FR_TYPE_OCTETS:
6598 slen = fr_dbuff_in_memcpy(&our_dbuff, vb->vb_octets, vb->vb_length);
6599 break;
6600
6601 case FR_TYPE_STRING:
6602 slen = fr_dbuff_in_memcpy(&our_dbuff, (uint8_t const *)vb->vb_strvalue, vb->vb_length);
6603 break;
6604
6605 case FR_TYPE_NULL: /* Skip null */
6606 continue;
6607
6608 default:
6609 cast:
6610 {
6611 fr_value_box_t tmp_vb;
6612
6613 if (!tmp_ctx) tmp_ctx = talloc_pool(NULL, 1024);
6614
6615 /*
6616 * Not equivalent to fr_value_box_to_network
6617 */
6618 if (fr_value_box_cast_to_octets(tmp_ctx, &tmp_vb, FR_TYPE_OCTETS, NULL, vb) < 0) {
6619 slen = -1;
6620 goto error;
6621 }
6622
6623 slen = fr_dbuff_in_memcpy(&our_dbuff, tmp_vb.vb_octets, tmp_vb.vb_length);
6624 fr_value_box_clear_value(&tmp_vb);
6625 break;
6626 }
6627 }
6628
6629 if (slen < 0) {
6630 error:
6631 talloc_free(tmp_ctx);
6632 return slen;
6633 }
6634
6635 if (sep && fr_value_box_list_next(list, vb)) {
6636 slen = fr_dbuff_in_memcpy(&our_dbuff, sep, sep_len);
6637 if (slen < 0) goto error;
6638 }
6639
6640 if (safety) _value_box_safety_merge(safety, &vb->safety);
6641 }
6642
6643 talloc_free(tmp_ctx);
6644
6645 /*
6646 * Free the boxes last so if there's
6647 * an issue concatenating them, everything
6648 * is still in a known state.
6649 */
6650 fr_value_box_list_foreach(list, vb) {
6651 if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
6652 if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
6653 if (vb_should_free(proc_action)) talloc_free(vb);
6654 }
6655
6656 return fr_dbuff_set(dbuff, &our_dbuff);
6657}
6658
6659/** Concatenate a list of value boxes
6660 *
6661 * @note Will automatically cast all #fr_value_box_t to type specified.
6662 *
6663 * @param[in] ctx to allocate new value buffer in.
6664 * @param[out] out Where to write the resulting box.
6665 * @param[in] list to concatenate together.
6666 * @param[in] type May be #FR_TYPE_STRING or #FR_TYPE_OCTETS, no other types are
6667 * supported.
6668 * @param[in] proc_action What to do with the boxes in the list once
6669 * they've been processed.
6670 * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
6671 * we concat the contents of its children together.
6672 * If false, the contents will be cast to the given type.
6673 * @param[in] max_size of the value.
6674 * @return
6675 * - 0 on success.
6676 * - -1 on failure.
6677 */
6679 fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type,
6680 fr_value_box_list_action_t proc_action, bool flatten,
6681 size_t max_size)
6682{
6683 fr_dbuff_t dbuff; /* FR_TYPE_OCTETS */
6684 fr_dbuff_uctx_talloc_t dbuff_tctx;
6685
6686 fr_sbuff_t sbuff; /* FR_TYPE_STRING */
6687 fr_sbuff_uctx_talloc_t sbuff_tctx;
6688
6689 fr_value_box_t *head_vb = fr_value_box_list_head(list);
6690
6691 fr_value_box_entry_t entry;
6692 fr_value_box_safety_t safety = { .safe_for = FR_VALUE_BOX_SAFE_FOR_ANY }; /* Merged safety of every box, applied to out at the end */
6693
6694 if (fr_value_box_list_empty(list)) {
6695 fr_strerror_const("Invalid arguments. List contains no elements");
6696 return -1;
6697 }
6698
6699 /*
6700 * Exit quickly if the list is only one box of the correct type and
6701 * out points at that box.
6702 */
6703 if ((fr_value_box_list_num_elements(list) == 1) && (head_vb == out) && (head_vb->type == type)) return 0;
6704
6705 /*
6706 * The accumulator starts as "safe for anything", the identity for the merge,
6707 * and each box narrows it. The constructor below re-initialises out, so the
6708 * merged safety is applied to out afterwards.
6709 */
6710
6711 switch (type) {
6712 case FR_TYPE_STRING:
6713 if (unlikely(!fr_sbuff_init_talloc(ctx, &sbuff, &sbuff_tctx, 256, max_size))) return -1;
6714 break;
6715
6716 case FR_TYPE_OCTETS:
6717 if (unlikely(!fr_dbuff_init_talloc(ctx, &dbuff, &dbuff_tctx, 256, max_size))) return -1;
6718 break;
6719
6720 default:
6721 fr_strerror_printf("Invalid argument. Can't concatenate boxes to type %s",
6723 return -1;
6724 }
6725
6726 /*
6727 * Merge all siblings into list head.
6728 *
6729 * This is where the first element in the
6730 * list is the output box.
6731 *
6732 * i.e. we want to merge all its siblings
6733 * into it.
6734 */
6735 if (out == head_vb) {
6736 switch (type) {
6737 case FR_TYPE_STRING:
6738 /*
6739 * Head gets dealt with specially as we don't
6740 * want to free it, and we don't want to free
6741 * the buffer associated with it (just yet).
6742 *
6743 * Note that we don't convert 'octets' to a printable string
6744 * here. Doing so breaks the keyword tests.
6745 */
6746 if (fr_value_box_list_concat_as_string(&safety, &sbuff, list,
6747 NULL, 0, NULL,
6749 fr_strerror_printf("Concatenation exceeded max_size (%zu)", max_size);
6750 error:
6751 switch (type) {
6752 case FR_TYPE_STRING:
6753 talloc_free(fr_sbuff_buff(&sbuff));
6754 break;
6755
6756 case FR_TYPE_OCTETS:
6757 talloc_free(fr_dbuff_buff(&dbuff));
6758 break;
6759
6760 default:
6761 break;
6762 }
6763 return -1;
6764 }
6765
6766 /*
6767 * Concat the rest of the children...
6768 */
6769 if (fr_value_box_list_concat_as_string(&safety, &sbuff, list,
6770 NULL, 0, NULL,
6771 proc_action, FR_VALUE_BOX_SAFE_FOR_ANY, flatten) < 0) {
6772 fr_value_box_list_insert_head(list, head_vb);
6773 goto error;
6774 }
6775 (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
6777 if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), out->tainted) < 0) goto error;
6778 fr_value_box_safety_set(out, &safety);
6779 break;
6780
6781 case FR_TYPE_OCTETS:
6782 if (fr_value_box_list_concat_as_octets(&safety, &dbuff, list,
6783 NULL, 0,
6784 FR_VALUE_BOX_LIST_REMOVE, flatten) < 0) goto error;
6785
6786 if (fr_value_box_list_concat_as_octets(&safety, &dbuff, list,
6787 NULL, 0,
6788 proc_action, flatten) < 0) {
6789 fr_value_box_list_insert_head(list, head_vb);
6790 goto error;
6791 }
6792 (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
6794 if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), out->tainted) < 0) goto error;
6795 fr_value_box_safety_set(out, &safety);
6796 break;
6797
6798 default:
6799 break;
6800 }
6801
6802 fr_value_box_list_insert_head(list, out);
6803
6804 /*
6805 * Merge all the boxes in the list into
6806 * a single contiguous buffer.
6807 *
6808 * This deals with an unrelated out and list
6809 * and also where list is the children of
6810 * out.
6811 */
6812 } else {
6813 switch (type) {
6814 case FR_TYPE_STRING:
6815 if (fr_value_box_list_concat_as_string(&safety, &sbuff, list,
6816 NULL, 0, NULL,
6817 proc_action, FR_VALUE_BOX_SAFE_FOR_ANY, flatten) < 0) goto error;
6818 (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
6819
6820 entry = out->entry;
6821 if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), out->tainted) < 0) goto error;
6822 out->entry = entry;
6823 fr_value_box_safety_set(out, &safety);
6824 break;
6825
6826 case FR_TYPE_OCTETS:
6827 if (fr_value_box_list_concat_as_octets(&safety, &dbuff, list,
6828 NULL, 0,
6829 proc_action, flatten) < 0) goto error;
6830 (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
6831
6832 entry = out->entry;
6833 if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), out->tainted) < 0) goto error;
6834 out->entry = entry;
6835 fr_value_box_safety_set(out, &safety);
6836 break;
6837
6838 default:
6839 break;
6840 }
6841 }
6842
6843 return 0;
6844}
6845
6846/** Escape a single value box in place
6847 *
6848 * @note Applies recursively to the children of group boxes.
6849 *
6850 * @param[in] vb to escape.
6851 * @param[in] escape escape definition to apply to the value box.
6852 * @param[in] uctx user context to pass to the escape function.
6853 * @return
6854 * - 0 on success.
6855 * - -1 on failure.
6856 */
6858{
6859 int ret;
6860
6861 switch (vb->type) {
6862 case FR_TYPE_GROUP:
6863 return fr_value_box_list_escape_in_place(&vb->vb_group, escape, uctx);
6864
6865 case FR_TYPE_NULL:
6866 case FR_TYPE_TLV:
6867 case FR_TYPE_STRUCT:
6868 case FR_TYPE_VSA:
6869 case FR_TYPE_VENDOR:
6870 case FR_TYPE_INTERNAL:
6871 fr_strerror_printf("Cannot escape data type '%s'", fr_type_to_str(vb->type));
6872 return -1;
6873
6874 case FR_TYPE_ATTR:
6875 fr_assert(0); /* @todo - print to string, and then escape? */
6876 fr_strerror_printf("Cannot escape data type '%s'", fr_type_to_str(vb->type));
6877 return -1;
6878
6879 default:
6880 break;
6881 }
6882
6883 /*
6884 * Don't do double escaping.
6885 */
6886 if (!escape->always_escape && fr_value_box_is_safe_for(vb, escape->safe_for)) return 0;
6887
6888 ret = escape->func(vb, uctx);
6889 if (unlikely(ret < 0)) return ret;
6890
6891 /*
6892 * '1' means that the function mashed the safe_for value, so we don't need to.
6893 */
6894 if (!ret) vb->vb_safefor = escape->safe_for;
6895 vb->tainted = false;
6896
6897 return 0;
6898}
6899
6900/** Escape a list of value boxes in place
6901 *
6902 * @note Applies recursively to the children of group boxes.
6903 *
6904 * @note on error, the list may be left in an inconsistent/partially escaped state.
6905 *
6906 * @param[in] list to escape.
6907 * @param[in] escape escape definition to apply to the value box.
6908 * @param[in] uctx user context to pass to the escape function.
6909 * @return
6910 * - 0 on success.
6911 * - -1 on failure.
6912 */
6913int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t const *escape, void *uctx)
6914{
6915 int ret = 0;
6916
6917 fr_value_box_list_foreach(list, vb) {
6918 ret = fr_value_box_escape_in_place(vb, escape, uctx);
6919 if (unlikely(ret < 0)) return ret;
6920 }
6921
6922 return ret;
6923}
6924
6929
6930static int _value_box_escape_rules(fr_value_box_t *vb, void *uctx)
6931{
6933
6934 if (fr_type_is_leaf(vb->type)) {
6935 if (fr_value_box_escape_in_place_erules(ctx->ctx, vb, ctx->erules) < 0) return -1;
6936
6937 return 1; /* safe_for has been updated */
6938 }
6939
6943 .safe_for = (fr_value_box_safe_for_t) ctx->erules,
6944 .always_escape = false,
6945 },
6947 .ctx = vb,
6948 .erules = ctx->erules,
6949 }
6950 );
6951}
6952
6953/** Escape a value-box in place using sbuff escaping rules, and mark it safe-for.
6954 *
6955 * If the input type isn't a string, then it is converted to a string.
6956 *
6957 * The output type is always #FR_TYPE_STRING
6958 *
6959 * @param[in] ctx to allocate any new buffers in.
6960 * @param[in] vb which will be escaped
6961 * @param[in] erules escape rules
6962 * @return
6963 * - <0 for error, generally OOM
6964 * - 0 for success (did not set safe_for)
6965 * - 1 for success (did set safe_for)
6966 */
6968{
6969 ssize_t slen;
6970 fr_sbuff_t *escaped = NULL;
6971
6972 FR_SBUFF_TALLOC_THREAD_LOCAL(&escaped, 256, 4096);
6973
6974 /*
6975 * Structural types are much more complicated. :(
6976 */
6977 if (!fr_type_is_leaf(vb->type)) {
6978 int rcode;
6979
6983 .safe_for = (fr_value_box_safe_for_t) erules,
6984 .always_escape = false,
6985 },
6987 .ctx = ctx,
6988 .erules = erules,
6989 }
6990 );
6991 if (rcode < 0) return rcode;
6992
6993 rcode = fr_value_box_list_concat_as_string(NULL, escaped, &vb->vb_group, NULL, 0, NULL,
6995 (fr_value_box_safe_for_t) erules, true);
6996 if (rcode < 0) return rcode;
6997
6998 fr_assert(fr_value_box_list_num_elements(&vb->vb_group) == 0);
6999
7000 goto set_value;
7001 }
7002
7003 if (vb->type != FR_TYPE_STRING) {
7004 if (fr_value_box_cast_in_place(ctx, vb, FR_TYPE_STRING, NULL) < 0) return -1;
7005 } else {
7006 if (fr_value_box_is_safe_for(vb, erules)) return 0;
7007 }
7008
7009 slen = fr_sbuff_in_escape(escaped, vb->vb_strvalue, vb->vb_length, erules);
7010 if (slen < 0) return -1;
7011
7012set_value:
7013 if (fr_value_box_bstrndup(ctx, vb, NULL, fr_sbuff_start(escaped), fr_sbuff_used(escaped), false) < 0) return -1;
7014
7015 fr_value_box_mark_safe_for(vb, erules);
7016
7017 return 1;
7018}
7019
7020/** Escape a value-box in place using the supplied #fr_sbuff_escape_rules_t in uctx
7021 *
7022 * If the input type isn't a string, then it is converted to a string.
7023 *
7024 * The output type is always #FR_TYPE_STRING
7025 *
7026 * @param[in] vb which will be escaped
7027 * @param[in] uctx escape rules
7028 * @return
7029 * - <0 for error, generally OOM
7030 * - 0 for success (did not set safe_for)
7031 * - 1 for success (did set safe_for)
7032 */
7034{
7035 return fr_value_box_escape_in_place_erules(vb, vb, uctx);
7036}
7037
7038/** Escape a value box in place using an sbuff escape function
7039 *
7040 * If the input type isn't a string, then it is converted to a string.
7041 *
7042 * The output type is always #FR_TYPE_STRING. The safe_for and tainted
7043 * flags are left as they were. The caller marks the box once it knows
7044 * which dialect the escape function produced.
7045 *
7046 * @param[in] ctx to allocate the escaped string in.
7047 * @param[in] vb which will be escaped. Must be a leaf type.
7048 * @param[in] escape function to run over the string value.
7049 * @return
7050 * - <0 for error, generally OOM.
7051 * - 0 for success.
7052 */
7053int fr_value_box_escape_in_place_func(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_sbuff_escape_func_t escape)
7054{
7055 fr_sbuff_t *escaped = NULL;
7056
7057 fr_assert(fr_type_is_leaf(vb->type));
7058
7059 if ((vb->type != FR_TYPE_STRING) && (fr_value_box_cast_in_place(ctx, vb, FR_TYPE_STRING, NULL) < 0)) {
7060 return -1;
7061 }
7062
7063 FR_SBUFF_TALLOC_THREAD_LOCAL(&escaped, 256, SIZE_MAX);
7064
7065 if (escape(escaped, &FR_SBUFF_IN(vb->vb_strvalue, vb->vb_length)) < 0) return -1;
7066
7067 return fr_value_box_bstrndup_replace(ctx, vb, fr_sbuff_start(escaped), (ssize_t)fr_sbuff_used(escaped));
7068}
7069
7070
7071/** Removes a single layer of nesting, moving all children into the parent list
7072 *
7073 * @param[in] ctx to reparent children in if steal is true.
7074 * @param[in] list to flatten.
7075 * @param[in] steal whether to change the talloc ctx of children.
7076 * @param[in] free whether to free any group boxes which have had
7077 * their children removed.
7078 */
7079void fr_value_box_flatten(TALLOC_CTX *ctx, fr_value_box_list_t *list, bool steal, bool free)
7080{
7081 fr_value_box_list_foreach(list, child) {
7082 if (!fr_type_is_structural(child->type)) continue;
7083
7084 fr_value_box_list_foreach(&child->vb_group, grandchild) {
7085 fr_value_box_list_remove(&child->vb_group, grandchild);
7086 if (steal) talloc_steal(ctx, grandchild);
7087 fr_value_box_list_insert_before(list, child, grandchild);
7088 }
7089
7090 if (free) talloc_free(child);
7091 }
7092}
7093
7094/** Concatenate the string representations of a list of value boxes together
7095 *
7096 * @param[in] ctx to allocate the buffer in.
7097 * @param[in] list of value boxes.
7098 * @param[in] delim to insert between value box values.
7099 * @param[in] e_rules to control escaping of the concatenated elements.
7100 * @return
7101 * - NULL on error.
7102 * - The concatenation of the string values of the value box list on success.
7103 */
7104char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
7105 fr_sbuff_escape_rules_t const *e_rules)
7106{
7107 fr_value_box_t const *vb = fr_value_box_list_head(list);
7108 char *aggr, *td = NULL;
7109 TALLOC_CTX *pool = NULL;
7110
7111 if (!vb) return NULL;
7112
7113 fr_value_box_aprint(ctx, &aggr, vb, e_rules);
7114 if (!aggr) return NULL;
7115 if (!fr_value_box_list_next(list, vb)) return aggr;
7116
7117 /*
7118 * If we're aggregating more values,
7119 * allocate a temporary pool.
7120 */
7121 pool = talloc_pool(NULL, 255);
7122 if (delim) td = talloc_strdup(pool, delim);
7123
7124 while ((vb = fr_value_box_list_next(list, vb))) {
7125 char *str, *new_aggr;
7126
7127 fr_value_box_aprint(pool, &str, vb, e_rules);
7128 if (!str) continue;
7129
7130 new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
7131 if (unlikely(!new_aggr)) {
7132 talloc_free(aggr);
7133 talloc_free(pool);
7134 return NULL;
7135 }
7136 aggr = new_aggr;
7137 talloc_free(str);
7138 }
7139 talloc_free(pool);
7140
7141 return aggr;
7142}
7143
7144/** Concatenate the string representations of a list of value boxes together hiding "secret" values
7145 *
7146 * @param[in] ctx to allocate the buffer in.
7147 * @param[in] list of value boxes.
7148 * @param[in] delim to insert between value box values.
7149 * @param[in] e_rules to control escaping of the concatenated elements.
7150 * @return
7151 * - NULL on error.
7152 * - The concatenation of the string values of the value box list on success.
7153 */
7154char *fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
7155 fr_sbuff_escape_rules_t const *e_rules)
7156{
7157 fr_value_box_t const *vb = fr_value_box_list_head(list);
7158 char *aggr, *td = NULL;
7159 TALLOC_CTX *pool = NULL;
7160
7161 if (!vb) return NULL;
7162
7164 aggr = talloc_strdup(ctx, "<<< secret >>>");
7165 } else {
7166 fr_value_box_aprint(ctx, &aggr, vb, e_rules);
7167 }
7168 if (!aggr) return NULL;
7169 if (!fr_value_box_list_next(list, vb)) return aggr;
7170
7171 /*
7172 * If we're aggregating more values,
7173 * allocate a temporary pool.
7174 */
7175 pool = talloc_pool(NULL, 255);
7176 if (delim) td = talloc_strdup(pool, delim);
7177
7178 while ((vb = fr_value_box_list_next(list, vb))) {
7179 char *str, *new_aggr;
7180
7182 str = talloc_strdup(pool, "<<< secret >>>");
7183 } else {
7184 fr_value_box_aprint(pool, &str, vb, e_rules);
7185 }
7186 if (!str) continue;
7187
7188 new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
7189 if (unlikely(!new_aggr)) {
7190 talloc_free(aggr);
7191 talloc_free(pool);
7192 return NULL;
7193 }
7194 aggr = new_aggr;
7195 talloc_free(str);
7196 }
7197 talloc_free(pool);
7198
7199 return aggr;
7200}
7201
7202/** Hash the contents of a value box
7203 *
7204 */
7206{
7207 switch (vb->type) {
7208 case FR_TYPE_FIXED_SIZE:
7209 return fr_hash(fr_value_box_raw(vb, vb->type),
7210 fr_value_box_field_sizes[vb->type]);
7211
7212 case FR_TYPE_STRING:
7213 return fr_hash(vb->vb_strvalue, vb->vb_length);
7214
7215 case FR_TYPE_OCTETS:
7216 return fr_hash(vb->vb_octets, vb->vb_length);
7217
7218 case FR_TYPE_ATTR:
7219 return fr_hash(&vb->vb_attr, sizeof(vb->vb_attr));
7220
7221 case FR_TYPE_STRUCTURAL:
7222 case FR_TYPE_INTERNAL:
7225 case FR_TYPE_NULL:
7226 fr_assert(0);
7227 break;
7228 }
7229
7230 return 0;
7231}
7232
7233/** Do a full copy of a list of value boxes
7234 *
7235 * @param[in] ctx to allocate boxes in.
7236 * @param[out] out Where to write the head of the new list.
7237 * @param[in] in boxes to copy.
7238 * @return
7239 * - A duplicate list of value boxes, allocated in the context of 'ctx'
7240 * - NULL on error, or empty input list.
7241 */
7242int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
7243{
7244 fr_value_box_t const *in_p = NULL;
7245
7246 while ((in_p = fr_value_box_list_next(in, in_p))) {
7247 fr_value_box_t *n = NULL;
7248
7250 if (!n) {
7251 error:
7252 fr_value_box_list_talloc_free(out);
7253 return -1;
7254 }
7255
7256 if (fr_value_box_copy(n, n, in_p) < 0) goto error;
7257 fr_dlist_insert_tail(fr_value_box_list_dlist_head(out), n);
7258 }
7259
7260 return 0;
7261}
7262
7263/** Check to see if any list members (or their children) are tainted
7264 *
7265 * @param[in] head of list to check.
7266 * @return
7267 * - true if a list member is tainted.
7268 * - false if no list members are tainted.
7269 */
7270bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
7271{
7272 fr_value_box_t *vb = NULL;
7273
7274 while ((vb = fr_value_box_list_next(head, vb))) {
7275 if (fr_type_is_group(vb->type) && fr_value_box_list_tainted(&vb->vb_group)) return true;
7276 if (vb->tainted) return true;
7277 }
7278
7279 return false;
7280}
7281
7282#if defined(WITH_VERIFY_PTR) || !defined(NDEBUG)
7283#define VB_NAME "fr_value_box_t %p (from %s:%d)"
7284#define VB_NAME_LOCATION(_x) (void const *) (_x), (_x)->file ? (_x)->file : "", (_x)->line
7285
7286/** Validation function to check that a fr_value_box_t is correctly initialised
7287 *
7288 */
7289void fr_value_box_verify(char const *file, int line, fr_value_box_t const *vb)
7290{
7291DIAG_OFF(nonnull-compare)
7292 /*
7293 * nonnull only does something if we're building
7294 * with ubsan... We still want to assert event
7295 * if we're building without sanitizers.
7296 */
7297 fr_fatal_assert_msg(vb, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t pointer was NULL", file, line);
7298DIAG_ON(nonnull-compare)
7299
7300 if (vb->talloced) vb = talloc_get_type_abort_const(vb, fr_value_box_t);
7301
7302#ifndef NDEBUG
7303 fr_fatal_assert_msg(vb->magic == FR_VALUE_BOX_MAGIC, "CONSISTENCY CHECK FAILED %s[%i]: " VB_NAME " magic "
7304 "incorrect, expected %" PRIx64 ", got %" PRIx64,
7305 file, line,
7306 VB_NAME_LOCATION(vb),
7307 FR_VALUE_BOX_MAGIC, vb->magic);
7308#endif
7309 switch (vb->type) {
7310 case FR_TYPE_STRING:
7311 if (!vb->vb_length) {
7312#if 0
7313 fr_fatal_assert_msg(!vb->vb_strvalue || (talloc_array_length(vb->vb_strvalue) == 1), "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " strvalue field "
7314 "wasn non-NULL, but length was %u",
7315 file, line,
7316 VB_NAME_LOCATION(vb),
7317 vb->vb_length);
7318#endif
7319 break;
7320 }
7321
7322 fr_fatal_assert_msg(vb->vb_strvalue, "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " strvalue field "
7323 "was NULL", file, line, VB_NAME_LOCATION(vb));
7324 fr_fatal_assert_msg(vb->vb_strvalue[vb->vb_length] == '\0',
7325 "CONSISTENCY CHECK FAILED %s[%i]: " VB_NAME " strvalue field "
7326 "not null terminated", file, line, VB_NAME_LOCATION(vb));
7327 if (vb->talloced) {
7328 size_t len = talloc_array_length(vb->vb_strvalue);
7329
7330 /* We always \0 terminate to be safe, even though most things should use the len field */
7331 if (len <= vb->vb_length) {
7332 fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%d]: Expected " VB_NAME " strvalue talloc buffer "
7333 "len >= %zu, got %zu",
7334 file, line,
7335 VB_NAME_LOCATION(vb),
7336 vb->vb_length + 1, len);
7337 }
7338 }
7339 break;
7340
7341 case FR_TYPE_OCTETS:
7342 if (!vb->vb_length) {
7343#if 0
7344 fr_fatal_assert_msg(!vb->vb_octets || (talloc_array_length(vb->vb_octets) == 0), "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " octets field "
7345 "wasn non-NULL, but length was %u",
7346 file, line,
7347 VB_NAME_LOCATION(vb).
7348 vb->vb_length);
7349#endif
7350 break;
7351 }
7352
7353 fr_fatal_assert_msg(vb->vb_octets, "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " octets field "
7354 "was NULL", file, line, VB_NAME_LOCATION(vb));
7355 break;
7356
7357 case FR_TYPE_VOID:
7358 fr_fatal_assert_msg(vb->vb_void, "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " ptr field "
7359 "was NULL", file, line, VB_NAME_LOCATION(vb));
7360 break;
7361
7362 case FR_TYPE_GROUP:
7363 fr_value_box_list_verify(file, line, &vb->vb_group);
7364 break;
7365
7366 case FR_TYPE_ATTR:
7367 fr_fatal_assert_msg(vb->vb_attr, "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " vb_attr field "
7368 "was NULL", file, line, VB_NAME_LOCATION(vb));
7369 break;
7370
7371 case FR_TYPE_BOOL:
7372 fr_fatal_assert_msg(vb->vb_uint8 <= 1, "CONSISTENCY CHECK FAILED %s[%d]: " VB_NAME " vb_bool field "
7373 "was not boolean!", file, line, VB_NAME_LOCATION(vb));
7374 break;
7375
7376 default:
7377 break;
7378 }
7379}
7380
7381void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
7382{
7384}
7385#endif
7386
7387/** Mark a value-box as "safe", of a particular type.
7388 *
7389 */
7391{
7392 /*
7393 * Don't over-ride value-boxes which are already safe, unless we want to mark them as being
7394 * completely unsafe.
7395 */
7396 if ((vb->vb_safefor == FR_VALUE_BOX_SAFE_FOR_ANY) &&
7397 (safe_for != FR_VALUE_BOX_SAFE_FOR_NONE)) {
7398 fr_assert(!vb->tainted);
7399 return;
7400 }
7401
7402 vb->vb_safefor = safe_for;
7403}
7404
7405/** Mark a value-box as "unsafe"
7406 *
7407 * This always succeeds, and there are no side effects.
7408 */
7410{
7411 vb->vb_safefor = FR_VALUE_BOX_SAFE_FOR_NONE;
7412}
7413
7414/** Set the escaped flag for all value boxes in a list
7415 *
7416 * @note Only operates on a single level.
7417 *
7418 * @param[in] list to operate on.
7419 * @param[in] safe_for value to set.
7420 */
7421void fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for)
7422{
7423 fr_value_box_list_foreach(list, vb) {
7424 /*
7425 * Don't over-ride value-boxes which are already safe.
7426 */
7427 if (vb->vb_safefor == FR_VALUE_BOX_SAFE_FOR_ANY) {
7428 fr_assert(!vb->tainted);
7429
7430 } else {
7431 vb->vb_safefor = safe_for;
7432 }
7433 }
7434}
7435
7436/** Copy the safety values from one box to another.
7437 *
7438 */
7440{
7441 if (out == in) return;
7442
7443 out->vb_safefor = in->vb_safefor;
7444 out->tainted = in->tainted;
7445 out->vb_secret = in->vb_secret;
7446}
7447
7448/** Copy the safety values from one box to another.
7449 *
7450 * But note that we have changed the output format, so we reset the "safe_for" value to NONE.
7451 */
7453{
7454 out->vb_safefor = FR_VALUE_BOX_SAFE_FOR_NONE;
7455 out->tainted = in->tainted;
7456 out->vb_secret = in->vb_secret;
7457}
7458
7459/** Merge one safety into another
7460 *
7461 * @param[in,out] out safety to narrow.
7462 * @param[in] in safety to merge in.
7463 */
7465{
7466 if (out == in) return;
7467
7468 /*
7469 * If we're already at no safety, then we don't need to do anything.
7470 *
7471 * Otherwise we update the safety only if we need to change it.
7472 */
7473 if ((out->safe_for != FR_VALUE_BOX_SAFE_FOR_NONE) &&
7474 (out->safe_for != in->safe_for)) {
7475 /*
7476 * If the output is anything, then the input is more restrictive, so we switch to that.
7477 *
7478 * If the input is anything, then the output is already the more restrictive of the
7479 * two, so we leave it alone.
7480 *
7481 * Otherwise the values are different. Either it's X/Y, or NONE/X, or X/NONE. In which
7482 * case the answer is always NONE.
7483 */
7484 if (out->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) {
7485 out->safe_for = in->safe_for;
7486
7487 } else if (in->safe_for != FR_VALUE_BOX_SAFE_FOR_ANY) {
7488 out->safe_for = FR_VALUE_BOX_SAFE_FOR_NONE;
7489 }
7490 }
7491
7492 out->secret |= in->secret;
7493}
7494
7495/** Merge safety results.
7496 */
7498{
7499 _value_box_safety_merge(&out->safety, &in->safety);
7500 out->tainted |= in->tainted;
7501}
7502
7503/** Replace the safety of a box
7504 *
7505 * @param[out] box to update.
7506 * @param[in] safety to copy into the box.
7507 */
7509{
7510 box->safety = *safety;
7511}
7512
7513/** Mark a box as holding a secret, or not
7514 *
7515 * A structural value has no safety of its own, the children carry theirs. In a
7516 * #fr_pair_t the children list overlays the safety field, so a structural box is
7517 * left alone rather than written to.
7518 */
7520{
7521 if (fr_type_is_structural(box->type)) return;
7522
7523 box->vb_secret = secret;
7524}
7525
7526/** Merge the safety of every leaf box in a list into out
7527 *
7528 * Recurses into group boxes, which carry no safety of their own.
7529 */
7530static void _value_box_list_safety_merge(fr_value_box_t *out, fr_value_box_list_t const *list)
7531{
7532 fr_value_box_list_foreach(list, vb) {
7533 if (fr_type_is_group(vb->type)) {
7534 _value_box_list_safety_merge(out, &vb->vb_group);
7535 continue;
7536 }
7537
7539 }
7540}
7541
7542/** Set the safety of out to the most restrictive safety of any leaf box in a list
7543 *
7544 * Use when a value is built from several boxes without going through
7545 * #fr_value_box_list_concat_in_place, e.g. when a separator is inserted between them.
7546 * A box safe for consumer X, joined with a box safe for X or for anything, is still
7547 * safe for X. Any other combination is safe for nothing.
7548 *
7549 * @param[out] out Box whose safety is replaced. Its value is left alone.
7550 * @param[in] list Boxes to merge. Group boxes are descended into.
7551 */
7552void fr_value_box_list_safety_merge(fr_value_box_t *out, fr_value_box_list_t const *list)
7553{
7554 out->vb_safefor = FR_VALUE_BOX_SAFE_FOR_ANY;
7555 out->vb_secret = false;
7556
7558}
7559
7560
7561/** Check truthiness of values.
7562 *
7563 * The casting rules for expressions / conditions are slightly
7564 * different than fr_value_box_cast(). Largely because that
7565 * function is used to parse configuration files, and parses "yes
7566 * / no" and "true / false" strings, even if there's no
7567 * fr_dict_attr_t passed to it.
7568 */
7570{
7571 fr_value_box_t box;
7572
7573 switch (in->type) {
7574 case FR_TYPE_NULL:
7578 case FR_TYPE_ATTR:
7579 case FR_TYPE_INTERNAL:
7580 break;
7581
7582 case FR_TYPE_GROUP:
7583 return (fr_value_box_list_num_elements(&in->vb_group) > 0);
7584
7585 case FR_TYPE_BOOL:
7586 return in->vb_bool;
7587
7588 case FR_TYPE_STRING:
7589 case FR_TYPE_OCTETS:
7590 return (in->vb_length > 0);
7591
7592 case FR_TYPE_IPV4_ADDR:
7593 case FR_TYPE_IPV6_ADDR:
7594 return !fr_ipaddr_is_inaddr_any(&in->vb_ip);
7595
7598 return !((in->vb_ip.prefix == 0) && fr_ipaddr_is_inaddr_any(&in->vb_ip));
7599
7601 case FR_TYPE_FLOAT32:
7602 case FR_TYPE_FLOAT64:
7603 case FR_TYPE_IFID:
7604 case FR_TYPE_ETHERNET:
7606 if (fr_value_box_cast(NULL, &box, FR_TYPE_BOOL, NULL, in) < 0) return false;
7607 return box.vb_bool;
7608 }
7609
7610 return false;
7611}
7612
7613#define INFO_INDENT(_fmt, ...) fprintf(fp, "%*s" _fmt "\n", depth * 2, " ", ## __VA_ARGS__)
7614
7615static void _fr_value_box_debug(FILE *fp, fr_value_box_t const *vb, int depth, int idx);
7616static void _fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head, int depth)
7617{
7618 int i = 0;
7619
7620 INFO_INDENT("{");
7622 INFO_INDENT("}");
7623}
7624
7625/** Print a list of value boxes as info messages
7626 *
7627 * @note Call directly from the debugger
7628 */
7629void fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head)
7630{
7632}
7633
7634static void _fr_value_box_debug(FILE *fp, fr_value_box_t const *vb, int depth, int idx)
7635{
7636 char *value;
7637 char buffer[64];
7638
7639 if (fr_type_is_structural(vb->type)) {
7640 _fr_value_box_list_debug(fp, &vb->vb_group, depth + 1);
7641 return;
7642 }
7643
7644 buffer[0] = '\0';
7645 if (vb->type == FR_TYPE_TIME_DELTA) {
7646 if (!vb->enumv) {
7647 snprintf(buffer, sizeof(buffer), " (sec!) %" PRId64, fr_time_delta_unwrap(vb->vb_time_delta));
7648 } else {
7649 snprintf(buffer, sizeof(buffer), " (%s) %" PRId64,
7650 fr_table_str_by_value(fr_time_precision_table, vb->enumv->flags.flag_time_res, "?"),
7651 fr_time_delta_unwrap(vb->vb_time_delta));
7652 }
7653 }
7654
7655 fr_value_box_aprint(NULL, &value, vb, NULL);
7656 if (idx >= 0) {
7657 INFO_INDENT("[%d] (%s) %s", idx, fr_type_to_str(vb->type), value);
7658 INFO_INDENT(" %s %s %lx%s",
7659 vb->vb_secret ? "s" : "-",
7660 vb->tainted ? "t" : "-",
7661 vb->vb_safefor, buffer);
7662 } else {
7663 INFO_INDENT("(%s) %s", fr_type_to_str(vb->type), value);
7664 INFO_INDENT(" %s %s %lx%s",
7665 vb->vb_secret ? "s" : "-",
7666 vb->tainted ? "t" : "-",
7667 vb->vb_safefor, buffer);
7668 }
7670}
7671
7672/** Print the value of a box as info messages
7673 *
7674 * @note Call directly from the debugger
7675 */
7676void fr_value_box_debug(FILE *fp, fr_value_box_t const *vb)
7677{
7678 _fr_value_box_debug(fp, vb, 0, -1);
7679}
static int const char char buffer[256]
Definition acutest.h:576
int const char * file
Definition acutest.h:702
va_end(args)
int n
Definition acutest.h:577
static int const char * fmt
Definition acutest.h:573
int const char int line
Definition acutest.h:702
va_start(args, fmt)
#define fr_base16_encode(_out, _in)
Definition base16.h:71
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:109
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:560
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:391
#define DIAG_ON(_x)
Definition build.h:535
#define SIZEOF_MEMBER(_t, _m)
Definition build.h:405
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:113
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define DIAG_OFF(_x)
Definition build.h:534
#define MEMCMP_FIELDS(_a, _b, _field, _len_field)
Return the comparison of two opaque fields of a structure.
Definition build.h:178
static fr_atomic_queue_t ** aq
static size_t min(size_t x, size_t y)
Definition dbuff.c:66
int fr_dbuff_trim_talloc(fr_dbuff_t *dbuff, size_t len)
Trim a talloced dbuff to the minimum length required to represent the contained string.
Definition dbuff.c:297
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:810
#define FR_DBUFF_OUT_UINT64V_RETURN(_num, _dbuff_or_marker, _len)
Read bytes from a dbuff or marker and interpret them as a network order unsigned integer.
Definition dbuff.h:1898
#define fr_dbuff_set(_dst, _src)
Set the 'current' position in a dbuff or marker using another dbuff or marker, a char pointer,...
Definition dbuff.h:1047
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition dbuff.h:387
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:941
#define FR_DBUFF_OUT_INT64V_RETURN(_num, _dbuff_or_marker, _len)
Read bytes from a dbuff or marker and interpret them as a network order unsigned integer.
Definition dbuff.h:1938
#define fr_dbuff_buff(_dbuff_or_marker)
Return the underlying buffer in a dbuff or one of marker.
Definition dbuff.h:925
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
Definition dbuff.h:1772
#define FR_DBUFF_MEMSET_RETURN(_dbuff_or_marker, _c, _inlen)
Set _inlen bytes of a dbuff or marker to _c returning if there is insufficient space.
Definition dbuff.h:1548
#define FR_DBUFF_OUT_MEMCPY_RETURN(_out, _dbuff_or_marker, _outlen)
Copy outlen bytes from the dbuff returning if there's insufficient data in the dbuff.
Definition dbuff.h:1792
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
Definition dbuff.h:1422
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition dbuff.h:1390
#define FR_DBUFF_IN_RETURN(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff returning if there is insufficient space.
Definition dbuff.h:1625
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition dbuff.h:230
#define FR_DBUFF_OUT_RETURN(_out, _dbuff_or_marker)
Copy data from a dbuff or marker to a fixed sized C type returning if there is insufficient data.
Definition dbuff.h:1858
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
Definition dbuff.h:444
#define FR_DBUFF_IN_BYTES_RETURN(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker returning if there's insufficient space.
Definition dbuff.h:1512
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:547
#define fr_fatal_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:229
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:254
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:222
#define da_is_length_field16(_da)
Definition dict.h:174
bool const fr_dict_attr_nested_allowed_chars[SBUFF_CHAR_CLASS]
Characters allowed in a nested dictionary attribute name.
Definition dict_util.c:63
static fr_slen_t err
Definition dict.h:904
static fr_dict_attr_t * fr_dict_attr_unknown_copy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Definition dict.h:608
#define da_is_length_field8(_da)
Definition dict.h:173
int fr_dict_protocol_reference(fr_dict_attr_t const **da_p, fr_dict_attr_t const *root, fr_sbuff_t *in)
Resolve a reference string to a dictionary attribute.
Definition dict_fixup.c:135
bool const fr_dict_enum_allowed_chars[SBUFF_CHAR_CLASS]
Characters that are allowed in dictionary enumeration value names.
Definition dict_util.c:71
fr_slen_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *in, fr_sbuff_term_t const *tt))
Resolve an attribute using an OID string.
Definition dict_util.c:2644
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Definition dict.h:635
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2720
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:281
char const * fr_dict_enum_name_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the name of an enum value in a fr_dict_attr_t.
Definition dict_util.c:3768
fr_slen_t fr_dict_attr_unknown_afrom_oid_substr(TALLOC_CTX *ctx, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *in, fr_type_t type))
Create a fr_dict_attr_t from an ASCII attribute and value.
@ FR_DICT_ATTR_EXT_REF
Attribute references another attribute and/or dictionary.
Definition dict.h:184
#define FR_DICT_ATTR_OID_PRINT_RETURN(...)
Definition dict.h:772
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3670
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3781
static fr_slen_t in
Definition dict.h:904
static int8_t fr_dict_attr_cmp(fr_dict_attr_t const *a, fr_dict_attr_t const *b)
Definition dict.h:676
Value of an enumerated attribute.
Definition dict.h:277
fr_dict_attr_ref_type_t type
The state of the reference.
Definition dict_ext.h:79
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:122
@ FR_DICT_ATTR_REF_ROOT
only for FR_TYPE_ATTR, point to the default root for enums
Definition dict_ext.h:66
Attribute extension - Holds a reference to an attribute in another dictionary.
Definition dict_ext.h:78
Test enumeration values.
Definition dict_test.h:92
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:360
uint32_t fr_hash(void const *data, size_t size)
Definition hash.c:866
free(array)
talloc_free(hp)
int fr_ipaddr_is_prefix(fr_ipaddr_t const *ipaddr)
Determine if an address is a prefix.
Definition inet.c:126
char * fr_inet_ntop_prefix(char out[static FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print a fr_ipaddr_t as a CIDR style network prefix.
Definition inet.c:1080
int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask)
Parse an IPv6 address or IPv6 prefix in presentation format (and others)
Definition inet.c:632
bool fr_hostname_lookups
hostname -> IP lookups?
Definition inet.c:52
int fr_inet_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
Definition inet.c:783
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition inet.c:62
char * fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print the address portion of a fr_ipaddr_t.
Definition inet.c:1025
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition inet.c:218
fr_cmp_ret_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition inet.c:1353
char * fr_inet_ifid_ntop(char *out, size_t outlen, uint8_t const *ifid)
Print an interface-id in standard colon notation.
Definition inet.c:1106
uint8_t * fr_inet_ifid_pton(uint8_t out[static 8], char const *ifid_str)
Convert interface-id in colon notation to 8 byte binary form.
Definition inet.c:1120
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition inet.h:69
int af
Address family.
Definition inet.h:64
uint8_t addr[6]
Ethernet address.
Definition inet.h:46
Struct to represent an ethernet address.
Definition inet.h:45
IPv4/6 prefix.
#define fr_multiply(_out, _a, _b)
Multiplies two integers together.
Definition math.h:176
static const uint8_t * zero
Definition md4.c:359
unsigned short uint16_t
#define SBUFF_CHAR_CLASS
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_VALUE_BOX
A boxed value.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned int uint32_t
int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask_bits)
long int ssize_t
fr_sbuff_err_t
@ FR_SBUFF_ERR_NOT_FOUND
@ FR_SBUFF_OK
unsigned char uint8_t
fr_sbuff_err_t fr_sbuff_out_unescape_until(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
ssize_t fr_slen_t
unsigned long int size_t
#define UINT8_MAX
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
fr_cmp_ret_t
Result of an ordering comparison.
Definition misc.h:50
@ CMP_ERR
comparison failed
Definition misc.h:51
void * memset_explicit(void *ptr, int ch, size_t len)
Definition missing.c:624
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition nbo.h:243
static uint64_t fr_nbo_to_uint64(uint8_t const data[static sizeof(uint64_t)])
Read an unsigned 64bit integer from wire format (big endian)
Definition nbo.h:177
static void fr_nbo_from_uint64(uint8_t out[static sizeof(uint64_t)], uint64_t num)
Write out an unsigned 64bit integer in wire format (big endian)
Definition nbo.h:72
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:860
#define fr_assert(_expr)
Definition rad_assert.h:37
static char * secret
static bool done
Definition radclient.c:80
static uint32_t mask
Definition rbmonkey.c:39
static char const * name
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static SBUFF_CHAR_CLASS], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
Definition sbuff.c:1936
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
Definition sbuff.c:444
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
Definition sbuff.c:1705
bool const sbuff_char_class_hex[SBUFF_CHAR_CLASS]
Definition sbuff.c:109
bool const sbuff_char_class_uint[SBUFF_CHAR_CLASS]
Definition sbuff.c:75
bool const sbuff_char_class_hostname[SBUFF_CHAR_CLASS]
Definition sbuff.c:97
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
Definition sbuff.c:2311
ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1553
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
Definition sbuff.c:2011
fr_sbuff_err_t fr_sbuff_out_bstrncpy(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max)
Copy as many bytes as possible from a sbuff to a sbuff.
Definition sbuff.c:755
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
Definition sbuff.c:2247
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_strcase_literal(_sbuff, _needle)
#define fr_sbuff_current(_sbuff_or_marker)
char chr
Character at the start of an escape sequence.
Definition sbuff.h:211
#define FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(...)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:190
char const * name
Name for rule set to aid we debugging.
Definition sbuff.h:209
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_extend(_sbuff_or_marker)
#define fr_sbuff_buff(_sbuff_or_marker)
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define fr_sbuff_is_digit(_sbuff_or_marker)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_out(_out, _in)
#define FR_SBUFF_IN_ESCAPE_RETURN(...)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SBUFF_CHAR_UNPRINTABLES_LOW
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
Definition sbuff.h:178
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Talloc sbuff extension structure.
Definition sbuff.h:137
Set of parsing rules for *unescape_until functions.
fr_slen_t fr_size_from_str(size_t *out, fr_sbuff_t *in)
Parse a size string with optional unit.
Definition size.c:40
fr_slen_t fr_size_to_str(fr_sbuff_t *out, size_t in)
Print a size string with unit.
Definition size.c:155
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:37
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
fr_aka_sim_id_type_t type
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition talloc.c:718
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
Definition talloc.c:446
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:618
#define talloc_get_type_abort_const
Definition talloc.h:117
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:288
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
fr_table_num_ordered_t const fr_time_precision_table[]
Definition time.c:46
fr_slen_t fr_time_delta_from_substr(fr_time_delta_t *out, fr_sbuff_t *in, fr_time_res_t hint, bool no_trailing, fr_sbuff_term_t const *tt)
Create fr_time_delta_t from a string.
Definition time.c:221
int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
Convert string in various formats to a fr_unix_time_t.
Definition time.c:824
int64_t fr_time_scale(int64_t t, fr_time_res_t hint)
Scale an input time to NSEC, clamping it at max / min.
Definition time.c:713
fr_slen_t fr_time_delta_to_str(fr_sbuff_t *out, fr_time_delta_t delta, fr_time_res_t res, bool is_unsigned)
Print fr_time_delta_t to a string with an appropriate suffix.
Definition time.c:454
fr_slen_t fr_unix_time_to_str(fr_sbuff_t *out, fr_unix_time_t time, fr_time_res_t res, bool utc)
Convert unix time to string.
Definition time.c:1159
int64_t const fr_time_multiplier_by_res[]
Definition time.c:32
static fr_time_delta_t fr_time_delta_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
Definition time.h:548
static int64_t fr_time_delta_to_integer(fr_time_delta_t delta, fr_time_res_t res)
Definition time.h:627
static fr_unix_time_t fr_unix_time_from_nsec(int64_t nsec)
Definition time.h:423
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
static int8_t fr_time_delta_cmp(fr_time_delta_t a, fr_time_delta_t b)
Compare two fr_time_delta_t values.
Definition time.h:930
#define fr_time_delta_isneg(_a)
Definition time.h:291
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_unix_time_wrap(_time)
Definition time.h:160
fr_time_res_t
The base resolution for print parse operations.
Definition time.h:48
@ FR_TIME_RES_NSEC
Definition time.h:60
@ FR_TIME_RES_SEC
Definition time.h:50
static fr_unix_time_t fr_unix_time_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
Definition time.h:411
#define NSEC
Definition time.h:379
static int8_t fr_unix_time_cmp(fr_unix_time_t a, fr_unix_time_t b)
Compare two fr_unix_time_t values.
Definition time.h:944
static uint64_t fr_unix_time_unwrap(fr_unix_time_t time)
Definition time.h:161
static int64_t fr_unix_time_to_integer(fr_unix_time_t delta, fr_time_res_t res)
Definition time.h:486
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
Definition token.c:224
enum fr_token fr_token_t
@ T_SINGLE_QUOTED_STRING
Definition token.h:120
@ T_BARE_WORD
Definition token.h:118
@ T_BACK_QUOTED_STRING
Definition token.h:121
@ T_OP_NE
Definition token.h:95
@ T_OP_REG_EQ
Definition token.h:100
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
@ T_OP_CMP_EQ
Definition token.h:104
@ T_OP_LE
Definition token.h:98
@ T_OP_GE
Definition token.h:96
@ T_OP_GT
Definition token.h:97
@ T_SOLIDUS_QUOTED_STRING
Definition token.h:122
@ T_OP_LT
Definition token.h:99
@ T_OP_REG_NE
Definition token.h:101
#define T_TOKEN_LAST
Definition token.h:127
static fr_slen_t head
Definition xlat.h:410
static fr_slen_t parent
Definition pair.h:860
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:581
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define FR_TYPE_VARIABLE_SIZE
Definition types.h:311
#define FR_TYPE_QUOTED
Definition types.h:312
#define FR_TYPE_STRUCTURAL_EXCEPT_GROUP
Definition types.h:315
#define fr_type_is_non_leaf(_x)
Definition types.h:394
@ FR_TYPE_VALUE_BOX_CURSOR
cursor over a fr_value_box_t
Definition types.h:88
@ FR_TYPE_UNION
A union of limited children.
Definition types.h:81
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:83
@ FR_TYPE_PAIR_CURSOR
cursor over a fr_pair_t
Definition types.h:90
#define fr_type_is_group(_x)
Definition types.h:376
#define fr_type_is_variable_size(_x)
Definition types.h:388
#define fr_type_is_structural(_x)
Definition types.h:392
#define FR_TYPE_INTERNAL
Definition types.h:319
#define FR_TYPE_NON_LEAF
Definition types.h:318
#define fr_type_is_fixed_size(_x)
Definition types.h:387
#define FR_TYPE_STRUCTURAL
Definition types.h:316
#define fr_type_is_ip(_x)
Definition types.h:385
#define FR_TYPE_INTEGER_EXCEPT_BOOL
Definition types.h:303
#define FR_TYPE_IP
Definition types.h:308
#define FR_TYPE_INTEGER
Definition types.h:304
#define fr_type_is_leaf(_x)
Definition types.h:393
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
#define FR_TYPE_NUMERIC
Definition types.h:306
#define FR_TYPE_FIXED_SIZE
Definition types.h:310
int fr_value_box_bstrndup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Definition value.c:4923
void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
Definition value.c:7381
fr_cmp_ret_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:761
void fr_value_box_memdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, bool tainted)
Assign a talloced buffer to a box, but don't copy it.
Definition value.c:5242
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
Definition value.c:151
fr_slen_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules)
Definition value.c:6141
int fr_value_box_hton(fr_value_box_t *dst, fr_value_box_t const *src)
Performs byte order reversal for types that need it.
Definition value.c:1321
size_t fr_value_box_network_length(fr_value_box_t const *value)
Get the size of the value held by the fr_value_box_t.
Definition value.c:1422
int fr_value_box_vasprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt, va_list ap)
Print a formatted string using our internal printf wrapper and assign it to a value box.
Definition value.c:4705
void fr_value_box_set_void_shallow(fr_value_box_t *dst, void const *ptr)
Assign a void pointer to a box.
Definition value.c:5270
static void _fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head, int depth)
Definition value.c:7616
#define INFO_INDENT(_fmt,...)
Definition value.c:7613
fr_sbuff_unescape_rules_t const fr_value_unescape_single
Definition value.c:290
void fr_value_box_mark_unsafe(fr_value_box_t *vb)
Mark a value-box as "unsafe".
Definition value.c:7409
int fr_value_box_strtrim(TALLOC_CTX *ctx, fr_value_box_t *vb)
Trim the length of the string buffer to match the length of the C string.
Definition value.c:4674
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition value.c:7205
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
Definition value.c:6178
fr_sbuff_escape_rules_t const fr_value_escape_double
Definition value.c:355
fr_sbuff_err_t fr_value_substr_unescape(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, char quote)
Convert a string value with escape sequences into its binary form.
Definition value.c:1291
fr_sbuff_parse_rules_t const value_parse_rules_single_3quoted
Definition value.c:585
static fr_slen_t fr_value_box_from_numeric_substr(fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules, bool tainted)
Convert integer encoded as string to a fr_value_box_t type.
Definition value.c:5370
fr_sbuff_escape_rules_t const fr_value_escape_backtick
Definition value.c:424
static int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to a string.
Definition value.c:2630
int fr_value_box_escape_erules(fr_value_box_t *vb, void *uctx)
Escape a value-box in place using the supplied fr_sbuff_escape_rules_t in uctx.
Definition value.c:7033
fr_sbuff_escape_rules_t const fr_value_escape_secret
Escape secret fields by simply mashing all data to '.
Definition value.c:386
fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted
Definition value.c:489
char * fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together hiding "secret" values.
Definition value.c:7154
#define O(_x, _y)
fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted
Definition value.c:564
#define VB_NAME
Definition value.c:7283
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition value.c:1905
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Pre-allocate an octets buffer for filling by the caller.
Definition value.c:5046
int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, bool tainted)
Copy a talloced buffer to a fr_value_box_t.
Definition value.c:5202
fr_sbuff_escape_rules_t const fr_value_escape_unprintables
Definition value.c:460
#define network_min_size(_x)
Sanity checks.
Definition value.c:105
int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated talloced buffer to a fr_value_box_t.
Definition value.c:4962
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3973
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
Definition value.c:4736
ssize_t fr_value_box_list_concat_as_octets(fr_value_box_safety_t *safety, fr_dbuff_t *dbuff, fr_value_box_list_t *list, uint8_t const *sep, size_t sep_len, fr_value_box_list_action_t proc_action, bool flatten)
Concatenate a list of value boxes together.
Definition value.c:6578
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
Definition value.c:611
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
Definition value.c:7104
int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
Definition value.c:5079
static size_t const fr_value_box_network_sizes[FR_TYPE_MAX+1][2]
Definition value.c:107
fr_sbuff_escape_rules_t const fr_value_escape_solidus
Definition value.c:403
static int fr_value_box_cast_to_float(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any value to a floating point value.
Definition value.c:3852
fr_sbuff_unescape_rules_t const * fr_value_unescape_by_quote[T_TOKEN_LAST]
Definition value.c:341
#define SIGN_BIT_HIGH(_int, _len)
size_t const fr_value_box_offsets[]
Where the value starts in the fr_value_box_t.
Definition value.c:193
static void _fr_value_box_debug(FILE *fp, fr_value_box_t const *vb, int depth, int idx)
Definition value.c:7634
#define CAST_IP_FIX_COMBO
Definition value.c:2807
fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted
Default formatting rules.
Definition value.c:485
static int fr_value_box_cast_to_ipv4addr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to an IPv4 address.
Definition value.c:2848
static const fr_value_box_ipaddr_sizes_t ipaddr_sizes[FR_TYPE_MAX]
Definition value.c:2274
int fr_value_box_escape_in_place_func(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_sbuff_escape_func_t escape)
Escape a value box in place using an sbuff escape function.
Definition value.c:7053
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4421
fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted
Definition value.c:493
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two attributes using an operator.
Definition value.c:1008
int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t const *escape, void *uctx)
Escape a list of value boxes in place.
Definition value.c:6913
int fr_value_box_bstrndup_replace(TALLOC_CTX *ctx, fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a copy of a ...
Definition value.c:4794
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted_char[SBUFF_CHAR_CLASS]
Definition value.c:521
uint64_t fr_value_box_as_uint64(fr_value_box_t const *vb)
Return a uint64_t from a fr_value_box_t.
Definition value.c:4273
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7569
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition value.c:4223
void fr_value_box_set_cursor_shallow(fr_value_box_t *dst, fr_type_t type, void *cursor, char const *name)
Definition value.c:5255
fr_sbuff_parse_rules_t const value_parse_rules_single_quoted
Definition value.c:558
static uint8_t const v4_v6_map[]
v4 to v6 mapping prefix
Definition value.c:2616
void fr_value_box_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a box, but don't copy it.
Definition value.c:5224
static void _value_box_safety_merge(fr_value_box_safety_t *out, fr_value_box_safety_t const *in)
Merge one safety into another.
Definition value.c:7464
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
Perform a shallow copy of a value_box.
Definition value.c:4545
static int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to octets.
Definition value.c:2690
void fr_value_box_increment(fr_value_box_t *vb)
Increment a boxed value.
Definition value.c:5316
fr_slen_t fr_value_box_from_substr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules)
Convert string value to a fr_value_box_t type.
Definition value.c:5469
void _fr_value_box_mark_safe_for(fr_value_box_t *vb, fr_value_box_safe_for_t safe_for)
Mark a value-box as "safe", of a particular type.
Definition value.c:7390
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4358
void fr_value_box_set_attr(fr_value_box_t *dst, fr_dict_attr_t const *da)
Definition value.c:5302
fr_sbuff_unescape_rules_t const fr_value_unescape_backtick
Definition value.c:322
void fr_value_box_verify(char const *file, int line, fr_value_box_t const *vb)
Validation function to check that a fr_value_box_t is correctly initialised.
Definition value.c:7289
void fr_value_box_set_secret(fr_value_box_t *box, bool secret)
Mark a box as holding a secret, or not.
Definition value.c:7519
fr_sbuff_parse_rules_t const * value_parse_rules_3quoted[T_TOKEN_LAST]
Definition value.c:627
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition value.c:4648
#define network_max_size(_x)
Definition value.c:106
#define COMPARE(_type)
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
Definition value.c:4774
void fr_value_box_safety_set(fr_value_box_t *box, fr_value_box_safety_t const *safety)
Replace the safety of a box.
Definition value.c:7508
fr_sbuff_unescape_rules_t const fr_value_unescape_double
Definition value.c:271
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
Definition value.c:6418
fr_sbuff_parse_rules_t const value_parse_rules_double_3quoted
Definition value.c:579
static int fr_value_box_cast_to_integer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any value to a signed or unsigned integer.
Definition value.c:3591
ssize_t fr_value_box_list_concat_as_string(fr_value_box_safety_t *safety, fr_sbuff_t *sbuff, fr_value_box_list_t *list, char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules, fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
Concatenate a list of value boxes together.
Definition value.c:6461
static int fr_value_box_cast_to_ipv6prefix(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to an IPv6 address.
Definition value.c:3191
ssize_t fr_value_box_from_memory(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, void const *src, size_t len)
Decode a fr_value_box_t from a C type in memory.
Definition value.c:2430
void fr_value_box_safety_copy_changed(fr_value_box_t *out, fr_value_box_t const *in)
Copy the safety values from one box to another.
Definition value.c:7452
int fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ipaddr_t const *ipaddr, bool tainted)
Assign a fr_value_box_t value from an fr_ipaddr_t.
Definition value.c:4307
static void _value_box_list_safety_merge(fr_value_box_t *out, fr_value_box_list_t const *list)
Merge the safety of every leaf box in a list into out.
Definition value.c:7530
static int fr_value_box_cidr_cmp_op(fr_token_t op, int bytes, uint8_t a_net, uint8_t const *a, uint8_t b_net, uint8_t const *b)
Definition value.c:885
static void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t const *src)
Copy flags and type data from one value box to another.
Definition value.c:643
void fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for)
Set the escaped flag for all value boxes in a list.
Definition value.c:7421
static int fr_value_box_fixed_size_from_octets(fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert octets to a fixed size value box value.
Definition value.c:2560
static int fr_value_box_cast_to_bool(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to a bool.
Definition value.c:3347
int fr_value_unbox_ipaddr(fr_ipaddr_t *dst, fr_value_box_t *src)
Unbox an IP address performing a type check.
Definition value.c:4339
int fr_value_box_escape_in_place_erules(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_sbuff_escape_rules_t const *erules)
Escape a value-box in place using sbuff escaping rules, and mark it safe-for.
Definition value.c:6967
fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted
Definition value.c:529
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
Merge safety results.
Definition value.c:7497
fr_sbuff_parse_rules_t const value_parse_rules_backtick_3quoted
Definition value.c:597
fr_sbuff_escape_rules_t const fr_value_escape_single
Definition value.c:393
static uint64_t const fr_value_box_integer_max[]
Definition value.c:231
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition value.c:4758
void fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head)
Print a list of value boxes as info messages.
Definition value.c:7629
fr_sbuff_parse_rules_t const * value_parse_rules_quoted_char[SBUFF_CHAR_CLASS]
Definition value.c:619
fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted
Definition value.c:497
#define RETURN(_type)
fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted
Definition value.c:570
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted[T_TOKEN_LAST]
Parse rules for non-quoted strings.
Definition value.c:513
static int fr_value_box_cast_to_ipv4prefix(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to an IPv6 address.
Definition value.c:2962
static int fr_value_box_cast_to_ethernet(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to an ethernet address.
Definition value.c:3289
void fr_value_box_safety_copy(fr_value_box_t *out, fr_value_box_t const *in)
Copy the safety values from one box to another.
Definition value.c:7439
fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted
Definition value.c:501
ssize_t fr_value_box_ipaddr_from_network(fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, int prefix_len, uint8_t const *data, size_t data_len, bool fixed, bool tainted)
Decode a fr_value_box_t of type IP address / prefix.
Definition value.c:2309
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted
Definition value.c:552
fr_sbuff_escape_rules_t const * erules
Definition value.c:6927
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Alloc and assign an empty \0 terminated string to a fr_value_box_t.
Definition value.c:4825
#define SIGN_PROMOTE(_int, _len)
fr_sbuff_parse_rules_t const value_parse_rules_solidus_3quoted
Definition value.c:591
static int _value_box_escape_rules(fr_value_box_t *vb, void *uctx)
Definition value.c:6930
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
Copy value data verbatim moving any buffers to the specified context.
Definition value.c:4579
static int fr_value_box_cast_unsupported(fr_type_t dst, fr_type_t src)
Definition value.c:2824
int fr_value_box_to_key(uint8_t **out, size_t *outlen, fr_value_box_t const *value)
Get a key from a value box.
Definition value.c:2497
void fr_value_box_flatten(TALLOC_CTX *ctx, fr_value_box_list_t *list, bool steal, bool free)
Removes a single layer of nesting, moving all children into the parent list.
Definition value.c:7079
static int8_t float_cmp(double a, double b)
Compare two floating point numbers for equality.
Definition value.c:707
int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
Do a full copy of a list of value boxes.
Definition value.c:7242
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4404
bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
Check to see if any list members (or their children) are tainted.
Definition value.c:7270
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
Encode a single value box, serializing its contents in generic network format.
Definition value.c:1508
void fr_value_box_list_safety_merge(fr_value_box_t *out, fr_value_box_list_t const *list)
Set the safety of out to the most restrictive safety of any leaf box in a list.
Definition value.c:7552
static int64_t const fr_value_box_integer_min[]
Definition value.c:251
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
Definition value.c:4858
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4899
int fr_value_box_memdup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Definition value.c:5165
fr_sbuff_unescape_rules_t const * fr_value_unescape_by_char[SBUFF_CHAR_CLASS]
Definition value.c:348
void fr_value_box_debug(FILE *fp, fr_value_box_t const *vb)
Print the value of a box as info messages.
Definition value.c:7676
int fr_regex_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two boxes using an operator.
Definition regex.c:1028
fr_sbuff_unescape_rules_t const fr_value_unescape_solidus
Definition value.c:301
fr_sbuff_escape_rules_t const * fr_value_escape_by_quote[T_TOKEN_LAST]
Definition value.c:446
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
Definition value.c:5007
static fr_dict_attr_t const * fr_value_box_attr_enumv(fr_dict_attr_t const *da)
Definition value.c:5276
int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t const *escape, void *uctx)
Escape a single value box in place.
Definition value.c:6857
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
Definition value.c:4986
static int fr_value_box_cast_to_ipv6addr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any supported type to an IPv6 address.
Definition value.c:3077
fr_sbuff_escape_rules_t const * fr_value_escape_by_char[SBUFF_CHAR_CLASS]
Definition value.c:453
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:5140
#define VB_NAME_LOCATION(_x)
Definition value.c:7284
fr_sbuff_err_t fr_value_str_unescape(size_t *len, fr_sbuff_t *out, fr_sbuff_t *in, size_t max, char quote)
Convert a string value with escape sequences into its binary form.
Definition value.c:1223
static int fr_value_box_cast_integer_to_integer(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert any signed or unsigned integer type to any other signed or unsigned integer type.
Definition value.c:3434
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
Definition value.c:6678
fr_value_box_list_action_t
Actions to perform when we process a box in a list.
Definition value.h:255
@ FR_VALUE_BOX_LIST_NONE
Do nothing to processed boxes.
Definition value.h:256
@ FR_VALUE_BOX_LIST_REMOVE
Remove the box from the input list.
Definition value.h:257
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:261
#define vb_should_free(_action)
Definition value.h:264
#define vb_ipv6addr
Definition value.h:289
#define vb_ether
Definition value.h:292
#define vb_date
Definition value.h:309
#define vb_int64
Definition value.h:304
#define vb_octets
Definition value.h:282
#define vb_should_free_value(_action)
Definition value.h:265
#define vb_should_remove(_action)
Definition value.h:266
#define vb_int32
Definition value.h:303
static int fr_value_box_memcpy_out(void *out, fr_value_box_t const *vb)
Copy the value of a value box to a field in a C struct.
Definition value.h:829
fr_value_box_safe_for_t safe_for
A unique value to indicate if that value box is safe for consumption by a particular module for a par...
Definition value.h:182
#define vb_int16
Definition value.h:302
#define fr_value_box_mark_safe_for(_box, _safe_for)
Definition value.h:1125
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define vb_uint8
Definition value.h:295
static fr_sbuff_err_t char size_t fr_sbuff_t size_t max
Definition value.h:1062
#define vb_length
Definition value.h:315
#define vb_int8
Definition value.h:301
static fr_slen_t data
Definition value.h:1367
static bool fr_value_box_contains_secret(fr_value_box_t const *box)
Definition value.h:1150
#define vb_float64
Definition value.h:307
unsigned int secret
Same as fr_dict_attr_flags_t secret.
Definition value.h:188
#define FR_VALUE_BOX_NET_ERROR
Special value to indicate fr_value_box_from_network experienced a general error.
Definition value.h:1079
static uint8_t * fr_value_box_raw(fr_value_box_t const *vb, fr_type_t type)
Return a pointer to the "raw" value from a value-box.
Definition value.h:805
#define fr_box_strvalue_len(_val, _len)
Definition value.h:334
#define FR_VALUE_BOX_MAGIC
Definition value.h:91
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:641
#define fr_value_box_is_safe_for(_box, _safe_for)
Definition value.h:1132
static fr_sbuff_err_t char ** out
Definition value.h:1062
static fr_sbuff_err_t char size_t * len
Definition value.h:1062
#define vb_ip
Definition value.h:287
fr_value_box_safe_for_t safe_for
Definition value.h:707
#define vb_uint16
Definition value.h:296
#define vb_bool
Definition value.h:294
#define vb_size
Definition value.h:311
#define FR_VALUE_BOX_SAFE_FOR_NONE
Definition value.h:172
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition value.h:162
#define vb_strvalue
Definition value.h:281
#define VALUE_BOX_VERIFY(_x)
Definition value.h:1389
#define vb_uint32
Definition value.h:297
int nonnull(2, 5))
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:680
#define vb_ifid
Definition value.h:291
#define vb_attr
Definition value.h:285
#define vb_time_delta
Definition value.h:313
fr_value_box_escape_func_t func
Definition value.h:706
static always_inline int fr_value_box_ethernet_addr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ethernet_t const *src, bool tainted)
Definition value.h:888
#define vb_ipv4addr
Definition value.h:288
#define vb_float32
Definition value.h:306
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:635
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:247
#define FR_VALUE_BOX_NET_OOM
Special value to indicate fr_value_box_from_network hit an out of memory error.
Definition value.h:1083
#define vb_uint64
Definition value.h:298
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
The safety of a value.
Definition value.h:181