The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
24 RCSID("$Id: 8e84b99e5d52354d614a68bc89a91430d3c14885 $")
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[%u]", 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 
112  case FR_TYPE_IPV4_ADDR:
113  case FR_TYPE_IPV4_PREFIX:
114  case FR_TYPE_IPV6_ADDR:
115  case FR_TYPE_IPV6_PREFIX:
116  case FR_TYPE_UINT8:
117  case FR_TYPE_UINT16:
118  case FR_TYPE_UINT32:
119  case FR_TYPE_DATE:
120  case FR_TYPE_TIME_DELTA:
121  break;
122 
123  case FR_TYPE_STRING:
124  case FR_TYPE_OCTETS:
125  if (!flags->length) {
126  fr_strerror_const("Variable length attributes cannot be marked as 'array'");
127  return false;
128  }
129 
130  flags->is_known_width = 1;
131  break;
132 
133  case FR_TYPE_STRUCT:
134  /*
135  * If we have arrays of structs, then the structure MUST be known width.
136  */
137  flags->is_known_width = 1;
138  break;
139  }
140 
141  /*
142  * DHCPv6 has arrays of string / octets, prefixed
143  * with a uint16 field of "length". Also, arrays of dns_labels.
144  */
145  ALLOW_FLAG(extra);
146  ALLOW_FLAG(subtype);
147 
149  }
150 
151  /*
152  * 'has_value' should only be set internally. If the
153  * caller sets it, we still sanity check it.
154  */
155  if (flags->has_value) {
156  if (type != FR_TYPE_UINT32) {
157  fr_strerror_printf("The 'has_value' flag can only be used with attributes "
158  "of type 'integer'");
159  return false;
160  }
161 
162  FORBID_OTHER_FLAGS(has_value, shift_internal);
163  }
164 
165  /*
166  * The "extra" flag is a grab-bag of stuff, depending on
167  * the data type.
168  */
169  if (flags->extra) {
170  if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD) &&
171  (flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) {
172  fr_strerror_const("The 'key' and 'length' flags cannot be used with any other flags.");
173  return false;
174  }
175 
176  switch (type) {
177  case FR_TYPE_BOOL:
178  case FR_TYPE_UINT8:
179  case FR_TYPE_UINT16:
180  case FR_TYPE_UINT32:
181  case FR_TYPE_UINT64:
182  if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD)) {
183  fr_strerror_const("Invalid type (not 'key' field or 'bit' field) for extra flag.");
184  return false;
185  }
186 
187  if (parent->type != FR_TYPE_STRUCT) {
188  fr_strerror_const("The 'key' flag can only be used inside of a 'struct'.");
189  return false;
190  }
191 
192  ALLOW_FLAG(extra);
193  ALLOW_FLAG(subtype);
194  break;
195 
196  case FR_TYPE_OCTETS:
197  case FR_TYPE_STRING:
198  if (flags->length != 0) {
199  fr_strerror_const("Cannot use [..] and length=uint...");
200  return false;
201  }
202 
203  /*
204  * We can do arrays of variable-length types, so long as they have a "length="
205  * modifier.
206  *
207  * But any other modifier is foridden, including the use of "length=" outside of
208  * the context of arrays.
209  */
210  if (flags->array) {
211  ALLOW_FLAG(array);
212 
213  if ((flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) goto invalid_extra;
214  } else if (flags->subtype) {
215  invalid_extra:
216  fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
217  return false;
218  }
219 
220  ALLOW_FLAG(extra);
221  ALLOW_FLAG(subtype);
222  break;
223 
224  case FR_TYPE_STRUCT:
225  if ((flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) {
226  fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
227  return false;
228  }
229 
230  ALLOW_FLAG(extra);
231  ALLOW_FLAG(subtype);
232  ALLOW_FLAG(array);
233  break;
234 
235  case FR_TYPE_TLV:
236  ALLOW_FLAG(extra);
237  /* @todo - allow arrays of struct? */
238  ALLOW_FLAG(subtype);
239  break;
240 
241  default:
242  fr_strerror_printf("Type %s cannot hold extra flags",
244  return false;
245  }
246 
247  if (((flags->subtype == FLAG_LENGTH_UINT8) || (flags->subtype == FLAG_LENGTH_UINT16)) &&
248  ((type != FR_TYPE_STRING) && (type != FR_TYPE_OCTETS) && (type != FR_TYPE_STRUCT))) {
249  fr_strerror_printf("The 'length' flag cannot be used used with type %s",
251  return false;
252  }
253 
254  FORBID_OTHER_FLAGS(extra, 0);
255  }
256 
257  /*
258  * Force "length" for fixed-size data types which aren't
259  * bit fields. Check / set "length" and "type_size" for
260  * other types.
261  */
262  if (!flags->extra || (flags->subtype != FLAG_BIT_FIELD)) switch (type) {
263  case FR_TYPE_UINT8:
264  case FR_TYPE_BOOL:
265  flags->length = 1;
266  break;
267 
268  case FR_TYPE_UINT16:
269  flags->length = 2;
270  break;
271 
272  case FR_TYPE_DATE:
273  case FR_TYPE_TIME_DELTA:
274  if (!flags->length) flags->length = 4;
275 
276  if ((flags->length != 2) && (flags->length != 4) && (flags->length != 8)) {
277  fr_strerror_printf("Invalid length %u for attribute of type '%s'",
278  flags->length, fr_type_to_str(type));
279  return false;
280  }
281  break;
282 
283  case FR_TYPE_IPV4_ADDR:
284  case FR_TYPE_UINT32:
285  case FR_TYPE_INT32:
286  case FR_TYPE_FLOAT32:
287  flags->length = 4;
288  break;
289 
290  case FR_TYPE_UINT64:
291  case FR_TYPE_FLOAT64:
292  flags->length = 8;
293  break;
294 
295  case FR_TYPE_SIZE:
296  flags->length = sizeof(size_t);
297  break;
298 
299  case FR_TYPE_ETHERNET:
300  flags->length = 6;
301  break;
302 
303  case FR_TYPE_IFID:
304  flags->length = 8;
305  break;
306 
307  case FR_TYPE_IPV6_ADDR:
309  flags->length = 16;
310  break;
311 
312  case FR_TYPE_IPV6_PREFIX:
314  flags->length = 17;
315  break;
316 
317  case FR_TYPE_STRUCT:
318  ALLOW_FLAG(internal);
319  ALLOW_FLAG(array);
320  if (all_flags) {
321  fr_strerror_const("Invalid flag for attribute of type 'struct'");
322  return false;
323  }
324  break;
325 
326  case FR_TYPE_VENDOR:
327  if (parent->type != FR_TYPE_VSA) {
328  fr_strerror_printf("Attributes of type 'vendor' MUST have a parent of type 'vsa' "
329  "instead of '%s'",
330  fr_type_to_str(parent->type));
331  return false;
332  }
333 
334  if (flags->length) {
335  if ((flags->length != 1) &&
336  (flags->length != 2) &&
337  (flags->length != 4)) {
338  fr_strerror_const("The 'length' flag can only be used for attributes of type 'vendor' with lengths of 1,2 or 4");
339  return false;
340  }
341 
342  break;
343  }
344 
345  /*
346  * Set the length / type_size of vendor
347  * attributes from the vendor definition.
348  */
349  flags->type_size = 1;
350  flags->length = 1;
351  if (attr > 0) {
352  fr_dict_vendor_t const *dv;
353 
354  dv = fr_dict_vendor_by_num(dict, attr);
355  if (dv) {
356  flags->type_size = dv->type;
357  flags->length = dv->length;
358  }
359  }
360  break;
361 
362  case FR_TYPE_TLV:
363  if (flags->length) {
364  if ((flags->length != 1) &&
365  (flags->length != 2) &&
366  (flags->length != 4)) {
367  fr_strerror_const("The 'length' flag can only be used for attributes of type 'tlv' with lengths of 1,2 or 4");
368  return false;
369  }
370 
371  break;
372  }
373 
374  /*
375  * Find an appropriate parent to copy the
376  * TLV-specific fields from.
377  */
378  for (v = parent; v != NULL; v = v->parent) {
379  if ((v->type == FR_TYPE_TLV) || (v->type == FR_TYPE_VENDOR)) {
380  break;
381  }
382  }
383 
384  /*
385  * root is always FR_TYPE_TLV, so we're OK.
386  */
387  if (!v) {
388  fr_strerror_printf("Attributes of type '%s' require a parent attribute",
390  return false;
391  }
392 
393  /*
394  * Over-ride whatever was there before, so we
395  * don't have multiple formats of VSAs.
396  */
397  flags->type_size = v->flags.type_size;
398  flags->length = v->flags.length;
399  break;
400 
401  /*
402  * 'octets[n]' can only be used in a few limited situations.
403  */
404  case FR_TYPE_OCTETS:
405  if (flags->length) {
406  /*
407  * Internal attributes can use octets[n]
408  * MS-MPPE-Keys use octets[18],encrypt=User-Password
409  * EAP-SIM-RAND uses array
410  */
411  ALLOW_FLAG(internal);
412  ALLOW_FLAG(subtype);
413  ALLOW_FLAG(array);
414 
415  if (all_flags) {
416  fr_strerror_const("The 'octets[...]' syntax cannot be used any other flag");
417  return false;
418  }
419 
420  if (flags->length > 253) {
421  fr_strerror_printf("Invalid length %d", flags->length);
422  return false;
423  }
424  }
425  break;
426 
427  case FR_TYPE_NULL:
428  fr_strerror_printf("Attributes of type '%s' cannot be used in dictionaries",
430  return false;
431 
432  default:
433  break;
434  }
435 
436  /*
437  * type_size is used to limit the maximum attribute number, so it's checked first.
438  */
439  if (flags->type_size) {
440  if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
441  /*
442  * Allow all time res here
443  */
444  } else if (!flags->extra) {
445  if ((type != FR_TYPE_TLV) && (type != FR_TYPE_VENDOR)) {
446  fr_strerror_const("The 'format=' flag can only be used with attributes of type 'tlv'");
447  return false;
448  }
449 
450  if ((flags->type_size != 1) &&
451  (flags->type_size != 2) &&
452  (flags->type_size != 4)) {
453  fr_strerror_const("The 'format=' flag can only be used with attributes of type size 1,2 or 4");
454  return false;
455  }
456  }
457  }
458 
459  /*
460  * Counters can be time deltas, or unsigned integers.
461  * For other data types, we don't know how to
462  * automatically add two counters.
463  */
464  if (flags->counter) {
466  ALLOW_FLAG(counter);
467  } else {
468  fr_strerror_printf("The 'counter' flag cannot be used with '%s'", fr_type_to_str(type));
469  return false;
470  }
471  }
472 
473  /*
474  * Check flags against the parent attribute.
475  */
476  switch (parent->type) {
477  case FR_TYPE_STRUCT:
478  ALLOW_FLAG(extra);
479  ALLOW_FLAG(subtype);
480 
481  if (parent->flags.is_known_width && !flags->is_known_width && !flags->length) {
482  fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
483  return false;
484  }
485 
486  if (flags->array) {
487  switch (type) {
488  case FR_TYPE_FIXED_SIZE:
489  ALLOW_FLAG(array);
490  break;
491 
492  default:
493  if (flags->is_known_width) ALLOW_FLAG(array);
494  break;
495  }
496  }
497 
498  if (all_flags) {
499  fr_strerror_const("Invalid flag for attribute inside of a 'struct'");
500  return false;
501  }
502 
503  if (!attr) break;
504 
505  /*
506  * If we have keyed structs, then the first
507  * member can be variable length.
508  *
509  * For subsequent children, have each one check
510  * the previous child.
511  */
512  if (attr != 1) {
513  int i;
514  fr_dict_attr_t const *sibling;
515 
516  sibling = fr_dict_attr_child_by_num(parent, (attr) - 1);
517 
518  /*
519  * sibling might not exist, if it's a deferred 'tlv clone=...'
520  */
521 
522  /*
523  * Variable sized elements cannot have anything after them in a struct.
524  */
525  if (sibling && !sibling->flags.length && !sibling->flags.is_known_width) {
526  fr_strerror_const("No other field can follow a struct MEMBER which is variable sized");
527  return false;
528  }
529 
530  /*
531  * The same goes for arrays.
532  */
533  if (sibling && sibling->flags.array) {
534  fr_strerror_const("No other field can follow a struct MEMBER which is 'array'");
535  return false;
536  }
537 
538  /*
539  * Check for bad key fields, or multiple
540  * key fields. Yes, this is O(N^2), but
541  * the structs are small.
542  */
543  if (flags->extra && (flags->subtype == FLAG_KEY_FIELD)) {
544  for (i = 1; i < attr; i++) {
545  sibling = fr_dict_attr_child_by_num(parent, i);
546  if (!sibling) {
547  fr_strerror_printf("Child %d of 'struct' type attribute %s does not exist.",
548  i, parent->name);
549  return false;
550  }
551 
552  if (!fr_dict_attr_is_key_field(sibling)) continue;
553 
554  fr_strerror_printf("Duplicate key attributes '%s' and '%s' in 'struct' type attribute %s are forbidden",
555  name, sibling->name, parent->name);
556  return false;
557  }
558  }
559  }
560  break;
561 
562  case FR_TYPE_VSA:
563  if ((type != FR_TYPE_VENDOR) && !flags->internal) {
564  fr_strerror_printf("Attributes of type '%s' cannot be children of the 'vsa' type",
566  return false;
567  }
568  break;
569 
570  case FR_TYPE_TLV:
571  case FR_TYPE_VENDOR:
572  break;
573 
574  /*
575  * "key" fields inside of a STRUCT can have
576  * children, even if they are integer data type.
577  */
578  case FR_TYPE_UINT8:
579  case FR_TYPE_UINT16:
580  case FR_TYPE_UINT32:
581  if (fr_dict_attr_is_key_field(parent)) break;
582  FALL_THROUGH;
583 
584  default:
585  fr_strerror_printf("Attributes of type '%s' cannot have child attributes",
586  fr_type_to_str(parent->type));
587  return false;
588  }
589 
590  return true;
591 }
592 
593 
594 /** Validate a new attribute definition
595  *
596  * @todo we need to check length of none vendor attributes.
597  *
598  * @param[in] da to validate.
599  * @return
600  * - true if attribute definition is valid.
601  * - false if attribute definition is not valid.
602  */
604 {
605  if (!fr_cond_assert(da->parent)) return false;
606 
607  if (fr_dict_valid_name(da->name, -1) <= 0) return false;
608 
609  /*
610  * Run protocol-specific validation functions, BEFORE we
611  * do the rest of the checks.
612  */
613  if (da->dict->proto->attr.valid && !da->dict->proto->attr.valid(da)) return false;
614 
615  /*
616  * Check the flags, data types, and parent data types and flags.
617  */
618  if (!dict_attr_flags_valid(da)) return false;
619 
620  return true;
621 }
static fr_dict_t * dict
Definition: fuzzer.c:46
#define RCSID(id)
Definition: build.h:481
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
size_t type
Length of type data.
Definition: dict.h:247
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition: dict.h:148
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
Definition: dict.h:149
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
Definition: dict.h:146
@ FLAG_BIT_FIELD
bit field inside of a struct
Definition: dict.h:147
unsigned int has_value
Has a value.
Definition: dict.h:92
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:2680
unsigned int is_root
Is root of a dictionary.
Definition: dict.h:74
unsigned int array
Pack multiples into 1 attr.
Definition: dict.h:88
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition: dict.h:112
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition: dict.h:86
uint8_t type_size
For TLV2 and root attributes.
Definition: dict.h:135
size_t length
Length of length data.
Definition: dict.h:248
unsigned int is_known_width
is treated as if it has a known width for structs
Definition: dict.h:90
ssize_t fr_dict_valid_name(char const *name, ssize_t len)
Definition: dict_util.c:4620
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:3328
#define fr_dict_attr_is_key_field(_da)
Definition: dict.h:152
uint8_t subtype
protocol-specific values, OR key fields
Definition: dict.h:121
uint8_t length
length of the attribute
Definition: dict.h:127
unsigned int counter
integer attribute is actually an impulse / counter
Definition: dict.h:96
unsigned int is_unknown
This dictionary attribute is ephemeral and not part of the main dictionary.
Definition: dict.h:76
Values of the encryption flags.
Definition: merged_model.c:139
Private enterprise.
Definition: dict.h:244
#define FORBID_OTHER_FLAGS(_flag, _allowed)
bool dict_attr_flags_valid(fr_dict_attr_t *da)
Validate a set of flags.
Definition: dict_validate.c:35
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
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_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_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ 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_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_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_FLOAT64
Double precision floating point.
Definition: merged_model.c:109
unsigned int uint32_t
Definition: merged_model.c:33
unsigned long int size_t
Definition: merged_model.c:25
static size_t array[MY_ARRAY_SIZE]
static char const * name
fr_aka_sim_id_type_t type
static fr_slen_t parent
Definition: pair.h:851
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
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_signed(_x)
Definition: types.h:362
#define fr_type_is_integer(_x)
Definition: types.h:360
#define FR_TYPE_FIXED_SIZE
Definition: types.h:290