The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 2ef35b08dee54fc50b562f3d6928a107818b3c1b $
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 
26 RCSID("$Id: 2ef35b08dee54fc50b562f3d6928a107818b3c1b $")
27 
28 #include <freeradius-devel/unlang/xlat_priv.h>
29 #include <freeradius-devel/unlang/xlat.h>
30 #include <freeradius-devel/unlang/xlat_func.h>
31 
32 static fr_rb_tree_t *xlat_root = NULL;
33 
34 /*
35  * Compare two xlat_t structs, based ONLY on the module name.
36  */
37 static int8_t xlat_cmp(void const *one, void const *two)
38 {
39  xlat_t const *a = one, *b = two;
40  size_t a_len, b_len;
41  int ret;
42 
43  a_len = strlen(a->name);
44  b_len = strlen(b->name);
45 
46  ret = CMP(a_len, b_len);
47  if (ret != 0) return ret;
48 
49  ret = memcmp(a->name, b->name, a_len);
50  return CMP(ret, 0);
51 }
52 
53 /*
54  * find the appropriate registered xlat function.
55  */
57 {
58  char buffer[256];
59 
60  if (!xlat_root) return NULL;
61 
62  if (inlen < 0) return fr_rb_find(xlat_root, &(xlat_t){ .name = in });
63 
64  if ((size_t) inlen >= sizeof(buffer)) return NULL;
65 
66  memcpy(buffer, in, inlen);
67  buffer[inlen] = '\0';
68 
69  return fr_rb_find(xlat_root, &(xlat_t){ .name = buffer });
70 }
71 
72 /** Remove an xlat function from the function tree
73  *
74  * @param[in] xlat to free.
75  * @return 0
76  */
77 static int _xlat_func_talloc_free(xlat_t *xlat)
78 {
79  if (!xlat_root) return 0;
80 
81  fr_rb_delete(xlat_root, xlat);
82  if (fr_rb_num_elements(xlat_root) == 0) TALLOC_FREE(xlat_root);
83 
84  return 0;
85 }
86 
87 
88 /** Callback for the rbtree to clear out any xlats still registered
89  *
90  */
91 static void _xlat_func_tree_free(void *xlat)
92 {
93  talloc_free(xlat);
94 }
95 
96 #if 0
97 /** Compare two argument entries to see if they're equivalent
98  *
99  * @note Does not check escape function or uctx pointers.
100  *
101  * @param[in] a First argument structure.
102  * @param[in] b Second argument structure.
103  * @return
104  * - 1 if a > b
105  * - 0 if a == b
106  * - -1 if a < b
107  */
108 static int xlat_arg_cmp_no_escape(xlat_arg_parser_t const *a, xlat_arg_parser_t const *b)
109 {
110  int8_t ret;
111 
112  ret = CMP(a->required, b->required);
113  if (ret != 0) return ret;
114 
115  ret = CMP(a->concat, b->concat);
116  if (ret != 0) return ret;
117 
118  ret = CMP(a->single, b->single);
119  if (ret != 0) return ret;
120 
121  ret = CMP(a->variadic, b->variadic);
122  if (ret != 0) return ret;
123 
124  ret = CMP(a->always_escape, b->always_escape);
125  if (ret != 0) return ret;
126 
127  return CMP(a->type, b->type);
128 }
129 
130 /** Compare two argument lists to see if they're equivalent
131  *
132  * @note Does not check escape function or uctx pointers.
133  *
134  * @param[in] a First argument structure.
135  * @param[in] b Second argument structure.
136  * @return
137  * - 1 if a > b
138  * - 0 if a == b
139  * - -1 if a < b
140  */
141 static int xlat_arg_cmp_list_no_escape(xlat_arg_parser_t const a[], xlat_arg_parser_t const b[])
142 {
143  xlat_arg_parser_t const *arg_a_p;
144  xlat_arg_parser_t const *arg_b_p;
145 
146  for (arg_a_p = a, arg_b_p = b;
147  (arg_a_p->type != FR_TYPE_NULL) && (arg_b_p->type != FR_TYPE_NULL);
148  arg_a_p++, arg_b_p++) {
149  int8_t ret;
150 
151  ret = xlat_arg_cmp_no_escape(arg_a_p, arg_b_p);
152  if (ret != 0) return ret;
153  }
154 
155  return CMP(arg_a_p, arg_b_p); /* Check we ended at the same point */
156 }
157 #endif
158 
160 {
161  char inst_name[256];
162 
164 
165  if (!*name) {
166  ERROR("%s: Invalid xlat name", __FUNCTION__);
167  return NULL;
168  }
169 
170  /*
171  * Name xlats other than those which are just the module instance
172  * as <instance name>.<function name>
173  */
174  if (mctx && name != mctx->inst->name) {
175  snprintf(inst_name, sizeof(inst_name), "%s.%s", mctx->inst->name, name);
176  name = inst_name;
177  }
178 
179  /*
180  * If it already exists, replace the instance.
181  */
182  return fr_rb_find(xlat_root, &(xlat_t){ .name = name });
183 }
184 
185 /** Register an xlat function
186  *
187  * @param[in] ctx Used to automate deregistration of the xlat function.
188  * @param[in] name of the xlat.
189  * @param[in] func to register.
190  * @param[in] return_type what type of output the xlat function will produce.
191  * @return
192  * - A handle for the newly registered xlat function on success.
193  * - NULL on failure.
194  */
195 xlat_t *xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
196 {
197  xlat_t *c;
198  fr_sbuff_t in;
199  size_t len, used;
200 
202 
203  if (!*name) {
204  invalid_name:
205  ERROR("%s: Invalid xlat name", __FUNCTION__);
206  return NULL;
207  }
208 
209  len = strlen(name);
210  if ((len == 1) && (strchr("InscCdDeGHlmMStTY", *name) != NULL)) goto invalid_name;
211 
212  in = FR_SBUFF_IN(name, len);
213  fr_sbuff_adv_past_allowed(&in, SIZE_MAX, xlat_func_chars, NULL);
214  used = fr_sbuff_used(&in);
215 
216  if (used < len) {
217  ERROR("%s: Invalid character '%c' in dynamic expansion name '%s'", __FUNCTION__, name[used], name);
218  return NULL;
219  }
220 
221  /*
222  * If it already exists, replace the instance.
223  */
224  c = fr_rb_find(xlat_root, &(xlat_t){ .name = name });
225  if (c) {
226  if (c->internal) {
227  ERROR("%s: Cannot re-define internal expansion %s", __FUNCTION__, name);
228  return NULL;
229  }
230 
231  if (c->func != func) {
232  ERROR("%s: Cannot change callback function for %s", __FUNCTION__, name);
233  return NULL;
234  }
235 
236  return c;
237  }
238 
239  /*
240  * Doesn't exist. Create it.
241  */
242  MEM(c = talloc(ctx, xlat_t));
243  *c = (xlat_t){
245  .func = func,
246  .return_type = return_type,
247  .input_type = XLAT_INPUT_UNPROCESSED /* set default - will be overridden if args are registered */
248  };
249  talloc_set_destructor(c, _xlat_func_talloc_free);
250  DEBUG3("%s: %s", __FUNCTION__, c->name);
251 
252  if (fr_rb_replace(NULL, xlat_root, c) < 0) {
253  ERROR("%s: Failed inserting xlat registration for %s", __FUNCTION__, c->name);
254  talloc_free(c);
255  return NULL;
256  }
257 
258  return c;
259 }
260 
261 /** Register an xlat function for a module
262  *
263  * @param[in] ctx Used to automate deregistration of the xlat function.
264  * @param[in] mctx Instantiation context from the module.
265  * Will be duplicated and passed to future xlat calls.
266  * @param[in] name of the xlat. Must be NULL, for "self-named" xlats.
267  * e.g. `cache`, `sql`, `delay`, etc.
268  * @param[in] func to register.
269  * @param[in] return_type what type of output the xlat function will produce.
270  * @return
271  * - A handle for the newly registered xlat function on success.
272  * - NULL on failure.
273  */
274 xlat_t *xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx,
275  char const *name, xlat_func_t func, fr_type_t return_type)
276 {
277  module_inst_ctx_t *our_mctx = NULL;
278  xlat_t *c;
279  char inst_name[256];
280 
281  fr_assert_msg(name != mctx->inst->name, "`name` must not be the same as the module "
282  "instance name. Pass a NULL `name` arg if this is required");
283 
284  if (!name) {
285  name = mctx->inst->name;
286  } else {
287  if ((size_t)snprintf(inst_name, sizeof(inst_name), "%s.%s", mctx->inst->name, name) >= sizeof(inst_name)) {
288  ERROR("%s: Instance name too long", __FUNCTION__);
289  return NULL;
290  }
291  name = inst_name;
292  }
293 
294  c = xlat_func_register(ctx, name, func, return_type);
295  if (!c) return NULL;
296 
297  MEM(our_mctx = talloc_zero(c, module_inst_ctx_t)); /* Original won't stick around */
298  memcpy(our_mctx, mctx, sizeof(*our_mctx));
299  c->mctx = our_mctx;
300 
301  return c;
302 }
303 
304 /** Verify xlat arg specifications are valid
305  *
306  * @param[in] x we're setting arguments for.
307  * @param[in] arg specification to validate.
308  * @param[in] last Is this the last argument in the list.
309  */
310 static inline int xlat_arg_parser_validate(xlat_t *x, xlat_arg_parser_t const *arg, bool last)
311 {
312  if (arg->concat) {
313  if (!fr_cond_assert_msg((arg->type == FR_TYPE_STRING) || (arg->type == FR_TYPE_OCTETS),
314  "%s - concat type must be string or octets", x->name)) return -1;
315 
316  if (!fr_cond_assert_msg(!arg->single, "%s - concat and single are mutually exclusive", x->name)) return -1;
317  }
318 
319  if (arg->single) {
320  if (!fr_cond_assert_msg(!arg->concat, "%s - single and concat are mutually exclusive", x->name)) return -1;
321  }
322 
323  if (arg->variadic) {
324  if (!fr_cond_assert_msg(last, "%s - variadic can only be set on the last argument", x->name)) return -1;
325  if (!fr_cond_assert_msg(!arg->required, "%s - required can't be set on a variadic argument. "
326  "Set required in the preceding entry", x->name)) return -1;
327  }
328 
329  if (arg->always_escape) {
330  if (!fr_cond_assert_msg(arg->func, "%s - always_escape requires an escape func", x->name)) return -1;
331  }
332 
333  if (arg->uctx) {
334  if (!fr_cond_assert_msg(arg->func, "%s - uctx requires an escape func", x->name)) return -1;
335  }
336 
337  switch (arg->type) {
338  case FR_TYPE_LEAF:
339  case FR_TYPE_VOID:
340  break;
341 
342  default:
343  fr_assert_fail("%s - type must be a leaf box type", x->name);
344  return -1;
345  }
346 
347  return 0;
348 }
349 
350 /** Register the arguments of an xlat
351  *
352  * For xlats that take multiple arguments
353  *
354  * @param[in,out] x to have it's arguments registered
355  * @param[in] args to be registered
356  * @return
357  * - 0 on success.
358  * - < 0 on failure.
359  */
361 {
362  xlat_arg_parser_t const *arg_p = args;
363  bool seen_optional = false;
364 
365  for (arg_p = args; arg_p->type != FR_TYPE_NULL; arg_p++) {
366  if (xlat_arg_parser_validate(x, arg_p, (arg_p + 1)->type == FR_TYPE_NULL) < 0) return -1;
367 
368  if (arg_p->required) {
369  if (!fr_cond_assert_msg(!seen_optional,
370  "required arguments must be at the "
371  "start of the argument list")) return -1;
372  } else {
373  seen_optional = true;
374  }
375  }
376  x->args = args;
378 
379  return 0;
380 }
381 
382 /** Register the argument of an xlat
383  *
384  * For xlats that take all their input as a single argument
385  *
386  * @param[in,out] x to have it's arguments registered
387  * @param[in] args to be registered
388  * @return
389  * - 0 on success.
390  * - < 0 on failure.
391  */
393 {
394  if (xlat_func_args_set(x, args) < 0) return -1;
396 
397  return 0;
398 }
399 
400 /** Register call environment of an xlat
401  *
402  * @param[in,out] x to have it's module method env registered.
403  * @param[in] env_method to be registered.
404  */
406 {
407  x->call_env_method = env_method;
408 }
409 
410 /** Specify flags that alter the xlat's behaviour
411  *
412  * @param[in] x xlat to set flags for.
413  * @param[in] flags to set.
414  */
416 {
417  x->flags.pure = flags & XLAT_FUNC_FLAG_PURE;
418  x->internal = flags & XLAT_FUNC_FLAG_INTERNAL;
419 }
420 
421 /** Set a print routine for an xlat function.
422  *
423  * @param[in] xlat to set
424  * @param[in] func for printing
425  */
427 {
428  xlat->print = func;
429 }
430 
431 /** Set a resolve routine for an xlat function.
432  *
433  * @param[in] xlat to set
434  * @param[in] func to resolve xlat.
435  */
437 {
438  xlat->resolve = func;
439 }
440 
441 /** Set a resolve routine for an xlat function.
442  *
443  * @param[in] xlat to set
444  * @param[in] func to purify xlat
445  */
447 {
448  xlat->purify = func;
449 }
450 
451 /** Set the escaped values for output boxes
452  *
453  * @param[in] xlat function to set the escaped value for (as returned by xlat_register).
454  * @param[in] safe_for escaped value to write to output boxes.
455  */
457 {
458  xlat->return_safe_for = safe_for;
459 }
460 
461 /** Set global instantiation/detach callbacks
462  *
463  * @param[in] xlat to set instantiation callbacks for.
464  * @param[in] instantiate Instantiation function. Called whenever a xlat is
465  * compiled.
466  * @param[in] inst_type Name of the instance structure.
467  * @param[in] inst_size The size of the instance struct.
468  * Pre-allocated for use by the instantiate function.
469  * If 0, no memory will be allocated.
470  * @param[in] detach Called when an xlat_exp_t is freed.
471  * @param[in] uctx Passed to the instantiation function.
472  */
474  xlat_instantiate_t instantiate, char const *inst_type, size_t inst_size,
475  xlat_detach_t detach,
476  void *uctx)
477 {
478  xlat_t *c = UNCONST(xlat_t *, xlat);
479 
481  c->inst_type = inst_type;
482  c->inst_size = inst_size;
483  c->detach = detach;
484  c->uctx = uctx;
485 }
486 
487 /** Register an async xlat
488  *
489  * All functions registered must be !pure
490  *
491  * @param[in] xlat to set instantiation callbacks for.
492  * @param[in] thread_instantiate Instantiation function. Called for every compiled xlat
493  * every time a thread is started.
494  * @param[in] thread_inst_type Name of the thread instance structure.
495  * @param[in] thread_inst_size The size of the thread instance struct.
496  * Pre-allocated for use by the instantiate function.
497  * If 0, no memory will be allocated.
498  * @param[in] thread_detach Called when the thread is freed.
499  * @param[in] uctx Passed to the thread instantiate function.
500  */
503  char const *thread_inst_type, size_t thread_inst_size,
505  void *uctx)
506 {
507  xlat_t *c = UNCONST(xlat_t *, xlat);
508 
509  /*
510  * Pure functions can't use any thread-local
511  * variables. They MUST operate only on constant
512  * instantiation data, and on their (possibly constant)
513  * inputs.
514  */
515  fr_assert(!c->flags.pure);
516 
518  c->thread_inst_type = thread_inst_type;
519  c->thread_inst_size = thread_inst_size;
521  c->thread_uctx = uctx;
522 }
523 
524 /** Unregister an xlat function
525  *
526  * We can only have one function to call per name, so the passing of "func"
527  * here is extraneous.
528  *
529  * @param[in] name xlat to unregister.
530  */
531 void xlat_func_unregister(char const *name)
532 {
533  xlat_t *c;
534 
535  if (!name || !xlat_root) return;
536 
537  c = fr_rb_find(xlat_root, &(xlat_t){ .name = name });
538  if (!c) return;
539 
540  (void) talloc_get_type_abort(c, xlat_t);
541 
542  talloc_free(c); /* Should also remove from tree */
543 }
544 
546 {
547  xlat_t *c;
549 
550  if (!xlat_root) return; /* All xlats have already been freed */
551 
552  for (c = fr_rb_iter_init_inorder(&iter, xlat_root);
553  c;
554  c = fr_rb_iter_next_inorder(&iter)) {
555  if (!c->mctx) continue;
556  if (c->mctx->inst != inst) continue;
557 
559  }
560 }
561 
562 int xlat_func_init(void)
563 {
564  if (xlat_root) return 0;
565 
566  /*
567  * Create the function tree
568  */
570  if (!xlat_root) {
571  ERROR("%s: Failed to create tree", __FUNCTION__);
572  return -1;
573  }
574 
575  return 0;
576 }
577 
578 void xlat_func_free(void)
579 {
580  fr_rb_tree_t *xr = xlat_root; /* Make sure the tree can't be freed multiple times */
581 
582  if (!xr) return;
583 
584  xlat_root = NULL;
585  talloc_free(xr);
586 }
static int const char char buffer[256]
Definition: acutest.h:574
va_list args
Definition: acutest.h:770
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#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:110
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition: debug.h:208
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition: debug.h:214
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:154
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static fr_slen_t in
Definition: dict.h:645
char const *_CONST name
Instance name.
Definition: dl_module.h:163
A module/inst tuple.
Definition: dl_module.h:162
#define DEBUG3(_fmt,...)
Definition: log.h:266
talloc_free(reap)
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
long int ssize_t
Definition: merged_model.c:24
static size_t used
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
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:775
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition: rb.c:892
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:644
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:844
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:736
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:818
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:576
#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:1312
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:1736
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:333
fr_type_t type
Type to cast argument to.
Definition: xlat.h:153
int(* xlat_thread_detach_t)(xlat_thread_inst_ctx_t const *xctx)
xlat thread detach callback
Definition: xlat.h:273
int(* xlat_detach_t)(xlat_inst_ctx_t const *xctx)
xlat detach callback
Definition: xlat.h:258
void * uctx
Argument to pass to escape callback.
Definition: xlat.h:157
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
xlat_escape_func_t func
Function to handle tainted values.
Definition: xlat.h:154
xlat_arg_parser_variadic_t variadic
All additional boxes should be processed using this definition.
Definition: xlat.h:149
bool concat
Concat boxes together.
Definition: xlat.h:147
bool single
Argument must only contain a single box.
Definition: xlat.h:148
bool always_escape
Pass all arguments to escape function not just tainted ones.
Definition: xlat.h:151
struct xlat_s xlat_t
Definition: xlat.h:106
@ XLAT_INPUT_MONO
Ingests a single argument.
Definition: xlat.h:47
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
Definition: xlat.h:48
@ XLAT_INPUT_UNPROCESSED
No input argument processing.
Definition: xlat.h:46
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:214
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
Definition: xlat.h:113
int(* xlat_thread_instantiate_t)(xlat_thread_inst_ctx_t const *xctx)
Allocate new thread instance data for an xlat instance.
Definition: xlat.h:244
int(* xlat_instantiate_t)(xlat_inst_ctx_t const *xctx)
Allocate new instance data for an xlat instance.
Definition: xlat.h:235
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
#define FR_TYPE_LEAF
Definition: types.h:297
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
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:77
void xlat_purify_func_set(xlat_t *xlat, xlat_purify_t func)
Set a resolve routine for an xlat function.
Definition: xlat_func.c:446
void xlat_func_free(void)
Definition: xlat_func.c:578
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:415
void xlat_func_resolve_set(xlat_t *xlat, xlat_resolve_t func)
Set a resolve routine for an xlat function.
Definition: xlat_func.c:436
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition: xlat_func.c:360
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:195
static int8_t xlat_cmp(void const *one, void const *two)
Definition: xlat_func.c:37
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:405
static fr_rb_tree_t * xlat_root
Definition: xlat_func.c:32
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
Definition: xlat_func.c:56
int xlat_func_init(void)
Definition: xlat_func.c:562
void xlat_func_print_set(xlat_t *xlat, xlat_print_t func)
Set a print routine for an xlat function.
Definition: xlat_func.c:426
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:456
int xlat_func_mono_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the argument of an xlat.
Definition: xlat_func.c:392
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:310
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition: xlat_func.c:531
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:501
void xlat_func_unregister_module(dl_module_inst_t const *inst)
Definition: xlat_func.c:545
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.
Definition: xlat_func.c:274
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:473
static void _xlat_func_tree_free(void *xlat)
Callback for the rbtree to clear out any xlats still registered.
Definition: xlat_func.c:91
xlat_t * xlat_func_find_module(module_inst_ctx_t const *mctx, char const *name)
Definition: xlat_func.c:159
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:60
char const * thread_inst_type
C type of thread instance structure.
Definition: xlat_priv.h:78
bool const xlat_func_chars[UINT8_MAX+1]
bool internal
If true, cannot be redefined.
Definition: xlat_priv.h:63
xlat_func_t func
async xlat function (async unsafe).
Definition: xlat_priv.h:61
xlat_instantiate_t instantiate
Instantiation function.
Definition: xlat_priv.h:69
size_t thread_inst_size
Size of the thread instance data to pre-allocate.
Definition: xlat_priv.h:79
xlat_detach_t detach
Destructor for when xlat instances are freed.
Definition: xlat_priv.h:70
void * thread_uctx
uctx to pass to instantiation functions.
Definition: xlat_priv.h:80
call_env_method_t const * call_env_method
Optional tmpl expansions performed before calling the xlat.
Definition: xlat_priv.h:91
size_t inst_size
Size of instance data to pre-allocate.
Definition: xlat_priv.h:72
xlat_arg_parser_t const * args
Definition of args consumed.
Definition: xlat_priv.h:89
xlat_resolve_t resolve
function to call when resolving
Definition: xlat_priv.h:83
module_inst_ctx_t const * mctx
Original module instantiation ctx if this xlat was registered by a module.
Definition: xlat_priv.h:66
xlat_thread_instantiate_t thread_instantiate
Thread instantiation function.
Definition: xlat_priv.h:75
char const * inst_type
C type of instance structure.
Definition: xlat_priv.h:71
xlat_input_type_t input_type
Type of input used.
Definition: xlat_priv.h:88
fr_value_box_safe_for_t return_safe_for
Escaped value to set in output boxes.
Definition: xlat_priv.h:95
xlat_thread_detach_t thread_detach
Destructor for when xlat thread instance data is freed.
Definition: xlat_priv.h:76
xlat_purify_t purify
function to call when purifying the node.
Definition: xlat_priv.h:84
xlat_flags_t flags
various flags
Definition: xlat_priv.h:86
xlat_print_t print
function to call when printing
Definition: xlat_priv.h:82
void * uctx
uctx to pass to instantiation functions.
Definition: xlat_priv.h:73