baddec707462e67f49637e4e199c78129e85cbe2
[asterisk/asterisk.git] / main / loader.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * Kevin P. Fleming <kpfleming@digium.com>
8  * Luigi Rizzo <rizzo@icir.org>
9  *
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.
15  *
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.
19  */
20
21 /*! \file
22  *
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>
27  * - See ModMngMnt
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/_private.h"
35 #include "asterisk/paths.h"     /* use ast_config_AST_MODULE_DIR */
36 #include <dirent.h>
37
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
53 #ifdef DLFCNCOMPAT
54 #include "asterisk/dlfcn-compat.h"
55 #else
56 #include <dlfcn.h>
57 #endif
58
59 #include "asterisk/md5.h"
60 #include "asterisk/utils.h"
61
62 #ifndef RTLD_NOW
63 #define RTLD_NOW 0
64 #endif
65
66 #ifndef RTLD_LOCAL
67 #define RTLD_LOCAL 0
68 #endif
69
70 struct ast_module_user {
71         struct ast_channel *chan;
72         AST_LIST_ENTRY(ast_module_user) entry;
73 };
74
75 AST_LIST_HEAD(module_user_list, ast_module_user);
76
77 static unsigned char expected_key[] =
78 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
79   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
80
81 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
82
83 static unsigned int embedding = 1; /* we always start out by registering embedded modules,
84                                       since they are here before we dlopen() any
85                                    */
86
87 struct ast_module {
88         const struct ast_module_info *info;
89         void *lib;                                      /* the shared lib, or NULL if embedded */
90         int usecount;                                   /* the number of 'users' currently in this module */
91         struct module_user_list users;                  /* the list of users in the module */
92         struct {
93                 unsigned int running:1;
94                 unsigned int declined:1;
95         } flags;
96         AST_LIST_ENTRY(ast_module) entry;
97         char resource[0];
98 };
99
100 static AST_LIST_HEAD_STATIC(module_list, ast_module);
101
102 /*
103  * module_list is cleared by its constructor possibly after
104  * we start accumulating embedded modules, so we need to
105  * use another list (without the lock) to accumulate them.
106  * Then we update the main list when embedding is done.
107  */
108 static struct module_list embedded_module_list;
109
110 struct loadupdate {
111         int (*updater)(void);
112         AST_LIST_ENTRY(loadupdate) entry;
113 };
114
115 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
116
117 AST_MUTEX_DEFINE_STATIC(reloadlock);
118
119 /* when dynamic modules are being loaded, ast_module_register() will
120    need to know what filename the module was loaded from while it
121    is being registered
122 */
123 struct ast_module *resource_being_loaded;
124
125 /* XXX: should we check for duplicate resource names here? */
126
127 void ast_module_register(const struct ast_module_info *info)
128 {
129         struct ast_module *mod;
130
131         if (embedding) {
132                 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
133                         return;
134                 strcpy(mod->resource, info->name);
135         } else {
136                 mod = resource_being_loaded;
137         }
138
139         mod->info = info;
140         AST_LIST_HEAD_INIT(&mod->users);
141
142         /* during startup, before the loader has been initialized,
143            there are no threads, so there is no need to take the lock
144            on this list to manipulate it. it is also possible that it
145            might be unsafe to use the list lock at that point... so
146            let's avoid it altogether
147         */
148         if (embedding) {
149                 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
150         } else {
151                 AST_LIST_LOCK(&module_list);
152                 /* it is paramount that the new entry be placed at the tail of
153                    the list, otherwise the code that uses dlopen() to load
154                    dynamic modules won't be able to find out if the module it
155                    just opened was registered or failed to load
156                 */
157                 AST_LIST_INSERT_TAIL(&module_list, mod, entry);
158                 AST_LIST_UNLOCK(&module_list);
159         }
160
161         /* give the module a copy of its own handle, for later use in registrations and the like */
162         *((struct ast_module **) &(info->self)) = mod;
163 }
164
165 void ast_module_unregister(const struct ast_module_info *info)
166 {
167         struct ast_module *mod = NULL;
168
169         /* it is assumed that the users list in the module structure
170            will already be empty, or we cannot have gotten to this
171            point
172         */
173         AST_LIST_LOCK(&module_list);
174         AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
175                 if (mod->info == info) {
176                         AST_LIST_REMOVE_CURRENT(entry);
177                         break;
178                 }
179         }
180         AST_LIST_TRAVERSE_SAFE_END;
181         AST_LIST_UNLOCK(&module_list);
182
183         if (mod) {
184                 AST_LIST_HEAD_DESTROY(&mod->users);
185                 ast_free(mod);
186         }
187 }
188
189 struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
190                                               struct ast_channel *chan)
191 {
192         struct ast_module_user *u = ast_calloc(1, sizeof(*u));
193
194         if (!u)
195                 return NULL;
196
197         u->chan = chan;
198
199         AST_LIST_LOCK(&mod->users);
200         AST_LIST_INSERT_HEAD(&mod->users, u, entry);
201         AST_LIST_UNLOCK(&mod->users);
202
203         ast_atomic_fetchadd_int(&mod->usecount, +1);
204
205         ast_update_use_count();
206
207         return u;
208 }
209
210 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
211 {
212         AST_LIST_LOCK(&mod->users);
213         AST_LIST_REMOVE(&mod->users, u, entry);
214         AST_LIST_UNLOCK(&mod->users);
215         ast_atomic_fetchadd_int(&mod->usecount, -1);
216         ast_free(u);
217
218         ast_update_use_count();
219 }
220
221 void __ast_module_user_hangup_all(struct ast_module *mod)
222 {
223         struct ast_module_user *u;
224
225         AST_LIST_LOCK(&mod->users);
226         while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
227                 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
228                 ast_atomic_fetchadd_int(&mod->usecount, -1);
229                 ast_free(u);
230         }
231         AST_LIST_UNLOCK(&mod->users);
232
233         ast_update_use_count();
234 }
235
236 /*! \note
237  * In addition to modules, the reload command handles some extra keywords
238  * which are listed here together with the corresponding handlers.
239  * This table is also used by the command completion code.
240  */
241 static struct reload_classes {
242         const char *name;
243         int (*reload_fn)(void);
244 } reload_classes[] = {  /* list in alpha order, longest match first for cli completion */
245         { "cdr",        ast_cdr_engine_reload },
246         { "dnsmgr",     dnsmgr_reload },
247         { "extconfig",  read_config_maps },
248         { "enum",       ast_enum_reload },
249         { "manager",    reload_manager },
250         { "rtp",        ast_rtp_reload },
251         { "http",       ast_http_reload },
252         { "logger",     logger_reload },
253         { "features",   ast_features_reload },
254         { "dsp",        ast_dsp_reload},
255         { "udptl",      ast_udptl_reload },
256         { NULL,         NULL }
257 };
258
259 static int printdigest(const unsigned char *d)
260 {
261         int x, pos;
262         char buf[256]; /* large enough so we don't have to worry */
263
264         for (pos = 0, x = 0; x < 16; x++)
265                 pos += sprintf(buf + pos, " %02x", *d++);
266
267         ast_debug(1, "Unexpected signature:%s\n", buf);
268
269         return 0;
270 }
271
272 static int key_matches(const unsigned char *key1, const unsigned char *key2)
273 {
274         int x;
275
276         for (x = 0; x < 16; x++) {
277                 if (key1[x] != key2[x])
278                         return 0;
279         }
280
281         return 1;
282 }
283
284 static int verify_key(const unsigned char *key)
285 {
286         struct MD5Context c;
287         unsigned char digest[16];
288
289         MD5Init(&c);
290         MD5Update(&c, key, strlen((char *)key));
291         MD5Final(digest, &c);
292
293         if (key_matches(expected_key, digest))
294                 return 0;
295
296         printdigest(digest);
297
298         return -1;
299 }
300
301 static int resource_name_match(const char *name1_in, const char *name2_in)
302 {
303         char *name1 = (char *) name1_in;
304         char *name2 = (char *) name2_in;
305
306         /* trim off any .so extensions */
307         if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
308                 name1 = ast_strdupa(name1);
309                 name1[strlen(name1) - 3] = '\0';
310         }
311         if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
312                 name2 = ast_strdupa(name2);
313                 name2[strlen(name2) - 3] = '\0';
314         }
315
316         return strcasecmp(name1, name2);
317 }
318
319 static struct ast_module *find_resource(const char *resource, int do_lock)
320 {
321         struct ast_module *cur;
322
323         if (do_lock)
324                 AST_LIST_LOCK(&module_list);
325
326         AST_LIST_TRAVERSE(&module_list, cur, entry) {
327                 if (!resource_name_match(resource, cur->resource))
328                         break;
329         }
330
331         if (do_lock)
332                 AST_LIST_UNLOCK(&module_list);
333
334         return cur;
335 }
336
337 #ifdef LOADABLE_MODULES
338 static void unload_dynamic_module(struct ast_module *mod)
339 {
340         void *lib = mod->lib;
341
342         /* WARNING: the structure pointed to by mod is going to
343            disappear when this operation succeeds, so we can't
344            dereference it */
345
346         if (lib)
347                 while (!dlclose(lib));
348 }
349
350 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
351 {
352         char fn[PATH_MAX] = "";
353         void *lib = NULL;
354         struct ast_module *mod;
355         unsigned int wants_global;
356         int space;      /* room needed for the descriptor */
357         int missing_so = 0;
358
359         space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
360         if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
361                 missing_so = 1;
362                 space += 3;     /* room for the extra ".so" */
363         }
364
365         snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
366
367         /* make a first load of the module in 'quiet' mode... don't try to resolve
368            any symbols, and don't export any symbols. this will allow us to peek into
369            the module's info block (if available) to see what flags it has set */
370
371         resource_being_loaded = ast_calloc(1, space);
372         if (!resource_being_loaded)
373                 return NULL;
374         strcpy(resource_being_loaded->resource, resource_in);
375         if (missing_so)
376                 strcat(resource_being_loaded->resource, ".so");
377
378         if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
379                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
380                 ast_free(resource_being_loaded);
381                 return NULL;
382         }
383
384         /* the dlopen() succeeded, let's find out if the module
385            registered itself */
386         /* note that this will only work properly as long as
387            ast_module_register() (which is called by the module's
388            constructor) places the new module at the tail of the
389            module_list
390         */
391         if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
392                 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
393                 /* no, it did not, so close it and return */
394                 while (!dlclose(lib));
395                 /* note that the module's destructor will call ast_module_unregister(),
396                    which will free the structure we allocated in resource_being_loaded */
397                 return NULL;
398         }
399
400         wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
401
402         /* if we are being asked only to load modules that provide global symbols,
403            and this one does not, then close it and return */
404         if (global_symbols_only && !wants_global) {
405                 while (!dlclose(lib));
406                 return NULL;
407         }
408
409         /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
410            on the already-opened library to what we want... if not, we have to
411            close it and start over
412         */
413 #if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
414         if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
415                 ast_log(LOG_WARNING, "Unable to promote flags on module '%s': %s\n", resource_in, dlerror());
416                 while (!dlclose(lib));
417                 ast_free(resource_being_loaded);
418                 return NULL;
419         }
420 #else
421         while (!dlclose(lib));
422         resource_being_loaded = NULL;
423
424         /* start the load process again */
425         resource_being_loaded = ast_calloc(1, space);
426         if (!resource_being_loaded)
427                 return NULL;
428         strcpy(resource_being_loaded->resource, resource_in);
429         if (missing_so)
430                 strcat(resource_being_loaded->resource, ".so");
431
432         if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
433                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
434                 ast_free(resource_being_loaded);
435                 return NULL;
436         }
437
438         /* since the module was successfully opened, and it registered itself
439            the previous time we did that, we're going to assume it worked this
440            time too :) */
441 #endif
442
443         AST_LIST_LAST(&module_list)->lib = lib;
444         resource_being_loaded = NULL;
445
446         return AST_LIST_LAST(&module_list);
447 }
448 #endif
449
450 void ast_module_shutdown(void)
451 {
452         struct ast_module *mod;
453         AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
454
455         /* We have to call the unload() callbacks in reverse order that the modules
456          * exist in the module list so it is the reverse order of how they were
457          * loaded. */
458
459         AST_LIST_LOCK(&module_list);
460         while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
461                 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
462         AST_LIST_UNLOCK(&module_list);
463
464         while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
465                 if (mod->info->unload)
466                         mod->info->unload();
467                 /* Since this should only be called when shutting down "gracefully",
468                  * all channels should be down before we get to this point, meaning
469                  * there will be no module users left. */
470                 AST_LIST_HEAD_DESTROY(&mod->users);
471                 free(mod);
472         }
473 }
474
475 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
476 {
477         struct ast_module *mod;
478         int res = -1;
479         int error = 0;
480
481         AST_LIST_LOCK(&module_list);
482
483         if (!(mod = find_resource(resource_name, 0))) {
484                 AST_LIST_UNLOCK(&module_list);
485                 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
486                 return 0;
487         }
488
489         if (!(mod->flags.running || mod->flags.declined))
490                 error = 1;
491
492         if (!error && (mod->usecount > 0)) {
493                 if (force)
494                         ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
495                                 resource_name, mod->usecount);
496                 else {
497                         ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
498                                 mod->usecount);
499                         error = 1;
500                 }
501         }
502
503         if (!error) {
504                 __ast_module_user_hangup_all(mod);
505                 res = mod->info->unload();
506
507                 if (res) {
508                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
509                         if (force <= AST_FORCE_FIRM)
510                                 error = 1;
511                         else
512                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
513                 }
514         }
515
516         if (!error)
517                 mod->flags.running = mod->flags.declined = 0;
518
519         AST_LIST_UNLOCK(&module_list);
520
521         if (!error && !mod->lib && mod->info && mod->info->restore_globals)
522                 mod->info->restore_globals();
523
524 #ifdef LOADABLE_MODULES
525         if (!error)
526                 unload_dynamic_module(mod);
527 #endif
528
529         if (!error)
530                 ast_update_use_count();
531
532         return res;
533 }
534
535 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
536 {
537         struct ast_module *cur;
538         int i, which=0, l = strlen(word);
539         char *ret = NULL;
540
541         if (pos != rpos)
542                 return NULL;
543
544         AST_LIST_LOCK(&module_list);
545         AST_LIST_TRAVERSE(&module_list, cur, entry) {
546                 if (!strncasecmp(word, cur->resource, l) &&
547                     (cur->info->reload || !needsreload) &&
548                     ++which > state) {
549                         ret = ast_strdup(cur->resource);
550                         break;
551                 }
552         }
553         AST_LIST_UNLOCK(&module_list);
554
555         if (!ret) {
556                 for (i=0; !ret && reload_classes[i].name; i++) {
557                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
558                                 ret = ast_strdup(reload_classes[i].name);
559                 }
560         }
561
562         return ret;
563 }
564
565 int ast_module_reload(const char *name)
566 {
567         struct ast_module *cur;
568         int res = 0; /* return value. 0 = not found, others, see below */
569         int i;
570
571         if (ast_mutex_trylock(&reloadlock)) {
572                 ast_verbose("The previous reload command didn't finish yet\n");
573                 return -1;      /* reload already in progress */
574         }
575         ast_lastreloadtime = ast_tvnow();
576
577         /* Call "predefined" reload here first */
578         for (i = 0; reload_classes[i].name; i++) {
579                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
580                         reload_classes[i].reload_fn();  /* XXX should check error ? */
581                         res = 2;        /* found and reloaded */
582                 }
583         }
584
585         if (name && res) {
586                 ast_mutex_unlock(&reloadlock);
587                 return res;
588         }
589
590         AST_LIST_LOCK(&module_list);
591         AST_LIST_TRAVERSE(&module_list, cur, entry) {
592                 const struct ast_module_info *info = cur->info;
593
594                 if (name && resource_name_match(name, cur->resource))
595                         continue;
596
597                 if (!cur->flags.running || cur->flags.declined) {
598                         if (!name)
599                                 continue;
600                         ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
601                                 "Before reloading the module, you must run \"module load %s\" "
602                                 "and fix whatever is preventing the module from being initialized.\n",
603                                 name, name);
604                         res = 2; /* Don't report that the module was not found */
605                         break;
606                 }
607
608                 if (!info->reload) {    /* cannot be reloaded */
609                         if (res < 1)    /* store result if possible */
610                                 res = 1;        /* 1 = no reload() method */
611                         continue;
612                 }
613
614                 res = 2;
615                 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
616                 info->reload();
617         }
618         AST_LIST_UNLOCK(&module_list);
619
620         ast_mutex_unlock(&reloadlock);
621
622         return res;
623 }
624
625 static unsigned int inspect_module(const struct ast_module *mod)
626 {
627         if (!mod->info->description) {
628                 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
629                 return 1;
630         }
631
632         if (!mod->info->key) {
633                 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
634                 return 1;
635         }
636
637         if (verify_key((unsigned char *) mod->info->key)) {
638                 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
639                 return 1;
640         }
641
642         if (!ast_strlen_zero(mod->info->buildopt_sum) &&
643             strcmp(buildopt_sum, mod->info->buildopt_sum)) {
644                 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
645                 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
646                 return 1;
647         }
648
649         return 0;
650 }
651
652 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
653 {
654         struct ast_module *mod;
655         enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
656         char tmp[256];
657
658         if ((mod = find_resource(resource_name, 0))) {
659                 if (mod->flags.running) {
660                         ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
661                         return AST_MODULE_LOAD_DECLINE;
662                 }
663                 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
664                         return AST_MODULE_LOAD_SKIP;
665         } else {
666 #ifdef LOADABLE_MODULES
667                 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
668                         /* don't generate a warning message during load_modules() */
669                         if (!global_symbols_only) {
670                                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
671                                 return AST_MODULE_LOAD_DECLINE;
672                         } else {
673                                 return AST_MODULE_LOAD_SKIP;
674                         }
675                 }
676 #else
677                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
678                 return AST_MODULE_LOAD_DECLINE;
679 #endif
680         }
681
682         if (inspect_module(mod)) {
683                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
684 #ifdef LOADABLE_MODULES
685                 unload_dynamic_module(mod);
686 #endif
687                 return AST_MODULE_LOAD_DECLINE;
688         }
689
690         if (!mod->lib && mod->info->backup_globals()) {
691                 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
692                 return AST_MODULE_LOAD_DECLINE;
693         }
694
695         mod->flags.declined = 0;
696
697         if (mod->info->load)
698                 res = mod->info->load();
699
700         switch (res) {
701         case AST_MODULE_LOAD_SUCCESS:
702                 if (!ast_fully_booted) {
703                         ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
704                         if (ast_opt_console && !option_verbose)
705                                 ast_verbose( ".");
706                 } else {
707                         ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
708                 }
709
710                 mod->flags.running = 1;
711
712                 ast_update_use_count();
713                 break;
714         case AST_MODULE_LOAD_DECLINE:
715                 mod->flags.declined = 1;
716                 break;
717         case AST_MODULE_LOAD_FAILURE:
718                 break;
719         case AST_MODULE_LOAD_SKIP:
720                 /* modules should never return this value */
721                 break;
722         }
723
724         return res;
725 }
726
727 int ast_load_resource(const char *resource_name)
728 {
729         AST_LIST_LOCK(&module_list);
730         load_resource(resource_name, 0);
731         AST_LIST_UNLOCK(&module_list);
732
733         return 0;
734 }
735
736 struct load_order_entry {
737         char *resource;
738         AST_LIST_ENTRY(load_order_entry) entry;
739 };
740
741 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
742
743 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
744 {
745         struct load_order_entry *order;
746
747         AST_LIST_TRAVERSE(load_order, order, entry) {
748                 if (!resource_name_match(order->resource, resource))
749                         return NULL;
750         }
751
752         if (!(order = ast_calloc(1, sizeof(*order))))
753                 return NULL;
754
755         order->resource = ast_strdup(resource);
756         AST_LIST_INSERT_TAIL(load_order, order, entry);
757
758         return order;
759 }
760 int load_modules(unsigned int preload_only)
761 {
762         struct ast_config *cfg;
763         struct ast_module *mod;
764         struct load_order_entry *order;
765         struct ast_variable *v;
766         unsigned int load_count;
767         struct load_order load_order;
768         int res = 0;
769         struct ast_flags config_flags = { 0 };
770         int modulecount = 0;
771 #ifdef LOADABLE_MODULES
772         struct dirent *dirent;
773         DIR *dir;
774 #endif
775
776         /* all embedded modules have registered themselves by now */
777         embedding = 0;
778
779         ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
780
781         AST_LIST_HEAD_INIT_NOLOCK(&load_order);
782
783         AST_LIST_LOCK(&module_list);
784
785         if (embedded_module_list.first) {
786                 module_list.first = embedded_module_list.first;
787                 module_list.last = embedded_module_list.last;
788                 embedded_module_list.first = NULL;
789         }
790
791         if (!(cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags))) {
792                 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
793                 goto done;
794         }
795
796         /* first, find all the modules we have been explicitly requested to load */
797         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
798                 if (!strcasecmp(v->name, preload_only ? "preload" : "load"))
799                         add_to_load_order(v->value, &load_order);
800         }
801
802         /* check if 'autoload' is on */
803         if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
804                 /* if so, first add all the embedded modules that are not already running to the load order */
805                 AST_LIST_TRAVERSE(&module_list, mod, entry) {
806                         /* if it's not embedded, skip it */
807                         if (mod->lib)
808                                 continue;
809
810                         if (mod->flags.running)
811                                 continue;
812
813                         order = add_to_load_order(mod->resource, &load_order);
814                 }
815
816 #ifdef LOADABLE_MODULES
817                 /* if we are allowed to load dynamic modules, scan the directory for
818                    for all available modules and add them as well */
819                 if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
820                         while ((dirent = readdir(dir))) {
821                                 int ld = strlen(dirent->d_name);
822
823                                 /* Must end in .so to load it.  */
824
825                                 if (ld < 4)
826                                         continue;
827
828                                 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
829                                         continue;
830
831                                 /* if there is already a module by this name in the module_list,
832                                    skip this file */
833                                 if (find_resource(dirent->d_name, 0))
834                                         continue;
835
836                                 add_to_load_order(dirent->d_name, &load_order);
837                         }
838
839                         closedir(dir);
840                 } else {
841                         if (!ast_opt_quiet)
842                                 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
843                                         ast_config_AST_MODULE_DIR);
844                 }
845 #endif
846         }
847
848         /* now scan the config for any modules we are prohibited from loading and
849            remove them from the load order */
850         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
851                 if (strcasecmp(v->name, "noload"))
852                         continue;
853
854                 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
855                         if (!resource_name_match(order->resource, v->value)) {
856                                 AST_LIST_REMOVE_CURRENT(entry);
857                                 ast_free(order->resource);
858                                 ast_free(order);
859                         }
860                 }
861                 AST_LIST_TRAVERSE_SAFE_END;
862         }
863
864         /* we are done with the config now, all the information we need is in the
865            load_order list */
866         ast_config_destroy(cfg);
867
868         load_count = 0;
869         AST_LIST_TRAVERSE(&load_order, order, entry)
870                 load_count++;
871
872         if (load_count)
873                 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
874
875         /* first, load only modules that provide global symbols */
876         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
877                 switch (load_resource(order->resource, 1)) {
878                 case AST_MODULE_LOAD_SUCCESS:
879                         modulecount++;
880                 case AST_MODULE_LOAD_DECLINE:
881                         AST_LIST_REMOVE_CURRENT(entry);
882                         ast_free(order->resource);
883                         ast_free(order);
884                         break;
885                 case AST_MODULE_LOAD_FAILURE:
886                         res = -1;
887                         goto done;
888                 case AST_MODULE_LOAD_SKIP:
889                         /* try again later */
890                         break;
891                 }
892         }
893         AST_LIST_TRAVERSE_SAFE_END;
894
895         /* now load everything else */
896         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
897                 switch (load_resource(order->resource, 0)) {
898                 case AST_MODULE_LOAD_SUCCESS:
899                         modulecount++;
900                 case AST_MODULE_LOAD_DECLINE:
901                         AST_LIST_REMOVE_CURRENT(entry);
902                         ast_free(order->resource);
903                         ast_free(order);
904                         break;
905                 case AST_MODULE_LOAD_FAILURE:
906                         res = -1;
907                         goto done;
908                 case AST_MODULE_LOAD_SKIP:
909                         /* should not happen */
910                         break;
911                 }
912         }
913         AST_LIST_TRAVERSE_SAFE_END;
914
915 done:
916         while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
917                 ast_free(order->resource);
918                 ast_free(order);
919         }
920
921         AST_LIST_UNLOCK(&module_list);
922         
923         /* Tell manager clients that are aggressive at logging in that we're done
924            loading modules. If there's a DNS problem in chan_sip, we might not
925            even reach this */
926         manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
927         
928         return res;
929 }
930
931 void ast_update_use_count(void)
932 {
933         /* Notify any module monitors that the use count for a
934            resource has changed */
935         struct loadupdate *m;
936
937         AST_LIST_LOCK(&updaters);
938         AST_LIST_TRAVERSE(&updaters, m, entry)
939                 m->updater();
940         AST_LIST_UNLOCK(&updaters);
941 }
942
943 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
944                            const char *like)
945 {
946         struct ast_module *cur;
947         int unlock = -1;
948         int total_mod_loaded = 0;
949
950         if (AST_LIST_TRYLOCK(&module_list))
951                 unlock = 0;
952  
953         AST_LIST_TRAVERSE(&module_list, cur, entry) {
954                 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
955         }
956
957         if (unlock)
958                 AST_LIST_UNLOCK(&module_list);
959
960         return total_mod_loaded;
961 }
962
963 /*! \brief Check if module exists */
964 int ast_module_check(const char *name)
965 {
966         struct ast_module *cur;
967
968         if (ast_strlen_zero(name))
969                 return 0;       /* FALSE */
970
971         cur = find_resource(name, 1);
972
973         return (cur != NULL);
974 }
975
976
977 int ast_loader_register(int (*v)(void))
978 {
979         struct loadupdate *tmp;
980
981         if (!(tmp = ast_malloc(sizeof(*tmp))))
982                 return -1;
983
984         tmp->updater = v;
985         AST_LIST_LOCK(&updaters);
986         AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
987         AST_LIST_UNLOCK(&updaters);
988
989         return 0;
990 }
991
992 int ast_loader_unregister(int (*v)(void))
993 {
994         struct loadupdate *cur;
995
996         AST_LIST_LOCK(&updaters);
997         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
998                 if (cur->updater == v)  {
999                         AST_LIST_REMOVE_CURRENT(entry);
1000                         break;
1001                 }
1002         }
1003         AST_LIST_TRAVERSE_SAFE_END;
1004         AST_LIST_UNLOCK(&updaters);
1005
1006         return cur ? 0 : -1;
1007 }
1008
1009 struct ast_module *ast_module_ref(struct ast_module *mod)
1010 {
1011         ast_atomic_fetchadd_int(&mod->usecount, +1);
1012         ast_update_use_count();
1013
1014         return mod;
1015 }
1016
1017 void ast_module_unref(struct ast_module *mod)
1018 {
1019         ast_atomic_fetchadd_int(&mod->usecount, -1);
1020         ast_update_use_count();
1021 }