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