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: 7aefaecf22ea3cbc85e1bf76635a70fdc2bcba86 $")
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_attr_t const *v;
44 fr_dict_t *dict = da->dict;
45 fr_dict_attr_t const *parent = da->parent;
46 char const *name = da->name;
47 int attr = da->attr;
48 fr_type_t type = da->type;
49 fr_dict_attr_flags_t *flags = &da->flags;
50
51 /*
52 * Convert the 1-bit fields into bits numbers, so that we
53 * can check them in parallel.
54 */
55 all_flags = 0;
56 bit = -1;
57
58#define SET_FLAG(_flag) do { shift_ ## _flag = 1 << ++bit; if (flags->_flag) all_flags |= (1 << bit); } while (0)
59 SET_FLAG(is_root);
60 SET_FLAG(internal);
61 SET_FLAG(array);
62 SET_FLAG(has_value);
63 SET_FLAG(extra);
64 SET_FLAG(counter);
65 SET_FLAG(subtype);
66
67#define FORBID_OTHER_FLAGS(_flag, _allowed) \
68 do { \
69 if (all_flags & ~shift_ ## _flag & ~(_allowed)) { \
70 fr_strerror_printf("The '" STRINGIFY(_flag) "' flag cannot be used with any other flag (%u) %s[%d]", all_flags, da->filename, da->line); \
71 return false; \
72 } \
73 } while (0)
74
75#define ALLOW_FLAG(_flag) do { all_flags &= ~shift_ ## _flag; } while (0)
76
77 // is_root
78 // is_unknown
79 // internal
80 // array
81 // has_value
82 // extra
83 // encrypt
84 // length
85 // type_size
86
87 if (flags->is_root) {
88 FORBID_OTHER_FLAGS(is_root, 0);
89 }
90
91 if (flags->is_unknown) {
92 fr_strerror_const("The 'unknown' flag cannot be set for attributes in the dictionary.");
93 return false;
94 }
95
96 if (flags->local != parent->flags.local) {
97 fr_strerror_const("Cannot mix local variables with non-local attributes");
98 return false;
99 }
100
101 /*
102 * Only some data types can be in arrays, because we need
103 * to be able to decode the various array members.
104 */
105 if (flags->array) {
106 if (!flags->is_known_width) switch (type) {
107 default:
108 fr_strerror_printf("The 'array' flag cannot be used with attributes of type '%s'",
110 return false;
111
116 case FR_TYPE_UINT8:
117 case FR_TYPE_UINT16:
118 case FR_TYPE_UINT32:
119 case FR_TYPE_DATE:
121 break;
122
123 case FR_TYPE_ATTR:
124 flags->is_known_width = 1;
125 break;
126
127 case FR_TYPE_STRING:
128 case FR_TYPE_OCTETS:
129 if (!flags->length) {
130 fr_strerror_const("Variable length attributes cannot be marked as 'array'");
131 return false;
132 }
133
134 flags->is_known_width = 1;
135 break;
136
137 case FR_TYPE_STRUCT:
138 /*
139 * If we have arrays of structs, then the structure MUST be known width.
140 */
141 flags->is_known_width = 1;
142 break;
143 }
144
145 /*
146 * DHCPv6 has arrays of string / octets, prefixed
147 * with a uint16 field of "length". Also, arrays of dns_labels.
148 */
149 ALLOW_FLAG(extra);
150 ALLOW_FLAG(subtype);
151
152 FORBID_OTHER_FLAGS(array, 0);
153 }
154
155 /*
156 * 'has_value' should only be set internally. If the
157 * caller sets it, we still sanity check it.
158 */
159 if (flags->has_value) {
160 if (type != FR_TYPE_UINT32) {
161 fr_strerror_printf("The 'has_value' flag can only be used with attributes "
162 "of type 'integer'");
163 return false;
164 }
165
166 FORBID_OTHER_FLAGS(has_value, shift_internal);
167 }
168
169 /*
170 * Sanity check aliases.
171 */
172 if (flags->is_alias) {
174
176 if (!ext) {
177 fr_strerror_const("ALIAS is missing extension");
178 return false;
179 }
180
181 if (!ext->ref) {
182 fr_strerror_const("ALIAS is missing ref");
183 return false;
184 }
185
186 if (da->parent->type == FR_TYPE_STRUCT) {
187 fr_strerror_const("ALIAS cannot be added to a data type 'struct'");
188 return false;
189 }
190
191 fr_assert(!da->flags.is_unknown);
192 fr_assert(!da->flags.is_raw);
193 fr_assert(!da->flags.array);
194 fr_assert(!da->flags.is_known_width);
195 fr_assert(!da->flags.has_value);
196 fr_assert(!da->flags.counter);
197 fr_assert(!da->flags.secret);
198 fr_assert(!da->flags.unsafe);
199 fr_assert(!da->flags.is_ref_target);
200 fr_assert(!da->flags.local);
201 fr_assert(!da->flags.has_fixup);
202 }
203
204 /*
205 * The "extra" flag is a grab-bag of stuff, depending on
206 * the data type.
207 */
208 if (flags->extra) {
210 fr_strerror_const("The 'key' and 'length' flags cannot be used with any other flags.");
211 return false;
212 }
213
214 switch (type) {
215 case FR_TYPE_BOOL:
216 case FR_TYPE_UINT8:
217 case FR_TYPE_UINT16:
218 case FR_TYPE_UINT32:
219 case FR_TYPE_UINT64:
220 if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD)) {
221 fr_strerror_const("Invalid type (not 'key' field or 'bit' field) for extra flag.");
222 return false;
223 }
224
225 if (parent->type != FR_TYPE_STRUCT) {
226 fr_strerror_const("The 'key' flag can only be used inside of a 'struct'.");
227 return false;
228 }
229
230 ALLOW_FLAG(extra);
231 ALLOW_FLAG(subtype);
232 break;
233
234 case FR_TYPE_OCTETS:
235 case FR_TYPE_STRING:
236 if (flags->length != 0) {
237 fr_strerror_const("Cannot use [..] and length=uint...");
238 return false;
239 }
240
241 /*
242 * We can do arrays of variable-length types, so long as they have a "length="
243 * modifier.
244 *
245 * But any other modifier is foridden, including the use of "length=" outside of
246 * the context of arrays.
247 */
248 if (flags->array) {
249 ALLOW_FLAG(array);
250
251 if (!da_is_length_field(da)) {
252 fr_assert(0);
253 goto invalid_extra;
254 }
255
256 } else if (flags->subtype) {
257 invalid_extra:
258 fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
259 return false;
260 }
261
262 ALLOW_FLAG(extra);
263 ALLOW_FLAG(subtype);
264 break;
265
266 case FR_TYPE_STRUCT:
267 if (!da_is_length_field(da)) {
268 fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
269 return false;
270 }
271
272 ALLOW_FLAG(extra);
273 ALLOW_FLAG(subtype);
274 ALLOW_FLAG(array);
275 break;
276
277 case FR_TYPE_TLV:
278 ALLOW_FLAG(extra);
279 /* @todo - allow arrays of struct? */
280 ALLOW_FLAG(subtype);
281 break;
282
283 default:
284 fr_strerror_printf("Type %s cannot hold extra flags",
286 return false;
287 }
288
289 if (da_is_length_field(da) &&
290 ((type != FR_TYPE_STRING) && (type != FR_TYPE_OCTETS) && (type != FR_TYPE_STRUCT))) {
291 fr_strerror_printf("The 'length' flag cannot be used used with type %s",
293 return false;
294 }
295
296 FORBID_OTHER_FLAGS(extra, 0);
297 }
298
299 /*
300 * Force "length" for fixed-size data types which aren't
301 * bit fields. Check / set "length" and "type_size" for
302 * other types.
303 */
304 if (!flags->extra || (flags->subtype != FLAG_BIT_FIELD)) switch (type) {
305 case FR_TYPE_INT8:
306 case FR_TYPE_UINT8:
307 case FR_TYPE_BOOL:
308 flags->length = 1;
309 break;
310
311 case FR_TYPE_INT16:
312 case FR_TYPE_UINT16:
313 flags->length = 2;
314 break;
315
316 case FR_TYPE_DATE:
318 if (!flags->length) flags->length = 4;
319
320 if ((flags->length != 2) && (flags->length != 4) && (flags->length != 8)) {
321 fr_strerror_printf("Invalid length %u for attribute of type '%s'",
322 flags->length, fr_type_to_str(type));
323 return false;
324 }
325 break;
326
328 case FR_TYPE_INT32:
329 case FR_TYPE_UINT32:
330 case FR_TYPE_FLOAT32:
331 flags->length = 4;
332 break;
333
334 case FR_TYPE_INT64:
335 case FR_TYPE_UINT64:
336 case FR_TYPE_FLOAT64:
337 flags->length = 8;
338 break;
339
340 case FR_TYPE_SIZE:
341 flags->length = sizeof(size_t);
342 break;
343
344 case FR_TYPE_ETHERNET:
345 flags->length = 6;
346 break;
347
348 case FR_TYPE_IFID:
349 flags->length = 8;
350 break;
351
354 flags->length = 16;
355 break;
356
359 flags->length = 17;
360 break;
361
362 case FR_TYPE_STRUCT:
363 ALLOW_FLAG(internal);
364 ALLOW_FLAG(array);
365 if (all_flags) {
366 fr_strerror_const("Invalid flag for attribute of type 'struct'");
367 return false;
368 }
369 break;
370
371 case FR_TYPE_VENDOR:
372 if (parent->type != FR_TYPE_VSA) {
373 fr_strerror_printf("Attributes of type 'vendor' MUST have a parent of type 'vsa' "
374 "instead of '%s'",
375 fr_type_to_str(parent->type));
376 return false;
377 }
378
379 if (flags->length) {
380 if ((flags->length != 1) &&
381 (flags->length != 2) &&
382 (flags->length != 4)) {
383 fr_strerror_const("The 'length' flag can only be used for attributes of type 'vendor' with lengths of 1,2 or 4");
384 return false;
385 }
386
387 break;
388 }
389
390 /*
391 * Set the length / type_size of vendor
392 * attributes from the vendor definition.
393 */
394 flags->type_size = 1;
395 flags->length = 1;
396 if (attr > 0) {
397 fr_dict_vendor_t const *dv;
398
399 dv = fr_dict_vendor_by_num(dict, attr);
400 if (dv) {
401 flags->type_size = dv->type;
402 flags->length = dv->length;
403 }
404 }
405 break;
406
407 case FR_TYPE_TLV:
408 if (flags->length) {
409 if ((flags->length != 1) &&
410 (flags->length != 2) &&
411 (flags->length != 4)) {
412 fr_strerror_const("The 'length' flag can only be used for attributes of type 'tlv' with lengths of 1,2 or 4");
413 return false;
414 }
415
416 break;
417 }
418
419 /*
420 * Find an appropriate parent to copy the
421 * TLV-specific fields from.
422 */
423 for (v = parent; v != NULL; v = v->parent) {
424 if ((v->type == FR_TYPE_TLV) || (v->type == FR_TYPE_VENDOR)) {
425 break;
426 }
427 }
428
429 /*
430 * root is always FR_TYPE_TLV, so we're OK.
431 */
432 if (!v) {
433 fr_strerror_printf("Attributes of type '%s' require a parent attribute",
435 return false;
436 }
437
438 /*
439 * Over-ride whatever was there before, so we
440 * don't have multiple formats of VSAs.
441 */
442 flags->type_size = v->flags.type_size;
443 flags->length = v->flags.length;
444 break;
445
446 /*
447 * 'octets[n]' can only be used in a few limited situations.
448 */
449 case FR_TYPE_OCTETS:
450 if (flags->length) {
451 /*
452 * Internal attributes can use octets[n]
453 * MS-MPPE-Keys use octets[18],encrypt=User-Password
454 * EAP-SIM-RAND uses array
455 */
456 ALLOW_FLAG(internal);
457 ALLOW_FLAG(subtype);
458 ALLOW_FLAG(array);
459
460 if (all_flags) {
461 fr_strerror_const("The 'octets[...]' syntax cannot be used any other flag");
462 return false;
463 }
464
465 if (flags->length > 253) {
466 fr_strerror_printf("Invalid length %d", flags->length);
467 return false;
468 }
469 }
470 break;
471
472 case FR_TYPE_UNION:
473 if (parent->type != FR_TYPE_STRUCT) {
474 fr_strerror_printf("Attributes of type 'union' must have a parent of type 'struct', not of type '%s'",
475 fr_type_to_str(parent->type));
476 return false;
477 }
478
480 fr_strerror_const("Attribute of type 'union' is missing 'key=...'");
481 return false;
482 }
483 break;
484
485 case FR_TYPE_NULL:
486 case FR_TYPE_INTERNAL:
487 fr_strerror_printf("Attributes of type '%s' cannot be used in dictionaries",
489 return false;
490
491 /*
492 * These types are encoded differently in each protocol.
493 */
495 case FR_TYPE_ATTR:
496 case FR_TYPE_STRING:
497 case FR_TYPE_VSA:
498 case FR_TYPE_GROUP:
499 break;
500 }
501
502 /*
503 * type_size is used to limit the maximum attribute number, so it's checked first.
504 */
505 if (flags->type_size) {
506 if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
507 /*
508 * Allow all time res here
509 */
510 } else if (!flags->extra) {
511 if ((type != FR_TYPE_TLV) && (type != FR_TYPE_VENDOR)) {
512 fr_strerror_printf("The 'format=' flag can only be used with attributes of type 'tlv', and not type '%s'", fr_type_to_str(type));
513 return false;
514 }
515
516 if ((flags->type_size != 1) &&
517 (flags->type_size != 2) &&
518 (flags->type_size != 4)) {
519 fr_strerror_printf("The 'format=' flag can only be used with attributes of type size 1,2 or 4, not %i", flags->type_size);
520 return false;
521 }
522 }
523 }
524
525 /*
526 * Counters can be time deltas, or unsigned integers.
527 * For other data types, we don't know how to
528 * automatically add two counters.
529 */
530 if (flags->counter) {
532 ALLOW_FLAG(counter);
533 } else {
534 fr_strerror_printf("The 'counter' flag cannot be used with '%s'", fr_type_to_str(type));
535 return false;
536 }
537 }
538
539 /*
540 * Check flags against the parent attribute.
541 */
542 switch (parent->type) {
543 case FR_TYPE_STRUCT:
544 ALLOW_FLAG(extra);
545 ALLOW_FLAG(subtype);
546
547 /*
548 * If our parent is known width, then the children have to be known width, UNLESS
549 * either this child or its parent has a "length" prefix.
550 */
551 if (parent->flags.is_known_width && !flags->is_known_width && !flags->length &&
553 fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
554 return false;
555 }
556
557 if (flags->array) {
558 switch (type) {
560 ALLOW_FLAG(array);
561 break;
562
563 default:
564 if (flags->is_known_width) ALLOW_FLAG(array);
565 break;
566 }
567 }
568
569 if (all_flags) {
570 fr_strerror_const("Invalid flag for attribute inside of a 'struct'");
571 return false;
572 }
573
574 if (!attr) break;
575
576 /*
577 * If we have keyed structs, then the first
578 * member can be variable length.
579 *
580 * For subsequent children, have each one check
581 * the previous child.
582 */
583 if (attr != 1) {
584 int i;
585 fr_dict_attr_t const *sibling;
586
587 sibling = fr_dict_attr_child_by_num(parent, (attr) - 1);
588
589 /*
590 * sibling might not exist, if it's a deferred 'tlv clone=...'
591 */
592
593 /*
594 * Variable sized elements cannot have anything after them in a struct.
595 */
596 if (sibling && !sibling->flags.length && !sibling->flags.is_known_width) {
597 fr_strerror_const("No other field can follow a struct MEMBER which is variable sized");
598 return false;
599 }
600
601 /*
602 * The same goes for arrays.
603 */
604 if (sibling && sibling->flags.array) {
605 fr_strerror_const("No other field can follow a struct MEMBER which is 'array'");
606 return false;
607 }
608
609 /*
610 * Check for bad key fields, or multiple
611 * key fields. Yes, this is O(N^2), but
612 * the structs are small.
613 */
615 for (i = 1; i < attr; i++) {
616 sibling = fr_dict_attr_child_by_num(parent, i);
617 if (!sibling) {
618 fr_strerror_printf("Child %d of 'struct' type attribute %s does not exist.",
619 i, parent->name);
620 return false;
621 }
622
623 if (!fr_dict_attr_is_key_field(sibling)) continue;
624
625 fr_strerror_printf("Duplicate key attributes '%s' and '%s' in 'struct' type attribute %s are forbidden",
626 name, sibling->name, parent->name);
627 return false;
628 }
629 }
630 }
631 break;
632
633 case FR_TYPE_VSA:
634 if ((type != FR_TYPE_VENDOR) && !flags->internal) {
635 fr_strerror_printf("Attributes of type '%s' cannot be children of the 'vsa' type",
637 return false;
638 }
639 break;
640
641 case FR_TYPE_TLV:
642 case FR_TYPE_VENDOR:
643 break;
644
645 case FR_TYPE_UNION:
646 if (!((da->type == FR_TYPE_STRUCT) || (da->type == FR_TYPE_TLV) || fr_type_is_leaf(da->type))) {
647 fr_strerror_printf("Attributes of type '%s' cannot be children of the 'union' type",
649 return false;
650 }
651 break;
652
653 default:
654 fr_strerror_printf("Attributes of type '%s' cannot have child attributes",
655 fr_type_to_str(parent->type));
656 return false;
657 }
658
659 return true;
660}
661
662
663/** Validate a new attribute definition
664 *
665 * @todo we need to check length of none vendor attributes.
666 *
667 * @param[in] da to validate.
668 * @return
669 * - true if attribute definition is valid.
670 * - false if attribute definition is not valid.
671 */
673{
674 if (!fr_cond_assert(da->parent)) return false;
675
676 if (fr_dict_valid_name(da->name, -1) <= 0) return false;
677
678 /*
679 * Run protocol-specific validation functions, BEFORE we
680 * do the rest of the checks.
681 */
682 if (da->dict->proto->attr.valid && !da->dict->proto->attr.valid(da)) return false;
683
684 /*
685 * Check the flags, data types, and parent data types and flags.
686 */
687 if (!dict_attr_flags_valid(da)) return false;
688
689 return true;
690}
#define RCSID(id)
Definition build.h:485
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
size_t type
Length of type data.
Definition dict.h:272
unsigned int has_value
Has a value.
Definition dict.h:95
unsigned int is_root
Is root of a dictionary.
Definition dict.h:77
unsigned int array
Pack multiples into 1 attr.
Definition dict.h:91
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:119
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition dict.h:89
#define da_is_bit_field(_da)
Definition dict.h:170
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition dict.h:163
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition dict.h:164
#define da_is_length_field(_da)
Definition dict.h:171
uint8_t type_size
Type size for TLVs.
Definition dict.h:143
size_t length
Length of length data.
Definition dict.h:273
uint16_t length
length of the attribute
Definition dict.h:152
unsigned int local
is a local variable
Definition dict.h:121
@ FR_DICT_ATTR_EXT_REF
Attribute references another attribute and/or dictionary.
Definition dict.h:183
@ FR_DICT_ATTR_EXT_KEY
UNION attribute references a key.
Definition dict.h:185
unsigned int is_known_width
is treated as if it has a known width for structs
Definition dict.h:93
fr_dict_vendor_t const * fr_dict_vendor_by_num(fr_dict_t const *dict, uint32_t vendor_pen)
Look up a vendor by its PEN.
Definition dict_util.c:2819
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
Definition dict_util.c:4802
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:3467
#define fr_dict_attr_is_key_field(_da)
Definition dict.h:169
uint8_t subtype
needs a fixup during dictionary parsing
Definition dict.h:130
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:99
unsigned int is_unknown
This dictionary attribute is ephemeral and not part of the main dictionary.
Definition dict.h:79
Values of the encryption flags.
Private enterprise.
Definition dict.h:269
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:134
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:841
#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