The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
45 RCSID("$Id: 08af6a1f8107fbd3f9ff4da0aa1153bb501a86f9 $")
46 
47 #define _VALUE_PRIVATE
48 #include <freeradius-devel/util/value.h>
49 #undef _VALUE_PRIVATE
50 
51 #include <freeradius-devel/util/atexit.h>
52 #include <freeradius-devel/util/base16.h>
53 #include <freeradius-devel/util/dcursor.h>
54 #include <freeradius-devel/util/size.h>
55 #include <freeradius-devel/util/time.h>
56 
57 #include <math.h>
58 
59 /** Sanity checks
60  *
61  * There should never be an instance where these fail.
62  */
63 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ip.addr.v4.s_addr) == 4,
64  "in_addr.s_addr has unexpected length");
65 static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ip.addr.v6.s6_addr) == 16,
66  "in6_addr.s6_addr has unexpected length");
68  "vb_ifid has unexpected length");
70  "vb_ether has unexpected length");
71 
72 static_assert(SIZEOF_MEMBER(fr_value_box_t, datum.boolean) == 1,
73  "datum.boolean has unexpected length");
75  "vb_uint8 has unexpected length");
77  "vb_uint16 has unexpected length");
79  "vb_uint32 has unexpected length");
81  "vb_uint64 has unexpected length");
82 
84  "vb_int16 has unexpected length");
86  "vb_int16 has unexpected length");
88  "vb_int32 has unexpected length");
90  "vb_int64 has unexpected length");
91 
93  "vb_float32 has unexpected length");
95  "vb_float64 has unexpected length");
96 
97 /** How many bytes on-the-wire would a #fr_value_box_t value consume
98  *
99  * This is for the generic NETWORK format. For field sizes in the in-memory
100  * structure use #fr_value_box_field_sizes.
101  *
102  * @note Don't use this array directly when determining the length
103  * that would be consumed by the on-the-wire representation.
104  * Use #fr_value_box_network_length instead, as that deals with variable
105  * length attributes too.
106  */
107 #define network_min_size(_x) (fr_value_box_network_sizes[_x][0])
108 #define network_max_size(_x) (fr_value_box_network_sizes[_x][1])
109 static size_t const fr_value_box_network_sizes[FR_TYPE_MAX + 1][2] = {
110  [FR_TYPE_NULL] = {~0, 0},
111 
112  [FR_TYPE_STRING] = {0, ~0},
113  [FR_TYPE_OCTETS] = {0, ~0},
114 
115  [FR_TYPE_IPV4_ADDR] = {4, 4},
116  [FR_TYPE_IPV4_PREFIX] = {5, 5},
117  [FR_TYPE_IPV6_ADDR] = {16, 17},
118  [FR_TYPE_IPV6_PREFIX] = {17, 18},
119  [FR_TYPE_COMBO_IP_ADDR] = {4, 17},
120  [FR_TYPE_COMBO_IP_PREFIX] = {16, 18},
121  [FR_TYPE_IFID] = {8, 8},
122  [FR_TYPE_ETHERNET] = {6, 6},
123 
124  [FR_TYPE_BOOL] = {1, 1},
125  [FR_TYPE_UINT8] = {1, 1},
126  [FR_TYPE_UINT16] = {2, 2},
127  [FR_TYPE_UINT32] = {4, 4},
128  [FR_TYPE_UINT64] = {8, 8},
129 
130  [FR_TYPE_INT8] = {1, 1},
131  [FR_TYPE_INT16] = {2, 2},
132  [FR_TYPE_INT32] = {4, 4},
133  [FR_TYPE_INT64] = {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_MAX] = {~0, 0} //!< Ensure array covers all types.
142 };
143 
144 /** How many bytes wide each of the value data fields are
145  *
146  * This is useful when copying a value from a fr_value_box_t to a memory
147  * location passed as a void *.
148  */
149 size_t const fr_value_box_field_sizes[] = {
152 
161 
162  [FR_TYPE_BOOL] = SIZEOF_MEMBER(fr_value_box_t, datum.boolean),
167 
172 
175 
177 
178  [FR_TYPE_TIME_DELTA] = SIZEOF_MEMBER(fr_value_box_t, datum.time_delta),
179  [FR_TYPE_SIZE] = SIZEOF_MEMBER(fr_value_box_t, datum.size),
180 
181  [FR_TYPE_VALUE_BOX] = sizeof(fr_value_box_t),
182 
183  [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
184 };
185 
186 /** Where the value starts in the #fr_value_box_t
187  *
188  */
189 size_t const fr_value_box_offsets[] = {
191  [FR_TYPE_OCTETS] = offsetof(fr_value_box_t, vb_octets),
192 
193  [FR_TYPE_IPV4_ADDR] = offsetof(fr_value_box_t, vb_ip),
195  [FR_TYPE_IPV6_ADDR] = offsetof(fr_value_box_t, vb_ip),
199  [FR_TYPE_IFID] = offsetof(fr_value_box_t, vb_ifid),
201 
202  [FR_TYPE_BOOL] = offsetof(fr_value_box_t, vb_bool),
203  [FR_TYPE_UINT8] = offsetof(fr_value_box_t, vb_uint8),
204  [FR_TYPE_UINT16] = offsetof(fr_value_box_t, vb_uint16),
205  [FR_TYPE_UINT32] = offsetof(fr_value_box_t, vb_uint32),
206  [FR_TYPE_UINT64] = offsetof(fr_value_box_t, vb_uint64),
207 
208  [FR_TYPE_INT8] = offsetof(fr_value_box_t, vb_int8),
209  [FR_TYPE_INT16] = offsetof(fr_value_box_t, vb_int16),
210  [FR_TYPE_INT32] = offsetof(fr_value_box_t, vb_int32),
211  [FR_TYPE_INT64] = offsetof(fr_value_box_t, vb_int64),
212 
215 
216  [FR_TYPE_DATE] = offsetof(fr_value_box_t, vb_date),
217 
219  [FR_TYPE_SIZE] = offsetof(fr_value_box_t, vb_size),
220 
221  [FR_TYPE_VALUE_BOX] = 0,
222 
223  [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
224 };
225 
226 static uint64_t const fr_value_box_integer_max[] = {
227  [FR_TYPE_BOOL] = true,
229  [FR_TYPE_UINT16] = UINT16_MAX,
230  [FR_TYPE_UINT32] = UINT32_MAX,
231  [FR_TYPE_UINT64] = UINT64_MAX,
232 
233  [FR_TYPE_INT8] = INT8_MAX,
234  [FR_TYPE_INT16] = INT16_MAX,
235  [FR_TYPE_INT32] = INT32_MAX,
236  [FR_TYPE_INT64] = INT64_MAX,
237 
238  [FR_TYPE_DATE] = UINT64_MAX,
239  [FR_TYPE_TIME_DELTA] = INT64_MAX,
240 
241  [FR_TYPE_SIZE] = SIZE_MAX,
242 
243  [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
244 };
245 
246 static int64_t const fr_value_box_integer_min[] = {
247  [FR_TYPE_BOOL] = false,
248  [FR_TYPE_UINT8] = 0,
249  [FR_TYPE_UINT16] = 0,
250  [FR_TYPE_UINT32] = 0,
251  [FR_TYPE_UINT64] = 0,
252 
253  [FR_TYPE_INT8] = INT8_MIN,
254  [FR_TYPE_INT16] = INT16_MIN,
255  [FR_TYPE_INT32] = INT32_MIN,
256  [FR_TYPE_INT64] = INT64_MIN,
257 
258  [FR_TYPE_DATE] = 0,
259  [FR_TYPE_TIME_DELTA] = INT64_MIN,
260 
261  [FR_TYPE_SIZE] = 0,
262 
263  [FR_TYPE_MAX] = 0 //!< Ensure array covers all types.
264 };
265 
267  .name = "double",
268  .chr = '\\',
269  .subs = {
270  ['"'] = '"', /* Quoting char */
271  ['%'] = '%', /* xlat expansions */
272  ['\\'] = '\\',
273  ['a'] = '\a',
274  ['b'] = '\b',
275  ['e'] = '\\',
276  ['n'] = '\n',
277  ['r'] = '\r',
278  ['t'] = '\t',
279  ['v'] = '\v'
280  },
281  .do_hex = true,
282  .do_oct = true
283 };
284 
286  .name = "single",
287  .chr = '\\',
288  .subs = {
289  ['\''] = '\'', /* Quoting char */
290  ['\\'] = '\\'
291  },
292  .do_hex = false,
293  .do_oct = false
294 };
295 
297  .name = "solidus",
298  .chr = '\\',
299  .subs = {
300  ['%'] = '%', /* xlat expansions */
301  ['/'] = '/', /* Quoting char */
302  ['a'] = '\a',
303  ['b'] = '\b',
304  ['e'] = '\\',
305  ['n'] = '\n',
306  ['r'] = '\r',
307  ['t'] = '\t',
308  ['v'] = '\v'
309  },
310  .skip = {
311  ['\\'] = '\\' /* Leave this for the regex library */
312  },
313  .do_hex = true,
314  .do_oct = true
315 };
316 
318  .name = "backtick",
319  .chr = '\\',
320  .subs = {
321  ['%'] = '%', /* xlat expansions */
322  ['\\'] = '\\',
323  ['`'] = '`', /* Quoting char */
324  ['a'] = '\a',
325  ['b'] = '\b',
326  ['e'] = '\\',
327  ['n'] = '\n',
328  ['r'] = '\r',
329  ['t'] = '\t',
330  ['v'] = '\v'
331  },
332  .do_hex = true,
333  .do_oct = true
334 };
335 
341 };
342 
344  ['"'] = &fr_value_unescape_double,
345  ['\''] = &fr_value_unescape_single,
346  ['/'] = &fr_value_unescape_solidus,
348 };
349 
351  .name = "double",
352  .chr = '\\',
353  .subs = {
354  ['"'] = '"', /* Quoting char */
355  ['%'] = '%', /* xlat expansions */
356  ['\\'] = '\\',
357  ['\a'] = 'a',
358  ['\b'] = 'b',
359  ['\n'] = 'n',
360  ['\r'] = 'r',
361  ['\t'] = 't',
362  ['\v'] = 'v'
363  },
364  .esc = {
367  },
368  .do_utf8 = true,
369  .do_oct = true
370 };
371 
372 #ifdef __clang__
373 #pragma clang diagnostic ignored "-Wgnu-designator"
374 #endif
375 
376 /** Escape secret fields by simply mashing all data to '.'
377  *
378  * The length of the secret still leaks, but that is likely fine. Fixing that is more work.
379  *
380  */
382  .name = "secret",
383  .subs = {
384  [ 0 ... 255 ] = '.',
385  },
386 };
387 
389  .name = "single",
390  .chr = '\\',
391  .subs = {
392  ['\''] = '\'', /* Quoting char */
393  ['\\'] = '\\'
394  },
395  .do_utf8 = true,
396 };
397 
399  .name = "solidus",
400  .chr = '\\',
401  .subs = {
402  ['%'] = '%', /* xlat expansions */
403  ['/'] = '/', /* Quoting char */
404  ['\a'] = 'a',
405  ['\b'] = 'b',
406  ['\n'] = 'n',
407  ['\r'] = 'r',
408  ['\t'] = 't',
409  ['\v'] = 'v'
410  },
411  .esc = {
414  },
415  .do_utf8 = true,
416  .do_oct = true
417 };
418 
420  .name = "backtick",
421  .chr = '\\',
422  .subs = {
423  ['%'] = '%', /* xlat expansions */
424  ['\\'] = '\\',
425  ['`'] = '`', /* Quoting char */
426  ['\a'] = 'a',
427  ['\b'] = 'b',
428  ['\n'] = 'n',
429  ['\r'] = 'r',
430  ['\t'] = 't',
431  ['\v'] = 'v'
432  },
433  .esc = {
436  },
437  .do_utf8 = true,
438  .do_oct = true
439 };
440 
446 };
447 
449  ['"'] = &fr_value_escape_double,
450  ['\''] = &fr_value_escape_single,
451  ['/'] = &fr_value_escape_solidus,
452  ['`'] = &fr_value_escape_backtick,
453 };
454 
456  .name = "unprintables",
457  .chr = '\\',
458  .subs = {
459  ['\\'] = '\\',
460  },
461  .esc = {
464  },
465  .do_utf8 = true,
466  .do_oct = true
467 };
468 
469 
470 /** @name Produce a #tmpl_t from a string or substring
471  *
472  * @{
473  */
474 
475 /* clang-format off */
476 /** Default formatting rules
477  *
478  * Control token termination, escaping and how the tmpl is printed.
479  */
480 fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted = {
481 
482 };
483 
484 fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted = {
485  .escapes = &fr_value_unescape_double
486 };
487 
488 fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted = {
489  .escapes = &fr_value_unescape_single
490 };
491 
492 fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted = {
493  .escapes = &fr_value_unescape_solidus
494 };
495 
496 fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted = {
497  .escapes = &fr_value_unescape_backtick
498 };
499 
500 /** Parse rules for non-quoted strings
501  *
502  * These parse rules should be used for processing escape sequences in
503  * data from external data sources like SQL databases and REST APIs.
504  *
505  * They do not include terminals to stop parsing as it assumes the values
506  * are discrete, and not wrapped in quotes.
507  */
508 fr_sbuff_parse_rules_t const *value_parse_rules_unquoted[T_TOKEN_LAST] = {
514 };
515 
516 fr_sbuff_parse_rules_t const *value_parse_rules_unquoted_char[UINT8_MAX] = {
522 };
523 
524 fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted = {
525  .escapes = &(fr_sbuff_unescape_rules_t){
526  .chr = '\\',
527  /*
528  * Allow barewords to contain whitespace
529  * if they're escaped.
530  */
531  .subs = {
532  ['\t'] = '\t',
533  ['\n'] = '\n',
534  [' '] = ' '
535  },
536  .do_hex = false,
537  .do_oct = false
538  },
539  .terminals = &FR_SBUFF_TERMS(
540  L(""),
541  L("\t"),
542  L("\n"),
543  L(" ")
544  )
545 };
546 
547 fr_sbuff_parse_rules_t const value_parse_rules_double_quoted = {
548  .escapes = &fr_value_unescape_double,
549  .terminals = &FR_SBUFF_TERMS(
550  L(""), L("\n"), L("\r"), L("\""))
551 };
552 
553 fr_sbuff_parse_rules_t const value_parse_rules_single_quoted = {
554  .escapes = &fr_value_unescape_single,
555  .terminals = &FR_SBUFF_TERMS(
556  L(""), L("\n"), L("\r"), L("'"))
557 };
558 
559 fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted = {
560  .escapes = &fr_value_unescape_solidus,
561  .terminals = &FR_SBUFF_TERMS(
562  L(""), L("\n"), L("\r"), L("/"))
563 };
564 
565 fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted = {
566  .escapes = &fr_value_unescape_backtick,
567  .terminals = &FR_SBUFF_TERMS(
568  L(""), L("\n"), L("\r"), L("`"))
569 };
570 
571 /*
572  * And triple-quoted versions of the above.
573  */
574 fr_sbuff_parse_rules_t const value_parse_rules_double_3quoted = {
575  .escapes = &fr_value_unescape_double,
576  .terminals = &FR_SBUFF_TERMS(
577  L(""), L("\n"), L("\r"), L("\"\"\""))
578 };
579 
580 fr_sbuff_parse_rules_t const value_parse_rules_single_3quoted = {
581  .escapes = &fr_value_unescape_single,
582  .terminals = &FR_SBUFF_TERMS(
583  L(""), L("\n"), L("\r"), L("'''"))
584 };
585 
586 fr_sbuff_parse_rules_t const value_parse_rules_solidus_3quoted = {
587  .escapes = &fr_value_unescape_solidus,
588  .terminals = &FR_SBUFF_TERMS(
589  L(""), L("\n"), L("\r"), L("///"))
590 };
591 
592 fr_sbuff_parse_rules_t const value_parse_rules_backtick_3quoted = {
593  .escapes = &fr_value_unescape_backtick,
594  .terminals = &FR_SBUFF_TERMS(
595  L(""), L("\n"), L("\r"), L("```"))
596 };
597 
598 /** Parse rules for quoted strings
599  *
600  * These parse rules should be used for internal parsing functions that
601  * are working with configuration files.
602  *
603  * They include appropriate quote terminals to force functions parsing
604  * quoted strings to return when they reach a quote character.
605  */
606 fr_sbuff_parse_rules_t const *value_parse_rules_quoted[T_TOKEN_LAST] = {
612 };
613 
614 fr_sbuff_parse_rules_t const *value_parse_rules_quoted_char[UINT8_MAX] = {
620 };
621 
622 fr_sbuff_parse_rules_t const *value_parse_rules_3quoted[T_TOKEN_LAST] = {
628 };
629 
630 /* clang-format on */
631 /** @} */
632 
633 /** Copy flags and type data from one value box to another
634  *
635  * @param[in] dst to copy flags to
636  * @param[in] src of data.
637  */
638 static inline void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t const *src)
639 {
640  switch (src->type) {
642  dst->vb_length = src->vb_length;
643  break;
644  /*
645  * Not 100% sure this should be done here
646  * but if the intent is to make a null
647  * box usable, then we need to do this
648  * somewhere.
649  */
650  case FR_TYPE_GROUP:
651  fr_value_box_list_init(&dst->vb_group);
652  break;
653 
654  default:
655  break;
656  }
657 
658  dst->enumv = src->enumv;
659  dst->type = src->type;
660  dst->tainted = src->tainted;
661  dst->safe_for = src->safe_for;
662  dst->secret = src->secret;
663  fr_value_box_list_entry_init(dst);
664 }
665 
666 /** Compare two values
667  *
668  * @param[in] a Value to compare.
669  * @param[in] b Value to compare.
670  * @return
671  * - -1 if a is less than b.
672  * - 0 if both are equal.
673  * - 1 if a is more than b.
674  * - < -1 on failure.
675  */
677 {
678  if (!fr_cond_assert(a->type != FR_TYPE_NULL)) return -1;
679  if (!fr_cond_assert(b->type != FR_TYPE_NULL)) return -1;
680 
681  if (a->type != b->type) {
682  fr_strerror_printf("%s: Can't compare values of different types", __FUNCTION__);
683  return -2;
684  }
685 
686  /*
687  * After doing the previous check for special comparisons,
688  * do the per-type comparison here.
689  */
690  switch (a->type) {
692  {
693  size_t length;
694 
695  if (a->vb_length < b->vb_length) {
696  length = a->vb_length;
697  } else {
698  length = b->vb_length;
699  }
700 
701  if (length) {
702  int cmp;
703 
704  /*
705  * Use constant-time comparisons for secret values.
706  */
707  if (a->secret || b->secret) {
708  cmp = fr_digest_cmp(a->datum.ptr, b->datum.ptr, length);
709  } else {
710  cmp = memcmp(a->datum.ptr, b->datum.ptr, length);
711  }
712  if (cmp != 0) return CMP(cmp, 0);
713  }
714 
715  /*
716  * Contents are the same. The return code
717  * is therefore the difference in lengths.
718  *
719  * i.e. "0x00" is smaller than "0x0000"
720  */
721  return CMP(a->vb_length, b->vb_length);
722  }
723 
724  /*
725  * Short-hand for simplicity.
726  */
727 #define RETURN(_type) return CMP(a->datum._type, b->datum._type)
728 #define COMPARE(_type) return CMP(memcmp(&a->datum._type, &b->datum._type, sizeof(a->datum._type)), 0)
729 
730  case FR_TYPE_BOOL:
731  RETURN(boolean);
732 
733  case FR_TYPE_DATE:
734  return fr_unix_time_cmp(a->datum.date, b->datum.date);
735 
736  case FR_TYPE_UINT8:
737  RETURN(uint8);
738 
739  case FR_TYPE_UINT16:
740  RETURN(uint16);
741 
742  case FR_TYPE_UINT32:
743  RETURN(uint32);
744 
745  case FR_TYPE_UINT64:
746  RETURN(uint64);
747 
748  case FR_TYPE_INT8:
749  RETURN(int8);
750 
751  case FR_TYPE_INT16:
752  RETURN(int16);
753 
754  case FR_TYPE_INT32:
755  RETURN(int32);
756 
757  case FR_TYPE_INT64:
758  RETURN(int64);
759 
760  case FR_TYPE_SIZE:
761  RETURN(size);
762 
763  case FR_TYPE_TIME_DELTA:
764  return fr_time_delta_cmp(a->datum.time_delta, b->datum.time_delta);
765 
766  case FR_TYPE_FLOAT32:
767  RETURN(float32);
768 
769  case FR_TYPE_FLOAT64:
770  RETURN(float64);
771 
772  case FR_TYPE_ETHERNET:
773  COMPARE(ether);
774 
777  case FR_TYPE_IPV4_ADDR:
778  case FR_TYPE_IPV4_PREFIX:
779  case FR_TYPE_IPV6_ADDR:
780  case FR_TYPE_IPV6_PREFIX:
781  return fr_ipaddr_cmp(&a->vb_ip, &b->vb_ip);
782 
783  case FR_TYPE_IFID:
784  COMPARE(ifid);
785 
786  /*
787  * These should be handled at some point
788  */
789  case FR_TYPE_NON_LEAF:
790  (void)fr_cond_assert(0); /* unknown type */
791  return -2;
792 
793  /*
794  * Do NOT add a default here, as new types are added
795  * static analysis will warn us they're not handled
796  */
797  }
798  return 0;
799 }
800 
801 /*
802  * We leverage the fact that IPv4 and IPv6 prefixes both
803  * have the same format:
804  *
805  * reserved, prefix-len, data...
806  */
807 static int fr_value_box_cidr_cmp_op(fr_token_t op, int bytes,
808  uint8_t a_net, uint8_t const *a,
809  uint8_t b_net, uint8_t const *b)
810 {
811  int i, common;
812  uint32_t mask;
813 
814  /*
815  * Handle the case of netmasks being identical.
816  */
817  if (a_net == b_net) {
818  int compare;
819 
820  compare = memcmp(a, b, bytes);
821 
822  /*
823  * If they're identical return true for
824  * identical.
825  */
826  if ((compare == 0) &&
827  ((op == T_OP_CMP_EQ) ||
828  (op == T_OP_LE) ||
829  (op == T_OP_GE))) {
830  return true;
831  }
832 
833  /*
834  * Everything else returns false.
835  *
836  * 10/8 == 24/8 --> false
837  * 10/8 <= 24/8 --> false
838  * 10/8 >= 24/8 --> false
839  */
840  return false;
841  }
842 
843  /*
844  * Netmasks are different. That limits the
845  * possible results, based on the operator.
846  */
847  switch (op) {
848  case T_OP_CMP_EQ:
849  return false;
850 
851  case T_OP_NE:
852  return true;
853 
854  case T_OP_LE:
855  case T_OP_LT: /* 192/8 < 192.168/16 --> false */
856  if (a_net < b_net) {
857  return false;
858  }
859  break;
860 
861  case T_OP_GE:
862  case T_OP_GT: /* 192/16 > 192.168/8 --> false */
863  if (a_net > b_net) {
864  return false;
865  }
866  break;
867 
868  default:
869  return false;
870  }
871 
872  if (a_net < b_net) {
873  common = a_net;
874  } else {
875  common = b_net;
876  }
877 
878  /*
879  * Do the check uint8 by uint8. If the bytes are
880  * identical, it MAY be a match. If they're different,
881  * it is NOT a match.
882  */
883  i = 0;
884  while (i < bytes) {
885  /*
886  * All leading bytes are identical.
887  */
888  if (common == 0) return true;
889 
890  /*
891  * Doing bitmasks takes more work.
892  */
893  if (common < 8) break;
894 
895  if (a[i] != b[i]) return false;
896 
897  common -= 8;
898  i++;
899  continue;
900  }
901 
902  mask = 1;
903  mask <<= (8 - common);
904  mask--;
905  mask = ~mask;
906 
907  if ((a[i] & mask) == ((b[i] & mask))) {
908  return true;
909  }
910 
911  return false;
912 }
913 
914 /*
915  * So we don't have to include <util/regex.h> in a recursive fashion.
916  */
917 extern int fr_regex_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b);
918 
919 /** Compare two attributes using an operator
920  *
921  * @param[in] op to use in comparison.
922  * @param[in] a Value to compare.
923  * @param[in] b Value to compare.
924  * @return
925  * - 1 if true
926  * - 0 if false
927  * - -1 on failure.
928  */
930 {
931  int compare = 0;
932 
933  if (!fr_cond_assert(a->type != FR_TYPE_NULL)) return -1;
934  if (!fr_cond_assert(b->type != FR_TYPE_NULL)) return -1;
935 
936  if (unlikely((op == T_OP_REG_EQ) || (op == T_OP_REG_NE))) return fr_regex_cmp_op(op, a, b);
937 
938  switch (a->type) {
939  case FR_TYPE_IPV4_ADDR:
940  switch (b->type) {
942  if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
943  FALL_THROUGH;
944 
945  case FR_TYPE_IPV4_ADDR: /* IPv4 and IPv4 */
946  goto cmp;
947 
949  if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
950  FALL_THROUGH;
951 
952  case FR_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
953  return fr_value_box_cidr_cmp_op(op, 4, 32, (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
954  b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v4.s_addr);
955 
956  default:
957  fail_cmp_v4:
958  fr_strerror_const("Cannot compare IPv4 with IPv6 address");
959  return -1;
960  }
961 
962  case FR_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
963  cmp_prefix_v4:
964  switch (b->type) {
966  if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
967  FALL_THROUGH;
968 
969  case FR_TYPE_IPV4_ADDR:
970  return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
971  (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
972  32, (uint8_t const *) &b->vb_ip.addr.v4);
973 
975  if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
976  FALL_THROUGH;
977 
978  case FR_TYPE_IPV4_PREFIX: /* IPv4 Prefix and IPv4 Prefix */
979  return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
980  (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
981  b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v4.s_addr);
982 
983  default:
984  fr_strerror_const("Cannot compare IPv4 with IPv6 address");
985  return -1;
986  }
987 
988  case FR_TYPE_IPV6_ADDR:
989  switch (b->type) {
991  if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
992  FALL_THROUGH;
993 
994  case FR_TYPE_IPV6_ADDR: /* IPv6 and IPv6 */
995  goto cmp;
996 
998  if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
999  FALL_THROUGH;
1000 
1001  case FR_TYPE_IPV6_PREFIX: /* IPv6 and IPv6 Preifx */
1002  return fr_value_box_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->vb_ip.addr.v6,
1003  b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1004 
1005  default:
1006  fail_cmp_v6:
1007  fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1008  return -1;
1009  }
1010 
1011  case FR_TYPE_IPV6_PREFIX:
1012  cmp_prefix_v6:
1013  switch (b->type) {
1014  case FR_TYPE_COMBO_IP_ADDR:
1015  if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1016  FALL_THROUGH;
1017 
1018  case FR_TYPE_IPV6_ADDR: /* IPv6 Prefix and IPv6 */
1019  return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1020  (uint8_t const *) &a->vb_ip.addr.v6,
1021  128, (uint8_t const *) &b->vb_ip.addr.v6);
1022 
1024  if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1025  FALL_THROUGH;
1026 
1027  case FR_TYPE_IPV6_PREFIX: /* IPv6 Prefix and IPv6 */
1028  return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1029  (uint8_t const *) &a->vb_ip.addr.v6,
1030  b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1031 
1032  default:
1033  fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1034  return -1;
1035  }
1036 
1037  case FR_TYPE_COMBO_IP_ADDR:
1038  if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1039 
1040  goto cmp;
1041 
1043  if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1044 
1045  if (a->vb_ip.af == AF_INET) goto cmp_prefix_v4;
1046 
1047  goto cmp_prefix_v6;
1048 
1049  default:
1050  cmp:
1051  compare = fr_value_box_cmp(a, b);
1052  if (compare < -1) { /* comparison error */
1053  return -1;
1054  }
1055  }
1056 
1057  /*
1058  * Now do the operator comparison.
1059  */
1060  switch (op) {
1061  case T_OP_CMP_EQ:
1062  return (compare == 0);
1063 
1064  case T_OP_NE:
1065  return (compare != 0);
1066 
1067  case T_OP_LT:
1068  return (compare < 0);
1069 
1070  case T_OP_GT:
1071  return (compare > 0);
1072 
1073  case T_OP_LE:
1074  return (compare <= 0);
1075 
1076  case T_OP_GE:
1077  return (compare >= 0);
1078 
1079  default:
1080  return 0;
1081  }
1082 }
1083 
1084 /** Convert a string value with escape sequences into its binary form
1085  *
1086  * The quote character determines the escape sequences recognised.
1087  *
1088  * - Literal mode ("'" quote char) will unescape:
1089  @verbatim
1090  - \\ - Literal backslash.
1091  - <quote> - The quotation char.
1092  @endverbatim
1093  * - Expanded mode ('"' quote char) will also unescape:
1094  @verbatim
1095  - \a - Alert.
1096  - \b - Backspace.
1097  - \e - Escape character i.e. (\‍)
1098  - \r - Carriage return.
1099  - \n - Newline.
1100  - \t - Tab.
1101  - \v - Vertical tab
1102  - <oct> - An octal escape sequence.
1103  - \x<hex> - A hex escape sequence.
1104  @endverbatim
1105  * - Backtick mode ('`' quote char) identical to expanded mode.
1106  * - Regex mode ('/') identical to expanded mode but two successive
1107  * backslashes will be interpreted as an escape sequence, but not
1108  * unescaped, so that they will be passed to the underlying regex
1109  * library.
1110  * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1111  *
1112  * @note The resulting output may contain embedded \0s.
1113  * @note Unrecognised escape sequences will be copied verbatim.
1114  * @note In and out may point to the same underlying buffer.
1115  * @note Copying will stop early if an unescaped instance of the
1116  * quoting char is found in the input buffer.
1117  *
1118  * @param[out] out Where to write the unescaped string.
1119  * @param[in] in The string to unescape.
1120  * @param[in] inlen Length of input string. Pass SIZE_MAX to copy all data
1121  * in the input buffer.
1122  * @param[in] quote Character around the string, determines unescaping mode.
1123  *
1124  * @return
1125  * - 0 if input string was empty.
1126  * - >0 the number of bytes written to out.
1127  */
1128 size_t fr_value_str_unescape(fr_sbuff_t *out, fr_sbuff_t *in, size_t inlen, char quote)
1129 {
1130  switch (quote) {
1131  default:
1132  break;
1133 
1134  case '"':
1135  {
1137  }
1138  case '\'':
1139  {
1141  }
1142 
1143  case '`':
1144  {
1146  }
1147 
1148  case '/':
1149  {
1151  }
1152  }
1153 
1154  return fr_sbuff_out_bstrncpy(out, in, inlen);
1155 }
1156 
1157 /** Convert a string value with escape sequences into its binary form
1158  *
1159  * The quote character determines the escape sequences recognised.
1160  *
1161  * - Literal mode ("'" quote char) will unescape:
1162  @verbatim
1163  - \\ - Literal backslash.
1164  - <quote> - The quotation char.
1165  @endverbatim
1166  * - Expanded mode ('"' quote char) will also unescape:
1167  @verbatim
1168  - \a - Alert.
1169  - \b - Backspace.
1170  - \e - Escape character i.e. (\‍)
1171  - \r - Carriage return.
1172  - \n - Newline.
1173  - \t - Tab.
1174  - \v - Vertical tab
1175  - <oct> - An octal escape sequence.
1176  - \x<hex> - A hex escape sequence.
1177  @endverbatim
1178  * - Backtick mode ('`' quote char) identical to expanded mode.
1179  * - Regex mode ('/') identical to expanded mode but two successive
1180  * backslashes will be interpreted as an escape sequence, but not
1181  * unescaped, so that they will be passed to the underlying regex
1182  * library.
1183  * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1184  *
1185  * @note The resulting output may contain embedded \0s.
1186  * @note Unrecognised escape sequences will be copied verbatim.
1187  * @note In and out may point to the same underlying buffer.
1188  * @note Copying will stop early if an unescaped instance of the
1189  * quoting char is found in the input buffer.
1190  *
1191  * @param[out] out Where to write the unescaped string.
1192  * @param[in] in The string to unescape.
1193  * @param[in] inlen Length of input string. Pass SIZE_MAX to copy all data
1194  * in the input buffer.
1195  * @param[in] quote Character around the string, determines unescaping mode.
1196  *
1197  * @return
1198  * - 0 if input string was empty.
1199  * - >0 the number of bytes written to out.
1200  */
1202 {
1203  switch (quote) {
1204  default:
1205  break;
1206 
1207  case '"':
1209 
1210  case '\'':
1212 
1213  case '`':
1215 
1216  case '/':
1218  }
1219 
1220  return fr_sbuff_out_bstrncpy(out, in, inlen);
1221 }
1222 
1223 /** Performs byte order reversal for types that need it
1224  *
1225  * @param[in] dst Where to write the result. May be the same as src.
1226  * @param[in] src #fr_value_box_t containing an uint32 value.
1227  * @return
1228  * - 0 on success.
1229  * - -1 on failure.
1230  */
1232 {
1233  if (!fr_cond_assert(src->type != FR_TYPE_NULL)) return -1;
1234 
1235  switch (src->type) {
1236  default:
1237  break;
1238 
1239  case FR_TYPE_BOOL:
1240  case FR_TYPE_UINT8:
1241  case FR_TYPE_INT8:
1242  case FR_TYPE_IPV4_ADDR:
1243  case FR_TYPE_IPV4_PREFIX:
1244  case FR_TYPE_IPV6_ADDR:
1245  case FR_TYPE_IPV6_PREFIX:
1246  case FR_TYPE_COMBO_IP_ADDR:
1248  case FR_TYPE_IFID:
1249  case FR_TYPE_ETHERNET:
1250  case FR_TYPE_SIZE:
1251  fr_value_box_copy(NULL, dst, src);
1252  return 0;
1253 
1254  case FR_TYPE_OCTETS:
1255  case FR_TYPE_STRING:
1256  case FR_TYPE_NON_LEAF:
1257  fr_assert_fail(NULL);
1258  return -1; /* shouldn't happen */
1259  }
1260 
1261  /*
1262  * If we're not just flipping in place
1263  * initialise the destination box
1264  * with similar meta data as the src.
1265  *
1266  * Don't use the copy meta data function
1267  * here as that doesn't initialise the
1268  * destination box.
1269  */
1270  if (dst != src) fr_value_box_init(dst, src->type, src->enumv, src->tainted);
1271 
1272  switch (src->type) {
1273  case FR_TYPE_UINT16:
1274  dst->vb_uint16 = htons(src->vb_uint16);
1275  break;
1276 
1277  case FR_TYPE_UINT32:
1278  dst->vb_uint32 = htonl(src->vb_uint32);
1279  break;
1280 
1281  case FR_TYPE_UINT64:
1282  dst->vb_uint64 = htonll(src->vb_uint64);
1283  break;
1284 
1285  case FR_TYPE_INT16:
1286  dst->vb_int16 = htons(src->vb_int16);
1287  break;
1288 
1289  case FR_TYPE_INT32:
1290  dst->vb_int32 = htonl(src->vb_int32);
1291  break;
1292 
1293  case FR_TYPE_INT64:
1294  dst->vb_int64 = htonll(src->vb_int64);
1295  break;
1296 
1297  case FR_TYPE_DATE:
1298  dst->vb_date = fr_unix_time_wrap(htonll(fr_unix_time_unwrap(src->vb_date)));
1299  break;
1300 
1301  case FR_TYPE_TIME_DELTA:
1302  dst->vb_time_delta = fr_time_delta_wrap(htonll(fr_time_delta_unwrap(src->vb_time_delta)));
1303  break;
1304 
1305  case FR_TYPE_FLOAT32:
1306  dst->vb_float32 = htonl((uint32_t)src->vb_float32);
1307  break;
1308 
1309  case FR_TYPE_FLOAT64:
1310  dst->vb_float64 = htonll((uint64_t)src->vb_float64);
1311  break;
1312 
1313  default:
1314  fr_assert_fail(NULL);
1315  return -1; /* shouldn't happen */
1316  }
1317 
1318  return 0;
1319 }
1320 
1321 /** Get the size of the value held by the fr_value_box_t
1322  *
1323  * This is the length of the NETWORK presentation
1324  */
1326 {
1327  switch (value->type) {
1328  case FR_TYPE_VARIABLE_SIZE:
1329  if (value->enumv) {
1330  /*
1331  * Fixed-width fields.
1332  */
1333  if (value->enumv->flags.length) {
1334  return value->enumv->flags.length;
1335  }
1336 
1337  /*
1338  * Clamp length at maximum we're allowed to encode.
1339  */
1340  if (da_is_length_field(value->enumv)) {
1341  if (value->enumv->flags.subtype == FLAG_LENGTH_UINT8) {
1342  if (value->vb_length > 255) return 255;
1343 
1344  } else if (value->enumv->flags.subtype == FLAG_LENGTH_UINT16) {
1345  if (value->vb_length > 65535) return 65535;
1346  }
1347  }
1348  }
1349  return value->vb_length;
1350 
1351  /*
1352  * These can have different encodings, depending on the underlying protocol.
1353  */
1354  case FR_TYPE_DATE:
1355  case FR_TYPE_TIME_DELTA:
1356  if (value->enumv) return value->enumv->flags.length;
1357  FALL_THROUGH;
1358 
1359  default:
1360  return network_min_size(value->type);
1361  }
1362 }
1363 
1364 /** Encode a single value box, serializing its contents in generic network format
1365  *
1366  * The serialized form of #fr_value_box_t may not match the requirements of your protocol
1367  * completely. In cases where they do not, you should overload specific types in the
1368  * function calling #fr_value_box_to_network.
1369  *
1370  * The general serialization rules are:
1371  *
1372  * - Octets are encoded in binary form (not hex).
1373  * - Strings are encoded without the trailing \0 byte.
1374  * - Integers are encoded big-endian.
1375  * - Bools are encoded using one byte, with value 0x00 (false) or 0x01 (true).
1376  * - Signed integers are encoded two's complement, with the MSB as the sign bit.
1377  * Byte order is big-endian.
1378  * - Network addresses are encoded big-endian.
1379  * - IPv4 prefixes are encoded with 1 byte for the prefix, then 4 bytes of address.
1380  * - IPv6 prefixes are encoded with 1 byte for the scope_id, 1 byte for the prefix,
1381  * and 16 bytes of address.
1382  * - Floats are encoded in IEEE-754 format with a big-endian byte order. We rely
1383  * on the fact that the C standards require floats to be represented in IEEE-754
1384  * format in memory.
1385  * - Dates are encoded as 16/32/64-bit unsigned UNIX timestamps.
1386  * - time_deltas are encoded as 16/32/64-bit signed integers.
1387  *
1388  * #FR_TYPE_SIZE is not encodable, as it is system specific.
1389  *
1390  * This function will not encode structural types (TLVs, VSAs etc...). These are usually
1391  * specific to the protocol anyway.
1392  *
1393  * All of the dictionary rules are respected. string/octets can have
1394  * a fixed length (which is zero-padded if necessary), or can have an
1395  * 8/16-bit "length" prefix.
1396  *
1397  * @param[out] dbuff Where to write serialized data.
1398  * @param[in] value to encode.
1399  * @return
1400  * - 0 no bytes were written.
1401  * - >0 the number of bytes written to out.
1402  * - <0 the number of bytes we'd need in dbuff to complete the operation.
1403  */
1405 {
1406  size_t min, max;
1407  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1408 
1409  /*
1410  * We cannot encode structural types here.
1411  */
1412  if (!fr_type_is_leaf(value->type)) {
1413  unsupported:
1414  fr_strerror_printf("%s: Cannot encode type \"%s\"",
1415  __FUNCTION__,
1416  fr_type_to_str(value->type));
1417  return FR_VALUE_BOX_NET_ERROR;
1418  }
1419 
1420  /*
1421  * Variable length types
1422  */
1423  switch (value->type) {
1424  case FR_TYPE_OCTETS:
1425  case FR_TYPE_STRING:
1426  max = value->vb_length;
1427 
1428  /*
1429  * Sometimes variable length *inside* the server
1430  * has maximum length on the wire.
1431  */
1432  if (value->enumv) {
1433  if (value->enumv->flags.length) {
1434  /*
1435  * The field is fixed size, and the data is smaller than that, We zero-pad the field.
1436  */
1437  if (max < value->enumv->flags.length) {
1438  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1439  FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, value->enumv->flags.length - max);
1440  return fr_dbuff_set(dbuff, &work_dbuff);
1441 
1442  } else if (max > value->enumv->flags.length) {
1443  /*
1444  * Truncate the input to the maximum allowed length.
1445  */
1446  max = value->enumv->flags.length;
1447  }
1448 
1449  } else if (da_is_length_field(value->enumv)) {
1450  /*
1451  * Truncate the output to the max allowed for this field and encode the length.
1452  */
1453  if (value->enumv->flags.subtype == FLAG_LENGTH_UINT8) {
1454  if (max > 255) max = 255;
1455  FR_DBUFF_IN_RETURN(&work_dbuff, (uint8_t) max);
1456 
1457  } else if (value->enumv->flags.subtype == FLAG_LENGTH_UINT16) {
1458  if (max > 65536) max = 65535;
1459  FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) max);
1460 
1461  } else {
1462  return -1;
1463  }
1464  }
1465  }
1466 
1467  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1468  return fr_dbuff_set(dbuff, &work_dbuff);
1469 
1470  /*
1471  * The data can be encoded in a variety of widths.
1472  */
1473  case FR_TYPE_DATE:
1474  case FR_TYPE_TIME_DELTA:
1475  if (value->enumv) {
1476  min = value->enumv->flags.length;
1477  } else {
1478  min = 4;
1479  }
1480  break;
1481 
1482  default:
1483  min = network_min_size(value->type);
1484  break;
1485  }
1486 
1487  /*
1488  * We have to encode actual data here.
1489  */
1490  fr_assert(min > 0);
1491 
1492  switch (value->type) {
1493  case FR_TYPE_IPV4_ADDR:
1494  ipv4addr:
1495  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1496  (uint8_t const *)&value->vb_ip.addr.v4.s_addr,
1497  sizeof(value->vb_ip.addr.v4.s_addr));
1498  break;
1499  /*
1500  * Needs special mangling
1501  */
1502  case FR_TYPE_IPV4_PREFIX:
1503  ipv4prefix:
1504  FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1505  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1506  (uint8_t const *)&value->vb_ip.addr.v4.s_addr,
1507  sizeof(value->vb_ip.addr.v4.s_addr));
1508  break;
1509 
1510  case FR_TYPE_IPV6_ADDR:
1511  ipv6addr:
1512  if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1513  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ip.addr.v6.s6_addr, sizeof(value->vb_ip.addr.v6.s6_addr));
1514  break;
1515 
1516  case FR_TYPE_IPV6_PREFIX:
1517  ipv6prefix:
1518  if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1519  FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1520  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ip.addr.v6.s6_addr, sizeof(value->vb_ip.addr.v6.s6_addr));
1521  break;
1522 
1523  case FR_TYPE_BOOL:
1524  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, value->datum.boolean);
1525  break;
1526 
1527  case FR_TYPE_COMBO_IP_ADDR:
1528  switch (value->vb_ip.af) {
1529  case AF_INET:
1530  goto ipv4addr;
1531 
1532  case AF_INET6:
1533  goto ipv6addr;
1534 
1535  default:
1536  break;
1537  }
1538 
1539  fr_strerror_const("Combo IP value missing af");
1540  return 0;
1541 
1543  switch (value->vb_ip.af) {
1544  case AF_INET:
1545  goto ipv4prefix;
1546 
1547  case AF_INET6:
1548  goto ipv6prefix;
1549 
1550  default:
1551  break;
1552  }
1553 
1554  fr_strerror_const("Combo IP value missing af");
1555  return 0;
1556 
1557  /*
1558  * Already in network byte-order
1559  */
1560  case FR_TYPE_IFID:
1561  case FR_TYPE_ETHERNET:
1562  case FR_TYPE_UINT8:
1563  case FR_TYPE_INT8:
1564  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(value, value->type), min);
1565  break;
1566 
1567  /*
1568  * Needs a bytesex operation
1569  */
1570  case FR_TYPE_UINT16:
1571  case FR_TYPE_UINT32:
1572  case FR_TYPE_UINT64:
1573  case FR_TYPE_INT16:
1574  case FR_TYPE_INT32:
1575  case FR_TYPE_INT64:
1576  case FR_TYPE_FLOAT32:
1577  case FR_TYPE_FLOAT64:
1578  {
1579  fr_value_box_t tmp;
1580 
1581  fr_value_box_hton(&tmp, value);
1582 
1583  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, value->type), min);
1584  }
1585  break;
1586 
1587  /*
1588  * Dates and deltas are stored internally as
1589  * 64-bit nanoseconds. We have to convert to the
1590  * network format. First by resolution (ns, us,
1591  * ms, s), and then by size (16/32/64-bit).
1592  */
1593  case FR_TYPE_DATE:
1594  {
1595  uint64_t date = 0;
1596  fr_time_res_t res;
1597 
1598  if (!value->enumv) {
1599  res = FR_TIME_RES_SEC;
1600  } else {
1601  res = value->enumv->flags.flag_time_res;
1602  }
1603  date = fr_unix_time_to_integer(value->vb_date, res);
1604 
1605  if (!value->enumv) {
1606  goto date_size4;
1607 
1608  } else switch (value->enumv->flags.length) {
1609  case 2:
1610  if (date > UINT16_MAX) date = UINT16_MAX;
1611  FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t) date);
1612  break;
1613 
1614  date_size4:
1615  case 4:
1616  if (date > UINT32_MAX) date = UINT32_MAX;
1617  FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t) date);
1618  break;
1619 
1620  case 8:
1621  FR_DBUFF_IN_RETURN(&work_dbuff, date);
1622  break;
1623 
1624  default:
1625  goto unsupported;
1626  }
1627 
1628  }
1629  break;
1630 
1631  case FR_TYPE_TIME_DELTA:
1632  {
1633  int64_t date = 0; /* may be negative */
1635  if (value->enumv) res = value->enumv->flags.flag_time_res;
1636 
1637  date = fr_time_delta_to_integer(value->vb_time_delta, res);
1638 
1639  if (!value->enumv) {
1640  goto delta_size4;
1641 
1642  } else if (!value->enumv->flags.is_unsigned) {
1643  switch (value->enumv->flags.length) {
1644  case 2:
1645  if (date < INT16_MIN) {
1646  date = INT16_MIN;
1647  } else if (date > INT16_MAX) {
1648  date = INT16_MAX;
1649  }
1650  FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t)date);
1651  break;
1652 
1653  delta_size4:
1654  case 4:
1655  if (date < INT32_MIN) {
1656  date = INT32_MIN;
1657  } else if (date > INT32_MAX) {
1658  date = INT32_MAX;
1659  }
1660  FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t)date);
1661  break;
1662 
1663  case 8:
1664  FR_DBUFF_IN_RETURN(&work_dbuff, (int64_t)date);
1665  break;
1666 
1667  default:
1668  goto unsupported;
1669  }
1670  } else { /* time delta is unsigned! */
1671  switch (value->enumv->flags.length) {
1672  case 2:
1673  if (date < 0) {
1674  date = 0;
1675  } else if (date > UINT16_MAX) {
1676  date = UINT16_MAX;
1677  }
1678  FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t)date);
1679  break;
1680 
1681  case 4:
1682  if (date < 0) {
1683  date = 0;
1684  } else if (date > UINT32_MAX) {
1685  date = UINT32_MAX;
1686  }
1687  FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)date);
1688  break;
1689 
1690  case 8:
1691  FR_DBUFF_IN_RETURN(&work_dbuff, (uint64_t)date);
1692  break;
1693 
1694  default:
1695  goto unsupported;
1696  }
1697  }
1698  }
1699  break;
1700 
1701  case FR_TYPE_OCTETS:
1702  case FR_TYPE_STRING:
1703  case FR_TYPE_SIZE:
1704  case FR_TYPE_NON_LEAF:
1705  goto unsupported;
1706  }
1707 
1708  return fr_dbuff_set(dbuff, &work_dbuff);
1709 }
1710 
1711 /** Decode a #fr_value_box_t from serialized binary data
1712  *
1713  * The general deserialization rules are:
1714  *
1715  * - Octets are decoded in binary form (not hex).
1716  * - Strings are decoded without the trailing \0 byte. Strings must consist only of valid UTF8 chars.
1717  * - Integers are decoded big-endian.
1718  * - Bools are decoded using one byte, with value 0x00 (false) or 0x01 (true).
1719  * - Signed integers are decoded two's complement, with the MSB as the sign bit.
1720  * Byte order is big-endian.
1721  * - Network addresses are decoded big-endian.
1722  * - IPv4 prefixes are decoded with 1 byte for the prefix, then 4 bytes of address.
1723  * - IPv6 prefixes are decoded with 1 byte for the scope_id, 1 byte for the prefix,
1724  * and 16 bytes of address.
1725  * - Floats are decoded in IEEE-754 format with a big-endian byte order. We rely
1726  * on the fact that the C standards require floats to be represented in IEEE-754
1727  * format in memory.
1728  * - Dates are decoded as 32bit unsigned UNIX timestamps.
1729  *
1730  * All of the dictionary rules are respected. string/octets can have
1731  * a fixed length, or can have an 8/16-bit "length" prefix. If the
1732  * enumv is not an array, then the input # len MUST be the correct size
1733  * (not too large or small), otherwise an error is returned.
1734  *
1735  * If the enumv is an array, then the input must have the minimum
1736  * length, and the number of bytes decoded is capped at the maximum
1737  * length allowed to be decoded. This behavior allows the caller to
1738  * decode an array of values simply by calling this function in a
1739  * loop.
1740  *
1741  * @param[in] ctx Where to allocate any talloc buffers required.
1742  * @param[out] dst value_box to write the result to.
1743  * @param[in] type to decode data to.
1744  * @param[in] enumv Aliases for values.
1745  * @param[in] dbuff Binary data to decode.
1746  * @param[in] len Length of data to decode. For fixed length types we only
1747  * decode complete values.
1748  * @param[in] tainted Whether the value came from a trusted source.
1749  * @return
1750  * - >= 0 The number of bytes consumed.
1751  * - <0 - The negative offset where the error occurred.
1752  * - FR_VALUE_BOX_NET_OOM (negative value) - Out of memory.
1753  */
1755  fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv,
1756  fr_dbuff_t *dbuff, size_t len,
1757  bool tainted)
1758 {
1759  size_t min, max;
1760  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1761 
1763  max = network_max_size(type);
1764 
1765  if (len < min) {
1766  fr_strerror_printf("Got truncated value parsing type \"%s\". "
1767  "Expected length >= %zu bytes, got %zu bytes",
1769  min, len);
1770  return -(len);
1771  }
1772 
1773  /*
1774  * For array entries, we only decode one value at a time.
1775  */
1776  if (len > max) {
1777  if (enumv && !enumv->flags.array) {
1778  fr_strerror_printf("Found trailing garbage parsing type \"%s\". "
1779  "Expected length <= %zu bytes, got %zu bytes",
1781  max, len);
1782  return -(max);
1783  }
1784 
1785  len = max;
1786  }
1787 
1788  /*
1789  * String / octets are special.
1790  */
1792  size_t newlen = len;
1793  size_t offset = 0;
1794 
1795  /*
1796  * Decode fixed-width fields.
1797  */
1798  if (enumv) {
1799  if (enumv->flags.length) {
1800  newlen = enumv->flags.length;
1801 
1802  } else if (da_is_length_field(enumv)) {
1803  /*
1804  * Or fields with a length prefix.
1805  */
1806  if (enumv->flags.subtype == FLAG_LENGTH_UINT8) {
1807  uint8_t num = 0;
1808 
1809  FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1810  newlen = num;
1811  offset = 1;
1812 
1813  } else if (enumv->flags.subtype == FLAG_LENGTH_UINT16) {
1814  uint16_t num = 0;
1815 
1816  FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1817  newlen = num;
1818  offset = 2;
1819 
1820  } else {
1821  return -1;
1822  }
1823  }
1824  }
1825 
1826  /*
1827  * If we need more data than exists, that's an error.
1828  *
1829  * Otherwise, bound the decoding to the count we found.
1830  */
1831  if (newlen > len) return -(newlen + offset);
1832  len = newlen;
1833 
1834  switch (type) {
1835  case FR_TYPE_STRING:
1836  if (fr_value_box_bstrndup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1837  return FR_VALUE_BOX_NET_OOM;
1838  }
1839  return fr_dbuff_set(dbuff, &work_dbuff);
1840 
1841  case FR_TYPE_OCTETS:
1842  if (fr_value_box_memdup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1843  return FR_VALUE_BOX_NET_OOM;
1844  }
1845  return fr_dbuff_set(dbuff, &work_dbuff);
1846 
1847  default:
1848  return -1;
1849  }
1850  }
1851 
1852  /*
1853  * Pre-Initialise box for non-variable types
1854  */
1855  fr_value_box_init(dst, type, enumv, tainted);
1856  switch (type) {
1857  /*
1858  * Already in network byte order
1859  */
1860  case FR_TYPE_IPV4_ADDR:
1861  ipv4addr:
1862  dst->vb_ip = (fr_ipaddr_t){
1863  .af = AF_INET,
1864  .prefix = 32,
1865  };
1866  FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len);
1867  break;
1868 
1869  case FR_TYPE_IPV4_PREFIX:
1870  ipv4prefix:
1871  dst->vb_ip = (fr_ipaddr_t){
1872  .af = AF_INET,
1873  };
1874  FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
1875  FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len - 1);
1876  break;
1877 
1878  case FR_TYPE_IPV6_ADDR:
1879  ipv6addr:
1880  dst->vb_ip = (fr_ipaddr_t){
1881  .af = AF_INET6,
1882  .scope_id = 0,
1883  .prefix = 128
1884  };
1885  if (len == max) {
1886  uint8_t scope_id = 0;
1887 
1888  FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
1889  dst->vb_ip.scope_id = scope_id;
1890  len--;
1891  }
1892  FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len);
1893  break;
1894 
1895  case FR_TYPE_IPV6_PREFIX:
1896  ipv6prefix:
1897  dst->vb_ip = (fr_ipaddr_t){
1898  .af = AF_INET6,
1899  .scope_id = 0,
1900  };
1901  if (len == max) {
1902  uint8_t scope_id = 0;
1903 
1904  FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
1905  dst->vb_ip.scope_id = scope_id;
1906  len--;
1907  }
1908  FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
1909  FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len - 1);
1910  break;
1911 
1912  case FR_TYPE_COMBO_IP_ADDR:
1913  if ((len >= network_min_size(FR_TYPE_IPV6_ADDR)) &&
1914  (len <= network_max_size(FR_TYPE_IPV6_ADDR))) goto ipv6addr; /* scope is optional */
1915  else if ((len >= network_min_size(FR_TYPE_IPV4_ADDR)) &&
1916  (len <= network_max_size(FR_TYPE_IPV4_ADDR))) goto ipv4addr;
1917  fr_strerror_const("Invalid combo ip address value");
1918  return 0;
1919 
1921  if ((len >= network_min_size(FR_TYPE_IPV6_PREFIX)) &&
1922  (len <= network_max_size(FR_TYPE_IPV6_PREFIX))) goto ipv6prefix; /* scope is optional */
1923  else if ((len >= network_min_size(FR_TYPE_IPV4_PREFIX)) &&
1924  (len <= network_max_size(FR_TYPE_IPV4_PREFIX))) goto ipv4prefix;
1925  fr_strerror_const("Invalid combo ip prefix value");
1926  return 0;
1927 
1928  case FR_TYPE_BOOL:
1929  {
1930  uint8_t val = 0;
1931 
1932  FR_DBUFF_OUT_RETURN(&val, &work_dbuff);
1933  dst->datum.boolean = (val != 0);
1934  }
1935  break;
1936 
1937  case FR_TYPE_IFID:
1938  case FR_TYPE_ETHERNET:
1939  FR_DBUFF_OUT_MEMCPY_RETURN(fr_value_box_raw(dst, type), &work_dbuff, len);
1940  break;
1941 
1942  case FR_TYPE_UINT8:
1943  FR_DBUFF_OUT_RETURN(&dst->vb_uint8, &work_dbuff);
1944  break;
1945 
1946  case FR_TYPE_UINT16:
1947  FR_DBUFF_OUT_RETURN(&dst->vb_uint16, &work_dbuff);
1948  break;
1949 
1950  case FR_TYPE_UINT32:
1951  FR_DBUFF_OUT_RETURN(&dst->vb_uint32, &work_dbuff);
1952  break;
1953 
1954  case FR_TYPE_UINT64:
1955  FR_DBUFF_OUT_RETURN(&dst->vb_uint64, &work_dbuff);
1956  break;
1957 
1958  case FR_TYPE_INT8:
1959  FR_DBUFF_OUT_RETURN(&dst->vb_int8, &work_dbuff);
1960  break;
1961 
1962  case FR_TYPE_INT16:
1963  FR_DBUFF_OUT_RETURN(&dst->vb_int16, &work_dbuff);
1964  break;
1965 
1966  case FR_TYPE_INT32:
1967  FR_DBUFF_OUT_RETURN(&dst->vb_int32, &work_dbuff);
1968  break;
1969 
1970  case FR_TYPE_INT64:
1971  FR_DBUFF_OUT_RETURN(&dst->vb_int64, &work_dbuff);
1972  break;
1973 
1974  case FR_TYPE_FLOAT32:
1975  FR_DBUFF_OUT_RETURN(&dst->vb_float32, &work_dbuff);
1976  break;
1977 
1978  case FR_TYPE_FLOAT64:
1979  FR_DBUFF_OUT_RETURN(&dst->vb_float64, &work_dbuff);
1980  break;
1981 
1982  /*
1983  * Dates and deltas are stored internally as
1984  * 64-bit nanoseconds. We have to convert from
1985  * the network format. First by size
1986  * (16/32/64-bit), and then by resolution (ns,
1987  * us, ms, s).
1988  */
1989  case FR_TYPE_DATE:
1990  {
1991  size_t length = 4;
1992  fr_time_res_t precision = FR_TIME_RES_SEC;
1993  uint64_t date;
1994 
1995  if (enumv) {
1996  length = enumv->flags.length;
1997  precision = (fr_time_res_t)enumv->flags.flag_time_res;
1998  }
1999 
2000  /*
2001  * Input data doesn't match what we were told we
2002  * need.
2003  */
2004  if (len > length) return -(length);
2005 
2006  dst->enumv = enumv;
2007 
2008  FR_DBUFF_OUT_UINT64V_RETURN(&date, &work_dbuff, length);
2009 
2010  if (!fr_multiply(&date, date, fr_time_multiplier_by_res[precision])) {
2011  fr_strerror_const("date would overflow");
2012  return 0;
2013  }
2014 
2015  dst->vb_date = fr_unix_time_wrap(date);
2016  }
2017  break;
2018 
2019  case FR_TYPE_TIME_DELTA:
2020  {
2021  size_t length = 4;
2022  fr_time_res_t precision = FR_TIME_RES_SEC;
2023  int64_t date;
2024 
2025  if (enumv) {
2026  length = enumv->flags.length;
2027  precision = (fr_time_res_t)enumv->flags.flag_time_res;
2028  }
2029 
2030  /*
2031  * Input data doesn't match what we were told we
2032  * need.
2033  */
2034  if (len > length) return -(length);
2035 
2036  dst->enumv = enumv;
2037 
2038  if (!enumv || !enumv->flags.is_unsigned) {
2039  FR_DBUFF_OUT_INT64V_RETURN(&date, &work_dbuff, length);
2040  } else {
2041  uint64_t tmp;
2042 
2043  /*
2044  * Else it's an unsigned time delta, but
2045  * we do have to clamp it at the max
2046  * value for a signed 64-bit integer.
2047  */
2048  FR_DBUFF_OUT_UINT64V_RETURN(&tmp, &work_dbuff, length);
2049 
2050  if (tmp > INT64_MAX) tmp = INT64_MAX;
2051 
2052  date = tmp;
2053  }
2054 
2055  dst->vb_time_delta = fr_time_delta_wrap(fr_time_scale(date, precision));
2056  }
2057  break;
2058 
2059  case FR_TYPE_STRING:
2060  case FR_TYPE_OCTETS:
2061  break; /* Already dealt with */
2062 
2063  case FR_TYPE_SIZE:
2064  case FR_TYPE_NON_LEAF:
2065  fr_strerror_printf("Cannot decode type \"%s\" - Is not a value",
2066  fr_type_to_str(type));
2067  break;
2068  }
2069 
2070  return fr_dbuff_set(dbuff, &work_dbuff);
2071 }
2072 
2073 /** Get a key from a value box
2074  *
2075  * @param[in,out] out - set to a small buffer on input. If the callback has more data
2076  * than is available here, the callback can update "out" to point elsewhere
2077  * @param[in,out] outlen The number of bits available in the initial buffer. On output,
2078  * the number of bits available in the key
2079  * @param[in] value the value box which contains the key
2080  * @return
2081  * - <0 on error
2082  * - 0 on success
2083  */
2084 int fr_value_box_to_key(uint8_t **out, size_t *outlen, fr_value_box_t const *value)
2085 {
2086  ssize_t slen;
2087  fr_dbuff_t dbuff;
2088 
2089  switch (value->type) {
2090  case FR_TYPE_BOOL:
2091  if (*outlen < 8) return -1;
2092 
2093  *out[0] = (value->vb_bool) << 7;
2094  *outlen = 1;
2095  break;
2096 
2098  if (*outlen < (fr_value_box_network_sizes[value->type][1] * 8)) return -1;
2099 
2100  /*
2101  * Integers are put into network byte order.
2102  */
2103  fr_dbuff_init(&dbuff, *out, *outlen >> 3);
2104 
2105  slen = fr_value_box_to_network(&dbuff, value);
2106  if (slen < 0) return slen;
2107  *outlen = slen * 8; /* bits not bytes */
2108  break;
2109 
2110  case FR_TYPE_IP:
2111  /*
2112  * IPs are already in network byte order.
2113  */
2114  *out = UNCONST(uint8_t *, &value->vb_ip.addr);
2115  *outlen = value->vb_ip.prefix;
2116  break;
2117 
2118  case FR_TYPE_STRING:
2119  case FR_TYPE_OCTETS:
2120  *out = value->datum.ptr;
2121  *outlen = value->vb_length * 8;
2122  break;
2123 
2124  case FR_TYPE_ETHERNET:
2125  *out = UNCONST(uint8_t *, &value->vb_ether[0]);
2126  *outlen = sizeof(value->vb_ether) * 8;
2127  break;
2128 
2129  default:
2130  fr_strerror_printf("Invalid data type '%s' for getting key",
2131  fr_type_to_str(value->type));
2132  return -1;
2133  }
2134 
2135  return 0;
2136 }
2137 
2138 /** Convert octets to a fixed size value box value
2139  *
2140  * All fixed size types are allowed.
2141  *
2142  * @param dst Where to write result of casting.
2143  * @param dst_type to cast to.
2144  * @param dst_enumv enumeration values.
2145  * @param src Input data.
2146  */
2148  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2149  fr_value_box_t const *src)
2150 {
2151  uint8_t *ptr;
2152 
2153  if (!fr_type_is_fixed_size(dst_type)) if (!fr_cond_assert(false)) return -1;
2154 
2155  if (src->vb_length > network_max_size(dst_type)) {
2156  fr_strerror_printf("Invalid cast from %s to %s. Source length %zd is greater than "
2157  "destination type size %zd",
2158  fr_type_to_str(src->type),
2159  fr_type_to_str(dst_type),
2160  src->vb_length,
2161  network_max_size(dst_type));
2162  return -1;
2163  }
2164 
2165  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2166 
2167  /*
2168  * No data to copy means just reset it to zero.
2169  */
2170  if (!src->vb_length) return 0;
2171 
2172  ptr = (uint8_t *) &dst->datum;
2173 
2174  /*
2175  * If the source is too small, just left-fill with zeroes.
2176  */
2177  if (src->vb_length < network_min_size(dst_type)) {
2178  ptr += network_min_size(dst_type) - src->vb_length;
2179  }
2180 
2181  /*
2182  * Copy the raw octets into the datum of a value_box
2183  * inverting bytesex for uint32s (if LE).
2184  */
2185  memcpy(ptr, src->vb_octets, src->vb_length);
2186  fr_value_box_hton(dst, dst);
2187 
2188  return 0;
2189 }
2190 
2191 /** v4 to v6 mapping prefix
2192  *
2193  * Part of the IPv6 range is allocated to represent IPv4 addresses.
2194  */
2195 static uint8_t const v4_v6_map[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2196  0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
2197 
2198 
2199 /** Convert any supported type to a string
2200  *
2201  * All non-structural types are allowed.
2202  *
2203  * @param ctx unused.
2204  * @param dst Where to write result of casting.
2205  * @param dst_type to cast to.
2206  * @param dst_enumv enumeration values.
2207  * @param src Input data.
2208  */
2209 static inline int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t *dst,
2210  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2211  fr_value_box_t const *src)
2212 {
2213  if (!fr_cond_assert(dst_type == FR_TYPE_STRING)) return -1;
2214 
2215  switch (src->type) {
2216  /*
2217  * The presentation format of octets is hex
2218  * What we actually want here is the raw string
2219  */
2220  case FR_TYPE_OCTETS:
2221  return fr_value_box_bstrndup(ctx, dst, dst_enumv,
2222  (char const *)src->vb_octets, src->vb_length, src->tainted);
2223 
2224  case FR_TYPE_GROUP:
2226  dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2228  FR_VALUE_BOX_LIST_NONE, false,
2229  SIZE_MAX);
2230 
2231  /*
2232  * Get the presentation format
2233  */
2234  default:
2235  {
2236  char *str;
2237 
2238  fr_value_box_aprint(ctx, &str, src, NULL);
2239  if (unlikely(!str)) return -1;
2240 
2241  return fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, str, src->tainted);
2242  }
2243  }
2244 }
2245 
2246 /** Convert any supported type to octets
2247  *
2248  * All non-structural types are allowed.
2249  *
2250  * @param ctx unused.
2251  * @param dst Where to write result of casting.
2252  * @param dst_type to cast to.
2253  * @param dst_enumv enumeration values.
2254  * @param src Input data.
2255  */
2256 static inline int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *dst,
2257  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2258  fr_value_box_t const *src)
2259 {
2260  if (!fr_cond_assert(dst_type == FR_TYPE_OCTETS)) return -1;
2261 
2262  switch (src->type) {
2263  /*
2264  * <string> (excluding terminating \0)
2265  */
2266  case FR_TYPE_STRING:
2267  if (fr_value_box_memdup(ctx, dst, dst_enumv,
2268  (uint8_t const *)src->vb_strvalue, src->vb_length, src->tainted) < 0) {
2269  return -1;
2270  }
2271  return 0;
2272 
2273  case FR_TYPE_GROUP:
2275  dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2277  FR_VALUE_BOX_LIST_NONE, false,
2278  SIZE_MAX);
2279  /*
2280  * <4 bytes address>
2281  */
2282  case FR_TYPE_IPV4_ADDR:
2283  return fr_value_box_memdup(ctx, dst, dst_enumv,
2284  (uint8_t const *)&src->vb_ip.addr.v4.s_addr,
2285  sizeof(src->vb_ip.addr.v4.s_addr), src->tainted);
2286 
2287  /*
2288  * <1 uint8 prefix> + <4 bytes address>
2289  */
2290  case FR_TYPE_IPV4_PREFIX:
2291  {
2292  uint8_t *bin;
2293 
2294  if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2295  sizeof(src->vb_ip.addr.v4.s_addr) + 1, src->tainted) < 0) return -1;
2296 
2297  bin[0] = src->vb_ip.prefix;
2298  memcpy(&bin[1], (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2299  }
2300  return 0;
2301 
2302  /*
2303  * <16 bytes address>
2304  */
2305  case FR_TYPE_IPV6_ADDR:
2306  return fr_value_box_memdup(ctx, dst, dst_enumv,
2307  (uint8_t const *)src->vb_ip.addr.v6.s6_addr,
2308  sizeof(src->vb_ip.addr.v6.s6_addr), src->tainted);
2309 
2310  /*
2311  * <1 uint8 prefix> + <1 uint8 scope> + <16 bytes address>
2312  */
2313  case FR_TYPE_IPV6_PREFIX:
2314  {
2315  uint8_t *bin;
2316 
2317  if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2318  sizeof(src->vb_ip.addr.v6.s6_addr) + 2, src->tainted) < 0) return -1;
2319  bin[0] = src->vb_ip.scope_id;
2320  bin[1] = src->vb_ip.prefix;
2321  memcpy(&bin[2], src->vb_ip.addr.v6.s6_addr, sizeof(src->vb_ip.addr.v6.s6_addr));
2322  }
2323  return 0;
2324 
2325  /*
2326  * Get the raw binary in memory representation
2327  */
2328  case FR_TYPE_NUMERIC:
2329  {
2330  fr_value_box_t tmp;
2331 
2332  fr_value_box_hton(&tmp, src); /* Flip any numeric representations */
2333  return fr_value_box_memdup(ctx, dst, dst_enumv,
2334  fr_value_box_raw(&tmp, src->type),
2335  fr_value_box_field_sizes[src->type], src->tainted);
2336  }
2337 
2338  default:
2339  /* Not the same talloc_memdup call as above. The above memdup reads data from the dst */
2340  return fr_value_box_memdup(ctx, dst, dst_enumv,
2341  fr_value_box_raw(src, src->type),
2342  fr_value_box_field_sizes[src->type], src->tainted);
2343  }
2344 }
2345 
2346 #define CAST_IP_FIX_COMBO \
2347  case FR_TYPE_COMBO_IP_ADDR: \
2348  if (src->vb_ip.af == AF_INET) { \
2349  src_type = FR_TYPE_IPV4_ADDR; \
2350  } else if (src->vb_ip.af == AF_INET6) { \
2351  src_type = FR_TYPE_IPV6_ADDR; \
2352  } \
2353  break; \
2354  case FR_TYPE_COMBO_IP_PREFIX: \
2355  if (src->vb_ip.af == AF_INET) { \
2356  src_type = FR_TYPE_IPV4_PREFIX; \
2357  } else if (src->vb_ip.af == AF_INET6) { \
2358  src_type = FR_TYPE_IPV6_PREFIX; \
2359  } \
2360  break
2361 
2362 
2363 /** Convert any supported type to an IPv4 address
2364  *
2365  * Allowed input types are:
2366  * - FR_TYPE_IPV6_ADDR (with v4 prefix).
2367  * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2368  * - FR_TYPE_IPV6_PREFIX (with v4 prefix and 128bit mask).
2369  * - FR_TYPE_OCTETS (of length 4).
2370  * - FR_TYPE_UINT32
2371  *
2372  * @param ctx unused.
2373  * @param dst Where to write result of casting.
2374  * @param dst_type to cast to.
2375  * @param dst_enumv enumeration values.
2376  * @param src Input data.
2377  */
2378 static inline int fr_value_box_cast_to_ipv4addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
2379  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2380  fr_value_box_t const *src)
2381 {
2382  fr_type_t src_type = src->type;
2383 
2384  fr_assert(dst_type == FR_TYPE_IPV4_ADDR);
2385 
2386  switch (src_type) {
2387  case FR_TYPE_STRING:
2388  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2389  src->vb_strvalue, src->vb_length,
2390  NULL, src->tainted);
2391 
2393 
2394  default:
2395  break;
2396  }
2397 
2398  /*
2399  * Pre-initialise box for non-variable types
2400  */
2401  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2402  dst->vb_ip.af = AF_INET;
2403  dst->vb_ip.prefix = 32;
2404  dst->vb_ip.scope_id = 0;
2405 
2406  switch (src_type) {
2407  case FR_TYPE_IPV6_ADDR:
2408  if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
2409  bad_v6_prefix_map:
2410  fr_strerror_printf("Invalid cast from %s to %s. No IPv4-IPv6 mapping prefix",
2411  fr_type_to_str(src->type),
2412  fr_type_to_str(dst_type));
2413  return -1;
2414  }
2415 
2416  memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2417  sizeof(dst->vb_ip.addr.v4));
2418 
2419  break;
2420 
2421  case FR_TYPE_IPV4_PREFIX:
2422  if (src->vb_ip.prefix != 32) {
2423  fr_strerror_printf("Invalid cast from %s to %s. Only /32 (not %i/) prefixes may be "
2424  "cast to IP address types",
2425  fr_type_to_str(src->type),
2426  fr_type_to_str(dst_type),
2427  src->vb_ip.prefix);
2428  return -1;
2429  }
2430  FALL_THROUGH;
2431 
2432  case FR_TYPE_IPV4_ADDR: /* Needed for handling combo addresses */
2433  memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v4, sizeof(dst->vb_ip.addr.v4));
2434  break;
2435 
2436  case FR_TYPE_IPV6_PREFIX:
2437  if (src->vb_ip.prefix != 128) {
2438  fr_strerror_printf("Invalid cast from %s to %s. Only /128 (not /%i) prefixes may be "
2439  "cast to IP address types",
2440  fr_type_to_str(src->type),
2441  fr_type_to_str(dst_type),
2442  src->vb_ip.prefix);
2443  return -1;
2444  }
2445  if (memcmp(&src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
2446  memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2447  sizeof(dst->vb_ip.addr.v4));
2448  break;
2449 
2450  case FR_TYPE_OCTETS:
2451  if (src->vb_length != sizeof(dst->vb_ip.addr.v4.s_addr)) {
2452  fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
2453  fr_type_to_str(src->type),
2454  fr_type_to_str(dst_type),
2455  sizeof(dst->vb_ip.addr.v4.s_addr), src->vb_length);
2456  return -1;
2457  }
2458  memcpy(&dst->vb_ip.addr.v4, src->vb_octets, sizeof(dst->vb_ip.addr.v4.s_addr));
2459  break;
2460 
2461  case FR_TYPE_UINT32:
2462  {
2463  uint32_t net;
2464 
2465  net = ntohl(src->vb_uint32);
2466  memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ip.addr.v4.s_addr));
2467  }
2468  break;
2469 
2470  default:
2471  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2472  fr_type_to_str(src->type),
2473  fr_type_to_str(dst_type));
2474  return -1;
2475  }
2476 
2477  return 0;
2478 }
2479 
2480 /** Convert any supported type to an IPv6 address
2481  *
2482  * Allowed input types are:
2483  * - FR_TYPE_IPV4_ADDR
2484  * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2485  * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2486  * - FR_TYPE_OCTETS (of length 16).
2487  *
2488  * @param ctx unused.
2489  * @param dst Where to write result of casting.
2490  * @param dst_type to cast to.
2491  * @param dst_enumv enumeration values.
2492  * @param src Input data.
2493  */
2494 static inline int fr_value_box_cast_to_ipv4prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
2495  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2496  fr_value_box_t const *src)
2497 {
2498  fr_type_t src_type = src->type;
2499  fr_assert(dst_type == FR_TYPE_IPV4_PREFIX);
2500 
2501  switch (src_type) {
2502  case FR_TYPE_STRING:
2503  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2504  src->vb_strvalue, src->vb_length,
2505  NULL, src->tainted);
2506 
2508 
2509  default:
2510  break;
2511  }
2512 
2513  /*
2514  * Pre-initialise box for non-variable types
2515  */
2516  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2517  dst->vb_ip.af = AF_INET;
2518  dst->vb_ip.scope_id = 0;
2519 
2520  switch (src_type) {
2521  case FR_TYPE_IPV4_PREFIX: /* Needed for handling combo prefixes */
2522  dst->vb_ip.prefix = src->vb_ip.prefix;
2523  FALL_THROUGH;
2524 
2525  case FR_TYPE_IPV4_ADDR:
2526  memcpy(&dst->vb_ip, &src->vb_ip, sizeof(dst->vb_ip));
2527  break;
2528 
2529  /*
2530  * Copy the last four bytes, to make an IPv4prefix
2531  */
2532  case FR_TYPE_IPV6_ADDR:
2533  if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
2534  bad_v6_prefix_map:
2535  fr_strerror_printf("Invalid cast from %s to %s. No IPv4-IPv6 mapping prefix",
2536  fr_type_to_str(src->type),
2537  fr_type_to_str(dst_type));
2538  return -1;
2539  }
2540  memcpy(&dst->vb_ip.addr.v4.s_addr, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2541  sizeof(dst->vb_ip.addr.v4.s_addr));
2542  dst->vb_ip.prefix = 32;
2543  break;
2544 
2545  case FR_TYPE_IPV6_PREFIX:
2546  if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
2547 
2548  if (src->vb_ip.prefix < (sizeof(v4_v6_map) << 3)) {
2549  fr_strerror_printf("Invalid cast from %s to %s. Expected prefix >= %u bits got %u bits",
2550  fr_type_to_str(src->type),
2551  fr_type_to_str(dst_type),
2552  (unsigned int)(sizeof(v4_v6_map) << 3), src->vb_ip.prefix);
2553  return -1;
2554  }
2555  memcpy(&dst->vb_ip.addr.v4.s_addr, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2556  sizeof(dst->vb_ip.addr.v4.s_addr));
2557 
2558  /*
2559  * Subtract the bits used by the v4_v6_map to get the v4 prefix bits
2560  */
2561  dst->vb_ip.prefix = src->vb_ip.prefix - (sizeof(v4_v6_map) << 3);
2562  break;
2563 
2564  case FR_TYPE_OCTETS:
2565  if (src->vb_length != sizeof(dst->vb_ip.addr.v4.s_addr) + 1) {
2566  fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
2567  fr_type_to_str(src->type),
2568  fr_type_to_str(dst_type),
2569  sizeof(dst->vb_ip.addr.v4.s_addr) + 1, src->vb_length);
2570  return -1;
2571  }
2572  dst->vb_ip.prefix = src->vb_octets[0];
2573  memcpy(&dst->vb_ip.addr.v4, &src->vb_octets[1], sizeof(dst->vb_ip.addr.v4.s_addr));
2574  break;
2575 
2576  case FR_TYPE_UINT32:
2577  {
2578  uint32_t net;
2579 
2580  net = ntohl(src->vb_uint32);
2581  memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ip.addr.v4.s_addr));
2582  dst->vb_ip.prefix = 32;
2583  break;
2584  }
2585 
2586  default:
2587  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2588  fr_type_to_str(src->type),
2589  fr_type_to_str(dst_type));
2590  return -1;
2591  }
2592 
2593  return 0;
2594 }
2595 
2596 /** Convert any supported type to an IPv6 address
2597  *
2598  * Allowed input types are:
2599  * - FR_TYPE_IPV4_ADDR
2600  * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2601  * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2602  * - FR_TYPE_OCTETS (of length 16).
2603  *
2604  * @param ctx unused.
2605  * @param dst Where to write result of casting.
2606  * @param dst_type to cast to.
2607  * @param dst_enumv enumeration values.
2608  * @param src Input data.
2609  */
2610 static inline int fr_value_box_cast_to_ipv6addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
2611  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2612  fr_value_box_t const *src)
2613 {
2614  fr_type_t src_type = src->type;
2615 
2616  static_assert((sizeof(v4_v6_map) + sizeof(src->vb_ip.addr.v4)) <=
2617  sizeof(src->vb_ip.addr.v6), "IPv6 storage too small");
2618  fr_assert(dst_type == FR_TYPE_IPV6_ADDR);
2619 
2620  switch (src_type) {
2621  case FR_TYPE_STRING:
2622  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2623  src->vb_strvalue, src->vb_length,
2624  NULL, src->tainted);
2625 
2627 
2628  default:
2629  break;
2630  }
2631 
2632  /*
2633  * Pre-initialise box for non-variable types
2634  */
2635  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2636  dst->vb_ip.af = AF_INET6;
2637  dst->vb_ip.prefix = 128;
2638 
2639  switch (src_type) {
2640  case FR_TYPE_IPV4_ADDR:
2641  {
2642  uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2643 
2644  /* Add the v4/v6 mapping prefix */
2645  memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2646  p += sizeof(v4_v6_map);
2647  memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2648  dst->vb_ip.scope_id = 0;
2649  }
2650  break;
2651 
2652  case FR_TYPE_IPV4_PREFIX:
2653  {
2654  uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2655 
2656  if (src->vb_ip.prefix != 32) {
2657  fr_strerror_printf("Invalid cast from %s to %s. Only /32 (not /%i) prefixes may be "
2658  "cast to IP address types",
2659  fr_type_to_str(src->type),
2660  fr_type_to_str(dst_type),
2661  src->vb_ip.prefix);
2662  return -1;
2663  }
2664 
2665  /* Add the v4/v6 mapping prefix */
2666  memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2667  p += sizeof(v4_v6_map);
2668  memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2669  dst->vb_ip.scope_id = 0;
2670  }
2671  break;
2672 
2673  case FR_TYPE_IPV6_PREFIX:
2674  if (src->vb_ip.prefix != 128) {
2675  fr_strerror_printf("Invalid cast from %s to %s. Only /128 (not /%i) prefixes may be "
2676  "cast to IP address types",
2677  fr_type_to_str(src->type),
2678  fr_type_to_str(dst_type),
2679  src->vb_ip.prefix);
2680  return -1;
2681  }
2682  FALL_THROUGH;
2683 
2684  case FR_TYPE_IPV6_ADDR: /* Needed for handling combo addresses */
2685  memcpy(dst->vb_ip.addr.v6.s6_addr, src->vb_ip.addr.v6.s6_addr,
2686  sizeof(dst->vb_ip.addr.v6.s6_addr));
2687  dst->vb_ip.scope_id = src->vb_ip.scope_id;
2688  break;
2689 
2690  case FR_TYPE_OCTETS:
2691  if (src->vb_length != sizeof(dst->vb_ip.addr.v6.s6_addr)) {
2692  fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
2693  fr_type_to_str(src->type),
2694  fr_type_to_str(dst_type),
2695  sizeof(dst->vb_ip.addr.v6.s6_addr), src->vb_length);
2696  return -1;
2697  }
2698  memcpy(&dst->vb_ip.addr.v6.s6_addr, src->vb_octets, sizeof(dst->vb_ip.addr.v6.s6_addr));
2699  break;
2700 
2701  default:
2702  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2703  fr_type_to_str(src->type),
2704  fr_type_to_str(dst_type));
2705  break;
2706  }
2707 
2708  return 0;
2709 }
2710 
2711 /** Convert any supported type to an IPv6 address
2712  *
2713  * Allowed input types are:
2714  * - FR_TYPE_IPV4_ADDR
2715  * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2716  * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2717  * - FR_TYPE_OCTETS (of length 16).
2718  *
2719  * @param ctx unused.
2720  * @param dst Where to write result of casting.
2721  * @param dst_type to cast to.
2722  * @param dst_enumv enumeration values.
2723  * @param src Input data.
2724  */
2725 static inline int fr_value_box_cast_to_ipv6prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
2726  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2727  fr_value_box_t const *src)
2728 {
2729  fr_type_t src_type = src->type;
2730 
2731  fr_assert(dst_type == FR_TYPE_IPV6_PREFIX);
2732 
2733  switch (src_type) {
2734  case FR_TYPE_STRING:
2735  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2736  src->vb_strvalue, src->vb_length,
2737  NULL, src->tainted);
2738 
2740 
2741  default:
2742  break;
2743  }
2744 
2745  /*
2746  * Pre-initialise box for non-variable types
2747  */
2748  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2749  dst->vb_ip.af = AF_INET6;
2750 
2751  switch (src_type) {
2752  case FR_TYPE_IPV4_ADDR:
2753  {
2754  uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2755 
2756  /* Add the v4/v6 mapping prefix */
2757  memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2758  p += sizeof(v4_v6_map);
2759  memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2760  dst->vb_ip.prefix = 128;
2761  dst->vb_ip.scope_id = 0;
2762  }
2763  break;
2764 
2765  case FR_TYPE_IPV4_PREFIX:
2766  {
2767  uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2768 
2769  /* Add the v4/v6 mapping prefix */
2770  memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2771  p += sizeof(v4_v6_map);
2772  memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2773  dst->vb_ip.prefix = (sizeof(v4_v6_map) << 3) + src->vb_ip.prefix;
2774  dst->vb_ip.scope_id = 0;
2775  }
2776  break;
2777 
2778  case FR_TYPE_IPV6_PREFIX: /* Needed for handling combo prefixes */
2779  dst->vb_ip.prefix = src->vb_ip.prefix;
2780  goto v6_common;
2781 
2782  case FR_TYPE_IPV6_ADDR:
2783  dst->vb_ip.prefix = 128;
2784  v6_common:
2785  memcpy(dst->vb_ip.addr.v6.s6_addr, src->vb_ip.addr.v6.s6_addr,
2786  sizeof(dst->vb_ip.addr.v6.s6_addr));
2787  dst->vb_ip.scope_id = src->vb_ip.scope_id;
2788  break;
2789 
2790  case FR_TYPE_OCTETS:
2791  if (src->vb_length != (sizeof(dst->vb_ip.addr.v6.s6_addr) + 2)) {
2792  fr_strerror_printf("Invalid cast from %s to %s. Needed octet string of length %zu, got %zu",
2793  fr_type_to_str(src->type),
2794  fr_type_to_str(dst_type),
2795  sizeof(dst->vb_ip.addr.v6.s6_addr) + 2, src->vb_length);
2796  return -1;
2797  }
2798  dst->vb_ip.scope_id = src->vb_octets[0];
2799  dst->vb_ip.prefix = src->vb_octets[1];
2800  memcpy(&dst->vb_ip.addr.v6.s6_addr, src->vb_octets, sizeof(dst->vb_ip.addr.v6.s6_addr));
2801  break;
2802 
2803  default:
2804  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2805  fr_type_to_str(src->type),
2806  fr_type_to_str(dst_type));
2807  return -1;
2808  }
2809  return 0;
2810 }
2811 
2812 /** Convert any supported type to an ethernet address
2813  *
2814  * Allowed input types are:
2815  * - FR_TYPE_STRING ("00:11:22:33:44:55")
2816  * - FR_TYPE_OCTETS (0x001122334455)
2817  *
2818  *
2819  * @param ctx unused.
2820  * @param dst Where to write result of casting.
2821  * @param dst_type to cast to.
2822  * @param dst_enumv enumeration values.
2823  * @param src Input data.
2824  */
2825 static inline int fr_value_box_cast_to_ethernet(TALLOC_CTX *ctx, fr_value_box_t *dst,
2826  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2827  fr_value_box_t const *src)
2828 {
2829  fr_assert(dst_type == FR_TYPE_ETHERNET);
2830 
2831  switch (src->type) {
2832  case FR_TYPE_STRING:
2833  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2834  src->vb_strvalue, src->vb_length,
2835  NULL, src->tainted);
2836 
2837  case FR_TYPE_OCTETS:
2838  return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
2839 
2840  default:
2841  break;
2842  }
2843 
2844  /*
2845  * Pre-initialise box for non-variable types
2846  */
2847  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2848 
2849  switch (src->type) {
2850  case FR_TYPE_UINT64: {
2851  uint8_t array[8];
2852 
2853  fr_nbo_from_uint64(array, src->vb_uint64);
2854 
2855  /*
2856  * For OUIs in the DB.
2857  */
2858  if ((array[0] != 0) || (array[1] != 0)) return -1;
2859 
2860  memcpy(dst->vb_ether, &array[2], 6);
2861  break;
2862  }
2863 
2864  default:
2865  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2866  fr_type_to_str(src->type),
2867  fr_type_to_str(dst_type));
2868  return -1;
2869  }
2870 
2871  return 0;
2872 }
2873 
2874 /** Convert any supported type to a bool
2875  *
2876  * Allowed input types are:
2877  * - FR_TYPE_STRING ("yes", "true", "no", "false")
2878  *
2879  * @param ctx unused.
2880  * @param dst Where to write result of casting.
2881  * @param dst_type to cast to.
2882  * @param dst_enumv enumeration values.
2883  * @param src Input data.
2884  */
2885 static inline int fr_value_box_cast_to_bool(TALLOC_CTX *ctx, fr_value_box_t *dst,
2886  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2887  fr_value_box_t const *src)
2888 {
2889  fr_assert(dst_type == FR_TYPE_BOOL);
2890 
2891  switch (src->type) {
2892  case FR_TYPE_STRING:
2893  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2894  src->vb_strvalue, src->vb_length,
2895  NULL, src->tainted);
2896 
2897  case FR_TYPE_OCTETS:
2898  /*
2899  * This is really "bool from network"
2900  */
2901  return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
2902 
2903  default:
2904  break;
2905  }
2906 
2907  /*
2908  * Pre-initialise box for non-variable types
2909  */
2910  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2911 
2912  switch (src->type) {
2913  case FR_TYPE_INT8:
2914  dst->vb_bool = (src->vb_int8 != 0);
2915  break;
2916 
2917  case FR_TYPE_UINT8:
2918  dst->vb_bool = (src->vb_uint8 != 0);
2919  break;
2920 
2921  case FR_TYPE_INT16:
2922  dst->vb_bool = (src->vb_int16 != 0);
2923  break;
2924 
2925  case FR_TYPE_UINT16:
2926  dst->vb_bool = (src->vb_uint16 != 0);
2927  break;
2928 
2929  case FR_TYPE_INT32:
2930  dst->vb_bool = (src->vb_int32 != 0);
2931  break;
2932 
2933  case FR_TYPE_UINT32:
2934  dst->vb_bool = (src->vb_uint32 != 0);
2935  break;
2936 
2937  case FR_TYPE_INT64:
2938  dst->vb_bool = (src->vb_int64 != 0);
2939  break;
2940 
2941  case FR_TYPE_UINT64:
2942  dst->vb_bool = (src->vb_uint64 != 0);
2943  break;
2944 
2945  case FR_TYPE_SIZE:
2946  dst->vb_bool = (src->vb_size != 0);
2947  break;
2948 
2949  case FR_TYPE_TIME_DELTA:
2950  dst->vb_bool = (fr_time_delta_unwrap(src->vb_time_delta) != 0);
2951  break;
2952 
2953  case FR_TYPE_FLOAT32:
2954  dst->vb_bool = (fpclassify(src->vb_float32) == FP_ZERO);
2955  break;
2956 
2957  case FR_TYPE_FLOAT64:
2958  dst->vb_bool = (fpclassify(src->vb_float64) == FP_ZERO);
2959  break;
2960 
2961  default:
2962  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
2963  fr_type_to_str(src->type),
2964  fr_type_to_str(dst_type));
2965  return -1;
2966  }
2967 
2968  return 0;
2969 }
2970 
2971 /** Convert any signed or unsigned integer type to any other signed or unsigned integer type
2972  *
2973  */
2974 static inline int fr_value_box_cast_integer_to_integer(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
2975  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2976  fr_value_box_t const *src)
2977 {
2978  uint64_t tmp = 0;
2979  size_t len = fr_value_box_field_sizes[src->type];
2980  int64_t min;
2981 
2982 #define SIGN_BIT_HIGH(_int, _len) ((((uint64_t)1) << (((_len) << 3) - 1)) & (_int))
2983 #define SIGN_PROMOTE(_int, _len) ((_len) < sizeof(_int) ? \
2984  (_int) | (~((__typeof__(_int))0)) << ((_len) << 3) : (_int))
2985 
2986 #if !defined(NDEBUG) || defined(STATIC_ANALYZER)
2987  /*
2988  * Helps catch invalid fr_value_box_field_sizes
2989  * entries, and shuts up clang analyzer.
2990  */
2991  if (!fr_cond_assert_msg(len > 0, "Invalid cast from %s to %s. "
2992  "invalid source type len, expected > 0, got %zu",
2993  fr_type_to_str(src->type),
2994  fr_type_to_str(dst_type),
2995  len)) return -1;
2996 
2997  if (!fr_cond_assert_msg(len <= sizeof(uint64_t),
2998  "Invalid cast from %s to %s. "
2999  "invalid source type len, expected <= %zu, got %zu",
3000  fr_type_to_str(src->type),
3001  fr_type_to_str(dst_type),
3002  sizeof(uint64_t), len)) return -1;
3003 #endif
3004 
3005  switch (src->type) {
3006  /*
3007  * Dates are always represented in nanoseconds
3008  * internally, but when we convert to another
3009  * integer type, we scale appropriately.
3010  *
3011  * i.e. if the attribute value resolution is
3012  * seconds, then the integer value is
3013  * nanoseconds -> seconds.
3014  */
3015  case FR_TYPE_DATE:
3016  {
3018  if (src->enumv) res = src->enumv->flags.flag_time_res;
3019 
3020  tmp = fr_unix_time_to_integer(src->vb_date, res);
3021  }
3022  break;
3023 
3024  /*
3025  * Same deal with time deltas. Note that
3026  * even though we store the value as an
3027  * unsigned integer, it'll be cast to a
3028  * signed integer for comparisons.
3029  */
3030  case FR_TYPE_TIME_DELTA:
3031  {
3033 
3034  if (src->enumv) res = src->enumv->flags.flag_time_res;
3035 
3036  tmp = (uint64_t)fr_time_delta_to_integer(src->vb_time_delta, res);
3037  }
3038  break;
3039 
3040  default:
3041 #ifdef WORDS_BIGENDIAN
3042  memcpy(((uint8_t *)&tmp) + (sizeof(tmp) - len),
3043  fr_value_box_raw(src, src->type), len);
3044 #else
3045  memcpy(&tmp, fr_value_box_raw(src, src->type), len);
3046 #endif
3047  break;
3048  }
3049 
3050  min = fr_value_box_integer_min[dst_type];
3051 
3052  /*
3053  * Sign promote the input if the source type is
3054  * signed, and the high bit is set.
3055  */
3056  if (fr_value_box_integer_min[src->type] < 0) {
3057  if (SIGN_BIT_HIGH(tmp, len)) tmp = SIGN_PROMOTE(tmp, len);
3058 
3059  if ((int64_t)tmp < min) {
3060  fr_strerror_printf("Invalid cast from %s to %s. %"PRId64" "
3061  "outside value range %"PRId64"-%"PRIu64,
3062  fr_type_to_str(src->type),
3063  fr_type_to_str(dst_type),
3064  (int64_t)tmp,
3065  min, fr_value_box_integer_max[dst_type]);
3066  return -1;
3067  }
3068  } else if (tmp > fr_value_box_integer_max[dst_type]) {
3069  fr_strerror_printf("Invalid cast from %s to %s. %"PRIu64" "
3070  "outside value range 0-%"PRIu64,
3071  fr_type_to_str(src->type),
3072  fr_type_to_str(dst_type),
3073  tmp, fr_value_box_integer_max[dst_type]);
3074  return -1;
3075  }
3076 
3077  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3078  switch (dst_type) {
3079  case FR_TYPE_DATE:
3080  {
3081  bool overflow;
3083  if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3084 
3085  dst->vb_date = fr_unix_time_from_integer(&overflow, tmp, res);
3086  if (overflow) {
3087  fr_strerror_const("Input to data type would overflow");
3088  return -1;
3089  }
3090  }
3091  break;
3092 
3093  case FR_TYPE_TIME_DELTA:
3094  {
3095  bool overflow;
3097  if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3098 
3099  dst->vb_time_delta = fr_time_delta_from_integer(&overflow, tmp, res);
3100  if (overflow) {
3101  fr_strerror_const("Input to time_delta type would overflow");
3102  return -1;
3103  }
3104  }
3105  break;
3106 
3107  default:
3108 #ifdef WORDS_BIGENDIAN
3109  memcpy(fr_value_box_raw(dst, dst->type),
3110  ((uint8_t *)&tmp) + (sizeof(tmp) - len), fr_value_box_field_sizes[dst_type]);
3111 #else
3112  memcpy(fr_value_box_raw(dst, dst->type),
3113  &tmp, fr_value_box_field_sizes[dst_type]);
3114 #endif
3115  break;
3116  }
3117 
3118  return 0;
3119 }
3120 
3121 /** Convert any value to a signed or unsigned integer
3122  *
3123  * @param ctx unused.
3124  * @param dst Where to write result of casting.
3125  * @param dst_type to cast to.
3126  * @param dst_enumv enumeration values.
3127  * @param src Input data.
3128  */
3129 static inline int fr_value_box_cast_to_integer(TALLOC_CTX *ctx, fr_value_box_t *dst,
3130  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3131  fr_value_box_t const *src)
3132 {
3133  switch (src->type) {
3134  case FR_TYPE_STRING:
3135  return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3136  src->vb_strvalue, src->vb_length,
3137  NULL, src->tainted);
3138 
3139  case FR_TYPE_OCTETS:
3140  return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3141 
3142  case FR_TYPE_INTEGER:
3143  return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, src);
3144 
3145  case FR_TYPE_IPV4_ADDR:
3146  case FR_TYPE_IPV4_PREFIX:
3147  {
3148  fr_value_box_t tmp;
3149 
3150  switch (dst_type) {
3151  case FR_TYPE_UINT32:
3152  case FR_TYPE_INT64:
3153  case FR_TYPE_UINT64:
3154  case FR_TYPE_DATE:
3155  case FR_TYPE_TIME_DELTA:
3156  break;
3157 
3158  default:
3159  goto bad_cast;
3160  }
3161 
3162  fr_value_box_init(&tmp, FR_TYPE_UINT32, src->enumv, src->tainted);
3163  memcpy(&tmp.vb_uint32, &src->vb_ip.addr.v4, sizeof(tmp.vb_uint32));
3164  fr_value_box_hton(&tmp, &tmp);
3165  return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3166  }
3167 
3168  case FR_TYPE_ETHERNET:
3169  {
3170  fr_value_box_t tmp;
3171 
3172  switch (dst_type) {
3173  case FR_TYPE_INT64:
3174  case FR_TYPE_UINT64:
3175  case FR_TYPE_DATE:
3176  case FR_TYPE_TIME_DELTA:
3177  break;
3178 
3179  default:
3180  goto bad_cast;
3181  }
3182 
3183  fr_value_box_init(&tmp, FR_TYPE_UINT64, src->enumv, src->tainted);
3184  memcpy(((uint8_t *)&tmp.vb_uint64) + (sizeof(tmp.vb_uint64) - sizeof(src->vb_ether)),
3185  &src->vb_ether, sizeof(src->vb_ether));
3186 #ifndef WORDS_BIGENDIAN
3187  /*
3188  * Ethernet addresses are always stored bigendian,
3189  * convert to native on little endian systems
3190  */
3191  fr_value_box_hton(&tmp, &tmp);
3192 #endif
3193  return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3194  }
3195 
3196  case FR_TYPE_IFID:
3197  {
3198  switch (dst_type) {
3199  case FR_TYPE_UINT64:
3200  break;
3201 
3202  default:
3203  goto bad_cast;
3204  }
3205 
3206  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3207  dst->vb_uint64 = fr_nbo_to_uint64(&src->vb_ifid[0]);
3208  return 0;
3209  }
3210 
3211  default:
3212  break;
3213  }
3214 
3215 bad_cast:
3216  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
3217  fr_type_to_str(src->type),
3218  fr_type_to_str(dst_type));
3219  return -1;
3220 }
3221 
3222 /** Convert any value to a floating point value
3223  *
3224  * @param ctx unused.
3225  * @param dst Where to write result of casting.
3226  * @param dst_type to cast to.
3227  * @param dst_enumv enumeration values.
3228  * @param src Input data.
3229  */
3230 static inline int fr_value_box_cast_to_float(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
3231  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3232  fr_value_box_t const *src)
3233 {
3234  double num;
3235 
3236  switch (src->type) {
3237  case FR_TYPE_FLOAT32:
3238  if (dst_type == FR_TYPE_FLOAT64) {
3239  num = (double) src->vb_float32;
3240  goto good_cast;
3241  }
3242 
3243  goto bad_cast;
3244 
3245  case FR_TYPE_FLOAT64:
3246  if (dst_type == FR_TYPE_FLOAT32) {
3247  num = src->vb_float64;
3248  goto good_cast;
3249  }
3250 
3251  goto bad_cast;
3252 
3253  case FR_TYPE_BOOL:
3254  num = src->vb_bool;
3255  goto good_cast;
3256 
3257  case FR_TYPE_INT8:
3258  num = src->vb_int8;
3259  goto good_cast;
3260 
3261  case FR_TYPE_INT16:
3262  num = src->vb_int16;
3263  goto good_cast;
3264 
3265  case FR_TYPE_INT32:
3266  num = src->vb_int32;
3267  goto good_cast;
3268 
3269  case FR_TYPE_INT64:
3270  num = src->vb_int64;
3271  goto good_cast;
3272 
3273  case FR_TYPE_UINT8:
3274  num = src->vb_uint8;
3275  goto good_cast;
3276 
3277  case FR_TYPE_UINT16:
3278  num = src->vb_uint16;
3279  goto good_cast;
3280 
3281  case FR_TYPE_UINT32:
3282  num = src->vb_uint32;
3283  goto good_cast;
3284 
3285  case FR_TYPE_UINT64:
3286  num = src->vb_uint64;
3287  goto good_cast;
3288 
3289  case FR_TYPE_DATE:
3290  /*
3291  * Unix times are in nanoseconds
3292  */
3293  num = fr_unix_time_unwrap(src->vb_date);
3294  num /= NSEC;
3295  goto good_cast;
3296 
3297  case FR_TYPE_TIME_DELTA:
3298  /*
3299  * Time deltas are in nanoseconds, but scaled.
3300  */
3301  num = fr_time_delta_unwrap(src->vb_time_delta);
3302  if (src->enumv) {
3303  num /= fr_time_multiplier_by_res[src->enumv->flags.flag_time_res];
3304  } else {
3305  num /= NSEC;
3306  }
3307  goto good_cast;
3308 
3309  case FR_TYPE_SIZE:
3310  num = src->vb_size;
3311 
3312  good_cast:
3313  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3314  if (dst_type == FR_TYPE_FLOAT32) {
3315  dst->vb_float32 = num;
3316  } else {
3317  dst->vb_float64 = num;
3318  }
3319  return 0;
3320 
3321  default:
3322  break;
3323  }
3324 
3325 bad_cast:
3326  fr_strerror_printf("Invalid cast from %s to %s. Unsupported",
3327  fr_type_to_str(src->type),
3328  fr_type_to_str(dst_type));
3329  return -1;
3330 }
3331 
3332 
3333 /** Convert one type of fr_value_box_t to another
3334  *
3335  * This should be the canonical function used to convert between INTERNAL data formats.
3336  *
3337  * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
3338  *
3339  * @note src and dst must not be the same box. We do not support casting in place.
3340  *
3341  * @param ctx to allocate buffers in (usually the same as dst)
3342  * @param dst Where to write result of casting.
3343  * @param dst_type to cast to.
3344  * @param dst_enumv Aliases for values contained within this fr_value_box_t.
3345  * If #fr_value_box_t is passed to #fr_value_box_aprint
3346  * names will be printed instead of actual value.
3347  * @param src Input data.
3348  * @return
3349  * - 0 on success.
3350  * - -1 on failure.
3351  */
3352 int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst,
3353  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3354  fr_value_box_t const *src)
3355 {
3356  if (!fr_cond_assert(dst_type != FR_TYPE_NULL)) return -1;
3357  if (!fr_cond_assert(src != dst)) return -1;
3358  if (!fr_cond_assert(src->type != FR_TYPE_NULL)) return -1;
3359 
3360  if (fr_type_is_non_leaf(dst_type)) {
3361  fr_strerror_printf("Invalid cast from %s to %s. Can only cast simple data types",
3362  fr_type_to_str(src->type),
3363  fr_type_to_str(dst_type));
3364  return -1;
3365  }
3366 
3367  /*
3368  * If it's the same type, copy, but set the enumv
3369  * in the destination box to be the one provided.
3370  *
3371  * The theory here is that the attribute value isn't
3372  * being converted into its presentation format and
3373  * re-parsed, and the enumv names only get applied
3374  * when converting internal values to/from strings,
3375  * so it's OK just to swap out the enumv.
3376  *
3377  * If there's a compelling case in the future we
3378  * might revisit this, but it'd likely mean fixing
3379  * all the casting functions to treat any value
3380  * with an enumv as a string, which seems weird.
3381  */
3382  if (dst_type == src->type) {
3383  int ret;
3384 
3385  ret = fr_value_box_copy(ctx, dst, src);
3386  if (ret < 0) return ret;
3387 
3388  dst->enumv = dst_enumv;
3389 
3390  return ret;
3391  }
3392 
3393  /*
3394  * Initialise dst
3395  */
3396  fr_value_box_init(dst, dst_type, NULL, src->tainted);
3397 
3398  /*
3399  * Dispatch to specialised cast functions
3400  */
3401  switch (dst_type) {
3402  case FR_TYPE_STRING:
3403  return fr_value_box_cast_to_strvalue(ctx, dst, dst_type, dst_enumv, src);
3404 
3405  case FR_TYPE_OCTETS:
3406  return fr_value_box_cast_to_octets(ctx, dst, dst_type, dst_enumv, src);
3407 
3408  case FR_TYPE_IPV4_ADDR:
3409  return fr_value_box_cast_to_ipv4addr(ctx, dst, dst_type, dst_enumv, src);
3410 
3411  case FR_TYPE_IPV4_PREFIX:
3412  return fr_value_box_cast_to_ipv4prefix(ctx, dst, dst_type, dst_enumv, src);
3413 
3414  case FR_TYPE_IPV6_ADDR:
3415  return fr_value_box_cast_to_ipv6addr(ctx, dst, dst_type, dst_enumv, src);
3416 
3417  case FR_TYPE_IPV6_PREFIX:
3418  return fr_value_box_cast_to_ipv6prefix(ctx, dst, dst_type, dst_enumv, src);
3419 
3420  case FR_TYPE_COMBO_IP_ADDR:
3422  break;
3423  /*
3424  * Need func
3425  */
3426  case FR_TYPE_IFID:
3427  break;
3428 
3429  case FR_TYPE_ETHERNET:
3430  return fr_value_box_cast_to_ethernet(ctx, dst, dst_type, dst_enumv, src);
3431 
3432  case FR_TYPE_BOOL:
3433  return fr_value_box_cast_to_bool(ctx, dst, dst_type, dst_enumv, src);
3434 
3435  case FR_TYPE_DATE:
3436  if (src->type != FR_TYPE_TIME_DELTA) return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
3437 
3438  if (fr_time_delta_isneg(src->vb_time_delta)) {
3439  fr_strerror_const("Input to data type would underflow");
3440  return -1;
3441  }
3442 
3443  dst->type = dst_type;
3444  dst->enumv = dst_enumv;
3445  dst->vb_date = fr_unix_time_wrap(fr_time_delta_unwrap(src->vb_time_delta));
3446  return 0;
3447 
3448  case FR_TYPE_TIME_DELTA:
3449  /*
3450  * Unix time cast to time_delta is just nanoseconds since the epoch.
3451  *
3452  * Note that we do NOT change time resolution, but we DO change enumv. Both unix time
3453  * and time_delta are tracked internally as nanoseconds, and the only use of precision is
3454  * for printing / parsing.
3455  */
3456  if (src->type == FR_TYPE_DATE) {
3457  uint64_t when;
3458 
3459  when = fr_unix_time_unwrap(src->vb_date);
3460  if (when > INT64_MAX) {
3461  fr_strerror_const("Input to data type would overflow");
3462  return -1;
3463  }
3464 
3465  dst->type = dst_type;
3466  dst->enumv = dst_enumv;
3467  dst->vb_time_delta = fr_time_delta_wrap((int64_t) when);
3468  return 0;
3469  }
3470  FALL_THROUGH;
3471 
3472  case FR_TYPE_UINT8:
3473  case FR_TYPE_UINT16:
3474  case FR_TYPE_UINT32:
3475  case FR_TYPE_UINT64:
3476  case FR_TYPE_INT8:
3477  case FR_TYPE_INT16:
3478  case FR_TYPE_INT32:
3479  case FR_TYPE_INT64:
3480  case FR_TYPE_SIZE:
3481  return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
3482 
3483  case FR_TYPE_FLOAT32:
3484  case FR_TYPE_FLOAT64:
3485  if (fr_type_is_fixed_size(src->type)) {
3486  return fr_value_box_cast_to_float(ctx, dst, dst_type, dst_enumv, src);
3487  }
3488  break; /* use generic string/octets stuff below */
3489 
3490  /*
3491  * Invalid types for casting (should have been caught earlier)
3492  */
3493  case FR_TYPE_VALUE_BOX:
3494  case FR_TYPE_STRUCTURAL:
3495  case FR_TYPE_NULL:
3496  case FR_TYPE_VOID:
3497  case FR_TYPE_MAX:
3498  fr_strerror_printf("Invalid cast from %s to %s. Invalid destination type",
3499  fr_type_to_str(src->type),
3500  fr_type_to_str(dst_type));
3501  return -1;
3502  }
3503 
3504  /*
3505  * Deserialise a fr_value_box_t
3506  */
3507  if (src->type == FR_TYPE_STRING) return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3508  src->vb_strvalue, src->vb_length,
3509  NULL, src->tainted);
3510 
3511  if (src->type == FR_TYPE_OCTETS) {
3512  fr_value_box_t tmp;
3513 
3514  if (src->vb_length < network_min_size(dst_type)) {
3515  fr_strerror_printf("Invalid cast from %s to %s. Source is length %zd is smaller than "
3516  "destination type size %zd",
3517  fr_type_to_str(src->type),
3518  fr_type_to_str(dst_type),
3519  src->vb_length,
3520  network_min_size(dst_type));
3521  return -1;
3522  }
3523 
3524  if (src->vb_length > network_max_size(dst_type)) {
3525  fr_strerror_printf("Invalid cast from %s to %s. Source length %zd is greater than "
3526  "destination type size %zd",
3527  fr_type_to_str(src->type),
3528  fr_type_to_str(dst_type),
3529  src->vb_length,
3530  network_max_size(dst_type));
3531  return -1;
3532  }
3533 
3534  fr_value_box_init(&tmp, dst_type, NULL, false);
3535 
3536  /*
3537  * Copy the raw octets into the datum of a value_box
3538  * inverting bytesex for uint32s (if LE).
3539  */
3540  memcpy(&tmp.datum, src->vb_octets, fr_value_box_field_sizes[dst_type]);
3541  tmp.type = dst_type;
3542  dst->enumv = dst_enumv;
3543 
3544  fr_value_box_hton(dst, &tmp);
3545  return 0;
3546  }
3547 
3548  memcpy(&dst->datum, &src->datum, fr_value_box_field_sizes[src->type]);
3549 
3550  dst->type = dst_type;
3551  dst->enumv = dst_enumv;
3552 
3553  return 0;
3554 }
3555 
3556 /** Convert one type of fr_value_box_t to another in place
3557  *
3558  * This should be the canonical function used to convert between INTERNAL data formats.
3559  *
3560  * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
3561  *
3562  * @param ctx to allocate buffers in (usually the same as dst)
3563  * @param vb to cast.
3564  * @param dst_type to cast to.
3565  * @param dst_enumv Aliases for values contained within this fr_value_box_t.
3566  * If #fr_value_box_t is passed to #fr_value_box_aprint
3567  * names will be printed instead of actual value.
3568  * @return
3569  * - 0 on success.
3570  * - -1 on failure.
3571  */
3573  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
3574 {
3575  fr_value_box_t tmp;
3576  /*
3577  * Store list pointers to restore later - fr_value_box_cast clears them
3578  */
3579  fr_value_box_entry_t entry = vb->entry;
3580 
3581  /*
3582  * Simple case, destination type and current
3583  * type are the same.
3584  */
3585  if (vb->type == dst_type) {
3586  vb->enumv = dst_enumv; /* Update the enumv as this may be different */
3587  return 0;
3588  }
3589 
3590  /*
3591  * Copy meta data and any existing buffers to
3592  * a temporary box. We then clear that value
3593  * box after the cast has been completed,
3594  * freeing any old buffers.
3595  */
3596  fr_value_box_copy_shallow(NULL, &tmp, vb);
3597 
3598  if (fr_value_box_cast(ctx, vb, dst_type, dst_enumv, &tmp) < 0) {
3599  /*
3600  * On error, make sure the original
3601  * box is left in a consistent state.
3602  */
3603  fr_value_box_copy_shallow(NULL, vb, &tmp);
3604  vb->entry = entry;
3605  return -1;
3606  }
3607  fr_value_box_clear_value(&tmp); /* Clear out any old buffers */
3608 
3609  /*
3610  * Restore list pointers
3611  */
3612  vb->entry = entry;
3613 
3614  return 0;
3615 }
3616 
3617 /** Assign a #fr_value_box_t value from an #fr_ipaddr_t
3618  *
3619  * Automatically determines the type of the value box from the ipaddr address family
3620  * and the length of the prefix field.
3621  *
3622  * @param[in] dst to assign ipaddr to.
3623  * @param[in] enumv Aliases for values.
3624  * @param[in] ipaddr to copy address from.
3625  * @param[in] tainted Whether the value came from a trusted source.
3626  * @return
3627  * - 0 on success.
3628  * - -1 on failure.
3629  */
3630 int fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ipaddr_t const *ipaddr, bool tainted)
3631 {
3632  fr_type_t type;
3633 
3634  switch (ipaddr->af) {
3635  case AF_INET:
3637  break;
3638 
3639  case AF_INET6:
3641  break;
3642 
3643  default:
3644  fr_strerror_printf("Invalid address family %i", ipaddr->af);
3645  return -1;
3646  }
3647 
3648  fr_value_box_init(dst, type, enumv, tainted);
3649  memcpy(&dst->vb_ip, ipaddr, sizeof(dst->vb_ip));
3650 
3651  return 0;
3652 }
3653 
3654 /** Unbox an IP address performing a type check
3655  *
3656  * @param[out] dst Where to copy the IP address to.
3657  * @param[in] src Where to copy the IP address from.
3658  * @return
3659  * - 0 on success.
3660  * - -1 on type mismatch.
3661  */
3663 {
3664  if (!fr_type_is_ip(src->type)) {
3665  fr_strerror_printf("Unboxing failed. Needed IPv4/6 addr/prefix, had type %s",
3666  fr_type_to_str(src->type));
3667  return -1;
3668  }
3669 
3670  memcpy(dst, &src->vb_ip, sizeof(*dst));
3671 
3672  return 0;
3673 }
3674 
3675 /** Clear/free any existing value
3676  *
3677  * @note Do not use on uninitialised memory.
3678  *
3679  * @param[in] data to clear.
3680  */
3682 {
3683  switch (data->type) {
3684  case FR_TYPE_OCTETS:
3685  case FR_TYPE_STRING:
3686  if (data->secret) memset_explicit(data->datum.ptr, 0, data->vb_length);
3687  talloc_free(data->datum.ptr);
3688  break;
3689 
3690  case FR_TYPE_GROUP:
3691  /*
3692  * Depth first freeing of children
3693  *
3694  * This ensures orderly freeing, regardless
3695  * of talloc hierarchy.
3696  */
3697  {
3698  fr_value_box_t *vb = NULL;
3699 
3700  while ((vb = fr_value_box_list_next(&data->vb_group, vb))) {
3702  talloc_free(vb);
3703  }
3704  }
3705  return;
3706 
3707  case FR_TYPE_NULL:
3708  return;
3709 
3710  default:
3711  break;
3712  }
3713 
3714  memset(&data->datum, 0, sizeof(data->datum));
3715 }
3716 
3717 /** Clear/free any existing value and metadata
3718  *
3719  * @note Do not use on uninitialised memory.
3720  *
3721  * @param[in] data to clear.
3722  */
3724 {
3726  fr_value_box_init(data, FR_TYPE_NULL, NULL, false);
3727 }
3728 
3729 /** Copy value data verbatim duplicating any buffers
3730  *
3731  * @note Will free any exiting buffers associated with the dst #fr_value_box_t.
3732  *
3733  * @param ctx To allocate buffers in.
3734  * @param dst Where to copy value_box to.
3735  * @param src Where to copy value_box from.
3736  * @return
3737  * - 0 on success.
3738  * - -1 on failure.
3739  */
3740 int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
3741 {
3742  switch (src->type) {
3743  default:
3744  fr_value_box_memcpy_out(fr_value_box_raw(dst, src->type), src);
3745  fr_value_box_copy_meta(dst, src);
3746  break;
3747 
3748  case FR_TYPE_NULL:
3749  fr_value_box_copy_meta(dst, src);
3750  break;
3751 
3752  case FR_TYPE_STRING:
3753  {
3754  char *str = NULL;
3755 
3756  /*
3757  * Zero length strings still have a one uint8 buffer
3758  */
3759  str = talloc_bstrndup(ctx, src->vb_strvalue, src->vb_length);
3760  if (!str) {
3761  fr_strerror_const("Failed allocating string buffer");
3762  return -1;
3763  }
3764  dst->vb_strvalue = str;
3765  fr_value_box_copy_meta(dst, src);
3766  }
3767  break;
3768 
3769  case FR_TYPE_OCTETS:
3770  {
3771  uint8_t *bin;
3772 
3773  if (src->vb_length) {
3774  bin = talloc_memdup(ctx, src->vb_octets, src->vb_length);
3775  if (!bin) {
3776  fr_strerror_const("Failed allocating octets buffer");
3777  return -1;
3778  }
3779  talloc_set_type(bin, uint8_t);
3780  } else {
3781  bin = talloc_array(ctx, uint8_t, 0);
3782  }
3783  dst->vb_octets = bin;
3784  fr_value_box_copy_meta(dst, src);
3785  }
3786  break;
3787 
3788  case FR_TYPE_GROUP:
3789  {
3790  fr_value_box_t *child = NULL;
3791 
3792  fr_value_box_copy_meta(dst, src); /* Initialises group child dlist */
3793 
3794  while ((child = fr_value_box_list_next(&src->vb_group, child))) {
3795  fr_value_box_t *new;
3796 
3797  /*
3798  * Build out the child
3799  */
3800  new = fr_value_box_alloc_null(ctx);
3801  if (unlikely(!new)) {
3802  group_error:
3803  fr_strerror_const("Failed duplicating group child");
3804  fr_value_box_list_talloc_free(&dst->vb_group);
3805  return -1;
3806  }
3807 
3808  /*
3809  * Populate it with the
3810  * data from the original
3811  * child.
3812  */
3813  if (unlikely(fr_value_box_copy(new, new, child) < 0)) goto group_error;
3814  fr_value_box_list_insert_tail(&dst->vb_group, new);
3815  }
3816  }
3817  break;
3818  }
3819 
3820  return 0;
3821 }
3822 
3823 /** Perform a shallow copy of a value_box
3824  *
3825  * Like #fr_value_box_copy, but does not duplicate the buffers of the src value_box.
3826  *
3827  * For #FR_TYPE_STRING and #FR_TYPE_OCTETS adds a reference from ctx so that the
3828  * buffer cannot be freed until the ctx is freed.
3829  *
3830  * @param[in] ctx to add reference from. If NULL no reference will be added.
3831  * @param[in] dst to copy value to.
3832  * @param[in] src to copy value from.
3833  */
3834 void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
3835 {
3836  switch (src->type) {
3837  default:
3838  fr_value_box_copy(NULL, dst, src);
3839  break;
3840 
3841  case FR_TYPE_STRING:
3842  case FR_TYPE_OCTETS:
3843  dst->datum.ptr = ctx ? talloc_reference(ctx, src->datum.ptr) : src->datum.ptr;
3844  fr_value_box_copy_meta(dst, src);
3845  break;
3846  }
3847 }
3848 
3849 /** Copy value data verbatim moving any buffers to the specified context
3850  *
3851  * @param[in] ctx to allocate any new buffers in.
3852  * @param[in] dst to copy value to.
3853  * @param[in] src to copy value from.
3854  * @return
3855  * - 0 on success.
3856  * - -1 on failure.
3857  */
3858 int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
3859 {
3860  if (!fr_cond_assert(src->type != FR_TYPE_NULL)) return -1;
3861 
3862  switch (src->type) {
3863  default:
3864  return fr_value_box_copy(ctx, dst, src);
3865 
3866  case FR_TYPE_STRING:
3867  {
3868  char const *str;
3869 
3870  str = talloc_steal(ctx, src->vb_strvalue);
3871  if (!str) {
3872  fr_strerror_const("Failed stealing string buffer");
3873  return -1;
3874  }
3875  talloc_set_type(str, char);
3876  dst->vb_strvalue = str;
3877  fr_value_box_copy_meta(dst, src);
3878  memset(&src->datum, 0, sizeof(src->datum));
3879  }
3880  return 0;
3881 
3882  case FR_TYPE_OCTETS:
3883  {
3884  uint8_t const *bin;
3885 
3886  bin = talloc_steal(ctx, src->vb_octets);
3887  if (!bin) {
3888  fr_strerror_const("Failed stealing octets buffer");
3889  return -1;
3890  }
3891  talloc_set_type(bin, uint8_t);
3892 
3893  dst->vb_octets = bin;
3894  fr_value_box_copy_meta(dst, src);
3895  memset(&src->datum, 0, sizeof(src->datum));
3896  }
3897  return 0;
3898 
3899  case FR_TYPE_GROUP:
3900  {
3901  fr_value_box_t *child;
3902 
3903  while ((child = fr_value_box_list_pop_head(&src->vb_group))) {
3904  child = talloc_steal(ctx, child);
3905  if (unlikely(!child)) {
3906  fr_strerror_const("Failed stealing child");
3907  return -1;
3908  }
3909  fr_value_box_list_insert_tail(&dst->vb_group, child);
3910  }
3911  }
3912  return 0;
3913  }
3914 }
3915 
3916 /** Copy a nul terminated string to a #fr_value_box_t
3917  *
3918  * @param[in] ctx to allocate any new buffers in.
3919  * @param[in] dst to assign new buffer to.
3920  * @param[in] enumv Aliases for values.
3921  * @param[in] src a nul terminated buffer.
3922  * @param[in] tainted Whether the value came from a trusted source.
3923  * @return
3924  * - 0 on success.
3925  * - -1 on failure.
3926  */
3927 int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
3928  char const *src, bool tainted)
3929 {
3930  char const *str;
3931 
3932  str = talloc_typed_strdup(ctx, src);
3933  if (!str) {
3934  fr_strerror_const("Failed allocating string buffer");
3935  return -1;
3936  }
3937 
3938  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
3939  dst->vb_strvalue = str;
3940  dst->vb_length = talloc_array_length(str) - 1;
3941 
3942  return 0;
3943 }
3944 
3945 /** Trim the length of the string buffer to match the length of the C string
3946  *
3947  * @param[in] ctx to re-alloc the buffer in.
3948  * @param[in,out] vb to trim.
3949  * @return
3950  * - 0 on success.
3951  * - -1 on failure.
3952  */
3953 int fr_value_box_strtrim(TALLOC_CTX *ctx, fr_value_box_t *vb)
3954 {
3955  size_t len;
3956  char *str;
3957 
3958  if (!fr_cond_assert(vb->type == FR_TYPE_STRING)) return -1;
3959 
3960  len = strlen(vb->vb_strvalue);
3961  str = talloc_realloc(ctx, UNCONST(char *, vb->vb_strvalue), char, len + 1);
3962  if (!str) {
3963  fr_strerror_const("Failed re-allocing string buffer");
3964  return -1;
3965  }
3966  vb->vb_length = len;
3967 
3968  return 0;
3969 }
3970 
3971 /** Print a formatted string using our internal printf wrapper and assign it to a value box
3972  *
3973  * @param[in] ctx to allocate any new buffers in.
3974  * @param[in] dst to assign new buffer to.
3975  * @param[in] enumv Aliases for values.
3976  * @param[in] fmt The printf format string to process.
3977  * @param[in] tainted Whether the value came from a trusted source.
3978  * @param[in] ap Substitution arguments.
3979  * @return
3980  * - 0 on success.
3981  * - -1 on failure.
3982  */
3983 int fr_value_box_vasprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
3984  char const *fmt, va_list ap)
3985 {
3986  va_list aq;
3987  char *str;
3988 
3989  va_copy(aq, ap); /* See vlog_module_failure_msg for why */
3990  str = fr_vasprintf(ctx, fmt, aq);
3991  va_end(aq);
3992 
3993  if (!str) return -1;
3994 
3995  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
3996  dst->vb_strvalue = str;
3997  dst->vb_length = talloc_array_length(str) - 1;
3998 
3999  return 0;
4000 }
4001 
4002 /** Print a formatted string using our internal printf wrapper and assign it to a value box
4003  *
4004  * @param[in] ctx to allocate any new buffers in.
4005  * @param[in] dst to assign new buffer to.
4006  * @param[in] enumv Aliases for values.
4007  * @param[in] tainted Whether the value came from a trusted source.
4008  * @param[in] fmt The printf format string to process.
4009  * @param[in] ... Substitution arguments.
4010  * @return
4011  * - 0 on success.
4012  * - -1 on failure.
4013  */
4014 int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
4015  char const *fmt, ...)
4016 {
4017  va_list ap;
4018  int ret;
4019 
4020  va_start(ap, fmt);
4021  ret = fr_value_box_vasprintf(ctx, dst, enumv, tainted, fmt, ap);
4022  va_end(ap);
4023 
4024  return ret;
4025 }
4026 
4027 /** Assign a buffer containing a nul terminated string to a box, but don't copy it
4028  *
4029  * @note Input string will not be duplicated.
4030  *
4031  * @param[in] dst to assign string to.
4032  * @param[in] enumv Aliases for values.
4033  * @param[in] src to copy string from.
4034  * @param[in] tainted Whether the value came from a trusted source.
4035  */
4037  char const *src, bool tainted)
4038 {
4039  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4040  dst->vb_strvalue = src;
4041  dst->vb_length = strlen(src);
4042 }
4043 
4044 /** Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one
4045  *
4046  * @note Input string will not be duplicated.
4047  *
4048  * @param[in] vb to replace string in.
4049  * @param[in] src to assign string from.
4050  * @param[in] len of src.
4051  */
4053 {
4055  vb->vb_strvalue = src;
4056  vb->vb_length = len < 0 ? strlen(src) : (size_t)len;
4057 }
4058 
4059 /** Alloc and assign an empty \0 terminated string to a #fr_value_box_t
4060  *
4061  * @param[in] ctx to allocate any new buffers in.
4062  * @param[out] out if non-null where to write a pointer to the new buffer.
4063  * @param[in] dst to assign new buffer to.
4064  * @param[in] enumv Aliases for values.
4065  * @param[in] len of buffer to allocate.
4066  * @param[in] tainted Whether the value came from a trusted source.
4067  * @return
4068  * - 0 on success.
4069  * - -1 on failure.
4070  */
4071 int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4072  size_t len, bool tainted)
4073 {
4074  char *str;
4075 
4076  str = talloc_zero_array(ctx, char, len + 1);
4077  if (!str) {
4078  fr_strerror_const("Failed allocating string buffer");
4079  return -1;
4080  }
4081  str[len] = '\0';
4082 
4083  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4084  dst->vb_strvalue = str;
4085  dst->vb_length = talloc_array_length(str) - 1;
4086 
4087  if (out) *out = str;
4088 
4089  return 0;
4090 }
4091 
4092 /** Change the length of a buffer already allocated to a value box
4093  *
4094  * @note Do not use on an uninitialised box.
4095  *
4096  * @param[in] ctx to realloc buffer in.
4097  * @param[out] out if non-null where to write a pointer to the new buffer.
4098  * @param[in] dst to realloc buffer for.
4099  * @param[in] len to realloc to (don't include nul byte).
4100  * @return
4101  * - 0 on success.
4102  * - -1 on failure.
4103  */
4104 int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
4105 {
4106  size_t clen;
4107  char *cstr;
4108  char *str;
4109 
4110  fr_assert(dst->type == FR_TYPE_STRING);
4111 
4112  memcpy(&cstr, &dst->vb_strvalue, sizeof(cstr));
4113 
4114  clen = talloc_array_length(dst->vb_strvalue) - 1;
4115  if (clen == len) return 0; /* No change */
4116 
4117  str = talloc_realloc(ctx, cstr, char, len + 1);
4118  if (!str) {
4119  fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len + 1);
4120  return -1;
4121  }
4122 
4123  /*
4124  * Zero out the additional bytes
4125  */
4126  if (clen < len) {
4127  memset(str + clen, '\0', (len - clen) + 1);
4128  } else {
4129  cstr[len] = '\0';
4130  }
4131  dst->vb_strvalue = str;
4132  dst->vb_length = len;
4133 
4134  if (out) *out = str;
4135 
4136  return 0;
4137 }
4138 
4139 /** Copy a string to to a #fr_value_box_t
4140  *
4141  * @param[in] ctx to allocate any new buffers in.
4142  * @param[in] dst to assign buffer to.
4143  * @param[in] enumv Aliases for values.
4144  * @param[in] src a string. May be NULL only if len == 0.
4145  * @param[in] len of src.
4146  * @param[in] tainted Whether the value came from a trusted source.
4147  */
4148 int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4149  char const *src, size_t len, bool tainted)
4150 {
4151  char const *str;
4152 
4153  if (unlikely((len > 0) && !src)) {
4154  fr_strerror_printf("Invalid arguments to %s. Len > 0 (%zu) but src string was NULL",
4155  __FUNCTION__, len);
4156  return -1;
4157  }
4158 
4159  str = talloc_bstrndup(ctx, src, len);
4160  if (!str) {
4161  fr_strerror_const("Failed allocating string buffer");
4162  return -1;
4163  }
4164 
4165  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4166  dst->vb_strvalue = str;
4167  dst->vb_length = len;
4168 
4169  return 0;
4170 }
4171 
4172 int fr_value_box_bstrndup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4173  fr_dbuff_t *dbuff, size_t len, bool tainted)
4174 {
4175  char *str;
4176 
4177  str = talloc_array(ctx, char, len + 1);
4178  if (!str) {
4179  fr_strerror_printf("Failed allocating string buffer");
4180  return -1;
4181  }
4182 
4183  if (fr_dbuff_out_memcpy((uint8_t *)str, dbuff, len) < 0) return -1;
4184  str[len] = '\0';
4185 
4186  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4187  dst->vb_strvalue = str;
4188  dst->vb_length = len;
4189 
4190  return 0;
4191 }
4192 
4193 /** Copy a nul terminated talloced buffer to a #fr_value_box_t
4194  *
4195  * Copy a talloced nul terminated buffer, setting fields in the dst value box appropriately.
4196  *
4197  * The buffer must be \0 terminated, or an error will be returned.
4198  *
4199  * @param[in] ctx to allocate any new buffers in.
4200  * @param[in] dst to assign new buffer to.
4201  * @param[in] enumv Aliases for values.
4202  * @param[in] src a talloced nul terminated buffer.
4203  * @param[in] tainted Whether the value came from a trusted source.
4204  * @return
4205  * - 0 on success.
4206  * - -1 on failure.
4207  */
4208 int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4209  char const *src, bool tainted)
4210 {
4211  size_t len;
4212 
4213  (void)talloc_get_type_abort_const(src, char);
4214 
4215  len = talloc_array_length(src);
4216  if ((len == 0) || (src[len - 1] != '\0')) {
4217  fr_strerror_const("Input buffer not \\0 terminated");
4218  return -1;
4219  }
4220 
4221  return fr_value_box_bstrndup(ctx, dst, enumv, src, len - 1, tainted);
4222 }
4223 
4224 /** Assign a string to to a #fr_value_box_t
4225  *
4226  * @param[in] dst to assign new buffer to.
4227  * @param[in] enumv Aliases for values.
4228  * @param[in] src a string.
4229  * @param[in] len of src.
4230  * @param[in] tainted Whether the value came from a trusted source.
4231  */
4233  char const *src, size_t len, bool tainted)
4234 {
4235  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4236  dst->vb_strvalue = src;
4237  dst->vb_length = len;
4238 }
4239 
4240 /** Assign a talloced buffer containing a nul terminated string to a box, but don't copy it
4241  *
4242  * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4243  *
4244  * @param[in] ctx to add reference from. If NULL no reference will be added.
4245  * @param[in] dst to assign string to.
4246  * @param[in] enumv Aliases for values.
4247  * @param[in] src to copy string from.
4248  * @param[in] tainted Whether the value came from a trusted source.
4249  * @return
4250  * - 0 on success.
4251  * - -1 on failure.
4252  */
4254  char const *src, bool tainted)
4255 {
4256  size_t len;
4257 
4258  (void) talloc_get_type_abort_const(src, char);
4259 
4260  len = talloc_array_length(src);
4261  if ((len == 0) || (src[len - 1] != '\0')) {
4262  fr_strerror_const("Input buffer not \\0 terminated");
4263  return -1;
4264  }
4265 
4266  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4267  dst->vb_strvalue = ctx ? talloc_reference(ctx, src) : src;
4268  dst->vb_length = len - 1;
4269 
4270  return 0;
4271 }
4272 
4273 /** Append bytes from a buffer to an existing #fr_value_box_t
4274  *
4275  * @param[in] ctx Where to allocate any talloc buffers required.
4276  * @param[in] dst value box to append to.
4277  * @param[in] src octets data to append.
4278  * @param[in] len length of octets data.
4279  * @param[in] tainted Whether src is tainted.
4280  * @return
4281  * - 0 on success.
4282  * - -1 on failure.
4283  */
4284 int fr_value_box_bstrn_append(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, size_t len, bool tainted)
4285 {
4286  char *ptr, *nptr;
4287  size_t nlen;
4288 
4289  if (len == 0) return 0;
4290 
4291  if (dst->type != FR_TYPE_STRING) {
4292  fr_strerror_printf("%s: Expected boxed value of type %s, got type %s", __FUNCTION__,
4294  fr_type_to_str(dst->type));
4295  return -1;
4296  }
4297 
4298  ptr = dst->datum.ptr;
4299  if (!fr_cond_assert(ptr)) return -1;
4300 
4301  if (talloc_reference_count(ptr) > 0) {
4302  fr_strerror_printf("%s: Boxed value has too many references", __FUNCTION__);
4303  return -1;
4304  }
4305 
4306  nlen = dst->vb_length + len + 1;
4307  nptr = talloc_realloc(ctx, ptr, char, dst->vb_length + len + 1);
4308  if (!nptr) {
4309  fr_strerror_printf("%s: Realloc of %s array from %zu to %zu bytes failed",
4310  __FUNCTION__, talloc_get_name(ptr), talloc_array_length(ptr), nlen);
4311  return -1;
4312  }
4313  talloc_set_type(nptr, char);
4314  ptr = nptr;
4315 
4316  memcpy(ptr + dst->vb_length, src, len); /* Copy data into the realloced buffer */
4317 
4318  dst->tainted = dst->tainted || tainted;
4319  dst->datum.ptr = ptr;
4320  dst->vb_length += len;
4321 
4322  ptr[dst->vb_length] = '\0';
4323 
4324  return 0;
4325 }
4326 
4327 /** Append a talloced buffer to an existing fr_value_box_t
4328  *
4329  * @param[in] ctx Where to allocate any talloc buffers required.
4330  * @param[in] dst value box to append to.
4331  * @param[in] src string data to append.
4332  * @param[in] tainted Whether src is tainted.
4333  * @return
4334  * - 0 on success.
4335  * - -1 on failure.
4336  */
4337 int fr_value_box_bstr_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, bool tainted)
4338 {
4339  size_t len;
4340 
4341  (void) talloc_get_type_abort_const(src, char);
4342 
4343  len = talloc_array_length(src);
4344  if ((len == 0) || (src[len - 1] != '\0')) {
4345  fr_strerror_const("Input buffer not \\0 terminated");
4346  return -1;
4347  }
4348 
4349  return fr_value_box_bstrn_append(ctx, dst, src, len - 1, tainted);
4350 }
4351 
4352 /** Pre-allocate an octets buffer for filling by the caller
4353  *
4354  * @note Buffer will not be zeroed, as it's assumed the caller will be filling it.
4355  *
4356  * @param[in] ctx to allocate any new buffers in.
4357  * @param[out] out If non-null will be filled with a pointer to the
4358  * new buffer.
4359  * @param[in] dst to assign new buffer to.
4360  * @param[in] enumv Aliases for values.
4361  * @param[in] len of data in the buffer. If 0, a zero length
4362  * talloc buffer will be alloced. dst->vb_octets
4363  * will *NOT* be NULL. You should use the length
4364  * field of the box to determine if any value
4365  * is assigned.
4366  * @param[in] tainted Whether the value came from a trusted source.
4367  * @return
4368  * - 0 on success.
4369  * - -1 on failure.
4370  */
4371 int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4372  size_t len, bool tainted)
4373 {
4374  uint8_t *bin;
4375 
4376  bin = talloc_array(ctx, uint8_t, len);
4377  if (!bin) {
4378  fr_strerror_const("Failed allocating octets buffer");
4379  return -1;
4380  }
4381  talloc_set_type(bin, uint8_t);
4382 
4383  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4384  dst->vb_octets = bin;
4385  dst->vb_length = len;
4386 
4387  if (out) *out = bin;
4388 
4389  return 0;
4390 }
4391 
4392 /** Change the length of a buffer already allocated to a value box
4393  *
4394  * @note Do not use on an uninitialised box.
4395  *
4396  * @param[in] ctx to realloc buffer in.
4397  * @param[out] out if non-null where to write a pointer to the new buffer.
4398  * @param[in] dst to realloc buffer for.
4399  * @param[in] len to realloc to.
4400  * @return
4401  * - 0 on success.
4402  * - -1 on failure.
4403  */
4404 int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
4405 {
4406  size_t clen;
4407  uint8_t *cbin;
4408  uint8_t *bin;
4409 
4410  fr_assert(dst->type == FR_TYPE_OCTETS);
4411 
4412  memcpy(&cbin, &dst->vb_octets, sizeof(cbin));
4413 
4414  clen = talloc_array_length(dst->vb_octets);
4415  if (clen == len) return 0; /* No change */
4416 
4417  /*
4418  * Realloc the buffer. If the new length is 0, we
4419  * need to call talloc_array() instead of talloc_realloc()
4420  * as talloc_realloc() will fail.
4421  */
4422  if (len > 0) {
4423  bin = talloc_realloc(ctx, cbin, uint8_t, len);
4424  } else {
4425  bin = talloc_array(ctx, uint8_t, 0);
4426  }
4427  if (!bin) {
4428  fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len);
4429  return -1;
4430  }
4431 
4432  /*
4433  * Only free the original buffer once we've allocated
4434  * a new empty array.
4435  */
4436  if (len == 0) talloc_free(cbin);
4437 
4438  /*
4439  * Zero out the additional bytes
4440  */
4441  if (clen < len) memset(bin + clen, 0x00, len - clen);
4442  dst->vb_octets = bin;
4443  dst->vb_length = len;
4444 
4445  if (out) *out = bin;
4446 
4447  return 0;
4448 }
4449 
4450 /** Copy a buffer to a fr_value_box_t
4451  *
4452  * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
4453  *
4454  * @param[in] ctx to allocate any new buffers in.
4455  * @param[in] dst to assign new buffer to.
4456  * @param[in] enumv Aliases for values.
4457  * @param[in] src a buffer.
4458  * @param[in] len of data in the buffer. If 0, a zero length
4459  * talloc buffer will be alloced. dst->vb_octets
4460  * will *NOT* be NULL. You should use the length
4461  * field of the box to determine if any value
4462  * is assigned.
4463  * @param[in] tainted Whether the value came from a trusted source.
4464  * @return
4465  * - 0 on success.
4466  * - -1 on failure.
4467  */
4468 int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4469  uint8_t const *src, size_t len, bool tainted)
4470 {
4471  uint8_t *bin;
4472 
4473  if (unlikely((len > 0) && !src)) {
4474  fr_strerror_printf("Invalid arguments to %s. Len > 0 (%zu) but src was NULL",
4475  __FUNCTION__, len);
4476  return -1;
4477  }
4478 
4479  bin = talloc_memdup(ctx, src, len);
4480  if (!bin) {
4481  fr_strerror_const("Failed allocating octets buffer");
4482  return -1;
4483  }
4484  talloc_set_type(bin, uint8_t);
4485 
4486  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4487  dst->vb_octets = bin;
4488  dst->vb_length = len;
4489 
4490  return 0;
4491 }
4492 
4493 int fr_value_box_memdup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4494  fr_dbuff_t *dbuff, size_t len, bool tainted)
4495 {
4496  uint8_t *bin;
4497 
4498  bin = talloc_size(ctx, len);
4499  if (!bin) {
4500  fr_strerror_printf("Failed allocating octets buffer");
4501  return -1;
4502  }
4503  if (fr_dbuff_out_memcpy(bin, dbuff, len) < (ssize_t) len) return -1;
4504  talloc_set_type(bin, uint8_t);
4505 
4506  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4507  dst->vb_octets = bin;
4508  dst->vb_length = len;
4509 
4510  return 0;
4511 }
4512 
4513 /** Copy a talloced buffer to a fr_value_box_t
4514  *
4515  * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
4516  *
4517  * @param[in] ctx to allocate any new buffers in.
4518  * @param[in] dst to assign new buffer to.
4519  * @param[in] enumv Aliases for values.
4520  * @param[in] src a buffer.
4521  * @param[in] tainted Whether the value came from a trusted source.
4522  * @return
4523  * - 0 on success.
4524  * - -1 on failure.
4525  */
4526 int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4527  uint8_t const *src, bool tainted)
4528 {
4529  (void) talloc_get_type_abort_const(src, uint8_t);
4530 
4531  return fr_value_box_memdup(ctx, dst, enumv, src, talloc_array_length(src), tainted);
4532 }
4533 
4534 /** Assign a buffer to a box, but don't copy it
4535  *
4536  * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4537  *
4538  * Caller should set dst->taint = true, where the value was acquired from an untrusted source.
4539  *
4540  * @note Will free any exiting buffers associated with the value box.
4541  *
4542  * @param[in] dst to assign buffer to.
4543  * @param[in] enumv Aliases for values.
4544  * @param[in] src a talloced buffer.
4545  * @param[in] len of buffer.
4546  * @param[in] tainted Whether the value came from a trusted source.
4547  */
4549  uint8_t const *src, size_t len, bool tainted)
4550 {
4551  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4552  dst->vb_octets = src;
4553  dst->vb_length = len;
4554 }
4555 
4556 /** Assign a talloced buffer to a box, but don't copy it
4557  *
4558  * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4559  *
4560  * @param[in] ctx to allocate any new buffers in.
4561  * @param[in] dst to assign buffer to.
4562  * @param[in] enumv Aliases for values.
4563  * @param[in] src a talloced buffer.
4564  * @param[in] tainted Whether the value came from a trusted source.
4565  */
4566 void fr_value_box_memdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4567  uint8_t const *src, bool tainted)
4568 {
4569  (void) talloc_get_type_abort_const(src, uint8_t);
4570 
4571  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4572  dst->vb_octets = ctx ? talloc_reference(ctx, src) : src;
4573  dst->vb_length = talloc_array_length(src);
4574 }
4575 
4576 /** Append data to an existing fr_value_box_t
4577  *
4578  * @param[in] ctx Where to allocate any talloc buffers required.
4579  * @param[in] dst value box to append to.
4580  * @param[in] src octets data to append.
4581  * @param[in] len length of octets data.
4582  * @param[in] tainted Whether src is tainted.
4583  * @return
4584  * - 0 on success.
4585  * - -1 on failure.
4586  */
4587 int fr_value_box_mem_append(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, bool tainted)
4588 {
4589  uint8_t *nptr;
4590  size_t nlen;
4591 
4592  if (len == 0) return 0;
4593 
4594  if (dst->type != FR_TYPE_OCTETS) {
4595  fr_strerror_printf("%s: Expected boxed value of type %s, got type %s", __FUNCTION__,
4597  fr_type_to_str(dst->type));
4598  return -1;
4599  }
4600 
4601  if (!fr_cond_assert(dst->datum.ptr)) return -1;
4602 
4603  if (talloc_reference_count(dst->datum.ptr) > 0) {
4604  fr_strerror_printf("%s: Boxed value has too many references", __FUNCTION__);
4605  return -1;
4606  }
4607 
4608  nlen = dst->vb_length + len;
4609  nptr = talloc_realloc(ctx, dst->datum.ptr, uint8_t, dst->vb_length + len);
4610  if (!nptr) {
4611  fr_strerror_printf("%s: Realloc of %s array from %zu to %zu bytes failed",
4612  __FUNCTION__,
4613  talloc_get_name(dst->datum.ptr),
4614  talloc_array_length((uint8_t const *)dst->datum.ptr), nlen);
4615  return -1;
4616  }
4617 
4618  memcpy(nptr + dst->vb_length, src, len); /* Copy data into the realloced buffer */
4619 
4620  dst->tainted = dst->tainted || tainted;
4621  dst->datum.ptr = nptr;
4622  dst->vb_length += len;
4623 
4624  return 0;
4625 }
4626 
4627 /** Append a talloc buffer to an existing fr_value_box_t
4628  *
4629  * @param[in] ctx Where to allocate any talloc buffers required.
4630  * @param[in] dst value box to append to.
4631  * @param[in] src octets data to append.
4632  * @param[in] tainted Whether src is tainted.
4633  * @return
4634  * - 0 on success.
4635  * - -1 on failure.
4636  */
4637 int fr_value_box_mem_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, bool tainted)
4638 {
4639  return fr_value_box_mem_append(ctx, dst, src, talloc_array_length(src), tainted);
4640 }
4641 
4642 /** Increment a boxed value
4643  *
4644  * Implements safe integer overflow.
4645  *
4646  * @param[in] vb to increment.
4647  */
4649 {
4650  switch (vb->type) {
4651  case FR_TYPE_UINT8:
4652  vb->vb_uint8 = vb->vb_uint8 == UINT8_MAX ? 0 : vb->vb_uint8 + 1;
4653  return;
4654 
4655  case FR_TYPE_UINT16:
4656  vb->vb_uint16 = vb->vb_uint16 == UINT16_MAX ? 0 : vb->vb_uint16 + 1;
4657  return;
4658 
4659  case FR_TYPE_UINT32:
4660  vb->vb_uint32 = vb->vb_uint32 == UINT32_MAX ? 0 : vb->vb_uint32 + 1;
4661  return;
4662 
4663  case FR_TYPE_UINT64:
4664  vb->vb_uint64 = vb->vb_uint64 == UINT64_MAX ? 0 : vb->vb_uint64 + 1;
4665  return;
4666 
4667  case FR_TYPE_INT8:
4668  vb->vb_int8 = vb->vb_int8 == INT8_MAX ? INT8_MIN : vb->vb_int8 + 1;
4669  return;
4670 
4671  case FR_TYPE_INT16:
4672  vb->vb_int16 = vb->vb_int16 == INT16_MAX ? INT16_MIN : vb->vb_int16 + 1;
4673  return;
4674 
4675  case FR_TYPE_INT32:
4676  vb->vb_int32 = vb->vb_int32 == INT32_MAX ? INT32_MIN : vb->vb_int32 + 1;
4677  return;
4678 
4679  case FR_TYPE_INT64:
4680  vb->vb_int64 = vb->vb_int64 == INT64_MAX ? INT64_MIN : vb->vb_int64 + 1;
4681  return;
4682 
4683  default:
4684  return;
4685  }
4686 }
4687 
4688 /** Convert integer encoded as string to a fr_value_box_t type
4689  *
4690  * @param[out] dst where to write parsed value.
4691  * @param[in] dst_type type of integer to convert string to.
4692  * @param[in] dst_enumv Enumeration values.
4693  * @param[in] in String to convert to integer.
4694  * @param[in] rules for parsing string.
4695  * @param[in] tainted Whether the value came from a trusted source.
4696  * @return
4697  * - >= 0 on success (number of bytes parsed).
4698  * - < 0 on error (where the parse error occurred).
4699  */
4700 static inline CC_HINT(always_inline)
4702  fr_dict_attr_t const *dst_enumv,
4703  fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules, bool tainted)
4704 {
4705  fr_slen_t slen;
4707 
4708  fr_value_box_init(dst, dst_type, dst_enumv, tainted);
4709 
4710  switch (dst_type) {
4711  case FR_TYPE_UINT8:
4712  slen = fr_sbuff_out(&err, &dst->vb_uint8, in);
4713  break;
4714 
4715  case FR_TYPE_UINT16:
4716  slen = fr_sbuff_out(&err, &dst->vb_uint16, in);
4717  break;
4718 
4719  case FR_TYPE_UINT32:
4720  slen = fr_sbuff_out(&err, &dst->vb_uint32, in);
4721  break;
4722 
4723  case FR_TYPE_UINT64:
4724  slen = fr_sbuff_out(&err, &dst->vb_uint64, in);
4725  break;
4726 
4727  case FR_TYPE_INT8:
4728  slen = fr_sbuff_out(&err, &dst->vb_int8, in);
4729  break;
4730 
4731  case FR_TYPE_INT16:
4732  slen = fr_sbuff_out(&err, &dst->vb_int16, in);
4733  break;
4734 
4735  case FR_TYPE_INT32:
4736  slen = fr_sbuff_out(&err, &dst->vb_int32, in);
4737  break;
4738 
4739  case FR_TYPE_INT64:
4740  slen = fr_sbuff_out(&err, &dst->vb_int64, in);
4741  break;
4742 
4743  case FR_TYPE_SIZE:
4744  slen = fr_sbuff_out(&err, &dst->vb_size, in);
4745  break;
4746 
4747  case FR_TYPE_FLOAT32:
4748  slen = fr_sbuff_out(&err, &dst->vb_float32, in);
4749  break;
4750 
4751  case FR_TYPE_FLOAT64:
4752  slen = fr_sbuff_out(&err, &dst->vb_float64, in);
4753  break;
4754 
4755  default:
4756  fr_assert_fail(NULL);
4757  return -1;
4758  }
4759 
4760  if (slen < 0) {
4761  /*
4762  * If an enumeration attribute is provided and we
4763  * don't find an integer, assume this is an enumv
4764  * lookup fail, and produce a better error.
4765  */
4766  if (dst_enumv && dst_enumv->flags.has_value && (err == FR_SBUFF_PARSE_ERROR_NOT_FOUND)) {
4767  fr_sbuff_t our_in = FR_SBUFF(in);
4768  fr_sbuff_adv_until(&our_in, SIZE_MAX, rules->terminals,
4769  rules->escapes ? rules->escapes->chr : '\0');
4770 
4771  fr_strerror_printf("Invalid enumeration value \"%pV\" for attribute %s",
4772  fr_box_strvalue_len(fr_sbuff_start(&our_in), fr_sbuff_used(&our_in)),
4773  dst_enumv->name);
4774  return -1;
4775  }
4776 
4778  fr_strerror_printf("Failed parsing string as type '%s'",
4779  fr_type_to_str(dst_type));
4780  } else {
4781  fr_sbuff_parse_error_to_strerror(err);
4782  }
4783  }
4784 
4785 
4786  return slen;
4787 }
4788 
4789 /** Convert string value to a fr_value_box_t type
4790  *
4791  * @param[in] ctx to alloc strings in.
4792  * @param[out] dst where to write parsed value.
4793  * @param[in,out] dst_type of value data to create/dst_type of value created.
4794  * @param[in] dst_enumv fr_dict_attr_t with string names for uint32 values.
4795  * @param[in] in sbuff to read data from.
4796  * @param[in] rules unescape and termination rules.
4797  * @param[in] tainted Whether the value came from a trusted source.
4798  * @return
4799  * - >0 on success.
4800  * - <= 0 on parse error.
4801  */
4803  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
4804  fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules, bool tainted)
4805 {
4806  static fr_sbuff_parse_rules_t default_rules;
4807  fr_sbuff_t *unescaped = NULL;
4808  fr_sbuff_t our_in = FR_SBUFF(in);
4809  fr_ipaddr_t addr;
4810  fr_slen_t slen;
4811  char buffer[256];
4812 
4813  if (!rules) rules = &default_rules;
4814 
4816 
4817  /*
4818  * Lookup any names before continuing
4819  */
4820  if (dst_enumv && dst_enumv->flags.has_value) {
4821  size_t name_len;
4822  fr_dict_enum_value_t *enumv;
4823 
4824  (void) fr_sbuff_adv_past_str_literal(&our_in, "::");
4825 
4826  /*
4827  * Create a thread-local extensible buffer to
4828  * store unescaped data.
4829  *
4830  * This is created once per-thread (the first time
4831  * this function is called), and freed when the
4832  * thread exits.
4833  */
4834  FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096);
4835 
4836  name_len = fr_sbuff_out_unescape_until(unescaped, &our_in, SIZE_MAX,
4837  rules->terminals, rules->escapes);
4838  if (!name_len) {
4839  fr_sbuff_set_to_start(&our_in);
4840  goto parse; /* Zero length name can't match enum */
4841  }
4842 
4843  enumv = fr_dict_enum_by_name(dst_enumv, fr_sbuff_start(unescaped), fr_sbuff_used(unescaped));
4844  if (!enumv) {
4845  fr_sbuff_set_to_start(&our_in);
4846  goto parse; /* No enumeration matches escaped string */
4847  }
4848 
4849  /*
4850  * dst_type may not match enumv type
4851  */
4852  if (fr_value_box_cast(ctx, dst, dst_type, dst_enumv, enumv->value) < 0) return -1;
4853 
4854  FR_SBUFF_SET_RETURN(in, &our_in);
4855  }
4856 
4857 parse:
4858  /*
4859  * It's a variable ret src->dst_type so we just alloc a new buffer
4860  * of size len and copy.
4861  */
4862  switch (dst_type) {
4863  case FR_TYPE_STRING:
4864  /*
4865  * We've not unescaped the string yet, produce an unescaped version
4866  */
4867  if (!dst_enumv || !unescaped) {
4868  char *buff;
4869 
4870  if (unlikely(fr_sbuff_out_aunescape_until(ctx, &buff, &our_in, SIZE_MAX,
4871  rules->terminals, rules->escapes) < 0)) {
4872  return -1;
4873  }
4874  fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, buff, tainted);
4875  /*
4876  * We already have an unescaped version, just use that
4877  */
4878  } else {
4879  fr_value_box_bstrndup(ctx, dst, dst_enumv,
4880  fr_sbuff_start(unescaped), fr_sbuff_used(unescaped), tainted);
4881  }
4882  FR_SBUFF_SET_RETURN(in, &our_in);
4883 
4884  /* raw octets: 0x01020304... */
4885  case FR_TYPE_OCTETS:
4886  {
4887  fr_sbuff_marker_t hex_start;
4888  size_t hex_len;
4889  uint8_t *bin_buff;
4890 
4891  /*
4892  * If there's escape sequences that need to be processed
4893  * or the string doesn't start with 0x, then assume this
4894  * is literal data, not hex encoded data.
4895  */
4896  if (rules->escapes || !fr_sbuff_adv_past_strcase_literal(&our_in, "0x")) {
4897  if (!dst_enumv || !unescaped) {
4898  char *buff = NULL;
4899  uint8_t *bin;
4900 
4901  if (fr_sbuff_extend(&our_in)) {
4902  fr_sbuff_out_aunescape_until(ctx, &buff, &our_in, SIZE_MAX,
4903  rules->terminals, rules->escapes);
4904 
4905  if (talloc_array_length(buff) == 1) {
4906  talloc_free(buff);
4907  goto zero;
4908  }
4909 
4910  bin = talloc_realloc(ctx, buff, uint8_t, talloc_array_length(buff) - 1);
4911  if (unlikely(!bin)) {
4912  fr_strerror_const("Failed trimming string buffer");
4913  talloc_free(buff);
4914  return -1;
4915  }
4916  talloc_set_type(bin, uint8_t); /* talloc_realloc doesn't do this */
4917  /*
4918  * Input data is zero
4919  *
4920  * talloc realloc will refuse to realloc to
4921  * a zero length buffer. This is probably
4922  * a bug, because we can create zero length
4923  * arrays normally
4924  */
4925  } else {
4926  zero:
4927  bin = talloc_zero_array(ctx, uint8_t, 0);
4928  }
4929 
4930  fr_value_box_memdup_buffer_shallow(NULL, dst, dst_enumv, bin, tainted);
4931  /*
4932  * We already have an unescaped version, just use that
4933  */
4934  } else {
4935  fr_value_box_memdup(ctx, dst, dst_enumv,
4936  (uint8_t *)fr_sbuff_start(unescaped),
4937  fr_sbuff_used(unescaped), tainted);
4938  }
4939  FR_SBUFF_SET_RETURN(in, &our_in);
4940  }
4941 
4942  fr_sbuff_marker(&hex_start, &our_in); /* Record where the hexits start */
4943 
4944  /*
4945  * Find the end of the hex sequence.
4946  *
4947  * We don't technically need to do this, fr_base16_decode
4948  * will find the end on its own.
4949  *
4950  * We do this so we can alloc the correct sized
4951  * output buffer.
4952  */
4953  hex_len = fr_sbuff_adv_past_allowed(&our_in, SIZE_MAX, sbuff_char_class_hex, rules->terminals);
4954  if (hex_len == 0) {
4955  if (fr_value_box_memdup(ctx, dst, dst_enumv, (uint8_t[]){ 0x00 }, 0, tainted) < 0) return -1;
4956  FR_SBUFF_SET_RETURN(in, &our_in);
4957  }
4958 
4959  if ((hex_len & 0x01) != 0) {
4960  fr_strerror_printf("Length of hex string is not even, got %zu bytes", hex_len);
4961  FR_SBUFF_ERROR_RETURN(&our_in);
4962  }
4963 
4964  /*
4965  * Pre-allocate the bin buff and initialise the box
4966  */
4967  if (fr_value_box_mem_alloc(ctx, &bin_buff, dst, dst_enumv, (hex_len >> 1), tainted) < 0) return -1;
4968 
4969  /*
4970  * Reset to the start of the hex string
4971  */
4972  fr_sbuff_set(&our_in, &hex_start);
4973 
4974  if (unlikely(fr_base16_decode(NULL, &FR_DBUFF_TMP(bin_buff, hex_len), &our_in, false) < 0)) {
4975  talloc_free(bin_buff);
4976  FR_SBUFF_ERROR_RETURN(&our_in);
4977  }
4978 
4979  FR_SBUFF_SET_RETURN(in, &our_in);
4980  }
4981 
4982  case FR_TYPE_IPV4_ADDR:
4983  {
4984  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
4985  if (!name_len) return 0;
4986 
4987  if (fr_inet_pton4(&addr, fr_sbuff_current(in), name_len,
4988  fr_hostname_lookups, false, true) < 0) return -1;
4989 
4990  /*
4991  * We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
4992  * print them this way.
4993  */
4994  if (addr.prefix != 32) {
4995  fail_ipv4_prefix:
4996  fr_strerror_printf("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted "
4997  "for non-prefix types", addr.prefix);
4998  return -1;
4999  }
5000 
5001  memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5002  }
5003  goto finish;
5004 
5005  case FR_TYPE_IPV4_PREFIX:
5006  {
5007  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5008  if (!name_len) return 0;
5009 
5010  if (fr_inet_pton4(&dst->vb_ip, fr_sbuff_current(in), name_len,
5011  fr_hostname_lookups, false, true) < 0) return -1;
5012  }
5013  goto finish;
5014 
5015  case FR_TYPE_IPV6_ADDR:
5016  {
5017  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5018  if (!name_len) return 0;
5019 
5020  /*
5021  * Parse scope, too.
5022  */
5023  if (fr_sbuff_next_if_char(&our_in, '%')) {
5024  name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5025  }
5026 
5027  if (fr_inet_pton6(&addr, fr_sbuff_current(in), name_len,
5028  fr_hostname_lookups, false, true) < 0) return -1;
5029 
5030  /*
5031  * We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
5032  * print them this way.
5033  */
5034  if (addr.prefix != 128) {
5035  fail_ipv6_prefix:
5036  fr_strerror_printf("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted "
5037  "for non-prefix types", addr.prefix);
5038  return -1;
5039  }
5040 
5041  memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5042  }
5043  goto finish;
5044 
5045  case FR_TYPE_IPV6_PREFIX:
5046  {
5047  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5048  if (!name_len) return 0;
5049 
5050  if (fr_inet_pton6(&dst->vb_ip, fr_sbuff_current(in), name_len,
5051  fr_hostname_lookups, false, true) < 0) return -1;
5052  }
5053  goto finish;
5054 
5055  case FR_TYPE_COMBO_IP_ADDR:
5056  {
5057  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5058  if (!name_len) return 0;
5059 
5060  /*
5061  * Parse scope, too.
5062  */
5063  if (fr_sbuff_next_if_char(&our_in, '%')) {
5064  name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5065  }
5066 
5067  if (fr_inet_pton(&addr, fr_sbuff_current(in), name_len, AF_UNSPEC,
5068  fr_hostname_lookups, true) < 0) return -1;
5069 
5070  if ((addr.af == AF_INET) && (addr.prefix != 32)) {
5071  goto fail_ipv4_prefix;
5072  }
5073 
5074  if ((addr.af == AF_INET6) && (addr.prefix != 128)) {
5075  goto fail_ipv6_prefix;
5076  }
5077 
5078  memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5079  }
5080  goto finish;
5081 
5083  {
5084  size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5085  if (!name_len) return 0;
5086 
5087  if (fr_inet_pton(&dst->vb_ip, fr_sbuff_current(in), name_len, AF_UNSPEC,
5088  fr_hostname_lookups, true) < 0) return -1;
5089  }
5090  goto finish;
5091 
5092  case FR_TYPE_UINT8:
5093  case FR_TYPE_UINT16:
5094  case FR_TYPE_UINT32:
5095  case FR_TYPE_UINT64:
5096  case FR_TYPE_INT8:
5097  case FR_TYPE_INT16:
5098  case FR_TYPE_INT32:
5099  case FR_TYPE_INT64:
5100  case FR_TYPE_FLOAT32:
5101  case FR_TYPE_FLOAT64:
5102  return fr_value_box_from_numeric_substr(dst, dst_type, dst_enumv, in, rules, tainted);
5103 
5104  case FR_TYPE_SIZE:
5105  if (fr_size_from_str(&dst->datum.size, &our_in) < 0) return -1;
5106  goto finish;
5107 
5108  case FR_TYPE_BOOL:
5109  fr_value_box_init(dst, dst_type, dst_enumv, tainted);
5110 
5111  /*
5112  * Quoted boolean values are "yes", "no", "true", "false"
5113  */
5114  slen = fr_sbuff_out(NULL, &dst->vb_bool, in);
5115  if (slen >= 0) return slen;
5116 
5117  /*
5118  * For barewords we also allow 0 for false and any other
5119  * integer value for true.
5120  */
5121  if (!rules->escapes) {
5122  int64_t stmp;
5123  uint64_t utmp;
5124 
5125  slen = fr_sbuff_out(NULL, &stmp, in);
5126  if (slen >= 0) {
5127  dst->vb_bool = (stmp != 0);
5128  return slen;
5129  }
5130 
5131  slen = fr_sbuff_out(NULL, &utmp, in);
5132  if (slen >= 0) {
5133  dst->vb_bool = (utmp != 0);
5134  return slen;
5135  }
5136  }
5137 
5138  fr_strerror_const("Invalid boolean value. Accepted values are "
5139  "\"yes\", \"no\", \"true\", \"false\" or any unquoted integer");
5140 
5141  return slen; /* Just whatever the last error offset was */
5142 
5143  case FR_TYPE_ETHERNET:
5144  {
5145  uint64_t num;
5146  fr_ethernet_t ether;
5147  fr_dbuff_t dbuff;
5149 
5150  fr_dbuff_init(&dbuff, ether.addr, sizeof(ether.addr));
5151 
5152  /*
5153  * Convert things which are obviously integers to Ethernet addresses
5154  *
5155  * We assume the number is the decimal
5156  * representation of the ethernet address.
5157  * i.e. the ethernet address converted to a
5158  * number, and printed.
5159  *
5160  * The string gets converted to a network-order
5161  * 8-byte number, and then the lower bytes of
5162  * that get copied to the ethernet address.
5163  *
5164  * Note: We need to check for a terminal sequence
5165  * after the number, else we may just end up
5166  * parsing the first hexit and returning.
5167  *
5168  * i.e. 1c:00:00:00:00 -> 1
5169  */
5170  if ((fr_sbuff_out(NULL, &num, &our_in) > 0) && fr_sbuff_is_terminal(&our_in, rules->terminals)) {
5171  num = htonll(num);
5172 
5173  FR_DBUFF_IN_MEMCPY_RETURN(&dbuff, ((uint8_t *) &num) + 2, sizeof(dst->vb_ether));
5174  fr_value_box_ethernet_addr(dst, dst_enumv, &ether, tainted);
5175 
5176  FR_SBUFF_SET_RETURN(in, &our_in);
5177  }
5178 
5179  fr_sbuff_set_to_start(&our_in);
5180 
5181  fr_base16_decode(&err, &dbuff, &our_in, true);
5182  if (err != FR_SBUFF_PARSE_OK) {
5183  ether_error:
5184  fr_sbuff_parse_error_to_strerror(err);
5185  FR_SBUFF_ERROR_RETURN(&our_in);
5186  }
5187 
5188  if (!fr_sbuff_next_if_char(&our_in, ':')) {
5189  ether_sep_error:
5190  fr_strerror_const("Missing separator, expected ':'");
5191  FR_SBUFF_ERROR_RETURN(&our_in);
5192  }
5193 
5194  fr_base16_decode(&err, &dbuff, &our_in, true);
5195  if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5196 
5197  if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5198 
5199  fr_base16_decode(&err, &dbuff, &our_in, true);
5200  if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5201 
5202  if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5203 
5204  fr_base16_decode(&err, &dbuff, &our_in, true);
5205  if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5206 
5207  if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5208 
5209  fr_base16_decode(&err, &dbuff, &our_in, true);
5210  if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5211 
5212  if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5213 
5214  fr_base16_decode(&err, &dbuff, &our_in, true);
5215  if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5216 
5217  fr_value_box_ethernet_addr(dst, dst_enumv, (fr_ethernet_t * const)fr_dbuff_start(&dbuff), tainted);
5218 
5219  FR_SBUFF_SET_RETURN(in, &our_in);
5220  }
5221 
5222  case FR_TYPE_TIME_DELTA:
5223  fr_value_box_init(dst, FR_TYPE_TIME_DELTA, dst_enumv, tainted);
5224 
5225  slen = fr_time_delta_from_substr(&dst->datum.time_delta, &our_in,
5226  dst_enumv ? dst_enumv->flags.flag_time_res : FR_TIME_RES_SEC,
5227  false, rules->terminals);
5228  if (slen < 0) return slen;
5229  FR_SBUFF_SET_RETURN(in, &our_in);
5230 
5231  case FR_TYPE_NULL:
5232  if (!rules->escapes && fr_sbuff_adv_past_str_literal(&our_in, "NULL")) {
5233  fr_value_box_init(dst, dst_type, dst_enumv, tainted);
5234  FR_SBUFF_SET_RETURN(in, &our_in);
5235  }
5236 
5237  fr_strerror_const("String value was not NULL");
5238  return -1;
5239 
5240  /*
5241  * Dealt with below
5242  */
5243  default:
5244  break;
5245  }
5246 
5247  /*
5248  * We may have terminals. If so, respect them.
5249  */
5250  if (rules && rules->terminals) {
5251  size_t len;
5252 
5253  len = fr_sbuff_out_unescape_until(&FR_SBUFF_OUT(buffer, sizeof(buffer)), &our_in, SIZE_MAX,
5254  rules->terminals, rules->escapes);
5255  if (len >= sizeof(buffer)) goto too_small;
5256 
5257  buffer[len] = '\0';
5258 
5259  } else {
5260  /*
5261  * It's a fixed size src->dst_type, copy to a temporary buffer and
5262  * \0 terminate.
5263  *
5264  * @todo - note that this brute-force copy means that the input sbuff
5265  * is NOT advanced, and this function will return 0, even though it parsed data!
5266  */
5267  if (fr_sbuff_remaining(in) >= sizeof(buffer)) {
5268  too_small:
5269  fr_strerror_const("Temporary buffer too small");
5270  return -1;
5271  }
5272 
5274  buffer[fr_sbuff_remaining(in)] = '\0';
5275  }
5276 
5277  switch (dst_type) {
5278  case FR_TYPE_DATE:
5279  {
5280  if (dst_enumv) {
5281  if (fr_unix_time_from_str(&dst->vb_date, buffer, dst_enumv->flags.flag_time_res) < 0) return -1;
5282  } else {
5283  if (fr_unix_time_from_str(&dst->vb_date, buffer, FR_TIME_RES_SEC) < 0) return -1;
5284  }
5285 
5286  dst->enumv = dst_enumv;
5287  }
5288  break;
5289 
5290  case FR_TYPE_IFID:
5291  if (fr_inet_ifid_pton((void *) dst->vb_ifid, buffer) == NULL) {
5292  fr_strerror_printf("Failed to parse interface-id string \"%s\"", buffer);
5293  return -1;
5294  }
5295  break;
5296 
5297  default:
5298  fr_strerror_printf("Cannot parse input as data type %s", fr_type_to_str(dst_type));
5299  return -1;
5300  }
5301 
5302 finish:
5303  dst->type = dst_type;
5304  dst->tainted = tainted;
5305 
5306  /*
5307  * Fixup enumvs
5308  */
5309  dst->enumv = dst_enumv;
5310  fr_value_box_list_entry_init(dst);
5311 
5312  FR_SBUFF_SET_RETURN(in, &our_in);
5313 }
5314 
5316  fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
5317  char const *in, size_t inlen,
5318  fr_sbuff_unescape_rules_t const *erules, bool tainted)
5319 {
5320  ssize_t slen;
5321  fr_sbuff_parse_rules_t prules = { .escapes = erules };
5322 
5323  slen = fr_value_box_from_substr(ctx, dst, dst_type, dst_enumv, &FR_SBUFF_IN(in, inlen), &prules, tainted);
5324  if (slen <= 0) return slen;
5325 
5326  if (slen != (ssize_t)inlen) {
5327  fr_strerror_printf("Failed parsing '%s'. %zu bytes of trailing data after string value \"%pV\"",
5328  fr_type_to_str(dst_type),
5329  inlen - slen,
5330  fr_box_strvalue_len(in + slen, inlen - slen));
5331  return (slen - inlen) - 1;
5332  }
5333 
5334  return slen;
5335 }
5336 
5337 /** Print one boxed value to a string
5338  *
5339  * This function should primarily be used when a #fr_value_box_t is being
5340  * serialized in some non-standard way, i.e. as a value for a field
5341  * in a database, in all other instances it's better to use
5342  * #fr_value_box_print_quoted.
5343  *
5344  * @note - this function does NOT respect tainting! The escaping rules
5345  * are ONLY for escaping quotation characters, CR, LF, etc.
5346  *
5347  * @param[in] out Where to write the printed string.
5348  * @param[in] data Value box to print.
5349  * @param[in] e_rules To apply to FR_TYPE_STRING types, for escaping quotation characters _only_.
5350  * Is not currently applied to any other box type.
5351  */
5353 {
5354  fr_sbuff_t our_out = FR_SBUFF(out);
5355 
5356  char buf[1024]; /* Interim buffer to use with poorly behaved printing functions */
5357 
5358  if (data->enumv && data->enumv->flags.has_value) {
5359  char const *name;
5360 
5362  if (name) {
5363  FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(&our_out, name, NULL);
5364  goto done;
5365  }
5366  }
5367 
5368  switch (data->type) {
5369  case FR_TYPE_STRING:
5370  if (data->vb_length) FR_SBUFF_IN_ESCAPE_RETURN(&our_out,
5371  data->vb_strvalue, data->vb_length, e_rules);
5372  break;
5373 
5374  case FR_TYPE_OCTETS:
5375  FR_SBUFF_IN_CHAR_RETURN(&our_out, '0', 'x');
5376  if (data->vb_length) FR_SBUFF_RETURN(fr_base16_encode, &our_out,
5377  &FR_DBUFF_TMP(data->vb_octets, data->vb_length));
5378  break;
5379 
5380  /*
5381  * We need to use the proper inet_ntop functions for IP
5382  * addresses, else the output might not match output of
5383  * other functions, which makes testing difficult.
5384  *
5385  * An example is tunneled ipv4 in ipv6 addresses.
5386  */
5387  case FR_TYPE_IPV4_ADDR:
5388  case FR_TYPE_IPV6_ADDR:
5389  case FR_TYPE_COMBO_IP_ADDR:
5390  if (!fr_inet_ntop(buf, sizeof(buf), &data->vb_ip)) return 0;
5391  FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5392  break;
5393 
5394  case FR_TYPE_IPV4_PREFIX:
5395  case FR_TYPE_IPV6_PREFIX:
5397  if (!fr_inet_ntop_prefix(buf, sizeof(buf), &data->vb_ip)) return 0;
5398  FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5399  break;
5400 
5401  case FR_TYPE_IFID:
5402  if (!fr_inet_ifid_ntop(buf, sizeof(buf), data->vb_ifid)) return 0;
5403  FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5404  break;
5405 
5406  case FR_TYPE_ETHERNET:
5407  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%02x:%02x:%02x:%02x:%02x:%02x",
5408  data->vb_ether[0], data->vb_ether[1],
5409  data->vb_ether[2], data->vb_ether[3],
5410  data->vb_ether[4], data->vb_ether[5]);
5411  break;
5412 
5413  case FR_TYPE_BOOL:
5414  FR_SBUFF_IN_STRCPY_RETURN(&our_out, data->vb_uint8 ? "yes" : "no");
5415  break;
5416 
5417  case FR_TYPE_UINT8:
5418  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint8);
5419  break;
5420 
5421  case FR_TYPE_UINT16:
5422  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint16);
5423  break;
5424 
5425  case FR_TYPE_UINT32:
5426  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint32);
5427  break;
5428 
5429  case FR_TYPE_UINT64:
5430  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRIu64, data->vb_uint64);
5431  break;
5432 
5433  case FR_TYPE_INT8:
5434  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int8);
5435  break;
5436 
5437  case FR_TYPE_INT16:
5438  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int16);
5439  break;
5440 
5441  case FR_TYPE_INT32:
5442  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int32);
5443  break;
5444 
5445  case FR_TYPE_INT64:
5446  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRId64, data->vb_int64);
5447  break;
5448 
5449  case FR_TYPE_FLOAT32:
5450  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%f", (double) data->vb_float32);
5451  break;
5452 
5453  case FR_TYPE_FLOAT64:
5454  FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%g", data->vb_float64);
5455  break;
5456 
5457  case FR_TYPE_DATE:
5458  {
5460 
5461  if (data->enumv) res = data->enumv->flags.flag_time_res;
5462 
5463  FR_SBUFF_RETURN(fr_unix_time_to_str, &our_out, data->vb_date, res, true);
5464  break;
5465  }
5466 
5467  case FR_TYPE_SIZE:
5468  FR_SBUFF_RETURN(fr_size_to_str, &our_out, data->datum.size);
5469  break;
5470 
5471  case FR_TYPE_TIME_DELTA:
5472  {
5474  bool is_unsigned = false;
5475 
5476  if (data->enumv) {
5477  res = data->enumv->flags.flag_time_res;
5478  is_unsigned = data->enumv->flags.is_unsigned;
5479  }
5480 
5481 
5482  FR_SBUFF_RETURN(fr_time_delta_to_str, &our_out, data->vb_time_delta, res, is_unsigned);
5483  }
5484  break;
5485 
5486  case FR_TYPE_GROUP:
5487  /*
5488  * If the caller didn't ask to escape binary data
5489  * in 'octets' types, then we force that now.
5490  * Otherwise any 'octets' type which is buried
5491  * inside of a 'group' will get copied verbatim
5492  * from input to output, with no escaping!
5493  */
5494  if (!e_rules || (!e_rules->do_oct && !e_rules->do_hex)) {
5495  e_rules = &fr_value_escape_double;
5496  }
5497 
5498  /*
5499  * Represent groups as:
5500  *
5501  * { <value0>, <value1>, { <sub-value0>, <sub-value1>, <sub-valueN> }}
5502  */
5503  FR_SBUFF_IN_CHAR_RETURN(&our_out, '{');
5505  NULL, NULL, &our_out, UNCONST(fr_value_box_list_t *, &data->vb_group),
5506  ", ", (sizeof(", ") - 1), e_rules,
5507  0, 0, false);
5508  FR_SBUFF_IN_CHAR_RETURN(&our_out, '}');
5509  break;
5510 
5511  case FR_TYPE_NULL:
5512  FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "NULL");
5513  break;
5514  /*
5515  * Don't add default here
5516  */
5517  case FR_TYPE_TLV: /* Not a box type */
5518  case FR_TYPE_STRUCT: /* Not a box type */
5519  case FR_TYPE_VSA: /* Not a box type */
5520  case FR_TYPE_VENDOR: /* Not a box type */
5521  case FR_TYPE_VALUE_BOX:
5522  case FR_TYPE_VOID:
5523  case FR_TYPE_MAX:
5524  (void)fr_cond_assert(0);
5525  return 0;
5526  }
5527 
5528 done:
5529  FR_SBUFF_SET_RETURN(out, &our_out);
5530 }
5531 
5532 /** Print one boxed value to a string with quotes (where needed)
5533  *
5534  * @param[in] out Where to write the printed string.
5535  * @param[in] data Value box to print.
5536  * @param[in] quote To apply to FR_TYPE_STRING types.
5537  * Is not currently applied to any
5538  * other box type.
5539  */
5541 {
5542  fr_sbuff_t our_out = FR_SBUFF(out);
5543 
5544  if (quote == T_BARE_WORD) return fr_value_box_print(out, data, NULL);
5545 
5546  switch (data->type) {
5547  case FR_TYPE_QUOTED:
5548  FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
5550  FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
5551  break;
5552 
5553  default:
5554  return fr_value_box_print(out, data, NULL);
5555  }
5556 
5557  FR_SBUFF_SET_RETURN(out, &our_out);
5558 }
5559 
5560 /** Concatenate a list of value boxes together
5561  *
5562  * All boxes will be removed from the list.
5563  *
5564  * @param[out] tainted If nonnull, will be set to true if any input boxes are tainted.
5565  * bool pointed to must be initialised.
5566  * @param[out] secret If nonnull, will be set to true if any input boxes are secret.
5567  * @param[out] sbuff to write the result of the concatenation to.
5568  * @param[in] list to concatenate.
5569  * @param[in] sep Insert a separator between the values.
5570  * @param[in] sep_len Length of the separator.
5571  * @param[in] e_rules To apply to FR_TYPE_STRING types.
5572  * Is not currently applied to any other box type.
5573  * @param[in] proc_action What to do with the boxes in the list once
5574  * they've been processed.
5575  * @param[in] safe_for if value has this safe_for value, don't apply the escape rules.
5576  * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
5577  * we concat the contents of its children together.
5578  * If false, the contents will be cast to #FR_TYPE_STRING.
5579  * @return
5580  * - >=0 the number of bytes written to the sbuff.
5581  * - <0 how many additional bytes we would have needed to
5582  * concat the next box.
5583  */
5584 ssize_t fr_value_box_list_concat_as_string(bool *tainted, bool *secret, fr_sbuff_t *sbuff, fr_value_box_list_t *list,
5585  char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules,
5586  fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
5587 {
5588  fr_sbuff_t our_sbuff = FR_SBUFF(sbuff);
5589  ssize_t slen;
5590 
5591  if (fr_value_box_list_empty(list)) return 0;
5592 
5593  fr_value_box_list_foreach(list, vb) {
5594  switch (vb->type) {
5595  case FR_TYPE_GROUP:
5596  if (!flatten) goto print;
5597  slen = fr_value_box_list_concat_as_string(tainted, secret, &our_sbuff, &vb->vb_group,
5598  sep, sep_len, e_rules,
5599  proc_action, safe_for, flatten);
5600  break;
5601 
5602  case FR_TYPE_OCTETS:
5603 
5604  /*
5605  * Copy the raw string over, if necessary with escaping.
5606  */
5607  if (e_rules && (!fr_value_box_is_safe_for(vb, safe_for) || e_rules->do_oct || e_rules->do_hex)) {
5608  slen = fr_sbuff_in_escape(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length, e_rules);
5609  } else {
5610  slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
5611  }
5612  break;
5613 
5614  case FR_TYPE_STRING:
5615  if (!fr_value_box_is_safe_for(vb, safe_for) && e_rules) goto print;
5616 
5617  slen = fr_sbuff_in_bstrncpy(&our_sbuff, vb->vb_strvalue, vb->vb_length);
5618  break;
5619 
5620  case FR_TYPE_NULL: /* Skip null */
5621  continue;
5622 
5623  default:
5624  print:
5625  slen = fr_value_box_print(&our_sbuff, vb, e_rules);
5626  break;
5627  }
5628  if (slen < 0) {
5629  error:
5630  return slen;
5631  }
5632 
5633  if (sep && fr_value_box_list_next(list, vb)) {
5634  slen = fr_sbuff_in_bstrncpy(&our_sbuff, sep, sep_len);
5635  if (slen < 0) goto error;
5636  }
5637  }
5638 
5639  /*
5640  * Free the boxes last so if there's
5641  * an issue concatenating them, everything
5642  * is still in a known state.
5643  */
5644  fr_value_box_list_foreach_safe(list, vb) {
5645  if (tainted && vb->tainted) *tainted = true;
5646  if (secret && vb->secret) *secret = true;
5647 
5648  if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
5649  if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
5650  if (vb_should_free(proc_action)) talloc_free(vb);
5651  }}
5652 
5653  FR_SBUFF_SET_RETURN(sbuff, &our_sbuff);
5654 }
5655 
5656 /** Concatenate a list of value boxes together
5657  *
5658  * All boxes will be removed from the list.
5659  *
5660  * @param[out] tainted If nonnull, will be set to true if any input boxes are tainted.
5661  * bool pointed to must be initialised.
5662  * @param[out] secret If nonnull, will be set to true if any input boxes are secret.
5663  * @param[out] dbuff to write the result of the concatenation to.
5664  * @param[in] list to concatenate.
5665  * @param[in] sep Insert a separator between the values.
5666  * @param[in] sep_len Length of the separator.
5667  * @param[in] proc_action What to do with the boxes in the list once
5668  * they've been processed.
5669  * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
5670  * we concat the contents of its children together.
5671  * If false, the contents will be cast to #FR_TYPE_OCTETS.
5672  * @return
5673  * - >=0 the number of bytes written to the sbuff.
5674  * - <0 how many additional bytes we would have needed to
5675  * concat the next box.
5676  */
5677 ssize_t fr_value_box_list_concat_as_octets(bool *tainted, bool *secret, fr_dbuff_t *dbuff, fr_value_box_list_t *list,
5678  uint8_t const *sep, size_t sep_len,
5679  fr_value_box_list_action_t proc_action, bool flatten)
5680 {
5681  fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
5682  TALLOC_CTX *tmp_ctx = NULL;
5683  ssize_t slen;
5684 
5685  if (fr_value_box_list_empty(list)) return 0;
5686 
5687  fr_value_box_list_foreach(list, vb) {
5688  switch (vb->type) {
5689  case FR_TYPE_GROUP:
5690  if (!flatten) goto cast;
5691  slen = fr_value_box_list_concat_as_octets(tainted, secret, &our_dbuff, &vb->vb_group,
5692  sep, sep_len,
5693  proc_action, flatten);
5694  break;
5695 
5696  case FR_TYPE_OCTETS:
5697  slen = fr_dbuff_in_memcpy(&our_dbuff, vb->vb_octets, vb->vb_length);
5698  break;
5699 
5700  case FR_TYPE_STRING:
5701  slen = fr_dbuff_in_memcpy(&our_dbuff, (uint8_t const *)vb->vb_strvalue, vb->vb_length);
5702  break;
5703 
5704  case FR_TYPE_NULL: /* Skip null */
5705  continue;
5706 
5707  default:
5708  cast:
5709  {
5710  fr_value_box_t tmp_vb;
5711 
5712  if (!tmp_ctx) tmp_ctx = talloc_pool(NULL, 1024);
5713  /*
5714  * Not equivalent to fr_value_box_to_network
5715  */
5716  if (fr_value_box_cast_to_octets(tmp_ctx, &tmp_vb, FR_TYPE_OCTETS, NULL, vb) < 0) {
5717  slen = -1;
5718  goto error;
5719  }
5720 
5721  slen = fr_dbuff_in_memcpy(&our_dbuff, tmp_vb.vb_octets, tmp_vb.vb_length);
5722  fr_value_box_clear_value(&tmp_vb);
5723  break;
5724  }
5725  }
5726 
5727  if (slen < 0) {
5728  error:
5729  talloc_free(tmp_ctx);
5730  return slen;
5731  }
5732 
5733  if (sep && fr_value_box_list_next(list, vb)) {
5734  slen = fr_dbuff_in_memcpy(&our_dbuff, sep, sep_len);
5735  if (slen < 0) goto error;
5736  }
5737  }
5738 
5739  talloc_free(tmp_ctx);
5740 
5741  /*
5742  * Free the boxes last so if there's
5743  * an issue concatenating them, everything
5744  * is still in a known state.
5745  */
5746  fr_value_box_list_foreach_safe(list, vb) {
5747  if (tainted && vb->tainted) *tainted = true;
5748  if (secret && vb->secret) *secret = true;
5749 
5750  if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
5751  if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
5752  if (vb_should_free(proc_action)) talloc_free(vb);
5753  }}
5754 
5755  return fr_dbuff_set(dbuff, &our_dbuff);
5756 }
5757 
5758 /** Concatenate a list of value boxes
5759  *
5760  * @note Will automatically cast all #fr_value_box_t to type specified.
5761  *
5762  * @param[in] ctx to allocate new value buffer in.
5763  * @param[out] out Where to write the resulting box.
5764  * @param[in] list to concatenate together.
5765  * @param[in] type May be #FR_TYPE_STRING or #FR_TYPE_OCTETS, no other types are
5766  * supported.
5767  * @param[in] proc_action What to do with the boxes in the list once
5768  * they've been processed.
5769  * @param[in] flatten If true and we encounter a #FR_TYPE_GROUP,
5770  * we concat the contents of its children together.
5771  * If false, the contents will be cast to the given type.
5772  * @param[in] max_size of the value.
5773  * @return
5774  * - 0 on success.
5775  * - -1 on failure.
5776  */
5778  fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type,
5779  fr_value_box_list_action_t proc_action, bool flatten,
5780  size_t max_size)
5781 {
5782  fr_dbuff_t dbuff; /* FR_TYPE_OCTETS */
5783  fr_dbuff_uctx_talloc_t dbuff_tctx;
5784 
5785  fr_sbuff_t sbuff; /* FR_TYPE_STRING */
5786  fr_sbuff_uctx_talloc_t sbuff_tctx;
5787 
5788  fr_value_box_t *head_vb = fr_value_box_list_head(list);
5789  bool tainted = false;
5790  bool secret = false;
5791 
5792  fr_value_box_entry_t entry;
5793 
5794  if (fr_value_box_list_empty(list)) {
5795  fr_strerror_const("Invalid arguments. List contains no elements");
5796  return -1;
5797  }
5798 
5799  switch (type) {
5800  case FR_TYPE_STRING:
5801  if (unlikely(!fr_sbuff_init_talloc(ctx, &sbuff, &sbuff_tctx, 256, max_size))) return -1;
5802  break;
5803 
5804  case FR_TYPE_OCTETS:
5805  if (unlikely(!fr_dbuff_init_talloc(ctx, &dbuff, &dbuff_tctx, 256, max_size))) return -1;
5806  break;
5807 
5808  default:
5809  fr_strerror_printf("Invalid argument. Can't concatenate boxes to type %s",
5810  fr_type_to_str(type));
5811  return -1;
5812  }
5813 
5814  /*
5815  * Merge all siblings into list head.
5816  *
5817  * This is where the first element in the
5818  * list is the output box.
5819  *
5820  * i.e. we want to merge all its siblings
5821  * into it.
5822  */
5823  if (out == head_vb) {
5824  out = head_vb; /* sync up out and head_vb */
5825 
5826  switch (type) {
5827  case FR_TYPE_STRING:
5828  /*
5829  * Head gets dealt with specially as we don't
5830  * want to free it, and we don't want to free
5831  * the buffer associated with it (just yet).
5832  *
5833  * Note that we don't convert 'octets' to a printable string
5834  * here. Doing so breaks the keyword tests.
5835  */
5836  if (fr_value_box_list_concat_as_string(&tainted, &secret, &sbuff, list,
5837  NULL, 0, NULL,
5838  FR_VALUE_BOX_LIST_REMOVE, 0, flatten) < 0) {
5839  fr_strerror_printf("Concatenation exceeded max_size (%zu)", max_size);
5840  error:
5841  switch (type) {
5842  case FR_TYPE_STRING:
5843  talloc_free(fr_sbuff_buff(&sbuff));
5844  break;
5845 
5846  case FR_TYPE_OCTETS:
5847  talloc_free(fr_dbuff_buff(&dbuff));
5848  break;
5849 
5850  default:
5851  break;
5852  }
5853  return -1;
5854  }
5855 
5856  /*
5857  * Concat the rest of the children...
5858  */
5859  if (fr_value_box_list_concat_as_string(&tainted, &secret, &sbuff, list,
5860  NULL, 0, NULL,
5861  proc_action, 0, flatten) < 0) {
5862  fr_value_box_list_insert_head(list, head_vb);
5863  goto error;
5864  }
5865  (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
5867  if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), tainted) < 0) goto error;
5868  break;
5869 
5870  case FR_TYPE_OCTETS:
5871  if (fr_value_box_list_concat_as_octets(&tainted, &secret, &dbuff, list,
5872  NULL, 0,
5873  FR_VALUE_BOX_LIST_REMOVE, flatten) < 0) goto error;
5874 
5875  if (fr_value_box_list_concat_as_octets(&tainted, &secret, &dbuff, list,
5876  NULL, 0,
5877  proc_action, flatten) < 0) {
5878  fr_value_box_list_insert_head(list, head_vb);
5879  goto error;
5880  }
5881  (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
5883  if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), tainted) < 0) goto error;
5884  break;
5885 
5886  default:
5887  break;
5888  }
5889  fr_value_box_list_insert_head(list, out);
5890  /*
5891  * Merge all the boxes in the list into
5892  * a single contiguous buffer.
5893  *
5894  * This deals with an unrelated out and list
5895  * and also where list is the children of
5896  * out.
5897  */
5898  } else {
5899  switch (type) {
5900  case FR_TYPE_STRING:
5901  if (fr_value_box_list_concat_as_string(&tainted, &secret, &sbuff, list,
5902  NULL, 0, NULL,
5903  proc_action, 0, flatten) < 0) goto error;
5904  (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
5905 
5906  entry = out->entry;
5907  if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), tainted) < 0) goto error;
5908  out->entry = entry;
5909  break;
5910 
5911  case FR_TYPE_OCTETS:
5912  if (fr_value_box_list_concat_as_octets(&tainted, &secret, &dbuff, list,
5913  NULL, 0,
5914  proc_action, flatten) < 0) goto error;
5915  (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
5916 
5917  entry = out->entry;
5918  if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), tainted) < 0) goto error;
5919  out->entry = entry;
5920  break;
5921 
5922  default:
5923  break;
5924  }
5925  }
5927 
5928  return 0;
5929 }
5930 
5931 /** Escape a single value box in place
5932  *
5933  * @note Applies recursively to the children of group boxes.
5934  *
5935  * @param[in] vb to escape.
5936  * @param[in] escape function to apply to the value box.
5937  * @param[in] safe_for the escaped value to check value boxes again.
5938  * box has an escaped value that matches, it will
5939  * not be re-escaped.
5940  * @param[in] uctx user context to pass to the escape function.
5941  * @return
5942  * - 0 on success.
5943  * - -1 on failure.
5944  */
5946  fr_value_box_safe_for_t safe_for, void *uctx)
5947 {
5948  int ret;
5949 
5950  switch (vb->type) {
5951  case FR_TYPE_GROUP:
5952  return fr_value_box_list_escape_in_place(&vb->vb_group, escape, safe_for, uctx);
5953 
5954  default:
5955  break;
5956  }
5957 
5958  ret = escape(vb, uctx);
5959  if (unlikely(ret < 0)) return ret;
5960 
5961  vb->safe_for = safe_for;
5962 
5963  return 0;
5964 }
5965 
5966 /** Escape a list of value boxes in place
5967  *
5968  * @note Applies recursively to the children of group boxes.
5969  *
5970  * @note on error, the list may be left in an inconsistent/partially escaped state.
5971  *
5972  * @param[in] list to escape.
5973  * @param[in] escape function to apply to the value box.
5974  * @param[in] safe_for the escaped value to check value boxes again.
5975  * box has an escaped value that matches, it will
5976  * not be re-escaped.
5977  * @param[in] uctx user context to pass to the escape function.
5978  * @return
5979  * - 0 on success.
5980  * - -1 on failure.
5981  */
5982 int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape,
5983  fr_value_box_safe_for_t safe_for, void *uctx)
5984 {
5985  int ret = 0;
5986 
5987  fr_value_box_list_foreach(list, vb) {
5988  ret = fr_value_box_escape_in_place(vb, escape, safe_for, uctx);
5989  if (unlikely(ret < 0)) return ret;
5990  }
5991 
5992  return ret;
5993 }
5994 
5995 /** Removes a single layer of nesting, moving all children into the parent list
5996  *
5997  * @param[in] ctx to reparent children in if steal is true.
5998  * @param[in] list to flatten.
5999  * @param[in] steal whether to change the talloc ctx of children.
6000  * @param[in] free whether to free any group boxes which have had
6001  * their children removed.
6002  */
6003 void fr_value_box_flatten(TALLOC_CTX *ctx, fr_value_box_list_t *list, bool steal, bool free)
6004 {
6005  fr_value_box_list_foreach_safe(list, child) {
6006  if (!fr_type_is_structural(child->type)) continue;
6007 
6008  fr_value_box_list_foreach_safe(&child->vb_group, grandchild) {
6009  fr_value_box_list_remove(&child->vb_group, grandchild);
6010  if (steal) talloc_steal(ctx, grandchild);
6011  fr_value_box_list_insert_before(list, child, grandchild);
6012  }}
6013 
6014  if (free) talloc_free(child);
6015  }}
6016 }
6017 
6018 /** Concatenate the string representations of a list of value boxes together
6019  *
6020  * @param[in] ctx to allocate the buffer in.
6021  * @param[in] list of value boxes.
6022  * @param[in] delim to insert between value box values.
6023  * @param[in] e_rules to control escaping of the concatenated elements.
6024  * @return
6025  * - NULL on error.
6026  * - The concatenation of the string values of the value box list on success.
6027  */
6028 char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
6029  fr_sbuff_escape_rules_t const *e_rules)
6030 {
6031  fr_value_box_t const *vb = fr_value_box_list_head(list);
6032  char *aggr, *td = NULL;
6033  TALLOC_CTX *pool = NULL;
6034 
6035  if (!vb) return NULL;
6036 
6037  fr_value_box_aprint(ctx, &aggr, vb, e_rules);
6038  if (!aggr) return NULL;
6039  if (!fr_value_box_list_next(list, vb)) return aggr;
6040 
6041  /*
6042  * If we're aggregating more values,
6043  * allocate a temporary pool.
6044  */
6045  pool = talloc_pool(NULL, 255);
6046  if (delim) td = talloc_typed_strdup(pool, delim);
6047 
6048  while ((vb = fr_value_box_list_next(list, vb))) {
6049  char *str, *new_aggr;
6050 
6051  fr_value_box_aprint(pool, &str, vb, e_rules);
6052  if (!str) continue;
6053 
6054  new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
6055  if (unlikely(!new_aggr)) {
6056  talloc_free(aggr);
6057  talloc_free(pool);
6058  return NULL;
6059  }
6060  aggr = new_aggr;
6061  talloc_free(str);
6062  }
6063  talloc_free(pool);
6064 
6065  return aggr;
6066 }
6067 
6068 /** Concatenate the string representations of a list of value boxes together hiding "secret" values
6069  *
6070  * @param[in] ctx to allocate the buffer in.
6071  * @param[in] list of value boxes.
6072  * @param[in] delim to insert between value box values.
6073  * @param[in] e_rules to control escaping of the concatenated elements.
6074  * @return
6075  * - NULL on error.
6076  * - The concatenation of the string values of the value box list on success.
6077  */
6078 char *fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
6079  fr_sbuff_escape_rules_t const *e_rules)
6080 {
6081  fr_value_box_t const *vb = fr_value_box_list_head(list);
6082  char *aggr, *td = NULL;
6083  TALLOC_CTX *pool = NULL;
6084 
6085  if (!vb) return NULL;
6086 
6088  aggr = talloc_typed_strdup(ctx, "<<< secret >>>");
6089  } else {
6090  fr_value_box_aprint(ctx, &aggr, vb, e_rules);
6091  }
6092  if (!aggr) return NULL;
6093  if (!fr_value_box_list_next(list, vb)) return aggr;
6094 
6095  /*
6096  * If we're aggregating more values,
6097  * allocate a temporary pool.
6098  */
6099  pool = talloc_pool(NULL, 255);
6100  if (delim) td = talloc_typed_strdup(pool, delim);
6101 
6102  while ((vb = fr_value_box_list_next(list, vb))) {
6103  char *str, *new_aggr;
6104 
6106  str = talloc_typed_strdup(pool, "<<< secret >>>");
6107  } else {
6108  fr_value_box_aprint(pool, &str, vb, e_rules);
6109  }
6110  if (!str) continue;
6111 
6112  new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
6113  if (unlikely(!new_aggr)) {
6114  talloc_free(aggr);
6115  talloc_free(pool);
6116  return NULL;
6117  }
6118  aggr = new_aggr;
6119  talloc_free(str);
6120  }
6121  talloc_free(pool);
6122 
6123  return aggr;
6124 }
6125 
6126 /** Hash the contents of a value box
6127  *
6128  */
6130 {
6131  switch (vb->type) {
6132  case FR_TYPE_FIXED_SIZE:
6133  return fr_hash(fr_value_box_raw(vb, vb->type),
6134  fr_value_box_field_sizes[vb->type]);
6135 
6136  case FR_TYPE_STRING:
6137  return fr_hash(vb->vb_strvalue, vb->vb_length);
6138 
6139  case FR_TYPE_OCTETS:
6140  return fr_hash(vb->vb_octets, vb->vb_length);
6141 
6142  default:
6143  break;
6144  }
6145 
6146  return 0;
6147 }
6148 
6149 /** Do a full copy of a list of value boxes
6150  *
6151  * @param[in] ctx to allocate boxes in.
6152  * @param[out] out Where to write the head of the new list.
6153  * @param[in] in boxes to copy.
6154  * @return
6155  * - A duplicate list of value boxes, allocated in the context of 'ctx'
6156  * - NULL on error, or empty input list.
6157  */
6158 int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
6159 {
6160  fr_value_box_t const *in_p = NULL;
6161 
6162  while ((in_p = fr_value_box_list_next(in, in_p))) {
6163  fr_value_box_t *n = NULL;
6164 
6165  n = fr_value_box_alloc_null(ctx);
6166  if (!n) {
6167  error:
6168  fr_value_box_list_talloc_free(out);
6169  return -1;
6170  }
6171 
6172  if (fr_value_box_copy(n, n, in_p) < 0) goto error;
6173  fr_dlist_insert_tail(fr_value_box_list_dlist_head(out), n);
6174  }
6175 
6176  return 0;
6177 }
6178 
6179 /** Check to see if any list members (or their children) are tainted
6180  *
6181  * @param[in] head of list to check.
6182  * @return
6183  * - true if a list member is tainted.
6184  * - false if no list members are tainted.
6185  */
6186 bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
6187 {
6188  fr_value_box_t *vb = NULL;
6189 
6190  while ((vb = fr_value_box_list_next(head, vb))) {
6191  if (fr_type_is_group(vb->type) && fr_value_box_list_tainted(&vb->vb_group)) return true;
6192  if (vb->tainted) return true;
6193  }
6194 
6195  return false;
6196 }
6197 
6198 /** Taint every list member (and their children)
6199  *
6200  * @param[in] head of list.
6201  */
6202 void fr_value_box_list_taint(fr_value_box_list_t *head)
6203 {
6204  fr_value_box_t *vb = NULL;
6205 
6206  while ((vb = fr_value_box_list_next(head, vb))) {
6207  if (fr_type_is_group(vb->type)) fr_value_box_list_taint(&vb->vb_group);
6208  vb->tainted = true;
6209  }
6210 }
6211 
6212 /** Untaint every list member (and their children)
6213  *
6214  * @param[in] head of list.
6215  */
6216 void fr_value_box_list_untaint(fr_value_box_list_t *head)
6217 {
6218  fr_value_box_t *vb = NULL;
6219 
6220  while ((vb = fr_value_box_list_next(head, vb))) {
6221  if (fr_type_is_group(vb->type)) fr_value_box_list_untaint(&vb->vb_group);
6222  vb->tainted = false;
6223  }
6224 }
6225 
6226 /** Validation function to check that a fr_value_box_t is correctly initialised
6227  *
6228  */
6229 void fr_value_box_verify(char const *file, int line, fr_value_box_t const *vb)
6230 {
6231 DIAG_OFF(nonnull-compare)
6232  /*
6233  * nonnull only does something if we're building
6234  * with ubsan... We still want to assert event
6235  * if we're building without sanitizers.
6236  */
6237  fr_fatal_assert_msg(vb, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t pointer was NULL", file, line);
6238 DIAG_ON(nonnull-compare)
6239 
6240  if (vb->talloced) vb = talloc_get_type_abort_const(vb, fr_value_box_t);
6241 
6242 #ifndef NDEBUG
6243  fr_fatal_assert_msg(vb->magic == FR_VALUE_BOX_MAGIC, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t magic "
6244  "incorrect, expected %" PRIx64 ", got %" PRIx64, file, line, FR_VALUE_BOX_MAGIC, vb->magic);
6245 #endif
6246  switch (vb->type) {
6247  case FR_TYPE_STRING:
6248  fr_fatal_assert_msg(vb->vb_strvalue, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t strvalue field "
6249  "was NULL", file, line);
6250  fr_fatal_assert_msg(vb->vb_strvalue[vb->vb_length] == '\0',
6251  "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t strvalue field "
6252  "not null terminated", file, line);
6253  if (vb->talloced) {
6254  size_t len = talloc_array_length(vb->vb_strvalue);
6255 
6256  /* We always \0 terminate to be safe, even though most things should use the len field */
6257  if (len <= vb->vb_length) {
6258  fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%u]: Expected fr_value_box_t->vb_strvalue talloc buffer "
6259  "len >= %zu, got %zu",
6260  file, line, vb->vb_length + 1, len);
6261  }
6262  }
6263  break;
6264 
6265  case FR_TYPE_OCTETS:
6266  fr_fatal_assert_msg(vb->vb_octets, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t octets field "
6267  "was NULL", file, line);
6268  break;
6269 
6270  case FR_TYPE_VOID:
6271  fr_fatal_assert_msg(vb->vb_void, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t ptr field "
6272  "was NULL", file, line);
6273  break;
6274 
6275  case FR_TYPE_GROUP:
6276  fr_value_box_list_verify(file, line, &vb->vb_group);
6277  break;
6278 
6279  default:
6280  break;
6281  }
6282 }
6283 
6284 void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
6285 {
6287 }
6288 
6289 /** Mark a value-box as "safe", of a particular type.
6290  *
6291  */
6293 {
6294  vb->safe_for = safe_for;
6295 }
6296 
6297 /** Mark a value-box as "unsafe"
6298  *
6299  * This always succeeds, and there are no side effects.
6300  */
6302 {
6303  vb->safe_for = 0;
6304 }
6305 
6306 /** Set the escaped flag for all value boxes in a list
6307  *
6308  * @note Only operates on a single level.
6309  *
6310  * @param[in] list to operate on.
6311  * @param[in] safe_for value to set.
6312  */
6313 void fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for)
6314 {
6315  fr_value_box_list_foreach(list, vb) vb->safe_for = safe_for;
6316 }
6317 
6318 /** Check truthiness of values.
6319  *
6320  * The casting rules for expressions / conditions are slightly
6321  * different than fr_value_box_cast(). Largely because that
6322  * function is used to parse configuration files, and parses "yes
6323  * / no" and "true / false" strings, even if there's no
6324  * fr_dict_attr_t passed to it.
6325  */
6327 {
6328  fr_value_box_t box;
6329 
6330  switch (in->type) {
6331  case FR_TYPE_NULL:
6333  return false;
6334 
6335  case FR_TYPE_GROUP:
6336  return (fr_value_box_list_num_elements(&in->vb_group) > 0);
6337 
6338  case FR_TYPE_BOOL:
6339  return in->vb_bool;
6340 
6341  case FR_TYPE_STRING:
6342  case FR_TYPE_OCTETS:
6343  return (in->vb_length > 0);
6344 
6345  case FR_TYPE_IPV4_ADDR:
6346  case FR_TYPE_IPV6_ADDR:
6347  return !fr_ipaddr_is_inaddr_any(&in->vb_ip);
6348 
6349  case FR_TYPE_IPV4_PREFIX:
6350  case FR_TYPE_IPV6_PREFIX:
6351  return !((in->vb_ip.prefix == 0) && fr_ipaddr_is_inaddr_any(&in->vb_ip));
6352 
6353  default:
6354  fr_value_box_init_null(&box);
6355  (void) fr_value_box_cast(NULL, &box, FR_TYPE_BOOL, NULL, in);
6356  return box.vb_bool;
6357  }
6358 }
6359 
6360 #define INFO_INDENT(_fmt, ...) FR_FAULT_LOG("%*s"_fmt, depth * 2, " ", ## __VA_ARGS__)
6361 
6362 static void _fr_value_box_debug(fr_value_box_t const *vb, int depth, int idx);
6363 static void _fr_value_box_list_debug(fr_value_box_list_t const *head, int depth)
6364 {
6365  int i = 0;
6366 
6367  INFO_INDENT("{");
6369  INFO_INDENT("}");
6370 }
6371 
6372 /** Print a list of value boxes as info messages
6373  *
6374  * @note Call directly from the debugger
6375  */
6376 void fr_value_box_list_debug(fr_value_box_list_t const *head)
6377 {
6379 }
6380 
6381 static void _fr_value_box_debug(fr_value_box_t const *vb, int depth, int idx)
6382 {
6383  char *value;
6384 
6385  if (fr_type_is_structural(vb->type)) {
6386  _fr_value_box_list_debug(&vb->vb_group, depth + 1);
6387  return;
6388  }
6389 
6390  fr_value_box_aprint(NULL, &value, vb, NULL);
6391  if (idx >= 0) {
6392  INFO_INDENT("[%d] %s", idx, value);
6393  } else {
6394  INFO_INDENT("%s", value);
6395  }
6396  talloc_free(value);
6397 }
6398 
6399 /** Print the value of a box as info messages
6400  *
6401  * @note Call directly from the debugger
6402  */
6404 {
6405  _fr_value_box_debug(vb, 0, -1);
6406 }
static int const char char buffer[256]
Definition: acutest.h:574
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:57
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition: base16.h:95
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:481
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define DIAG_ON(_x)
Definition: build.h:456
#define static_assert
For systems with an old version libc, define static_assert.
Definition: build.h:35
#define SIZEOF_MEMBER(_t, _m)
Definition: build.h:334
#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:110
#define unlikely(_x)
Definition: build.h:379
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:455
static fr_atomic_queue_t * aq
Definition: control_test.c:47
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:767
#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:1858
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:898
#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:1898
#define fr_dbuff_buff(_dbuff_or_marker)
Return the underlying buffer in a dbuff or one of marker.
Definition: dbuff.h:882
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
Definition: dbuff.h:1732
#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:1508
#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:1752
#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:1382
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition: dbuff.h:1350
#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:1585
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:411
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:222
#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:1818
#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:1472
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:514
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
#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:191
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition: debug.h:216
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:156
#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:184
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition: dict.h:148
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
Definition: dict.h:149
static fr_slen_t err
Definition: dict.h:821
struct value_box_s fr_value_box_t
Definition: dict.h:49
fr_value_box_t const * value
Enum value (what name maps to).
Definition: dict.h:230
#define da_is_length_field(_da)
Definition: dict.h:154
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:3395
static fr_slen_t in
Definition: dict.h:821
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:3382
Value of an enumerated attribute.
Definition: dict.h:226
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:378
if(rcode > 0)
Definition: fd_read.h:9
uint32_t fr_hash(void const *data, size_t size)
Definition: hash.c:812
free(array)
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:1099
int fr_ipaddr_is_prefix(fr_ipaddr_t const *ipaddr)
Determine if an address is a prefix.
Definition: inet.c:125
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:1113
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:629
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:1073
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:778
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
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1346
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:1018
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.
Definition: merged_model.c:272
talloc_free(reap)
#define fr_multiply(_out, _a, _b)
Multiplies two integers together.
Definition: math.h:118
static const uint8_t * zero
Definition: md4.c:358
unsigned short uint16_t
Definition: merged_model.c:31
size_t fr_sbuff_out_unescape_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
Definition: merged_model.c:177
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
Definition: merged_model.c:113
@ FR_TYPE_FLOAT32
Single precision floating point.
Definition: merged_model.c:108
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_INT8
8 Bit signed integer.
Definition: merged_model.c:103
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
Definition: merged_model.c:93
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
Definition: merged_model.c:89
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_MAX
Number of defined data types.
Definition: merged_model.c:130
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_INT64
64 Bit signed integer.
Definition: merged_model.c:106
@ FR_TYPE_INT16
16 Bit signed integer.
Definition: merged_model.c:104
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
Definition: merged_model.c:111
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
Definition: merged_model.c:92
@ FR_TYPE_VALUE_BOX
A boxed value.
Definition: merged_model.c:125
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_INT32
32 Bit signed integer.
Definition: merged_model.c:105
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
Definition: merged_model.c:122
@ FR_TYPE_UINT64
64 Bit unsigned integer.
Definition: merged_model.c:100
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
Definition: merged_model.c:87
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
Definition: merged_model.c:115
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
Definition: merged_model.c:121
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
@ FR_TYPE_IFID
Interface ID.
Definition: merged_model.c:90
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
@ FR_TYPE_GROUP
A grouping of other attributes.
Definition: merged_model.c:124
@ FR_TYPE_FLOAT64
Double precision floating point.
Definition: merged_model.c:109
unsigned int uint32_t
Definition: merged_model.c:33
int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask_bits)
Definition: merged_model.c:275
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
unsigned long int size_t
Definition: merged_model.c:25
#define UINT8_MAX
Definition: merged_model.c:32
fr_sbuff_parse_error_t
Definition: merged_model.c:45
@ FR_SBUFF_PARSE_ERROR_NOT_FOUND
String does not contain a token matching the output type.
Definition: merged_model.c:47
@ FR_SBUFF_PARSE_OK
No error.
Definition: merged_model.c:46
static size_t array[MY_ARRAY_SIZE]
static uint8_t depth(fr_minmax_heap_index_t i)
Definition: minmax_heap.c:83
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
Definition: misc.c:472
void * memset_explicit(void *ptr, int ch, size_t len)
Definition: missing.c:620
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:175
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:851
static char * secret
Definition: radclient-ng.c:69
static bool done
Definition: radclient.c:80
static uint32_t mask
Definition: rbmonkey.c:39
static char const * name
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:407
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX+1], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
Definition: sbuff.c:1755
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:1598
bool const sbuff_char_class_hex[UINT8_MAX+1]
Definition: sbuff.c:94
bool const sbuff_char_class_uint[UINT8_MAX+1]
Definition: sbuff.c:60
static size_t min(size_t x, size_t y)
Definition: sbuff.c:143
bool const sbuff_char_class_hostname[UINT8_MAX+1]
Definition: sbuff.c:82
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
Definition: sbuff.c:2130
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:1458
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:1830
size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
Copy as many bytes as possible from a sbuff to a sbuff.
Definition: sbuff.c:700
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:2066
#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)
#define FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(...)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition: sbuff.h:167
char const * name
Name for rule set to aid we debugging.
Definition: sbuff.h:177
#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_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_out(_err, _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:155
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Talloc sbuff extension structure.
Definition: sbuff.h:114
Set of parsing rules for *unescape_until functions.
Definition: merged_model.c:163
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:41
PRIVATE void float64(struct DATA *p, double d)
Definition: snprintf.c:257
fr_assert(0)
fr_aka_sim_id_type_t type
Definition: sysutmp.h:112
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:445
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
Definition: talloc.c:696
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition: talloc.c:564
#define talloc_get_type_abort_const
Definition: talloc.h:282
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:214
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:827
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:716
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:468
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:1154
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 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_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:156
enum fr_token fr_token_t
@ T_SINGLE_QUOTED_STRING
Definition: token.h:122
@ T_BARE_WORD
Definition: token.h:120
@ T_BACK_QUOTED_STRING
Definition: token.h:123
@ T_OP_NE
Definition: token.h:97
@ T_OP_REG_EQ
Definition: token.h:102
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
@ T_OP_CMP_EQ
Definition: token.h:106
@ T_OP_LE
Definition: token.h:100
@ T_OP_GE
Definition: token.h:98
@ T_OP_GT
Definition: token.h:99
@ T_SOLIDUS_QUOTED_STRING
Definition: token.h:124
@ T_OP_LT
Definition: token.h:101
@ T_OP_REG_NE
Definition: token.h:103
#define T_TOKEN_LAST
Definition: token.h:129
static fr_slen_t head
Definition: xlat.h:406
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
#define FR_TYPE_VARIABLE_SIZE
Definition: types.h:291
#define FR_TYPE_QUOTED
Definition: types.h:292
#define FR_TYPE_STRUCTURAL_EXCEPT_GROUP
Definition: types.h:295
#define fr_type_is_non_leaf(_x)
Definition: types.h:373
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
#define fr_type_is_group(_x)
Definition: types.h:355
#define fr_type_is_variable_size(_x)
Definition: types.h:367
#define fr_type_is_structural(_x)
Definition: types.h:371
#define FR_TYPE_NON_LEAF
Definition: types.h:298
#define fr_type_is_fixed_size(_x)
Definition: types.h:366
#define FR_TYPE_STRUCTURAL
Definition: types.h:296
#define fr_type_is_ip(_x)
Definition: types.h:364
#define FR_TYPE_INTEGER_EXCEPT_BOOL
Definition: types.h:283
#define FR_TYPE_IP
Definition: types.h:288
#define FR_TYPE_INTEGER
Definition: types.h:284
#define fr_type_is_leaf(_x)
Definition: types.h:372
#define FR_TYPE_NUMERIC
Definition: types.h:286
#define FR_TYPE_FIXED_SIZE
Definition: types.h:290
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:4172
void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
Definition: value.c:6284
static void _fr_value_box_list_debug(fr_value_box_list_t const *head, int depth)
Definition: value.c:6363
static void _fr_value_box_debug(fr_value_box_t const *vb, int depth, int idx)
Definition: value.c:6381
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:4566
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
Definition: value.c:149
fr_sbuff_escape_rules_t fr_value_escape_double
Definition: value.c:350
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:1231
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:1325
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:3983
ssize_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, bool tainted)
Convert string value to a fr_value_box_t type.
Definition: value.c:4802
void fr_value_box_debug(fr_value_box_t const *vb)
Print the value of a box as info messages.
Definition: value.c:6403
#define INFO_INDENT(_fmt,...)
Definition: value.c:6360
int fr_value_box_bstrn_append(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, size_t len, bool tainted)
Append bytes from a buffer to an existing fr_value_box_t.
Definition: value.c:4284
void fr_value_box_mark_unsafe(fr_value_box_t *vb)
Mark a value-box as "unsafe".
Definition: value.c:6301
fr_sbuff_escape_rules_t fr_value_escape_single
Definition: value.c:388
ssize_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, bool tainted)
Definition: value.c:5315
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:3953
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition: value.c:6129
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:5352
fr_sbuff_parse_rules_t const value_parse_rules_single_3quoted
Definition: value.c:580
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:4701
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:2209
int fr_value_box_mem_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, bool tainted)
Append a talloc buffer to an existing fr_value_box_t.
Definition: value.c:4637
fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted
Definition: value.c:484
fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted
Definition: value.c:559
ssize_t fr_value_box_list_concat_as_octets(bool *tainted, bool *secret, 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:5677
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:1754
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:4371
int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape, fr_value_box_safe_for_t safe_for, void *uctx)
Escape a list of value boxes in place.
Definition: value.c:5982
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:4526
#define network_min_size(_x)
Sanity checks.
Definition: value.c:107
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:4208
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:3352
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:4014
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted_char[UINT8_MAX]
Definition: value.c:516
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
Definition: value.c:606
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:4404
static size_t const fr_value_box_network_sizes[FR_TYPE_MAX+1][2]
Definition: value.c:109
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:3230
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition: value.c:676
#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:189
fr_sbuff_parse_rules_t const * value_parse_rules_quoted_char[UINT8_MAX]
Definition: value.c:614
#define CAST_IP_FIX_COMBO
Definition: value.c:2346
void fr_value_box_list_untaint(fr_value_box_list_t *head)
Untaint every list member (and their children)
Definition: value.c:6216
fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted
Default formatting rules.
Definition: value.c:480
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:2378
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:3740
fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted
Definition: value.c:488
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:929
fr_sbuff_unescape_rules_t fr_value_unescape_solidus
Definition: value.c:296
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition: value.c:6326
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:3572
fr_sbuff_parse_rules_t const value_parse_rules_single_quoted
Definition: value.c:553
static uint8_t const v4_v6_map[]
v4 to v6 mapping prefix
Definition: value.c:2195
int fr_value_box_mem_append(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, bool tainted)
Append data to an existing fr_value_box_t.
Definition: value.c:4587
fr_sbuff_unescape_rules_t * fr_value_unescape_by_char[UINT8_MAX+1]
Definition: value.c:343
void fr_value_box_list_debug(fr_value_box_list_t const *head)
Print a list of value boxes as info messages.
Definition: value.c:6376
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:4548
fr_sbuff_escape_rules_t fr_value_escape_solidus
Definition: value.c:398
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:3834
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:2256
return fr_dbuff_set(dbuff, &our_dbuff)
void fr_value_box_increment(fr_value_box_t *vb)
Increment a boxed value.
Definition: value.c:4648
fr_sbuff_escape_rules_t * fr_value_escape_by_quote[T_TOKEN_LAST]
Definition: value.c:441
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:6292
size_t fr_value_str_unescape(fr_sbuff_t *out, fr_sbuff_t *in, size_t inlen, char quote)
Convert a string value with escape sequences into its binary form.
Definition: value.c:1128
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition: value.c:3681
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:6229
fr_sbuff_parse_rules_t const * value_parse_rules_3quoted[T_TOKEN_LAST]
Definition: value.c:622
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:3927
#define network_max_size(_x)
Definition: value.c:108
#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:4052
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:6028
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:5540
fr_sbuff_parse_rules_t const value_parse_rules_double_3quoted
Definition: value.c:574
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:3129
fr_sbuff_escape_rules_t fr_value_escape_unprintables
Definition: value.c:455
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:2725
fr_sbuff_escape_rules_t fr_value_escape_backtick
Definition: value.c:419
int fr_value_box_bstr_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, bool tainted)
Append a talloced buffer to an existing fr_value_box_t.
Definition: value.c:4337
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:3630
void fr_value_box_list_taint(fr_value_box_list_t *head)
Taint every list member (and their children)
Definition: value.c:6202
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
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:807
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:638
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:6313
fr_sbuff_escape_rules_t * fr_value_escape_by_char[UINT8_MAX+1]
Definition: value.c:448
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:2147
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:2885
fr_sbuff_unescape_rules_t fr_value_unescape_backtick
Definition: value.c:317
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:3662
fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted
Definition: value.c:524
fr_sbuff_parse_rules_t const value_parse_rules_backtick_3quoted
Definition: value.c:592
static uint64_t const fr_value_box_integer_max[]
Definition: value.c:226
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:4036
fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted
Definition: value.c:492
#define RETURN(_type)
fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted
Definition: value.c:565
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted[T_TOKEN_LAST]
Parse rules for non-quoted strings.
Definition: value.c:508
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:2494
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:2825
fr_sbuff_unescape_rules_t fr_value_unescape_single
Definition: value.c:285
fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted
Definition: value.c:496
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted
Definition: value.c:547
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:4071
fr_sbuff_unescape_rules_t * fr_value_unescape_by_quote[T_TOKEN_LAST]
Definition: value.c:336
#define SIGN_PROMOTE(_int, _len)
fr_sbuff_parse_rules_t const value_parse_rules_solidus_3quoted
Definition: value.c:586
ssize_t fr_value_box_list_concat_as_string(bool *tainted, bool *secret, 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:5584
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:3858
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:2084
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:6003
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:6158
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3723
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:6186
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:1404
static int64_t const fr_value_box_integer_min[]
Definition: value.c:246
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:4104
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:4148
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:4493
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:1360
fr_sbuff_unescape_rules_t fr_value_unescape_double
Definition: value.c:266
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:4253
int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escape, fr_value_box_safe_for_t safe_for, void *uctx)
Escape a single value box in place.
Definition: value.c:5945
size_t fr_value_substr_unescape(fr_sbuff_t *out, fr_sbuff_t *in, size_t inlen, char quote)
Convert a string value with escape sequences into its binary form.
Definition: value.c:1201
fr_sbuff_escape_rules_t fr_value_escape_secret
Escape secret fields by simply mashing all data to '.
Definition: value.c:381
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:4232
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:2610
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:4468
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:6078
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:2974
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:5777
fr_value_box_list_action_t
Actions to perform when we process a box in a list.
Definition: value.h:215
@ FR_VALUE_BOX_LIST_NONE
Do nothing to processed boxes.
Definition: value.h:216
@ FR_VALUE_BOX_LIST_REMOVE
Remove the box from the input list.
Definition: value.h:217
#define vb_should_free(_action)
Definition: value.h:224
#define fr_value_box_list_foreach_safe(_list_head, _iter)
Definition: value.h:207
#define vb_ether
Definition: value.h:249
#define vb_date
Definition: value.h:266
#define vb_int64
Definition: value.h:261
#define vb_octets
Definition: value.h:242
#define vb_should_free_value(_action)
Definition: value.h:225
#define vb_should_remove(_action)
Definition: value.h:226
#define vb_int32
Definition: value.h:260
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:764
#define vb_int16
Definition: value.h:259
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:252
#define vb_length
Definition: value.h:272
#define vb_int8
Definition: value.h:258
static fr_slen_t data
Definition: value.h:1265
static bool fr_value_box_contains_secret(fr_value_box_t const *box)
Definition: value.h:1066
#define vb_float64
Definition: value.h:264
#define FR_VALUE_BOX_NET_ERROR
Special value to indicate fr_value_box_from_network experienced a general error.
Definition: value.h:1014
static void fr_value_box_set_secret(fr_value_box_t *box, bool secret)
Definition: value.h:1080
int(* fr_value_box_escape_t)(fr_value_box_t *vb, void *uctx)
Escape a value box.
Definition: value.h:651
#define fr_box_strvalue_len(_val, _len)
Definition: value.h:286
#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:593
#define fr_value_box_is_safe_for(_box, _safe_for)
Definition: value.h:1055
#define vb_ip
Definition: value.h:246
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:997
#define vb_uint16
Definition: value.h:253
#define vb_bool
Definition: value.h:251
#define vb_size
Definition: value.h:268
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition: value.h:155
#define vb_strvalue
Definition: value.h:241
#define vb_uint32
Definition: value.h:254
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:632
#define vb_ifid
Definition: value.h:248
#define vb_time_delta
Definition: value.h:270
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:823
#define vb_float32
Definition: value.h:263
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition: value.h:587
#define fr_value_box_list_foreach(_list_head, _iter)
Definition: value.h:206
#define FR_VALUE_BOX_NET_OOM
Special value to indicate fr_value_box_from_network hit an out of memory error.
Definition: value.h:1018
#define vb_uint64
Definition: value.h:255
static size_t char ** out
Definition: value.h:997
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:740