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 int somethingchanged = 1, final = 0;
448 AST_LIST_LOCK(&module_list);
450 /*!\note Some resources, like timers, are started up dynamically, and thus
451 * may be still in use, even if all channels are dead. We must therefore
452 * check the usecount before asking modules to unload. */
454 if (!somethingchanged) {
455 /*!\note If we go through the entire list without changing
456 * anything, ignore the usecounts and unload, then exit. */
460 /* Reset flag before traversing the list */
461 somethingchanged = 0;
463 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
464 if (!final && mod->usecount) {
467 AST_LIST_REMOVE_CURRENT(entry);
468 if (mod->info->unload) {
471 AST_LIST_HEAD_DESTROY(&mod->users);
473 somethingchanged = 1;
475 AST_LIST_TRAVERSE_SAFE_END;
476 } while (somethingchanged && !final);
478 AST_LIST_UNLOCK(&module_list);
481 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
483 struct ast_module *mod;
487 AST_LIST_LOCK(&module_list);
489 if (!(mod = find_resource(resource_name, 0))) {
490 AST_LIST_UNLOCK(&module_list);
491 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
495 if (!(mod->flags.running || mod->flags.declined))
498 if (!error && (mod->usecount > 0)) {
500 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
501 resource_name, mod->usecount);
503 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
510 __ast_module_user_hangup_all(mod);
511 res = mod->info->unload();
514 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
515 if (force <= AST_FORCE_FIRM)
518 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
523 mod->flags.running = mod->flags.declined = 0;
525 AST_LIST_UNLOCK(&module_list);
527 if (!error && !mod->lib && mod->info && mod->info->restore_globals)
528 mod->info->restore_globals();
530 #ifdef LOADABLE_MODULES
532 unload_dynamic_module(mod);
536 ast_update_use_count();
541 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
543 struct ast_module *cur;
544 int i, which=0, l = strlen(word);
550 AST_LIST_LOCK(&module_list);
551 AST_LIST_TRAVERSE(&module_list, cur, entry) {
552 if (!strncasecmp(word, cur->resource, l) &&
553 (cur->info->reload || !needsreload) &&
555 ret = ast_strdup(cur->resource);
559 AST_LIST_UNLOCK(&module_list);
562 for (i=0; !ret && reload_classes[i].name; i++) {
563 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
564 ret = ast_strdup(reload_classes[i].name);
571 void ast_process_pending_reloads(void)
573 struct reload_queue_item *item;
575 if (!ast_fully_booted) {
579 AST_LIST_LOCK(&reload_queue);
581 if (do_full_reload) {
583 AST_LIST_UNLOCK(&reload_queue);
584 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
585 ast_module_reload(NULL);
589 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
590 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
591 ast_module_reload(item->module);
595 AST_LIST_UNLOCK(&reload_queue);
598 static void queue_reload_request(const char *module)
600 struct reload_queue_item *item;
602 AST_LIST_LOCK(&reload_queue);
604 if (do_full_reload) {
605 AST_LIST_UNLOCK(&reload_queue);
609 if (ast_strlen_zero(module)) {
610 /* A full reload request (when module is NULL) wipes out any previous
611 reload requests and causes the queue to ignore future ones */
612 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
617 /* No reason to add the same module twice */
618 AST_LIST_TRAVERSE(&reload_queue, item, entry) {
619 if (!strcasecmp(item->module, module)) {
620 AST_LIST_UNLOCK(&reload_queue);
624 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
626 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
627 AST_LIST_UNLOCK(&reload_queue);
630 strcpy(item->module, module);
631 AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
633 AST_LIST_UNLOCK(&reload_queue);
636 int ast_module_reload(const char *name)
638 struct ast_module *cur;
639 int res = 0; /* return value. 0 = not found, others, see below */
642 /* If we aren't fully booted, we just pretend we reloaded but we queue this
643 up to run once we are booted up. */
644 if (!ast_fully_booted) {
645 queue_reload_request(name);
649 if (ast_mutex_trylock(&reloadlock)) {
650 ast_verbose("The previous reload command didn't finish yet\n");
651 return -1; /* reload already in progress */
653 ast_lastreloadtime = ast_tvnow();
655 /* Call "predefined" reload here first */
656 for (i = 0; reload_classes[i].name; i++) {
657 if (!name || !strcasecmp(name, reload_classes[i].name)) {
658 reload_classes[i].reload_fn(); /* XXX should check error ? */
659 res = 2; /* found and reloaded */
664 ast_mutex_unlock(&reloadlock);
668 AST_LIST_LOCK(&module_list);
669 AST_LIST_TRAVERSE(&module_list, cur, entry) {
670 const struct ast_module_info *info = cur->info;
672 if (name && resource_name_match(name, cur->resource))
675 if (!cur->flags.running || cur->flags.declined) {
678 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. "
679 "Before reloading the module, you must run \"module load %s\" "
680 "and fix whatever is preventing the module from being initialized.\n",
682 res = 2; /* Don't report that the module was not found */
686 if (!info->reload) { /* cannot be reloaded */
687 if (res < 1) /* store result if possible */
688 res = 1; /* 1 = no reload() method */
693 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
696 AST_LIST_UNLOCK(&module_list);
698 ast_mutex_unlock(&reloadlock);
703 static unsigned int inspect_module(const struct ast_module *mod)
705 if (!mod->info->description) {
706 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
710 if (!mod->info->key) {
711 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
715 if (verify_key((unsigned char *) mod->info->key)) {
716 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
720 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
721 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
722 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
723 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
730 static enum ast_module_load_result start_resource(struct ast_module *mod)
733 enum ast_module_load_result res;
735 if (!mod->info->load) {
736 return AST_MODULE_LOAD_FAILURE;
739 res = mod->info->load();
742 case AST_MODULE_LOAD_SUCCESS:
743 if (!ast_fully_booted) {
744 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
745 if (ast_opt_console && !option_verbose)
748 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
751 mod->flags.running = 1;
753 ast_update_use_count();
755 case AST_MODULE_LOAD_DECLINE:
756 mod->flags.declined = 1;
758 case AST_MODULE_LOAD_FAILURE:
759 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
760 case AST_MODULE_LOAD_PRIORITY:
767 /*! loads a resource based upon resource_name. If global_symbols_only is set
768 * only modules with global symbols will be loaded.
770 * If the ast_heap is provided (not NULL) the module is found and added to the
771 * heap without running the module's load() function. By doing this, modules
772 * added to the resource_heap can be initialized later in order by priority.
774 * If the ast_heap is not provided, the module's load function will be executed
776 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap, int required)
778 struct ast_module *mod;
779 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
781 if ((mod = find_resource(resource_name, 0))) {
782 if (mod->flags.running) {
783 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
784 return AST_MODULE_LOAD_DECLINE;
786 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
787 return AST_MODULE_LOAD_SKIP;
789 #ifdef LOADABLE_MODULES
790 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
791 /* don't generate a warning message during load_modules() */
792 if (!global_symbols_only) {
793 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
794 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
796 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP;
800 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
801 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
805 if (inspect_module(mod)) {
806 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
807 #ifdef LOADABLE_MODULES
808 unload_dynamic_module(mod);
810 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
813 if (!mod->lib && mod->info->backup_globals()) {
814 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
815 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
818 mod->flags.declined = 0;
821 ast_heap_push(resource_heap, mod);
822 res = AST_MODULE_LOAD_PRIORITY;
824 res = start_resource(mod);
830 int ast_load_resource(const char *resource_name)
833 AST_LIST_LOCK(&module_list);
834 res = load_resource(resource_name, 0, NULL, 0);
835 AST_LIST_UNLOCK(&module_list);
840 struct load_order_entry {
843 AST_LIST_ENTRY(load_order_entry) entry;
846 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
848 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required)
850 struct load_order_entry *order;
852 AST_LIST_TRAVERSE(load_order, order, entry) {
853 if (!resource_name_match(order->resource, resource)) {
854 /* Make sure we have the proper setting for the required field
855 (we might have both load= and required= lines in modules.conf) */
856 order->required |= required;
862 if (!(order = ast_calloc(1, sizeof(*order))))
865 order->resource = ast_strdup(resource);
866 order->required = required;
867 AST_LIST_INSERT_TAIL(load_order, order, entry);
872 static int mod_load_cmp(void *a, void *b)
874 struct ast_module *a_mod = (struct ast_module *) a;
875 struct ast_module *b_mod = (struct ast_module *) b;
877 /* if load_pri is not set, default is 255. Lower is better*/
878 unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
879 unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
880 if (a_pri == b_pri) {
882 } else if (a_pri < b_pri) {
888 /*! loads modules in order by load_pri, updates mod_count
889 \return -1 on failure to load module, -2 on failure to load required module, otherwise 0
891 static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
893 struct ast_heap *resource_heap;
894 struct load_order_entry *order;
895 struct ast_module *mod;
899 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
903 /* first, add find and add modules to heap */
904 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
905 switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) {
906 case AST_MODULE_LOAD_SUCCESS:
907 case AST_MODULE_LOAD_DECLINE:
908 AST_LIST_REMOVE_CURRENT(entry);
909 ast_free(order->resource);
912 case AST_MODULE_LOAD_FAILURE:
913 ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
914 fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
915 res = order->required ? -2 : -1;
917 case AST_MODULE_LOAD_SKIP:
919 case AST_MODULE_LOAD_PRIORITY:
920 AST_LIST_REMOVE_CURRENT(entry);
924 AST_LIST_TRAVERSE_SAFE_END;
926 /* second remove modules from heap sorted by priority */
927 while ((mod = ast_heap_pop(resource_heap))) {
928 switch (start_resource(mod)) {
929 case AST_MODULE_LOAD_SUCCESS:
931 case AST_MODULE_LOAD_DECLINE:
933 case AST_MODULE_LOAD_FAILURE:
936 case AST_MODULE_LOAD_SKIP:
937 case AST_MODULE_LOAD_PRIORITY:
946 ast_heap_destroy(resource_heap);
951 int load_modules(unsigned int preload_only)
953 struct ast_config *cfg;
954 struct ast_module *mod;
955 struct load_order_entry *order;
956 struct ast_variable *v;
957 unsigned int load_count;
958 struct load_order load_order;
960 struct ast_flags config_flags = { 0 };
963 #ifdef LOADABLE_MODULES
964 struct dirent *dirent;
968 /* all embedded modules have registered themselves by now */
971 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
973 AST_LIST_HEAD_INIT_NOLOCK(&load_order);
975 AST_LIST_LOCK(&module_list);
977 if (embedded_module_list.first) {
978 module_list.first = embedded_module_list.first;
979 module_list.last = embedded_module_list.last;
980 embedded_module_list.first = NULL;
983 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
984 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
985 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
989 /* first, find all the modules we have been explicitly requested to load */
990 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
991 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
992 add_to_load_order(v->value, &load_order, 0);
994 if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) {
995 /* Add the module to the list and make sure it's required */
996 add_to_load_order(v->value, &load_order, 1);
997 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
1002 /* check if 'autoload' is on */
1003 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
1004 /* if so, first add all the embedded modules that are not already running to the load order */
1005 AST_LIST_TRAVERSE(&module_list, mod, entry) {
1006 /* if it's not embedded, skip it */
1010 if (mod->flags.running)
1013 order = add_to_load_order(mod->resource, &load_order, 0);
1016 #ifdef LOADABLE_MODULES
1017 /* if we are allowed to load dynamic modules, scan the directory for
1018 for all available modules and add them as well */
1019 if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
1020 while ((dirent = readdir(dir))) {
1021 int ld = strlen(dirent->d_name);
1023 /* Must end in .so to load it. */
1028 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
1031 /* if there is already a module by this name in the module_list,
1033 if (find_resource(dirent->d_name, 0))
1036 add_to_load_order(dirent->d_name, &load_order, 0);
1042 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
1043 ast_config_AST_MODULE_DIR);
1048 /* now scan the config for any modules we are prohibited from loading and
1049 remove them from the load order */
1050 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
1051 if (strcasecmp(v->name, "noload"))
1054 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
1055 if (!resource_name_match(order->resource, v->value)) {
1056 AST_LIST_REMOVE_CURRENT(entry);
1057 ast_free(order->resource);
1061 AST_LIST_TRAVERSE_SAFE_END;
1064 /* we are done with the config now, all the information we need is in the
1066 ast_config_destroy(cfg);
1069 AST_LIST_TRAVERSE(&load_order, order, entry)
1073 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
1075 /* first, load only modules that provide global symbols */
1076 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
1080 /* now load everything else */
1081 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
1086 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
1087 ast_free(order->resource);
1091 AST_LIST_UNLOCK(&module_list);
1093 /* Tell manager clients that are aggressive at logging in that we're done
1094 loading modules. If there's a DNS problem in chan_sip, we might not
1096 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
1101 void ast_update_use_count(void)
1103 /* Notify any module monitors that the use count for a
1104 resource has changed */
1105 struct loadupdate *m;
1107 AST_LIST_LOCK(&updaters);
1108 AST_LIST_TRAVERSE(&updaters, m, entry)
1110 AST_LIST_UNLOCK(&updaters);
1113 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
1116 struct ast_module *cur;
1118 int total_mod_loaded = 0;
1120 if (AST_LIST_TRYLOCK(&module_list))
1123 AST_LIST_TRAVERSE(&module_list, cur, entry) {
1124 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
1128 AST_LIST_UNLOCK(&module_list);
1130 return total_mod_loaded;
1133 /*! \brief Check if module exists */
1134 int ast_module_check(const char *name)
1136 struct ast_module *cur;
1138 if (ast_strlen_zero(name))
1139 return 0; /* FALSE */
1141 cur = find_resource(name, 1);
1143 return (cur != NULL);
1147 int ast_loader_register(int (*v)(void))
1149 struct loadupdate *tmp;
1151 if (!(tmp = ast_malloc(sizeof(*tmp))))
1155 AST_LIST_LOCK(&updaters);
1156 AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
1157 AST_LIST_UNLOCK(&updaters);
1162 int ast_loader_unregister(int (*v)(void))
1164 struct loadupdate *cur;
1166 AST_LIST_LOCK(&updaters);
1167 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
1168 if (cur->updater == v) {
1169 AST_LIST_REMOVE_CURRENT(entry);
1173 AST_LIST_TRAVERSE_SAFE_END;
1174 AST_LIST_UNLOCK(&updaters);
1176 return cur ? 0 : -1;
1179 struct ast_module *ast_module_ref(struct ast_module *mod)
1181 ast_atomic_fetchadd_int(&mod->usecount, +1);
1182 ast_update_use_count();
1187 void ast_module_unref(struct ast_module *mod)
1189 ast_atomic_fetchadd_int(&mod->usecount, -1);
1190 ast_update_use_count();