goto check;
}
+ /*
+ * Else we find the reference.
+ */
da = fr_dict_attr_by_oid(NULL, parent, ref);
if (da) {
dict = ctx->dict;
* dictionary.
*/
p = strchr(ref, '.');
- if (!p) goto save;
+ if (!p) goto fixup;
/*
* Get / skip protocol name.
* No known dictionary, so we're asked to just
* use the whole string. Which we did above. So
* either it's a bad ref, OR it's a ref to a
- * dictionary which doesn't exist.
+ * dictionary which hasn't yet been loaded.
+ *
+ * Save the fixup for later, when we've hopefully
+ * loaded the dictionary.
*/
if (slen == 0) {
- save:
+ fixup:
if (dict_fixup_group(&ctx->fixup, CURRENT_FRAME(ctx)->filename, CURRENT_FRAME(ctx)->line,
self, ref, talloc_array_length(ref) - 1) < 0) {
oom:
switch (type) {
case FR_TYPE_STRUCTURAL:
structural:
- if (dict_attr_ref_init(da_p, NULL) < 0) return -1; /* Just allocate space */
-
/*
- * Groups don't have children or
- * namespaces.
+ * Groups don't have children or namespaces. But
+ * they always have refs. Either to the root of
+ * the current dictionary, or to another dictionary,
+ * via its top-level TLV.
+ *
+ * Note that when multiple TLVs have the same
+ * children, the dictionary has to use "clone="
+ * instead of "ref=". That's because the
+ * children of the TLVs all require the correct
+ * parentage. Perhaps that can be changed when
+ * the encoders / decoders are updated. It would be good to just reference the DAs instead of cloning an entire subtree.
*/
- if (type == FR_TYPE_GROUP) break;
+ if (type == FR_TYPE_GROUP) {
+ if (dict_attr_ref_init(da_p, NULL) < 0) return -1;
+ break;
+ }
if (dict_attr_children_init(da_p) < 0) return -1;
if (dict_attr_namespace_init(da_p) < 0) return -1; /* Needed for all TLV style attributes */