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>
31 <support_level>core</support_level>
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include "asterisk/_private.h"
39 #include "asterisk/paths.h" /* use ast_config_AST_MODULE_DIR */
42 #include "asterisk/linkedlists.h"
43 #include "asterisk/module.h"
44 #include "asterisk/config.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/term.h"
47 #include "asterisk/acl.h"
48 #include "asterisk/manager.h"
49 #include "asterisk/cdr.h"
50 #include "asterisk/enum.h"
51 #include "asterisk/http.h"
52 #include "asterisk/lock.h"
53 #include "asterisk/features.h"
54 #include "asterisk/dsp.h"
55 #include "asterisk/udptl.h"
56 #include "asterisk/heap.h"
57 #include "asterisk/app.h"
58 #include "asterisk/test.h"
62 #include "asterisk/md5.h"
63 #include "asterisk/utils.h"
66 <managerEvent language="en_US" name="Reload">
67 <managerEventInstance class="EVENT_FLAG_SYSTEM">
68 <synopsis>Raised when a module has been reloaded in Asterisk.</synopsis>
70 <parameter name="Module">
71 <para>The name of the module that was reloaded, or
72 <literal>All</literal> if all modules were reloaded</para>
74 <parameter name="Status">
75 <para>The numeric status code denoting the success or failure
76 of the reload request.</para>
78 <enum name="0"><para>Success</para></enum>
79 <enum name="1"><para>Request queued</para></enum>
80 <enum name="2"><para>Module not found</para></enum>
81 <enum name="3"><para>Error</para></enum>
82 <enum name="4"><para>Reload already in progress</para></enum>
83 <enum name="5"><para>Module uninitialized</para></enum>
84 <enum name="6"><para>Reload not supported</para></enum>
88 </managerEventInstance>
100 struct ast_module_user {
101 struct ast_channel *chan;
102 AST_LIST_ENTRY(ast_module_user) entry;
105 AST_LIST_HEAD(module_user_list, ast_module_user);
107 static const unsigned char expected_key[] =
108 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
109 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
111 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
113 static unsigned int embedding = 1; /* we always start out by registering embedded modules,
114 since they are here before we dlopen() any
118 const struct ast_module_info *info;
119 void *lib; /* the shared lib, or NULL if embedded */
120 int usecount; /* the number of 'users' currently in this module */
121 struct module_user_list users; /* the list of users in the module */
123 unsigned int running:1;
124 unsigned int declined:1;
126 AST_LIST_ENTRY(ast_module) entry;
130 static AST_LIST_HEAD_STATIC(module_list, ast_module);
132 const char *ast_module_name(const struct ast_module *mod)
134 if (!mod || !mod->info) {
138 return mod->info->name;
142 * module_list is cleared by its constructor possibly after
143 * we start accumulating embedded modules, so we need to
144 * use another list (without the lock) to accumulate them.
145 * Then we update the main list when embedding is done.
147 static struct module_list embedded_module_list;
150 int (*updater)(void);
151 AST_LIST_ENTRY(loadupdate) entry;
154 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
156 AST_MUTEX_DEFINE_STATIC(reloadlock);
158 struct reload_queue_item {
159 AST_LIST_ENTRY(reload_queue_item) entry;
163 static int do_full_reload = 0;
165 static AST_LIST_HEAD_STATIC(reload_queue, reload_queue_item);
167 /* when dynamic modules are being loaded, ast_module_register() will
168 need to know what filename the module was loaded from while it
171 static struct ast_module *resource_being_loaded;
173 /* XXX: should we check for duplicate resource names here? */
175 void ast_module_register(const struct ast_module_info *info)
177 struct ast_module *mod;
180 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
182 strcpy(mod->resource, info->name);
184 mod = resource_being_loaded;
188 AST_LIST_HEAD_INIT(&mod->users);
190 /* during startup, before the loader has been initialized,
191 there are no threads, so there is no need to take the lock
192 on this list to manipulate it. it is also possible that it
193 might be unsafe to use the list lock at that point... so
194 let's avoid it altogether
197 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
199 AST_LIST_LOCK(&module_list);
200 /* it is paramount that the new entry be placed at the tail of
201 the list, otherwise the code that uses dlopen() to load
202 dynamic modules won't be able to find out if the module it
203 just opened was registered or failed to load
205 AST_LIST_INSERT_TAIL(&module_list, mod, entry);
206 AST_LIST_UNLOCK(&module_list);
209 /* give the module a copy of its own handle, for later use in registrations and the like */
210 *((struct ast_module **) &(info->self)) = mod;
213 void ast_module_unregister(const struct ast_module_info *info)
215 struct ast_module *mod = NULL;
217 /* it is assumed that the users list in the module structure
218 will already be empty, or we cannot have gotten to this
221 AST_LIST_LOCK(&module_list);
222 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
223 if (mod->info == info) {
224 AST_LIST_REMOVE_CURRENT(entry);
228 AST_LIST_TRAVERSE_SAFE_END;
229 AST_LIST_UNLOCK(&module_list);
232 AST_LIST_HEAD_DESTROY(&mod->users);
237 struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast_channel *chan)
239 struct ast_module_user *u;
241 u = ast_calloc(1, sizeof(*u));
248 AST_LIST_LOCK(&mod->users);
249 AST_LIST_INSERT_HEAD(&mod->users, u, entry);
250 AST_LIST_UNLOCK(&mod->users);
252 ast_atomic_fetchadd_int(&mod->usecount, +1);
254 ast_update_use_count();
259 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
265 AST_LIST_LOCK(&mod->users);
266 u = AST_LIST_REMOVE(&mod->users, u, entry);
267 AST_LIST_UNLOCK(&mod->users);
270 * Was not in the list. Either a bad pointer or
271 * __ast_module_user_hangup_all() has been called.
276 ast_atomic_fetchadd_int(&mod->usecount, -1);
279 ast_update_use_count();
282 void __ast_module_user_hangup_all(struct ast_module *mod)
284 struct ast_module_user *u;
286 AST_LIST_LOCK(&mod->users);
287 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
289 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
291 ast_atomic_fetchadd_int(&mod->usecount, -1);
294 AST_LIST_UNLOCK(&mod->users);
296 ast_update_use_count();
300 * In addition to modules, the reload command handles some extra keywords
301 * which are listed here together with the corresponding handlers.
302 * This table is also used by the command completion code.
304 static struct reload_classes {
306 int (*reload_fn)(void);
307 } reload_classes[] = { /* list in alpha order, longest match first for cli completion */
308 { "cdr", ast_cdr_engine_reload },
309 { "dnsmgr", dnsmgr_reload },
310 { "extconfig", read_config_maps },
311 { "enum", ast_enum_reload },
312 { "acl", ast_named_acl_reload },
313 { "manager", reload_manager },
314 { "http", ast_http_reload },
315 { "logger", logger_reload },
316 { "features", ast_features_reload },
317 { "dsp", ast_dsp_reload},
318 { "udptl", ast_udptl_reload },
319 { "indications", ast_indications_reload },
320 { "cel", ast_cel_engine_reload },
321 { "plc", ast_plc_reload },
325 static int printdigest(const unsigned char *d)
328 char buf[256]; /* large enough so we don't have to worry */
330 for (pos = 0, x = 0; x < 16; x++)
331 pos += sprintf(buf + pos, " %02x", *d++);
333 ast_debug(1, "Unexpected signature:%s\n", buf);
338 static int key_matches(const unsigned char *key1, const unsigned char *key2)
342 for (x = 0; x < 16; x++) {
343 if (key1[x] != key2[x])
350 static int verify_key(const unsigned char *key)
353 unsigned char digest[16];
356 MD5Update(&c, key, strlen((char *)key));
357 MD5Final(digest, &c);
359 if (key_matches(expected_key, digest))
367 static int resource_name_match(const char *name1_in, const char *name2_in)
369 char *name1 = (char *) name1_in;
370 char *name2 = (char *) name2_in;
372 /* trim off any .so extensions */
373 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
374 name1 = ast_strdupa(name1);
375 name1[strlen(name1) - 3] = '\0';
377 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
378 name2 = ast_strdupa(name2);
379 name2[strlen(name2) - 3] = '\0';
382 return strcasecmp(name1, name2);
385 static struct ast_module *find_resource(const char *resource, int do_lock)
387 struct ast_module *cur;
390 AST_LIST_LOCK(&module_list);
392 AST_LIST_TRAVERSE(&module_list, cur, entry) {
393 if (!resource_name_match(resource, cur->resource))
398 AST_LIST_UNLOCK(&module_list);
403 #ifdef LOADABLE_MODULES
404 static void unload_dynamic_module(struct ast_module *mod)
406 void *lib = mod->lib;
408 /* WARNING: the structure pointed to by mod is going to
409 disappear when this operation succeeds, so we can't
413 while (!dlclose(lib));
416 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap, int required);
418 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, struct ast_heap *resource_heap)
420 char fn[PATH_MAX] = "";
422 struct ast_module *mod;
423 unsigned int wants_global;
424 int space; /* room needed for the descriptor */
427 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
428 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
430 space += 3; /* room for the extra ".so" */
433 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
435 /* make a first load of the module in 'quiet' mode... don't try to resolve
436 any symbols, and don't export any symbols. this will allow us to peek into
437 the module's info block (if available) to see what flags it has set */
439 resource_being_loaded = ast_calloc(1, space);
440 if (!resource_being_loaded)
442 strcpy(resource_being_loaded->resource, resource_in);
444 strcat(resource_being_loaded->resource, ".so");
446 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
447 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
448 ast_free(resource_being_loaded);
452 /* the dlopen() succeeded, let's find out if the module
454 /* note that this will only work properly as long as
455 ast_module_register() (which is called by the module's
456 constructor) places the new module at the tail of the
459 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
460 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
461 /* no, it did not, so close it and return */
462 while (!dlclose(lib));
463 /* note that the module's destructor will call ast_module_unregister(),
464 which will free the structure we allocated in resource_being_loaded */
468 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
470 /* if we are being asked only to load modules that provide global symbols,
471 and this one does not, then close it and return */
472 if (global_symbols_only && !wants_global) {
473 while (!dlclose(lib));
477 /* This section is a workaround for a gcc 4.1 bug that has already been
478 * fixed in later versions. Unfortunately, some distributions, such as
479 * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal
480 * with this issue. This basically ensures that optional_api modules are
481 * loaded before any module which requires their functionality. */
482 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref)
483 if (!ast_strlen_zero(mod->info->nonoptreq)) {
484 /* Force any required dependencies to load */
485 char *each, *required_resource = ast_strdupa(mod->info->nonoptreq);
486 while ((each = strsep(&required_resource, ","))) {
487 struct ast_module *dependency;
488 each = ast_strip(each);
489 dependency = find_resource(each, 0);
490 /* Is it already loaded? */
492 load_resource(each, global_symbols_only, resource_heap, 1);
498 while (!dlclose(lib));
499 resource_being_loaded = NULL;
501 /* start the load process again */
502 resource_being_loaded = ast_calloc(1, space);
503 if (!resource_being_loaded)
505 strcpy(resource_being_loaded->resource, resource_in);
507 strcat(resource_being_loaded->resource, ".so");
509 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
510 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
511 ast_free(resource_being_loaded);
515 /* since the module was successfully opened, and it registered itself
516 the previous time we did that, we're going to assume it worked this
519 AST_LIST_LAST(&module_list)->lib = lib;
520 resource_being_loaded = NULL;
522 return AST_LIST_LAST(&module_list);
526 void ast_module_shutdown(void)
528 struct ast_module *mod;
529 int somethingchanged = 1, final = 0;
531 AST_LIST_LOCK(&module_list);
533 /*!\note Some resources, like timers, are started up dynamically, and thus
534 * may be still in use, even if all channels are dead. We must therefore
535 * check the usecount before asking modules to unload. */
537 if (!somethingchanged) {
538 /*!\note If we go through the entire list without changing
539 * anything, ignore the usecounts and unload, then exit. */
543 /* Reset flag before traversing the list */
544 somethingchanged = 0;
546 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
547 if (!final && mod->usecount) {
550 AST_LIST_REMOVE_CURRENT(entry);
551 if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
552 ast_verb(1, "Unloading %s\n", mod->resource);
555 AST_LIST_HEAD_DESTROY(&mod->users);
557 somethingchanged = 1;
559 AST_LIST_TRAVERSE_SAFE_END;
560 } while (somethingchanged && !final);
562 AST_LIST_UNLOCK(&module_list);
565 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
567 struct ast_module *mod;
571 AST_LIST_LOCK(&module_list);
573 if (!(mod = find_resource(resource_name, 0))) {
574 AST_LIST_UNLOCK(&module_list);
575 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
579 if (!mod->flags.running || mod->flags.declined) {
580 ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
584 if (!error && (mod->usecount > 0)) {
586 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
587 resource_name, mod->usecount);
589 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
596 /* Request any channels attached to the module to hangup. */
597 __ast_module_user_hangup_all(mod);
599 ast_verb(1, "Unloading %s\n", mod->resource);
600 res = mod->info->unload();
602 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
603 if (force <= AST_FORCE_FIRM) {
606 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
612 * Request hangup on any channels that managed to get attached
613 * while we called the module unload function.
615 __ast_module_user_hangup_all(mod);
621 mod->flags.running = mod->flags.declined = 0;
623 AST_LIST_UNLOCK(&module_list);
625 if (!error && !mod->lib && mod->info && mod->info->restore_globals)
626 mod->info->restore_globals();
628 #ifdef LOADABLE_MODULES
630 unload_dynamic_module(mod);
631 ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
636 ast_update_use_count();
641 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
643 struct ast_module *cur;
644 int i, which=0, l = strlen(word);
650 AST_LIST_LOCK(&module_list);
651 AST_LIST_TRAVERSE(&module_list, cur, entry) {
652 if (!strncasecmp(word, cur->resource, l) &&
653 (cur->info->reload || !needsreload) &&
655 ret = ast_strdup(cur->resource);
659 AST_LIST_UNLOCK(&module_list);
662 for (i=0; !ret && reload_classes[i].name; i++) {
663 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
664 ret = ast_strdup(reload_classes[i].name);
671 void ast_process_pending_reloads(void)
673 struct reload_queue_item *item;
675 if (!ast_fully_booted) {
679 AST_LIST_LOCK(&reload_queue);
681 if (do_full_reload) {
683 AST_LIST_UNLOCK(&reload_queue);
684 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
685 ast_module_reload(NULL);
689 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
690 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
691 ast_module_reload(item->module);
695 AST_LIST_UNLOCK(&reload_queue);
698 static void queue_reload_request(const char *module)
700 struct reload_queue_item *item;
702 AST_LIST_LOCK(&reload_queue);
704 if (do_full_reload) {
705 AST_LIST_UNLOCK(&reload_queue);
709 if (ast_strlen_zero(module)) {
710 /* A full reload request (when module is NULL) wipes out any previous
711 reload requests and causes the queue to ignore future ones */
712 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
717 /* No reason to add the same module twice */
718 AST_LIST_TRAVERSE(&reload_queue, item, entry) {
719 if (!strcasecmp(item->module, module)) {
720 AST_LIST_UNLOCK(&reload_queue);
724 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
726 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
727 AST_LIST_UNLOCK(&reload_queue);
730 strcpy(item->module, module);
731 AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
733 AST_LIST_UNLOCK(&reload_queue);
739 * \brief Publish a \ref stasis message regarding the reload result
741 static void publish_reload_message(const char *name, enum ast_module_reload_result result)
743 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
744 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
745 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
746 RAII_VAR(struct ast_json *, event_object, NULL, ast_json_unref);
749 snprintf(res_buffer, sizeof(res_buffer), "%d", result);
750 event_object = ast_json_pack("{s: s, s: s}",
751 "Module", S_OR(name, "All"),
752 "Status", res_buffer);
753 json_object = ast_json_pack("{s: s, s: i, s: O}",
755 "class_type", EVENT_FLAG_SYSTEM,
756 "event", event_object);
762 payload = ast_json_payload_create(json_object);
767 message = stasis_message_create(ast_manager_get_generic_type(), payload);
772 stasis_publish(ast_manager_get_topic(), message);
775 enum ast_module_reload_result ast_module_reload(const char *name)
777 struct ast_module *cur;
778 enum ast_module_reload_result res = AST_MODULE_RELOAD_NOT_FOUND;
781 /* If we aren't fully booted, we just pretend we reloaded but we queue this
782 up to run once we are booted up. */
783 if (!ast_fully_booted) {
784 queue_reload_request(name);
785 res = AST_MODULE_RELOAD_QUEUED;
786 goto module_reload_exit;
789 if (ast_mutex_trylock(&reloadlock)) {
790 ast_verbose("The previous reload command didn't finish yet\n");
791 res = AST_MODULE_RELOAD_IN_PROGRESS;
792 goto module_reload_exit;
794 ast_lastreloadtime = ast_tvnow();
796 if (ast_opt_lock_confdir) {
799 for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) {
800 res = ast_lock_path(ast_config_AST_CONFIG_DIR);
801 if (res == AST_LOCK_TIMEOUT) {
802 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
805 if (res != AST_LOCK_SUCCESS) {
806 ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
807 ast_mutex_unlock(&reloadlock);
808 res = AST_MODULE_RELOAD_ERROR;
809 goto module_reload_exit;
813 /* Call "predefined" reload here first */
814 for (i = 0; reload_classes[i].name; i++) {
815 if (!name || !strcasecmp(name, reload_classes[i].name)) {
816 if (reload_classes[i].reload_fn() == AST_MODULE_LOAD_SUCCESS) {
817 res = AST_MODULE_RELOAD_SUCCESS;
822 if (name && res == AST_MODULE_RELOAD_SUCCESS) {
823 if (ast_opt_lock_confdir) {
824 ast_unlock_path(ast_config_AST_CONFIG_DIR);
826 ast_mutex_unlock(&reloadlock);
827 goto module_reload_exit;
830 AST_LIST_LOCK(&module_list);
831 AST_LIST_TRAVERSE(&module_list, cur, entry) {
832 const struct ast_module_info *info = cur->info;
834 if (name && resource_name_match(name, cur->resource))
837 if (!cur->flags.running || cur->flags.declined) {
838 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
839 res = AST_MODULE_RELOAD_UNINITIALIZED;
847 if (!info->reload) { /* cannot be reloaded */
848 if (res == AST_MODULE_RELOAD_NOT_FOUND) {
849 res = AST_MODULE_RELOAD_NOT_IMPLEMENTED;
856 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
857 if (info->reload() == AST_MODULE_LOAD_SUCCESS) {
858 res = AST_MODULE_RELOAD_SUCCESS;
864 AST_LIST_UNLOCK(&module_list);
866 if (ast_opt_lock_confdir) {
867 ast_unlock_path(ast_config_AST_CONFIG_DIR);
869 ast_mutex_unlock(&reloadlock);
872 publish_reload_message(name, res);
876 static unsigned int inspect_module(const struct ast_module *mod)
878 if (!mod->info->description) {
879 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
883 if (!mod->info->key) {
884 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
888 if (verify_key((unsigned char *) mod->info->key)) {
889 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
893 if (!ast_strlen_zero(mod->info->buildopt_sum) &&
894 strcmp(buildopt_sum, mod->info->buildopt_sum)) {
895 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
896 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
903 static enum ast_module_load_result start_resource(struct ast_module *mod)
906 enum ast_module_load_result res;
908 if (mod->flags.running) {
909 return AST_MODULE_LOAD_SUCCESS;
912 if (!mod->info->load) {
913 return AST_MODULE_LOAD_FAILURE;
916 if (!ast_fully_booted) {
917 ast_verb(1, "Loading %s.\n", mod->resource);
919 res = mod->info->load();
922 case AST_MODULE_LOAD_SUCCESS:
923 if (!ast_fully_booted) {
924 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
925 if (ast_opt_console && !option_verbose) {
926 /* This never looks good on anything but the root console, so
927 * it's best not to try to funnel it through the logger. */
928 fprintf(stdout, ".");
931 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
934 mod->flags.running = 1;
936 ast_update_use_count();
938 case AST_MODULE_LOAD_DECLINE:
939 mod->flags.declined = 1;
941 case AST_MODULE_LOAD_FAILURE:
942 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
943 case AST_MODULE_LOAD_PRIORITY:
950 /*! loads a resource based upon resource_name. If global_symbols_only is set
951 * only modules with global symbols will be loaded.
953 * If the ast_heap is provided (not NULL) the module is found and added to the
954 * heap without running the module's load() function. By doing this, modules
955 * added to the resource_heap can be initialized later in order by priority.
957 * If the ast_heap is not provided, the module's load function will be executed
959 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap, int required)
961 struct ast_module *mod;
962 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
964 if ((mod = find_resource(resource_name, 0))) {
965 if (mod->flags.running) {
966 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
967 return AST_MODULE_LOAD_DECLINE;
969 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
970 return AST_MODULE_LOAD_SKIP;
972 #ifdef LOADABLE_MODULES
973 if (!(mod = load_dynamic_module(resource_name, global_symbols_only, resource_heap))) {
974 /* don't generate a warning message during load_modules() */
975 if (!global_symbols_only) {
976 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
977 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
979 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP;
983 ast_log(LOG_WARNING, "Module support is not available. Module '%s' could not be loaded.\n", resource_name);
984 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
988 if (inspect_module(mod)) {
989 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
990 #ifdef LOADABLE_MODULES
991 unload_dynamic_module(mod);
993 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
996 if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) {
997 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
998 return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
1001 mod->flags.declined = 0;
1003 if (resource_heap) {
1004 ast_heap_push(resource_heap, mod);
1005 res = AST_MODULE_LOAD_PRIORITY;
1007 res = start_resource(mod);
1010 /* Now make sure that the list is sorted */
1011 AST_LIST_LOCK(&module_list);
1012 AST_LIST_REMOVE(&module_list, mod, entry);
1013 AST_LIST_INSERT_SORTALPHA(&module_list, mod, entry, resource);
1014 AST_LIST_UNLOCK(&module_list);
1019 int ast_load_resource(const char *resource_name)
1022 AST_LIST_LOCK(&module_list);
1023 res = load_resource(resource_name, 0, NULL, 0);
1025 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
1027 AST_LIST_UNLOCK(&module_list);
1032 struct load_order_entry {
1035 AST_LIST_ENTRY(load_order_entry) entry;
1038 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
1040 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required)
1042 struct load_order_entry *order;
1044 AST_LIST_TRAVERSE(load_order, order, entry) {
1045 if (!resource_name_match(order->resource, resource)) {
1046 /* Make sure we have the proper setting for the required field
1047 (we might have both load= and required= lines in modules.conf) */
1048 order->required |= required;
1053 if (!(order = ast_calloc(1, sizeof(*order))))
1056 order->resource = ast_strdup(resource);
1057 order->required = required;
1058 AST_LIST_INSERT_TAIL(load_order, order, entry);
1063 static int mod_load_cmp(void *a, void *b)
1065 struct ast_module *a_mod = (struct ast_module *) a;
1066 struct ast_module *b_mod = (struct ast_module *) b;
1067 /* if load_pri is not set, default is 128. Lower is better */
1068 int a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
1069 int b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
1072 * Returns comparison values for a min-heap
1077 return b_pri - a_pri;
1080 /*! loads modules in order by load_pri, updates mod_count
1081 \return -1 on failure to load module, -2 on failure to load required module, otherwise 0
1083 static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
1085 struct ast_heap *resource_heap;
1086 struct load_order_entry *order;
1087 struct ast_module *mod;
1091 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
1095 /* first, add find and add modules to heap */
1096 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
1097 switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) {
1098 case AST_MODULE_LOAD_SUCCESS:
1099 case AST_MODULE_LOAD_DECLINE:
1100 AST_LIST_REMOVE_CURRENT(entry);
1101 ast_free(order->resource);
1104 case AST_MODULE_LOAD_FAILURE:
1105 ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
1106 fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
1107 res = order->required ? -2 : -1;
1109 case AST_MODULE_LOAD_SKIP:
1111 case AST_MODULE_LOAD_PRIORITY:
1112 AST_LIST_REMOVE_CURRENT(entry);
1113 ast_free(order->resource);
1118 AST_LIST_TRAVERSE_SAFE_END;
1120 /* second remove modules from heap sorted by priority */
1121 while ((mod = ast_heap_pop(resource_heap))) {
1122 switch (start_resource(mod)) {
1123 case AST_MODULE_LOAD_SUCCESS:
1125 case AST_MODULE_LOAD_DECLINE:
1127 case AST_MODULE_LOAD_FAILURE:
1130 case AST_MODULE_LOAD_SKIP:
1131 case AST_MODULE_LOAD_PRIORITY:
1138 *mod_count += count;
1140 ast_heap_destroy(resource_heap);
1145 int load_modules(unsigned int preload_only)
1147 struct ast_config *cfg;
1148 struct ast_module *mod;
1149 struct load_order_entry *order;
1150 struct ast_variable *v;
1151 unsigned int load_count;
1152 struct load_order load_order;
1154 struct ast_flags config_flags = { 0 };
1155 int modulecount = 0;
1157 #ifdef LOADABLE_MODULES
1158 struct dirent *dirent;
1162 /* all embedded modules have registered themselves by now */
1165 ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
1167 AST_LIST_HEAD_INIT_NOLOCK(&load_order);
1169 AST_LIST_LOCK(&module_list);
1171 if (embedded_module_list.first) {
1172 module_list.first = embedded_module_list.first;
1173 module_list.last = embedded_module_list.last;
1174 embedded_module_list.first = NULL;
1177 cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
1178 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
1179 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
1183 /* first, find all the modules we have been explicitly requested to load */
1184 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
1185 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
1186 add_to_load_order(v->value, &load_order, 0);
1188 if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) {
1189 /* Add the module to the list and make sure it's required */
1190 add_to_load_order(v->value, &load_order, 1);
1191 ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
1196 /* check if 'autoload' is on */
1197 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
1198 /* if so, first add all the embedded modules that are not already running to the load order */
1199 AST_LIST_TRAVERSE(&module_list, mod, entry) {
1200 /* if it's not embedded, skip it */
1204 if (mod->flags.running)
1207 add_to_load_order(mod->resource, &load_order, 0);
1210 #ifdef LOADABLE_MODULES
1211 /* if we are allowed to load dynamic modules, scan the directory for
1212 for all available modules and add them as well */
1213 if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
1214 while ((dirent = readdir(dir))) {
1215 int ld = strlen(dirent->d_name);
1217 /* Must end in .so to load it. */
1222 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
1225 /* if there is already a module by this name in the module_list,
1227 if (find_resource(dirent->d_name, 0))
1230 add_to_load_order(dirent->d_name, &load_order, 0);
1236 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
1237 ast_config_AST_MODULE_DIR);
1242 /* now scan the config for any modules we are prohibited from loading and
1243 remove them from the load order */
1244 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
1245 if (strcasecmp(v->name, "noload"))
1248 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
1249 if (!resource_name_match(order->resource, v->value)) {
1250 AST_LIST_REMOVE_CURRENT(entry);
1251 ast_free(order->resource);
1255 AST_LIST_TRAVERSE_SAFE_END;
1258 /* we are done with the config now, all the information we need is in the
1260 ast_config_destroy(cfg);
1263 AST_LIST_TRAVERSE(&load_order, order, entry)
1267 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
1269 /* first, load only modules that provide global symbols */
1270 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
1274 /* now load everything else */
1275 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
1280 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
1281 ast_free(order->resource);
1285 AST_LIST_UNLOCK(&module_list);
1289 void ast_update_use_count(void)
1291 /* Notify any module monitors that the use count for a
1292 resource has changed */
1293 struct loadupdate *m;
1295 AST_LIST_LOCK(&updaters);
1296 AST_LIST_TRAVERSE(&updaters, m, entry)
1298 AST_LIST_UNLOCK(&updaters);
1301 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like),
1304 struct ast_module *cur;
1306 int total_mod_loaded = 0;
1308 if (AST_LIST_TRYLOCK(&module_list))
1311 AST_LIST_TRAVERSE(&module_list, cur, entry) {
1312 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
1313 cur->flags.running ? "Running" : "Not Running", like);
1317 AST_LIST_UNLOCK(&module_list);
1319 return total_mod_loaded;
1322 /*! \brief Check if module exists */
1323 int ast_module_check(const char *name)
1325 struct ast_module *cur;
1327 if (ast_strlen_zero(name))
1328 return 0; /* FALSE */
1330 cur = find_resource(name, 1);
1332 return (cur != NULL);
1336 int ast_loader_register(int (*v)(void))
1338 struct loadupdate *tmp;
1340 if (!(tmp = ast_malloc(sizeof(*tmp))))
1344 AST_LIST_LOCK(&updaters);
1345 AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
1346 AST_LIST_UNLOCK(&updaters);
1351 int ast_loader_unregister(int (*v)(void))
1353 struct loadupdate *cur;
1355 AST_LIST_LOCK(&updaters);
1356 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
1357 if (cur->updater == v) {
1358 AST_LIST_REMOVE_CURRENT(entry);
1362 AST_LIST_TRAVERSE_SAFE_END;
1363 AST_LIST_UNLOCK(&updaters);
1365 return cur ? 0 : -1;
1368 struct ast_module *ast_module_ref(struct ast_module *mod)
1374 ast_atomic_fetchadd_int(&mod->usecount, +1);
1375 ast_update_use_count();
1380 void ast_module_unref(struct ast_module *mod)
1386 ast_atomic_fetchadd_int(&mod->usecount, -1);
1387 ast_update_use_count();