The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
dict_unknown.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/** Deal with 'unknown' attributes, creating ephemeral dictionary attributes for them
18 *
19 * @file src/lib/util/dict_unknown.c
20 *
21 * @copyright 2019 The FreeRADIUS server project
22 */
23RCSID("$Id: 59c7eea54b0b4d1467fbb199d7d077169afb7020 $")
24
25#include <freeradius-devel/util/dict_priv.h>
26
27/** Converts an unknown to a known by adding it to the internal dictionaries.
28 *
29 * Does not free old #fr_dict_attr_t, that is left up to the caller.
30 *
31 * @param[in] dict of protocol context we're operating in.
32 * If NULL the internal dictionary will be used.
33 * @param[in] unknown attribute to add.
34 * @return
35 * - Existing #fr_dict_attr_t if unknown was found in a dictionary.
36 * - A new entry representing unknown.
37 */
39{
40 fr_dict_attr_t const *da;
43
44 if (unlikely(dict->read_only)) {
45 fr_strerror_printf("%s dictionary has been marked as read only", fr_dict_root(dict)->name);
46 return NULL;
47 }
48
49#ifdef STATIC_ANALYZER
50 if (!unknown->name || !unknown->parent) return NULL;
51#endif
52
53 da = fr_dict_attr_by_name(NULL, unknown->parent, unknown->name);
54 if (da) {
55 if (da->attr == unknown->attr) return da;
56
57 fr_strerror_printf("Unknown attribute '%s' conflicts with existing attribute in namespace '%s'",
58 da->name, unknown->parent->name);
59 return da;
60 }
61
62 /*
63 * Define the complete unknown hierarchy
64 */
65 if (unknown->parent && unknown->parent->flags.is_unknown) {
66 parent = fr_dict_attr_unknown_add(dict, unknown->parent);
67 if (!parent) {
68 fr_strerror_printf_push("Failed adding parent \"%s\"", unknown->parent->name);
69 return NULL;
70 }
71 } else {
72 parent = unknown->parent;
73 }
74
75 memcpy(&flags, &unknown->flags, sizeof(flags));
76 flags.is_unknown = 0;
77
78 /*
79 * If this is a vendor, we skip most of the sanity
80 * checks and add it to the vendor hash, and add it
81 * as a child attribute to the Vendor-Specific
82 * container.
83 */
84 if (unknown->type == FR_TYPE_VENDOR) {
86
87 if (dict_vendor_add(dict, unknown->name, unknown->attr) < 0) return NULL;
88
89 n = dict_attr_alloc(dict->pool, parent, unknown->name, unknown->attr, unknown->type,
90 &(dict_attr_args_t){ .flags = &flags });
91 if (unlikely(!n)) return NULL;
92
93 /*
94 * Setup parenting for the attribute
95 */
96 if (dict_attr_child_add(UNCONST(fr_dict_attr_t *, unknown->parent), n) < 0) return NULL;
97
98 return n;
99 }
100
101 /*
102 * Look up the attribute by number. If it doesn't exist,
103 * add it both by name and by number. If it does exist,
104 * add it only by name.
105 */
106 da = fr_dict_attr_child_by_num(parent, unknown->attr);
107 if (da) {
109
110 n = dict_attr_alloc(dict->pool, parent, unknown->name, unknown->attr, unknown->type,
111 &(dict_attr_args_t){ .flags = &flags });
112 if (!n) return NULL;
113
114 /*
115 * Add the unknown by NAME. e.g. if the admin does "Attr-26", we want
116 * to return "Attr-26", and NOT "Vendor-Specific". The rest of the server
117 * is responsible for converting "Attr-26 = 0x..." to an actual attribute,
118 * if it so desires.
119 */
121 talloc_free(n);
122 return NULL;
123 }
124
125 return n;
126 }
127
128 /*
129 * Add the attribute by both name and number.
130 *
131 * Fixme - Copy extensions?
132 */
133 if (fr_dict_attr_add(dict, parent, unknown->name, unknown->attr, unknown->type, &flags) < 0) return NULL;
134
135 /*
136 * For paranoia, return it by name.
137 */
138 return fr_dict_attr_by_name(NULL, parent, unknown->name);
139}
140
141/** Free dynamically allocated (unknown attributes)
142 *
143 * If the da was dynamically allocated it will be freed, else the function
144 * will return without doing anything.
145 *
146 * @param[in] da to free.
147 */
149{
150 if (!da || !*da) return;
151
152 /* Don't free real DAs */
153 if (!(*da)->flags.is_unknown) {
154 return;
155 }
156
158
159 *da = NULL;
160}
161
162/** Allocate an unknown DA.
163 *
164 */
166{
168 fr_dict_attr_t const *parent;
169 fr_dict_attr_flags_t flags = da->flags;
170
171 fr_assert(!da->flags.is_root); /* cannot copy root attributes */
172
173 /*
174 * Set the unknown flag, and copy only those other flags
175 * which we know to be correct.
176 */
177 flags.is_unknown = 1;
178 flags.is_raw = 1;
179 flags.array = 0;
180 flags.has_value = 0;
181 if (type != FR_TYPE_VENDOR) {
182 flags.length = 0; /* not fixed length */
183 } else {
184 flags.type_size = da->flags.type_size;
185 flags.length = da->flags.length;
186 }
187 flags.extra = 0;
188
189 /*
190 * Allocate an attribute.
191 */
192 n = dict_attr_alloc_null(ctx, da->dict->proto);
193 if (!n) return NULL;
194
195 /*
196 * We want to have parent / child relationships, AND to
197 * copy all unknown parents, AND to free the unknown
198 * parents when this 'da' is freed. We therefore talloc
199 * the parent from the 'da'.
200 */
201 if (da->parent && da->parent->flags.is_unknown) {
202 parent = fr_dict_attr_unknown_copy(n, da->parent);
203 if (!parent) {
204 error:
205 talloc_free(n);
206 return NULL;
207 }
208
209 } else {
210 parent = da->parent;
211 }
212
213 /*
214 * Initialize the rest of the fields.
215 */
216 if (dict_attr_init(&n, parent, da->name, da->attr, type, &(dict_attr_args_t){ .flags = &flags }) < 0) {
217 goto error;
218 }
219 if (type != FR_TYPE_OCTETS) {
221
224 goto error;
225 }
226 DA_VERIFY(n);
227
228 return n;
229}
230
231/** Copy a known or unknown attribute to produce an unknown attribute with the specified name
232 *
233 * Will copy the complete hierarchy down to the first known attribute.
234 */
236{
237 fr_type_t type = da->type;
238
239 /*
240 * VENDOR, etc. are logical containers, and can have
241 * unknown children, so they're left alone. All other
242 * base types are mangled to OCTETs.
243 *
244 * Note that we can't allocate an unknown STRUCT. If the
245 * structure is malformed, then it's just a sequence of
246 * OCTETS. Similarly, if a GROUP is malformed, then we
247 * have no idea what's inside of it, and we make it OCTETS.
248 */
249 switch (type) {
250 case FR_TYPE_VENDOR:
251 fr_assert(da->flags.type_size != 0);
252 break;
253
254 case FR_TYPE_TLV:
255 case FR_TYPE_VSA:
256 break;
257
258 default:
260 break;
261 }
262
263 return dict_unknown_alloc(ctx, da, type);
264}
265
266/** Initialise a fr_dict_attr_t from a number and a data type
267 *
268 * @param[in] ctx to allocate the attribute in.
269 * @param[in] parent of the unknown attribute (may also be unknown).
270 * @param[in] num of the unknown attribute.
271 * @param[in] type data type
272 * @param[in] raw is it raw, i.e. _bad_ value, versus unknown?
273 * @return
274 * - An fr_dict_attr_t on success.
275 * - NULL on failure.
276 */
278{
279 fr_dict_attr_flags_t flags = {
280 .is_unknown = true,
281 .internal = parent->flags.internal,
282 .is_raw = raw,
283 };
284
285 switch (type) {
286 case FR_TYPE_VENDOR:
287 if (parent->type != FR_TYPE_VSA) goto fail;
288
289 if (!fr_cond_assert(!parent->flags.is_unknown)) return NULL;
290
291 /*
292 * These can be reset later if needed. But these
293 * values are most common.
294 */
295 flags.type_size = 1;
296 flags.length = 1;
297 break;
298
299 case FR_TYPE_NULL:
301 case FR_TYPE_VOID:
302 case FR_TYPE_MAX:
303 fr_strerror_printf("%s: Cannot allocate unknown %s attribute (%u) - invalid data type",
304 __FUNCTION__,
305 fr_type_to_str(type), num);
306 return NULL;
307
308 default:
309 /*
310 * @todo - remove after migration_union_key is deleted
311 */
313
315 fail:
316 fr_strerror_printf("%s: Cannot allocate unknown %s attribute (%u) with parent type %s",
317 __FUNCTION__,
318 fr_type_to_str(type), num,
319 fr_type_to_str(parent->type));
320 return NULL;
321 }
322
323 /*
324 * We can convert anything to 'octets'. But we shouldn't be able to create a raw
325 * attribute which is a _different_ type than an existing one.
326 */
327 if (type != FR_TYPE_OCTETS) {
328 fr_dict_attr_t const *child;
329
330 child = fr_dict_attr_child_by_num(parent, num);
331 if (child && (child->type != type)) {
332 fr_strerror_printf("%s: Cannot allocate unknown attribute (%u) which changes type from %s to %s",
333 __FUNCTION__,
334 num,
335 fr_type_to_str(child->type),
337 return NULL;
338 }
339 }
340
341 break;
342 }
343
344 if (parent->depth >= FR_DICT_MAX_TLV_STACK) {
345 fr_strerror_const("Attribute depth is too large");
346 return NULL;
347 }
348
349 return dict_attr_alloc(ctx, parent, NULL, num, type,
350 &(dict_attr_args_t){ .flags = &flags });
351}
352
353/** Initialise an octets type attribute from a da
354 *
355 * @param[in] ctx to allocate the attribute in.
356 * @param[in] da of the unknown attribute.
357 * @return
358 * - 0 on success.
359 * - -1 on failure.
360 */
362{
363 return dict_unknown_alloc(ctx, da, FR_TYPE_OCTETS);
364}
365
366/** Create a fr_dict_attr_t from an ASCII attribute and value
367 *
368 * Where the attribute name is in the form:
369 * - %d
370 * - %d.%d.%d...
371 *
372 * @note If vendor != 0, an unknown vendor (may) also be created, parented by
373 * the correct VSA attribute. This is accessible via vp->parent,
374 * and will be use the unknown da as its talloc parent.
375 *
376 * @param[in] ctx to alloc new attribute in.
377 * @param[out] out Where to write the head of the chain unknown
378 * dictionary attributes.
379 * @param[in] parent Attribute to use as the root for resolving OIDs in.
380 * Usually the root of a protocol dictionary.
381 * @param[in] in OID string to parse
382 * @param[in] type data type of the unknown attribute
383 * @return
384 * - The number of bytes parsed on success.
385 * - <= 0 on failure. Negative offset indicates parse error position.
386 */
388 fr_dict_attr_t const **out,
389 fr_dict_attr_t const *parent,
391{
392 fr_sbuff_t our_in = FR_SBUFF(in);
393 fr_dict_attr_t const *our_parent = parent;
394 fr_dict_attr_t *n = NULL;
395 fr_dict_attr_flags_t flags = {
396 .is_unknown = true,
397 .is_raw = true,
398 .type_size = parent->dict->root->flags.type_size,
399 .length = parent->dict->root->flags.length,
400 };
401
402 *out = NULL;
403
404 /*
405 * Allocate the final attribute first, so that any
406 * unknown parents can be freed when this da is freed.
407 *
408 * See fr_dict_attr_unknown_afrom_da() for more details.
409 *
410 * Note also that we copy the input name, even if it is
411 * not normalized.
412 *
413 * While the name of this attribute is "Attr-#.#.#", one
414 * or more of the leading components may, in fact, be
415 * known.
416 */
417 n = dict_attr_alloc_null(ctx, parent->dict->proto);
418
419 /*
420 * Loop until there's no more component separators.
421 */
422 for (;;) {
423 uint32_t num;
425
426 fr_sbuff_out(&sberr, &num, &our_in);
427 switch (sberr) {
429 switch (our_parent->type) {
430 /*
431 * If the parent is a VSA, this component
432 * must specify a vendor.
433 */
434 case FR_TYPE_VSA:
435 {
436 fr_dict_attr_t *ni;
437
438 if (fr_sbuff_next_if_char(&our_in, '.')) {
439 ni = fr_dict_attr_unknown_vendor_afrom_num(n, our_parent, num);
440 if (!ni) {
441 error:
442 talloc_free(n);
443 FR_SBUFF_ERROR_RETURN(&our_in);
444 }
445 our_parent = ni;
446 continue;
447 }
448 if (dict_attr_init(&n, our_parent, NULL, num, FR_TYPE_VENDOR,
449 &(dict_attr_args_t){ .flags = &flags }) < 0) goto error;
450 }
451 break;
452
453 /*
454 * If it's structural, this component must
455 * specify a TLV.
456 */
458 {
459 fr_dict_attr_t *ni;
460
461 if (fr_sbuff_next_if_char(&our_in, '.')) {
462 ni = fr_dict_attr_unknown_typed_afrom_num(n, our_parent, num, FR_TYPE_TLV);
463 if (!ni) goto error;
464 our_parent = ni;
465 continue;
466 }
467 }
469
470 default:
471 /*
472 * Leaf type with more components
473 * is an error.
474 */
475 if (fr_sbuff_is_char(&our_in, '.')) {
476 fr_strerror_printf("Interior OID component cannot proceed a %s type",
477 fr_type_to_str(our_parent->type));
478 goto error;
479 }
480 if (dict_attr_init(&n, our_parent, NULL, num, type,
481 &(dict_attr_args_t){ .flags = &flags }) < 0) goto error;
482 break;
483 }
484 break;
485
486 default:
487 {
488 fr_sbuff_marker_t c_start;
489
490 fr_sbuff_marker(&c_start, &our_in);
492 fr_strerror_printf("Unknown attribute \"%.*s\" for parent \"%s\"",
493 (int)fr_sbuff_behind(&c_start), fr_sbuff_current(&c_start), our_parent->name);
494 goto error;
495 }
496 }
497 break;
498 }
499
500 DA_VERIFY(n);
501
502 *out = n;
503
504 FR_SBUFF_SET_RETURN(in, &our_in);
505}
506
507/** Fixup the parent of an unknown attribute using an equivalent known attribute
508 *
509 * This can be useful where an unknown attribute's ancestors are added to
510 * a dictionary but not the unknown attribute itself.
511 *
512 * @param[in] da to fixup.
513 * @param[in] parent to assign. If NULL, we will attempt to resolve
514 * the parent in the dictionary the current unknown
515 * attribute extends.
516 * @return
517 * - 0 on success.
518 * - -1 on failure.
519 */
521{
522 fr_dict_attr_t const *da_u, *da_k;
523
524 if (parent) {
525 /*
526 * Walk back up the hierarchy until we get to a known
527 * ancestor on the unknown side.
528 */
529 for (da_u = da->parent, da_k = parent;
530 da_k && da_u && da_u->flags.is_unknown;
531 da_u = da_u->parent, da_k = da_k->parent) {
532 if (unlikely(da_u->attr != da_k->attr)) {
533 fr_strerror_printf("Unknown parent number %u does not match "
534 "known parent number %u (%s)",
535 da_u->attr, da_k->attr, da_k->name);
536 return -1;
537 }
538
539 if (unlikely(da_u->depth != da_k->depth)) {
540 fr_strerror_printf("Unknown parent depth %u does not match "
541 "known parent depth %u (%s)",
542 da_u->depth, da_k->depth, da_k->name);
543 return -1;
544 }
545 }
546 if ((da_k == NULL) != (da_u == NULL)) {
547 fr_strerror_printf("Truncated or over-extended hierarchy "
548 "for unknown attribute %u", da->attr);
549 return -1;
550 }
551 } else {
553 if (!parent) {
554 fr_strerror_printf("Failed resolving unknown attribute %u "
555 "in dictionary", da->attr);
556 return -1;
557 }
558 }
559
560 da->parent = fr_dict_attr_unconst(parent);
561
562 return 0;
563}
564
565/** Check to see if we can convert a nested TLV structure to known attributes
566 *
567 * @param[in] dict to search in.
568 * @param[in] da Nested tlv structure to convert.
569 * @return
570 * - NULL if we can't.
571 * - Known attribute if we can.
572 */
574{
575 INTERNAL_IF_NULL(dict, NULL);
576
577 if (!da->flags.is_unknown) return da; /* It's known */
578
579 if (da->parent) {
580 fr_dict_attr_t const *parent;
581
582 parent = fr_dict_attr_unknown_resolve(dict, da->parent);
583 if (!parent) return NULL;
584
585 return fr_dict_attr_child_by_num(parent, da->attr);
586 }
587
588 if (dict->root == da) return dict->root;
589 return NULL;
590}
int n
Definition acutest.h:577
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:485
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:324
#define unlikely(_x)
Definition build.h:383
#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:95
fr_dict_t const * fr_dict_by_da(fr_dict_attr_t const *da)
Attempt to locate the protocol dictionary containing an attribute.
Definition dict_util.c:2702
static fr_dict_attr_t * fr_dict_attr_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor)
Definition dict.h:598
bool const fr_dict_attr_allowed_chars[UINT8_MAX+1]
Characters allowed in a single dictionary attribute name.
Definition dict_util.c:64
static fr_dict_attr_t * fr_dict_attr_unknown_copy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Definition dict.h:578
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3359
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition dict_util.c:4736
unsigned int array
Pack multiples into 1 attr.
Definition dict.h:91
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2496
unsigned int extra
really "subtype is used by dict, not by protocol"
Definition dict.h:117
#define DA_VERIFY(_x)
Definition dict.h:68
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
uint8_t type_size
Type size for TLVs.
Definition dict.h:143
uint16_t length
length of the attribute
Definition dict.h:152
@ FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC
Protocol specific extensions.
Definition dict.h:190
#define FR_DICT_MAX_TLV_STACK
Maximum TLV stack size.
Definition dict.h:513
int fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, unsigned int attr, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
Definition dict_util.c:1790
static fr_dict_attr_t * fr_dict_attr_unknown_typed_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int num, fr_type_t type)
Definition dict.h:590
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:3424
#define fr_dict_attr_is_key_field(_da)
Definition dict.h:169
static fr_slen_t in
Definition dict.h:861
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
Definition dict.h:493
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.
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition dict_ext.h:141
static int dict_attr_ext_copy_all(fr_dict_attr_t **da_out_p, fr_dict_attr_t const *da_in)
Copy all attribute extensions from one attribute to another.
static void * dict_attr_ext_copy(fr_dict_attr_t **da_out_p, fr_dict_attr_t const *da_in, fr_dict_attr_ext_t ext)
Copy a single attribute extension from one attribute to another.
#define dict_attr_alloc(_ctx, _parent, _name, _attr, _type, _args)
Definition dict_priv.h:239
#define INTERNAL_IF_NULL(_dict, _ret)
Set the internal dictionary if none was provided.
Definition dict_priv.h:45
int dict_attr_add_to_namespace(fr_dict_attr_t const *parent, fr_dict_attr_t *da)
Add an attribute to the name table for an attribute.
Definition dict_util.c:1602
int dict_attr_child_add(fr_dict_attr_t *parent, fr_dict_attr_t *child)
Add a child to a parent.
Definition dict_util.c:1503
int dict_vendor_add(fr_dict_t *dict, char const *name, unsigned int num)
Add a vendor to the dictionary.
Definition dict_util.c:1384
#define dict_attr_init(_da_p, _parent, _name, _attr, _type, _args)
Full initialisation functions.
Definition dict_priv.h:215
fr_dict_attr_t * dict_attr_alloc_null(TALLOC_CTX *ctx, fr_dict_protocol_t const *dict)
Partial initialisation functions.
Definition dict_util.c:985
Optional arguments for initialising/allocating attributes.
Definition dict_priv.h:175
fr_slen_t fr_dict_attr_unknown_afrom_oid_substr(TALLOC_CTX *ctx, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *in, fr_type_t type)
Create a fr_dict_attr_t from an ASCII attribute and value.
fr_dict_attr_t const * fr_dict_attr_unknown_resolve(fr_dict_t const *dict, fr_dict_attr_t const *da)
Check to see if we can convert a nested TLV structure to known attributes.
fr_dict_attr_t * fr_dict_attr_unknown_typed_afrom_num_raw(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int num, fr_type_t type, bool raw)
Initialise a fr_dict_attr_t from a number and a data type.
int fr_dict_attr_unknown_parent_to_known(fr_dict_attr_t *da, fr_dict_attr_t const *parent)
Fixup the parent of an unknown attribute using an equivalent known attribute.
void fr_dict_attr_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
fr_dict_attr_t const * fr_dict_attr_unknown_add(fr_dict_t *dict, fr_dict_attr_t const *unknown)
Converts an unknown to a known by adding it to the internal dictionaries.
fr_dict_attr_t * fr_dict_attr_unknown_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Copy a known or unknown attribute to produce an unknown attribute with the specified name.
static fr_dict_attr_t * dict_unknown_alloc(TALLOC_CTX *ctx, fr_dict_attr_t const *da, fr_type_t type)
Allocate an unknown DA.
fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Initialise an octets type attribute from a da.
talloc_free(reap)
fr_type_t
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_VALUE_BOX
A boxed value.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
ssize_t fr_slen_t
fr_sbuff_parse_error_t
@ FR_SBUFF_PARSE_OK
No error.
#define fr_assert(_expr)
Definition rad_assert.h:38
static char const * name
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:1805
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:2116
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_behind(_sbuff_or_marker)
fr_aka_sim_id_type_t type
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:229
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_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define FR_TYPE_STRUCTURAL_EXCEPT_VSA
Definition types.h:315
#define fr_type_is_structural_except_vsa(_x)
Definition types.h:392
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
static size_t char ** out
Definition value.h:1023