The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
module_rlm.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: 22ffc9b68764c9a19e091f3c27f7fec3464c5cd6 $
19 *
20 * @file src/lib/server/module_rlm.c
21 * @brief Defines functions for rlm module (re-)initialisation.
22 *
23 * @copyright 2003,2006,2016 The FreeRADIUS server project
24 * @copyright 2016,2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25 * @copyright 2000 Alan DeKok (aland@freeradius.org)
26 * @copyright 2000 Alan Curry (pacman@world.std.com)
27 */
28
29RCSID("$Id: 22ffc9b68764c9a19e091f3c27f7fec3464c5cd6 $")
30
31#include <freeradius-devel/server/cf_file.h>
32
33#include <freeradius-devel/server/global_lib.h>
34#include <freeradius-devel/server/modpriv.h>
35#include <freeradius-devel/server/module_rlm.h>
36#include <freeradius-devel/server/pair.h>
37
38#include <freeradius-devel/util/atexit.h>
39
40#include <freeradius-devel/unlang/compile.h>
41
42#include <freeradius-devel/unlang/xlat_func.h>
43#include <freeradius-devel/unlang/xlat_redundant.h>
44
45
46/** Lookup virtual module by name
47 */
49
50typedef struct {
51 fr_rb_node_t name_node; //!< Entry in the name tree.
52 char const *name; //!< module name
53 CONF_SECTION *cs; //!< CONF_SECTION where it is defined
56
57/** Compare virtual modules by name
58 */
59static int8_t module_rlm_virtual_name_cmp(void const *one, void const *two)
60{
61 module_rlm_virtual_t const *a = one;
62 module_rlm_virtual_t const *b = two;
63 int ret;
64
65 ret = strcmp(a->name, b->name);
66 return CMP(ret, 0);
67}
68
69/** Global module list for all backend modules
70 *
71 */
73
74/** Runtime instantiated list
75 *
76 */
78
79/** Print information on all loaded modules
80 *
81 */
86
87/** Initialise a module specific exfile handle
88 *
89 * @see exfile_init
90 *
91 * @param[in] ctx to bind the lifetime of the exfile handle to.
92 * @param[in] module section.
93 * @param[in] max_entries Max file descriptors to cache, and manage locks for.
94 * @param[in] max_idle Maximum time a file descriptor can be idle before it's closed.
95 * @param[in] locking Whether or not to lock the files.
96 * @param[in] triggers Should triggers be enabled.
97 * @param[in] trigger_prefix if NULL will be set automatically from the module CONF_SECTION.
98 * @param[in] trigger_args to make available in any triggers executed by the connection pool.
99 * @return
100 * - New connection pool.
101 * - NULL on error.
102 */
104 CONF_SECTION *module,
105 uint32_t max_entries,
106 fr_time_delta_t max_idle,
107 bool locking,
108 bool triggers,
109 char const *trigger_prefix,
110 fr_pair_list_t *trigger_args)
111{
112 char trigger_prefix_buff[128];
113 bool prefix_set = trigger_prefix ? true : false;
114 exfile_t *handle;
115
116 if (!trigger_prefix) {
117 snprintf(trigger_prefix_buff, sizeof(trigger_prefix_buff), "modules.%s.file", cf_section_name1(module));
118 trigger_prefix = trigger_prefix_buff;
119 }
120
121 handle = exfile_init(ctx, max_entries, max_idle, locking);
122 if (!handle) return NULL;
123
124 if (triggers) exfile_enable_triggers(handle, prefix_set ? module : cf_section_find(module, "file", NULL),
125 trigger_prefix, trigger_args);
126
127 return handle;
128}
129
130/** Resolve polymorphic item's from a module's #CONF_SECTION to a subsection in another module
131 *
132 * This allows certain module sections to reference module sections in other instances
133 * of the same module and share #CONF_DATA associated with them.
134 *
135 * @verbatim
136 example {
137 data {
138 ...
139 }
140 }
141
142 example inst {
143 data = example
144 }
145 * @endverbatim
146 *
147 * @param[out] out where to write the pointer to a module's config section. May be NULL on success,
148 * indicating the config item was not found within the module #CONF_SECTION
149 * or the chain of module references was followed and the module at the end of the chain
150 * did not a subsection.
151 * @param[in] module #CONF_SECTION.
152 * @param[in] name of the polymorphic sub-section.
153 * @return
154 * - 0 on success with referenced section.
155 * - 1 on success with local section.
156 * - -1 on failure.
157 */
159{
160 CONF_PAIR *cp;
161 CONF_SECTION *cs;
162 CONF_DATA const *cd;
163
164
166 char const *inst_name;
167
168#define FIND_SIBLING_CF_KEY "find_sibling"
169
170 *out = NULL;
171
172 /*
173 * Is a real section (not referencing sibling module).
174 */
175 cs = cf_section_find(module, name, NULL);
176 if (cs) {
177 *out = cs;
178
179 return 0;
180 }
181
182 /*
183 * Item omitted completely from module config.
184 */
185 cp = cf_pair_find(module, name);
186 if (!cp) return 0;
187
189 cf_log_err(cp, "Module reference loop found");
190
191 return -1;
192 }
193 cd = cf_data_add(module, module, FIND_SIBLING_CF_KEY, false);
194
195 /*
196 * Item found, resolve it to a module instance.
197 * This triggers module loading, so we don't have
198 * instantiation order issues.
199 */
200 inst_name = cf_pair_value(cp);
201 mi = module_instance_by_name(rlm_modules_static, NULL, inst_name);
202 if (!mi) {
203 cf_log_err(cp, "Unknown module instance \"%s\"", inst_name);
204
205 return -1;
206 }
207
209 CONF_SECTION *parent = module;
210
211 /*
212 * Find the root of the config...
213 */
214 do {
215 CONF_SECTION *tmp;
216
218 if (!tmp) break;
219
220 parent = tmp;
221 } while (true);
222
223 if (unlikely(module_instantiate(module_instance_by_name(rlm_modules_static, NULL, inst_name)) < 0)) return -1;
224 }
225
226 /*
227 * Remove the config data we added for loop
228 * detection.
229 */
230 cf_data_remove_by_data(module, cd);
231
232 /*
233 * Check the module instances are of the same type.
234 */
235 if (strcmp(cf_section_name1(mi->conf), cf_section_name1(module)) != 0) {
236 cf_log_err(cp, "Referenced module is a rlm_%s instance, must be a rlm_%s instance",
238
239 return -1;
240 }
241
242 *out = cf_section_find(mi->conf, name, NULL);
243
244 return 1;
245}
246
248 char const *name, xlat_func_t func, fr_type_t return_type)
249{
250 module_instance_t *mi = mctx->mi;
251 module_rlm_instance_t *mri = talloc_get_type_abort(mi->uctx, module_rlm_instance_t);
253 xlat_t *x;
254 char inst_name[256];
255
256 fr_assert_msg(name != mctx->mi->name, "`name` must not be the same as the module "
257 "instance name. Pass a NULL `name` arg if this is required");
258
259 if (!name) {
260 name = mctx->mi->name;
261 } else {
262 if ((size_t)snprintf(inst_name, sizeof(inst_name), "%s.%s", mctx->mi->name, name) >= sizeof(inst_name)) {
263 ERROR("%s: Instance name too long", __FUNCTION__);
264 return NULL;
265 }
266 name = inst_name;
267 }
268
269 x = xlat_func_register(ctx, name, func, return_type);
270 if (unlikely(x == NULL)) return NULL;
271
272 xlat_mctx_set(x, mctx);
273
274 MEM(mrx = talloc(mi, module_rlm_xlat_t));
275 mrx->xlat = x;
276 mrx->mi = mi;
277
278 fr_dlist_insert_tail(&mri->xlats, mrx);
279
280 return x;
281}
282
283/** Initialise a module specific connection pool
284 *
285 * @see fr_pool_init
286 *
287 * @param[in] module section.
288 * @param[in] opaque data pointer to pass to callbacks.
289 * @param[in] c Callback to create new connections.
290 * @param[in] a Callback to check the status of connections.
291 * @param[in] log_prefix override, if NULL will be set automatically from the module CONF_SECTION.
292 * @param[in] trigger_prefix if NULL will be set automatically from the module CONF_SECTION.
293 * @param[in] trigger_args to make available in any triggers executed by the connection pool.
294 * @return
295 * - New connection pool.
296 * - NULL on error.
297 */
299 void *opaque,
302 char const *log_prefix,
303 char const *trigger_prefix,
304 fr_pair_list_t *trigger_args)
305{
306 CONF_SECTION *cs, *mycs;
307 char log_prefix_buff[128];
308 char trigger_prefix_buff[128];
309
310 fr_pool_t *pool;
311 char const *cs_name1, *cs_name2;
312
313 int ret;
314
315#define parent_name(_x) cf_section_name(cf_item_to_section(cf_parent(_x)))
316
317 cs_name1 = cf_section_name1(module);
318 cs_name2 = cf_section_name2(module);
319 if (!cs_name2) cs_name2 = cs_name1;
320
321 if (!trigger_prefix) {
322 snprintf(trigger_prefix_buff, sizeof(trigger_prefix_buff), "modules.%s.pool", cs_name1);
323 trigger_prefix = trigger_prefix_buff;
324 }
325
326 if (!log_prefix) {
327 snprintf(log_prefix_buff, sizeof(log_prefix_buff), "rlm_%s (%s)", cs_name1, cs_name2);
328 log_prefix = log_prefix_buff;
329 }
330
331 /*
332 * Get sibling's pool config section
333 */
334 ret = module_rlm_sibling_section_find(&cs, module, "pool");
335 switch (ret) {
336 case -1:
337 return NULL;
338
339 case 1:
340 DEBUG4("%s: Using pool section from \"%s\"", log_prefix, parent_name(cs));
341 break;
342
343 case 0:
344 DEBUG4("%s: Using local pool section", log_prefix);
345 break;
346 }
347
348 /*
349 * Get our pool config section
350 */
351 mycs = cf_section_find(module, "pool", NULL);
352 if (!mycs) {
353 DEBUG4("%s: Adding pool section to config item \"%s\" to store pool references", log_prefix,
354 cf_section_name(module));
355
356 mycs = cf_section_alloc(module, module, "pool", NULL);
357 }
358
359 /*
360 * Sibling didn't have a pool config section
361 * Use our own local pool.
362 */
363 if (!cs) {
364 DEBUG4("%s: \"%s.pool\" section not found, using \"%s.pool\"", log_prefix,
365 parent_name(cs), parent_name(mycs));
366 cs = mycs;
367 }
368
369 /*
370 * If fr_pool_init has already been called
371 * for this config section, reuse the previous instance.
372 *
373 * This allows modules to pass in the config sections
374 * they would like to use the connection pool from.
375 */
376 pool = cf_data_value(cf_data_find(cs, fr_pool_t, NULL));
377 if (!pool) {
378 DEBUG4("%s: No pool reference found for config item \"%s.pool\"", log_prefix, parent_name(cs));
379 pool = fr_pool_init(cs, cs, opaque, c, a, log_prefix);
380 if (!pool) return NULL;
381
382 fr_pool_enable_triggers(pool, trigger_prefix, trigger_args);
383
384 if (fr_pool_start(pool) < 0) {
385 ERROR("%s: Starting initial connections failed", log_prefix);
386 return NULL;
387 }
388
389 DEBUG4("%s: Adding pool reference %p to config item \"%s.pool\"", log_prefix, pool, parent_name(cs));
390 cf_data_add(cs, pool, NULL, false);
391 return pool;
392 }
393 fr_pool_ref(pool);
394
395 DEBUG4("%s: Found pool reference %p in config item \"%s.pool\"", log_prefix, pool, parent_name(cs));
396
397 /*
398 * We're reusing pool data add it to our local config
399 * section. This allows other modules to transitively
400 * reuse a pool through this module.
401 */
402 if (mycs != cs) {
403 DEBUG4("%s: Copying pool reference %p from config item \"%s.pool\" to config item \"%s.pool\"",
404 log_prefix, pool, parent_name(cs), parent_name(mycs));
405 cf_data_add(mycs, pool, NULL, false);
406 }
407
408 return pool;
409}
410
411/** Set the next section type if it's not already set
412 *
413 * @param[in] request The current request.
414 * @param[in] type_da to use. Usually attr_auth_type.
415 * @param[in] enumv Enumeration value of the specified type_da.
416 */
418{
419 fr_pair_t *vp;
420
421 switch (pair_update_control(&vp, type_da)) {
422 case 0:
423 if (unlikely(fr_value_box_copy(vp, &vp->data, enumv->value) < 0)) {
424 fr_strerror_printf("Failed to set control.%pP to %s", vp, enumv->name);
425 return false;
426 }
427 vp->data.enumv = vp->da; /* So we get the correct string alias */
428 RDEBUG2("Setting control.%pP", vp);
429 return true;
430
431 case 1:
432 RDEBUG2("control.%s already set. Not setting to %s", vp->da->name, enumv->name);
433 return false;
434
435 default:
436 return false;
437 }
438}
439
440/** Iterate over an array of named module methods, looking for matches
441 *
442 * @param[in] mmg A structure containing a terminated array of
443 * module method bindings. pre-sorted using #section_name_cmp
444 * with name2 sublists populated.
445 * @param[in] section name1 of the method being called can be one of the following:
446 * - An itenfier.
447 * - CF_IDENT_ANY if the method is a wildcard.
448 * name2 of the method being called can be one of the following:
449 * - An itenfier.
450 * - NULL to match section names with only a name1.
451 * - CF_IDENT_ANY if the method is a wildcard.
452 * @return
453 * - The module_method_name_t on success.
454 * - NULL on not found.
455 */
456static CC_HINT(nonnull)
458{
459 module_method_group_t const *mmg_p = mmg;
461
462 while (mmg_p) {
463 /*
464 * This could potentially be improved by using a binary search
465 * but given the small number of items, reduced branches and
466 * sequential access just scanning the list, it's probably not
467 * worth it.
468 */
469 for (p = mmg_p->bindings; p->section; p++) {
470 switch (section_name_match(p->section, section)) {
471 case 1: /* match */
472 return p;
473
474 case -1: /* name1 didn't match, skip to the end of the sub-list */
475 p = fr_dlist_tail(&p->same_name1);
476 break;
477
478 case 0: /* name1 did match - see if we can find a matching name2 */
479 {
480 fr_dlist_head_t const *same_name1 = &p->same_name1;
481
482 while ((p = fr_dlist_next(same_name1, p))) {
483 if (section_name2_match(p->section, section)) return p;
484 }
485 p = fr_dlist_tail(same_name1);
486 }
487 break;
488 }
489#ifdef __clang_analyzer__
490 /* Will never be NULL, worse case, p doesn't change*/
491 if (!p) break;
492#endif
493 }
494
495 /*
496 * Failed to match, search the next deepest group in the chain.
497 */
498 mmg_p = mmg_p->next;
499 }
500
501 return NULL;
502}
503
504/** Dump the available bindings for the module into the strerror stack
505 *
506 * @note Methods from _all_ linked module method groups will be pushed onto the error stack.
507 *
508 * @param[in] mmg module method group to evaluate.
509 */
511{
512 module_method_group_t const *mmg_p = mmg;
513 module_method_binding_t const *mmb_p;
514 bool first = true;
515
516 while (mmg_p) {
517 mmb_p = mmg_p->bindings;
518
519 if (!mmb_p || !mmb_p[0].section) goto next;
520
521 if (first) {
522 fr_strerror_const_push("Available methods are:");
523 first = false;
524 }
525
526 for (; mmb_p->section; mmb_p++) {
527 char const *name1 = section_name_str(mmb_p->section->name1);
528 char const *name2 = section_name_str(mmb_p->section->name2);
529
530 fr_strerror_printf_push(" %s%s%s",
531 name1, name2 ? "." : "", name2 ? name2 : "");
532 }
533 next:
534 mmg_p = mmg_p->next;
535 }
536
537 if (first) {
538 fr_strerror_const_push("No methods available");
539 }
540}
541
542/** Find an existing module instance and verify it implements the specified method
543 *
544 * Extracts the method from the module name where the format is @verbatim <module>[.<method1>[.<method2>]] @endverbatim
545 * and ensures the module implements the specified method.
546 *
547 * @param[in] ctx to allocate the dynamic module key tmpl from.
548 * @param[out] mmc_out the result from resolving the module method,
549 * plus the key tmpl for dynamic modules.
550 * This is not allocated from the ctx to save the runtime
551 * dereference.
552 * @param[in] vs Virtual server to search for alternative module names in.
553 * @param[in] section Section name containing the module call.
554 * @param[in] name The module method call i.e. module[<key>][.<method>]
555 * @param[in] t_rules for resolving the dynamic module key.
556 * @return
557 * - The module instance on success.
558 * - NULL on not found
559 *
560 * If the module exists but the method doesn't exist, then `method` is set to NULL.
561 */
563 virtual_server_t const *vs, section_name_t const *section, fr_sbuff_t *name,
564 tmpl_rules_t const *t_rules)
565{
566 fr_sbuff_term_t const *dyn_tt = &FR_SBUFF_TERMS(
567 L(""),
568 L("\t"),
569 L("\n"),
570 L(" "),
571 L("[")
572 );
573
574 fr_sbuff_term_t const *elem_tt = &FR_SBUFF_TERMS(
575 L(""),
576 L("\t"),
577 L("\n"),
578 L(" "),
579 L(".")
580 );
581
582 fr_sbuff_t *elem1;
584 module_method_call_t mmc_tmp;
585 module_method_binding_t const *mmb;
586
587 fr_sbuff_marker_t meth_start;
588
589 fr_slen_t slen;
590 fr_sbuff_t our_name = FR_SBUFF(name);
591
592 mmc = mmc_out ? mmc_out : &mmc_tmp;
593 if (mmc_out) memset(mmc_out, 0, sizeof(*mmc_out));
594
595 /*
596 * Advance until the start of the dynamic selector
597 * (if it exists).
598 */
599 if (fr_sbuff_adv_until(&our_name, SIZE_MAX, dyn_tt, '\0') == 0) {
600 fr_strerror_printf("Invalid module method name");
601 return fr_sbuff_error(&our_name);
602 }
603
605
606 /*
607 * If the method string contains a '['
608 *
609 * Search for a dynamic module method, e.g. `elem1[<key>]`.
610 */
611 if (fr_sbuff_is_char(&our_name, '[')) {
612 fr_sbuff_marker_t end, s_end;
613 fr_sbuff_marker(&end, &our_name);
614
615 slen = tmpl_afrom_substr(ctx, &mmc->key, &our_name, T_BARE_WORD, NULL, t_rules);
616 if (slen < 0) {
617 fr_strerror_const_push("Invalid dynamic module selector expression");
618 talloc_free(mmc);
619 return slen;
620 }
621
622 if (!fr_sbuff_is_char(&our_name, ']')) {
623 fr_strerror_const_push("Missing terminating ']' for dynamic module selector");
624 error:
625 talloc_free(mmc);
626 return fr_sbuff_error(&our_name);
627 }
628 fr_sbuff_marker(&s_end, &our_name);
629
630 fr_sbuff_set_to_start(&our_name);
631 slen = fr_sbuff_out_bstrncpy(elem1, &our_name, fr_sbuff_ahead(&end));
632 if (slen < 0) {
633 fr_strerror_const("Module method string too long");
634 goto error;
635 }
636 mmc->mi = module_instance_by_name(rlm_modules_dynamic, NULL, elem1->start);
637 if (!mmc->mi) {
638 fr_strerror_printf("No such dynamic module '%s'", elem1->start);
639 goto error;
640 }
642
643 fr_sbuff_set(&our_name, &s_end);
644 fr_sbuff_advance(&our_name, 1); /* Skip the ']' */
645 /*
646 * With elem1.elem2.elem3
647 *
648 * Search for a static module matching one of the following:
649 *
650 * - elem1.elem2.elem3
651 * - elem1.elem2
652 * - elem1
653 */
654 } else {
655 char *p;
656
657 fr_sbuff_set_to_start(&our_name);
658
659 slen = fr_sbuff_out_bstrncpy_until(elem1, &our_name, SIZE_MAX, dyn_tt, NULL);
660 if (slen == 0) {
661 fr_strerror_const("Invalid module name");
662 goto error;
663 }
664 if (slen < 0) {
665 fr_strerror_const("Module method string too long");
666 goto error;
667 }
668
669 /*
670 * Now we have a mutable buffer, we can start chopping
671 * it up to find the module.
672 */
673 for (;;) {
674 mmc->mi = (module_instance_t *)module_rlm_static_by_name(NULL, elem1->start);
675 if (mmc->mi) {
677 break; /* Done */
678 }
679
680 p = strrchr(elem1->start, '.');
681 if (!p) break; /* No more '.' */
682 *p = '\0'; /* Chop off the last '.' */
683 }
684
685 if (!mmc->mi) {
686 fr_strerror_printf("No such module '%pV'", fr_box_strvalue_len(our_name.start, slen));
687 return -1;
688 }
689
690 fr_sbuff_set_to_start(&our_name);
691 fr_sbuff_advance(&our_name, strlen(elem1->start)); /* Advance past the module name */
692 if (fr_sbuff_is_char(&our_name, '.')) {
693 fr_sbuff_advance(&our_name, 1); /* Static module method, search directly */
694 } else {
695 fr_sbuff_marker(&meth_start, &our_name); /* for the errors... */
696 goto by_section; /* Get the method dynamically from the section*/
697 }
698 }
699
700 /*
701 * For both cases, the buffer should be pointing
702 * at the start of the method string.
703 */
704 fr_sbuff_marker(&meth_start, &our_name);
705
706 /*
707 * If a module method was provided, search for it in the named
708 * methods provided by the module.
709 *
710 * The method name should be either:
711 *
712 * - name1
713 * - name1.name2
714 */
715 {
716 section_name_t method;
717 fr_sbuff_t *elem2;
718
719 fr_sbuff_set_to_start(elem1); /* May have used this already for module lookups */
720
721 slen = fr_sbuff_out_bstrncpy_until(elem1, &our_name, SIZE_MAX, elem_tt, NULL);
722 if (slen < 0) {
723 fr_strerror_const("Module method string too long");
724 return fr_sbuff_error(&our_name);
725 }
726 if (slen == 0) goto by_section; /* This works for both dynamic and static modules */
727
729
730 if (fr_sbuff_is_char(&our_name, '.')) {
731 fr_sbuff_advance(&our_name, 1);
732 if (fr_sbuff_out_bstrncpy_until(elem2, &our_name, SIZE_MAX,
733 elem_tt, NULL) == MODULE_INSTANCE_LEN_MAX) {
734 fr_strerror_const("Module method string too long");
735 goto error;
736 }
737 }
738
739 method = (section_name_t) {
740 .name1 = elem1->start,
741 .name2 = fr_sbuff_used(elem2) ? elem2->start : NULL
742 };
743
744 mmb = module_binding_find(&mmc->rlm->method_group, &method);
745 if (!mmb) {
746 fr_strerror_printf("Module \"%s\" does not have method %s%s%s",
747 mmc->mi->name,
748 method.name1,
749 method.name2 ? "." : "",
750 method.name2 ? method.name2 : ""
751 );
752
754 return fr_sbuff_error(&meth_start);
755 }
756 mmc->mmb = *mmb; /* For locality of reference and fewer derefs */
757 if (mmc_out) section_name_dup(ctx, &mmc->asked, &method);
758
759 return fr_sbuff_set(name, &our_name);
760 }
761
762by_section:
763 /*
764 * First look for the section name in the module's
765 * bindings. If that fails, look for the alt
766 * section names from the virtual server section.
767 *
768 * If that fails, we're done.
769 */
770 mmb = module_binding_find(&mmc->rlm->method_group, section);
771 if (!mmb) {
772 section_name_t const **alt_p = virtual_server_section_methods(vs, section);
773 if (alt_p) {
774 for (; *alt_p; alt_p++) {
775 mmb = module_binding_find(&mmc->rlm->method_group, *alt_p);
776 if (mmb) {
777 if (mmc_out) section_name_dup(ctx, &mmc->asked, *alt_p);
778 break;
779 }
780 }
781 }
782 } else {
783 if (mmc_out) section_name_dup(ctx, &mmc->asked, section);
784 }
785 if (!mmb) {
786 fr_strerror_printf("Module \"%s\" has no method for section %s %s { ... }, i.e. %s%s%s",
787 mmc->mi->name,
788 section->name1,
789 section->name2 ? section->name2 : "",
790 section->name1,
791 section->name2 ? "." : "",
792 section->name2 ? section->name2 : ""
793 );
795
796 return fr_sbuff_error(&meth_start);
797 }
798 mmc->mmb = *mmb; /* For locality of reference and fewer derefs */
799
800 return fr_sbuff_set(name, &our_name);
801}
802
804{
806
809 .name = asked_name,
810 });
811 if (!inst) return NULL;
812
813 return inst->cs;
814}
815
820
825
826/** Create a virtual module.
827 *
828 * @param[in] cs that defines the virtual module.
829 * @return
830 * - 0 on success.
831 * - -1 on failure.
832 */
834{
835 char const *name;
836 bool all_same;
837 CONF_ITEM *sub_ci = NULL;
838 CONF_PAIR *cp;
841
843
844 /*
845 * Groups, etc. must have a name.
846 */
847 if ((strcmp(name, "group") == 0) ||
848 (strcmp(name, "redundant") == 0) ||
849 (strcmp(name, "redundant-load-balance") == 0) ||
850 (strcmp(name, "load-balance") == 0)) {
852 if (!name) {
853 cf_log_err(cs, "Keyword module must have a second name");
854 return -1;
855 }
856
857 /*
858 * name2 was already checked in modules_rlm_bootstrap()
859 */
861 } else {
862 cf_log_err(cs, "Module names cannot be unlang keywords '%s'", name);
863 return -1;
864 }
865
866 /*
867 * Ensure that the module doesn't exist.
868 */
870 if (mi) {
871 ERROR("Duplicate module \"%s\" in file %s[%d] and file %s[%d]",
872 name,
873 cf_filename(cs),
874 cf_lineno(cs),
875 cf_filename(mi->conf),
876 cf_lineno(mi->conf));
877 return -1;
878 }
879
880 /*
881 * Don't bother registering redundant xlats for a simple "group".
882 */
883 all_same = (strcmp(cf_section_name1(cs), "group") != 0);
884
885 {
886 module_t const *last = NULL;
887
888 /*
889 * Ensure that the modules we reference here exist.
890 */
891 while ((sub_ci = cf_item_next(cs, sub_ci))) {
892 if (cf_item_is_pair(sub_ci)) {
893 cp = cf_item_to_pair(sub_ci);
894 if (cf_pair_value(cp)) {
895 cf_log_err(sub_ci, "Cannot set return codes in a %s block", cf_section_name1(cs));
896 return -1;
897 }
898
900 if (!mi) {
901 cf_log_perr(sub_ci, "Failed resolving module reference '%s' in %s block",
903 return -1;
904 }
905
906 if (all_same) {
907 if (!last) {
908 last = mi->exported;
909 } else if (last != mi->exported) {
910 last = NULL;
911 all_same = false;
912 }
913 }
914 } else {
915 all_same = false;
916 }
917
918 /*
919 * Don't check subsections for now. That check
920 * happens later in the unlang compiler.
921 */
922 } /* loop over things in a virtual module section */
923 }
924
925 inst = talloc_zero(cs, module_rlm_virtual_t);
926 if (!inst) return -1;
927
928 inst->cs = cs;
929 MEM(inst->name = talloc_strdup(inst, name));
930 inst->all_same = all_same;
931
934 return -1;
935 }
936
937 return 0;
938}
939
940/** Generic conf_parser_t func for loading drivers
941 *
942 */
943int module_rlm_submodule_parse(TALLOC_CTX *ctx, void *out, void *parent,
944 CONF_ITEM *ci, conf_parser_t const *rule)
945{
946 conf_parser_t our_rule = *rule;
947
948 our_rule.uctx = &rlm_modules_static;
949
950 return module_submodule_parse(ctx, out, parent, ci, &our_rule);
951}
952
953/** Frees thread-specific data for all registered backend modules
954 *
955 */
960
961/** Allocates thread-specific data for all registered backend modules
962 *
963 * @param[in] ctx To allocate any thread-specific data in.
964 * @param[in] el to register events.
965 * @return
966 * - 0 if all modules were instantiated successfully.
967 * - -1 if a module failed instantiation.
968 */
973
974/** Performs the instantiation phase for all backend modules
975 *
976 * @return
977 * - 0 if all modules were instantiated successfully.
978 * - -1 if a module failed instantiation.
979 */
984
985/** Compare the section names of two module_method_binding_t structures
986 */
987static int8_t binding_name_cmp(void const *one, void const *two)
988{
989 module_method_binding_t const *a = one;
990 module_method_binding_t const *b = two;
991
992 return section_name_cmp(a->section, b->section);
993}
994
996{
997 module_method_binding_t *p, *srt_p;
998 fr_dlist_head_t bindings;
999 bool in_order = true;
1000
1001 /*
1002 * Not all modules export module method bindings
1003 */
1004 if (!group || !group->bindings || group->validated) return 0;
1005
1006 fr_dlist_init(&bindings, module_method_binding_t, entry);
1007
1008 for (p = group->bindings; p->section; p++) {
1010 "First section identifier can't be NULL")) return -1;
1012 "Section identifiers can't both be null")) return -1;
1013
1014 /*
1015 * All the bindings go in a list so we can sort them
1016 * and produce the list in the correct order.
1017 */
1018 fr_dlist_insert_tail(&bindings, p);
1019 }
1020
1021 fr_dlist_sort(&bindings, binding_name_cmp);
1022
1023 /*
1024 * Iterate over the sorted list of bindings,
1025 * and the original list, to ensure they're
1026 * in the correct order.
1027 */
1028 for (srt_p = fr_dlist_head(&bindings), p = group->bindings;
1029 srt_p;
1030 srt_p = fr_dlist_next(&bindings, srt_p), p++) {
1031 if (p != srt_p) {
1032 in_order = false;
1033 break;
1034 }
1035 }
1036
1037 /*
1038 * Rebuild the binding list in the correct order.
1039 */
1040 if (!in_order) {
1041 module_method_binding_t *ordered;
1042
1043 MEM(ordered = talloc_array(NULL, module_method_binding_t, fr_dlist_num_elements(&bindings)));
1044 for (srt_p = fr_dlist_head(&bindings), p = ordered;
1045 srt_p;
1046 srt_p = fr_dlist_next(&bindings, srt_p), p++) {
1047 *p = *srt_p;
1048 }
1049 memcpy(group->bindings, ordered, fr_dlist_num_elements(&bindings) * sizeof(*ordered));
1050 talloc_free(ordered);
1051 }
1052
1053 /*
1054 * Build the "skip" list of name1 entries
1055 */
1056 {
1057 module_method_binding_t *last_binding = NULL;
1058
1059 for (p = group->bindings; p->section; p++) {
1060 if (!last_binding ||
1061 (
1062 (last_binding->section->name1 != p->section->name1) &&
1063 (
1064 (last_binding->section->name1 == CF_IDENT_ANY) ||
1065 (p->section->name1 == CF_IDENT_ANY) ||
1066 (strcmp(last_binding->section->name1, p->section->name1) != 0)
1067 )
1068 )
1069 ) {
1071 last_binding = p;
1072 }
1073 fr_dlist_insert_tail(&last_binding->same_name1, p);
1074 }
1075 }
1076 group->validated = true;
1077
1078 return module_method_group_validate(group->next);
1079}
1080
1087
1088/** Allocate a rlm module instance
1089 *
1090 * These have extra space allocated to hold the dlist of associated xlats.
1091 *
1092 * @param[in] ml Module list to allocate from.
1093 * @param[in] parent Parent module instance.
1094 * @param[in] type Type of module instance.
1095 * @param[in] mod_name Name of the module.
1096 * @param[in] inst_name Name of the instance.
1097 * @param[in] init_state Initial state of the module instance.
1098 * @return
1099 * - The allocated module instance on success.
1100 * - NULL on failure.
1101 */
1102static inline CC_HINT(always_inline)
1105 dl_module_type_t type, char const *mod_name, char const *inst_name,
1106 module_instance_state_t init_state)
1107{
1110
1111 mi = module_instance_alloc(ml, parent, type, mod_name, inst_name, init_state);
1112 if (unlikely(mi == NULL)) return NULL;
1113
1114 MEM(mri = talloc(mi, module_rlm_instance_t));
1115 module_instance_uctx_set(mi, mri);
1116
1118
1119 return mi;
1120}
1121
1123{
1124 char const *name;
1125 char const *inst_name;
1126 module_instance_t *mi = NULL;
1127 CONF_SECTION *actions;
1128
1129 /*
1130 * name2 can't be a keyword
1131 */
1132 name = cf_section_name2(mod_conf);
1134 invalid_name:
1135 cf_log_err(mod_conf, "Module names cannot be unlang keywords '%s'", name);
1136 return -1;
1137 }
1138
1139 name = cf_section_name1(mod_conf);
1140
1141 /*
1142 * For now, ignore name1 which is a keyword.
1143 */
1145 if (!cf_section_name2(mod_conf)) {
1146 cf_log_err(mod_conf, "Missing second name at '%s'", name);
1147 return -1;
1148 }
1149 if (module_rlm_bootstrap_virtual(mod_conf) < 0) return -1;
1150 return 0;
1151 }
1152
1153 /*
1154 * Skip inline templates, and disallow "template { ... }"
1155 */
1156 if (strcmp(name, "template") == 0) {
1157 if (!cf_section_name2(mod_conf)) goto invalid_name;
1158 return 0;
1159 }
1160
1161 if (module_instance_name_from_conf(&inst_name, mod_conf) < 0) goto invalid_name;
1162
1163 mi = module_rlm_instance_alloc(ml, NULL, DL_MODULE_TYPE_MODULE, name, inst_name, 0);
1164 if (unlikely(mi == NULL)) {
1165 cf_log_perr(mod_conf, "Failed loading module");
1166 return -1;
1167 }
1168
1169 /*
1170 * First time we've loaded the dl module, so we need to
1171 * check the module methods to make sure they're ordered
1172 * correctly, and to add the "skip list" style name2
1173 * entries.
1174 */
1175 if ((mi->module->refs == 1) && (module_method_validate(mi) < 0)) {
1176 talloc_free(mi);
1177 return -1;
1178 }
1179
1180 if (module_instance_conf_parse(mi, mod_conf) < 0) {
1181 cf_log_perr(mod_conf, "Failed parsing module config");
1182 talloc_free(mi);
1183 return -1;
1184 }
1185
1186 /*
1187 * Compile the default "actions" subsection, which includes retries.
1188 */
1189 actions = cf_section_find(mod_conf, "actions", NULL);
1190 if (actions && unlang_compile_actions(&mi->actions, actions, (mi->exported->flags & MODULE_TYPE_RETRY) != 0)) {
1191 talloc_free(mi);
1192 return -1;
1193 }
1194
1195 return 0;
1196}
1197
1198/** Bootstrap modules and virtual modules
1199 *
1200 * Parse the module config sections, and load and call each module's init() function.
1201 *
1202 * @param[in] root of the server configuration.
1203 * @return
1204 * - 0 if all modules were bootstrapped successfully.
1205 * - -1 if a module/virtual module failed to bootstrap.
1206 */
1208{
1209 CONF_SECTION *cs, *modules, *static_cs, *dynamic_cs;
1212
1213 /*
1214 * Ensure any libraries the modules depend on are instantiated
1215 */
1217
1218 /*
1219 * Remember where the modules were stored.
1220 */
1221 modules = cf_section_find(root, "modules", NULL);
1222 if (!modules) {
1223 WARN("Cannot find a \"modules\" section in the configuration file!");
1224 return 0;
1225 }
1226
1227 static_cs = cf_section_find(modules, "static", NULL);
1228 if (!static_cs) {
1229 static_cs = cf_section_alloc(modules, NULL, "static", NULL);
1230 cf_section_foreach(modules, mod_cs) {
1231 CONF_ITEM *prev;
1232 char const *name1 = cf_section_name1(mod_cs);
1233
1234 /*
1235 * Skip over the dynamic section
1236 */
1237 if ((strcmp(name1, "dynamic") == 0) && !cf_section_name2(mod_cs)) continue;
1238
1239 /*
1240 * Ignore this section if it is commented out with a magic name.
1241 */
1242 if (*name1 == '-') continue;
1243
1244 /*
1245 * Move all modules which are not in
1246 * the dynamic section into the static
1247 * section for backwards compatibility.
1248 */
1249 prev = cf_item_remove(modules, mod_cs);
1250 cf_item_add(static_cs, mod_cs);
1251
1252 /*
1253 * Find the previous item that's a section
1254 */
1255 while (prev && !cf_item_is_section(prev)) prev = cf_item_prev(modules, prev);
1256
1257 /*
1258 * Resume iterating from that item
1259 */
1260 mod_cs = cf_item_to_section(prev);
1261 }
1262 cf_item_add(modules, static_cs);
1263 }
1264 DEBUG2("#### Bootstrapping static modules ####");
1265 cf_log_debug(modules, " modules {");
1266 cf_log_debug(modules, " static {");
1267 cf_section_foreach(static_cs, mod_conf) {
1268 if (module_conf_parse(rlm_modules_static, mod_conf) < 0) return -1;
1269 }
1270 cf_log_debug(modules, " } # static");
1271
1272 /*
1273 * Now we have a module tree, run bootstrap on all the modules.
1274 * This will bootstrap modules and then submodules.
1275 */
1276 if (unlikely(modules_bootstrap(rlm_modules_static) < 0)) return -1;
1277
1278 if (fr_command_register_hook(NULL, NULL, static_cs, module_cmd_list_table) < 0) {
1279 PERROR("Failed registering radmin commands for modules");
1280 return -1;
1281 }
1282
1283 /*
1284 * Build the configuration and parse dynamic modules
1285 */
1286 dynamic_cs = cf_section_find(modules, "dynamic", NULL);
1287 if (dynamic_cs) {
1288 DEBUG2("#### Bootstrapping dynamic modules ####");
1289 /*
1290 * Parse and then instantiate any dynamic modules configure
1291 */
1292 cf_log_debug(modules, " dynamic {");
1293 cf_section_foreach(dynamic_cs, mod_conf) {
1294 if (unlikely(module_conf_parse(rlm_modules_dynamic, mod_conf) < 0)) return -1;
1295 }
1296 cf_log_debug(modules, " } # dynamic");
1297 if (unlikely(modules_bootstrap(rlm_modules_dynamic) < 0)) return -1;
1298 cf_log_debug(modules, " } # modules");
1299 }
1300
1301 /*
1302 * Check for duplicate policies. They're treated as
1303 * modules, so we might as well check them here.
1304 */
1305 cs = cf_section_find(root, "policy", NULL);
1306 if (cs) {
1307 cf_section_foreach(cs, policy_cs) {
1308 CONF_SECTION *problemcs;
1309 char const *name1 = cf_section_name1(policy_cs);
1310
1311 if (unlang_compile_is_keyword(name1)) {
1312 cf_log_err(policy_cs, "Policy name '%s' cannot be an unlang keyword", name1);
1313 return -1;
1314 }
1315
1316 if (cf_section_name2(policy_cs)) {
1317 cf_log_err(policy_cs, "Policies cannot have two names");
1318 return -1;
1319 }
1320
1321 problemcs = cf_section_find_next(cs, policy_cs, name1, CF_IDENT_ANY);
1322 if (!problemcs) continue;
1323
1324 cf_log_err(problemcs, "Duplicate policy '%s' is forbidden.",
1325 cf_section_name1(policy_cs));
1326 return -1;
1327 }
1328 }
1329
1330 /*
1331 * Now that all of the xlat things have been registered,
1332 * register our redundant xlats. But only when all of
1333 * the items in such a section are the same.
1334 */
1336 vm;
1337 vm = fr_rb_iter_next_inorder(&iter)) {
1338 if (!vm->all_same) continue;
1339
1340 if (xlat_register_redundant(vm->cs) < 0) return -1;
1341 }
1342
1343 return 0;
1344}
1345
1346/** Cleanup all global structures
1347 *
1348 * Automatically called on exit.
1349 */
1351{
1352 if (talloc_free(rlm_modules_static) < 0) return -1;
1353 rlm_modules_static = NULL;
1354 if (talloc_free(module_rlm_virtual_name_tree) < 0) return -1;
1356
1357 return 0;
1358}
1359
1360static int _modules_rlm_free_atexit(UNUSED void *uctx)
1361{
1362 return modules_rlm_free();
1363}
1364
1365/** Initialise the module list structure
1366 *
1367 */
1369{
1372 module_list_mask_set(rlm_modules_dynamic, MODULE_INSTANCE_INSTANTIATED); /* Ensure we never instantiate dynamic modules */
1373
1377
1378 return 0;
1379}
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
Definition atexit.h:59
#define RCSID(id)
Definition build.h:485
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#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 unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:620
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:597
Internal data that is associated with a configuration section.
Definition cf_priv.h:125
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:631
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1750
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1426
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition cf_util.c:1196
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1048
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1565
#define cf_item_add(_parent, _child)
Definition cf_util.h:83
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:286
#define cf_lineno(_cf)
Definition cf_util.h:104
#define cf_section_foreach(_parent, _iter)
Definition cf_util.h:152
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:252
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:241
#define cf_data_remove_by_data(_cf, _cd)
Remove an item from a parent.
Definition cf_util.h:271
#define cf_item_prev(_parent, _curr)
Definition cf_util.h:95
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_item_remove(_parent, _child)
Definition cf_util.h:89
#define cf_item_next(_parent, _curr)
Definition cf_util.h:92
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:293
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#define cf_filename(_cf)
Definition cf_util.h:107
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:289
#define CF_IDENT_ANY
Definition cf_util.h:78
fr_command_register_hook_t fr_command_register_hook
Definition command.c:42
bool unlang_compile_is_keyword(const char *name)
Check if name is an unlang keyword.
Definition compile.c:2265
bool unlang_compile_actions(unlang_mod_actions_t *actions, CONF_SECTION *action_cs, bool module_retry)
Definition compile.c:1082
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
#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:202
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:148
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:250
char const * name
Enum name.
Definition dict.h:247
Value of an enumerated attribute.
Definition dict.h:246
dl_module_type_t
Definition dl_module.h:65
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
Definition dl_module.h:66
static void fr_dlist_sort(fr_dlist_head_t *list, fr_cmp_t cmp)
Sort a dlist using merge sort.
Definition dlist.h:1064
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:260
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
Definition dlist.h:486
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
Definition dlist.h:939
static void * fr_dlist_tail(fr_dlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
Definition dlist.h:531
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:378
#define fr_dlist_talloc_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:275
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition dlist.h:555
Head of a doubly linked list.
Definition dlist.h:51
exfile_t * exfile_init(TALLOC_CTX *ctx, uint32_t max_entries, fr_time_delta_t max_idle, bool locking)
Initialize a way for multiple threads to log to one or more files.
Definition exfile.c:168
void exfile_enable_triggers(exfile_t *ef, CONF_SECTION *conf, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Enable triggers for an exfiles handle.
Definition exfile.c:216
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
Definition global_lib.c:218
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG4(_fmt,...)
Definition log.h:267
talloc_free(reap)
Stores all information relating to an event list.
Definition event.c:377
static char const * mod_name(fr_listen_t *li)
Definition master.c:2889
fr_type_t
unsigned int uint32_t
size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
ssize_t fr_slen_t
fr_cmd_table_t module_cmd_list_table[]
Definition module.c:91
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 module_list_t * rlm_modules_dynamic
Runtime instantiated list.
Definition module_rlm.c:77
static int _modules_rlm_free_atexit(UNUSED void *uctx)
void modules_rlm_thread_detach(void)
Frees thread-specific data for all registered backend modules.
Definition module_rlm.c:956
int modules_rlm_bootstrap(CONF_SECTION *root)
Bootstrap modules and virtual modules.
static int module_rlm_bootstrap_virtual(CONF_SECTION *cs)
Create a virtual module.
Definition module_rlm.c:833
static int8_t binding_name_cmp(void const *one, void const *two)
Compare the section names of two module_method_binding_t structures.
Definition module_rlm.c:987
static module_method_binding_t const * module_binding_find(module_method_group_t const *mmg, section_name_t const *section)
Iterate over an array of named module methods, looking for matches.
Definition module_rlm.c:457
fr_slen_t module_rlm_by_name_and_method(TALLOC_CTX *ctx, module_method_call_t *mmc_out, virtual_server_t const *vs, section_name_t const *section, fr_sbuff_t *name, tmpl_rules_t const *t_rules)
Find an existing module instance and verify it implements the specified method.
Definition module_rlm.c:562
exfile_t * module_rlm_exfile_init(TALLOC_CTX *ctx, CONF_SECTION *module, uint32_t max_entries, fr_time_delta_t max_idle, bool locking, bool triggers, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific exfile handle.
Definition module_rlm.c:103
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:247
module_instance_t * module_rlm_dynamic_by_name(module_instance_t const *parent, char const *asked_name)
Definition module_rlm.c:816
char const * name
module name
Definition module_rlm.c:52
fr_rb_node_t name_node
Entry in the name tree.
Definition module_rlm.c:51
int module_rlm_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char const *name)
Resolve polymorphic item's from a module's CONF_SECTION to a subsection in another module.
Definition module_rlm.c:158
static int8_t module_rlm_virtual_name_cmp(void const *one, void const *two)
Compare virtual modules by name.
Definition module_rlm.c:59
void module_rlm_list_debug(void)
Print information on all loaded modules.
Definition module_rlm.c:82
static int module_method_validate(module_instance_t *mi)
static fr_rb_tree_t * module_rlm_virtual_name_tree
Lookup virtual module by name.
Definition module_rlm.c:48
int module_rlm_submodule_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic conf_parser_t func for loading drivers.
Definition module_rlm.c:943
module_instance_t * module_rlm_static_by_name(module_instance_t const *parent, char const *asked_name)
Definition module_rlm.c:821
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
Definition module_rlm.c:417
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
Definition module_rlm.c:298
static int module_conf_parse(module_list_t *ml, CONF_SECTION *mod_conf)
static void module_rlm_methods_to_strerror(module_method_group_t const *mmg)
Dump the available bindings for the module into the strerror stack.
Definition module_rlm.c:510
int modules_rlm_free(void)
Cleanup all global structures.
#define FIND_SIBLING_CF_KEY
int modules_rlm_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Allocates thread-specific data for all registered backend modules.
Definition module_rlm.c:969
static module_instance_t * module_rlm_instance_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name, module_instance_state_t init_state)
Allocate a rlm module instance.
#define parent_name(_x)
CONF_SECTION * module_rlm_virtual_by_name(char const *asked_name)
Definition module_rlm.c:803
static module_list_t * rlm_modules_static
Global module list for all backend modules.
Definition module_rlm.c:72
int modules_rlm_instantiate(void)
Performs the instantiation phase for all backend modules.
Definition module_rlm.c:980
int modules_rlm_init(void)
Initialise the module list structure.
static int module_method_group_validate(module_method_group_t *group)
Definition module_rlm.c:995
CONF_SECTION * cs
CONF_SECTION where it is defined.
Definition module_rlm.c:53
module_method_group_t method_group
named methods
Definition module_rlm.h:40
module_instance_t * mi
The module instance that registered the xlat.
Definition module_rlm.h:54
fr_dlist_head_t xlats
xlats registered to this module instance.
Definition module_rlm.h:44
module_instance_t * mi
The process modules also push module calls onto the stack for execution.
Definition module_rlm.h:63
xlat_t const * xlat
The xlat function.
Definition module_rlm.h:53
tmpl_t * key
Dynamic key, only set for dynamic modules.
Definition module_rlm.h:71
section_name_t asked
The actual <name1>.
Definition module_rlm.h:67
module_method_binding_t mmb
Method we're calling.
Definition module_rlm.h:70
module_rlm_t const * rlm
Cached module_rlm_t.
Definition module_rlm.h:66
static module_rlm_t * module_rlm_from_module(module_t *module)
Definition module_rlm.h:74
The output of module_rlm_by_name_and_method.
Definition module_rlm.h:62
An xlat function registered to a module.
Definition module_rlm.h:52
int fr_pool_start(fr_pool_t *pool)
Definition pool.c:1114
void fr_pool_ref(fr_pool_t *pool)
Increment pool reference by one.
Definition pool.c:1210
fr_pool_t * fr_pool_init(TALLOC_CTX *ctx, CONF_SECTION const *cs, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix)
Create a new connection pool.
Definition pool.c:965
void fr_pool_enable_triggers(fr_pool_t *pool, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Enable triggers for a connection pool.
Definition pool.c:931
A connection pool.
Definition pool.c:85
void *(* fr_pool_connection_create_t)(TALLOC_CTX *ctx, void *opaque, fr_time_delta_t timeout)
Create a new connection handle.
Definition pool.h:111
int(* fr_pool_connection_alive_t)(void *opaque, void *connection)
Check a connection handle is still viable.
Definition pool.h:126
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define DEBUG2(fmt,...)
Definition radclient.h:43
#define WARN(fmt,...)
Definition radclient.h:47
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_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_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:271
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
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
Definition sbuff.c:1880
size_t fr_sbuff_out_bstrncpy(fr_sbuff_t *out, fr_sbuff_t *in, size_t len)
Copy as many bytes as possible from a sbuff to a sbuff.
Definition sbuff.c:728
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:192
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define fr_sbuff_error(_sbuff_or_marker)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_ahead(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Set of terminal elements.
int8_t section_name_cmp(void const *one, void const *two)
Compare two sections.
Definition section.c:47
static int section_name2_match(section_name_t const *a, section_name_t const *b)
Definition section.h:60
static char const * section_name_str(char const *name)
Return a printable string for the section name.
Definition section.h:98
static int section_name_match(section_name_t const *a, section_name_t const *b)
Definition section.h:84
static void section_name_dup(TALLOC_CTX *ctx, section_name_t *dst, section_name_t const *src)
Definition section.h:105
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
Definition section.h:46
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
Definition section.h:45
Section name identifier.
Definition section.h:44
char const * name
Instance name e.g. user_database.
Definition module.h:355
@ MODULE_TYPE_RETRY
can handle retries
Definition module.h:51
module_flags_t flags
Flags that control how a module starts up and how a module is called.
Definition module.h:236
module_method_group_t * next
Next group in the list.
Definition module.h:168
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:349
module_instance_state_t state
What's been done with this module so far.
Definition module.h:348
unlang_mod_actions_t actions
default actions and retries.
Definition module.h:323
bool validated
Set to true by module_method_group_validate.
Definition module.h:167
#define MODULE_INSTANCE_LEN_MAX
The maximum size of a module instance.
Definition module.h:148
fr_dlist_head_t same_name1
List of bindings with the same name1.
Definition module.h:187
module_instance_state_t
What state the module instance is currently in.
Definition module.h:263
@ MODULE_INSTANCE_INSTANTIATED
Module instance has been bootstrapped and instantiated.
Definition module.h:266
void * uctx
Extra data passed to module_instance_alloc.
Definition module.h:359
module_method_binding_t * bindings
named methods
Definition module.h:165
section_name_t const * section
Identifier for a section.
Definition module.h:175
module_t * exported
Public module structure.
Definition module.h:296
Module instance data.
Definition module.h:285
A list of modules.
Definition module.h:405
Named methods exported by a module.
Definition module.h:174
A group of methods exported by a module or added as an overlay.
Definition module.h:164
Struct exported by a rlm_* module.
Definition module.h:203
#define pair_update_control(_attr, _da)
Return or allocate a fr_pair_t in the control list.
Definition pair.h:140
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
Definition module.c:615
module_list_type_t const module_list_type_thread_local
Callbacks for a thread local list.
Definition module.c:582
module_instance_t * module_instance_by_name(module_list_t const *ml, module_instance_t const *parent, char const *asked_name)
Find an existing module instance by its name and parent.
Definition module.c:897
void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
Set a new bootstrap/instantiate state for a list.
Definition module.c:1829
module_instance_t * module_instance_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name, module_instance_state_t init_state)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
Definition module.c:1645
fr_slen_t module_instance_name_from_conf(char const **name, CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
Definition module.c:729
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
Definition module.c:1003
int modules_thread_instantiate(TALLOC_CTX *ctx, module_list_t const *ml, fr_event_list_t *el)
Creates per-thread instance data for modules which need it.
Definition module.c:1154
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition module.c:1275
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
Definition module.c:1851
void module_instance_uctx_set(module_instance_t *mi, void *uctx)
Set the uctx pointer for a module instance.
Definition module.c:1613
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:528
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition module.c:1366
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
Definition module.c:1189
int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic callback for conf_parser_t to load a submodule.
Definition module.c:841
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition module.c:758
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
@ T_BARE_WORD
Definition token.h:120
static fr_event_list_t * el
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:232
static fr_slen_t parent
Definition pair.h:841
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4148
#define fr_box_strvalue_len(_val, _len)
Definition value.h:308
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1023
section_name_t const ** virtual_server_section_methods(virtual_server_t const *vs, section_name_t const *section)
Find the component for a section.
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:216
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:296
int xlat_register_redundant(CONF_SECTION *cs)
Registers a redundant xlat.