The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: dc6e1b1564c23e459d78892db29760fa35067731 $
19  *
20  * @file src/lib/server/module.c
21  * @brief Defines functions for module (re-)initialisation.
22  *
23  * @copyright 2003,2006,2016 The FreeRADIUS server project
24  * @copyright 2016 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 
29 RCSID("$Id: dc6e1b1564c23e459d78892db29760fa35067731 $")
30 
31 #include <freeradius-devel/server/base.h>
32 #include <freeradius-devel/server/cf_file.h>
33 #include <freeradius-devel/server/modpriv.h>
34 #include <freeradius-devel/server/module_rlm.h>
35 #include <freeradius-devel/server/radmin.h>
36 #include <freeradius-devel/server/request_data.h>
37 #include <freeradius-devel/server/module.h>
38 #include <freeradius-devel/util/strerror.h>
39 #include <freeradius-devel/unlang/xlat_func.h>
40 
41 /** Heap of all lists/modules used to get a common index with module_thread_inst_list
42  *
43  */
45 
46 /** An array of thread-local module lists
47  *
48  * The indexes in this array are identical to module_list_global, allowing
49  * O(1) lookups. Arrays are used here as there's no performance penalty
50  * once they're populated.
51  */
53 
54 /** Toggle used to determine if it's safe to use index based lookups
55  *
56  * Index based heap lookups are significantly more efficient than binary
57  * searches, but they can only be performed when all module data is inserted
58  * into both the global module list and the thread local module list.
59  *
60  * When we start removing module lists or modules from the thread local
61  * heap those heaps no longer have a common index with the global module
62  * list so we need to revert back to doing binary searches instead of using
63  * common indexes.
64  */
65 static _Thread_local bool module_list_in_sync = true;
66 
67 /** dl module tracking
68  *
69  */
71 
72 static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info);
73 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);
74 static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info);
75 static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info);
76 static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info);
77 
79  {
80  .parent = "show module",
81  .add_name = true,
82  .name = "status",
83  .func = cmd_show_module_status,
84  .help = "Show the status of a particular module.",
85  .read_only = true,
86  },
87 
88  {
89  .parent = "show module",
90  .add_name = true,
91  .name = "config",
92  .func = cmd_show_module_config,
93  .help = "Show configuration for a module",
94  // @todo - do tab expand, by walking over the whole module list...
95  .read_only = true,
96  },
97 
98  {
99  .parent = "set module",
100  .add_name = true,
101  .name = "status",
102  .syntax = "(alive|disallow|fail|reject|handled|invalid|notfound|noop|ok|updated)",
103  .func = cmd_set_module_status,
104  .help = "Change module status to fixed value.",
105  .read_only = false,
106  },
107 
109 };
110 
112  {
113  .parent = "show",
114  .name = "module",
115  .help = "Show information about modules.",
116  .tab_expand = module_name_tab_expand,
117  .read_only = true,
118  },
119 
120  // @todo - what if there's a module called "list" ?
121  {
122  .parent = "show module",
123  .name = "list",
124  .func = cmd_show_module_list,
125  .help = "Show the list of modules loaded in the server.",
126  .read_only = true,
127  },
128 
129  {
130  .parent = "set",
131  .name = "module",
132  .help = "Change module settings.",
133  .tab_expand = module_name_tab_expand,
134  .read_only = false,
135  },
136 
137 
139 };
140 
141 static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
142 {
143  module_instance_t *mi = ctx;
144 
145  fr_assert(mi->dl_inst->conf != NULL);
146 
147  (void) cf_section_write(fp, mi->dl_inst->conf, 0);
148 
149  return 0;
150 }
151 
152 static int module_name_tab_expand(UNUSED TALLOC_CTX *talloc_ctx, UNUSED void *uctx,
153  fr_cmd_info_t *info, int max_expansions, char const **expansions)
154 {
155  char const *text;
156  int count;
157 
158  if (info->argc <= 0) return 0;
159 
160  text = info->argv[info->argc - 1];
161  count = 0;
162 
164  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
165 
166  if (count >= max_expansions) {
167  break;
168  }
169  if (fr_command_strncmp(text, mi->name)) {
170  expansions[count] = strdup(mi->name);
171  count++;
172  }
173  }}
174 
175  return count;
176 }
177 
178 static int cmd_show_module_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *uctx, UNUSED fr_cmd_info_t const *info)
179 {
181  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
182 
183  fprintf(fp, "\t%s\n", mi->name);
184  }}
185 
186  return 0;
187 }
188 
189 static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
190 {
191  module_instance_t *mi = ctx;
192 
193  if (!mi->force) {
194  fprintf(fp, "alive\n");
195  return 0;
196  }
197 
198  fprintf(fp, "%s\n", fr_table_str_by_value(rcode_table, mi->code, "<invalid>"));
199 
200  return 0;
201 }
202 
203 static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
204 {
205  module_instance_t *mi = ctx;
206  rlm_rcode_t rcode;
207 
208  if (strcmp(info->argv[0], "alive") == 0) {
209  mi->force = false;
210  return 0;
211  }
212 
214  if (rcode == RLM_MODULE_NOT_SET) {
215  fprintf(fp_err, "Unknown status '%s'\n", info->argv[0]);
216  return -1;
217  }
218 
219  mi->code = rcode;
220  mi->force = true;
221 
222  return 0;
223 }
224 
225 /** Sort module instance data first by list then by number
226  *
227  * The module's position in the global instance heap informs of us
228  * of its position in the thread-specific heap, which allows for
229  * O(1) lookups.
230  */
231 static int8_t _module_instance_global_cmp(void const *one, void const *two)
232 {
235  int8_t ret;
236 
237  fr_assert(a->ml && b->ml);
238 
239  ret = CMP(a->ml, b->ml);
240  if (ret != 0) return 0;
241 
242  return CMP(a->number, b->number);
243 }
244 
245 /** Compare module instances by parent and name
246  *
247  * The reason why we need parent, is because we could have submodules with names
248  * that conflict with their parent.
249  */
250 static int8_t module_instance_name_cmp(void const *one, void const *two)
251 {
252  module_instance_t const *a = one;
253  module_instance_t const *b = two;
254  dl_module_inst_t const *dl_inst;
255  int a_depth = 0, b_depth = 0;
256  int ret;
257 
258  /*
259  * Sort by depth, so for tree walking we start
260  * at the shallowest node, and finish with
261  * the deepest child.
262  */
263  for (dl_inst = a->dl_inst; dl_inst; dl_inst = dl_inst->parent) a_depth++;
264  for (dl_inst = b->dl_inst; dl_inst; dl_inst = dl_inst->parent) b_depth++;
265 
266  ret = CMP(a_depth, b_depth);
267  if (ret != 0) return ret;
268 
269  /*
270  * This happens, as dl_inst is is used in
271  * as the loop condition above.
272  */
273 #ifdef STATIC_ANALYZER
274  if (!fr_cond_assert(a->dl_inst)) return +1;
275  if (!fr_cond_assert(b->dl_inst)) return -1;
276 #endif
277 
278  ret = CMP(a->dl_inst->parent, b->dl_inst->parent);
279  if (ret != 0) return ret;
280 
281  ret = strcmp(a->name, b->name);
282  return CMP(ret, 0);
283 }
284 
285 /** Compare module's by their private instance data
286  *
287  */
288 static int8_t module_instance_data_cmp(void const *one, void const *two)
289 {
290  void const *a = (((module_instance_t const *)one)->dl_inst)->data;
291  void const *b = (((module_instance_t const *)two)->dl_inst)->data;
292 
293  return CMP(a, b);
294 }
295 
296 /** Generic callback for conf_parser_t to load a submodule
297  *
298  * conf_parser_t entry should point to a module_instance_t field in the instance data
299  *
300  * @param[in] ctx unused.
301  * @param[out] out A pointer to a pointer to a module_instance_t.
302  * @param[in] parent This _must_ point to the instance data of the parent
303  * module.
304  * @param[in] ci The CONF_PAIR containing the name of the submodule to load.
305  * @param[in] rule uctx pointer must be a pointer to a module_list_t **
306  * containing the list to search in.
307  * @return
308  * - 0 on success.
309  * - -1 if we failed to load the submodule.
310  */
311 int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
312  CONF_ITEM *ci, conf_parser_t const *rule)
313 {
314  char const *name = cf_pair_value(cf_item_to_pair(ci));
316  CONF_SECTION *submodule_cs;
317  module_instance_t *mi;
318  module_list_t *ml = talloc_get_type_abort(*((void * const *)rule->uctx), module_list_t);
319 
320  /*
321  * We assume the submodule's config is the
322  * in a section with the same name as
323  * the submodule.
324  */
325  submodule_cs = cf_section_find(cs, name, NULL);
326 
327  /*
328  * Allocate an empty section if one doesn't exist
329  * this is so defaults get parsed.
330  */
331  if (!submodule_cs) submodule_cs = cf_section_alloc(cs, cs, name, NULL);
332 
333  /*
334  * The submodule name dictates the module loaded
335  * the instance name is always the submodule name
336  * and will be appended to the parent's instance
337  * name.
338  */
340  if (unlikely(mi == NULL)) {
341  cf_log_err(submodule_cs, "Failed loading submodule");
342  return -1;
343  }
344 
345  if (unlikely(module_conf_parse(mi, submodule_cs) < 0)) {
346  cf_log_err(submodule_cs, "Failed parsing submodule config");
347  talloc_free(mi);
348  return -1;
349  }
350 
351  *((module_instance_t **)out) = mi;
352 
353  return 0;
354 }
355 
356 /** Find an existing module instance by its name and parent
357  *
358  * @param[in] ml to search in.
359  * @param[in] parent to qualify search with.
360  * @param[in] asked_name The name of the module we're attempting to find.
361  * May include '-' which indicates that it's ok for
362  * the module not to be loaded.
363  * @return
364  * - Module instance matching name.
365  * - NULL if no such module exists.
366  */
367 module_instance_t *module_by_name(module_list_t const *ml, module_instance_t const *parent, char const *asked_name)
368 {
369  char const *inst_name;
370  void *inst;
371 
372  if (!ml->name_tree) return NULL;
373 
374  /*
375  * Look for the real name. Ignore the first character,
376  * which tells the server "it's OK for this module to not
377  * exist."
378  */
379  inst_name = asked_name;
380  if (inst_name[0] == '-') inst_name++;
381 
382  inst = fr_rb_find(ml->name_tree,
384  .dl_inst = &(dl_module_inst_t){ .parent = parent ? parent->dl_inst : NULL },
385  .name = inst_name
386  });
387  if (!inst) return NULL;
388 
389  return talloc_get_type_abort(inst, module_instance_t);
390 }
391 
392 /** Find the module's parent (if any)
393  *
394  * @param[in] child to locate the parent for.
395  * @return
396  * - The module's parent.
397  * - NULL on error.
398  */
400 {
401  dl_module_inst_t const *parent;
402 
404  if (!parent) return NULL;
405 
406  return module_by_data(child->ml, parent->data);
407 }
408 
409 /** Find the module's shallowest parent
410  *
411  * @param[in] child to locate the root for.
412  * @return
413  * - The module's shallowest parent.
414  * - NULL on error.
415  */
417 {
418  module_instance_t *next;
419 
420  for (;;) {
421  next = module_parent(child);
422  if (!next) break;
423 
424  child = next;
425  }
426 
427  return UNCONST(module_instance_t *, child);
428 }
429 
430 /** Find an existing module instance by its private instance data
431  *
432  * @param[in] ml to search in.
433  * @param[in] data to resolve to module_instance_t.
434  * @return
435  * - Module instance matching data.
436  * - NULL if no such module exists.
437  */
439 {
440  module_instance_t *mi;
441 
442  mi = fr_rb_find(ml->data_tree,
444  .dl_inst = &(dl_module_inst_t){ .data = UNCONST(void *, data) },
445  });
446  if (!mi) return NULL;
447 
448  return talloc_get_type_abort(mi, module_instance_t);
449 }
450 
451 
452 /** Retrieve module/thread specific instance for a module
453  *
454  * @param[in] mi to find thread specific data for.
455  * @return
456  * - Thread specific instance data on success.
457  * - NULL if module has no thread instance data.
458  */
460 {
462 
463  fr_assert(mi->number < talloc_array_length(module_thread_inst_list));
466  "mismatch between global module heap (%u entries) and thread local (%zu entries)",
468 
469  ti = talloc_get_type_abort(module_thread_inst_list[mi->inst_idx - 1], module_thread_instance_t);
470  fr_assert_msg(ti->mi == mi, "thread/module mismatch thread %s (%p), module %s (%p)",
471  ti->mi->name, ti->mi, mi->name, mi);
472  return ti;
473 }
474 
475 /** Retrieve module/thread specific instance data for a module
476  *
477  * @param[in] ml Module list module belongs to.
478  * @param[in] data Private instance data of the module.
479  * Same as what would be provided by
480  * #module_by_data.
481  * @return
482  * - Thread specific instance data on success.
483  * - NULL if module has no thread instance data.
484  */
486 {
489  if (!mi) return NULL;
490 
491  fr_assert(mi->number < ml->last_number);
494  "mismatch between global module heap (%u entries) and thread local (%zu entries)",
496 
497  ti = talloc_get_type_abort(module_thread_inst_list[mi->inst_idx - 1], module_thread_instance_t);
498  fr_assert_msg(ti->mi == mi, "thread/module mismatch thread %s (%p), module %s (%p)",
499  ti->mi->name, ti->mi, mi->name, mi);
500  return ti;
501 }
502 
503 /** Explicitly free a module if a fatal error occurs during bootstrap
504  *
505  * @param[in] mi to free.
506  */
508 {
509  talloc_free(mi);
510 }
511 
512 /** Remove thread-specific data for a given module list
513  *
514  * Removes all module thread data for the
515  */
517 {
519  void *instance;
520 
521  /*
522  * Loop over all the modules in the module list
523  * finding and extracting their thread specific
524  * data, and calling their detach methods.
525  */
526  for (instance = fr_rb_iter_init_inorder(&iter, ml->name_tree);
527  instance;
528  instance = fr_rb_iter_next_inorder(&iter)) {
529  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
530 
532  }
533 }
534 
536 {
537  module_instance_t const *mi = ti->mi;
538 
539  module_list_in_sync = false; /* Help catch anything attempting to do lookups */
540 
541  DEBUG4("Worker cleaning up %s thread instance data (%p/%p)",
542  mi->module->name, ti, ti->data);
543 
544  if (mi->module->thread_detach) {
546  .inst = ti->mi->dl_inst,
547  .thread = ti->data,
548  .el = ti->el
549  });
550  }
551 
552  /*
553  * Pull the thread instance out of the tree
554  */
555  module_thread_inst_list[ti->mi->inst_idx - 1] = NULL;
556  return 0;
557 }
558 
559 /** Free the thread local heap on exit
560  *
561  * All thread local module lists should have been destroyed by this point
562  */
563 static int _module_thread_inst_list_free(void *tilp)
564 {
565  module_thread_instance_t **til = talloc_get_type_abort(tilp, module_thread_instance_t *);
566  size_t i, len = talloc_array_length(til);
567  unsigned int found = 0;
568 
569  for (i = 0; i < len; i++) if (til[i]) found++;
570 
571 
572  if (!fr_cond_assert_msg(found == 0,
573  "Thread local array has %u non-null elements remaining on exit. This is a leak",
574  found)) {
575  return -1;
576  }
577 
578  return talloc_free(til);
579 }
580 
581 /** Allocate thread-local instance data for a module
582  *
583  * The majority of modules will have a single set of thread-specific instance data.
584  *
585  * An exception is dynamic modules, which may have multiple sets of thread-specific instance data tied to
586  * a specific dynamic use of that module.
587  *
588  * @param[in] ctx Talloc ctx to bind thread specific data to.
589  * @param[out] out Where to write the allocated #module_thread_instance_t.
590  * @param[in] ml Module list to perform thread instantiation for.
591  * @param[in] mi Module instance to perform thread instantiation for.
592  * @param[in] el Event list serviced by this thread.
593  * @return
594  * - 0 on success.
595  * - -1 on failure.
596  */
598 {
600  TALLOC_CTX *our_ctx = ctx;
601 
602  /*
603  * Check the list pointers are ok
604  */
605  (void)talloc_get_type_abort(mi->ml, module_list_t);
606 
607  MEM(ti = talloc_zero(our_ctx, module_thread_instance_t));
608  talloc_set_destructor(ti, _module_thread_inst_free);
609  ti->el = el;
610  ti->mi = mi;
611 
612  if (mi->module->thread_inst_size) {
613  module_instance_t *rmi;
614 
615  MEM(ti->data = talloc_zero_array(ti, uint8_t, mi->module->thread_inst_size));
616  rmi = module_root(mi);
617 
618  /*
619  * Fixup the type name, in case something calls
620  * talloc_get_type_abort() on it...
621  */
622  if (!mi->module->thread_inst_type) {
623  talloc_set_name(ti->data, "%s_%s_thread_t",
625  rmi ? rmi->dl_inst->module->type :
626  mi->dl_inst->module->type,
627  "<INVALID>"),
628  mi->module->name);
629  } else {
630  talloc_set_name_const(ti->data, mi->module->thread_inst_type);
631  }
632  }
633 
634  /*
635  * So we don't get spurious errors
636  */
638 
639  DEBUG4("Alloced %s thread instance data (%p/%p)", ti->mi->module->name, ti, ti->data);
640  if (mi->module->thread_instantiate &&
642  PERROR("Thread instantiation failed for module \"%s\"", mi->name);
643  /* Leave module_thread_inst_list intact, other modules may need to clean up */
645  return -1;
646  }
647  *out = ti;
648 
649  return 0;
650 }
651 
652 /** Creates per-thread instance data for modules which need it
653  *
654  * Must be called by any new threads before attempting to execute unlang sections.
655  *
656  * @param[in] ctx Talloc ctx to bind thread specific data to.
657  * @param[in] ml Module list to perform thread instantiation for.
658  * @param[in] el Event list serviced by this thread.
659  * @return
660  * - 0 on success.
661  * - -1 on failure.
662  */
664 {
665  void *instance;
667 
668  /*
669  * Initialise the thread specific tree if this is the
670  * first time through or if everything else was
671  * de-initialised.
672  */
675 
676  arr = talloc_zero_array(NULL, module_thread_instance_t *,
678 
680  }
681 
682  for (instance = fr_rb_iter_init_inorder(&iter, ml->name_tree);
683  instance;
684  instance = fr_rb_iter_next_inorder(&iter)) {
685  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
687 
688  if (module_thread_instantiate(ctx, &ti, ml, mi, el) < 0) return -1;
689  module_thread_inst_list[ti->mi->inst_idx - 1] = ti;
690  }
691 
692  return 0;
693 }
694 
695 /** Manually complete module setup by calling its instantiate function
696  *
697  * @param[in] instance of module to complete instantiation for.
698  * @return
699  * - 0 on success.
700  * - -1 on failure.
701  */
703 {
704  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
705  CONF_SECTION *cs = mi->dl_inst->conf;
706 
707  /*
708  * We only instantiate modules in the bootstrapped state
709  */
710  if (mi->state != MODULE_INSTANCE_BOOTSTRAPPED) return 0;
711 
712  if (mi->dl_inst->module->type == DL_MODULE_TYPE_MODULE) {
713  if (fr_command_register_hook(NULL, mi->name, mi, module_cmd_table) < 0) {
714  PERROR("Failed registering radmin commands for module %s", mi->name);
715  return -1;
716  }
717  }
718 
719  /*
720  * Now that ALL modules are instantiated, and ALL xlats
721  * are defined, go compile the config items marked as XLAT.
722  */
723  if (mi->module->config && (cf_section_parse_pass2(mi->dl_inst->data,
724  mi->dl_inst->conf) < 0)) return -1;
725 
726  /*
727  * Call the instantiate method, if any.
728  */
729  if (mi->module->instantiate) {
730  cf_log_debug(cs, "Instantiating %s_%s \"%s\"",
732  mi->dl_inst->module->common->name,
733  mi->name);
734 
735  /*
736  * Call the module's instantiation routine.
737  */
738  if (mi->module->instantiate(MODULE_INST_CTX(mi->dl_inst)) < 0) {
739  cf_log_err(mi->dl_inst->conf, "Instantiation failed for module \"%s\"", mi->name);
740 
741  return -1;
742  }
743  }
745 
746  return 0;
747 }
748 
749 /** Completes instantiation of modules
750  *
751  * Allows the module to initialise connection pools, and complete any registrations that depend on
752  * attributes created during the bootstrap phase.
753  *
754  * @param[in] ml containing modules to instantiate.
755  * @return
756  * - 0 on success.
757  * - -1 on failure.
758  */
760 {
761  void *instance;
763 
764  DEBUG2("#### Instantiating %s modules ####", ml->name);
765 
766  for (instance = fr_rb_iter_init_inorder(&iter, ml->name_tree);
767  instance;
768  instance = fr_rb_iter_next_inorder(&iter)) {
769  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
770  if (mi->state != MODULE_INSTANCE_BOOTSTRAPPED) continue;
771 
772  if (module_instantiate(mi) < 0) return -1;
773  }
774 
775  return 0;
776 }
777 
778 /** Manually complete module bootstrap by calling its instantiate function
779  *
780  * - Parse the module configuration.
781  * - Call the modules "bootstrap" method.
782  *
783  * @param[in] mi Module instance to bootstrap.
784  * @return
785  * - 0 on success.
786  * - -1 on failure.
787  */
789 {
790  /*
791  * We only bootstrap modules in the init state
792  */
793  if (mi->state != MODULE_INSTANCE_INIT) return 0;
794 
795  /*
796  * Bootstrap the module.
797  * This must be done last so that the
798  * module can find its module_instance_t
799  * in the trees if it needs to bootstrap
800  * submodules.
801  */
802  if (mi->module->bootstrap) {
803  CONF_SECTION *cs = mi->dl_inst->conf;
804 
805  cf_log_debug(cs, "Bootstrapping %s_%s \"%s\"",
807  mi->dl_inst->module->common->name,
808  mi->name);
809 
810  if (mi->module->bootstrap(MODULE_INST_CTX(mi->dl_inst)) < 0) {
811  cf_log_err(cs, "Bootstrap failed for module \"%s\"", mi->name);
812  return -1;
813  }
814  }
816 
817  return 0;
818 }
819 
820 /** Bootstrap any modules which have not been bootstrapped already
821  *
822  * Allows the module to initialise connection pools, and complete any registrations that depend on
823  * attributes created during the bootstrap phase.
824  *
825  * @param[in] ml containing modules to bootstrap.
826  * @return
827  * - 0 on success.
828  * - -1 on failure.
829  */
831 {
832  void *instance;
834 
835  DEBUG2("#### Bootstrapping %s modules ####", ml->name);
836 
837  for (instance = fr_rb_iter_init_inorder(&iter, ml->name_tree);
838  instance;
839  instance = fr_rb_iter_next_inorder(&iter)) {
840  module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
841  if (mi->state != MODULE_INSTANCE_INIT) continue;
842 
843  if (module_bootstrap(mi) < 0) return -1;
844  }
845 
846  return 0;
847 }
848 
849 /** Generate a module name from the module's name and its parents
850  *
851  * @param[in] ctx Where to allocate the module name.
852  * @param[out] out Where to write a pointer to the instance name.
853  * @param[in] ml Module list in which to find the parent.
854  * @param[in] parent of the module.
855  * @param[in] inst_name module's instance name.
856  */
857 static fr_slen_t module_instance_name(TALLOC_CTX *ctx, char **out, module_list_t const *ml,
858  module_instance_t const *parent, char const *inst_name)
859 {
860  fr_sbuff_t *agg;
861 
862  FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 64, 256);
863 
864  while (parent) {
865  FR_SBUFF_IN_STRCPY_RETURN(agg, parent->name);
866  FR_SBUFF_IN_CHAR_RETURN(agg, '.');
867 
868  if (!parent->dl_inst->parent) break;
869 
870  parent = module_by_data(ml, parent->dl_inst->parent->data);
871  }
872 
873  FR_SBUFF_IN_STRCPY_RETURN(agg, inst_name);
874 
875  MEM(*out = talloc_bstrndup(ctx, fr_sbuff_start(agg), fr_sbuff_used(agg)));
876 
877  return fr_sbuff_used(agg);
878 
879 }
880 
881 /** Free module's instance data, and any xlats or paircmps
882  *
883  * @param[in] mi to free.
884  * @return 0
885  */
887 {
888  module_list_t *ml = mi->ml;
889 
890  DEBUG3("Freeing %s (%p)", mi->name, mi);
891 
893  if (fr_rb_node_inline_in_tree(&mi->name_node) && !fr_cond_assert(fr_rb_delete(ml->name_tree, mi))) return 1;
894  if (fr_rb_node_inline_in_tree(&mi->data_node) && !fr_cond_assert(fr_rb_delete(ml->data_tree, mi))) return 1;
895 
896  /*
897  * mi->module may be NULL if we failed loading the module
898  */
899  if (mi->module && ((mi->module->flags & MODULE_TYPE_THREAD_UNSAFE) != 0)) {
900 #ifndef NDEBUG
901  int ret;
902 
903  /*
904  * If the mutex is locked that means
905  * the server exited without cleaning
906  * up requests.
907  *
908  * Assert that the mutex is not held.
909  */
910  ret = pthread_mutex_trylock(&mi->mutex);
911  fr_assert_msg(ret == 0, "Failed locking module mutex during exit: %s", fr_syserror(ret));
912  pthread_mutex_unlock(&mi->mutex);
913 #endif
914  pthread_mutex_destroy(&mi->mutex);
915  }
916 
917  /*
918  * Remove all xlat's registered to module instance.
919  */
920  if (mi->dl_inst && mi->dl_inst->data) {
923  }
924 
925  /*
926  * We need to explicitly free all children, so the module instance
927  * destructors get executed before we unload the bytecode for the
928  * module.
929  *
930  * If we don't do this, we get a SEGV deep inside the talloc code
931  * when it tries to call a destructor that no longer exists.
932  */
933  talloc_free_children(mi);
934 
935  return 0;
936 }
937 
938 /** Parse the configuration associated with a module
939  *
940  * @param[in] mi To parse the configuration for.
941  * @param[in] mod_conf To parse.
942  * @return
943  * - 0 on success.
944  * - -1 on failure.
945  */
947 {
948  if (dl_module_conf_parse(mi->dl_inst, mod_conf) < 0) return -1;
949 
950  return 0;
951 }
952 
953 /** Allocate a new module and add it to a module list for later bootstrap/instantiation
954  *
955  * - Load the module shared library.
956  * - Allocate instance data for it.
957  *
958  * @param[in] ml To add module to.
959  * @param[in] parent of the module being bootstrapped, if this is a submodule.
960  * If this is not a submodule parent must be NULL.
961  * @param[in] type What type of module we're loading. Determines the prefix
962  * added to the library name. Should be one of:
963  * - DL_MODULE_TYPE_MODULE - Standard backend module.
964  * - DL_MODULE_TYPE_SUBMODULE - Usually a driver for a backend module.
965  * - DL_MODULE_TYPE_PROTO - A module associated with a listen section.
966  * - DL_MODULE_TYPE_PROCESS - Protocol state machine bound to a virtual server.
967  * @param[in] mod_name The name of this module, i.e. 'redis' for 'rlm_redis'.
968  * @param[in] inst_name Instance name for this module, i.e. "aws_redis_01".
969  * The notable exception is if this is a submodule, in which case
970  * inst_name is usually the mod_name.
971  * @return
972  * - A new module instance handle, containing the module's public interface,
973  * and private instance data.
974  * - NULL on error.
975  */
977  module_instance_t const *parent,
978  dl_module_type_t type, char const *mod_name, char const *inst_name)
979 {
980  char *qual_inst_name = NULL;
981  module_instance_t *mi;
982 
985  (type == DL_MODULE_TYPE_PROTO) ||
987 
988  /*
989  * Takes the inst_name and adds qualifiers
990  * if this is a submodule.
991  */
992  if (module_instance_name(NULL, &qual_inst_name, ml, parent, inst_name) < 0) {
993  ERROR("Module name too long");
994  return NULL;
995  }
996 
997  /*
998  * See if the module already exists.
999  */
1000  mi = module_by_name(ml, parent, qual_inst_name);
1001  if (mi) {
1002  /*
1003  * We may not have configuration data yet
1004  * for the duplicate module.
1005  */
1006  if (mi->dl_inst->conf) {
1007  ERROR("Duplicate %s_%s instance \"%s\", previous instance defined at %s[%d]",
1009  mi->dl_inst->module->common->name,
1010  qual_inst_name,
1011  cf_filename(mi->dl_inst->conf),
1012  cf_lineno(mi->dl_inst->conf));
1013 
1014  } else {
1015  ERROR("Duplicate %s_%s instance \"%s\"",
1017  mi->dl_inst->module->common->name,
1018  qual_inst_name);
1019  }
1020  talloc_free(qual_inst_name);
1021  return NULL;
1022  }
1023 
1024  MEM(mi = talloc_zero(parent ? (void const *)parent : (void const *)ml, module_instance_t));
1025  if (dl_module_instance(mi, &mi->dl_inst, parent ? parent->dl_inst : NULL,
1026  type, mod_name, qual_inst_name) < 0) {
1027  error:
1028  mi->name = qual_inst_name; /* Assigned purely for debug log output when mi is freed */
1029  talloc_free(mi);
1030  talloc_free(qual_inst_name);
1031  return NULL;
1032  }
1033  fr_assert(mi->dl_inst);
1034 
1035  mi->module = (module_t const *)mi->dl_inst->module->common;
1036  if (!mi->module) {
1037  ERROR("Missing public structure for \"%s\"", qual_inst_name);
1038  talloc_free(mi);
1039  return NULL;
1040  }
1041 
1042  /*
1043  * If we're threaded, check if the module is thread-safe.
1044  *
1045  * If it isn't, we init the mutex.
1046  *
1047  * Do this here so the destructor can trylock the mutex
1048  * correctly even if bootstrap/instantiation fails.
1049  */
1050  if ((mi->module->flags & MODULE_TYPE_THREAD_UNSAFE) != 0) pthread_mutex_init(&mi->mutex, NULL);
1051  talloc_set_destructor(mi, _module_instance_free);
1052 
1053  mi->name = talloc_typed_strdup(mi, qual_inst_name);
1054  talloc_free(qual_inst_name); /* Avoid stealing */
1055 
1056  mi->number = ml->last_number++;
1057  mi->ml = ml;
1058 
1059  /*
1060  * Remember the module for later.
1061  */
1062  if (!fr_cond_assert(fr_rb_insert(ml->name_tree, mi))) goto error;
1063 
1064  /*
1065  * Allow modules to get at their own
1066  * module_instance_t data, for
1067  * looking up thread specific data
1068  * and for bootstrapping submodules.
1069  */
1070  if (mi->dl_inst->data && !fr_cond_assert(fr_rb_insert(ml->data_tree, mi))) goto error;
1071 
1072  /*
1073  * ...and finally insert the module
1074  * into the global heap so we can
1075  * get common thread-local indexes.
1076  */
1077  if (fr_heap_insert(&module_global_inst_list, mi) < 0) goto error;
1078 
1079  return mi;
1080 }
1081 
1082 /** Free all modules loaded by the server
1083  *
1084  * @param[in] ml Module list being freed.
1085  * @return 0
1086  */
1088 {
1089  fr_rb_iter_inorder_t iter;
1090  module_instance_t *mi;
1091 
1092  /*
1093  * Re-initialize the iterator after freeing each module.
1094  * The module may have children which are also in the
1095  * tree. It can cause problems when we delete children
1096  * without the iterator knowing about it.
1097  */
1098  while ((mi = fr_rb_iter_init_inorder(&iter, ml->name_tree)) != NULL) {
1099  fr_rb_iter_delete_inorder(&iter); /* Keeps the iterator sane */
1100  talloc_free(mi);
1101  }
1102 
1103  return 0;
1104 }
1105 
1106 /** Allocate a new module list
1107  *
1108  * This is used to instantiate and destroy modules in distinct phases
1109  * for example, we may need to load all proto modules before rlm modules.
1110  *
1111  * If the list is freed all module instance data will be freed.
1112  * If no more instances of the module exist the module be unloaded.
1113  *
1114  * @param[in] ctx To allocate the list in.
1115  * @param[in] name of the list.
1116  * @return A new module list.
1117  */
1118 module_list_t *module_list_alloc(TALLOC_CTX *ctx, char const *name)
1119 {
1120  module_list_t *ml;
1121 
1122  MEM(ml = talloc_zero(ctx, module_list_t));
1123  talloc_set_destructor(ml, _module_list_free);
1124 
1125  MEM(ml->name = talloc_typed_strdup(ml, name));
1128 
1129  return ml;
1130 }
1131 
1132 static int _module_global_list_init(void *uctx)
1133 {
1136 
1137  /*
1138  * Ensure the common library tracking
1139  * tree is in place...
1140  */
1141  global_lib_init();
1142 
1143  return 0;
1144 }
1145 
1146 static int _module_global_list_free(UNUSED void *uctx)
1147 {
1148 
1150  "Global module heap has %u elements remaining on exit. This is a leak",
1152  if (talloc_free(module_global_inst_list) < 0) return -1;
1153  module_global_inst_list = NULL;
1154 
1155  if (talloc_free(dl_modules) < 0) return -1;
1156  dl_modules = NULL;
1157  return 0;
1158 }
1159 
1160 /** Perform global initialisation for modules
1161  *
1162  */
1163 void modules_init(char const *lib_dir)
1164 {
1165  /*
1166  * Create the global module heap we use for
1167  * common indexes in the thread-specific
1168  * heaps.
1169  */
1171 }
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition: atexit.h:221
#define fr_atexit_global_once(_init, _free, _uctx)
Definition: atexit.h:211
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition: build.h:110
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
int cf_section_write(FILE *fp, CONF_SECTION *cs, int depth)
Definition: cf_file.c:3141
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
Definition: cf_parse.c:1163
void const * uctx
User data accessible by the cf_parse_t func.
Definition: cf_parse.h:586
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
Common header for all CONF_* types.
Definition: cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:629
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:970
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_lineno(_cf)
Definition: cf_util.h:101
#define cf_parent(_cf)
Definition: cf_util.h:98
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition: cf_util.h:137
#define cf_filename(_cf)
Definition: cf_util.h:104
#define cf_log_debug(_cf, _fmt,...)
Definition: cf_util.h:268
fr_command_register_hook_t fr_command_register_hook
Definition: command.c:42
bool fr_command_strncmp(const char *word, const char *name)
Definition: command.c:2906
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:137
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition: debug.h:208
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:154
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
int dl_module_instance(TALLOC_CTX *ctx, dl_module_inst_t **out, dl_module_inst_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Load a module and parse its CONF_SECTION in one operation.
Definition: dl_module.c:552
fr_table_num_sorted_t const dl_module_type_prefix[]
Name prefixes matching the types of loadable module.
Definition: dl_module.c:66
dl_module_inst_t const * dl_module_parent_instance(dl_module_inst_t const *child)
Lookup a module's parent.
Definition: dl_module.c:207
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
Definition: dl_module.c:706
int dl_module_conf_parse(dl_module_inst_t *dl_inst, CONF_SECTION *conf)
Definition: dl_module.c:594
Wrapper struct around dl_loader_t.
Definition: dl_module.c:46
dl_module_type_t _CONST type
of this module.
Definition: dl_module.h:147
dl_module_type_t
Definition: dl_module.h:67
@ DL_MODULE_TYPE_PROTO
Protocol module.
Definition: dl_module.h:69
@ DL_MODULE_TYPE_SUBMODULE
Driver (or method in the case of EAP)
Definition: dl_module.h:71
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
Definition: dl_module.h:68
@ DL_MODULE_TYPE_PROCESS
protocol processor.
Definition: dl_module.h:70
dl_module_t const *_CONST module
Module.
Definition: dl_module.h:164
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
dl_module_common_t const *_CONST common
Symbol exported by the module, containing its public functions, name and behaviour control flags.
Definition: dl_module.h:149
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
Definition: dl_module.h:167
A module/inst tuple.
Definition: dl_module.h:162
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
#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
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define DEBUG4(_fmt,...)
Definition: log.h:267
talloc_free(reap)
Stores all information relating to an event list.
Definition: event.c:411
static char const * mod_name(fr_listen_t *li)
Definition: master.c:2704
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
#define MODULE_INST_CTX(_dl_inst)
Wrapper to create a module_inst_ctx_t as a compound literal.
Definition: module_ctx.h:153
#define MODULE_THREAD_INST_CTX(_dl_inst, _thread, _el)
Wrapper to create a module_thread_inst_ctx_t as a compound literal.
Definition: module_ctx.h:165
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:58
#define DEBUG2(fmt,...)
Definition: radclient.h:43
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition: rb.c:892
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:844
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition: rb.c:624
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition: rb.c:736
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition: rb.c:818
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition: rb.c:576
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition: rb.h:271
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:314
Iterator structure for in-order traversal of an rbtree.
Definition: rb.h:321
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:40
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
Definition: rcode.h:51
static char const * name
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
module_instance_t const * mi
As opposed to the thread local inst.
Definition: module.h:224
char const * name
Instance name e.g. user_database.
Definition: module.h:181
@ MODULE_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: module.h:50
fr_rb_node_t name_node
Entry in the name tree.
Definition: module.h:174
bool force
Force the module to return a specific code.
Definition: module.h:200
module_instance_state_t state
What's been done with this module so far.
Definition: module.h:195
module_thread_instantiate_t thread_instantiate
Definition: module.h:148
module_instantiate_t instantiate
Definition: module.h:146
fr_rb_tree_t * name_tree
Modules indexed by name.
Definition: module.h:238
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
Definition: module.h:183
void * data
Thread specific instance data.
Definition: module.h:220
rlm_rcode_t code
Code module will return when 'force' has has been set to true.
Definition: module.h:203
fr_rb_tree_t * data_tree
Modules indexed by data.
Definition: module.h:239
fr_heap_index_t inst_idx
Entry in the bootstrap/instantiation heap.
Definition: module.h:170
@ MODULE_INSTANCE_INSTANTIATED
Definition: module.h:160
@ MODULE_INSTANCE_INIT
Definition: module.h:158
@ MODULE_INSTANCE_BOOTSTRAPPED
Definition: module.h:159
uint32_t number
Unique module number.
Definition: module.h:179
char const * thread_inst_type
Definition: module.h:150
module_instantiate_t bootstrap
Definition: module.h:145
fr_rb_node_t data_node
Entry in the data tree.
Definition: module.h:175
module_thread_detach_t thread_detach
Definition: module.h:149
int flags
Definition: module.h:147
module_t const * module
Public module structure.
Definition: module.h:188
uint32_t last_number
Last identifier assigned to a module instance.
Definition: module.h:236
module_list_t * ml
Module list this instance belongs to.
Definition: module.h:177
size_t thread_inst_size
Definition: module.h:151
char const * name
Friendly list identifier.
Definition: module.h:237
fr_event_list_t * el
Event list associated with this thread.
Definition: module.h:222
pthread_mutex_t mutex
Used prevent multiple threads entering a thread unsafe module simultaneously.
Definition: module.h:192
Per instance data.
Definition: module.h:169
A list of modules.
Definition: module.h:235
Struct exported by a rlm_* module.
Definition: module.h:142
Per thread per instance data.
Definition: module.h:215
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition: module.c:1163
static int _module_list_free(module_list_t *ml)
Free all modules loaded by the server.
Definition: module.c:1087
static int module_thread_instantiate(TALLOC_CTX *ctx, module_thread_instance_t **out, module_list_t const *ml, module_instance_t *mi, fr_event_list_t *el)
Allocate thread-local instance data for a module.
Definition: module.c:597
static int _module_instance_free(module_instance_t *mi)
Free module's instance data, and any xlats or paircmps.
Definition: module.c:886
module_instance_t * module_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:367
static fr_slen_t module_instance_name(TALLOC_CTX *ctx, char **out, module_list_t const *ml, module_instance_t const *parent, char const *inst_name)
Generate a module name from the module's name and its parents.
Definition: module.c:857
static int _module_thread_inst_list_free(void *tilp)
Free the thread local heap on exit.
Definition: module.c:563
module_thread_instance_t * module_thread(module_instance_t *mi)
Retrieve module/thread specific instance for a module.
Definition: module.c:459
static int cmd_show_module_status(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
Definition: module.c:189
static _Thread_local bool module_list_in_sync
Toggle used to determine if it's safe to use index based lookups.
Definition: module.c:65
static int8_t module_instance_data_cmp(void const *one, void const *two)
Compare module's by their private instance data.
Definition: module.c:288
static int8_t module_instance_name_cmp(void const *one, void const *two)
Compare module instances by parent and name.
Definition: module.c:250
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:663
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:178
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:152
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition: module.c:759
static int8_t _module_instance_global_cmp(void const *one, void const *two)
Sort module instance data first by list then by number.
Definition: module.c:231
module_instance_t * module_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
Definition: module.c:976
module_instance_t * module_by_data(module_list_t const *ml, void const *data)
Find an existing module instance by its private instance data.
Definition: module.c:438
static int cmd_set_module_status(UNUSED FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
Definition: module.c:203
int module_conf_parse(module_instance_t *mi, CONF_SECTION *mod_conf)
Parse the configuration associated with a module.
Definition: module.c:946
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:485
static int cmd_show_module_config(FILE *fp, UNUSED FILE *fp_err, void *ctx, UNUSED fr_cmd_info_t const *info)
Definition: module.c:141
void modules_thread_detach(module_list_t const *ml)
Remove thread-specific data for a given module list.
Definition: module.c:516
void module_free(module_instance_t *mi)
Explicitly free a module if a fatal error occurs during bootstrap.
Definition: module.c:507
static fr_heap_t * module_global_inst_list
Heap of all lists/modules used to get a common index with module_thread_inst_list.
Definition: module.c:44
return count
Definition: module.c:175
static _Thread_local module_thread_instance_t ** module_thread_inst_list
An array of thread-local module lists.
Definition: module.c:52
static int _module_thread_inst_free(module_thread_instance_t *ti)
Definition: module.c:535
static dl_module_loader_t * dl_modules
dl module tracking
Definition: module.c:70
fr_cmd_table_t module_cmd_list_table[]
Definition: module.c:111
static int _module_global_list_init(void *uctx)
Definition: module.c:1132
module_instance_t * module_root(module_instance_t const *child)
Find the module's shallowest parent.
Definition: module.c:416
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition: module.c:830
fr_cmd_table_t module_cmd_table[]
Definition: module.c:78
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
Definition: module.c:702
static int _module_global_list_free(UNUSED void *uctx)
Definition: module.c:1146
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:311
module_instance_t * module_parent(module_instance_t const *child)
Find the module's parent (if any)
Definition: module.c:399
module_list_t * module_list_alloc(TALLOC_CTX *ctx, char const *name)
Allocate a new module list.
Definition: module.c:1118
int module_bootstrap(module_instance_t *mi)
Manually complete module bootstrap by calling its instantiate function.
Definition: module.c:788
if(!subtype_vp) goto fail
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
char 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:134
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:333
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition: talloc.c:452
#define talloc_get_type_abort_const
Definition: talloc.h:270
static fr_event_list_t * el
static fr_slen_t parent
Definition: pair.h:844
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition: xlat_func.c:531
void xlat_func_unregister_module(dl_module_inst_t const *inst)
Definition: xlat_func.c:545