The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
xlat_func.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 4ce620fd72d54fafe0e94993d07a86eb0e9683ab $
19 *
20 * @file xlat_func.c
21 * @brief Registration API for xlat functions
22 *
23 * @copyright 2023 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 */
25
26RCSID("$Id: 4ce620fd72d54fafe0e94993d07a86eb0e9683ab $")
27
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/unlang/xlat_priv.h>
30#include <freeradius-devel/unlang/xlat.h>
31#include <freeradius-devel/unlang/xlat_func.h>
32
33static fr_rb_tree_t *xlat_root = NULL;
34
35/** Compare two xlat_t by the registered name
36 *
37 * @param[in] one First xlat_t to compare.
38 * @param[in] two Second xlat_t to compare.
39 * @return
40 * - -1 if one < two
41 * - 0 if one == two
42 * - 1 if one > two
43 */
44static int8_t xlat_name_cmp(void const *one, void const *two)
45{
46 xlat_t const *a = one, *b = two;
47 size_t a_len, b_len;
48 int ret;
49
50 a_len = strlen(a->name);
51 b_len = strlen(b->name);
52
53 ret = CMP(a_len, b_len);
54 if (ret != 0) return ret;
55
56 ret = memcmp(a->name, b->name, a_len);
57 return CMP(ret, 0);
58}
59
60/** Compare two xlat_t by the underlying function
61 *
62 * @param[in] one First xlat_t to compare.
63 * @param[in] two Second xlat_t to compare.
64 * @return
65 * - -1 if one < two
66 * - 0 if one == two
67 * - 1 if one > two
68 */
69int8_t xlat_func_cmp(void const *one, void const *two)
70{
71 xlat_t const *a = one, *b = two;
72
73 return CMP((uintptr_t)a->func, (uintptr_t)b->func);
74}
75
76/*
77 * find the appropriate registered xlat function.
78 */
80{
81 char buffer[256];
82
83 if (!xlat_root) return NULL;
84
85 if (inlen < 0) return fr_rb_find(xlat_root, &(xlat_t){ .name = in });
86
87 if ((size_t) inlen >= sizeof(buffer)) return NULL;
88
89 memcpy(buffer, in, inlen);
90 buffer[inlen] = '\0';
91
92 return fr_rb_find(xlat_root, &(xlat_t){ .name = buffer });
93}
94
95/** Remove an xlat function from the function tree
96 *
97 * @param[in] xlat to free.
98 * @return 0
99 */
101{
102 if (!xlat_root) return 0;
103
104 fr_rb_delete(xlat_root, xlat);
105 if (fr_rb_num_elements(xlat_root) == 0) TALLOC_FREE(xlat_root);
106
107 return 0;
108}
109
110
111/** Callback for the rbtree to clear out any xlats still registered
112 *
113 */
114static void _xlat_func_tree_free(void *xlat)
115{
116 talloc_free(xlat);
117}
118
119#if 0
120/** Compare two argument entries to see if they're equivalent
121 *
122 * @note Does not check escape function or uctx pointers.
123 *
124 * @param[in] a First argument structure.
125 * @param[in] b Second argument structure.
126 * @return
127 * - 1 if a > b
128 * - 0 if a == b
129 * - -1 if a < b
130 */
131static int xlat_arg_cmp_no_escape(xlat_arg_parser_t const *a, xlat_arg_parser_t const *b)
132{
133 int8_t ret;
134
135 ret = CMP(a->required, b->required);
136 if (ret != 0) return ret;
137
138 ret = CMP(a->concat, b->concat);
139 if (ret != 0) return ret;
140
141 ret = CMP(a->single, b->single);
142 if (ret != 0) return ret;
143
144 ret = CMP(a->variadic, b->variadic);
145 if (ret != 0) return ret;
146
147 ret = CMP(a->always_escape, b->always_escape);
148 if (ret != 0) return ret;
149
150 return CMP(a->type, b->type);
151}
152
153/** Compare two argument lists to see if they're equivalent
154 *
155 * @note Does not check escape function or uctx pointers.
156 *
157 * @param[in] a First argument structure.
158 * @param[in] b Second argument structure.
159 * @return
160 * - 1 if a > b
161 * - 0 if a == b
162 * - -1 if a < b
163 */
164static int xlat_arg_cmp_list_no_escape(xlat_arg_parser_t const a[], xlat_arg_parser_t const b[])
165{
166 xlat_arg_parser_t const *arg_a_p;
167 xlat_arg_parser_t const *arg_b_p;
168
169 for (arg_a_p = a, arg_b_p = b;
170 (arg_a_p->type != FR_TYPE_NULL) && (arg_b_p->type != FR_TYPE_NULL);
171 arg_a_p++, arg_b_p++) {
172 int8_t ret;
173
174 ret = xlat_arg_cmp_no_escape(arg_a_p, arg_b_p);
175 if (ret != 0) return ret;
176 }
177
178 return CMP(arg_a_p, arg_b_p); /* Check we ended at the same point */
179}
180#endif
181
183{
184 char inst_name[256];
185
187
188 if (!*name) {
189 ERROR("%s: Invalid xlat name", __FUNCTION__);
190 return NULL;
191 }
192
193 /*
194 * Name xlats other than those which are just the module instance
195 * as <instance name>.<function name>
196 */
197 if (mctx && name != mctx->mi->name) {
198 snprintf(inst_name, sizeof(inst_name), "%s.%s", mctx->mi->name, name);
199 name = inst_name;
200 }
201
202 /*
203 * If it already exists, replace the instance.
204 */
205 return fr_rb_find(xlat_root, &(xlat_t){ .name = name });
206}
207
208/** Register an xlat function
209 *
210 * @param[in] ctx Used to automate deregistration of the xlat function.
211 * @param[in] name of the xlat.
212 * @param[in] func to register.
213 * @param[in] return_type what type of output the xlat function will produce.
214 * @return
215 * - A handle for the newly registered xlat function on success.
216 * - NULL on failure.
217 */
218xlat_t *xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
219{
220 xlat_t *c;
222 size_t len, used;
223
225
226 if (!*name) {
227 invalid_name:
228 ERROR("%s: Invalid xlat name", __FUNCTION__);
229 return NULL;
230 }
231
232 len = strlen(name);
233 if ((len == 1) && (strchr("InscCdDeGHlmMStTY", *name) != NULL)) goto invalid_name;
234
235 in = FR_SBUFF_IN(name, len);
238
239 if (used < len) {
240 ERROR("%s: Invalid character '%c' in dynamic expansion name '%s'", __FUNCTION__, name[used], name);
241 return NULL;
242 }
243
244 /*
245 * If it already exists, replace the instance.
246 */
247 c = fr_rb_find(xlat_root, &(xlat_t){ .name = name });
248 if (c) {
249 if (c->internal) {
250 ERROR("%s: Cannot re-define internal expansion %s", __FUNCTION__, name);
251 return NULL;
252 }
253
254 if (c->func != func) {
255 ERROR("%s: Cannot change callback function for %s", __FUNCTION__, name);
256 return NULL;
257 }
258
259 return c;
260 }
261
262 /*
263 * Doesn't exist. Create it.
264 */
265 MEM(c = talloc(NULL, xlat_t));
266 *c = (xlat_t){
268 .func = func,
269 .return_type = return_type,
270 .input_type = XLAT_INPUT_UNPROCESSED /* set default - will be overridden if args are registered */
271 };
272
273 /*
274 * Don't allocate directly in the parent ctx, it might be mprotected
275 * later, and that'll cause segfaults if any of the xlat_t are still
276 * protected when we start shuffling the contents of the rbtree.
277 */
278 if (ctx) talloc_link_ctx(c, ctx);
279
280 talloc_set_destructor(c, _xlat_func_talloc_free);
281 DEBUG3("%s: %s", __FUNCTION__, c->name);
282
283 if (fr_rb_replace(NULL, xlat_root, c) < 0) {
284 ERROR("%s: Failed inserting xlat registration for %s", __FUNCTION__, c->name);
285 talloc_free(c);
286 return NULL;
287 }
288
289 return c;
290}
291
292/** Associate a module calling ctx with the xlat
293 *
294 * @note Intended to be called from the module_rlm
295 *
296 * @param[in] x to set the mctx for.
297 * @param[in] mctx Is duplicated and about to the lifetime of the xlat.
298 */
300{
301 module_inst_ctx_t *our_mctx = NULL;
302
303 TALLOC_FREE(x->mctx);
304 MEM(our_mctx = talloc_zero(x, module_inst_ctx_t)); /* Original won't stick around */
305 memcpy(our_mctx, mctx, sizeof(*our_mctx));
306 x->mctx = our_mctx;
307}
308
309/** Verify xlat arg specifications are valid
310 *
311 * @param[in] x we're setting arguments for.
312 * @param[in] arg specification to validate.
313 * @param[in] last Is this the last argument in the list.
314 */
315static inline int xlat_arg_parser_validate(xlat_t *x, xlat_arg_parser_t const *arg, bool last)
316{
317 if (arg->concat) {
318 if (!fr_cond_assert_msg((arg->type == FR_TYPE_STRING) || (arg->type == FR_TYPE_OCTETS),
319 "%s - concat type must be string or octets", x->name)) return -1;
320
321 if (!fr_cond_assert_msg(!arg->single, "%s - concat and single are mutually exclusive", x->name)) return -1;
322 }
323
324 if (arg->single) {
325 if (!fr_cond_assert_msg(!arg->concat, "%s - single and concat are mutually exclusive", x->name)) return -1;
326 }
327
328 if (arg->variadic) {
329 if (!fr_cond_assert_msg(last, "%s - variadic can only be set on the last argument", x->name)) return -1;
330 if (!fr_cond_assert_msg(!arg->required, "%s - required can't be set on a variadic argument. "
331 "Set required in the preceding entry", x->name)) return -1;
332 }
333
334 if (arg->always_escape) {
335 if (!fr_cond_assert_msg(arg->func, "%s - always_escape requires an escape func", x->name)) return -1;
336 }
337
338 if (arg->uctx) {
339 if (!fr_cond_assert_msg(arg->func, "%s - uctx requires an escape func", x->name)) return -1;
340 }
341
342 switch (arg->type) {
343 case FR_TYPE_LEAF:
344 case FR_TYPE_VOID:
345 break;
346
347 default:
348 fr_assert_fail("%s - type must be a leaf box type", x->name);
349 return -1;
350 }
351
352 return 0;
353}
354
355/** Register the arguments of an xlat
356 *
357 * For xlats that take multiple arguments
358 *
359 * @param[in,out] x to have it's arguments registered
360 * @param[in] args to be registered
361 * @return
362 * - 0 on success.
363 * - < 0 on failure.
364 */
366{
367 xlat_arg_parser_t const *arg_p = args;
368 bool seen_optional = false;
369
370 for (arg_p = args; arg_p->type != FR_TYPE_NULL; arg_p++) {
371 if (xlat_arg_parser_validate(x, arg_p, (arg_p + 1)->type == FR_TYPE_NULL) < 0) return -1;
372
373 if (arg_p->required) {
374 if (!fr_cond_assert_msg(!seen_optional,
375 "required arguments must be at the "
376 "start of the argument list")) return -1;
377 } else {
378 seen_optional = true;
379 }
380 }
381 x->args = args;
383
384 return 0;
385}
386
387/** Register call environment of an xlat
388 *
389 * @param[in,out] x to have it's module method env registered.
390 * @param[in] env_method to be registered.
391 */
393{
394 x->call_env_method = env_method;
395}
396
397/** Specify flags that alter the xlat's behaviour
398 *
399 * @param[in] x xlat to set flags for.
400 * @param[in] flags to set.
401 */
403{
404 x->flags.pure = flags & XLAT_FUNC_FLAG_PURE;
406 x->flags.impure_func = !x->flags.pure;
407}
408
409/** Set a print routine for an xlat function.
410 *
411 * @param[in] xlat to set
412 * @param[in] func for printing
413 */
415{
416 xlat->print = func;
417}
418
419/** Set a resolve routine for an xlat function.
420 *
421 * @param[in] xlat to set
422 * @param[in] func to resolve xlat.
423 */
425{
426 xlat->resolve = func;
427}
428
429/** Set a resolve routine for an xlat function.
430 *
431 * @param[in] xlat to set
432 * @param[in] func to purify xlat
433 */
435{
436 xlat->purify = func;
437}
438
439/** Set the escaped values for output boxes
440 *
441 * @param[in] xlat function to set the escaped value for (as returned by xlat_register).
442 * @param[in] safe_for escaped value to write to output boxes.
443 */
445{
446 xlat->return_safe_for = safe_for;
447}
448
449/** Set global instantiation/detach callbacks
450 *
451 * @param[in] xlat to set instantiation callbacks for.
452 * @param[in] instantiate Instantiation function. Called whenever a xlat is
453 * compiled.
454 * @param[in] inst_type Name of the instance structure.
455 * @param[in] inst_size The size of the instance struct.
456 * Pre-allocated for use by the instantiate function.
457 * If 0, no memory will be allocated.
458 * @param[in] detach Called when an xlat_exp_t is freed.
459 * @param[in] uctx Passed to the instantiation function.
460 */
462 xlat_instantiate_t instantiate, char const *inst_type, size_t inst_size,
463 xlat_detach_t detach,
464 void *uctx)
465{
466 xlat_t *c = UNCONST(xlat_t *, xlat);
467
469 c->inst_type = inst_type;
470 c->inst_size = inst_size;
471 c->detach = detach;
472 c->uctx = uctx;
473}
474
475/** Register an async xlat
476 *
477 * All functions registered must be !pure
478 *
479 * @param[in] xlat to set instantiation callbacks for.
480 * @param[in] thread_instantiate Instantiation function. Called for every compiled xlat
481 * every time a thread is started.
482 * @param[in] thread_inst_type Name of the thread instance structure.
483 * @param[in] thread_inst_size The size of the thread instance struct.
484 * Pre-allocated for use by the instantiate function.
485 * If 0, no memory will be allocated.
486 * @param[in] thread_detach Called when the thread is freed.
487 * @param[in] uctx Passed to the thread instantiate function.
488 */
491 char const *thread_inst_type, size_t thread_inst_size,
493 void *uctx)
494{
495 xlat_t *c = UNCONST(xlat_t *, xlat);
496
497 /*
498 * Pure functions can't use any thread-local
499 * variables. They MUST operate only on constant
500 * instantiation data, and on their (possibly constant)
501 * inputs.
502 */
503 fr_assert(!c->flags.pure);
504
506 c->thread_inst_type = thread_inst_type;
507 c->thread_inst_size = thread_inst_size;
509 c->thread_uctx = uctx;
510}
511
512/** Unregister an xlat function
513 *
514 * We can only have one function to call per name, so the passing of "func"
515 * here is extraneous.
516 *
517 * @param[in] name xlat to unregister.
518 */
519void xlat_func_unregister(char const *name)
520{
521 xlat_t *c;
522
523 if (!name || !xlat_root) return;
524
525 c = fr_rb_find(xlat_root, &(xlat_t){ .name = name });
526 if (!c) return;
527
528 (void) talloc_get_type_abort(c, xlat_t);
529
530 talloc_free(c); /* Should also remove from tree */
531}
532
534{
535 xlat_t *c;
537
538 if (!xlat_root) return; /* All xlats have already been freed */
539
540 for (c = fr_rb_iter_init_inorder(&iter, xlat_root);
541 c;
542 c = fr_rb_iter_next_inorder(&iter)) {
543 if (!c->mctx) continue;
544 if (c->mctx->mi != inst) continue;
545
547 }
548}
549
551{
552 if (xlat_root) return 0;
553
554 /*
555 * Create the function tree
556 */
558 if (!xlat_root) {
559 ERROR("%s: Failed to create tree", __FUNCTION__);
560 return -1;
561 }
562
563 return 0;
564}
565
567{
568 fr_rb_tree_t *xr = xlat_root; /* Make sure the tree can't be freed multiple times */
569
570 if (!xr) return;
571
572 xlat_root = NULL;
573 talloc_free(xr);
574}
static int const char char buffer[256]
Definition acutest.h:576
va_list args
Definition acutest.h:770
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:483
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition debug.h:216
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:156
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
static fr_slen_t in
Definition dict.h:824
#define DEBUG3(_fmt,...)
Definition log.h:266
talloc_free(reap)
fr_type_t
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
static size_t used
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
#define fr_assert(_expr)
Definition rad_assert.h:38
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
Definition radiusd.c:149
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
Definition radiusd.c:132
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
Definition rb.c:781
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition rb.c:824
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition rb.c:898
int fr_rb_replace(void **old, fr_rb_tree_t *tree, void const *data)
Replace old data with new data, OR insert if there is no old.
Definition rb.c:647
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:850
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition rb.c:741
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
Definition rb.h:246
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:321
The main red black tree structure.
Definition rb.h:73
static char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX+1], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
Definition sbuff.c:1777
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
char const * name
Instance name e.g. user_database.
Definition module.h:335
Module instance data.
Definition module.h:265
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
Definition talloc.c:171
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:445
fr_type_t type
Type to cast argument to.
Definition xlat.h:155
int(* xlat_thread_detach_t)(xlat_thread_inst_ctx_t const *xctx)
xlat thread detach callback
Definition xlat.h:289
int(* xlat_detach_t)(xlat_inst_ctx_t const *xctx)
xlat detach callback
Definition xlat.h:274
void * uctx
Argument to pass to escape callback.
Definition xlat.h:159
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
xlat_escape_func_t func
Function to handle tainted values.
Definition xlat.h:156
xlat_arg_parser_variadic_t variadic
All additional boxes should be processed using this definition.
Definition xlat.h:151
bool concat
Concat boxes together.
Definition xlat.h:149
bool single
Argument must only contain a single box.
Definition xlat.h:150
bool always_escape
Pass all arguments to escape function not just tainted ones.
Definition xlat.h:153
struct xlat_s xlat_t
Definition xlat.h:107
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
Definition xlat.h:49
@ XLAT_INPUT_UNPROCESSED
No input argument processing.
Definition xlat.h:48
xlat_action_t(* xlat_func_t)(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
xlat callback function
Definition xlat.h:230
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
Definition xlat.h:114
int(* xlat_thread_instantiate_t)(xlat_thread_inst_ctx_t const *xctx)
Allocate new thread instance data for an xlat instance.
Definition xlat.h:260
bool impure_func
xlat contains an impure function
Definition xlat.h:115
int(* xlat_instantiate_t)(xlat_inst_ctx_t const *xctx)
Allocate new instance data for an xlat instance.
Definition xlat.h:251
Definition for a single argument consumend by an xlat function.
Definition xlat.h:147
#define FR_TYPE_LEAF
Definition types.h:297
static size_t char fr_sbuff_t size_t inlen
Definition value.h:997
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition value.h:155
static int _xlat_func_talloc_free(xlat_t *xlat)
Remove an xlat function from the function tree.
Definition xlat_func.c:100
void xlat_purify_func_set(xlat_t *xlat, xlat_purify_t func)
Set a resolve routine for an xlat function.
Definition xlat_func.c:434
void xlat_func_free(void)
Definition xlat_func.c:566
static int8_t xlat_name_cmp(void const *one, void const *two)
Compare two xlat_t by the registered name.
Definition xlat_func.c:44
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
Definition xlat_func.c:402
void xlat_func_resolve_set(xlat_t *xlat, xlat_resolve_t func)
Set a resolve routine for an xlat function.
Definition xlat_func.c:424
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:365
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
Definition xlat_func.c:392
void xlat_func_unregister_module(module_instance_t const *inst)
Definition xlat_func.c:533
static fr_rb_tree_t * xlat_root
Definition xlat_func.c:33
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:218
int xlat_func_init(void)
Definition xlat_func.c:550
void xlat_func_print_set(xlat_t *xlat, xlat_print_t func)
Set a print routine for an xlat function.
Definition xlat_func.c:414
int8_t xlat_func_cmp(void const *one, void const *two)
Compare two xlat_t by the underlying function.
Definition xlat_func.c:69
void _xlat_func_safe_for_set(xlat_t *xlat, fr_value_box_safe_for_t safe_for)
Set the escaped values for output boxes.
Definition xlat_func.c:444
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
Definition xlat_func.c:79
void xlat_mctx_set(xlat_t *x, module_inst_ctx_t const *mctx)
Associate a module calling ctx with the xlat.
Definition xlat_func.c:299
static int xlat_arg_parser_validate(xlat_t *x, xlat_arg_parser_t const *arg, bool last)
Verify xlat arg specifications are valid.
Definition xlat_func.c:315
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519
void _xlat_func_thread_instantiate_set(xlat_t const *xlat, xlat_thread_instantiate_t thread_instantiate, char const *thread_inst_type, size_t thread_inst_size, xlat_thread_detach_t thread_detach, void *uctx)
Register an async xlat.
Definition xlat_func.c:489
xlat_t * xlat_func_find_module(module_inst_ctx_t const *mctx, char const *name)
Definition xlat_func.c:182
void _xlat_func_instantiate_set(xlat_t const *xlat, xlat_instantiate_t instantiate, char const *inst_type, size_t inst_size, xlat_detach_t detach, void *uctx)
Set global instantiation/detach callbacks.
Definition xlat_func.c:461
static void _xlat_func_tree_free(void *xlat)
Callback for the rbtree to clear out any xlats still registered.
Definition xlat_func.c:114
int(* xlat_purify_t)(xlat_exp_t *xlat, void *inst, request_t *request)
Custom function purify the result of an xlat function.
Definition xlat_func.h:53
int(* xlat_resolve_t)(xlat_exp_t *xlat, void *inst, xlat_res_rules_t const *xr_rules)
Custom function to perform resolution of arguments.
Definition xlat_func.h:49
fr_slen_t(* xlat_print_t)(fr_sbuff_t *in, xlat_exp_t const *self, void *inst, fr_sbuff_escape_rules_t const *e_rules)
Custom function to print xlat debug.
Definition xlat_func.h:45
xlat_func_flags_t
Definition xlat_func.h:36
@ XLAT_FUNC_FLAG_PURE
Definition xlat_func.h:38
@ XLAT_FUNC_FLAG_INTERNAL
Definition xlat_func.h:39
char const * name
Name of xlat function.
Definition xlat_priv.h:64
char const * thread_inst_type
C type of thread instance structure.
Definition xlat_priv.h:82
module_inst_ctx_t * mctx
Original module instantiation ctx if this xlat was registered by a module.
Definition xlat_priv.h:70
bool const xlat_func_chars[UINT8_MAX+1]
bool internal
If true, cannot be redefined.
Definition xlat_priv.h:67
xlat_func_t func
async xlat function (async unsafe).
Definition xlat_priv.h:65
xlat_instantiate_t instantiate
Instantiation function.
Definition xlat_priv.h:73
size_t thread_inst_size
Size of the thread instance data to pre-allocate.
Definition xlat_priv.h:83
xlat_detach_t detach
Destructor for when xlat instances are freed.
Definition xlat_priv.h:74
void * thread_uctx
uctx to pass to instantiation functions.
Definition xlat_priv.h:84
call_env_method_t const * call_env_method
Optional tmpl expansions performed before calling the xlat.
Definition xlat_priv.h:95
size_t inst_size
Size of instance data to pre-allocate.
Definition xlat_priv.h:76
xlat_arg_parser_t const * args
Definition of args consumed.
Definition xlat_priv.h:93
xlat_resolve_t resolve
function to call when resolving
Definition xlat_priv.h:87
xlat_thread_instantiate_t thread_instantiate
Thread instantiation function.
Definition xlat_priv.h:79
char const * inst_type
C type of instance structure.
Definition xlat_priv.h:75
xlat_input_type_t input_type
Type of input used.
Definition xlat_priv.h:92
fr_value_box_safe_for_t return_safe_for
Escaped value to set in output boxes.
Definition xlat_priv.h:99
xlat_thread_detach_t thread_detach
Destructor for when xlat thread instance data is freed.
Definition xlat_priv.h:80
xlat_purify_t purify
function to call when purifying the node.
Definition xlat_priv.h:88
xlat_flags_t flags
various flags
Definition xlat_priv.h:90
xlat_print_t print
function to call when printing
Definition xlat_priv.h:86
void * uctx
uctx to pass to instantiation functions.
Definition xlat_priv.h:77