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