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: 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 
26 RCSID("$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 
33 static 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  */
44 static 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  */
69 int8_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  */
114 static 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  */
131 static 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  */
164 static 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  */
218 xlat_t *xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
219 {
220  xlat_t *c;
221  fr_sbuff_t in;
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);
236  fr_sbuff_adv_past_allowed(&in, SIZE_MAX, xlat_func_chars, NULL);
237  used = fr_sbuff_used(&in);
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  */
315 static 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;
405  x->internal = flags & XLAT_FUNC_FLAG_INTERNAL;
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  */
519 void 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 
541  c;
543  if (!c->mctx) continue;
544  if (c->mctx->mi != inst) continue;
545 
547  }
548 }
549 
550 int xlat_func_init(void)
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 
566 void xlat_func_free(void)
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: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:481
#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
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
fr_dcursor_iter_t iter
Definition: dcursor.h:147
#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 ERROR(fmt,...)
Definition: dhcpclient.c:41
static fr_slen_t in
Definition: dict.h:821
#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
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
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
Definition: radiusd.c:148
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:131
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition: rb.c:898
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:850
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
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#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
int fr_rb_replace(void **old, fr_rb_tree_t *tree, void const *data))
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
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:1302
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:1755
#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
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:445
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
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:105
@ XLAT_INPUT_ARGS
Ingests a number of arguments.
Definition: xlat.h:47
@ 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:112
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
bool impure_func
xlat contains an impure function
Definition: xlat.h:113
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: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
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
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_find(char const *in, ssize_t inlen)
Definition: xlat_func.c:79
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
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
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
xlat_t * xlat_func_find_module(module_inst_ctx_t const *mctx, char const *name)
Definition: xlat_func.c:182
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