From: Arran Cudbard-Bell Date: Tue, 7 Nov 2023 23:34:46 +0000 (-0600) Subject: Rename xlat instance registration functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66c526658ec0e28fbd072188468363de5c56ff53;p=thirdparty%2Ffreeradius-server.git Rename xlat instance registration functions Bootstrap is a distinct phase for modules, and calling the registration phase "bootstrap" is confusing as there's no bootstrap function available to xlats... --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 1c6c33aebe6..df05f6d954f 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -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); } diff --git a/src/lib/server/trigger.c b/src/lib/server/trigger.c index 2c121d0b185..ea1906ecf13 100644 --- a/src/lib/server/trigger.c +++ b/src/lib/server/trigger.c @@ -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; diff --git a/src/lib/unlang/xlat.h b/src/lib/unlang/xlat.h index b7775963f6a..7a06b094e87 100644 --- a/src/lib/unlang/xlat.h +++ b/src/lib/unlang/xlat.h @@ -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); diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index bc753ed5d1a..e36194f3ad2 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -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; } diff --git a/src/lib/unlang/xlat_inst.c b/src/lib/unlang/xlat_inst.c index 7270ce1671c..8055f55f5a6 100644 --- a/src/lib/unlang/xlat_inst.c +++ b/src/lib/unlang/xlat_inst.c @@ -31,8 +31,6 @@ RCSID("$Id$") #include #include -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; -} diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 4a0ea8061a7..53d64fcbc98 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -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 diff --git a/src/lib/unlang/xlat_purify.c b/src/lib/unlang/xlat_purify.c index 0f7e20b47a4..1c53dc9573e 100644 --- a/src/lib/unlang/xlat_purify.c +++ b/src/lib/unlang/xlat_purify.c @@ -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); diff --git a/src/lib/unlang/xlat_redundant.c b/src/lib/unlang/xlat_redundant.c index 5f09055b161..5646b3b2a2e 100644 --- a/src/lib/unlang/xlat_redundant.c +++ b/src/lib/unlang/xlat_redundant.c @@ -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; diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 49e2ccebb0a..6e0eaa386d6 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -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