]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Rename xlat instance registration functions
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 7 Nov 2023 23:34:46 +0000 (17:34 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 8 Nov 2023 01:09:00 +0000 (19:09 -0600)
Bootstrap is a distinct phase for modules, and calling the registration phase "bootstrap" is confusing as there's no bootstrap function available to xlats...

src/lib/server/tmpl_tokenize.c
src/lib/server/trigger.c
src/lib/unlang/xlat.h
src/lib/unlang/xlat_expr.c
src/lib/unlang/xlat_inst.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_purify.c
src/lib/unlang/xlat_redundant.c
src/lib/unlang/xlat_tokenize.c

index 1c6c33aebe6d2d136dc09b269d4037fd9fa0d9e6..df05f6d954f8df5fa311b50b5b69eff532167a1e 100644 (file)
@@ -3278,7 +3278,7 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      so that their instance data will be created.
                 */
                if (head) {
-                       if (xlat_bootstrap(head, t_rules) < 0) {
+                       if (xlat_finalize(head, t_rules) < 0) {
                                fr_strerror_const("Failed to bootstrap xlat");
                                FR_SBUFF_ERROR_RETURN(&our_in);
                        }
index 2c121d0b185ecd0ef53221b0cad782393136e811..ea1906ecf13941dd7e50daca90516d38fa4df776 100644 (file)
@@ -460,12 +460,12 @@ int trigger_exec(unlang_interpret_t *intp,
                }
        }
 
-       if (xlat_bootstrap(trigger->xlat, &(tmpl_rules_t ) {
+       if (xlat_finalize(trigger->xlat, &(tmpl_rules_t ) {
                                        .xlat = {
                                                .runtime_el = intp ? unlang_interpret_event_list(request) : main_loop_event_list(),
                                        },
                                        .at_runtime = true
-                       }) < 0) {
+                         }) < 0) {
                fr_strerror_const("Failed performing ephemeral instantiation for xlat");
                talloc_free(request);
                return -1;
index b7775963f6a7157432056330f50361bba00a613e..7a06b094e87a3d5f7382d300a5b293045dc3ae28 100644 (file)
@@ -458,9 +458,11 @@ int                xlat_instantiate(void);
 
 void           xlat_thread_detach(void);
 
-int            xlat_bootstrap_func(xlat_exp_t *node);
+int            xlat_instance_unregister_func(xlat_exp_t *node);
 
-int            xlat_bootstrap(xlat_exp_head_t *root, tmpl_rules_t const *t_rules);
+int            xlat_instance_register_func(xlat_exp_t *node);
+
+int            xlat_finalize(xlat_exp_head_t *head, tmpl_rules_t const *t_rules); /* xlat_instance_register() or xlat_instantiate_ephemeral() */
 
 void           xlat_instances_free(void);
 
index bc753ed5d1a8894905a9f8c599c5d89f04aef1a4..e36194f3ad223ed5da5f6124b2911838b9b48995 100644 (file)
@@ -940,7 +940,7 @@ check:
 
        if (!*result) return true;
 
-       xlat_inst_remove(parent);
+       xlat_instance_unregister_func(parent);
 
        xlat_exp_set_type(parent, XLAT_BOX);
        fr_value_box_copy(parent, &parent->data, box);
@@ -1081,7 +1081,7 @@ static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t
        fr_assert(group != NULL);
        talloc_steal(node, group);
 
-       xlat_inst_remove(node);
+       xlat_instance_unregister_func(node);
        xlat_exp_set_type(node, XLAT_GROUP);
 
        /* re-print, with purified nodes removed */
@@ -2999,7 +2999,7 @@ static fr_slen_t xlat_tokenize_expression_internal(TALLOC_CTX *ctx, xlat_exp_hea
         *      Add nodes that need to be bootstrapped to
         *      the registry.
         */
-       if (xlat_bootstrap(head, t_rules) < 0) {
+       if (xlat_finalize(head, t_rules) < 0) {
                talloc_free(head);
                return -1;
        }
index 7270ce1671cf62313a7b53ff245b3053322cd178..8055f55f5a610e1b8f6ffc9ecb9a6a2fcc9427aa 100644 (file)
@@ -31,8 +31,6 @@ RCSID("$Id$")
 #include <freeradius-devel/util/debug.h>
 #include <freeradius-devel/util/heap.h>
 
-static int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el);
-
 /** Holds instance data created by xlat_instantiate
  */
 static fr_heap_t *xlat_inst_tree;
@@ -350,7 +348,6 @@ static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx)
        return 0;
 }
 
-
 /** Create instance data for "ephemeral" xlats
  *
  * @note This function should only be called from routines which get
@@ -359,7 +356,7 @@ static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx)
  * @param[in] head of xlat tree to create instance data for.
  * @param[in] el event list used to run any instantiate data
  */
-static int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el)
+static inline CC_HINT(always_inline) int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el)
 {
        int ret;
 
@@ -491,7 +488,7 @@ static int xlat_instantiate_init(void)
        return 0;
 }
 
-/** Call instantiation functions for "permanent" xlats
+/** Call instantiation functions for all registered, "permanent" xlats
  *
  * Should be called after all the permanent xlats have been tokenised/bootstrapped.
  */
@@ -526,18 +523,58 @@ int xlat_instantiate(void)
        return 0;
 }
 
+/** Remove a node from the list of xlat instance data
+ *
+ * @note This is primarily used during "purification", to remove xlats which are no longer used.
+ *
+ * @param[in] node     to remove instance data for.
+ */
+int xlat_instance_unregister_func(xlat_exp_t *node)
+{
+       int ret;
+
+       fr_assert(node->type == XLAT_FUNC);
+       fr_assert(!node->call.func->detach);
+       fr_assert(!node->call.func->thread_detach);
+
+       if (node->call.inst) {
+               ret = fr_heap_extract(&xlat_inst_tree, node->call.inst);
+               if (ret < 0) return ret;
+
+               talloc_set_destructor(node->call.inst, NULL);
+               TALLOC_FREE(node->call.inst);
+       }
+
+       if (node->call.thread_inst) {
+               if (!node->call.ephemeral) {
+                       ret = fr_heap_extract(&xlat_thread_inst_tree, node->call.thread_inst);
+                       if (ret < 0) return ret;
+               }
+
+               talloc_set_destructor(node->call.thread_inst, NULL);
+               TALLOC_FREE(node->call.inst);
+       }
+
+       return 0;
+}
+
 /** Callback for creating "permanent" instance data for a #xlat_exp_t
  *
  * This function records the #xlat_exp_t requiring instantiation but does
  * not call the instantiation function.  This is to allow for a clear separation
  * between the module instantiation phase and the xlat instantiation phase.
  *
+ * @note This is very similar to #xlat_instance_register but does not walk the
+ *      children of the node.  This is primarily used to register individual
+ *      nodes for instantiation and when an xlat function is resolved in a
+ *      subsequent resolution pass and needs to be registered for instantiation.
+ *
  * @param[in] node     to create "permanent" instance data for.
  * @return
  *     - 0 if instantiation functions were successful.
  *     - -1 if either instantiation function failed.
  */
-int xlat_bootstrap_func(xlat_exp_t *node)
+int xlat_instance_register_func(xlat_exp_t *node)
 {
        static uint64_t call_id;
        xlat_call_t *call = &node->call;
@@ -573,7 +610,7 @@ int xlat_bootstrap_func(xlat_exp_t *node)
        return 0;
 }
 
-static int _xlat_bootstrap_walker(xlat_exp_t *node, UNUSED void *uctx)
+static int _xlat_inst_walker(xlat_exp_t *node, UNUSED void *uctx)
 {
        /*
         *      tmpl_tokenize() instantiates ephemeral xlats.  So for
@@ -586,7 +623,7 @@ static int _xlat_bootstrap_walker(xlat_exp_t *node, UNUSED void *uctx)
        if (node->type != XLAT_FUNC) return 0; /* skip it */
 
 
-       return xlat_bootstrap_func(node);
+       return xlat_instance_register_func(node);
 }
 
 /** Create instance data for "permanent" xlats
@@ -595,18 +632,13 @@ static int _xlat_bootstrap_walker(xlat_exp_t *node, UNUSED void *uctx)
  *      IF THIS IS CALLED FOR XLATS TOKENIZED AT RUNTIME YOU WILL LEAK LARGE AMOUNTS OF MEMORY.
  *      If the caller has a #tmpl_rules_t, it should call xlat_finalize() instead.
  *
- * @param[in] head of xlat tree to create instance data for.
- * @param[in] t_rules parsing rules with #fr_event_list_t
+ * @param[in] head     of xlat tree to create instance data for.  Will walk the entire tree
+ *                     registering all the xlat function calls for later instantiation.
  */
-int xlat_bootstrap(xlat_exp_head_t *head, tmpl_rules_t const *t_rules)
+static inline CC_HINT(always_inline) int xlat_instance_register(xlat_exp_head_t *head)
 {
        int ret;
 
-       /*
-        *      Runtime xlats get ephemeral instantiation
-        */
-       if (t_rules && t_rules->xlat.runtime_el) return xlat_instantiate_ephemeral(head, t_rules->xlat.runtime_el);
-
        /*
         *      If thread instantiate has been called, it's too late to
         *      bootstrap new xlats.
@@ -625,13 +657,27 @@ int xlat_bootstrap(xlat_exp_head_t *head, tmpl_rules_t const *t_rules)
         *      Walk an expression registering all the function calls
         *      so that we can instantiate them later.
         */
-       ret = xlat_eval_walk(head, _xlat_bootstrap_walker, XLAT_INVALID, NULL);
+       ret = xlat_eval_walk(head, _xlat_inst_walker, XLAT_INVALID, NULL);
        if (ret < 0) return ret;
 
        head->instantiated = true;
        return 0;
 }
 
+/** Bootstrap static xlats, or instantiate ephemeral ones.
+ *
+ * @param[in] head of xlat tree to create instance data for.
+ * @param[in] t_rules parsing rules with #fr_event_list_t
+ */
+int xlat_finalize(xlat_exp_head_t *head, tmpl_rules_t const *t_rules)
+{
+       if (!t_rules || !t_rules->at_runtime) {
+               fr_assert(!t_rules || !t_rules->xlat.runtime_el);
+               return xlat_instance_register(head);
+       }
+       return xlat_instantiate_ephemeral(head, t_rules->xlat.runtime_el);
+}
+
 /** Walk over all registered instance data and free them explicitly
  *
  * This must be called before any modules or xlats are deregistered/unloaded and before
@@ -649,35 +695,3 @@ void xlat_instances_free(void)
         */
        while (xlat_inst_tree && (xi = fr_heap_pop(&xlat_inst_tree))) talloc_free(xi);
 }
-
-/** Remove a node from the list of xlat instance data
- *
- */
-int xlat_inst_remove(xlat_exp_t *node)
-{
-       int ret;
-
-       fr_assert(node->type == XLAT_FUNC);
-       fr_assert(!node->call.func->detach);
-       fr_assert(!node->call.func->thread_detach);
-
-       if (node->call.inst) {
-               ret = fr_heap_extract(&xlat_inst_tree, node->call.inst);
-               if (ret < 0) return ret;
-
-               talloc_set_destructor(node->call.inst, NULL);
-               TALLOC_FREE(node->call.inst);
-       }
-
-       if (node->call.thread_inst) {
-               if (!node->call.ephemeral) {
-                       ret = fr_heap_extract(&xlat_thread_inst_tree, node->call.thread_inst);
-                       if (ret < 0) return ret;
-               }
-
-               talloc_set_destructor(node->call.thread_inst, NULL);
-               TALLOC_FREE(node->call.inst);
-       }
-
-       return 0;
-}
index 4a0ea8061a73b077bb914a57654789ef3661ba8c..53d64fcbc98ed9ee9736387b8a7c64776428ed8d 100644 (file)
@@ -184,7 +184,11 @@ struct xlat_exp_head_s {
        fr_dlist_head_t         dlist;
        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_dict_t const         *dict;          //!< Records the namespace this xlat was created in.
+                                               ///< Used by the purify code to run fake requests in
+                                               ///< the correct namespace, and passed to instantiation
+                                               ///< functions in case the xlat needs to perform runtime
+                                               ///< resolution of attributes (as with %eval()).
 
 #ifndef NDEBUG
        char const * _CONST     file;           //!< File where the xlat was allocated.
@@ -342,11 +346,6 @@ int                xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
 ssize_t                xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_t const *node,
                                fr_sbuff_escape_rules_t const *e_rules);
 
-/*
- *     xlat_inst.c
- */
-int            xlat_inst_remove(xlat_exp_t *node);
-
 #ifdef __cplusplus
 }
 #endif
index 0f7e20b47a43201ff4ade2de694891c9a3bd70ed..1c53dc9573e28a64aea38e929740653785c8dd17 100644 (file)
@@ -170,7 +170,7 @@ int xlat_purify_list(xlat_exp_head_t *head, request_t *request)
                        /*
                         *      The function call becomes a GROUP of boxes
                         */
-                       xlat_inst_remove(node);
+                       xlat_instance_unregister_func(node);
                        xlat_exp_set_type(node, XLAT_GROUP);    /* Frees the argument list */
 
                        xlat_value_list_to_xlat(node->group, &list);
index 5f09055b1611b5eaf7c8afff86bb7c24368aacbe..5646b3b2a2e99344e0a2b7f6f86f132b3e9c6547 100644 (file)
@@ -321,7 +321,7 @@ static int xlat_redundant_instantiate(xlat_inst_ctx_t const *xctx)
                 *      we return.
                 */
                head->flags = node->flags;
-               if (xlat_bootstrap(head, NULL) < 0) {
+               if (xlat_finalize(head, NULL) < 0) {
                        PERROR("Failed boostrapping function \"%s\"",
                               xrf->func->name);
                        goto error;
index 49e2ccebb0a81566bcaf3ad201d72f07fe1e1ac8..6e0eaa386d629cae31228e8ef8b3ea9d4e63f418 100644 (file)
@@ -1923,7 +1923,7 @@ fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
         *      Add nodes that need to be bootstrapped to
         *      the registry.
         */
-       if (xlat_bootstrap(head, t_rules) < 0) {
+       if (xlat_finalize(head, t_rules) < 0) {
                talloc_free(head);
                return 0;
        }
@@ -2107,7 +2107,7 @@ int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
                         *      Add the freshly resolved function
                         *      to the bootstrap tree.
                         */
-                       if (xlat_bootstrap_func(node) < 0) return -1;
+                       if (xlat_instance_register_func(node) < 0) return -1;
 
                        /*
                         *      The function is now resolved, so we go through the normal process of resolving