From: Alan T. DeKok Date: Mon, 6 Dec 2021 17:27:16 +0000 (-0500) Subject: add t_rules flag "list_as_attr" X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b738d0bbc56e960e21df44571501aea59a97720a;p=thirdparty%2Ffreeradius-server.git add t_rules flag "list_as_attr" which encodes the list in the tmpl attribute reference structure @todo - if there's no list prefix AND the flag is set, the tokenizer should statically determine the list prefix, and set the correct attribute reference. This would prevent those checks being done at run-time in tmpl_pair_cursor_init() --- diff --git a/src/lib/server/tmpl.h b/src/lib/server/tmpl.h index d917916a55..f572edcc90 100644 --- a/src/lib/server/tmpl.h +++ b/src/lib/server/tmpl.h @@ -317,6 +317,8 @@ struct tmpl_rules_s { bool at_runtime; //!< Produce an ephemeral/runtime tmpl. ///< Instantiated xlats are not added to the global ///< trees, regexes are not JIT'd. + bool list_as_attr; //!< return #TMPL_TYPE_ATTR for lists, and not #TMPL_TYPE_LIST + fr_event_list_t *runtime_el; //!< The eventlist to use for runtime instantiation ///< of xlats. diff --git a/src/lib/server/tmpl_eval.c b/src/lib/server/tmpl_eval.c index be24e382a3..9962e5b44c 100644 --- a/src/lib/server/tmpl_eval.c +++ b/src/lib/server/tmpl_eval.c @@ -1081,7 +1081,7 @@ fr_pair_t *tmpl_pair_cursor_init(int *err, TALLOC_CTX *ctx, tmpl_pair_cursor_ctx fr_dcursor_t *cursor, request_t *request, tmpl_t const *vpt) { fr_pair_t *vp = NULL; - fr_pair_list_t *list_head; + fr_pair_list_t *list_head = NULL; tmpl_request_t *rr = NULL; TALLOC_CTX *list_ctx; @@ -1108,18 +1108,44 @@ fr_pair_t *tmpl_pair_cursor_init(int *err, TALLOC_CTX *ctx, tmpl_pair_cursor_ctx } /* - * Get the right list in the specified context + * If the rules say "return the list as an attribute", + * then check for that. But if the first da isn't a + * list, then default to whatever list ref is given. + * + * @todo - for the future, have the tokenizer (or + * whatever) always add the list head to the list of + * attribute references. */ - list_head = tmpl_list_head(request, tmpl_list(vpt)); + if (vpt->rules.list_as_attr) { + tmpl_attr_t const *ar; + + ar = fr_dlist_head(&vpt->data.attribute.ar); + fr_assert(ar != NULL); + + if ((ar->ar_da == request_attr_request) || + (ar->ar_da == request_attr_reply) || + (ar->ar_da == request_attr_control) || + (ar->ar_da == request_attr_state)) { + list_head = &request->pair_root->vp_group; + list_ctx = request->pair_root; + } + } + if (!list_head) { - if (err) { - *err = -2; - fr_strerror_printf("List \"%s\" not available in this context", - fr_table_str_by_value(pair_list_table, tmpl_list(vpt), "")); + /* + * Get the right list in the specified context + */ + list_head = tmpl_list_head(request, tmpl_list(vpt)); + if (!list_head) { + if (err) { + *err = -2; + fr_strerror_printf("List \"%s\" not available in this context", + fr_table_str_by_value(pair_list_table, tmpl_list(vpt), "")); + } + goto error; } - goto error; + list_ctx = tmpl_list_ctx(request, tmpl_list(vpt)); } - list_ctx = tmpl_list_ctx(request, tmpl_list(vpt)); /* * Initialise the temporary cursor context diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index b7583f5bd5..9b10002fec 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -1830,7 +1830,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_rules_t const *t_rules) { int ret; - size_t list_len; + size_t list_len = 0; tmpl_t *vpt; fr_sbuff_t our_name = FR_SBUFF(name); /* Take a local copy in case we need to back track */ bool ref_prefix = false; @@ -1896,37 +1896,39 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, fr_sbuff_marker(&m_l, &our_name); - /* - * Parse the list reference - * - * This code should be removed when lists - * are integrated into attribute references. - */ - fr_sbuff_out_by_longest_prefix(&list_len, &vpt->data.attribute.list, pair_list_table, - &our_name, t_rules->list_def); + if (!t_rules->list_as_attr) { + /* + * Parse the list reference + * + * This code should be removed when lists + * are integrated into attribute references. + */ + fr_sbuff_out_by_longest_prefix(&list_len, &vpt->data.attribute.list, pair_list_table, + &our_name, t_rules->list_def); - /* - * Check if we need to backtrack - * - * Lists can be followed by a '.', '[', or the end of the attribute reference - * - * If we don't find any of those things it wasn't an actual list match - * but one of the list identifiers matched part of an attribute reference. - * - * i.e. reply with reply-message. - */ - if ((list_len > 0) && !fr_sbuff_is_char(&our_name, '.') && - !fr_sbuff_is_char(&our_name, '[') && !tmpl_substr_terminal_check(&our_name, p_rules)) { - fr_sbuff_set(&our_name, &m_l); - list_len = 0; - vpt->data.attribute.list = t_rules->list_def; - } + /* + * Check if we need to backtrack + * + * Lists can be followed by a '.', '[', or the end of the attribute reference + * + * If we don't find any of those things it wasn't an actual list match + * but one of the list identifiers matched part of an attribute reference. + * + * i.e. reply with reply-message. + */ + if ((list_len > 0) && !fr_sbuff_is_char(&our_name, '.') && + !fr_sbuff_is_char(&our_name, '[') && !tmpl_substr_terminal_check(&our_name, p_rules)) { + fr_sbuff_set(&our_name, &m_l); + list_len = 0; + vpt->data.attribute.list = t_rules->list_def; + } - if ((t_rules->attr_parent || t_rules->disallow_qualifiers) && (list_len > 0)) { - fr_strerror_const("It is not permitted to specify a pair list here"); - if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER; - talloc_free(vpt); - FR_SBUFF_ERROR_RETURN(&our_name); + if ((t_rules->attr_parent || t_rules->disallow_qualifiers) && (list_len > 0)) { + fr_strerror_const("It is not permitted to specify a pair list here"); + if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER; + talloc_free(vpt); + FR_SBUFF_ERROR_RETURN(&our_name); + } } /* diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index 6bd568fe99..ab598c6771 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -1546,6 +1546,7 @@ static unlang_t *compile_edit(unlang_t *parent, unlang_compile_t *unlang_ctx, un */ t_rules = *(unlang_ctx->rules); t_rules.allow_unknown = true; + t_rules.list_as_attr = true; RULES_VERIFY(&t_rules); c = *prev;