The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
dict_fixup.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 /** Code to apply fctx and finalisation steps to a dictionary
18  *
19  * @file src/lib/util/dict_fixup.c
20  *
21  * @copyright 2020 The FreeRADIUS server project
22  * @copyright 2020 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23  */
24 RCSID("$Id: 32532812ba65083d58940e709365825e61dbe292 $")
25 
26 #include <freeradius-devel/util/talloc.h>
27 #include <freeradius-devel/util/file.h>
28 #include "dict_fixup_priv.h"
29 
30 /** Common fields for every fixup structure
31  *
32  */
33 typedef struct {
34  fr_dlist_t entry; //!< Entry in linked list of fctx.
35 
36  char *filename; //!< where the line being fixed up.
37  int line; //!< ditto.
39 
40 /** Add an enumeration value to an attribute that wasn't defined at the time the value was parsed
41  *
42  */
43 typedef struct {
44  dict_fixup_common_t common; //!< Common fields.
45 
46  char *attribute; //!< we couldn't find (and will need to resolve later).
47  char *name; //!< Raw enum name.
48  char *value; //!< Raw enum value. We can't do anything with this until
49  //!< we know the attribute type, which we only find out later.
50 
51  fr_dict_attr_t const *parent; //!< Parent attribute to resolve the 'attribute' string in.
53 
54 /** Resolve a group reference
55  *
56  */
57 typedef struct {
58  dict_fixup_common_t common; //!< Common fields.
59 
60  fr_dict_attr_t *da; //!< FR_TYPE_GROUP to fix
61  char *ref; //!< the reference name
63 
64 /** Clone operation from one tree node to another
65  *
66  */
67 typedef struct {
68  dict_fixup_common_t common; //!< Common fields.
69 
70  fr_dict_attr_t *parent; //!< parent where we add the clone
71  fr_dict_attr_t *da; //!< FR_TYPE_TLV to clone
72  char *ref; //!< the target attribute to clone
74 
75 /** Dictionary attribute namespaces need their hash tables finalised
76  *
77  */
78 typedef struct {
79  dict_fixup_common_t common; //!< Common fields.
80 
81  fr_hash_table_t *hash; //!< We need to finalise.
83 
84 /** Initialise common fields in fixup struct, and add it to a fixup list
85  *
86  * @param[in] filename this fixup relates to.
87  * @param[in] line this fixup relates to.
88  * @param[in] fixup_list to add fixup to.
89  * @param[in] common common header to populate.
90  * @return
91  * - 0 on success.
92  * - -1 on out of memory.
93  */
94 static inline CC_HINT(always_inline) int dict_fixup_common(char const *filename, int line,
95  fr_dlist_head_t *fixup_list, dict_fixup_common_t *common)
96 {
97  common->filename = talloc_strdup(common, filename);
98  if (!common->filename) {
99  fr_strerror_const("Out of memory");
100  return -1;
101  }
102  common->line = line;
103 
104  fr_dlist_insert_tail(fixup_list, common);
105 
106  return 0;
107 }
108 
109 /** Add an enumeration value to an attribute which has not yet been defined
110  *
111  * @param[in] fctx Holds current dictionary parsing information.
112  * @param[in] filename this fixup relates to.
113  * @param[in] line this fixup relates to.
114  * @param[in] attr The OID string pointing to the attribute
115  * to add the enumeration value to.
116  * @param[in] attr_len The length of the attr string.
117  * @param[in] name The name of the enumv.
118  * @param[in] name_len Length of the name string.
119  * @param[in] value Value string. This is kept as a string until we know
120  * what type we want to transform it into.
121  * @param[in] value_len Length of the value string.
122  * @param[in] parent of this attribute.
123  * @return
124  * - 0 on success.
125  * - -1 on out of memory.
126  */
127 int dict_fixup_enumv(dict_fixup_ctx_t *fctx, char const *filename, int line,
128  char const *attr, size_t attr_len,
129  char const *name, size_t name_len,
130  char const *value, size_t value_len,
131  fr_dict_attr_t const *parent)
132 {
133  dict_fixup_enumv_t *fixup;
134 
135  fixup = talloc(fctx->pool, dict_fixup_enumv_t);
136  if (!fixup) {
137  oom:
138  fr_strerror_const("Out of memory");
139  return -1;
140  }
141  *fixup = (dict_fixup_enumv_t) {
142  .attribute = talloc_bstrndup(fixup, attr, attr_len),
143  .name = talloc_bstrndup(fixup, name, name_len),
144  .value = talloc_bstrndup(fixup, value, value_len),
145  .parent = parent
146  };
147  if (!fixup->attribute || !fixup->name || !fixup->value) goto oom;
148 
149  return dict_fixup_common(filename, line, &fctx->enumv, &fixup->common);
150 }
151 
152 /** Add a previously defined enumeration value to an existing attribute
153  *
154  * @param[in] fctx Holds current dictionary parsing information.
155  * @param[in] fixup Hash table to fill.
156  * @return
157  * - 0 on success.
158  * - -1 on failure.
159  */
160 static inline CC_HINT(always_inline) int dict_fixup_enumv_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_enumv_t *fixup)
161 {
162  fr_dict_attr_t *da;
164  fr_type_t type;
165  int ret;
166  fr_dict_attr_t const *da_const;
167 
168  da_const = fr_dict_attr_by_oid(NULL, fixup->parent, fixup->attribute);
169  if (!da_const) {
170  fr_strerror_printf_push("Failed resolving ATTRIBUTE referenced by VALUE '%s' at %s[%d]",
171  fixup->name, fr_cwd_strip(fixup->common.filename), fixup->common.line);
172  return -1;
173  }
174  da = fr_dict_attr_unconst(da_const);
175  type = da->type;
176 
177  if (fr_value_box_from_str(fixup, &value, type, NULL,
178  fixup->value, talloc_array_length(fixup->value) - 1,
179  NULL, false) < 0) {
180  fr_strerror_printf_push("Invalid VALUE '%pV' for attribute '%s' at %s[%d]",
182  da->name,
183  fr_cwd_strip(fixup->common.filename), fixup->common.line);
184  return -1;
185  }
186 
187  ret = fr_dict_enum_add_name(da, fixup->name, &value, false, false);
189 
190  if (ret < 0) return -1;
191 
192  return 0;
193 }
194 
195 /** Resolve a group reference
196  *
197  * This is required as the reference may point to another dictionary which
198  * hasn't been loaded yet.
199  *
200  * @param[in] fctx Holds current dictionary parsing information.
201  * @param[in] filename this fixup relates to.
202  * @param[in] line this fixup relates to.
203  * @param[in] da The group dictionary attribute.
204  * @param[in] ref OID string representing what the group references.
205  * @return
206  * - 0 on success.
207  * - -1 on out of memory.
208  */
209 int dict_fixup_group(dict_fixup_ctx_t *fctx, char const *filename, int line,
210  fr_dict_attr_t *da, char const *ref)
211 {
212  dict_fixup_group_t *fixup;
213 
214  fixup = talloc(fctx->pool, dict_fixup_group_t);
215  if (!fixup) {
216  fr_strerror_const("Out of memory");
217  return -1;
218  }
219  *fixup = (dict_fixup_group_t) {
220  .da = da,
221  .ref = talloc_strdup(fixup, ref),
222  };
223 
224  return dict_fixup_common(filename, line, &fctx->group, &fixup->common);
225 }
226 
227 static fr_dict_attr_t const *dict_protocol_reference(fr_dict_t **dict_def, char const *ref, char const *filename, int line)
228 {
229  fr_dict_t *dict;
230  fr_dict_attr_t const *da;
231  char const *name;
232  ssize_t slen;
233  char protocol[64];
234 
235  fr_assert((ref[0] == '.') && (ref[1] == '.'));
236  name = ref + 2; /* already checked when we inserted it */
237 
238  /*
239  * Reference to foreign protocol. Get the protocol name.
240  */
241  slen = dict_by_protocol_substr(NULL, &dict, &FR_SBUFF_IN(name, strlen(name)), NULL);
242  if (slen <= 0) {
243  char *p;
244  char const *q;
245 
246  /*
247  * The filenames are lowercase. The names in the dictionaries are case-insensitive. So
248  * we mash the name to all lowercase.
249  */
250  p = protocol;
251  q = name;
252  while (*q && (*q != '.')) {
253  *(p++) = tolower((int) *(q++));
254 
255  if ((size_t) (p - protocol) >= sizeof(protocol)) {
256  invalid:
257  fr_strerror_printf("Invalid attribute reference '%s' at %s[%d]", ref,
258  fr_cwd_strip(filename), line);
259  return NULL;
260  }
261  }
262  *p = '\0';
263 
264  /*
265  * Load the new dictionary, and mark it as loaded from our dictionary.
266  */
267  if (fr_dict_protocol_afrom_file(&dict, protocol, NULL, (*dict_def)->root->name) < 0) {
268  return NULL;
269  }
270 
271  if (!fr_hash_table_insert((*dict_def)->autoref, dict)) {
272  fr_strerror_const("Failed inserting into internal autoref table");
273  return NULL;
274  }
275 
276  /*
277  * The reference is to the root of the foreign protocol, we're done.
278  */
279  if (!*q) {
280  *dict_def = dict;
281  return dict->root;
282  }
283 
284  name = p + 1;
285 
286  } else {
287  /*
288  * The foreign dictionary was loaded by someone
289  * else, try to resolve the attribute.
290  */
291  name += slen;
292 
293  if (!*name) {
294  /*
295  * The reference is to the root of the foreign protocol, we're done.
296  */
297  *dict_def = dict;
298  return dict->root;
299  }
300 
301  if (*name != '.') goto invalid;
302  name++;
303  }
304 
305  /*
306  * Look up the attribute.
307  */
309  if (!da) {
310  fr_strerror_printf("No such attribute '%s' in protocol '%s' at %s[%d]",
311  name, dict->root->name, fr_cwd_strip(filename), line);
312  return NULL;
313  }
314 
315  *dict_def = dict;
316  return da;
317 }
318 
319 /** Resolve a group reference
320  *
321  * @param[in] fctx Holds current dictionary parsing information.
322  * @param[in] fixup Hash table to fill.
323  * @return
324  * - 0 on success.
325  * - -1 on failure.
326  */
327 static inline CC_HINT(always_inline) int dict_fixup_group_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_group_t *fixup)
328 {
329  fr_dict_attr_t const *da;
331 
332  /*
333  * Ref to attribute in existing dictionary. The dictionary MUST be loaded by $INCLUDEs.
334  */
335  if (fixup->ref[0] != '.') {
336  da = fr_dict_attr_by_oid(NULL, fr_dict_root(dict), fixup->ref);
337  if (!da) {
338  fr_strerror_printf("Invalid attribute reference '%s' at %s[%d]", fixup->ref,
339  fr_cwd_strip(fixup->common.filename), fixup->common.line);
340  return -1;
341  }
342  } else {
343  /*
344  * Load a foreign protocol, which may include
345  * loops.
346  */
347  da = dict_protocol_reference(&dict, fixup->ref, fixup->common.filename, fixup->common.line);
348  if (!da) return -1;
349  }
350 
351  if (da->type != FR_TYPE_TLV) {
352  fr_strerror_printf("References MUST be to attributes of type 'tlv' at %s[%d]",
353  fr_cwd_strip(fixup->common.filename), fixup->common.line);
354  return -1;
355  }
356 
357  if (fr_dict_attr_ref(da)) {
358  fr_strerror_printf("References MUST NOT refer to an ATTRIBUTE which also has 'ref=...' at %s[%d]",
359  fr_cwd_strip(fixup->common.filename), fixup->common.line);
360  return -1;
361  }
362  dict_attr_ref_set(fixup->da, da);
363 
364  return 0;
365 }
366 
367 /** Clone one area of a tree into another
368  *
369  * These must be processed later to ensure that we've finished building an
370  * attribute by the time it has been cloned.
371  *
372  * @param[in] fctx Holds current dictionary parsing information.
373  * @param[in] filename this fixup relates to.
374  * @param[in] line this fixup relates to.
375  * @param[in] parent for the cloned attribute.
376  * @param[in] da The group dictionary attribute.
377  * @param[in] ref OID string representing what the group references.
378  * @param[in] ref_len Length of the reference string.
379  * @return
380  * - 0 on success.
381  * - -1 on out of memory.
382  */
383 int dict_fixup_clone(dict_fixup_ctx_t *fctx, char const *filename, int line,
385  char const *ref, size_t ref_len)
386 {
387  dict_fixup_clone_t *fixup;
388 
389  /*
390  * Delay type checks until we've loaded all of the
391  * dictionaries. This means that errors are produced
392  * later, but that shouldn't matter for the default
393  * dictionaries. They're supposed to work.
394  */
395  fixup = talloc(fctx->pool, dict_fixup_clone_t);
396  if (!fixup) {
397  fr_strerror_const("Out of memory");
398  return -1;
399  }
400  *fixup = (dict_fixup_clone_t) {
401  .parent = parent,
402  .da = da,
403  .ref = talloc_bstrndup(fixup, ref, ref_len)
404  };
405 
406  return dict_fixup_common(filename, line, &fctx->clone, &fixup->common);
407 }
408 
409 /** Clone one are of a tree into another
410  *
411  * @param[in] fctx Holds current dictionary parsing information.
412  * @param[in] fixup Containing source/destination of the clone.
413  * @return
414  * - 0 on success.
415  * - -1 on failure.
416  */
417 static inline CC_HINT(always_inline) int dict_fixup_clone_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_clone_t *fixup)
418 {
419  fr_dict_attr_t const *da, *root;
420  fr_dict_attr_t *cloned;
422  char const *ref = fixup->ref;
423 
424  /*
425  * Allow relative attribute references.
426  */
427  if (ref[0] == '.') {
428  root = fixup->da->parent;
429  ref++;
430 
431  while (ref[0] == '.') {
432  /*
433  * @todo - allow references to other protocols.
434  */
435  if (root->flags.is_root) {
436  fr_strerror_printf("Too many '.' in clone=%s at %s[%d]",
437  fixup->ref, fr_cwd_strip(fixup->common.filename), fixup->common.line);
438  return -1;
439  }
440 
441  root = root->parent;
442  ref++;
443  }
444  } else {
445  root = fr_dict_root(dict);
446  }
447 
448  /*
449  * Find the reference
450  */
451  da = fr_dict_attr_by_oid(NULL, root, ref);
452  if (!da) {
453  fr_strerror_printf("Unknown attribute reference in clone=%s at parent %s %s[%d]",
454  fixup->ref, root->name, fr_cwd_strip(fixup->common.filename), fixup->common.line);
455  return -1;
456  }
457 
458  /*
459  * The referenced DA is higher than the one we're
460  * creating. Ensure it's not a parent.
461  */
462  if (da->depth < fixup->da->depth) {
463  fr_dict_attr_t const *parent;
464 
465  for (parent = fixup->da->parent; !parent->flags.is_root; parent = parent->parent) {
466  if (parent == da) {
467  fr_strerror_printf("References MUST NOT refer to a parent attribute %s at %s[%d]",
468  parent->name, fr_cwd_strip(fixup->common.filename), fixup->common.line);
469  return -1;
470  }
471  }
472  }
473 
474  if (fr_dict_attr_ref(da)) {
475  fr_strerror_printf("References MUST NOT refer to an ATTRIBUTE which itself has a 'ref=...' at %s[%d]",
476  fr_cwd_strip(fixup->common.filename), fixup->common.line);
477  return -1;
478  }
479 
480  /*
481  * If the attributes are of different types, then we have
482  * to _manually_ clone the values. This means looping
483  * over the ref da, and _casting_ the values to the new
484  * data type. If the cast succeeds, we add the value.
485  * Otherwise we don't
486  *
487  * We do this if the source type is a leaf node, AND the
488  * types are different, or the destination has no
489  * children.
490  */
491  if (!fr_type_is_non_leaf(fixup->da->type) &&
492  ((da->type != fixup->da->type) || !dict_attr_children(da))) {
493  int copied;
494 
495  /*
496  * Only TLV and STRUCT types can be the source or destination of clones.
497  *
498  * Leaf types can be cloned, even if they're
499  * different types. But only if they don't have
500  * children (i.e. key fields).
501  */
502  if (fr_type_is_non_leaf(da->type) || fr_type_is_non_leaf(fixup->da->type) ||
503  dict_attr_children(da) || dict_attr_children(fixup->da)) {
504  fr_strerror_printf("Reference MUST be to a simple data type of type '%s' at %s[%d]",
505  fr_type_to_str(fixup->da->type),
506  fr_cwd_strip(fixup->common.filename), fixup->common.line);
507  return -1;
508  }
509 
510  /*
511  * We copy all of the VALUEs over from the source
512  * da by hand, by casting them.
513  *
514  * We have to do this work manually because we
515  * can't call dict_attr_acopy(), as that function
516  * copies the VALUE with the *source* data type,
517  * where we need the *destination* data type.
518  */
519  copied = dict_attr_acopy_enumv(fixup->da, da);
520  if (copied < 0) return -1;
521 
522  if (!copied) {
523  fr_strerror_printf("Reference copied no VALUEs from type type '%s' at %s[%d]",
524  fr_type_to_str(fixup->da->type),
525  fr_cwd_strip(fixup->common.filename), fixup->common.line);
526  return -1;
527  }
528 
529  /*
530  * We don't need to copy any children, so leave
531  * fixup->da in the dictionary.
532  */
533  return 0;
534  }
535 
536  /*
537  * Can't clone KEY fields directly, you MUST clone the parent struct.
538  */
540  fr_strerror_printf("Invalid reference from '%s' to %s", fixup->ref, da->name);
541  return -1;
542  }
543 
544  /*
545  * Copy the source attribute, but with a
546  * new name and a new attribute number.
547  */
548  cloned = dict_attr_acopy(dict->pool, da, fixup->da->name);
549  if (!cloned) {
550  fr_strerror_printf("Failed copying attribute '%s' to %s", da->name, fixup->ref);
551  return -1;
552  }
553 
554  cloned->attr = fixup->da->attr;
555  cloned->parent = fixup->parent; /* we need to re-parent this attribute */
556  cloned->depth = cloned->parent->depth + 1;
557 
558  /*
559  * Copy any pre-existing children over.
560  */
561  if (dict_attr_children(fixup->da)) {
562  if (dict_attr_acopy_children(dict, cloned, fixup->da) < 0) {
563  fr_strerror_printf("Failed copying attribute '%s' from children of %s", da->name, fixup->ref);
564  return -1;
565  }
566  }
567 
568  /*
569  * Copy children of the DA we're cloning.
570  */
571  if (dict_attr_children(da)) {
572  if (dict_attr_acopy_children(dict, cloned, da) < 0) {
573  fr_strerror_printf("Failed copying attribute '%s' from children of %s", da->name, fixup->ref);
574  return -1;
575  }
576 
577  if (dict_attr_child_add(fr_dict_attr_unconst(fixup->parent), cloned) < 0) {
578  fr_strerror_printf("Failed adding attribute %s", da->name);
579  talloc_free(cloned);
580  return -1;
581  }
582  }
583 
584  if (dict_attr_add_to_namespace(fixup->parent, cloned) < 0) return -1;
585 
586  return 0;
587 }
588 
589 /** Initialise a fixup ctx
590  *
591  * @param[in] ctx to allocate the fixup pool in.
592  * @param[in] fctx to initialise.
593  * @return
594  * - 0 on success.
595  * - -1 on failure.
596  */
597 int dict_fixup_init(TALLOC_CTX *ctx, dict_fixup_ctx_t *fctx)
598 {
599  if (fctx->pool) return 0;
600 
601  fr_dlist_talloc_init(&fctx->enumv, dict_fixup_enumv_t, common.entry);
602  fr_dlist_talloc_init(&fctx->group, dict_fixup_group_t, common.entry);
603  fr_dlist_talloc_init(&fctx->clone, dict_fixup_clone_t, common.entry);
604 
605  fctx->pool = talloc_pool(ctx, DICT_FIXUP_POOL_SIZE);
606  if (!fctx->pool) return -1;
607 
608  return 0;
609 }
610 
611 /** Apply all outstanding fixes to a set of dictionaries
612  *
613  */
615 {
616 
617 #define APPLY_FIXUP(_fctx, _list, _func, _type) \
618 do { \
619  _type *_fixup; \
620  while ((_fixup = fr_dlist_head(&(_fctx)->_list))) { \
621  if (_func(_fctx, _fixup) < 0) return -1; \
622  fr_dlist_remove(&(_fctx)->_list, _fixup); \
623  talloc_free(_fixup); \
624  } \
625 } while (0)
626 
627  /*
628  * Apply all the fctx in order
629  *
630  * - Enumerations first as they have no dependencies
631  * - Group references next, as group attributes may be cloned.
632  * - Clones last as all other references and additions should
633  * be applied before cloning.
634  * - Hash table fctx last.
635  */
639 
640  TALLOC_FREE(fctx->pool);
641 
642  return 0;
643 }
644 
645 /** Fixup all hash tables in the dictionary so they're suitable for threaded access
646  *
647  */
648 static int _dict_attr_fixup_hash_tables(fr_dict_attr_t const *da, UNUSED void *uctx)
649 {
650  {
652 
654  if (ext) {
657  }
658  }
659 
660  {
662 
665  }
666 
667  return 0;
668 }
669 
670 /** Walk a dictionary finalising the hash tables in all attributes with a distinct namespace
671  *
672  * @param[in] dict to finalise namespaces for.
673  */
675 {
677 
678  (void)_dict_attr_fixup_hash_tables(root, NULL);
679 
681 
682  /*
683  * Walk over all of the hash tables to ensure they're
684  * initialized. We do this because the threads may perform
685  * lookups, and we don't want multi-threaded re-ordering
686  * of the table entries. That would be bad.
687  */
688  fr_hash_table_fill(dict->vendors_by_name);
689  fr_hash_table_fill(dict->vendors_by_num);
690 }
int const char int line
Definition: acutest.h:702
static fr_dict_t * dict
Definition: fuzzer.c:46
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
fr_dict_attr_t const * fr_dict_attr_by_oid(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *oid))
Resolve an attribute using an OID string.
Definition: dict_util.c:1970
int fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name, fr_value_box_t const *value, bool coerce, bool replace)
Add a value name.
Definition: dict_util.c:1535
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition: dict_util.c:4191
int fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx)
Definition: dict_util.c:4371
int fr_dict_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir, char const *dependent)
(Re)-initialize a protocol dictionary
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
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:2203
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
Definition: dict_util.c:4179
@ FR_DICT_ATTR_EXT_ENUMV
Enumeration values.
Definition: dict.h:166
#define fr_dict_attr_is_key_field(_da)
Definition: dict.h:149
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
Definition: dict_ext.h:120
fr_hash_table_t * name_by_value
Lookup a name by value.
Definition: dict_ext.h:90
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
Definition: dict_ext.h:164
fr_hash_table_t * value_by_name
Lookup an enumeration value by name.
Definition: dict_ext.h:89
Attribute extension - Holds enumeration values.
Definition: dict_ext.h:87
static int dict_attr_ref_set(fr_dict_attr_t const *da, fr_dict_attr_t const *ref)
static fr_hash_table_t * dict_attr_namespace(fr_dict_attr_t const *da)
Return the namespace hash table associated with the attribute.
static fr_dict_attr_t const ** dict_attr_children(fr_dict_attr_t const *da)
fr_dict_attr_t * da
FR_TYPE_GROUP to fix.
Definition: dict_fixup.c:60
dict_fixup_common_t common
Common fields.
Definition: dict_fixup.c:44
int dict_fixup_apply(dict_fixup_ctx_t *fctx)
Apply all outstanding fixes to a set of dictionaries.
Definition: dict_fixup.c:614
char * ref
the target attribute to clone
Definition: dict_fixup.c:72
char * attribute
we couldn't find (and will need to resolve later).
Definition: dict_fixup.c:46
static int dict_fixup_clone_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_clone_t *fixup)
Clone one are of a tree into another.
Definition: dict_fixup.c:417
char * value
Raw enum value.
Definition: dict_fixup.c:48
int dict_fixup_group(dict_fixup_ctx_t *fctx, char const *filename, int line, fr_dict_attr_t *da, char const *ref)
Resolve a group reference.
Definition: dict_fixup.c:209
int dict_fixup_enumv(dict_fixup_ctx_t *fctx, char const *filename, int line, char const *attr, size_t attr_len, char const *name, size_t name_len, char const *value, size_t value_len, fr_dict_attr_t const *parent)
Add an enumeration value to an attribute which has not yet been defined.
Definition: dict_fixup.c:127
static fr_dict_attr_t const * dict_protocol_reference(fr_dict_t **dict_def, char const *ref, char const *filename, int line)
Definition: dict_fixup.c:227
dict_fixup_common_t common
Common fields.
Definition: dict_fixup.c:58
int dict_fixup_init(TALLOC_CTX *ctx, dict_fixup_ctx_t *fctx)
Initialise a fixup ctx.
Definition: dict_fixup.c:597
fr_dict_attr_t * parent
parent where we add the clone
Definition: dict_fixup.c:70
fr_dlist_t entry
Entry in linked list of fctx.
Definition: dict_fixup.c:34
char * filename
where the line being fixed up.
Definition: dict_fixup.c:36
fr_dict_attr_t const * parent
Parent attribute to resolve the 'attribute' string in.
Definition: dict_fixup.c:51
static int _dict_attr_fixup_hash_tables(fr_dict_attr_t const *da, UNUSED void *uctx)
Fixup all hash tables in the dictionary so they're suitable for threaded access.
Definition: dict_fixup.c:648
static int dict_fixup_common(char const *filename, int line, fr_dlist_head_t *fixup_list, dict_fixup_common_t *common)
Initialise common fields in fixup struct, and add it to a fixup list.
Definition: dict_fixup.c:94
dict_fixup_common_t common
Common fields.
Definition: dict_fixup.c:79
fr_hash_table_t * hash
We need to finalise.
Definition: dict_fixup.c:81
static int dict_fixup_group_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_group_t *fixup)
Resolve a group reference.
Definition: dict_fixup.c:327
char * ref
the reference name
Definition: dict_fixup.c:61
static int dict_fixup_enumv_apply(UNUSED dict_fixup_ctx_t *fctx, dict_fixup_enumv_t *fixup)
Add a previously defined enumeration value to an existing attribute.
Definition: dict_fixup.c:160
#define APPLY_FIXUP(_fctx, _list, _func, _type)
char * name
Raw enum name.
Definition: dict_fixup.c:47
void dict_hash_tables_finalise(fr_dict_t *dict)
Walk a dictionary finalising the hash tables in all attributes with a distinct namespace.
Definition: dict_fixup.c:674
fr_dict_attr_t * da
FR_TYPE_TLV to clone.
Definition: dict_fixup.c:71
dict_fixup_common_t common
Common fields.
Definition: dict_fixup.c:68
int dict_fixup_clone(dict_fixup_ctx_t *fctx, char const *filename, int line, fr_dict_attr_t *parent, fr_dict_attr_t *da, char const *ref, size_t ref_len)
Clone one area of a tree into another.
Definition: dict_fixup.c:383
Clone operation from one tree node to another.
Definition: dict_fixup.c:67
Common fields for every fixup structure.
Definition: dict_fixup.c:33
Add an enumeration value to an attribute that wasn't defined at the time the value was parsed.
Definition: dict_fixup.c:43
Resolve a group reference.
Definition: dict_fixup.c:57
Dictionary attribute namespaces need their hash tables finalised.
Definition: dict_fixup.c:78
Functions to finalise and fixup dictionaries.
fr_dlist_head_t group
Group references to resolve.
fr_dlist_head_t clone
Clone operation to apply.
fr_dlist_head_t enumv
Raw enumeration values to add.
TALLOC_CTX * pool
Temporary pool for fixups, reduces holes.
fr_slen_t dict_by_protocol_substr(fr_dict_attr_err_t *err, fr_dict_t **out, fr_sbuff_t *name, fr_dict_t const *dict_def)
Definition: dict_util.c:2012
fr_dict_attr_t * dict_attr_acopy(TALLOC_CTX *ctx, fr_dict_attr_t const *in, char const *new_name)
Copy a an existing attribute.
Definition: dict_util.c:725
#define DICT_FIXUP_POOL_SIZE
Definition: dict_priv.h:38
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:1145
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:1046
int dict_attr_acopy_children(fr_dict_t *dict, fr_dict_attr_t *dst, fr_dict_attr_t const *src)
Copy the children of an existing attribute.
Definition: dict_util.c:751
int dict_attr_acopy_enumv(fr_dict_attr_t *dst, fr_dict_attr_t const *src)
Copy the VALUEs of an existing attribute, by casting them.
Definition: dict_util.c:804
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
#define fr_dlist_talloc_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition: dlist.h:275
Head of a doubly linked list.
Definition: dlist.h:51
Entry in a doubly linked list.
Definition: dlist.h:41
char const * fr_cwd_strip(char const *filename)
Intended to be used in logging functions to make output more readable.
Definition: file.c:365
bool fr_hash_table_insert(fr_hash_table_t *ht, void const *data)
Insert data into a hash table.
Definition: hash.c:466
void fr_hash_table_fill(fr_hash_table_t *ht)
Ensure all buckets are filled.
Definition: hash.c:713
talloc_free(reap)
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
long int ssize_t
Definition: merged_model.c:24
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:132
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
fr_assert(0)
fr_aka_sim_id_type_t type
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition: talloc.c:452
static fr_slen_t parent
Definition: pair.h:844
#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_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
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
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3672
#define fr_box_strvalue_buffer(_val)
Definition: value.h:282
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
Definition: value.h:475