2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
7 * Kevin P. Fleming <kpfleming@digium.com>
8 * Luigi Rizzo <rizzo@icir.org>
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief Module Loader
24 * \author Mark Spencer <markster@digium.com>
25 * \author Kevin P. Fleming <kpfleming@digium.com>
26 * \author Luigi Rizzo <rizzo@icir.org>
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include "asterisk/_private.h"
35 #include "asterisk/paths.h" /* use ast_config_AST_MODULE_DIR */
38 #include "asterisk/linkedlists.h"
39 #include "asterisk/module.h"
40 #include "asterisk/config.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/term.h"
43 #include "asterisk/manager.h"
44 #include "asterisk/cdr.h"
45 #include "asterisk/enum.h"
46 #include "asterisk/http.h"
47 #include "asterisk/lock.h"
48 #include "asterisk/features.h"
49 #include "asterisk/dsp.h"
50 #include "asterisk/udptl.h"
51 #include "asterisk/heap.h"
55 #include "asterisk/md5.h"
56 #include "asterisk/utils.h"
66 struct ast_module_user {
67 struct ast_channel *chan;
68 AST_LIST_ENTRY(ast_module_user) entry;
71 AST_LIST_HEAD(module_user_list, ast_module_user);
73 static const unsigned char expected_key[] =
74 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
75 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
77 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
79 static unsigned int embedding = 1; /* we always start out by registering embedded modules,
80 since they are here before we dlopen() any
84 const struct ast_module_info *info;
85 void *lib; /* the shared lib, or NULL if embedded */
86 int usecount; /* the number of 'users' currently in this module */
87 struct module_user_list users; /* the list of users in the module */
89 unsigned int running:1;
90 unsigned int declined:1;
92 AST_LIST_ENTRY(ast_module) entry;
96 static AST_LIST_HEAD_STATIC(module_list, ast_module);
99 * module_list is cleared by its constructor possibly after
100 * we start accumulating embedded modules, so we need to
101 * use another list (without the lock) to accumulate them.
102 * Then we update the main list when embedding is done.
104 static struct module_list embedded_module_list;
107 int (*updater)(void);
108 AST_LIST_ENTRY(loadupdate) entry;
111 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
113 AST_MUTEX_DEFINE_STATIC(reloadlock);
115 struct reload_queue_item {
116 AST_LIST_ENTRY(reload_queue_item) entry;
120 static int do_full_reload = 0;
122 static AST_LIST_HEAD_STATIC(reload_queue, reload_queue_item);
124 /* when dynamic modules are being loaded, ast_module_register() will
125 need to know what filename the module was loaded from while it
128 static struct ast_module *resource_being_loaded;
130 /* XXX: should we check for duplicate resource names here? */
132 void ast_module_register(const struct ast_module_info *info)
134 struct ast_module *mod;
137 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
139 strcpy(mod->resource, info->name);
141 mod = resource_being_loaded;
145 AST_LIST_HEAD_INIT(&mod->users);
147 /* during startup, before the loader has been initialized,
148 there are no threads, so there is no need to take the lock
149 on this list to manipulate it. it is also possible that it
150 might be unsafe to use the list lock at that point... so
151 let's avoid it altogether
154 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
156 AST_LIST_LOCK(&module_list);
157 /* it is paramount that the new entry be placed at the tail of
158 the list, otherwise the code that uses dlopen() to load
159 dynamic modules won't be able to find out if the module it
160 just opened was registered or failed to load
162 AST_LIST_INSERT_TAIL(&module_list, mod, entry);
163 AST_LIST_UNLOCK(&module_list);
166 /* give the module a copy of its own handle, for later use in registrations and the like */
167 *((struct ast_module **) &(info->self)) = mod;
170 void ast_module_unregister(const struct ast_module_info *info)
172 struct ast_module *mod = NULL;
174 /* it is assumed that the users list in the module structure
175 will already be empty, or we cannot have gotten to this
178 AST_LIST_LOCK(&module_list);
179 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
180 if (mod->info == info) {
181 AST_LIST_REMOVE_CURRENT(entry);
185 AST_LIST_TRAVERSE_SAFE_END;
186 AST_LIST_UNLOCK(&module_list);
189 AST_LIST_HEAD_DESTROY(&mod->users);
194 struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
195 struct ast_channel *chan)
197 struct ast_module_user *u = ast_calloc(1, sizeof(*u));
204 AST_LIST_LOCK(&mod->users);
205 AST_LIST_INSERT_HEAD(&mod->users, u, entry);
206 AST_LIST_UNLOCK(&mod->users);
208 ast_atomic_fetchadd_int(&mod->usecount, +1);
210 ast_update_use_count();
215 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
217 AST_LIST_LOCK(&mod->users);
218 AST_LIST_REMOVE(&mod->users, u, entry);
219 AST_LIST_UNLOCK(&mod->users);
220 ast_atomic_fetchadd_int(&mod->usecount, -1);
223 ast_update_use_count();
226 void __ast_module_user_hangup_all(struct ast_module *mod)
228 struct ast_module_user *u;
230 AST_LIST_LOCK(&mod->users);
231 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
232 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
233 ast_atomic_fetchadd_int(&mod->usecount, -1);
236 AST_LIST_UNLOCK(&mod->users);
238 ast_update_use_count();
242 * In addition to modules, the reload command handles some extra keywords
243 * which are listed here together with the corresponding handlers.
244 * This table is also used by the command completion code.
246 static struct reload_classes {
248 int (*reload_fn)(void);
249 } reload_classes[] = { /* list in alpha order, longest match first for cli completion */
250 { "cdr", ast_cdr_engine_reload },
251 { "dnsmgr", dnsmgr_reload },
252 { "extconfig", read_config_maps },
253 { "enum", ast_enum_reload },
254 { "manager", reload_manager },
255 { "http", ast_http_reload },
256 { "logger", logger_reload },
257 { "features", ast_features_reload },
258 { "dsp", ast_dsp_reload},
259 { "udptl", ast_udptl_reload },
260 { "indications", ast_indications_reload },
261 { "cel", ast_cel_engine_reload },
265 static int printdigest(const unsigned char *d)
268 char buf[256]; /* large enough so we don't have to worry */
270 for (pos = 0, x = 0; x < 16; x++)
271 pos += sprintf(buf + pos, " %02x", *d++);
273 ast_debug(1, "Unexpected signature:%s\n", buf);
278 static int key_matches(const unsigned char *key1, const unsigned char *key2)
282 for (x = 0; x < 16; x++) {
283 if (key1[x] != key2[x])
290 static int verify_key(const unsigned char *key)
293 unsigned char digest[16];
296 MD5Update(&c, key, strlen((char *)key));
297 MD5Final(digest, &c);
299 if (key_matches(expected_key, digest))
307 static int resource_name_match(const char *name1_in, const char *name2_in)
309 char *name1 = (char *) name1_in;
310 char *name2 = (char *) name2_in;
312 /* trim off any .so extensions */
313 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
314 name1 = ast_strdupa(name1);
315 name1[strlen(name1) - 3] = '\0';
317 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
318 name2 = ast_strdupa(name2);
319 name2[strlen(name2) - 3] = '\0';
322 return strcasecmp(name1, name2);
325 static struct ast_module *find_resource(const char *resource, int do_lock)
327 struct ast_module *cur;
330 AST_LIST_LOCK(&module_list);
332 AST_LIST_TRAVERSE(&module_list, cur, entry) {
333 if (!resource_name_match(resource, cur->resource))
338 AST_LIST_UNLOCK(&module_list);
343 #ifdef LOADABLE_MODULES
344 static void unload_dynamic_module(struct ast_module *mod)
346 void *lib = mod->lib;
348 /* WARNING: the structure pointed to by mod is going to
349 disappear when this operation succeeds, so we can't
353 while (!dlclose(lib));
356 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
358 char fn[PATH_MAX] = "";
360 struct ast_module *mod;
361 unsigned int wants_global;
362 int space; /* room needed for the descriptor */
365 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
366 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
368 space += 3; /* room for the extra ".so" */
371 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
373 /* make a first load of the module in 'quiet' mode... don't try to resolve
374 any symbols, and don't export any symbols. this will allow us to peek into
375 the module's info block (if available) to see what flags it has set */
377 resource_being_loaded = ast_calloc(1, space);
378 if (!resource_being_loaded)
380 strcpy(resource_being_loaded->resource, resource_in);
382 strcat(resource_being_loaded->resource, ".so");
384 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
385 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
386 ast_free(resource_being_loaded);
390 /* the dlopen() succeeded, let's find out if the module
392 /* note that this will only work properly as long as
393 ast_module_register() (which is called by the module's
394 constructor) places the new module at the tail of the
397 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
398 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
399 /* no, it did not, so close it and return */
400 while (!dlclose(lib));
401 /* note that the module's destructor will call ast_module_unregister(),
402 which will free the structure we allocated in resource_being_loaded */
406 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
408 /* if we are being asked only to load modules that provide global symbols,
409 and this one does not, then close it and return */
410 if (global_symbols_only && !wants_global) {
411 while (!dlclose(lib));
415 while (!dlclose(lib));
416 resource_being_loaded = NULL;
418 /* start the load process again */
419 resource_being_loaded = ast_calloc(1, space);
420 if (!resource_being_loaded)
422 strcpy(resource_being_loaded->resource, resource_in);
424 strcat(resource_being_loaded->resource, ".so");
426 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
427 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
428 ast_free(resource_being_loaded);
432 /* since the module was successfully opened, and it registered itself
433 the previous time we did that, we're going to assume it worked this
436 AST_LIST_LAST(&module_list)->lib = lib;
437 resource_being_loaded = NULL;
439 return AST_LIST_LAST(&module_list);
443 void ast_module_shutdown(void)
445 struct ast_module *mod;
446 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
448 /* We have to call the unload() callbacks in reverse order that the modules
449 * exist in the module list so it is the reverse order of how they were
452 AST_LIST_LOCK(&module_list);
453 while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
454 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
455 AST_LIST_UNLOCK(&module_list);
457 while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
458 if (mod->info->unload)
460 /* Since this should only be called when shutting down "gracefully",
461 * all channels should be down before we get to this point, meaning
462 * there will be no module users left. */
463 AST_LIST_HEAD_DESTROY(&mod->users);
468 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
470 struct ast_module *mod;
474 AST_LIST_LOCK(&module_list);
476 if (!(mod = find_resource(resource_name, 0))) {
477 AST_LIST_UNLOCK(&module_list);
478 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
482 if (!(mod->flags.running || mod->flags.declined))
485 if (!error && (mod->usecount > 0)) {
487 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
488 resource_name, mod->usecount);
490 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
497 __ast_module_user_hangup_all(mod);
498 res = mod->info->unload();
501 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
502 if (force <= AST_FORCE_FIRM)
505 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
510 mod->flags.running = mod->flags.declined = 0;
512 AST_LIST_UNLOCK(&module_list);
514 if (!error && !mod->lib && mod->info && mod->info->restore_globals)
515 mod->info->restore_globals();
517 #ifdef LOADABLE_MODULES
519 unload_dynamic_module(mod);
523 ast_update_use_count();
528 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
530 struct ast_module *cur;
531 int i, which=0, l = strlen(word);
537 AST_LIST_LOCK(&module_list);
538 AST_LIST_TRAVERSE(&module_list, cur, entry) {
539 if (!strncasecmp(word, cur->resource, l) &&
540 (cur->info->reload || !needsreload) &&
542 ret = ast_strdup(cur->resource);
546 AST_LIST_UNLOCK(&module_list);
549 for (i=0; !ret && reload_classes[i].name; i++) {
550 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
551 ret = ast_strdup(reload_classes[i].name);
558 void ast_process_pending_reloads(void)
560 struct reload_queue_item *item;
562 if (!ast_fully_booted) {
566 AST_LIST_LOCK(&reload_queue);
568 if (do_full_reload) {
570 AST_LIST_UNLOCK(&reload_queue);
571 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
572 ast_module_reload(NULL);
576 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
577 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
578 ast_module_reload(item->module);
582 AST_LIST_UNLOCK(&reload_queue);
585 static void queue_reload_request(const char *module)
587 struct reload_queue_item *item;
589 AST_LIST_LOCK(&reload_queue);
591 if (do_full_reload) {
592 AST_LIST_UNLOCK(&reload_queue);
596 if (ast_strlen_zero(module)) {
597 /* A full reload request (when module is NULL) wipes out any previous
598 reload requests and causes the queue to ignore future ones */
599 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
604 /* No reason to add the same module twice */
605 AST_LIST_TRAVERSE(&reload_queue, item, entry) {
606 if (!strcasecmp(item->module, module)) {
607 AST_LIST_UNLOCK(&reload_queue);
611 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
613 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
614 AST_LIST_UNLOCK(&reload_queue);
617 strcpy(item->module, module);
618 AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
620 AST_LIST_UNLOCK(&reload_queue);
623 int ast_module_reload(const char *name)
625 struct ast_module *cur;
626 int res = 0; /* return value. 0 = not found, others, see below */
629 /* If we aren't fully booted, we just pretend we reloaded but we queue this
630 up to run once we are booted up. */
631 if (!ast_fully_booted) {
632 queue_reload_request(name);
636 if (ast_mutex_trylock(&reloadlock)) {
637 ast_verbose("The previous reload command didn't finish yet\n");
638 return -1; /* reload already in progress */
640 ast_lastreloadtime = ast_tvnow();
642 /* Call "predefined" reload here first */
643 for (i = 0; reload_classes[i].name; i++) {
644 if (!name || !strcasecmp(name, reload_classes[i].name)) {
645 reload_classes[i].reload_fn(); /* XXX should check error ? */
646 res = 2; /* found and reloaded */
651 ast_mutex_unlock(&reloadlock);
655 AST_LIST_LOCK(&module_list);
656 AST_LIST_TRAVERSE(&module_list, cur, entry) {
657 const struct ast_module_info *info = cur->info;
659 if (name && resource_name_match(name, cur->resource))
662 if (!cur->flags.running || cur->flags.declined) {
665 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. "
666 "Before reloading the module, you must run \"module load %s\" "
667 "and fix whatever is preventing the module from being initialized.\n",
669 res = 2; /* Don't report that the module was not found */
673 if (!info->reload) { /* cannot be reloaded */
674 if (res < 1) /* store result if possible */
675 res = 1; /* 1 = no reload() method */
680 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
683 AST_LIST_UNLOCK(&module_list);
685 ast_mutex_unlock(&reloadlock);
690 static unsigned int inspect_module(const struct ast_module *mod)
692 if (!mod->info->description) {
693 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
697 if (!mod->info->key) {
698 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
702 if (verify_key((unsigned char *) mod->info->key)) {
703 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
707 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
708 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
709 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
710 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
717 static enum ast_module_load_result start_resource(struct ast_module *mod)
720 enum ast_module_load_result res;
722 if (!mod->info->load) {
723 return AST_MODULE_LOAD_FAILURE;
726 res = mod->info->load();
729 case AST_MODULE_LOAD_SUCCESS:
730 if (!ast_fully_booted) {
731 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
732 if (ast_opt_console && !option_verbose)
735 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
738 mod->flags.running = 1;
740 ast_update_use_count();
742 case AST_MODULE_LOAD_DECLINE:
743 mod->flags.declined = 1;
745 case AST_MODULE_LOAD_FAILURE:
746 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
747 case AST_MODULE_LOAD_PRIORITY:
754 /*! loads a resource based upon resource_name. If global_symbols_only is set
755 * only modules with global symbols will be loaded.
757 * If the ast_heap is provided (not NULL) the module is found and added to the
758 * heap without running the module's load() function. By doing this, modules
759 * added to the resource_heap can be initialized later in order by priority.
761 * If the ast_heap is not provided, the module's load function will be executed
763 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap)
765 struct ast_module *mod;
766 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
768 if ((mod = find_resource(resource_name, 0))) {
769 if (mod->flags.running) {
770 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
771 return AST_MODULE_LOAD_DECLINE;
773 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
774 return AST_MODULE_LOAD_SKIP;
776 #ifdef LOADABLE_MODULES
777 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
778 /* don't generate a warning message during load_modules() */
779 if (!global_symbols_only) {
780 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
781 return AST_MODULE_LOAD_DECLINE;
783 return AST_MODULE_LOAD_SKIP;
787 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
788 return AST_MODULE_LOAD_DECLINE;
792 if (inspect_module(mod)) {
793 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
794 #ifdef LOADABLE_MODULES
795 unload_dynamic_module(mod);
797 return AST_MODULE_LOAD_DECLINE;
800 if (!mod->lib && mod->info->backup_globals()) {
801 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
802 return AST_MODULE_LOAD_DECLINE;
805 mod->flags.declined = 0;
808 ast_heap_push(resource_heap, mod);
809 res = AST_MODULE_LOAD_PRIORITY;
811 res = start_resource(mod);
817 int ast_load_resource(const char *resource_name)
820 AST_LIST_LOCK(&module_list);
821 res = load_resource(resource_name, 0, NULL);
822 AST_LIST_UNLOCK(&module_list);
827 struct load_order_entry {
829 AST_LIST_ENTRY(load_order_entry) entry;
832 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
834 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
836 struct load_order_entry *order;
838 AST_LIST_TRAVERSE(load_order, order, entry) {
839 if (!resource_name_match(order->resource, resource))
843 if (!(order = ast_calloc(1, sizeof(*order))))
846 order->resource = ast_strdup(resource);
847 AST_LIST_INSERT_TAIL(load_order, order, entry);
852 static int mod_load_cmp(void *a, void *b)
854 struct ast_module *a_mod = (struct ast_module *) a;
855 struct ast_module *b_mod = (struct ast_module *) b;
857 /* if load_pri is not set, default is 255. Lower is better*/
858 unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
859 unsigned char b_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
860 if (a_pri == b_pri) {
862 } else if (a_pri < b_pri) {
868 /*! loads modules in order by load_pri, updates mod_count */
869 static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
871 struct ast_heap *resource_heap;
872 struct load_order_entry *order;
873 struct ast_module *mod;
877 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
881 /* first, add find and add modules to heap */
882 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
883 switch (load_resource(order->resource, global_symbols, resource_heap)) {
884 case AST_MODULE_LOAD_SUCCESS:
885 case AST_MODULE_LOAD_DECLINE:
886 AST_LIST_REMOVE_CURRENT(entry);
887 ast_free(order->resource);
890 case AST_MODULE_LOAD_FAILURE:
893 case AST_MODULE_LOAD_SKIP:
895 case AST_MODULE_LOAD_PRIORITY:
896 AST_LIST_REMOVE_CURRENT(entry);
900 AST_LIST_TRAVERSE_SAFE_END;
902 /* second remove modules from heap sorted by priority */
903 while ((mod = ast_heap_pop(resource_heap))) {
904 switch (start_resource(mod)) {
905 case AST_MODULE_LOAD_SUCCESS:
907 case AST_MODULE_LOAD_DECLINE:
909 case AST_MODULE_LOAD_FAILURE:
912 case AST_MODULE_LOAD_SKIP:
913 case AST_MODULE_LOAD_PRIORITY:
922 ast_heap_destroy(resource_heap);
927 int load_modules(unsigned int preload_only)
929 struct ast_config *cfg;
930 struct ast_module *mod;
931 struct load_order_entry *order;
932 struct ast_variable *v;
933 unsigned int load_count;
934 struct load_order load_order;
936 struct ast_flags config_flags = { 0 };
939 #ifdef LOADABLE_MODULES
940 struct dirent *dirent;
944 /* all embedded modules have registered themselves by now */
947 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
949 AST_LIST_HEAD_INIT_NOLOCK(&load_order);
951 AST_LIST_LOCK(&module_list);
953 if (embedded_module_list.first) {
954 module_list.first = embedded_module_list.first;
955 module_list.last = embedded_module_list.last;
956 embedded_module_list.first = NULL;
959 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
960 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
961 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
965 /* first, find all the modules we have been explicitly requested to load */
966 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
967 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
968 add_to_load_order(v->value, &load_order);
972 /* check if 'autoload' is on */
973 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
974 /* if so, first add all the embedded modules that are not already running to the load order */
975 AST_LIST_TRAVERSE(&module_list, mod, entry) {
976 /* if it's not embedded, skip it */
980 if (mod->flags.running)
983 order = add_to_load_order(mod->resource, &load_order);
986 #ifdef LOADABLE_MODULES
987 /* if we are allowed to load dynamic modules, scan the directory for
988 for all available modules and add them as well */
989 if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
990 while ((dirent = readdir(dir))) {
991 int ld = strlen(dirent->d_name);
993 /* Must end in .so to load it. */
998 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
1001 /* if there is already a module by this name in the module_list,
1003 if (find_resource(dirent->d_name, 0))
1006 add_to_load_order(dirent->d_name, &load_order);
1012 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
1013 ast_config_AST_MODULE_DIR);
1018 /* now scan the config for any modules we are prohibited from loading and
1019 remove them from the load order */
1020 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
1021 if (strcasecmp(v->name, "noload"))
1024 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
1025 if (!resource_name_match(order->resource, v->value)) {
1026 AST_LIST_REMOVE_CURRENT(entry);
1027 ast_free(order->resource);
1031 AST_LIST_TRAVERSE_SAFE_END;
1034 /* we are done with the config now, all the information we need is in the
1036 ast_config_destroy(cfg);
1039 AST_LIST_TRAVERSE(&load_order, order, entry)
1043 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
1045 /* first, load only modules that provide global symbols */
1046 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
1050 /* now load everything else */
1051 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
1056 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
1057 ast_free(order->resource);
1061 AST_LIST_UNLOCK(&module_list);
1063 /* Tell manager clients that are aggressive at logging in that we're done
1064 loading modules. If there's a DNS problem in chan_sip, we might not
1066 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
1071 void ast_update_use_count(void)
1073 /* Notify any module monitors that the use count for a
1074 resource has changed */
1075 struct loadupdate *m;
1077 AST_LIST_LOCK(&updaters);
1078 AST_LIST_TRAVERSE(&updaters, m, entry)
1080 AST_LIST_UNLOCK(&updaters);
1083 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
1086 struct ast_module *cur;
1088 int total_mod_loaded = 0;
1090 if (AST_LIST_TRYLOCK(&module_list))
1093 AST_LIST_TRAVERSE(&module_list, cur, entry) {
1094 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
1098 AST_LIST_UNLOCK(&module_list);
1100 return total_mod_loaded;
1103 /*! \brief Check if module exists */
1104 int ast_module_check(const char *name)
1106 struct ast_module *cur;
1108 if (ast_strlen_zero(name))
1109 return 0; /* FALSE */
1111 cur = find_resource(name, 1);
1113 return (cur != NULL);
1117 int ast_loader_register(int (*v)(void))
1119 struct loadupdate *tmp;
1121 if (!(tmp = ast_malloc(sizeof(*tmp))))
1125 AST_LIST_LOCK(&updaters);
1126 AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
1127 AST_LIST_UNLOCK(&updaters);
1132 int ast_loader_unregister(int (*v)(void))
1134 struct loadupdate *cur;
1136 AST_LIST_LOCK(&updaters);
1137 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
1138 if (cur->updater == v) {
1139 AST_LIST_REMOVE_CURRENT(entry);
1143 AST_LIST_TRAVERSE_SAFE_END;
1144 AST_LIST_UNLOCK(&updaters);
1146 return cur ? 0 : -1;
1149 struct ast_module *ast_module_ref(struct ast_module *mod)
1151 ast_atomic_fetchadd_int(&mod->usecount, +1);
1152 ast_update_use_count();
1157 void ast_module_unref(struct ast_module *mod)
1159 ast_atomic_fetchadd_int(&mod->usecount, -1);
1160 ast_update_use_count();