From: Alan T. DeKok Date: Mon, 25 Aug 2025 12:19:57 +0000 (-0400) Subject: add migration flag for key field transition X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6abeb6a6994ccdd18204fd01d5e113c7ab33340;p=thirdparty%2Ffreeradius-server.git add migration flag for key field transition there's no configuration for it, but the flag is added automatically --- diff --git a/src/lib/server/tmpl_eval.c b/src/lib/server/tmpl_eval.c index ea437fb01b3..a370b09ca66 100644 --- a/src/lib/server/tmpl_eval.c +++ b/src/lib/server/tmpl_eval.c @@ -892,6 +892,8 @@ int pair_append_by_tmpl_parent(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t * * We just skip one level down an don't create or update * the key pair. + * + * @todo - remove after migration_union_key is deleted */ if (vp && fr_dict_attr_is_key_field(ar->da) && fr_type_is_leaf(vp->data.type)) { ar = tmpl_attr_list_next(ar_list, ar); diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index e6dd2d54ea5..89d829788ad 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -2108,6 +2108,8 @@ do_suffix: /* * Key fields can have children, because we really don't know how else to * represent the child structures. + * + * @todo - remove after migration_union_key is deleted */ if (fr_dict_attr_is_key_field(da)) goto is_union; diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 98dc6de8f63..6c122acea81 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -120,6 +120,8 @@ typedef struct { unsigned int has_fixup : 1; //! needs a fixup during dictionary parsing + unsigned int migration_union_key; //!< for migrating key fields + /* * main: extra is set, then this field is is key, bit, or a uint16 length field. * radius: is one of 9 options for flags diff --git a/src/lib/util/dict_ext.c b/src/lib/util/dict_ext.c index f9b35ba37ba..01e45b71092 100644 --- a/src/lib/util/dict_ext.c +++ b/src/lib/util/dict_ext.c @@ -66,7 +66,11 @@ static int fr_dict_attr_ext_enumv_copy(UNUSED int ext, fr_dict_attr_ext_enumv_t *src_ext = src_ext_ptr; fr_hash_iter_t iter; fr_dict_enum_value_t *enumv; - bool has_child = fr_dict_attr_is_key_field(da_src); + + /* + * @todo - remove after migration_union_key is deleted + */ + bool has_child = fr_dict_attr_is_key_field(da_src) && !da_src->flags.migration_union_key; if (!src_ext->value_by_name) return 0; diff --git a/src/lib/util/dict_fixup.c b/src/lib/util/dict_fixup.c index f1098942784..47c5c630611 100644 --- a/src/lib/util/dict_fixup.c +++ b/src/lib/util/dict_fixup.c @@ -541,6 +541,8 @@ int dict_fixup_clone(fr_dict_attr_t **dst_p, fr_dict_attr_t const *src) /* * Can't clone KEY fields directly, you MUST clone the parent struct. + * + * @todo - remove after migration_union_key is deleted */ if (!fr_type_is_non_leaf(src->type) || fr_dict_attr_is_key_field(src) || fr_dict_attr_is_key_field(dst)) { fr_strerror_printf("Invalid reference from '%s' to %s", dst->name, src->name); diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index 4e9de584cfb..95deb64be87 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -1440,6 +1440,8 @@ static int dict_read_process_attribute(dict_tokenize_ctx_t *dctx, char **argv, i key = ext->ref; fr_assert(key); fr_assert(fr_dict_attr_is_key_field(key)); + da = UNCONST(fr_dict_attr_t *, key); + da->flags.migration_union_key = true; } da = dict_attr_alloc_null(dctx->dict->pool, dctx->dict->proto); @@ -2546,6 +2548,9 @@ static int dict_read_process_struct(dict_tokenize_ctx_t *dctx, char **argv, int return -1; } + /* + * @todo - remove after migration_union_key is deleted + */ if (!fr_dict_attr_is_key_field(parent)) { fr_strerror_printf("Attribute '%s' is not a 'key' attribute", key_attr); return -1; diff --git a/src/lib/util/dict_unknown.c b/src/lib/util/dict_unknown.c index 8d5e7a5616c..59c7eea54b0 100644 --- a/src/lib/util/dict_unknown.c +++ b/src/lib/util/dict_unknown.c @@ -306,6 +306,9 @@ fr_dict_attr_t *fr_dict_attr_unknown_typed_afrom_num_raw(TALLOC_CTX *ctx, fr_dic return NULL; default: + /* + * @todo - remove after migration_union_key is deleted + */ if (fr_dict_attr_is_key_field(parent)) break; if (!fr_type_is_structural_except_vsa(parent->type)) { diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index 0bca91fe6c6..5500f6236aa 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -1479,6 +1479,8 @@ bool dict_attr_can_have_children(fr_dict_attr_t const *da) /* * Children are allowed here, but ONLY if this * attribute is a key field. + * + * @todo - remove after migration_union_key is deleted */ if (da->parent && (da->parent->type == FR_TYPE_STRUCT) && fr_dict_attr_is_key_field(da)) return true; break; @@ -1868,6 +1870,8 @@ int dict_attr_enum_add_name(fr_dict_attr_t *da, char const *name, * * Perhaps this can be done as a special case after we convert to UNIONs? Because then * we can allow ATTRIBUTE Global-VPN 255 struct[0]. + * + * @todo - remove after migration_union_key is deleted */ if (fr_dict_attr_is_key_field(da) && !key_child_ref) { fr_strerror_const("Child attribute must be defined for VALUEs associated with a 'key' attribute"); @@ -5019,6 +5023,8 @@ bool fr_dict_attr_can_contain(fr_dict_attr_t const *parent, fr_dict_attr_t const /* * Child is a STRUCT which has a parent key field. The * child pair nesting, though, is in the grandparent. + * + * @todo - remove after migration_union_key is deleted */ if (fr_dict_attr_is_key_field(child->parent)) { fr_assert(child->parent->parent == parent); diff --git a/src/lib/util/dict_validate.c b/src/lib/util/dict_validate.c index 17bc7dad4d0..59a726e1710 100644 --- a/src/lib/util/dict_validate.c +++ b/src/lib/util/dict_validate.c @@ -622,6 +622,9 @@ bool dict_attr_flags_valid(fr_dict_attr_t *da) case FR_TYPE_UINT8: case FR_TYPE_UINT16: case FR_TYPE_UINT32: + /* + * @todo - remove after migration_union_key is deleted + */ if (fr_dict_attr_is_key_field(parent)) break; FALL_THROUGH; diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index af392fb493e..09f8078b85a 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -431,6 +431,8 @@ fr_pair_t *fr_pair_afrom_da_depth_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, * Otherwise if we're creating a child struct (which is magically parented by the key * field), then don't bother creating the key field. It will be automatically filled in * by the encoder. + * + * @todo - remove after migration_union_key is deleted */ if ((find != da) && fr_dict_attr_is_key_field(find)) { continue; @@ -3430,6 +3432,8 @@ static fr_pair_t *pair_alloc_parent(fr_pair_t *in, fr_pair_t *item, fr_dict_attr * * If we're asked to create children of a keyed * structure, just create the children in the parent. + * + * @todo - remove after migration_union_key is deleted */ if (!fr_type_is_structural(da->type)) { fr_assert(fr_dict_attr_is_key_field(da)); diff --git a/src/lib/util/pair_legacy.c b/src/lib/util/pair_legacy.c index f1f0844cb44..3eed1c66694 100644 --- a/src/lib/util/pair_legacy.c +++ b/src/lib/util/pair_legacy.c @@ -556,10 +556,10 @@ redo: case FR_TYPE_UINT16: case FR_TYPE_UINT32: /* - * Key fields have children in their namespace, but the children go into the - * parents context and list. + * Key fields have children in their namespace, but for OLD style, the children + * go into the parents context and list. */ - if (fr_dict_attr_is_key_field(vp->da)) { + if (fr_dict_attr_is_key_field(vp->da) && !vp->da->flags.migration_union_key) { fr_pair_t *parent_vp; parent_vp = fr_pair_parent(vp);