The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
module.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: 76c3d70570975b481673ea23edb2b7d50e6c1175 $
19 *
20 * @file src/lib/server/module.c
21 * @brief Defines functions for module initialisation
22 *
23 * @copyright 2016,2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 * @copyright 2003,2006,2016 The FreeRADIUS server project
25 * @copyright 2000 Alan DeKok (aland@freeradius.org)
26 * @copyright 2000 Alan Curry (pacman@world.std.com)
27 */
28
29RCSID("$Id: 76c3d70570975b481673ea23edb2b7d50e6c1175 $")
30
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/server/module_rlm.h>
33#include <freeradius-devel/server/radmin.h>
34#include <freeradius-devel/unlang/xlat_func.h>
35
36#include <sys/mman.h>
37
39
40/** Heap of all lists/modules used to get a common index with mlg_thread->inst_list
41 */
43
44/** An array of thread-local module lists
45*
46* The indexes in this array are identical to module_list_global, allowing
47* O(1) lookups. Arrays are used here as there's no performance penalty
48* once they're populated.
49*/
51
52static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info);
53static int module_name_tab_expand(UNUSED TALLOC_CTX *talloc_ctx, UNUSED void *uctx, fr_cmd_info_t *info, int max_expansions, char const **expansions);
54static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info);
55static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info);
56static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info);
57
59 {
60 .parent = "show module",
61 .add_name = true,
62 .name = "status",
64 .help = "Show the status of a particular module.",
65 .read_only = true,
66 },
67
68 {
69 .parent = "show module",
70 .add_name = true,
71 .name = "config",
73 .help = "Show configuration for a module",
74 // @todo - do tab expand, by walking over the whole module list...
75 .read_only = true,
76 },
77
78 {
79 .parent = "set module",
80 .add_name = true,
81 .name = "status",
82 .syntax = "(alive|disallow|fail|reject|handled|invalid|notfound|noop|ok|updated)",
84 .help = "Change module status to fixed value.",
85 .read_only = false,
86 },
87
89};
90
92 {
93 .parent = "show",
94 .name = "module",
95 .help = "Show information about modules.",
96 .tab_expand = module_name_tab_expand,
97 .read_only = true,
98 },
99
100 // @todo - what if there's a module called "list" ?
101 {
102 .parent = "show module",
103 .name = "list",
104 .func = cmd_show_module_list,
105 .help = "Show the list of modules loaded in the server.",
106 .read_only = true,
107 },
108
109 {
110 .parent = "set",
111 .name = "module",
112 .help = "Change module settings.",
113 .tab_expand = module_name_tab_expand,
114 .read_only = false,
115 },
116
117
119};
120
121static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
122{
123 module_instance_t *mi = ctx;
124
125 fr_assert(mi->conf != NULL);
126
127 (void) cf_section_write(fp, mi->conf, 0);
128
129 return 0;
130}
131
132static int module_name_tab_expand(UNUSED TALLOC_CTX *talloc_ctx, UNUSED void *uctx,
133 fr_cmd_info_t *info, int max_expansions, char const **expansions)
134{
135 char const *text;
136 int count;
137
138 if (info->argc <= 0) return 0;
139
140 text = info->argv[info->argc - 1];
141 count = 0;
142
144 module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
145
146 if (count >= max_expansions) {
147 break;
148 }
149 if (fr_command_strncmp(text, mi->name)) {
150 expansions[count] = strdup(mi->name);
151 count++;
152 }
153 }}
154
155 return count;
156}
157
158static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info)
159{
161 module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
162
163 fprintf(fp, "\t%s\n", mi->name);
164 }}
165
166 return 0;
167}
168
169static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
170{
171 module_instance_t *mi = ctx;
172
173 if (!mi->force) {
174 fprintf(fp, "alive\n");
175 return 0;
176 }
177
178 fprintf(fp, "%s\n", fr_table_str_by_value(rcode_table, mi->code, "<invalid>"));
179
180 return 0;
181}
182
183static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
184{
185 module_instance_t *mi = ctx;
186 rlm_rcode_t rcode;
187
188 if (strcmp(info->argv[0], "alive") == 0) {
190 mi->force = false;
192 return 0;
193 }
194
196 if (rcode == RLM_MODULE_NOT_SET) {
197 fprintf(fp_err, "Unknown status '%s'\n", info->argv[0]);
198 return -1;
199 }
200
202 mi->code = rcode;
203 mi->force = true;
205
206 return 0;
207}
208
209/** Chars that are allowed in a module instance name
210 *
211 */
213 ['-'] = true, ['/'] = true, ['_'] = true, ['.'] = true,
214 ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true,
215 ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true,
216 ['A'] = true, ['B'] = true, ['C'] = true, ['D'] = true, ['E'] = true,
217 ['F'] = true, ['G'] = true, ['H'] = true, ['I'] = true, ['J'] = true,
218 ['K'] = true, ['L'] = true, ['M'] = true, ['N'] = true, ['O'] = true,
219 ['P'] = true, ['Q'] = true, ['R'] = true, ['S'] = true, ['T'] = true,
220 ['U'] = true, ['V'] = true, ['W'] = true, ['X'] = true, ['Y'] = true,
221 ['Z'] = true,
222 ['a'] = true, ['b'] = true, ['c'] = true, ['d'] = true, ['e'] = true,
223 ['f'] = true, ['g'] = true, ['h'] = true, ['i'] = true, ['j'] = true,
224 ['k'] = true, ['l'] = true, ['m'] = true, ['n'] = true, ['o'] = true,
225 ['p'] = true, ['q'] = true, ['r'] = true, ['s'] = true, ['t'] = true,
226 ['u'] = true, ['v'] = true, ['w'] = true, ['x'] = true, ['y'] = true,
227 ['z'] = true
228};
229
230/** dl module tracking
231 *
232 * This is used by all module lists, irrespecitve of their type, and is thread safe.
233 */
235
236/** Callback to initialise any global structures required for the module list
237 *
238 * @param[in] ml to initialise global data for.
239 * @return
240 * - 0 on success.
241 * - -1 on failure.
242 */
244
245/** Callback to free any global structures associated with the module list
246 *
247 * @param[in] ml to free.
248 */
250
251/** Callback to add data for a module
252 *
253 * @param[in] mi to add data for.
254 * Use mi->ml for the module list.
255 * Use mi->data to access the data.
256 * @return
257 * - 0 on success.
258 * - -1 on failure.
259 */
261
262/** Callback to del data for a module
263 *
264 * @param[in] mi to add data to (use mi->ml for the module list).
265 *
266 */
268
269/** Callback to initialise a list for thread-local data, called once per thread
270 *
271 * @param[in] ctx talloc context for thread-local data.
272 * May be modified by the init function if the
273 * module_thread_instance_t need to be parented
274 * by another ctx.
275 * @param[in] ml to initialise thread-local data for.
276 * @return
277 * - 0 on success.
278 * - -1 on failure.
279 */
280typedef int (*module_list_thread_init_t)(TALLOC_CTX **ctx, module_list_t const *ml);
281
282/** Callback to free thread-local structures, called once per thread as the thread is being destroyed
283 *
284 * @param[in] ml to free thread-local data for.
285 */
287
288/** Callback to add thread-local data for a module
289 *
290 * @param[in] ti to add data for.
291 * Use `ti->mi->ml` for the module list.
292 * Use `ti->mi` for the module instance.
293 * Use `ti->data` for the thread specific data.
294 * @return
295 * - 0 on success.
296 * - -1 on failure.
297 */
299
300/** Callback to remove thread-local data for a module
301 *
302 * @param[in] ti to del data for.
303 * Use `ti->mi->ml` for the module list.
304 * Use `ti->mi` for the module instance.
305 * Use `ti->data` for the thread specific data.
306 */
308
309/** Structure to hold callbacks for a module list type
310 *
311 * We care about performance for module lists, as they're used heavily at runtime.
312 *
313 * As much as possible we try to avoid jumping through unecessary functions and
314 * unecessary switch statements.
315 *
316 * This structure contains callbacks which change how the module list operates,
317 * making it either a global module list, or a thread-local module list, i.e. one
318 * which only be used by a single thread.
319 *
320 * Instances of this structure are created in this compilation unit, and exported
321 * for the caller to pass into module_list_alloc().
322 */
324 size_t list_size; //!< Size of talloc_chunk to allocate for the module_list_t.
325
326 module_list_init_t init; //!< Initialise any global structures required for thread-local lookups.
327 module_list_free_t free; //!< Free any global structures required for thread-local lookups.
328
329 size_t inst_size; //!< Size of talloc chunk to allocate for the module_instance_t.
330 ///< allows over-allocation if list types want to append fields.
331 module_list_data_add_t data_add; //!< Record that module data has been added.
332 module_list_data_del_t data_del; //!< Record that module data has been removed.
333
334 /** Callbacks to manage thread-local data
335 */
336 struct {
337 module_list_thread_init_t init; //!< Initialise any thread-local structures required for thread-local lookups.
338 module_list_thread_free_t free; //!< Free any thread-local structures.
339
340 module_list_thread_data_add_t data_add; //!< Add thread-local data for a module.
341 module_list_thread_data_get_t data_get; //!< Retrieve thread local-data for a module.
342 module_list_thread_data_del_t data_del; //!< Remove (but not free) thread-local data for a module.
343
344 void *data; //!< Pointer to hold any global resources for the thread-local implementation.
346};
347
348typedef struct {
349 module_instance_t mi; //!< Common module instance fields. Must come first.
350
351 fr_heap_index_t inst_idx; //!< Entry in the bootstrap/instantiation heap.
352 //!< should be an identical value to the thread-specific
353 ///< data for this module.
355
356/** Sort module instance data first by list then by number
357 *
358 * The module's position in the global instance heap informs of us
359 * of its position in the thread-specific heap, which allows for
360 * O(1) lookups.
361 */
362static int8_t _mlg_module_instance_cmp(void const *one, void const *two)
363{
366 int8_t ret;
367
368 fr_assert(a->ml && b->ml);
369
370 ret = CMP(a->ml, b->ml);
371 if (ret != 0) return ret;
372
373 return CMP(a->number, b->number);
374}
375
376/** Free the global module index
377 *
378 */
379static int _mlg_global_free(UNUSED void *uctx)
380{
381 return talloc_free(mlg_index);
382}
383
384/** Initialise the global module index
385 *
386 */
387static int _mlg_global_init(UNUSED void *uctx)
388{
390 return 0;
391}
392
393/** Global initialisation for index heap and module array
394 *
395 */
397{
398 /*
399 * Create the global module heap we use for
400 * common indexes in the thread-specific
401 * heaps.
402 */
404
405 return 0;
406}
407
408/** Add the unique index value so we can do thread local lookups
409 *
410 */
412{
413 /*
414 * Insert the module into the global heap so
415 * we can get common thread-local indexes.
416 */
417 if (fr_heap_insert(&mlg_index, mi) < 0) {
418 ERROR("Failed inserting into global module index");
419 return -1;
420 }
421
422 return 0;
423}
424
426{
427 mlg_module_instance_t *mlg_mi = (mlg_module_instance_t *)talloc_get_type_abort(mi, module_instance_t);
428
429 if (!fr_heap_entry_inserted(mlg_mi->inst_idx)) return;
430
431 if (fr_heap_extract(&mlg_index, mi) == 0) return;
432
433 fr_assert(0);
434}
435
436/** Free the thread local heap on exit
437 *
438 * All thread local module lists should have been destroyed by this point
439 */
440static int _module_thread_inst_list_free(void *tilp)
441{
442 module_thread_instance_t **til = talloc_get_type_abort(tilp, module_thread_instance_t *);
443 size_t i, len = talloc_array_length(til);
444 unsigned int found = 0;
445
446 for (i = 0; i < len; i++) if (til[i]) found++;
447
448 if (!fr_cond_assert_msg(found == 0,
449 "Thread local array has %u non-null elements remaining on exit. This is a leak",
450 found)) {
451 return -1;
452 }
453
454 return talloc_free(til);
455}
456
457/** Allocate a thread-local array to hold thread data for each module thats been instantiated
458 *
459 * @param[in] ctx Talloc context for the thread-local data.
460 * Mutated by this function so that thread local data is allocated
461 * beneath the array.
462 * @param[in] ml Module list to initialise the thread-local data for.
463 */
464static int mlg_thread_init(UNUSED TALLOC_CTX **ctx, UNUSED module_list_t const *ml)
465{
466 /*
467 * Initialise the thread specific tree if this is the
468 * first time through or if everything else was
469 * de-initialised.
470 */
473
474 MEM(arr = talloc_zero_array(NULL, module_thread_instance_t *, fr_heap_num_elements(mlg_index)));
475
477 }
478
479 return 0;
480}
481
482/** Retrieve the thread-specific data for a module from the thread-local array of instance data
483 *
484 * This looks complex, but it's just asserts for sanity. This is really only returning an array offset.
485 *
486 * @param[in] mi Module instance to get the thread-specific data for.
487 */
489{
492 void *ti_p;
493
495 mlg_mi->inst_idx <= talloc_array_length(mlg_thread_inst_list),
496 "module instance index %u must be <= thread local array %zu",
497 mlg_mi->inst_idx, talloc_array_length(mlg_thread_inst_list));
498
500 "mismatch between global module heap (%u entries) and thread local (%zu entries)",
502
503 /*
504 * Check for a NULL entry. This can happen when a module's
505 * thread instantiate callback fails, and we try and cleanup
506 * a partially instantiated thread.
507 */
508 ti_p = mlg_thread_inst_list[mlg_mi->inst_idx - 1];
509 if (unlikely(!ti_p)) return NULL;
510
511 ti = talloc_get_type_abort(ti_p, module_thread_instance_t);
512 fr_assert_msg(ti->mi == mi, "thread/module mismatch thread %s (%p), module %s (%p)",
513 ti->mi->name, ti->mi, mi->name, mi);
514
515 return ti;
516}
517
524
530
531/** Callbacks for a global module list
532 */
534 .init = mlg_init,
535
536 .inst_size = sizeof(mlg_module_instance_t),
537 .data_add = mlg_data_add,
538 .data_del = mlg_data_del,
539
540 .thread = {
541 .init = mlg_thread_init,
542 .data_add = mlg_thread_data_add,
543 .data_get = mlg_thread_data_get,
544 .data_del = mlg_thread_data_del
545 }
546};
547
548/** A slightly larger module_instance structure to hold the module instance and thread instance
549 */
550typedef struct {
551 module_instance_t mi; //!< Common module instance fields. Must come first.
552 module_thread_instance_t *ti; //!< Thread-specific data. Still in its own structure
553 ///< for talloc reasons.
555
557{
558 mltl_module_instance_t *mltl_mi = (mltl_module_instance_t *)talloc_get_type_abort(mi, module_instance_t);
559
560 /*
561 * Only free thread instance data we allocated...
562 */
563 if (mltl_mi->ti) module_thread_detach(mltl_mi->ti);
564}
565
571
573{
574 mltl_module_instance_t *mltl_mi = (mltl_module_instance_t *)talloc_get_type_abort(ti->mi, module_instance_t);
575 mltl_mi->ti = ti;
576 return 0;
577}
578
580{
581 mltl_module_instance_t *mltl_mi = (mltl_module_instance_t *)talloc_get_type_abort(ti->mi, module_instance_t);
582 mltl_mi->ti = NULL;
583}
584
585/** Callbacks for a thread local list
586 */
589 .data_del = mltl_mlg_data_del,
590
591 .thread = {
592 .data_add = mltl_thread_data_add,
593 .data_get = mltl_thread_data_get,
594 .data_del = mltl_thread_data_del
595 }
596};
597
598/** Print debugging information for a module
599 *
600 * @param[in] mi Module instance to print.
601 */
603{
604 FR_FAULT_LOG("%s (%p) {", mi->name, mi);
605 FR_FAULT_LOG(" type : %s", fr_table_str_by_value(dl_module_type_prefix, mi->module->type, "<invalid>"));
606 if (mi->parent) {
607 FR_FAULT_LOG(" parent : \"%s\" (%p)", mi->parent->name, mi->parent);
608 }
609 FR_FAULT_LOG(" bootstrapped : %s", mi->state & MODULE_INSTANCE_BOOTSTRAPPED ? "yes" : "no");
610 FR_FAULT_LOG(" instantiated : %s", mi->state & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
611 FR_FAULT_LOG(" boot : %p", mi->boot);
612 FR_FAULT_LOG(" data : %p", mi->data);
613 FR_FAULT_LOG(" conf : %p", mi->conf);
614 FR_FAULT_LOG("}");
615}
616
617/** Print the contents of a module list
618 *
619 */
621{
622 module_instance_t const *inst;
624
625 FR_FAULT_LOG("Module list \"%s\" (%p) {", ml->name, ml);
626 FR_FAULT_LOG(" phase masked:");
627 FR_FAULT_LOG(" bootstrap : %s", ml->mask & MODULE_INSTANCE_BOOTSTRAPPED ? "yes" : "no");
628 FR_FAULT_LOG(" instantiate : %s", ml->mask & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
629 FR_FAULT_LOG(" thread : %s", ml->mask & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
630 FR_FAULT_LOG("}");
631 /*
632 * Modules are printed in the same order
633 * they would be bootstrapped or inserted
634 * into the tree.
635 */
636 for (inst = fr_rb_iter_init_inorder(ml->name_tree, &iter);
637 inst;
638 inst = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
640 }
641}
642
643/** Protect module data
644 *
645 * @param[in] mi module instance.
646 * @param[in] pool to protect
647 * @return
648 * - 0 on success.
649 * - -1 on failure.
650 */
651static inline CC_HINT(always_inline)
653{
654 if ((pool->start == NULL) || !mi->ml->write_protect) return 0; /* noop */
655
656 DEBUG3("Protecting data for module \"%s\" %p-%p",
657 mi->name, pool->start, ((uint8_t *)pool->start + pool->len - 1));
658
659 if (unlikely(mprotect(pool->start, pool->len, PROT_READ) < 0)) {
660 fr_strerror_printf("Protecting \"%s\" module data failed: %s", mi->name, fr_syserror(errno));
661 return -1;
662 }
663
664 return 0;
665}
666
667/** Unprotect module data
668 *
669 * @param[in] mi module instance.
670 * @param[in] pool to protect
671 * @return
672 * - 0 on success.
673 * - -1 on failure.
674 */
675static inline CC_HINT(always_inline)
677{
678 if ((pool->start == NULL) || !mi->ml->write_protect) return 0; /* noop */
679
680 DEBUG3("Unprotecting data for module \"%s\" %p-%p",
681 mi->name, pool->start, ((uint8_t *)pool->start + pool->len - 1));
682
683 if (unlikely(mprotect(pool->start, pool->len, PROT_READ | PROT_WRITE) < 0)) {
684 fr_strerror_printf("Unprotecting \"%s\" data failed: %s", mi->name, fr_syserror(errno));
685 return -1;
686 }
687
688 return 0;
689}
690
691/** Mark module data as read only
692 *
693 * @param[in] mi Instance data to protect (mark as read only).
694 * @return
695 * - 0 on success.
696 * - -1 on failure.
697 */
702
703/** Mark module data as read/write
704 *
705 * @param[in] mi Instance data to unprotect (mark as read/write).
706 * @return
707 * - 0 on success.
708 * - -1 on failure.
709 */
714
715/** Return the prefix string for the deepest module
716 *
717 * This is useful for submodules which don't have a prefix of their own.
718 * In this case we need to use the prefix of the shallowest module, which
719 * will be a proto or rlm module.
720 *
721 * @param[in] mi Instance to get the prefix for.
722 * @return The prefix string for the shallowest module.
723 */
725{
726 module_instance_t const *root = module_instance_root(mi);
727
728 return fr_table_str_by_value(dl_module_type_prefix, root->module->type, "<INVALID>");
729}
730
731/** Avoid boilerplate when setting the module instance name
732 *
733 */
735{
736 char const *name2;
737 char const *inst_name;
738 fr_slen_t slen;
739
740 name2 = cf_section_name2(conf);
741 if (name2) {
742 inst_name = name2;
743 goto done;
744 }
745
746 inst_name = cf_section_name1(conf);
747done:
748 slen = module_instance_name_valid(inst_name);
749 if (slen < 0) {
750 cf_log_perr(conf, "Invalid module configuration");
751 *name = NULL;
752 return slen;
753 }
754
755 *name = inst_name;
756
757 return 0;
758}
759
760/** Covert a CONF_SECTION into parsed module instance data
761 *
762 */
764{
765 /*
766 * Associate the module instance with the conf section
767 * *before* executing any parse rules that might need it.
768 */
769 cf_data_add(conf, mi, mi->module->dl->name, false);
770 mi->conf = conf;
771
772 if (mi->exported->config && mi->conf) {
773 if ((cf_section_rules_push(mi->conf, mi->exported->config)) < 0 ||
774 (cf_section_parse(mi->data, mi->data, mi->conf) < 0)) {
775 cf_log_err(mi->conf, "Failed evaluating configuration for module \"%s\"",
776 mi->module->dl->name);
777 return -1;
778 }
779 }
780
781 return 0;
782}
783
784/** Compare module instances by parent and name
785 *
786 * The reason why we need parent, is because we could have submodules with names
787 * that conflict with their parent.
788 */
789static int8_t module_instance_name_cmp(void const *one, void const *two)
790{
791 module_instance_t const *a = one;
792 module_instance_t const *b = two;
793 module_instance_t const *mi;
794 int a_depth = 0, b_depth = 0;
795 int ret;
796
797#ifdef STATIC_ANALYZER
798 if (!fr_cond_assert(a)) return +1;
799 if (!fr_cond_assert(b)) return -1;
800#endif
801
802 /*
803 * Sort by depth, so for tree walking we start
804 * at the shallowest node, and finish with
805 * the deepest child.
806 */
807 for (mi = a; mi; mi = mi->parent) a_depth++;
808 for (mi = b; mi; mi = mi->parent) b_depth++;
809
810 ret = CMP(a_depth, b_depth);
811 if (ret != 0) return ret;
812
813 ret = CMP(a->parent, b->parent);
814 if (ret != 0) return ret;
815
816 ret = strcmp(a->name, b->name);
817 return CMP(ret, 0);
818}
819
820/** Compare module's by their private instance data
821 *
822 */
823static int8_t module_instance_data_cmp(void const *one, void const *two)
824{
825 void const *a = ((module_instance_t const *)one)->data;
826 void const *b = ((module_instance_t const *)two)->data;
827
828 return CMP(a, b);
829}
830
831/** Generic callback for conf_parser_t to load a submodule
832 *
833 * conf_parser_t entry should point to a module_instance_t field in the instance data
834 *
835 * @param[in] ctx unused.
836 * @param[out] out A pointer to a pointer to a module_instance_t.
837 * @param[in] parent This _must_ point to the instance data of the parent
838 * module.
839 * @param[in] ci The CONF_PAIR containing the name of the submodule to load.
840 * @param[in] rule uctx pointer must be a pointer to a module_list_t **
841 * containing the list to search in.
842 * @return
843 * - 0 on success.
844 * - -1 if we failed to load the submodule.
845 */
846int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
847 CONF_ITEM *ci, conf_parser_t const *rule)
848{
849 char const *name = cf_pair_value(cf_item_to_pair(ci));
851 CONF_SECTION *submodule_cs;
853 module_list_t *ml = talloc_get_type_abort(*((void * const *)rule->uctx), module_list_t);
854
855 /*
856 * We assume the submodule's config is the
857 * in a section with the same name as
858 * the submodule.
859 */
860 submodule_cs = cf_section_find(cs, name, NULL);
861
862 /*
863 * Allocate an empty section if one doesn't exist
864 * this is so defaults get parsed.
865 */
866 if (!submodule_cs) submodule_cs = cf_section_alloc(cs, cs, name, NULL);
867
868 /*
869 * The submodule name dictates the module loaded
870 * the instance name is always the submodule name
871 * and will be appended to the parent's instance
872 * name.
873 */
875 if (unlikely(mi == NULL)) {
876 cf_log_err(submodule_cs, "Failed loading submodule");
877 return -1;
878 }
879
880 if (unlikely(module_instance_conf_parse(mi, submodule_cs) < 0)) {
881 cf_log_err(submodule_cs, "Failed parsing submodule config");
882 talloc_free(mi);
883 return -1;
884 }
885
886 *((module_instance_t **)out) = mi;
887
888 return 0;
889}
890
891/** Find an existing module instance by its name and parent
892 *
893 * @param[in] ml to search in.
894 * @param[in] parent to qualify search with.
895 * @param[in] asked_name The name of the module we're attempting to find.
896 * May include '-' which indicates that it's ok for
897 * the module not to be loaded.
898 * @return
899 * - Module instance matching name.
900 * - NULL if no such module exists.
901 */
903{
904 char const *inst_name;
905 void *inst;
906
907 if (!ml->name_tree) return NULL;
908
909 /*
910 * Look for the real name. Ignore the first character,
911 * which tells the server "it's OK for this module to not
912 * exist."
913 */
914 inst_name = asked_name;
915 if (inst_name[0] == '-') inst_name++;
916
919 .parent = UNCONST(module_instance_t *, parent),
920 .name = inst_name
921 });
922 if (!inst) return NULL;
923
924 return talloc_get_type_abort(inst, module_instance_t);
925}
926
927/** Find the module's shallowest parent
928 *
929 * @param[in] child to locate the root for.
930 * @return
931 * - The module's shallowest parent.
932 * - NULL on error.
933 */
935{
936 module_instance_t const *next;
937
938 for (;;) {
939 next = child->parent;
940 if (!next) break;
941
942 child = next;
943 }
944
945 return UNCONST(module_instance_t *, child);
946}
947
948/** Find an existing module instance by its private instance data
949 *
950 * @param[in] ml to search in.
951 * @param[in] data to resolve to module_instance_t.
952 * @return
953 * - Module instance matching data.
954 * - NULL if no such module exists.
955 */
957{
959
960 mi = fr_rb_find(ml->data_tree,
962 .data = UNCONST(void *, data)
963 });
964 if (!mi) return NULL;
965
966 return talloc_get_type_abort(mi, module_instance_t);
967}
968
969/** Retrieve module/thread specific instance data for a module
970 *
971 * @param[in] ml Module list module belongs to.
972 * @param[in] data Private instance data of the module.
973 * Same as what would be provided by
974 * #module_instance_by_data.
975 * @return
976 * - Thread specific instance data on success.
977 * - NULL if module has no thread instance data.
978 */
980{
982
983 if (!mi) return NULL;
984
985 return module_thread(mi);
986}
987
989{
990 module_list_t *ml;
991
992 /*
993 * This can happen when a module's thread instantiate
994 * callback fails, and we try and cleanup a partially
995 * instantiated thread.
996 */
997 if (unlikely(!ti)) return;
998
999 ml = ti->mi->ml;
1000 ml->type->thread.data_del(ti);
1001 talloc_free(ti);
1002}
1003
1004/** Remove thread-specific data for a given module list
1005 *
1006 * Removes all module thread data for the
1007 */
1009{
1011 void *inst;
1012
1013 /*
1014 * Loop over all the modules in the module list
1015 * finding and extracting their thread specific
1016 * data, and calling their detach methods.
1017 */
1018 for (inst = fr_rb_iter_init_inorder(ml->name_tree, &iter);
1019 inst;
1020 inst = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
1021 module_instance_t *mi = talloc_get_type_abort(inst, module_instance_t);
1023
1025 }
1026
1027 /*
1028 * Cleanup any lists the module list added to this thread
1029 */
1030 if (ml->type->thread.free) ml->type->thread.free(ml);
1031}
1032
1033/** Callback to free thread local data
1034 *
1035 * ti->data is allocated in the context of ti, so will be freed too.
1036 *
1037 * Calls the detach function for thread local data, and removes the data from the
1038 * thread local list.
1039 *
1040 * @param[in] ti to free.
1041 */
1043{
1044 module_instance_t const *mi = ti->mi;
1045
1046 /*
1047 * Never allocated a thread instance, so we don't need
1048 * to clean it up...
1049 */
1050 if (mi->state & MODULE_INSTANCE_NO_THREAD_INSTANTIATE) return 0;
1051
1052 DEBUG4("Cleaning up %s thread instance data (%p/%p)",
1053 mi->exported->name, ti, ti->data);
1054
1055 if (mi->exported->thread_detach) {
1057 .mi = ti->mi,
1058 .thread = ti->data,
1059 .el = ti->el
1060 });
1061 }
1062
1063 ti->mi->ml->type->thread.data_del(ti);
1064
1065 return 0;
1066}
1067
1068/** Allocate thread-local instance data for a module
1069 *
1070 * The majority of modules will have a single set of thread-specific instance data.
1071 *
1072 * An exception is dynamic modules, which may have multiple sets of thread-specific instance data tied to
1073 * a specific dynamic use of that module.
1074 *
1075 * @param[in] ctx Talloc ctx to bind thread specific data to.
1076 * @param[in] mi Module instance to perform thread instantiation for.
1077 * @param[in] el Event list serviced by this thread.
1078 * @return
1079 * - 0 on success.
1080 * - -1 on failure.
1081 */
1083{
1084 module_list_t *ml = mi->ml;
1086
1087 /*
1088 * Allows the caller of module_instance_alloc to
1089 * skip thread instantiation for certain modules instances
1090 * whilst allowing modules to still register thread
1091 * instantiation callbacks.
1092 *
1093 * This is mainly there for the single global instance of
1094 * a module, which will only have run-time thread-specific
1095 * instances, like dynamic/keyed modules.
1096 */
1098
1099 /*
1100 * Check the list pointers are ok
1101 */
1102 (void)talloc_get_type_abort(mi->ml, module_list_t);
1103
1104 MEM(ti = talloc_zero(ctx, module_thread_instance_t));
1105 talloc_set_destructor(ti, _module_thread_inst_free);
1106 ti->el = el;
1107 ti->mi = mi;
1108
1109 if (mi->exported->thread_inst_size) {
1110 MEM(ti->data = talloc_zero_array(ti, uint8_t, mi->exported->thread_inst_size));
1111
1112 /*
1113 * Fixup the type name, in case something calls
1114 * talloc_get_type_abort() on it...
1115 */
1116 if (!mi->exported->thread_inst_type) {
1117 talloc_set_name(ti->data, "%s_%s_thread_t",
1119 mi->exported->name);
1120 } else {
1121 talloc_set_name_const(ti->data, mi->exported->thread_inst_type);
1122 }
1123 }
1124
1125 if (ml->type->thread.data_add(ti) < 0) {
1126 PERROR("Failed adding thread data for module \"%s\"", mi->name);
1127 error:
1128 ml->type->thread.data_del(ti);
1129 talloc_free(ti);
1130 return -1;
1131 }
1132
1133 /*
1134 * So we don't get spurious errors
1135 */
1137
1138 DEBUG4("Alloced %s thread instance data (%p/%p)", ti->mi->exported->name, ti, ti->data);
1139 if (mi->exported->thread_instantiate &&
1141 PERROR("Thread instantiation failed for module \"%s\"", mi->name);
1142 goto error;
1143 }
1144
1145 return 0;
1146}
1147
1148/** Creates per-thread instance data for modules which need it
1149 *
1150 * Must be called by any new threads before attempting to execute unlang sections.
1151 *
1152 * @param[in] ctx Talloc ctx to bind thread specific data to.
1153 * @param[in] ml Module list to perform thread instantiation for.
1154 * @param[in] el Event list serviced by this thread.
1155 * @return
1156 * - 0 on success.
1157 * - -1 on failure.
1158 */
1160{
1161 void *inst;
1163 int ret;
1164
1165 /*
1166 * Do any thread-local instantiation necessary
1167 */
1168 if (ml->type->thread.init) {
1169 ret = ml->type->thread.init(&ctx, ml);
1170 if (unlikely(ret < 0)) return ret;
1171 }
1172
1173 for (inst = fr_rb_iter_init_inorder(ml->name_tree, &iter);
1174 inst;
1175 inst = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
1176 module_instance_t *mi = talloc_get_type_abort(inst, module_instance_t); /* Sanity check*/
1177
1178 if (module_thread_instantiate(ctx, mi, el) < 0) {
1180 return -1;
1181 }
1182 }
1183
1184 return 0;
1185}
1186
1187/** Call the coordinator attach callback for any modules using a coordinator
1188 *
1189 * @param ml List of modules to check
1190 * @param el Event list serviced by this thread
1191 * @return
1192 * - 0 on success
1193 * - -1 on failure
1194 */
1196{
1197 void *inst;
1199
1200 for (inst = fr_rb_iter_init_inorder(ml->name_tree, &iter);
1201 inst;
1202 inst = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
1203 module_instance_t *mi = talloc_get_type_abort(inst, module_instance_t);
1205 if (!mi->exported->coord_attach) continue;
1206
1207 thread = ml->thread_data_get(mi);
1208 if (mi->exported->coord_attach(MODULE_THREAD_INST_CTX(mi, thread->data, el)) < 0) return -1;
1209 }
1210
1211 return 0;
1212}
1213
1214/** Manually complete module setup by calling its instantiate function
1215 *
1216 * @param[in] instance of module to complete instantiation for.
1217 * @return
1218 * - 0 on success.
1219 * - -1 on failure.
1220 */
1222{
1223 module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
1224 CONF_SECTION *cs = mi->conf;
1225
1226 /*
1227 * If we're instantiating, then nothing should be able to
1228 * modify the boot data for this module.
1229 *
1230 * mprotect is thread-safe, so we don't need to worry about
1231 * synchronisation. There is the overhead of a system call
1232 * but dynamic module instantiation is relatively rare.
1233 *
1234 * We need to wait until all modules have registered things
1235 * like xlat functions, as the xlat functions themselves may
1236 * end up being allocated in boot pool data, and have inline
1237 * rbtree node structures, which may be modified as additional
1238 * xlat functions are registered.
1239 */
1240 if (unlikely(module_data_protect(mi, &mi->boot_pool) < 0)) {
1241 cf_log_perr(mi->conf, "\"%s\"", mi->name);
1242 return -1;
1243 }
1244
1245 /*
1246 * We only instantiate modules in the bootstrapped state
1247 */
1248 if (module_instance_skip_instantiate(mi)) return 0;
1249
1250 if (mi->module->type == DL_MODULE_TYPE_MODULE) {
1251 if (fr_command_register_hook(NULL, mi->name, mi, module_cmd_table) < 0) {
1252 PERROR("Failed registering radmin commands for module %s", mi->name);
1253 return -1;
1254 }
1255 }
1256
1257 /*
1258 * Now that ALL modules are instantiated, and ALL xlats
1259 * are defined, go compile the config items marked as XLAT.
1260 */
1261 if (mi->exported->config && (cf_section_parse_pass2(mi->data,
1262 mi->conf) < 0)) return -1;
1263
1264 /*
1265 * Call the instantiate method, if any.
1266 */
1267 if (mi->exported->instantiate) {
1268 cf_log_debug(cs, "Instantiating %s_%s \"%s\"",
1270 mi->module->exported->name,
1271 mi->name);
1272
1273 /*
1274 * Call the module's instantiation routine.
1275 */
1276 if (mi->exported->instantiate(MODULE_INST_CTX(mi)) < 0) {
1277 cf_log_err(mi->conf, "Instantiation failed for module \"%s\"", mi->name);
1278
1279 return -1;
1280 }
1281 }
1282
1283 /*
1284 * Instantiate shouldn't modify any global resources
1285 * so we can protect the data now without the side
1286 * effects we might see with boot data.
1287 */
1288 if (unlikely(module_data_protect(mi, &mi->inst_pool) < 0)) {
1289 cf_log_perr(mi->conf, "\"%s\"", mi->name);
1290 return -1;
1291 }
1293
1294 return 0;
1295}
1296
1297/** Completes instantiation of modules
1298 *
1299 * Allows the module to initialise connection pools, and complete any registrations that depend on
1300 * attributes created during the bootstrap phase.
1301 *
1302 * @param[in] ml containing modules to instantiate.
1303 * @return
1304 * - 0 on success.
1305 * - -1 on failure.
1306 */
1308{
1309 void *inst;
1311
1312 DEBUG2("#### Instantiating %s modules ####", ml->name);
1313
1314 for (inst = fr_rb_iter_init_inorder(ml->name_tree, &iter);
1315 inst;
1316 inst = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
1317 module_instance_t *mi = talloc_get_type_abort(inst, module_instance_t);
1318 if (module_instantiate(mi) < 0) return -1;
1319 }
1320
1321 return 0;
1322}
1323
1324/** Manually complete module bootstrap by calling its instantiate function
1325 *
1326 * - Parse the module configuration.
1327 * - Call the modules "bootstrap" method.
1328 *
1329 * @param[in] mi Module instance to bootstrap.
1330 * @return
1331 * - 0 on success.
1332 * - -1 on failure.
1333 */
1335{
1336 /*
1337 * We only bootstrap modules in the init state
1338 */
1339 if (module_instance_skip_bootstrap(mi)) return 0;
1340
1341 /*
1342 * Bootstrap the module.
1343 * This must be done last so that the
1344 * module can find its module_instance_t
1345 * in the trees if it needs to bootstrap
1346 * submodules.
1347 */
1348 if (mi->exported->bootstrap) {
1349 CONF_SECTION *cs = mi->conf;
1350
1351 cf_log_debug(cs, "Bootstrapping %s_%s \"%s\"",
1353 mi->module->exported->name,
1354 mi->name);
1355
1356 /*
1357 * Modules MUST NOT modify their instance data during
1358 * bootstrap. This is because dynamic (runtime) modules
1359 * don't run their boostrap callbacks, and MUST re-resolve
1360 * any resources added during bootstrap in the
1361 * instantiate callback.
1362 *
1363 * Bootstrap is ONLY there for adding global,
1364 * module-specific resources.
1365 *
1366 * If the module has MODULE_TYPE_DYNAMIC_UNSAFE is set,
1367 * then we don't need the restriction.
1368 */
1369 if ((!(mi->exported->flags & MODULE_TYPE_DYNAMIC_UNSAFE)) &&
1370 unlikely(module_data_protect(mi, &mi->inst_pool) < 0)) {
1371 cf_log_perr(cs, "\"%s\"", mi->name);
1372 return -1;
1373 }
1374 if (mi->exported->bootstrap(MODULE_INST_CTX(mi)) < 0) {
1375 cf_log_err(cs, "Bootstrap failed for module \"%s\"", mi->name);
1376 return -1;
1377 }
1378 if (unlikely(module_data_unprotect(mi, &mi->inst_pool) < 0)) {
1379 cf_log_perr(cs, "\"%s\"", mi->name);
1380 return -1;
1381 }
1382 }
1384
1385 return 0;
1386}
1387
1388/** Bootstrap any modules which have not been bootstrapped already
1389 *
1390 * Allows the module to initialise connection pools, and complete any registrations that depend on
1391 * attributes created during the bootstrap phase.
1392 *
1393 * @param[in] ml containing modules to bootstrap.
1394 * @return
1395 * - 0 on success.
1396 * - -1 on failure.
1397 */
1399{
1400 void *instance;
1402
1403 DEBUG2("#### Bootstrapping %s modules ####", ml->name);
1404
1405 for (instance = fr_rb_iter_init_inorder(ml->name_tree, &iter);
1406 instance;
1407 instance = fr_rb_iter_next_inorder(ml->name_tree, &iter)) {
1408 module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
1409 if (module_bootstrap(mi) < 0) return -1;
1410 }
1411
1412 return 0;
1413}
1414
1415/** Generate a module name from the module's name and its parents
1416 *
1417 * @param[in] ctx Where to allocate the module name.
1418 * @param[out] out Where to write a pointer to the instance name.
1419 * @param[in] parent of the module.
1420 * @param[in] inst_name module's instance name.
1421 */
1422static fr_slen_t module_instance_name(TALLOC_CTX *ctx, char **out,
1423 module_instance_t const *parent, char const *inst_name)
1424{
1425 fr_sbuff_t *agg;
1426
1428
1429 /*
1430 * Parent has all of the qualifiers of its ancestors
1431 * already in the name, so we just need to concatenate.
1432 */
1433 if (parent) {
1435 FR_SBUFF_IN_CHAR_RETURN(agg, '.');
1436 }
1437 FR_SBUFF_IN_STRCPY_RETURN(agg, inst_name);
1438
1439 MEM(*out = talloc_bstrndup(ctx, fr_sbuff_start(agg), fr_sbuff_used(agg)));
1440
1441 return fr_sbuff_used(agg);
1442}
1443
1444/** Detach the shallowest parent first
1445 *
1446 * This ensures that the module's parent is detached before it is.
1447 *
1448 * Generally parents reach into their children and not the other way
1449 * around. Calling the parent's detach method first ensures that
1450 * there's no code that access the child module's instance data or
1451 * reach into its symbol space if it's being unloaded.
1452 *
1453 * @note If you don't want to detach the parent, maybe because its children
1454 * are ephemeral, consider using a seaprate thread-local module list
1455 * to hold the children instead.
1456 *
1457 * @param[in] mi to detach.
1458 */
1460{
1462
1464
1466 if (mi->exported && mi->exported->detach) {
1468 }
1470 }
1471
1473 if (mi->exported && mi->exported->unstrap) {
1475 }
1477 }
1478}
1479
1480/** Free module's instance data, and any xlats or paircmps
1481 *
1482 * @param[in] mi to free.
1483 * @return 0
1484 */
1486{
1487 module_list_t *ml = mi->ml;
1488
1489 DEBUG3("Freeing %s (%p)", mi->name, mi);
1490
1491 /*
1492 * Allow writing to instance and bootstrap data again
1493 * so we can clean up without segving.
1494 */
1495 if (unlikely(module_data_unprotect(mi, &mi->inst_pool) < 0)) {
1496 cf_log_perr(mi->conf, "\"%s\"", mi->name);
1497 return -1;
1498 }
1499 if (unlikely(module_data_unprotect(mi, &mi->boot_pool) < 0)) {
1500 cf_log_perr(mi->conf, "\"%s\"", mi->name);
1501 return -1;
1502 }
1503
1506 if (ml->type->data_del) ml->type->data_del(mi);
1507
1508 /*
1509 * mi->exported may be NULL if we failed loading the module
1510 */
1511 if (mi->exported && ((mi->exported->flags & MODULE_TYPE_THREAD_UNSAFE) != 0)) {
1512#ifndef NDEBUG
1513 int ret;
1514
1515 /*
1516 * If the mutex is locked that means
1517 * the server exited without cleaning
1518 * up requests.
1519 *
1520 * Assert that the mutex is not held.
1521 */
1522 ret = pthread_mutex_trylock(&mi->mutex);
1523 fr_assert_msg(ret == 0, "Failed locking module mutex during exit: %s", fr_syserror(ret));
1524 pthread_mutex_unlock(&mi->mutex);
1525#endif
1526 pthread_mutex_destroy(&mi->mutex);
1527 }
1528
1529 /*
1530 * Remove all xlat's registered to module instance.
1531 */
1532 if (mi->data) {
1535 }
1536
1538
1539 /*
1540 * We need to explicitly free all children, so the module instance
1541 * destructors get executed before we unload the bytecode for the
1542 * module.
1543 *
1544 * If we don't do this, we get a SEGV deep inside the talloc code
1545 * when it tries to call a destructor that no longer exists.
1546 */
1547 talloc_free_children(mi);
1548
1549 dl_module_free(mi->module);
1550
1551 return 0;
1552}
1553
1554/** Duplicate a module instance, placing it in a new module list
1555 *
1556 * @param[in] dst list to place the new module instance in.
1557 * @param[in] src to duplicate.
1558 * @param[in] inst_name new instance name. If null, src->name will be used.
1559 */
1561{
1562 module_instance_t *mi = module_instance_alloc(dst, src->parent, src->module->type,
1563 src->module->name,
1564 inst_name ? inst_name : src->name, 0);
1565 if (!mi) return NULL;
1566
1567 return mi;
1568}
1569
1570/** Allocate module instance data
1571 *
1572 * @param[in] ctx talloc context to allocate data in.
1573 * @param[out] pool_out where to write pool details.
1574 * @param[out] out where to write data pointer.
1575 * @param[in] mi module instance.
1576 * @param[in] size of data to allocate.
1577 * @param[in] type talloc type to assign.
1578 */
1579static inline CC_HINT(always_inline)
1580void module_instance_data_alloc(TALLOC_CTX *ctx, module_data_pool_t *pool_out, void **out,
1581 module_instance_t *mi, size_t size, char const *type)
1582{
1583 dl_module_t const *module = mi->module;
1584 void *data;
1585
1586 /*
1587 * If there is supposed to be instance data, allocate it now.
1588 *
1589 * If the structure is zero length then allocation will still
1590 * succeed, and will create a talloc chunk header.
1591 *
1592 * This is needed so we can resolve instance data back to
1593 * module_instance_t/dl_module_t/dl_t.
1594 */
1595 pool_out->ctx = talloc_page_aligned_pool(ctx,
1596 &pool_out->start, &pool_out->len,
1597 1, size);
1598 MEM(data = talloc_zero_array(pool_out->ctx, uint8_t, size));
1599 if (!type) {
1600 talloc_set_name(data, "%s_t", module->dl->name ? module->dl->name : "config");
1601 } else {
1602 talloc_set_name_const(data, type);
1603 }
1604 *out = data;
1605}
1606
1607/** Check to see if a module instance name is valid
1608 *
1609 * @note On failure the error message may be retrieved with fr_strerror().
1610 *
1611 * @param[in] inst_name to check.
1612 *
1613 * @return
1614 * - 0 on success.
1615 * - Negative value on error indicating the position of the bad char.
1616 */
1618{
1619 /*
1620 * [] are used for dynamic module selection.
1621 * . is used as a method and submodule separator.
1622 * Quoting and other characters would just confuse the parser in too many
1623 * instances so they're disallowed too.
1624 */
1625 {
1626 size_t len = strlen(inst_name);
1627
1628 for (size_t i = 0; i < len; i++) {
1629 if (!module_instance_allowed_chars[(uint8_t)inst_name[i]]) {
1630 fr_strerror_printf("Instance name \"%s\" contains an invalid character. "
1631 "Valid characters are [0-9a-zA-Z/_-]", inst_name);
1632 return -(i + 1);
1633 }
1634 }
1635 }
1636
1637 return 0;
1638}
1639
1640/** Set the uctx pointer for a module instance
1641 *
1642 * @param[in] mi to set the uctx for.
1643 * @param[in] uctx to set.
1644 */
1646{
1647 mi->uctx = uctx;
1648}
1649
1650/** Allocate a new module and add it to a module list for later bootstrap/instantiation
1651 *
1652 * - Load the module shared library.
1653 * - Allocate instance data for it.
1654 *
1655 * @param[in] ml To add module to.
1656 * @param[in] parent of the module being bootstrapped, if this is a submodule.
1657 * If this is not a submodule parent must be NULL.
1658 * @param[in] type What type of module we're loading. Determines the prefix
1659 * added to the library name. Should be one of:
1660 * - DL_MODULE_TYPE_MODULE - Standard backend module.
1661 * - DL_MODULE_TYPE_SUBMODULE - Usually a driver for a backend module.
1662 * - DL_MODULE_TYPE_PROTO - A module associated with a listen section.
1663 * - DL_MODULE_TYPE_PROCESS - Protocol state machine bound to a virtual server.
1664 * @param[in] mod_name The name of this module, i.e. 'redis' for 'rlm_redis'.
1665 * @param[in] inst_name Instance name for this module, i.e. "aws_redis_01".
1666 * The notable exception is if this is a submodule, in which case
1667 * inst_name is usually the mod_name.
1668 * @param[in] init_state The state the module "starts" in. Can be used to prevent
1669 * bootstrapping, instantiation, or thread instantiation of the module,
1670 * by passing one or more of the MODULE_INSTANCE_* flags.
1671 * Should usually be 0, unless special behaviour is required.
1672 * @return
1673 * - A new module instance handle, containing the module's public interface,
1674 * and private instance data.
1675 * - NULL on error.
1676 */
1679 dl_module_type_t type, char const *mod_name, char const *inst_name,
1680 module_instance_state_t init_state)
1681{
1682 char *qual_inst_name = NULL;
1684
1689
1690 /*
1691 * Takes the inst_name and adds qualifiers
1692 * if this is a submodule.
1693 */
1694 if (module_instance_name(NULL, &qual_inst_name, parent, inst_name) < 0) {
1695 ERROR("Module name too long");
1696 return NULL;
1697 }
1698
1699 /*
1700 * See if the module already exists.
1701 */
1702 mi = module_instance_by_name(ml, parent, qual_inst_name);
1703 if (mi) {
1704 /*
1705 * We may not have configuration data yet
1706 * for the duplicate module.
1707 */
1708 if (mi->conf) {
1709 ERROR("Duplicate %s_%s instance \"%s\", previous instance defined at %s[%d]",
1710 fr_table_str_by_value(dl_module_type_prefix, mi->module->type, "<INVALID>"),
1711 mi->module->exported->name,
1712 qual_inst_name,
1713 cf_filename(mi->conf),
1714 cf_lineno(mi->conf));
1715
1716 } else {
1717 ERROR("Duplicate %s_%s instance \"%s\"",
1718 fr_table_str_by_value(dl_module_type_prefix, mi->module->type, "<INVALID>"),
1719 mi->module->exported->name,
1720 qual_inst_name);
1721 }
1722 talloc_free(qual_inst_name);
1723 return NULL;
1724 }
1725
1726 /*
1727 * Overallocate the module instance, so we can add
1728 * some module list type specific data to it.
1729 */
1730 MEM(mi = (module_instance_t *)talloc_zero_array(parent ? (void const *)parent : (void const *)ml, uint8_t, ml->type->inst_size));
1731 talloc_set_name_const(mi, "module_instance_t");
1732 mi->name = talloc_strdup(mi, qual_inst_name);
1733 talloc_free(qual_inst_name); /* Avoid stealing */
1734
1735 mi->ml = ml;
1736 mi->parent = parent;
1737 mi->state = init_state;
1738
1739 /*
1740 * Increment the reference count on an already loaded module,
1741 * or load the .so or .dylib, and run all the global callbacks.
1742 */
1743 mi->module = dl_module_alloc(parent ? parent->module : NULL, mod_name, type);
1744 if (!mi->module) {
1745 error:
1746 talloc_free(mi);
1747 return NULL;
1748 }
1749
1750 /*
1751 * We have no way of checking if this is correct... so we hope...
1752 */
1753 mi->exported = (module_t *)mi->module->exported;
1754 if (unlikely(mi->exported == NULL)) {
1755 ERROR("Missing public structure for \"%s\"", mi->name);
1756 goto error;
1757 }
1758
1759 /*
1760 * Allocate bootstrap data.
1761 */
1762 if (mi->exported->bootstrap) {
1764 mi, mi->exported->boot_size, mi->exported->boot_type);
1765 }
1766 /*
1767 * Allocate the module instance data. We always allocate
1768 * this so the module can use it for lookup.
1769 */
1771 mi, mi->exported->inst_size, mi->exported->inst_type);
1772 /*
1773 * If we're threaded, check if the module is thread-safe.
1774 *
1775 * If it isn't, we init the mutex.
1776 *
1777 * Do this here so the destructor can trylock the mutex
1778 * correctly even if bootstrap/instantiation fails.
1779 */
1780 if ((mi->exported->flags & MODULE_TYPE_THREAD_UNSAFE) != 0) pthread_mutex_init(&mi->mutex, NULL);
1781 talloc_set_destructor(mi, _module_instance_free); /* Set late intentionally */
1782 mi->number = ml->last_number++;
1783
1784 /*
1785 * Remember the module for later.
1786 */
1787 if (!fr_cond_assert(fr_rb_insert(ml->name_tree, mi))) goto error;
1788 if (!fr_cond_assert(fr_rb_insert(ml->data_tree, mi))) goto error;
1789 if (ml->type->data_add && unlikely(ml->type->data_add(mi) < 0)) goto error;
1790
1791 return mi;
1792}
1793
1794/** Free all modules loaded by the server
1795 *
1796 * @param[in] ml Module list being freed.
1797 * @return 0
1798 */
1800{
1803
1804 /*
1805 * Re-initialize the iterator after freeing each module.
1806 * The module may have children which are also in the
1807 * tree. It can cause problems when we delete children
1808 * without the iterator knowing about it.
1809 */
1810 while ((mi = fr_rb_iter_init_inorder(ml->name_tree, &iter)) != NULL) {
1811 fr_rb_iter_delete_inorder(ml->name_tree, &iter); /* Keeps the iterator sane */
1812 talloc_free(mi);
1813 }
1814
1815 if (ml->type->free) ml->type->free(ml);
1816
1817 return 0;
1818}
1819
1820/** Should we bootstrap this module instance?
1821 *
1822 * @param[in] mi to check.
1823 * @return
1824 * - true if the module instance should be bootstrapped.
1825 * - false if the module instance has already been bootstrapped.
1826 */
1831
1832/** Should we instantiate this module instance?
1833 *
1834 * @param[in] mi to check.
1835 * @return
1836 * - true if the module instance should be instantiated.
1837 * - false if the module instance has already been instantiated.
1838 */
1843
1844/** Should we instantiate this module instance in a new thread?
1845 *
1846 * @param[in] mi to check.
1847 * @return
1848 * - true if the module instance should be instantiated in a new thread.
1849 * - false if the module instance has already been instantiated in a new thread.
1850 */
1855
1856/** Set a new bootstrap/instantiate state for a list
1857 *
1858 * @param[in] ml To set the state for.
1859 * @param[in] mask New state.
1860 */
1865
1866/** Allocate a new module list
1867 *
1868 * This is used to instantiate and destroy modules in distinct phases
1869 * for example, we may need to load all proto modules before rlm modules.
1870 *
1871 * If the list is freed all module instance data will be freed.
1872 * If no more instances of the module exist the module be unloaded.
1873 *
1874 * @param[in] ctx To allocate the list in.
1875 * @param[in] type of the list. Controls whether this is a global
1876 * module list, or a per-thread list containing
1877 * variants of an existing module.
1878 * @param[in] name of the list. Used for debugging.
1879 * @param[in] write_protect Whether to write protect the module data
1880 * after instantiation and bootstrapping.
1881 * @return A new module list.
1882 */
1884 char const *name, bool write_protect)
1885{
1886 module_list_t *ml;
1887
1888 /*
1889 * These callbacks are NOT optional, the rest are.
1890 */
1891 fr_assert(type->thread.data_add);
1892 fr_assert(type->thread.data_get);
1893 fr_assert(type->thread.data_del);
1894
1895 MEM(ml = talloc_zero(ctx, module_list_t));
1896 ml->type = type;
1897
1898 ml->thread_data_get = type->thread.data_get; /* Cache for access outside of the compilation unit */
1899 MEM(ml->name = talloc_strdup(ml, name));
1902 talloc_set_destructor(ml, _module_list_free);
1903
1904 if (ml->type->init && (ml->type->init(ml) < 0)) {
1905 talloc_free(ml);
1906 return NULL;
1907 }
1908 ml->write_protect = write_protect;
1909
1910 return ml;
1911}
1912
1913static int _module_dl_loader_init(void *uctx)
1914{
1916
1917 /*
1918 * Ensure the common library tracking
1919 * tree is in place...
1920 */
1922
1923 return 0;
1924}
1925
1926static int _module_dl_loader_free(UNUSED void *uctx)
1927{
1928 if (talloc_free(dl_modules) < 0) return -1;
1929 dl_modules = NULL;
1930 return 0;
1931}
1932
1933/** Perform global initialisation for modules
1934 *
1935 */
1936void modules_init(char const *lib_dir)
1937{
1938 /*
1939 * Create the global module heap we use for
1940 * common indexes in the thread-specific
1941 * heaps.
1942 */
1944}
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:220
#define fr_atexit_global_once(_init, _free, _uctx)
Definition atexit.h:210
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:506
#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:113
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
int cf_section_write(FILE *fp, CONF_SECTION *cs, int depth)
Definition cf_file.c:3778
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1208
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
Definition cf_parse.c:1318
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:617
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:689
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:594
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first 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_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1574
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define cf_lineno(_cf)
Definition cf_util.h:101
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:251
#define cf_parent(_cf)
Definition cf_util.h:98
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:292
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:143
#define cf_filename(_cf)
Definition cf_util.h:104
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:288
fr_command_register_hook_t fr_command_register_hook
Definition command.c:41
bool fr_command_strncmp(const char *word, const char *name)
Definition command.c:2900
int argc
current argument count
Definition command.h:39
char const * parent
e.g. "show module"
Definition command.h:52
#define CMD_TABLE_END
Definition command.h:62
char const ** argv
text version of commands
Definition command.h:42
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:141
#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:212
#define FR_FAULT_LOG(_fmt,...)
Definition debug.h:60
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:158
#define MEM(x)
Definition debug.h:46
#define ERROR(fmt,...)
Definition dhcpclient.c:40
fr_table_num_sorted_t const dl_module_type_prefix[]
Name prefixes matching the types of loadable module.
Definition dl_module.c:54
dl_module_t * dl_module_alloc(dl_module_t const *parent, char const *name, dl_module_type_t type)
Load a module library using dlopen() or return a previously loaded module from the cache.
Definition dl_module.c:312
int dl_module_free(dl_module_t *dl_module)
Free a dl_module (when there are no more references to it)
Definition dl_module.c:278
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
Definition dl_module.c:524
Wrapper struct around dl_loader_t.
Definition dl_module.c:44
dl_module_type_t
Definition dl_module.h:65
@ DL_MODULE_TYPE_PROTO
Protocol module.
Definition dl_module.h:67
@ DL_MODULE_TYPE_SUBMODULE
Driver (or method in the case of EAP)
Definition dl_module.h:69
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
Definition dl_module.h:66
@ DL_MODULE_TYPE_PROCESS
protocol processor.
Definition dl_module.h:68
int global_lib_init(void)
Initialise the global list of external libraries.
Definition global_lib.c:204
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:146
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:239
unsigned int fr_heap_index_t
Definition heap.h:80
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
Definition heap.h:100
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:124
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
Definition heap.h:179
#define fr_heap_foreach(_heap, _type, _data)
Iterate over the contents of a heap.
Definition heap.h:205
The main heap structure.
Definition heap.h:66
talloc_free(hp)
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG3(_fmt,...)
Definition log.h:266
#define DEBUG4(_fmt,...)
Definition log.h:267
Stores all information relating to an event list.
Definition event.c:377
static char const * mod_name(fr_listen_t *li)
Definition master.c:2948
unsigned char uint8_t
ssize_t fr_slen_t
#define MODULE_DETACH_CTX(_mi)
Wrapper to create a module_detach_ctx_t as a compound literal.
Definition module_ctx.h:164
#define MODULE_THREAD_INST_CTX(_mi, _thread, _el)
Wrapper to create a module_thread_inst_ctx_t as a compound literal.
Definition module_ctx.h:176
#define MODULE_INST_CTX(_mi)
Wrapper to create a module_inst_ctx_t as a compound literal.
Definition module_ctx.h:158
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
#define fr_assert(_expr)
Definition rad_assert.h:37
#define DEBUG2(fmt,...)
static bool done
Definition radclient.c:80
static rs_t * conf
Definition radsniff.c:52
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
Definition rb.c:824
void fr_rb_iter_delete_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition rb.c:899
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
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition rb.c:741
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:850
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:269
static bool fr_rb_node_inline_in_tree(fr_rb_node_t const *node)
Check to see if an item is in a tree by examining its inline fr_rb_node_t.
Definition rb.h:312
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:319
static uint32_t mask
Definition rbmonkey.c:39
fr_table_num_sorted_t const rcode_table[]
Definition rcode.c:35
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
Definition rcode.h:45
static char const * name
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define SBUFF_CHAR_CLASS
Definition sbuff.h:203
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
module_thread_instantiate_t coord_attach
Callback to attach a worker to a coordinator.
Definition module.h:244
module_instance_t * mi
As opposed to the thread local inst.
Definition module.h:378
char const * name
Instance name e.g. user_database.
Definition module.h:357
@ MODULE_TYPE_DYNAMIC_UNSAFE
Instances of this module cannot be created at runtime.
Definition module.h:53
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition module.h:49
module_flags_t flags
Flags that control how a module starts up and how a module is called.
Definition module.h:236
fr_rb_node_t name_node
Entry in the name tree.
Definition module.h:332
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
size_t inst_size
Size of the module's instance data.
Definition module.h:212
module_detach_t detach
Clean up module resources from the instantiation phases.
Definition module.h:232
bool force
Force the module to return a specific code.
Definition module.h:319
void * data
Module's instance data.
Definition module.h:293
module_instance_state_t state
What's been done with this module so far.
Definition module.h:350
module_instance_t const * parent
Parent module's instance (if any).
Definition module.h:359
module_thread_instantiate_t thread_instantiate
Callback to populate a new module thread instance data.
Definition module.h:239
module_instantiate_t instantiate
Callback to allow the module to register any per-instance resources like sockets and file handles.
Definition module.h:227
void * boot
Data allocated during the boostrap phase.
Definition module.h:296
TALLOC_CTX * ctx
ctx data is allocated in.
Definition module.h:276
module_instance_state_t mask
Prevent phases from being executed.
Definition module.h:409
module_thread_instance_t *(* module_list_thread_data_get_t)(module_instance_t const *mi)
Callback to retrieve thread-local data for a module.
Definition module.h:394
#define MODULE_INSTANCE_LEN_MAX
The maximum size of a module instance.
Definition module.h:148
void * data
Thread specific instance data.
Definition module.h:374
module_data_pool_t inst_pool
Data to allow mprotect state toggling for instance data.
Definition module.h:341
bool write_protect
If true, pages containing module boot or instance data will be write protected after bootstrapping an...
Definition module.h:416
rlm_rcode_t code
Code module will return when 'force' has has been set to true.
Definition module.h:322
char const * boot_type
talloc type to assign to bootstrap data.
Definition module.h:210
size_t len
How much data we need mprotect to protect.
Definition module.h:278
char const * inst_type
talloc type to assign to instance data.
Definition module.h:213
module_data_pool_t boot_pool
Data to allow mprotect state toggling for bootstrap data.
Definition module.h:343
module_detach_t unstrap
Clean up module resources from both the bootstrap phase.
Definition module.h:234
static module_thread_instance_t * module_thread(module_instance_t const *mi)
Retrieve module/thread specific instance for a module.
Definition module.h:503
module_instance_state_t
What state the module instance is currently in.
Definition module.h:265
@ MODULE_INSTANCE_INSTANTIATED
Module instance has been bootstrapped and instantiated.
Definition module.h:268
@ MODULE_INSTANCE_NO_THREAD_INSTANTIATE
Not set internally, but can be used to prevent thread instantiation for certain modules.
Definition module.h:270
@ MODULE_INSTANCE_BOOTSTRAPPED
Module instance has been bootstrapped, but not yet instantiated.
Definition module.h:266
fr_rb_tree_t * data_tree
Modules indexed by data.
Definition module.h:413
uint32_t number
Unique module number.
Definition module.h:334
module_list_thread_data_get_t thread_data_get
Callback to get thread-specific data.
Definition module.h:435
char const * thread_inst_type
talloc type to assign to thread instance data.
Definition module.h:247
module_instantiate_t bootstrap
Callback to allow the module to register any global resources like xlat functions and attributes.
Definition module.h:215
fr_rb_node_t data_node
Entry in the data tree.
Definition module.h:333
module_thread_detach_t thread_detach
Callback to free thread-specific resources associated < with a module.
Definition module.h:241
void * uctx
Extra data passed to module_instance_alloc.
Definition module.h:361
void * start
Start address which may be passed to mprotect.
Definition module.h:277
size_t boot_size
Size of the module's bootstrap data.
Definition module.h:209
module_list_t * ml
Module list this instance belongs to.
Definition module.h:331
size_t thread_inst_size
Size of the module's thread-specific instance data.
Definition module.h:246
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
char const * name
Friendly list identifier.
Definition module.h:408
fr_event_list_t * el
Event list associated with this thread.
Definition module.h:376
module_list_type_t const * type
Type of module list.
Definition module.h:434
uint32_t last_number
Last identifier assigned to a module instance.
Definition module.h:411
fr_rb_tree_t * name_tree
Modules indexed by name.
Definition module.h:412
module_t * exported
Public module structure.
Definition module.h:298
pthread_mutex_t mutex
Used prevent multiple threads entering a thread unsafe module simultaneously.
Definition module.h:305
Module instance data.
Definition module.h:287
A list of modules.
Definition module.h:407
Struct exported by a rlm_* module.
Definition module.h:203
Per thread per instance data.
Definition module.h:369
static int mltl_thread_data_add(module_thread_instance_t *ti)
Definition module.c:572
static void module_thread_detach(module_thread_instance_t *ti)
Definition module.c:988
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
Definition module.c:620
module_list_type_t const module_list_type_thread_local
Callbacks for a thread local list.
Definition module.c:587
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1936
bool module_instance_skip_thread_instantiate(module_instance_t *mi)
Should we instantiate this module instance in a new thread?
Definition module.c:1851
static int module_data_unprotect(module_instance_t const *mi, module_data_pool_t const *pool)
Unprotect module data.
Definition module.c:676
static int mlg_init(UNUSED module_list_t *ml)
Global initialisation for index heap and module array.
Definition module.c:396
static int _module_dl_loader_free(UNUSED void *uctx)
Definition module.c:1926
module_list_free_t free
Free any global structures required for thread-local lookups.
Definition module.c:327
static int _module_list_free(module_list_t *ml)
Free all modules loaded by the server.
Definition module.c:1799
module_thread_instance_t * ti
Thread-specific data.
Definition module.c:552
static int _module_instance_free(module_instance_t *mi)
Free module's instance data, and any xlats or paircmps.
Definition module.c:1485
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:902
static int module_data_protect(module_instance_t *mi, module_data_pool_t *pool)
Protect module data.
Definition module.c:652
static void module_detach_parent(module_instance_t *mi)
Detach the shallowest parent first.
Definition module.c:1459
static int _module_thread_inst_list_free(void *tilp)
Free the thread local heap on exit.
Definition module.c:440
void(* module_list_free_t)(module_list_t *ml)
Callback to free any global structures associated with the module list.
Definition module.c:249
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:1861
module_instance_t * module_instance_copy(module_list_t *dst, module_instance_t const *src, char const *inst_name)
Duplicate a module instance, placing it in a new module list.
Definition module.c:1560
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:1677
static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
Definition module.c:169
static int8_t module_instance_data_cmp(void const *one, void const *two)
Compare module's by their private instance data.
Definition module.c:823
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:734
static int8_t module_instance_name_cmp(void const *one, void const *two)
Compare module instances by parent and name.
Definition module.c:789
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
Definition module.c:1008
static int mlg_data_add(module_instance_t *mi)
Add the unique index value so we can do thread local lookups.
Definition module.c:411
module_list_data_add_t data_add
Record that module data has been added.
Definition module.c:331
module_list_init_t init
Initialise any global structures required for thread-local lookups.
Definition module.c:326
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:1159
bool module_instance_skip_instantiate(module_instance_t *mi)
Should we instantiate this module instance?
Definition module.c:1839
static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info)
Definition module.c:158
static int module_name_tab_expand(UNUSED TALLOC_CTX *talloc_ctx, UNUSED void *uctx, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Definition module.c:132
void(* module_list_data_del_t)(module_instance_t *mi)
Callback to del data for a module.
Definition module.c:267
size_t inst_size
Size of talloc chunk to allocate for the module_instance_t.
Definition module.c:329
int(* module_list_thread_data_add_t)(module_thread_instance_t *ti)
Callback to add thread-local data for a module.
Definition module.c:298
module_instance_t * module_instance_by_data(module_list_t const *ml, void const *data)
Find an existing module instance by its private instance data.
Definition module.c:956
bool const module_instance_allowed_chars[SBUFF_CHAR_CLASS]
Chars that are allowed in a module instance name.
Definition module.c:212
static void module_instance_data_alloc(TALLOC_CTX *ctx, module_data_pool_t *pool_out, void **out, module_instance_t *mi, size_t size, char const *type)
Allocate module instance data.
Definition module.c:1580
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition module.c:1307
int(* module_list_init_t)(module_list_t *ml)
Callback to initialise any global structures required for the module list.
Definition module.c:243
static module_thread_instance_t * mltl_thread_data_get(module_instance_t const *mi)
Definition module.c:566
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:1883
static void mlg_thread_data_del(module_thread_instance_t *ti)
Definition module.c:525
static int mlg_thread_data_add(module_thread_instance_t *ti)
Definition module.c:518
static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
Definition module.c:183
static int _module_dl_loader_init(void *uctx)
Definition module.c:1913
void(* module_list_thread_free_t)(module_list_t *ml)
Callback to free thread-local structures, called once per thread as the thread is being destroyed.
Definition module.c:286
void module_instance_uctx_set(module_instance_t *mi, void *uctx)
Set the uctx pointer for a module instance.
Definition module.c:1645
int modules_coord_attach(module_list_t const *ml, fr_event_list_t *el)
Call the coordinator attach callback for any modules using a coordinator.
Definition module.c:1195
static fr_slen_t module_instance_name(TALLOC_CTX *ctx, char **out, module_instance_t const *parent, char const *inst_name)
Generate a module name from the module's name and its parents.
Definition module.c:1422
static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
Definition module.c:121
void(* module_list_thread_data_del_t)(module_thread_instance_t *ti)
Callback to remove thread-local data for a module.
Definition module.c:307
fr_slen_t module_instance_name_valid(char const *inst_name)
Check to see if a module instance name is valid.
Definition module.c:1617
return count
Definition module.c:155
static int _module_thread_inst_free(module_thread_instance_t *ti)
Callback to free thread local data.
Definition module.c:1042
static int _mlg_global_free(UNUSED void *uctx)
Free the global module index.
Definition module.c:379
int module_thread_instantiate(TALLOC_CTX *ctx, module_instance_t *mi, fr_event_list_t *el)
Allocate thread-local instance data for a module.
Definition module.c:1082
module_list_data_del_t data_del
Record that module data has been removed.
Definition module.c:332
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:533
static dl_module_loader_t * dl_modules
dl module tracking
Definition module.c:234
fr_cmd_table_t module_cmd_list_table[]
Definition module.c:91
static module_thread_instance_t * mlg_thread_data_get(module_instance_t const *mi)
Retrieve the thread-specific data for a module from the thread-local array of instance data.
Definition module.c:488
fr_heap_index_t inst_idx
Entry in the bootstrap/instantiation heap.
Definition module.c:351
struct module_list_type_s::@66 thread
Callbacks to manage thread-local data.
int(* module_list_thread_init_t)(TALLOC_CTX **ctx, module_list_t const *ml)
Callback to initialise a list for thread-local data, called once per thread.
Definition module.c:280
module_thread_instance_t * module_thread_by_data(module_list_t const *ml, void const *data)
Retrieve module/thread specific instance data for a module.
Definition module.c:979
int module_instance_data_protect(module_instance_t *mi)
Mark module data as read only.
Definition module.c:698
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition module.c:1398
int module_instance_data_unprotect(module_instance_t *mi)
Mark module data as read/write.
Definition module.c:710
fr_cmd_table_t module_cmd_table[]
Definition module.c:58
module_instance_t mi
Common module instance fields. Must come first.
Definition module.c:349
static _Thread_local module_thread_instance_t ** mlg_thread_inst_list
An array of thread-local module lists.
Definition module.c:50
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
Definition module.c:1221
static int mlg_thread_init(UNUSED TALLOC_CTX **ctx, UNUSED module_list_t const *ml)
Allocate a thread-local array to hold thread data for each module thats been instantiated.
Definition module.c:464
bool module_instance_skip_bootstrap(module_instance_t *mi)
Should we bootstrap this module instance?
Definition module.c:1827
module_instance_t mi
Common module instance fields. Must come first.
Definition module.c:551
static int _mlg_global_init(UNUSED void *uctx)
Initialise the global module index.
Definition module.c:387
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:846
int(* module_list_data_add_t)(module_instance_t *mi)
Callback to add data for a module.
Definition module.c:260
module_instance_t * module_instance_root(module_instance_t const *child)
Find the module's shallowest parent.
Definition module.c:934
size_t list_size
Size of talloc_chunk to allocate for the module_list_t.
Definition module.c:324
static void mlg_data_del(module_instance_t *mi)
Definition module.c:425
static void mltl_thread_data_del(module_thread_instance_t *ti)
Definition module.c:579
static void mltl_mlg_data_del(module_instance_t *mi)
Definition module.c:556
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition module.c:763
char const * module_instance_root_prefix_str(module_instance_t const *mi)
Return the prefix string for the deepest module.
Definition module.c:724
static fr_heap_t * mlg_index
Heap of all lists/modules used to get a common index with mlg_thread->inst_list.
Definition module.c:42
static int8_t _mlg_module_instance_cmp(void const *one, void const *two)
Sort module instance data first by list then by number.
Definition module.c:362
int module_bootstrap(module_instance_t *mi)
Manually complete module bootstrap by calling its instantiate function.
Definition module.c:1334
void module_instance_debug(module_instance_t const *mi)
Print debugging information for a module.
Definition module.c:602
A slightly larger module_instance structure to hold the module instance and thread instance.
Definition module.c:550
Structure to hold callbacks for a module list type.
Definition module.c:323
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:617
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
Definition talloc.c:308
#define talloc_get_type_abort_const
Definition talloc.h:110
#define talloc_strdup(_ctx, _str)
Definition talloc.h:142
static fr_event_list_t * el
static fr_slen_t parent
Definition pair.h:858
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:576
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
static fr_slen_t data
Definition value.h:1340
static size_t char ** out
Definition value.h:1030
void xlat_func_unregister_module(module_instance_t const *inst)
Definition xlat_func.c:530
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:516