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