From: Alan T. DeKok Date: Thu, 25 Dec 2025 15:35:38 +0000 (-0500) Subject: clean up and clarify namespace issues X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=603ffc60cb14690d01e4ddaf473a4eb0a269efc5;p=thirdparty%2Ffreeradius-server.git clean up and clarify namespace issues both for structural attribute to child , and for groups of protocol/internal -> internal/protocol in preparation for supporting "flat" attributes in some groups --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 81cccae9079..da44580a6fc 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -541,18 +541,44 @@ static fr_slen_t tmpl_request_ref_list_from_substr(TALLOC_CTX *ctx, tmpl_attr_er at_rules = &t_rules->attr; /* - * The caller wants to know the default namespace for - * resolving the attribute. - * - * @todo - why not use dict_def if it's set? Tho TBH we - * should probably just remove dict_def, and always use "namespace". + * The caller wants to know the default namespace for resolving the attribute. */ if (namespace) { if (at_rules->namespace) { - /* - * If the namespace is FR_TYPE_GROUP use the correct namespace - */ - *namespace = at_rules->namespace->type == FR_TYPE_GROUP ? fr_dict_attr_ref(at_rules->namespace) : at_rules->namespace; + if (request_attr_is_list(at_rules->namespace)) { + /* + * If the namespace is a list attribute, then reset it to NULL, so that the rest of the + * code will use the default dictionary. + */ + if (!at_rules->dict_def) { + fr_strerror_const("No dictionary was set - cannot parse attributes"); + FR_SBUFF_ERROR_RETURN(&our_in); + } + *namespace = NULL; + + } else if (at_rules->namespace->type != FR_TYPE_GROUP) { + /* + * If the namespace is a structural type, then use the namespace is this + * attribute. We can then parse children of the attribute. + */ + *namespace = at_rules->namespace; + + } else if (at_rules->namespace->flags.internal && at_rules->dict_def) { + /* + * If the group is internal, AND we have a default dictionary, reset the + * namespace to NULL, so that the rest of the code will use the default + * dictionary. + */ + *namespace = NULL; + + } else { + /* + * The namespace is a non-internal group. Update the namespace to be + * whereever the group is pointing to. + */ + *namespace = fr_dict_attr_ref(at_rules->namespace); + } + } else { *namespace = NULL; } @@ -568,7 +594,7 @@ static fr_slen_t tmpl_request_ref_list_from_substr(TALLOC_CTX *ctx, tmpl_attr_er /* * We're in a name space, OR lists are forbidden, don't allow list qualifiers. */ - if (at_rules->namespace || (at_rules->list_presence == TMPL_ATTR_LIST_FORBID)) { + if (*namespace || (at_rules->list_presence == TMPL_ATTR_LIST_FORBID)) { if (fr_sbuff_is_str_literal(&our_in, "outer.") || fr_sbuff_is_str_literal(&our_in, "parent.")) { fr_strerror_const("request list qualifiers are not allowed here"); diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index b606be70278..1d25388fc45 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -682,16 +682,10 @@ static unlang_t *compile_edit_section(unlang_t *parent, unlang_compile_ctx_t *un map_t *child; /* - * Don't update namespace for reply += { ... } - * - * Do update namespace for reply.foo += { ... } - * - * Don't update if the LHS is an internal group. + * Reset the namespace to be this attribute. The tmpl tokenizer will take care of + * figuring out if this is a group, TLV, dictionary switch, etc. */ - if ((tmpl_attr_num_elements(map->lhs) > 1) && (t_rules.attr.list_def != parent_da) && - !((parent_da->type == FR_TYPE_GROUP) && parent_da->flags.internal)) { - t_rules.attr.namespace = parent_da; - } + t_rules.attr.namespace = parent_da; if (map_afrom_cs_edit(map, &map->child, cs, &t_rules, &t_rules, unlang_fixup_edit, map, 256) < 0) { goto fail;