The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
dl_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: 742541762963c4cfc46f723070b93ccf301f9c36 $
19  *
20  * @file src/lib/server/dl_module.c
21  * @brief Wrappers around dlopen to manage loading modules at runtime.
22  *
23  * @copyright 2016-2019 The FreeRADIUS server project
24  * @copyright 2016-2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  */
26 RCSID("$Id: 742541762963c4cfc46f723070b93ccf301f9c36 $")
27 #define _DL_MODULE_PRIVATE 1
28 #include <freeradius-devel/server/dl_module.h>
29 
30 #include <freeradius-devel/server/log.h>
31 #include <freeradius-devel/server/global_lib.h>
32 #include <freeradius-devel/util/debug.h>
33 
34 #include <freeradius-devel/util/dl.h>
35 #include <freeradius-devel/util/syserror.h>
36 
37 #include <pthread.h>
38 #include <ctype.h>
39 #include <unistd.h>
40 
41 #define DL_INIT_CHECK fr_assert(dl_module_loader)
42 
43 /** Wrapper struct around dl_loader_t
44  *
45  * Provides space to store instance data.
46  */
48  pthread_mutex_t lock; //!< Protects the module tree when multiple threads are loading modules simultaneously.
49  fr_rb_tree_t *module_tree; //!< Module's dl handles.
50  dl_loader_t *dl_loader; //!< A list of loaded libraries, and symbol to callback mappings.
51 };
52 
54 
55 /** Name prefixes matching the types of loadable module
56  */
58  { L(""), DL_MODULE_TYPE_SUBMODULE },
59  { L("process"), DL_MODULE_TYPE_PROCESS },
60  { L("proto"), DL_MODULE_TYPE_PROTO },
61  { L("rlm"), DL_MODULE_TYPE_MODULE }
62 };
64 
65 static int8_t dl_module_cmp(void const *one, void const *two)
66 {
67  dl_module_t const *a = one, *b = two;
68  int ret;
69 
70  fr_assert(a->dl);
71  fr_assert(b->dl);
72 
73  ret = strcmp(a->dl->name, b->dl->name);
74  return CMP(ret, 0);
75 }
76 
77 /** Find the module's shallowest parent, or the child if no parents are found
78  *
79  * @param[in] child to locate the root for.
80  * @return
81  * - The module's shallowest parent.
82  * - NULL on error.
83  */
84 static dl_module_t const *dl_module_root(dl_module_t const *child)
85 {
86  dl_module_t const *next;
87 
88  for (;;) {
89  next = child->parent;
90  if (!next) break;
91 
92  child = next;
93  }
94 
95  return child;
96 }
97 
98 /** Return the prefix string for the deepest module
99  *
100  * This is useful for submodules which don't have a prefix of their own.
101  * In this case we need to use the prefix of the shallowest module, which
102  * will be a proto or rlm module.
103  *
104  * @param[in] module to get the prefix for.
105  * @return The prefix string for the shallowest module.
106  */
107 static inline CC_HINT(always_inline)
108 char const *dl_module_root_prefix_str(dl_module_t const *module)
109 {
110  dl_module_t const *root = dl_module_root(module);
111 
112  return fr_table_str_by_value(dl_module_type_prefix, root->type, "<INVALID>");
113 }
114 
115 /** Call the load() function in a module's exported structure
116  *
117  * @param[in] dl to call the load function for.
118  * @param[in] symbol UNUSED.
119  * @param[in] ctx UNUSED.
120  * @return
121  * - 0 on success.
122  * - -1 on failure.
123  */
124 static int dl_module_onload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
125 {
126  dl_module_t *dl_module = talloc_get_type_abort(dl->uctx, dl_module_t);
127 
128  /*
129  * Clear pre-existing errors.
130  */
132 
133  if (dl_module->exported->onload) {
134  int ret;
135 
136  ret = dl_module->exported->onload();
137  if (ret < 0) {
138 #ifndef NDEBUG
139  PERROR("Initialisation failed for module \"%s\" - onload() returned %i",
140  dl_module->exported->name, ret);
141 #else
142  PERROR("Initialisation failed for module \"%s\"", dl_module->exported->name);
143 #endif
144  return -1;
145  }
146  }
147 
148  return 0;
149 }
150 
151 /** Call the unload() function in a module's exported structure
152  *
153  * @param[in] dl to call the unload function for.
154  * @param[in] symbol UNUSED.
155  * @param[in] ctx UNUSED.
156  */
157 static void dl_module_unload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
158 {
159  dl_module_t *dl_module = talloc_get_type_abort(dl->uctx, dl_module_t);
160 
161  /*
162  * common is NULL if we couldn't find the
163  * symbol and are erroring out.
164  */
165  if (dl_module->exported && dl_module->exported->unload) dl_module->exported->unload();
166 }
167 
168 /** Check if the magic number in the module matches the one in the library
169  *
170  * This is used to detect potential ABI issues caused by running with modules which
171  * were built for a different version of the server.
172  *
173  * @param[in] module Common fields from module's exported interface struct.
174  * @returns
175  * - 0 on success.
176  * - -1 if prefix mismatch.
177  * - -2 if version mismatch.
178  * - -3 if commit mismatch.
179  */
181 {
182 #ifdef HAVE_DLADDR
183  Dl_info dl_info;
184  dladdr(module, &dl_info);
185 #endif
186 
187  if (MAGIC_PREFIX(module->magic) != MAGIC_PREFIX(RADIUSD_MAGIC_NUMBER)) {
188 #ifdef HAVE_DLADDR
189  ERROR("Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
190 #endif
191  ERROR("Application and rlm_%s magic number (prefix) mismatch."
192  " application: %x module: %x", module->name,
194  MAGIC_PREFIX(module->magic));
195  return -1;
196  }
197 
198  if (MAGIC_VERSION(module->magic) != MAGIC_VERSION(RADIUSD_MAGIC_NUMBER)) {
199 #ifdef HAVE_DLADDR
200  ERROR("Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
201 #endif
202  ERROR("Application and rlm_%s magic number (version) mismatch."
203  " application: %lx module: %lx", module->name,
204  (unsigned long) MAGIC_VERSION(RADIUSD_MAGIC_NUMBER),
205  (unsigned long) MAGIC_VERSION(module->magic));
206  return -2;
207  }
208 
209  if (MAGIC_COMMIT(module->magic) != MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER)) {
210 #ifdef HAVE_DLADDR
211  ERROR("Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname);
212 #endif
213  ERROR("Application and rlm_%s magic number (commit) mismatch."
214  " application: %lx module: %lx", module->name,
215  (unsigned long) MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER),
216  (unsigned long) MAGIC_COMMIT(module->magic));
217  return -3;
218  }
219 
220  return 0;
221 }
222 
223 /** Decrement the reference count of the dl, eventually freeing it
224  *
225  */
226 static int _dl_module_free(dl_module_t *dl_module)
227 {
228  /*
229  * Talloc destructors access the talloc chunk after
230  * calling the destructor, which could lead to a race
231  * if the mutex is acquired within the destructor
232  * itself. This unfortunately means that we have to
233  * free modules using a dedicated free function which
234  * locks the dl_module_loader mutex.
235  *
236  * Ensure this module is not being freed using the
237  * normal talloc hierarchy, or with talloc_free().
238  */
239  fr_assert_msg(pthread_mutex_trylock(&dl_module->loader->lock) != 0,
240  "dl_module_loader->lock not held when freeing module, "
241  "use dl_module_free() to free modules, not talloc_free");
242 
243  /*
244  * Decrement refcounts, freeing at zero
245  */
246  if (--dl_module->refs > 0) return -1;
247 
248  /*
249  * dl is empty if we tried to load it and failed.
250  */
251  if (dl_module->dl) {
252  if (DEBUG_ENABLED4) {
253  DEBUG4("%s unloaded. Handle address %p, symbol address %p", dl_module->dl->name,
254  dl_module->dl->handle, dl_module->exported);
255  } else {
256  DEBUG3("%s unloaded", dl_module->dl->name);
257  }
258  }
259 
260  if (dl_module->in_tree) {
262  dl_module->in_tree = false;
263  }
264 
265  dl_free(dl_module->dl);
266 
267  return 0;
268 }
269 
270 /** Free a dl_module (when there are no more references to it)
271  *
272  * Decrement the reference count for a module, freeing it and unloading the module if there are no
273  * more references.
274  *
275  * @note This must be used to free modules, not talloc_free().
276  *
277  * @return
278  * - 0 on success.
279  * - -1 if the module wasn't freed. This likely means there are more ferences held to it.
280  */
282 {
283  int ret;
284  dl_module_loader_t *dl_module_l = dl_module->loader; /* Save this, as dl_module will be free'd */
285 
286  pthread_mutex_lock(&dl_module_l->lock);
287  ret = talloc_free(dl_module);
288  pthread_mutex_unlock(&dl_module_l->lock);
289 
290  return ret;
291 }
292 
293 /** Load a module library using dlopen() or return a previously loaded module from the cache
294  *
295  * When the dl_module_t is no longer used, talloc_free() may be used to free it.
296  *
297  * When all references to the original dlhandle are freed, dlclose() will be called on the
298  * dlhandle to unload the module.
299  *
300  * @note This function is threadsafe. Multiple callers may attempt to load the same module
301  * at the same time, and the module will only be loaded once, and will not be freed
302  * until all callers have released their references to it. This is useful for dynamic/runtime
303  * loading of modules.
304  *
305  * @param[in] parent The dl_module_t of the parent module, e.g. rlm_sql for rlm_sql_postgresql.
306  * @param[in] name of the module e.g. sql for rlm_sql.
307  * @param[in] type Used to determine module name prefixes. Must be one of:
308  * - DL_MODULE_TYPE_MODULE
309  * - DL_MODULE_TYPE_PROTO
310  * - DL_MODULE_TYPE_SUBMODULE
311  * @return
312  * - Module handle holding dlhandle, and module's public interface structure.
313  * - NULL if module couldn't be loaded, or some other error occurred.
314  */
316 {
317  dl_module_t *dl_module = NULL;
318  dl_t *dl = NULL;
319  char *module_name = NULL;
320  dl_module_common_t *common;
321 
323 
324  if (parent) {
325  module_name = talloc_typed_asprintf(NULL, "%s_%s_%s",
327  parent->exported->name, name);
328  } else {
329  module_name = talloc_typed_asprintf(NULL, "%s_%s",
331  name);
332  }
333 
334  if (!module_name) {
335  fr_strerror_const("Out of memory");
336  return NULL;
337  }
338 
339  talloc_bstr_tolower(module_name);
340 
341  pthread_mutex_lock(&dl_module_loader->lock);
342  /*
343  * If the module's already been loaded, increment the reference count.
344  */
346  &(dl_module_t){ .dl = &(dl_t){ .name = module_name }});
347  if (dl_module) {
348  dl_module->refs++;
349 
350  /*
351  * Release the lock, the caller is guaranteed to have a completely
352  * loaded module, which won't be freed out from underneath them until
353  * the reference count drops to zero.
354  */
355  pthread_mutex_unlock(&dl_module_loader->lock);
356  talloc_free(module_name);
357 
358  return dl_module;
359  }
360 
361  MEM(dl_module = talloc_zero(dl_module_loader, dl_module_t));
362  dl_module->name = talloc_strdup(dl_module, name);
363  dl_module->loader = dl_module_loader;
364  dl_module->parent = parent;
365  dl_module->type = type;
366  dl_module->refs = 1;
367  talloc_set_destructor(dl_module, _dl_module_free); /* Do this late */
368 
369  /*
370  * Pass in dl_module as the uctx so that
371  * we can get at it in any callbacks.
372  */
373  dl = dl_by_name(dl_module_loader->dl_loader, module_name, dl_module, false);
374  if (!dl) {
375  PERROR("Failed to link to module \"%s\"", module_name);
376  ERROR("Make sure it (and all its dependent libraries!) are in the search path"
377  " of your system's ld");
378  error:
379  talloc_free(module_name);
380  talloc_free(dl_module); /* Do not free dl explicitly, it's handled by the destructor */
381  pthread_mutex_unlock(&dl_module_loader->lock);
382  return NULL;
383  }
384  dl_module->dl = dl;
385 
386  DEBUG3("%s loaded, checking if it's valid", module_name);
387 
388  common = dlsym(dl->handle, module_name);
389  if (!common) {
390  ERROR("Could not find \"%s\" symbol in module: %s", module_name, dlerror());
391  goto error;
392  }
393  dl_module->exported = common;
394 
395  /*
396  * Before doing anything else, check if it's sane.
397  */
398  if (dl_module_magic_verify(common) < 0) goto error;
399 
400  DEBUG3("%s validated. Handle address %p, symbol address %p", module_name, dl, common);
401 
403  PERROR("Failed calling initializers for module \"%s\"", module_name);
404  goto error;
405  }
406 
407  DEBUG2("Loaded module %s", module_name);
408 
409  /*
410  * Add the module to the dl cache
411  */
412  dl_module->in_tree = fr_rb_insert(dl_module_loader->module_tree, dl_module);
413  if (!dl_module->in_tree) {
414  ERROR("Failed caching module \"%s\"", module_name);
415  goto error;
416  }
417 
418  /*
419  * Hold the lock for the entire module loading process.
420  *
421  * This ensures that all the global resources the module has symbol callbacks
422  * registered for, are fully populated, before something else attempts to use
423  * it.
424  */
425  pthread_mutex_unlock(&dl_module_loader->lock);
426 
427  talloc_free(module_name);
428 
429  return dl_module;
430 }
431 
433 {
434  int ret = 0;
435 
436  /*
437  * Lock must not be held when freeing the loader list.
438  */
439  fr_assert_msg(pthread_mutex_trylock(&dl_module_l->lock) == 0,
440  "dl_module_loader->lock held when attempting to free dL_module_loader_t");
441 
442  if (fr_rb_num_elements(dl_module_l->module_tree) > 0) {
443 #ifndef NDEBUG
445  void *data;
446 
447  WARN("Refusing to cleanup dl loader, the following modules are still in use:");
448  for (data = fr_rb_iter_init_inorder(&iter, dl_module_l->module_tree);
449  data;
451  dl_module_t *module = talloc_get_type_abort(data, dl_module_t);
452 
453  WARN(" %s", module->exported->name);
454  }
455 #endif
456  ret = -1;
457  goto finish;
458  }
459 
460  /*
461  * Do this as an explicit step, as this free can fail
462  */
463  ret = talloc_free(dl_module_l->dl_loader);
464  if (ret != 0) {
465  PWARN("dl loader not freed");
466  }
467 
468 finish:
469  if (ret != 0) {
470 #ifndef NDEBUG
471  WARN("This may appear as a leak in talloc memory reports");
472 #endif
473  } else {
474  dl_module_loader = NULL;
475  }
476 
477  pthread_mutex_unlock(&dl_module_l->lock);
478  pthread_mutex_destroy(&dl_module_l->lock);
479 
480  return ret;
481 }
482 
483 char const *dl_module_search_path(void)
484 {
486 }
487 
489 {
490  return dl_module_l->dl_loader;
491 }
492 
493 /** Wrapper to log errors
494  */
495 static int dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
496 {
497  int ret;
498 
499  ret = fr_dl_dict_enum_autoload(module, symbol, user_ctx);
500  if (ret < 0) PERROR("Failed autoloading enum value for \"%s\"", module->name);
501 
502  return ret;
503 }
504 
505 /** Wrapper to log errors
506  */
507 static int dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
508 {
509  int ret;
510 
511  ret = fr_dl_dict_attr_autoload(module, symbol, user_ctx);
512  if (ret < 0) PERROR("Failed autoloading attribute for \"%s\"", module->name);
513 
514  return ret;
515 }
516 
517 /** Wrapper to log errors
518  */
519 static int dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx)
520 {
521  int ret;
522 
523  ret = fr_dl_dict_autoload(module, symbol, user_ctx);
524  if (ret < 0) PERROR("Failed autoloading dictionary for \"%s\"", module->name);
525 
526  return ret;
527 }
528 
529 /** Initialise structures needed by the dynamic linker
530  *
531  */
533 {
534  if (dl_module_loader) {
535  /*
536  * Allow it to update the search path.
537  */
538  if (dl_search_path_set(dl_module_loader->dl_loader, lib_dir) < 0) {
539  return NULL;
540  }
541 
542  return dl_module_loader;
543  }
544 
545  dl_module_loader = talloc_zero(NULL, dl_module_loader_t);
546  if (!dl_module_loader) {
547  ERROR("Failed initialising uctx for dl_loader");
548  return NULL;
549  }
550  pthread_mutex_init(&dl_module_loader->lock, NULL);
551 
553  if (!dl_module_loader) {
554  PERROR("Failed initialising dl_loader");
555  error:
556  TALLOC_FREE(dl_module_loader);
557  return NULL;
558  }
559  if (lib_dir) dl_search_path_prepend(dl_module_loader->dl_loader, lib_dir);
560 
562  dl_module_cmp, NULL);
564  ERROR("Failed initialising dl->module_tree");
565  goto error;
566  }
567 
569  DL_PRIORITY_BOOTSTRAP, NULL, dl_module_onload_func, NULL) < 0) {
570  ERROR("Failed registering load() callback");
571  goto error;
572  }
573 
575  DL_PRIORITY_BOOTSTRAP, NULL, dl_module_unload_func, NULL) < 0) {
576  ERROR("Failed registering unload() callback");
577  goto error;
578  }
579 
580  /*
581  * Register dictionary autoload callbacks
582  */
584  DL_PRIORITY_DICT_ENUM, "dict_enum", dl_dict_enum_autoload, NULL);
586  DL_PRIORITY_DICT_ATTR, "dict_attr", dl_dict_attr_autoload, NULL);
588  DL_PRIORITY_DICT, "dict", dl_dict_autoload, NULL);
590  DL_PRIORITY_DICT, "dict", fr_dl_dict_autofree, NULL);
591 
592  /*
593  * Register library autoload callbacks for registering
594  * global configuration sections.
595  */
599  DL_PRIORITY_LIB, "lib", global_lib_autofree, NULL);
600 
601  talloc_set_destructor(dl_module_loader, _dl_module_loader_free);
602 
603  DEBUG4("Module linker search path(s)");
604  if (DEBUG_ENABLED4) {
605  char const *env;
606 
607 #ifdef __APPLE__
608  char buffer[PATH_MAX];
609 
610  env = getenv("LD_LIBRARY_PATH");
611  if (env) {
612  DEBUG4("LD_LIBRARY_PATH : %s", env);
613  }
614  env = getenv("DYLD_LIBRARY_PATH");
615  if (env) {
616  DEBUG4("DYLB_LIBRARY_PATH : %s", env);
617  }
618  env = getenv("DYLD_FALLBACK_LIBRARY_PATH");
619  if (env) {
620  DEBUG4("DYLD_FALLBACK_LIBRARY_PATH : %s", env);
621  }
622  env = getcwd(buffer, sizeof(buffer));
623  if (env) {
624  DEBUG4("Current directory : %s", env);
625  }
626 #else
627  env = getenv("LD_LIBRARY_PATH");
628  if (env) {
629  DEBUG4("LD_LIBRARY_PATH : %s", env);
630  }
631  DEBUG4("Defaults : /lib:/usr/lib");
632 #endif
633  }
634 
635  return dl_module_loader;
636 }
static int const char char buffer[256]
Definition: acutest.h:574
static dl_t * dl
Definition: fuzzer.c:42
#define RCSID(id)
Definition: build.h:481
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#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 UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
next
Definition: dcursor.h:178
fr_dcursor_iter_t iter
Definition: dcursor.h:147
#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:210
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
int fr_dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
void fr_dl_dict_autofree(dl_t const *module, void *symbol, void *user_ctx)
int fr_dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx)
int fr_dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
dl_loader_t * dl_loader_init(TALLOC_CTX *ctx, void *uctx, bool uctx_free, bool defer_symbol_init)
Initialise structures needed by the dynamic linker.
Definition: dl.c:885
dl_t * dl_by_name(dl_loader_t *dl_loader, char const *name, void *uctx, bool uctx_free)
Search for a dl's shared object in various locations.
Definition: dl.c:470
int dl_symbol_free_cb_register(dl_loader_t *dl_loader, unsigned int priority, char const *symbol, dl_unload_t func, void *uctx)
Register a callback to execute when a dl with a particular symbol is unloaded.
Definition: dl.c:384
int dl_search_path_prepend(dl_loader_t *dl_loader, char const *lib_dir)
Append a new search path component to the library search path.
Definition: dl.c:813
char const * dl_search_path(dl_loader_t *dl_loader)
Return current library path.
Definition: dl.c:729
int dl_symbol_init_cb_register(dl_loader_t *dl_loader, unsigned int priority, char const *symbol, dl_onload_t func, void *uctx)
Register a callback to execute when a dl with a particular symbol is first loaded.
Definition: dl.c:321
int dl_search_path_set(dl_loader_t *dl_loader, char const *lib_dir)
Set the current library path.
Definition: dl.c:788
int dl_free(dl_t const *dl)
"free" a dl handle, possibly actually freeing it, and unloading the library
Definition: dl.c:678
int dl_symbol_init(dl_loader_t *dl_loader, dl_t const *dl)
Walk over the registered init callbacks, searching for the symbols they depend on.
Definition: dl.c:233
A dynamic loader.
Definition: dl.c:81
void * handle
Handle returned by dlopen.
Definition: dl.h:62
void * uctx
API client's opaque data.
Definition: dl.h:65
char const * name
Name of the module e.g. sql.
Definition: dl.h:61
Module handle.
Definition: dl.h:58
char const * dl_module_search_path(void)
Definition: dl_module.c:483
#define DL_INIT_CHECK
Definition: dl_module.c:41
static dl_module_t const * dl_module_root(dl_module_t const *child)
Find the module's shallowest parent, or the child if no parents are found.
Definition: dl_module.c:84
dl_loader_t * dl_loader
A list of loaded libraries, and symbol to callback mappings.
Definition: dl_module.c:50
static int _dl_module_loader_free(dl_module_loader_t *dl_module_l)
Definition: dl_module.c:432
static int _dl_module_free(dl_module_t *dl_module)
Decrement the reference count of the dl, eventually freeing it.
Definition: dl_module.c:226
fr_table_num_sorted_t const dl_module_type_prefix[]
Name prefixes matching the types of loadable module.
Definition: dl_module.c:57
static void dl_module_unload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
Call the unload() function in a module's exported structure.
Definition: dl_module.c:157
static int8_t dl_module_cmp(void const *one, void const *two)
Definition: dl_module.c:65
dl_loader_t * dl_loader_from_module_loader(dl_module_loader_t *dl_module_l)
Definition: dl_module.c:488
static int dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
Definition: dl_module.c:519
fr_rb_tree_t * module_tree
Module's dl handles.
Definition: dl_module.c:49
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
Definition: dl_module.c:532
static int dl_module_onload_func(dl_t const *dl, UNUSED void *symbol, UNUSED void *ctx)
Call the load() function in a module's exported structure.
Definition: dl_module.c:124
static char const * dl_module_root_prefix_str(dl_module_t const *module)
Return the prefix string for the deepest module.
Definition: dl_module.c:108
pthread_mutex_t lock
Protects the module tree when multiple threads are loading modules simultaneously.
Definition: dl_module.c:48
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:315
static int dl_module_magic_verify(dl_module_common_t const *module)
Check if the magic number in the module matches the one in the library.
Definition: dl_module.c:180
static int dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
Definition: dl_module.c:507
static int dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx)
Wrapper to log errors.
Definition: dl_module.c:495
size_t dl_module_type_prefix_len
Definition: dl_module.c:63
static dl_module_loader_t * dl_module_loader
Definition: dl_module.c:53
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:281
Wrapper struct around dl_loader_t.
Definition: dl_module.c:47
bool _CONST in_tree
Definition: dl_module.h:143
dl_t *_CONST dl
Dynamic loader handle.
Definition: dl_module.h:122
dl_module_common_t * exported
Symbol exported by the module, containing its public functions, name and behaviour control flags.
Definition: dl_module.h:128
dl_module_t const *_CONST parent
of this module.
Definition: dl_module.h:124
dl_module_type_t _CONST type
of this module.
Definition: dl_module.h:126
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
#define DL_PRIORITY_BOOTSTRAP
Callback priority for bootstrap callback.
Definition: dl_module.h:80
#define DL_PRIORITY_DICT_ATTR
Callback priority for attribute resolution.
Definition: dl_module.h:77
#define DL_PRIORITY_DICT
Callback priorities.
Definition: dl_module.h:76
dl_module_loader_t *_CONST loader
Loader that owns this dl.
Definition: dl_module.h:120
#define DL_PRIORITY_LIB
Callback priority for library config.
Definition: dl_module.h:79
#define DL_PRIORITY_DICT_ENUM
Callback priority for enum resolution.
Definition: dl_module.h:78
unsigned int refs
Number of references to this module.
Definition: dl_module.h:135
Fields common to all types of loadable modules.
Definition: dl_module.h:108
void global_lib_autofree(UNUSED dl_t const *module, void *symbol, UNUSED void *user_ctx)
Callback for freeing of "lib" symbols.
Definition: global_lib.c:174
int global_lib_auto_instantiate(UNUSED dl_t const *module, void *symbol, UNUSED void *user_ctx)
Callback for creation of "lib" symbols.
Definition: global_lib.c:137
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition: log.h:260
#define PWARN(_fmt,...)
Definition: log.h:227
#define DEBUG4(_fmt,...)
Definition: log.h:267
talloc_free(reap)
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define WARN(fmt,...)
Definition: radclient.h:47
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:850
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition: rb.c:824
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#define fr_rb_talloc_alloc(_ctx, _type, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
Definition: rb.h:205
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Iterator structure for in-order traversal of an rbtree.
Definition: rb.h:321
The main red black tree structure.
Definition: rb.h:73
static char const * name
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:772
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:49
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:492
static void talloc_bstr_tolower(char *str)
Convert a talloced string to lowercase.
Definition: talloc.h:128
static fr_slen_t parent
Definition: pair.h:851
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
#define fr_strerror_const(_msg)
Definition: strerror.h:223
#define MAGIC_PREFIX(_x)
Definition: version.h:82
#define MAGIC_VERSION(_x)
Definition: version.h:83
#define MAGIC_COMMIT(_x)
Definition: version.h:84
#define RADIUSD_MAGIC_NUMBER
Definition: version.h:81
static fr_slen_t data
Definition: value.h:1265