]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow for instantiated xlats to be put into other ones
authorAlan T. DeKok <aland@freeradius.org>
Tue, 24 May 2022 14:19:43 +0000 (10:19 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 24 May 2022 20:46:48 +0000 (16:46 -0400)
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

src/lib/unlang/xlat_inst.c
src/lib/unlang/xlat_priv.h

index 363f6d36b8b043d8c29d84a2cc6e612ad04f7751..3fff1b2c55ba82751dcc3dbccc0689b72118a3eb 100644 (file)
@@ -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
index 06020c690db464c7d1de690eb7c4626042eb2c6f..717c61a30441879d0b3094818711aae68356fe6f 100644 (file)
@@ -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;
 };