The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
dict_validate.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Validation framework to allow protocols to set custom validation rules
18 *
19 * @file src/lib/util/dict_validate.c
20 *
21 * @copyright 2019 The FreeRADIUS server project
22 * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24RCSID("$Id: 2ae8ca1ea3ee0e59efdcdba167d8632ec11c3e07 $")
25
26#include <freeradius-devel/util/dict_priv.h>
27
28/** Validate a set of flags
29 *
30 * @param[in] da to check.
31 * @return
32 * - true if attribute definition is valid.
33 * - false if attribute definition is not valid.
34 */
36{
37 int bit;
38 uint32_t all_flags;
39 uint32_t shift_is_root, shift_internal;
40 uint32_t shift_array, shift_has_value;
41 uint32_t shift_subtype, shift_extra;
42 uint32_t shift_counter;
43 fr_dict_t *dict = da->dict;
44 fr_dict_attr_t const *parent = da->parent;
45 char const *name = da->name;
46 int attr = da->attr;
47 fr_type_t type = da->type;
48 fr_dict_attr_flags_t *flags = &da->flags;
49
50 /*
51 * Convert the 1-bit fields into bits numbers, so that we
52 * can check them in parallel.
53 */
54 all_flags = 0;
55 bit = -1;
56
57#define SET_FLAG(_flag) do { shift_ ## _flag = 1 << ++bit; if (flags->_flag) all_flags |= (1 << bit); } while (0)
58 SET_FLAG(is_root);
59 SET_FLAG(internal);
60 SET_FLAG(array);
61 SET_FLAG(has_value);
62 SET_FLAG(extra);
63 SET_FLAG(counter);
64 SET_FLAG(subtype);
65
66#define FORBID_OTHER_FLAGS(_flag, _allowed) \
67 do { \
68 if (all_flags & ~shift_ ## _flag & ~(_allowed)) { \
69 fr_strerror_printf("The '" STRINGIFY(_flag) "' flag cannot be used with any other flag (%u) %s[%d]", all_flags, da->filename, da->line); \
70 return false; \
71 } \
72 } while (0)
73
74#define ALLOW_FLAG(_flag) do { all_flags &= ~shift_ ## _flag; } while (0)
75
76 // is_root
77 // is_unknown
78 // internal
79 // array
80 // has_value
81 // extra
82 // encrypt
83 // length
84 // type_size
85
86 if (flags->is_root) {
87 FORBID_OTHER_FLAGS(is_root, 0);
88 }
89
90 if (flags->is_unknown) {
91 fr_strerror_const("The 'unknown' flag cannot be set for attributes in the dictionary.");
92 return false;
93 }
94
95 if (flags->local != parent->flags.local) {
96 fr_strerror_const("Cannot mix local variables with non-local attributes");
97 return false;
98 }
99
100 if (flags->local && (flags->is_unknown || flags->is_raw)) {
101 fr_strerror_const("Local variables cannot be 'raw' or unknown");
102 return false;
103 }
104
105 /*
106 * "flat" attributes can only go into a group.
107 */
108 if ((flags->allow_flat) && (type != FR_TYPE_GROUP)) {
109 fr_strerror_printf("Cannot set the 'flat' flag for data type %s", fr_type_to_str(type));
110 return false;
111 }
112
113 /*
114 * Only some data types can be in arrays, because we need
115 * to be able to decode the various array members.
116 */
117 if (flags->array) {
118 if (!flags->is_known_width) switch (type) {
119 default:
120 fr_strerror_printf("The 'array' flag cannot be used with attributes of type '%s'",
122 return false;
123
128 case FR_TYPE_UINT8:
129 case FR_TYPE_UINT16:
130 case FR_TYPE_UINT32:
131 case FR_TYPE_DATE:
133 break;
134
135 case FR_TYPE_ATTR:
136 flags->is_known_width = 1;
137 break;
138
139 case FR_TYPE_STRING:
140 case FR_TYPE_OCTETS:
141 if (!flags->length) {
142 fr_strerror_const("Variable length attributes cannot be marked as 'array'");
143 return false;
144 }
145
146 flags->is_known_width = 1;
147 break;
148
149 case FR_TYPE_STRUCT:
150 /*
151 * If we have arrays of structs, then the structure MUST be known width.
152 */
153 flags->is_known_width = 1;
154 break;
155 }
156
157 /*
158 * DHCPv6 has arrays of string / octets, prefixed
159 * with a uint16 field of "length". Also, arrays of dns_labels.
160 */
161 ALLOW_FLAG(extra);
162 ALLOW_FLAG(subtype);
163
164 FORBID_OTHER_FLAGS(array, 0);
165 }
166
167 /*
168 * 'has_value' should only be set internally. If the
169 * caller sets it, we still sanity check it.
170 */
171 if (flags->has_value) {
172 if (type != FR_TYPE_UINT32) {
173 fr_strerror_printf("The 'has_value' flag can only be used with attributes "
174 "of type 'integer'");
175 return false;
176 }
177
178 FORBID_OTHER_FLAGS(has_value, shift_internal);
179 }
180
181 /*
182 * Sanity check aliases.
183 */
184 if (flags->is_alias) {
186
188 if (!ext) {
189 fr_strerror_const("ALIAS is missing extension");
190 return false;
191 }
192
193 if (!ext->ref) {
194 fr_strerror_const("ALIAS is missing ref");
195 return false;
196 }
197
198 if (da->parent->type == FR_TYPE_STRUCT) {
199 fr_strerror_const("ALIAS cannot be added to a data type 'struct'");
200 return false;
201 }
202
203 fr_assert(!da->flags.is_unknown);
204 fr_assert(!da->flags.is_raw);
205 fr_assert(!da->flags.array);
206 fr_assert(!da->flags.is_known_width);
207 fr_assert(!da->flags.has_value);
208 fr_assert(!da->flags.counter);
209 fr_assert(!da->flags.secret);
210 fr_assert(!da->flags.unsafe);
211 fr_assert(!da->flags.is_ref_target);
212 fr_assert(!da->flags.local);
213 fr_assert(!da->flags.has_fixup);
214 }
215
216 /*
217 * The "extra" flag is a grab-bag of stuff, depending on
218 * the data type.
219 */
220 if (flags->extra) {
222 fr_strerror_const("The 'key' and 'length' flags cannot be used with any other flags.");
223 return false;
224 }
225
226 switch (type) {
227 case FR_TYPE_BOOL:
228 case FR_TYPE_UINT8:
229 case FR_TYPE_UINT16:
230 case FR_TYPE_UINT32:
231 case FR_TYPE_UINT64:
232 if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD)) {
233 fr_strerror_const("Invalid type (not 'key' field or 'bit' field) for extra flag.");
234 return false;
235 }
236
237 if (parent->type != FR_TYPE_STRUCT) {
238 fr_strerror_const("The 'key' flag can only be used inside of a 'struct'.");
239 return false;
240 }
241
242 ALLOW_FLAG(extra);
243 ALLOW_FLAG(subtype);
244 break;
245
246 case FR_TYPE_OCTETS:
247 case FR_TYPE_STRING:
248 if (flags->length != 0) {
249 fr_strerror_const("Cannot use [..] and length=uint...");
250 return false;
251 }
252
253 /*
254 * We can do arrays of variable-length types, so long as they have a "length="
255 * modifier.
256 *
257 * But any other modifier is foridden, including the use of "length=" outside of
258 * the context of arrays.
259 */
260 if (flags->array) {
261 ALLOW_FLAG(array);
262
263 if (!da_is_length_field(da)) {
264 goto invalid_extra;
265 }
266
267 } else if (da_is_length_field(da)) {
268 /* this is allowed */
269
270 } else if (flags->subtype) {
271 invalid_extra:
272 fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
273 return false;
274 }
275
276 ALLOW_FLAG(extra);
277 ALLOW_FLAG(subtype);
278 break;
279
280 case FR_TYPE_STRUCT:
281 if (!da_is_length_field(da)) {
282 fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
283 return false;
284 }
285
286 ALLOW_FLAG(extra);
287 ALLOW_FLAG(subtype);
288 ALLOW_FLAG(array);
289 break;
290
291 case FR_TYPE_TLV:
292 ALLOW_FLAG(extra);
293 /* @todo - allow arrays of struct? */
294 ALLOW_FLAG(subtype);
295 break;
296
297 default:
298 fr_strerror_printf("Type %s cannot hold extra flags",
300 return false;
301 }
302
303 if (da_is_length_field(da) &&
304 ((type != FR_TYPE_STRING) && (type != FR_TYPE_OCTETS) && (type != FR_TYPE_STRUCT))) {
305 fr_strerror_printf("The 'length' flag cannot be used used with type %s",
307 return false;
308 }
309
310 FORBID_OTHER_FLAGS(extra, 0);
311 }
312
313 /*
314 * Force "length" for fixed-size data types which aren't
315 * bit fields. Check / set "length" and "type_size" for
316 * other types.
317 */
318 if (!flags->extra || (flags->subtype != FLAG_BIT_FIELD)) switch (type) {
319 case FR_TYPE_INT8:
320 case FR_TYPE_UINT8:
321 case FR_TYPE_BOOL:
322 flags->length = 1;
323 break;
324
325 case FR_TYPE_INT16:
326 case FR_TYPE_UINT16:
327 flags->length = 2;
328 break;
329
330 case FR_TYPE_DATE:
332 if (!flags->length) flags->length = 4;
333
334 if ((flags->length != 2) && (flags->length != 4) && (flags->length != 8)) {
335 fr_strerror_printf("Invalid length %u for attribute of type '%s'",
336 flags->length, fr_type_to_str(type));
337 return false;
338 }
339 break;
340
342 case FR_TYPE_INT32:
343 case FR_TYPE_UINT32:
344 case FR_TYPE_FLOAT32:
345 flags->length = 4;
346 break;
347
348 case FR_TYPE_INT64:
349 case FR_TYPE_UINT64:
350 case FR_TYPE_FLOAT64:
351 flags->length = 8;
352 break;
353
354 case FR_TYPE_SIZE:
355 flags->length = sizeof(size_t);
356 break;
357
358 case FR_TYPE_ETHERNET:
359 flags->length = 6;
360 break;
361
362 case FR_TYPE_IFID:
363 flags->length = 8;
364 break;
365
368 flags->length = 16;
369 break;
370
373 flags->length = 17;
374 break;
375
376 case FR_TYPE_STRUCT:
377 ALLOW_FLAG(internal);
378 ALLOW_FLAG(array);
379 if (all_flags) {
380 fr_strerror_const("Invalid flag for attribute of type 'struct'");
381 return false;
382 }
383 break;
384
385 case FR_TYPE_VENDOR:
386 if (dict->string_based) break;
387
388 if (parent->type != FR_TYPE_VSA) {
389 fr_strerror_printf("Attributes of type 'vendor' MUST have a parent of type 'vsa' "
390 "instead of '%s'",
391 fr_type_to_str(parent->type));
392 return false;
393 }
394
395 if ((flags->length != 1) &&
396 (flags->length != 2) &&
397 (flags->length != 4)) {
398 fr_strerror_const("The 'length' flag can only be used for attributes of type 'vendor' with lengths of 1,2 or 4");
399 return false;
400 }
401 break;
402
403 case FR_TYPE_TLV:
404 if ((flags->length != 1) &&
405 (flags->length != 2) &&
406 (flags->length != 4)) {
407 fr_strerror_const("The 'length' flag can only be used for attributes of type 'tlv' with lengths of 1,2 or 4");
408 return false;
409 }
410 break;
411
412 /*
413 * 'octets[n]' can only be used in a few limited situations.
414 */
415 case FR_TYPE_OCTETS:
416 if (flags->length) {
417 /*
418 * Internal attributes can use octets[n]
419 * MS-MPPE-Keys use octets[18],encrypt=User-Password
420 * EAP-SIM-RAND uses array
421 */
422 ALLOW_FLAG(internal);
423 ALLOW_FLAG(subtype);
424 ALLOW_FLAG(array);
425
426 if (all_flags) {
427 fr_strerror_const("The 'octets[...]' syntax cannot be used any other flag");
428 return false;
429 }
430
431 if (flags->length > 253) {
432 fr_strerror_printf("Invalid length %d", flags->length);
433 return false;
434 }
435 }
436 break;
437
438 case FR_TYPE_UNION:
439 if (parent->type != FR_TYPE_STRUCT) {
440 fr_strerror_printf("Attributes of type 'union' must have a parent of type 'struct', not of type '%s'",
441 fr_type_to_str(parent->type));
442 return false;
443 }
444
445 /*
446 * If the UNION is missing a key extension, then the children of the UNION cannot find
447 * the key field in the parent STRUCT.
448 */
450 fr_strerror_const("Attribute of type 'union' is missing 'key=...'");
451 return false;
452 }
453 break;
454
455 case FR_TYPE_NULL:
456 case FR_TYPE_INTERNAL:
457 fr_strerror_printf("Attributes of type '%s' cannot be used in dictionaries",
459 return false;
460
461 /*
462 * These types are encoded differently in each protocol.
463 */
465 case FR_TYPE_ATTR:
466 case FR_TYPE_STRING:
467 case FR_TYPE_VSA:
468 case FR_TYPE_GROUP:
469 break;
470 }
471
472 /*
473 * type_size is used to limit the maximum attribute number, so it's checked first.
474 */
475 if (flags->type_size) {
476 if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
477 /*
478 * Allow all time res here
479 */
480 } else if (!flags->extra) {
481 if ((type != FR_TYPE_TLV) && (type != FR_TYPE_VENDOR)) {
482 fr_strerror_printf("The 'format=' flag can only be used with attributes of type 'tlv', and not type '%s'", fr_type_to_str(type));
483 return false;
484 }
485
486 if ((flags->type_size != 1) &&
487 (flags->type_size != 2) &&
488 (flags->type_size != 4)) {
489 fr_strerror_printf("The 'format=' flag can only be used with attributes of type size 1,2 or 4, not %i", flags->type_size);
490 return false;
491 }
492 }
493 }
494
495 /*
496 * Counters can be time deltas, or unsigned integers.
497 * For other data types, we don't know how to
498 * automatically add two counters.
499 */
500 if (flags->counter) {
502 ALLOW_FLAG(counter);
503 } else {
504 fr_strerror_printf("The 'counter' flag cannot be used with '%s'", fr_type_to_str(type));
505 return false;
506 }
507 }
508
509 /*
510 * Check flags against the parent attribute.
511 */
512 switch (parent->type) {
513 case FR_TYPE_STRUCT:
514 ALLOW_FLAG(extra);
515 ALLOW_FLAG(subtype);
516
517 /*
518 * If our parent is known width, then the children have to be known width, UNLESS
519 * either this child or its parent has a "length" prefix.
520 */
521 if (parent->flags.is_known_width && !flags->is_known_width && !flags->length &&
523 fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
524 return false;
525 }
526
527 if (flags->array) {
528 switch (type) {
530 ALLOW_FLAG(array);
531 break;
532
533 default:
534 if (flags->is_known_width) ALLOW_FLAG(array);
535 break;
536 }
537 }
538
539 if (all_flags) {
540 fr_strerror_const("Invalid flag for attribute inside of a 'struct'");
541 return false;
542 }
543
544 if (!attr) break;
545
546 /*
547 * If we have keyed structs, then the first
548 * member can be variable length.
549 *
550 * For subsequent children, have each one check
551 * the previous child.
552 */
553 if (attr != 1) {
554 int i;
555 fr_dict_attr_t const *sibling;
556
557 sibling = fr_dict_attr_child_by_num(parent, (attr) - 1);
558
559 /*
560 * sibling might not exist, if it's a deferred 'tlv clone=...'
561 */
562
563 /*
564 * Variable sized elements cannot have anything after them in a struct.
565 */
566 if (sibling && !sibling->flags.length && !sibling->flags.is_known_width) {
567 fr_strerror_const("No other field can follow a struct MEMBER which is variable sized");
568 return false;
569 }
570
571 /*
572 * The same goes for arrays.
573 */
574 if (sibling && sibling->flags.array) {
575 fr_strerror_const("No other field can follow a struct MEMBER which is 'array'");
576 return false;
577 }
578
579 /*
580 * Check for bad key fields, or multiple
581 * key fields. Yes, this is O(N^2), but
582 * the structs are small.
583 */
585 for (i = 1; i < attr; i++) {
586 sibling = fr_dict_attr_child_by_num(parent, i);
587 if (!sibling) {
588 fr_strerror_printf("Child %d of 'struct' type attribute %s does not exist.",
589 i, parent->name);
590 return false;
591 }
592
593 if (!fr_dict_attr_is_key_field(sibling)) continue;
594
595 fr_strerror_printf("Duplicate key attributes '%s' and '%s' in 'struct' type attribute %s are forbidden",
596 name, sibling->name, parent->name);
597 return false;
598 }
599 }
600 }
601 break;
602
603 case FR_TYPE_VSA:
604 if ((type != FR_TYPE_VENDOR) && !flags->internal) {
605 fr_strerror_printf("Attributes of type '%s' cannot be children of the 'vsa' type",
607 return false;
608 }
609 break;
610
611 case FR_TYPE_TLV:
612 case FR_TYPE_VENDOR:
613 break;
614
615 case FR_TYPE_UNION:
616 if (!((da->type == FR_TYPE_STRUCT) || (da->type == FR_TYPE_TLV) || fr_type_is_leaf(da->type))) {
617 fr_strerror_printf("Attributes of type '%s' cannot be children of the 'union' type",
619 return false;
620 }
621 break;
622
623 default:
624 fr_strerror_printf("Attributes of type '%s' cannot have child attributes",
625 fr_type_to_str(parent->type));
626 return false;
627 }
628
629 return true;
630}
631
632
633/** Validate a new attribute definition
634 *
635 * @todo we need to check length of none vendor attributes.
636 *
637 * @param[in] da to validate.
638 * @return
639 * - true if attribute definition is valid.
640 * - false if attribute definition is not valid.
641 */
643{
644 if (!fr_cond_assert(da->parent)) return false;
645
646 if (fr_dict_valid_name(da->name, -1) <= 0) return false;
647
648 /*
649 * Run protocol-specific validation functions, BEFORE we
650 * do the rest of the checks.
651 */
652 if (da->dict->proto->attr.valid && !da->dict->proto->attr.valid(da)) return false;
653
654 /*
655 * Check the flags, data types, and parent data types and flags.
656 */
657 if (!dict_attr_flags_valid(da)) return false;
658
659 return true;
660}
#define RCSID(id)
Definition build.h:487
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
unsigned int has_value
Has a value.
Definition dict.h:96
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition dict.h:166
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition dict.h:167
unsigned int is_root
Is root of a dictionary.
Definition dict.h:77
unsigned int array
Pack multiples into 1 attr.
Definition dict.h:92
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:120
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition dict.h:90
unsigned int is_raw
This dictionary attribute was constructed from a known attribute to allow the user to assign octets v...
Definition dict.h:82
#define da_is_bit_field(_da)
Definition dict.h:173
#define da_is_length_field(_da)
Definition dict.h:174
uint8_t type_size
Type size for TLVs.
Definition dict.h:146
uint16_t length
length of the attribute
Definition dict.h:155
unsigned int local
is a local variable
Definition dict.h:122
@ FR_DICT_ATTR_EXT_REF
Attribute references another attribute and/or dictionary.
Definition dict.h:186
@ FR_DICT_ATTR_EXT_KEY
UNION attribute references a key.
Definition dict.h:188
unsigned int is_known_width
is treated as if it has a known width for structs
Definition dict.h:94
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
Definition dict_util.c:4932
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3597
#define fr_dict_attr_is_key_field(_da)
Definition dict.h:172
uint8_t subtype
needs a fixup during dictionary parsing
Definition dict.h:133
unsigned int is_alias
This isn't a real attribute, it's a reference to to one.
Definition dict.h:87
unsigned int counter
integer attribute is actually an impulse / counter
Definition dict.h:100
unsigned int is_unknown
This dictionary attribute is ephemeral and not part of the main dictionary.
Definition dict.h:79
unsigned int allow_flat
only for FR_TYPE_GROUP, can contain "flat" lists.
Definition dict.h:124
Values of the encryption flags.
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:121
Attribute extension - Holds a reference to an attribute in another dictionary.
Definition dict_ext.h:77
#define FORBID_OTHER_FLAGS(_flag, _allowed)
bool dict_attr_flags_valid(fr_dict_attr_t *da)
Validate a set of flags.
bool dict_attr_valid(fr_dict_attr_t *da)
Validate a new attribute definition.
#define ALLOW_FLAG(_flag)
#define SET_FLAG(_flag)
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned int uint32_t
unsigned long int size_t
#define fr_assert(_expr)
Definition rad_assert.h:38
static char const * name
fr_aka_sim_id_type_t type
static fr_slen_t parent
Definition pair.h:857
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
@ FR_TYPE_UNION
A union of limited children.
Definition types.h:82
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:84
#define FR_TYPE_INTERNAL
Definition types.h:320
#define fr_type_is_signed(_x)
Definition types.h:384
#define fr_type_is_leaf(_x)
Definition types.h:394
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
#define fr_type_is_integer(_x)
Definition types.h:382
#define FR_TYPE_FIXED_SIZE
Definition types.h:311