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: 213453 $")
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/rtp.h"
47
#include "asterisk/http.h"
48
#include "asterisk/lock.h"
49
#include "asterisk/features.h"
50
#include "asterisk/dsp.h"
51
#include "asterisk/udptl.h"
52
#include "asterisk/heap.h"
56
#include "asterisk/md5.h"
57
#include "asterisk/utils.h"
67
struct ast_module_user {
68
struct ast_channel *chan;
69
AST_LIST_ENTRY(ast_module_user) entry;
72
AST_LIST_HEAD(module_user_list, ast_module_user);
74
static unsigned char expected_key[] =
75
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
76
0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
78
static char buildopt_sum[33] = AST_BUILDOPT_SUM;
80
static unsigned int embedding = 1; /* we always start out by registering embedded modules,
81
since they are here before we dlopen() any
85
const struct ast_module_info *info;
86
void *lib; /* the shared lib, or NULL if embedded */
87
int usecount; /* the number of 'users' currently in this module */
88
struct module_user_list users; /* the list of users in the module */
90
unsigned int running:1;
91
unsigned int declined:1;
93
AST_LIST_ENTRY(ast_module) entry;
97
static AST_LIST_HEAD_STATIC(module_list, ast_module);
100
* module_list is cleared by its constructor possibly after
101
* we start accumulating embedded modules, so we need to
102
* use another list (without the lock) to accumulate them.
103
* Then we update the main list when embedding is done.
105
static struct module_list embedded_module_list;
108
int (*updater)(void);
109
AST_LIST_ENTRY(loadupdate) entry;
112
static AST_LIST_HEAD_STATIC(updaters, loadupdate);
114
AST_MUTEX_DEFINE_STATIC(reloadlock);
116
struct reload_queue_item {
117
AST_LIST_ENTRY(reload_queue_item) entry;
121
static int do_full_reload = 0;
123
static AST_LIST_HEAD_STATIC(reload_queue, reload_queue_item);
125
/* when dynamic modules are being loaded, ast_module_register() will
126
need to know what filename the module was loaded from while it
129
struct ast_module *resource_being_loaded;
131
/* XXX: should we check for duplicate resource names here? */
133
void ast_module_register(const struct ast_module_info *info)
135
struct ast_module *mod;
138
if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
140
strcpy(mod->resource, info->name);
142
mod = resource_being_loaded;
146
AST_LIST_HEAD_INIT(&mod->users);
148
/* during startup, before the loader has been initialized,
149
there are no threads, so there is no need to take the lock
150
on this list to manipulate it. it is also possible that it
151
might be unsafe to use the list lock at that point... so
152
let's avoid it altogether
155
AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
157
AST_LIST_LOCK(&module_list);
158
/* it is paramount that the new entry be placed at the tail of
159
the list, otherwise the code that uses dlopen() to load
160
dynamic modules won't be able to find out if the module it
161
just opened was registered or failed to load
163
AST_LIST_INSERT_TAIL(&module_list, mod, entry);
164
AST_LIST_UNLOCK(&module_list);
167
/* give the module a copy of its own handle, for later use in registrations and the like */
168
*((struct ast_module **) &(info->self)) = mod;
171
void ast_module_unregister(const struct ast_module_info *info)
173
struct ast_module *mod = NULL;
175
/* it is assumed that the users list in the module structure
176
will already be empty, or we cannot have gotten to this
179
AST_LIST_LOCK(&module_list);
180
AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
181
if (mod->info == info) {
182
AST_LIST_REMOVE_CURRENT(entry);
186
AST_LIST_TRAVERSE_SAFE_END;
187
AST_LIST_UNLOCK(&module_list);
190
AST_LIST_HEAD_DESTROY(&mod->users);
195
struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
196
struct ast_channel *chan)
198
struct ast_module_user *u = ast_calloc(1, sizeof(*u));
205
AST_LIST_LOCK(&mod->users);
206
AST_LIST_INSERT_HEAD(&mod->users, u, entry);
207
AST_LIST_UNLOCK(&mod->users);
209
ast_atomic_fetchadd_int(&mod->usecount, +1);
211
ast_update_use_count();
216
void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
218
AST_LIST_LOCK(&mod->users);
219
AST_LIST_REMOVE(&mod->users, u, entry);
220
AST_LIST_UNLOCK(&mod->users);
221
ast_atomic_fetchadd_int(&mod->usecount, -1);
224
ast_update_use_count();
227
void __ast_module_user_hangup_all(struct ast_module *mod)
229
struct ast_module_user *u;
231
AST_LIST_LOCK(&mod->users);
232
while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
233
ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
234
ast_atomic_fetchadd_int(&mod->usecount, -1);
237
AST_LIST_UNLOCK(&mod->users);
239
ast_update_use_count();
243
* In addition to modules, the reload command handles some extra keywords
244
* which are listed here together with the corresponding handlers.
245
* This table is also used by the command completion code.
247
static struct reload_classes {
249
int (*reload_fn)(void);
250
} reload_classes[] = { /* list in alpha order, longest match first for cli completion */
251
{ "cdr", ast_cdr_engine_reload },
252
{ "dnsmgr", dnsmgr_reload },
253
{ "extconfig", read_config_maps },
254
{ "enum", ast_enum_reload },
255
{ "manager", reload_manager },
256
{ "rtp", ast_rtp_reload },
257
{ "http", ast_http_reload },
258
{ "logger", logger_reload },
259
{ "features", ast_features_reload },
260
{ "dsp", ast_dsp_reload},
261
{ "udptl", ast_udptl_reload },
262
{ "indications", ast_indications_reload },
266
static int printdigest(const unsigned char *d)
269
char buf[256]; /* large enough so we don't have to worry */
271
for (pos = 0, x = 0; x < 16; x++)
272
pos += sprintf(buf + pos, " %02x", *d++);
274
ast_debug(1, "Unexpected signature:%s\n", buf);
279
static int key_matches(const unsigned char *key1, const unsigned char *key2)
283
for (x = 0; x < 16; x++) {
284
if (key1[x] != key2[x])
291
static int verify_key(const unsigned char *key)
294
unsigned char digest[16];
297
MD5Update(&c, key, strlen((char *)key));
298
MD5Final(digest, &c);
300
if (key_matches(expected_key, digest))
308
static int resource_name_match(const char *name1_in, const char *name2_in)
310
char *name1 = (char *) name1_in;
311
char *name2 = (char *) name2_in;
313
/* trim off any .so extensions */
314
if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
315
name1 = ast_strdupa(name1);
316
name1[strlen(name1) - 3] = '\0';
318
if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
319
name2 = ast_strdupa(name2);
320
name2[strlen(name2) - 3] = '\0';
323
return strcasecmp(name1, name2);
326
static struct ast_module *find_resource(const char *resource, int do_lock)
328
struct ast_module *cur;
331
AST_LIST_LOCK(&module_list);
333
AST_LIST_TRAVERSE(&module_list, cur, entry) {
334
if (!resource_name_match(resource, cur->resource))
339
AST_LIST_UNLOCK(&module_list);
344
#ifdef LOADABLE_MODULES
345
static void unload_dynamic_module(struct ast_module *mod)
347
void *lib = mod->lib;
349
/* WARNING: the structure pointed to by mod is going to
350
disappear when this operation succeeds, so we can't
354
while (!dlclose(lib));
357
static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
359
char fn[PATH_MAX] = "";
361
struct ast_module *mod;
362
unsigned int wants_global;
363
int space; /* room needed for the descriptor */
366
space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
367
if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
369
space += 3; /* room for the extra ".so" */
372
snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
374
/* make a first load of the module in 'quiet' mode... don't try to resolve
375
any symbols, and don't export any symbols. this will allow us to peek into
376
the module's info block (if available) to see what flags it has set */
378
resource_being_loaded = ast_calloc(1, space);
379
if (!resource_being_loaded)
381
strcpy(resource_being_loaded->resource, resource_in);
383
strcat(resource_being_loaded->resource, ".so");
385
if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
386
ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
387
ast_free(resource_being_loaded);
391
/* the dlopen() succeeded, let's find out if the module
393
/* note that this will only work properly as long as
394
ast_module_register() (which is called by the module's
395
constructor) places the new module at the tail of the
398
if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
399
ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
400
/* no, it did not, so close it and return */
401
while (!dlclose(lib));
402
/* note that the module's destructor will call ast_module_unregister(),
403
which will free the structure we allocated in resource_being_loaded */
407
wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
409
/* if we are being asked only to load modules that provide global symbols,
410
and this one does not, then close it and return */
411
if (global_symbols_only && !wants_global) {
412
while (!dlclose(lib));
416
while (!dlclose(lib));
417
resource_being_loaded = NULL;
419
/* start the load process again */
420
resource_being_loaded = ast_calloc(1, space);
421
if (!resource_being_loaded)
423
strcpy(resource_being_loaded->resource, resource_in);
425
strcat(resource_being_loaded->resource, ".so");
427
if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
428
ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
429
ast_free(resource_being_loaded);
433
/* since the module was successfully opened, and it registered itself
434
the previous time we did that, we're going to assume it worked this
437
AST_LIST_LAST(&module_list)->lib = lib;
438
resource_being_loaded = NULL;
440
return AST_LIST_LAST(&module_list);
444
void ast_module_shutdown(void)
446
struct ast_module *mod;
447
AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
449
/* We have to call the unload() callbacks in reverse order that the modules
450
* exist in the module list so it is the reverse order of how they were
453
AST_LIST_LOCK(&module_list);
454
while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
455
AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
456
AST_LIST_UNLOCK(&module_list);
458
while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
459
if (mod->info->unload)
461
/* Since this should only be called when shutting down "gracefully",
462
* all channels should be down before we get to this point, meaning
463
* there will be no module users left. */
464
AST_LIST_HEAD_DESTROY(&mod->users);
469
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
471
struct ast_module *mod;
475
AST_LIST_LOCK(&module_list);
477
if (!(mod = find_resource(resource_name, 0))) {
478
AST_LIST_UNLOCK(&module_list);
479
ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
483
if (!(mod->flags.running || mod->flags.declined))
486
if (!error && (mod->usecount > 0)) {
488
ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
489
resource_name, mod->usecount);
491
ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
498
__ast_module_user_hangup_all(mod);
499
res = mod->info->unload();
502
ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
503
if (force <= AST_FORCE_FIRM)
506
ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
511
mod->flags.running = mod->flags.declined = 0;
513
AST_LIST_UNLOCK(&module_list);
515
if (!error && !mod->lib && mod->info && mod->info->restore_globals)
516
mod->info->restore_globals();
518
#ifdef LOADABLE_MODULES
520
unload_dynamic_module(mod);
524
ast_update_use_count();
529
char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
531
struct ast_module *cur;
532
int i, which=0, l = strlen(word);
538
AST_LIST_LOCK(&module_list);
539
AST_LIST_TRAVERSE(&module_list, cur, entry) {
540
if (!strncasecmp(word, cur->resource, l) &&
541
(cur->info->reload || !needsreload) &&
543
ret = ast_strdup(cur->resource);
547
AST_LIST_UNLOCK(&module_list);
550
for (i=0; !ret && reload_classes[i].name; i++) {
551
if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
552
ret = ast_strdup(reload_classes[i].name);
559
void ast_process_pending_reloads(void)
561
struct reload_queue_item *item;
563
if (!ast_fully_booted) {
567
AST_LIST_LOCK(&reload_queue);
569
if (do_full_reload) {
571
AST_LIST_UNLOCK(&reload_queue);
572
ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
573
ast_module_reload(NULL);
577
while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
578
ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
579
ast_module_reload(item->module);
583
AST_LIST_UNLOCK(&reload_queue);
586
static void queue_reload_request(const char *module)
588
struct reload_queue_item *item;
590
AST_LIST_LOCK(&reload_queue);
592
if (do_full_reload) {
593
AST_LIST_UNLOCK(&reload_queue);
597
if (ast_strlen_zero(module)) {
598
/* A full reload request (when module is NULL) wipes out any previous
599
reload requests and causes the queue to ignore future ones */
600
while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
605
/* No reason to add the same module twice */
606
AST_LIST_TRAVERSE(&reload_queue, item, entry) {
607
if (!strcasecmp(item->module, module)) {
608
AST_LIST_UNLOCK(&reload_queue);
612
item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
614
ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
615
AST_LIST_UNLOCK(&reload_queue);
618
strcpy(item->module, module);
619
AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
621
AST_LIST_UNLOCK(&reload_queue);
624
int ast_module_reload(const char *name)
626
struct ast_module *cur;
627
int res = 0; /* return value. 0 = not found, others, see below */
630
/* If we aren't fully booted, we just pretend we reloaded but we queue this
631
up to run once we are booted up. */
632
if (!ast_fully_booted) {
633
queue_reload_request(name);
637
if (ast_mutex_trylock(&reloadlock)) {
638
ast_verbose("The previous reload command didn't finish yet\n");
639
return -1; /* reload already in progress */
641
ast_lastreloadtime = ast_tvnow();
643
/* Call "predefined" reload here first */
644
for (i = 0; reload_classes[i].name; i++) {
645
if (!name || !strcasecmp(name, reload_classes[i].name)) {
646
reload_classes[i].reload_fn(); /* XXX should check error ? */
647
res = 2; /* found and reloaded */
652
ast_mutex_unlock(&reloadlock);
656
AST_LIST_LOCK(&module_list);
657
AST_LIST_TRAVERSE(&module_list, cur, entry) {
658
const struct ast_module_info *info = cur->info;
660
if (name && resource_name_match(name, cur->resource))
663
if (!cur->flags.running || cur->flags.declined) {
666
ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. "
667
"Before reloading the module, you must run \"module load %s\" "
668
"and fix whatever is preventing the module from being initialized.\n",
670
res = 2; /* Don't report that the module was not found */
674
if (!info->reload) { /* cannot be reloaded */
675
if (res < 1) /* store result if possible */
676
res = 1; /* 1 = no reload() method */
681
ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
684
AST_LIST_UNLOCK(&module_list);
686
ast_mutex_unlock(&reloadlock);
691
static unsigned int inspect_module(const struct ast_module *mod)
693
if (!mod->info->description) {
694
ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
698
if (!mod->info->key) {
699
ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
703
if (verify_key((unsigned char *) mod->info->key)) {
704
ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
708
if (!ast_strlen_zero(mod->info->buildopt_sum) &&
709
strcmp(buildopt_sum, mod->info->buildopt_sum)) {
710
ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
711
ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
718
static enum ast_module_load_result start_resource(struct ast_module *mod)
721
enum ast_module_load_result res;
723
if (!mod->info->load) {
724
return AST_MODULE_LOAD_FAILURE;
727
res = mod->info->load();
730
case AST_MODULE_LOAD_SUCCESS:
731
if (!ast_fully_booted) {
732
ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
733
if (ast_opt_console && !option_verbose)
736
ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
739
mod->flags.running = 1;
741
ast_update_use_count();
743
case AST_MODULE_LOAD_DECLINE:
744
mod->flags.declined = 1;
746
case AST_MODULE_LOAD_FAILURE:
747
case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
748
case AST_MODULE_LOAD_PRIORITY:
755
/*! loads a resource based upon resource_name. If global_symbols_only is set
756
* only modules with global symbols will be loaded.
758
* If the ast_heap is provided (not NULL) the module is found and added to the
759
* heap without running the module's load() function. By doing this, modules
760
* added to the resource_heap can be initialized later in order by priority.
762
* If the ast_heap is not provided, the module's load function will be executed
764
static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap)
766
struct ast_module *mod;
767
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
769
if ((mod = find_resource(resource_name, 0))) {
770
if (mod->flags.running) {
771
ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
772
return AST_MODULE_LOAD_DECLINE;
774
if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
775
return AST_MODULE_LOAD_SKIP;
777
#ifdef LOADABLE_MODULES
778
if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
779
/* don't generate a warning message during load_modules() */
780
if (!global_symbols_only) {
781
ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
782
return AST_MODULE_LOAD_DECLINE;
784
return AST_MODULE_LOAD_SKIP;
788
ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
789
return AST_MODULE_LOAD_DECLINE;
793
if (inspect_module(mod)) {
794
ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
795
#ifdef LOADABLE_MODULES
796
unload_dynamic_module(mod);
798
return AST_MODULE_LOAD_DECLINE;
801
if (!mod->lib && mod->info->backup_globals()) {
802
ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
803
return AST_MODULE_LOAD_DECLINE;
806
mod->flags.declined = 0;
809
ast_heap_push(resource_heap, mod);
810
res = AST_MODULE_LOAD_PRIORITY;
812
res = start_resource(mod);
818
int ast_load_resource(const char *resource_name)
821
AST_LIST_LOCK(&module_list);
822
res = load_resource(resource_name, 0, NULL);
823
AST_LIST_UNLOCK(&module_list);
828
struct load_order_entry {
830
AST_LIST_ENTRY(load_order_entry) entry;
833
AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
835
static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
837
struct load_order_entry *order;
839
AST_LIST_TRAVERSE(load_order, order, entry) {
840
if (!resource_name_match(order->resource, resource))
844
if (!(order = ast_calloc(1, sizeof(*order))))
847
order->resource = ast_strdup(resource);
848
AST_LIST_INSERT_TAIL(load_order, order, entry);
853
static int mod_load_cmp(void *a, void *b)
855
struct ast_module *a_mod = (struct ast_module *) a;
856
struct ast_module *b_mod = (struct ast_module *) b;
858
/* if load_pri is not set, default is 255. Lower is better*/
859
unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
860
unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
861
if (a_pri == b_pri) {
863
} else if (a_pri < b_pri) {
869
/*! loads modules in order by load_pri, updates mod_count */
870
static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
872
struct ast_heap *resource_heap;
873
struct load_order_entry *order;
874
struct ast_module *mod;
878
if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
882
/* first, add find and add modules to heap */
883
AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
884
switch (load_resource(order->resource, global_symbols, resource_heap)) {
885
case AST_MODULE_LOAD_SUCCESS:
886
case AST_MODULE_LOAD_DECLINE:
887
AST_LIST_REMOVE_CURRENT(entry);
888
ast_free(order->resource);
891
case AST_MODULE_LOAD_FAILURE:
894
case AST_MODULE_LOAD_SKIP:
896
case AST_MODULE_LOAD_PRIORITY:
897
AST_LIST_REMOVE_CURRENT(entry);
901
AST_LIST_TRAVERSE_SAFE_END;
903
/* second remove modules from heap sorted by priority */
904
while ((mod = ast_heap_pop(resource_heap))) {
905
switch (start_resource(mod)) {
906
case AST_MODULE_LOAD_SUCCESS:
908
case AST_MODULE_LOAD_DECLINE:
910
case AST_MODULE_LOAD_FAILURE:
913
case AST_MODULE_LOAD_SKIP:
914
case AST_MODULE_LOAD_PRIORITY:
923
ast_heap_destroy(resource_heap);
928
int load_modules(unsigned int preload_only)
930
struct ast_config *cfg;
931
struct ast_module *mod;
932
struct load_order_entry *order;
933
struct ast_variable *v;
934
unsigned int load_count;
935
struct load_order load_order;
937
struct ast_flags config_flags = { 0 };
940
#ifdef LOADABLE_MODULES
941
struct dirent *dirent;
945
/* all embedded modules have registered themselves by now */
948
ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
950
AST_LIST_HEAD_INIT_NOLOCK(&load_order);
952
AST_LIST_LOCK(&module_list);
954
if (embedded_module_list.first) {
955
module_list.first = embedded_module_list.first;
956
module_list.last = embedded_module_list.last;
957
embedded_module_list.first = NULL;
960
cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
961
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
962
ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
966
/* first, find all the modules we have been explicitly requested to load */
967
for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
968
if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
969
add_to_load_order(v->value, &load_order);
973
/* check if 'autoload' is on */
974
if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
975
/* if so, first add all the embedded modules that are not already running to the load order */
976
AST_LIST_TRAVERSE(&module_list, mod, entry) {
977
/* if it's not embedded, skip it */
981
if (mod->flags.running)
984
order = add_to_load_order(mod->resource, &load_order);
987
#ifdef LOADABLE_MODULES
988
/* if we are allowed to load dynamic modules, scan the directory for
989
for all available modules and add them as well */
990
if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
991
while ((dirent = readdir(dir))) {
992
int ld = strlen(dirent->d_name);
994
/* Must end in .so to load it. */
999
if (strcasecmp(dirent->d_name + ld - 3, ".so"))
1002
/* if there is already a module by this name in the module_list,
1004
if (find_resource(dirent->d_name, 0))
1007
add_to_load_order(dirent->d_name, &load_order);
1013
ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
1014
ast_config_AST_MODULE_DIR);
1019
/* now scan the config for any modules we are prohibited from loading and
1020
remove them from the load order */
1021
for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
1022
if (strcasecmp(v->name, "noload"))
1025
AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
1026
if (!resource_name_match(order->resource, v->value)) {
1027
AST_LIST_REMOVE_CURRENT(entry);
1028
ast_free(order->resource);
1032
AST_LIST_TRAVERSE_SAFE_END;
1035
/* we are done with the config now, all the information we need is in the
1037
ast_config_destroy(cfg);
1040
AST_LIST_TRAVERSE(&load_order, order, entry)
1044
ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
1046
/* first, load only modules that provide global symbols */
1047
if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
1051
/* now load everything else */
1052
if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
1057
while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
1058
ast_free(order->resource);
1062
AST_LIST_UNLOCK(&module_list);
1064
/* Tell manager clients that are aggressive at logging in that we're done
1065
loading modules. If there's a DNS problem in chan_sip, we might not
1067
manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
1072
void ast_update_use_count(void)
1074
/* Notify any module monitors that the use count for a
1075
resource has changed */
1076
struct loadupdate *m;
1078
AST_LIST_LOCK(&updaters);
1079
AST_LIST_TRAVERSE(&updaters, m, entry)
1081
AST_LIST_UNLOCK(&updaters);
1084
int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
1087
struct ast_module *cur;
1089
int total_mod_loaded = 0;
1091
if (AST_LIST_TRYLOCK(&module_list))
1094
AST_LIST_TRAVERSE(&module_list, cur, entry) {
1095
total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
1099
AST_LIST_UNLOCK(&module_list);
1101
return total_mod_loaded;
1104
/*! \brief Check if module exists */
1105
int ast_module_check(const char *name)
1107
struct ast_module *cur;
1109
if (ast_strlen_zero(name))
1110
return 0; /* FALSE */
1112
cur = find_resource(name, 1);
1114
return (cur != NULL);
1118
int ast_loader_register(int (*v)(void))
1120
struct loadupdate *tmp;
1122
if (!(tmp = ast_malloc(sizeof(*tmp))))
1126
AST_LIST_LOCK(&updaters);
1127
AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
1128
AST_LIST_UNLOCK(&updaters);
1133
int ast_loader_unregister(int (*v)(void))
1135
struct loadupdate *cur;
1137
AST_LIST_LOCK(&updaters);
1138
AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
1139
if (cur->updater == v) {
1140
AST_LIST_REMOVE_CURRENT(entry);
1144
AST_LIST_TRAVERSE_SAFE_END;
1145
AST_LIST_UNLOCK(&updaters);
1147
return cur ? 0 : -1;
1150
struct ast_module *ast_module_ref(struct ast_module *mod)
1152
ast_atomic_fetchadd_int(&mod->usecount, +1);
1153
ast_update_use_count();
1158
void ast_module_unref(struct ast_module *mod)
1160
ast_atomic_fetchadd_int(&mod->usecount, -1);
1161
ast_update_use_count();