From: Alan T. DeKok Date: Tue, 24 May 2022 14:19:43 +0000 (-0400) Subject: allow for instantiated xlats to be put into other ones X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0acb9f4473a62123c66e1fec90fe1ed97c33eb11;p=thirdparty%2Ffreeradius-server.git allow for instantiated xlats to be put into other ones tmpl_tokenize() will call xlat_instantiate_ephemeral() on things it sees. However, if we then hoist that xlat out of the tmpl and into the main xlat tree, we can't re-instantiate the node. Rather than adding flags to change the rest of the code, we just catch that here. This should likely be cleaned up later --- diff --git a/src/lib/unlang/xlat_inst.c b/src/lib/unlang/xlat_inst.c index 363f6d36b8b..3fff1b2c55b 100644 --- a/src/lib/unlang/xlat_inst.c +++ b/src/lib/unlang/xlat_inst.c @@ -265,6 +265,16 @@ static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx) xlat_inst_t *xi; xlat_thread_inst_t *xt; + /* + * tmpl_tokenize() instantiates ephemeral xlats. So for + * now, just ignore ones which are already instantiated. + */ + if (node->type == XLAT_GROUP) { + return node->group->instantiated; /* prune on 1, continue on 0 */ + } + + if (node->type != XLAT_FUNC) return 0; /* skip it */ + fr_assert(!call->inst && !call->thread_inst); /* @@ -315,7 +325,16 @@ static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx) */ int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el) { - return xlat_eval_walk(head, _xlat_instantiate_ephemeral_walker, XLAT_FUNC, el); + int ret; + + if (head->instantiated) return 0; + + ret = xlat_eval_walk(head, _xlat_instantiate_ephemeral_walker, XLAT_INVALID, el); + if (ret < 0) return ret; + + head->instantiated = true; + + return 0; } /** Retrieve xlat/thread specific instance data @@ -511,6 +530,17 @@ int xlat_bootstrap_func(xlat_exp_t *node) static int _xlat_bootstrap_walker(xlat_exp_t *node, UNUSED void *uctx) { + /* + * tmpl_tokenize() instantiates ephemeral xlats. So for + * now, just ignore ones which are already instantiated. + */ + if (node->type == XLAT_GROUP) { + return node->group->instantiated; /* prune on 1, continue on 0 */ + } + + if (node->type != XLAT_FUNC) return 0; /* skip it */ + + return xlat_bootstrap_func(node); } @@ -524,6 +554,8 @@ static int _xlat_bootstrap_walker(xlat_exp_t *node, UNUSED void *uctx) */ int xlat_bootstrap(xlat_exp_head_t *head) { + int ret; + /* * If thread instantiate has been called, it's too late to * bootstrap new xlats. @@ -536,11 +568,17 @@ int xlat_bootstrap(xlat_exp_head_t *head) */ if (unlikely(!xlat_inst_tree)) xlat_instantiate_init(); + if (head->instantiated) return 0; + /* * Walk an expression registering all the function calls * so that we can instantiate them later. */ - return xlat_eval_walk(head, _xlat_bootstrap_walker, XLAT_FUNC, NULL); + ret = xlat_eval_walk(head, _xlat_bootstrap_walker, XLAT_INVALID, NULL); + if (ret < 0) return ret; + + head->instantiated = true; + return 0; } /** Walk over all registered instance data and free them explicitly diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 06020c690db..717c61a3044 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -153,6 +153,7 @@ struct xlat_exp { struct xlat_exp_head { char const *fmt; //!< The original format string (a talloced buffer). xlat_flags_t flags; //!< Flags that control resolution and evaluation. + bool instantiated; //!< temporary flag until we fix more things fr_dict_t const *dict; //!< dictionary for this xlat fr_dlist_head_t dlist; };