26 RCSID(
"$Id: 9c531711a718636d58251b8fa0c7804d57537b44 $")
28 #include <freeradius-devel/io/schedule.h>
29 #include <freeradius-devel/server/base.h>
30 #include <freeradius-devel/unlang/xlat_priv.h>
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/util/heap.h>
52 return CMP(a->
node->call.id, b->node->call.id);
65 return CMP(a->
node->call.id, b->node->call.id);
82 DEBUG4(
"Cleaning up xlat thread instance (%p/%p)", xt, xt->
data);
106 size_t extra_headers = 0;
107 size_t extra_mem = 0;
124 extra_mem +=
sizeof(*call->
func->
mctx);
127 if (extra_headers || extra_mem) {
146 talloc_set_name(xt->data,
"xlat_%s_thread_t", call->
func->
name);
166 DEBUG4(
"Alloced xlat thread instance (%p/%p)", xt, xt->data);
188 call = &xi->
node->call;
200 DEBUG4(
"Cleaning up xlat instance (%p/%p)", xi, xi->
data);
218 (void)talloc_get_type_abort(node,
xlat_exp_t);
244 talloc_set_name(xi->
data,
"xlat_%s_t", call->
func->
name);
253 "Method environment for module %s, xlat %s declared, "
272 .dict_def = call->dict,
273 .list_def = request_attr_request
307 return node->group->instantiated;
337 TALLOC_FREE(call->
inst);
381 if (
head->flags.needs_resolving) {
385 if (
head->instantiated)
return 0;
388 if (ret < 0)
return ret;
390 head->instantiated =
true;
457 DEBUG3(
"Instantiating xlat \"%s\" node %p, instance %p, new thread instance %p",
526 fr_assert(!xi->node->flags.needs_resolving);
551 fr_assert(!node->call.func->thread_detach);
553 if (node->call.inst) {
555 if (ret < 0)
return ret;
557 talloc_set_destructor(node->call.inst, NULL);
558 TALLOC_FREE(node->call.inst);
561 if (node->call.thread_inst) {
562 if (!node->call.ephemeral) {
564 if (ret < 0)
return ret;
567 talloc_set_destructor(node->call.thread_inst, NULL);
568 TALLOC_FREE(node->call.inst);
592 static uint64_t call_id;
603 DEBUG3(
"Instantiating xlat \"%s\" node %p, new instance %p", call->
func->
name, node, call->
inst);
615 node->call.id = call_id++;
619 TALLOC_FREE(call->
inst);
633 return node->group->instantiated;
660 "xlat.runtime_el likely not set in tmpl rules when it should've been. "
661 "Use unlang_interpret_event_list() to get the current event list from the request");
669 if (
head->instantiated)
return 0;
676 if (ret < 0)
return ret;
678 head->instantiated =
true;
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
call_env_t * call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, tmpl_rules_t const *t_rules, CONF_SECTION *cs, char const *section_name1, char const *section_name2, void const *data)
Given a call_env_method, parse all call_env_pair_t in the context of a specific call to an xlat or mo...
size_t inst_size
Size of per call env.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
char const *_CONST name
Instance name.
void *_CONST data
Module instance's parsed configuration.
CONF_SECTION *_CONST conf
Module's instance configuration.
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
static void * fr_heap_peek_at(fr_heap_t *h, fr_heap_index_t idx)
Peek at a specific index in the heap.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
#define fr_heap_foreach(_heap, _type, _data)
Iterate over the contents of a heap.
Stores all information relating to an event list.
void * thread
Thread specific instance data.
static module_ctx_t * module_ctx_from_inst(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx)
Allocate a module calling ctx on the heap based on an instance ctx.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
module_thread_instance_t * module_rlm_thread_by_data(void const *data)
void * data
Thread specific instance data.
Optional arguments passed to vp_tmpl functions.
if(!subtype_vp) goto fail
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define talloc_get_type_abort_const
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
static fr_event_list_t * el
fr_heap_index_t idx
Entry in heap of xlat instances.
xlat_exp_t * node
Node this data relates to.
void * data
Thread specific instance data.
xlat_exp_t const * node
Node this data relates to.
fr_heap_index_t idx
Entry in heap of xlat thread instances.
fr_event_list_t * el
Event list associated with this thread.
void * data
xlat node specific instance data.
#define XLAT_VERIFY(_node)
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
call_env_t const * call_env
Per call environment.
module_ctx_t const * mctx
A synthesised module calling ctx containing module global and thread instance data.
Instance data for an xlat expansion node.
Thread specific instance data for xlat expansion node.
#define XLAT_THREAD_INST_CTX(_inst, _thread, _ex, _mctx, _el, _uctx)
Wrapper to create a xlat_thread_inst_ctx_t as a compound literal.
#define XLAT_INST_CTX(_inst, _ex, _mctx, _uctx)
Wrapper to create a xlat_inst_ctx_t as a compound literal.
int xlat_eval_walk(xlat_exp_head_t *head, xlat_walker_t walker, xlat_type_t type, void *uctx)
Walk over all xlat nodes (depth first) in a xlat expansion, calling a callback.
static int _xlat_inst_detach(xlat_inst_t *xi)
Destructor for xlat_inst_t.
xlat_thread_inst_t * xlat_thread_instance_find(xlat_exp_t const *node)
Retrieve xlat/thread specific instance data.
int xlat_instance_register_func(xlat_exp_t *node)
Callback for creating "permanent" instance data for a xlat_exp_t.
void xlat_thread_detach(void)
Destroy any thread specific xlat instances.
static int xlat_instance_register(xlat_exp_head_t *head)
Create instance data for "permanent" xlats.
static int _xlat_instantiate_ephemeral_walker(xlat_exp_t *node, void *uctx)
Callback for creating "ephemeral" instance data for a xlat_exp_t.
static int xlat_instantiate_ephemeral(xlat_exp_head_t *head, fr_event_list_t *el)
Create instance data for "ephemeral" xlats.
int xlat_instantiate(void)
Call instantiation functions for all registered, "permanent" xlats.
static int8_t _xlat_inst_cmp(void const *one, void const *two)
Compare two xlat instances based on node pointer.
static xlat_inst_t * xlat_inst_alloc(xlat_exp_t *node)
Allocate instance data for an xlat expansion.
static int8_t _xlat_thread_inst_cmp(void const *one, void const *two)
Compare two thread instances based on node pointer.
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
static int _xlat_inst_walker(xlat_exp_t *node, UNUSED void *uctx)
static int _xlat_thread_inst_detach(xlat_thread_inst_t *xt)
Destructor for xlat_thread_inst_t.
void xlat_instances_free(void)
Walk over all registered instance data and free them explicitly.
static fr_heap_t * xlat_inst_tree
Holds instance data created by xlat_instantiate.
static int xlat_instantiate_init(void)
Initialise the xlat instance data code.
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
static _Thread_local fr_heap_t * xlat_thread_inst_tree
Holds thread specific instance data created by xlat_instantiate.
int xlat_instance_unregister_func(xlat_exp_t *node)
Remove a node from the list of xlat instance data.
static xlat_thread_inst_t * xlat_thread_inst_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, xlat_inst_t *xi)
Create thread instances where needed.
char const * name
Name of xlat function.
char const * thread_inst_type
C type of thread instance structure.
bool ephemeral
Instance data is ephemeral (not inserted) into the instance tree.
xlat_instantiate_t instantiate
Instantiation function.
size_t thread_inst_size
Size of the thread instance data to pre-allocate.
xlat_detach_t detach
Destructor for when xlat instances are freed.
void * thread_uctx
uctx to pass to instantiation functions.
call_env_method_t const * call_env_method
Optional tmpl expansions performed before calling the xlat.
size_t inst_size
Size of instance data to pre-allocate.
@ XLAT_GROUP
encapsulated string of xlats
@ XLAT_INVALID
Bad expansion.
module_inst_ctx_t const * mctx
Original module instantiation ctx if this xlat was registered by a module.
xlat_thread_instantiate_t thread_instantiate
Thread instantiation function.
xlat_thread_inst_t * thread_inst
Thread specific instance.
xlat_inst_t * inst
Instance data for the xlat_t.
char const * inst_type
C type of instance structure.
xlat_t const * func
The xlat expansion to expand format with.
uint64_t id
Identifier unique to each permanent xlat node.
xlat_type_t _CONST type
type of this expansion.
xlat_thread_detach_t thread_detach
Destructor for when xlat thread instance data is freed.
void * uctx
uctx to pass to instantiation functions.