370e41fa4033c9bdcbcac4eda2412acecfe8143f
[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
51 #ifdef DLFCNCOMPAT
52 #include "asterisk/dlfcn-compat.h"
53 #else
54 #include <dlfcn.h>
55 #endif
56
57 #include "asterisk/md5.h"
58 #include "asterisk/utils.h"
59
60 #ifndef RTLD_NOW
61 #define RTLD_NOW 0
62 #endif
63
64 #ifndef RTLD_LOCAL
65 #define RTLD_LOCAL 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 char buildopt_sum[33] = 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         { "logger",     logger_reload },
251         { "features",   ast_features_reload },
252         { NULL,         NULL }
253 };
254
255 static int printdigest(const unsigned char *d)
256 {
257         int x, pos;
258         char buf[256]; /* large enough so we don't have to worry */
259
260         for (pos = 0, x = 0; x < 16; x++)
261                 pos += sprintf(buf + pos, " %02x", *d++);
262
263         ast_debug(1, "Unexpected signature:%s\n", buf);
264
265         return 0;
266 }
267
268 static int key_matches(const unsigned char *key1, const unsigned char *key2)
269 {
270         int x;
271
272         for (x = 0; x < 16; x++) {
273                 if (key1[x] != key2[x])
274                         return 0;
275         }
276
277         return 1;
278 }
279
280 static int verify_key(const unsigned char *key)
281 {
282         struct MD5Context c;
283         unsigned char digest[16];
284
285         MD5Init(&c);
286         MD5Update(&c, key, strlen((char *)key));
287         MD5Final(digest, &c);
288
289         if (key_matches(expected_key, digest))
290                 return 0;
291
292         printdigest(digest);
293
294         return -1;
295 }
296
297 static int resource_name_match(const char *name1_in, const char *name2_in)
298 {
299         char *name1 = (char *) name1_in;
300         char *name2 = (char *) name2_in;
301
302         /* trim off any .so extensions */
303         if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
304                 name1 = ast_strdupa(name1);
305                 name1[strlen(name1) - 3] = '\0';
306         }
307         if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
308                 name2 = ast_strdupa(name2);
309                 name2[strlen(name2) - 3] = '\0';
310         }
311
312         return strcasecmp(name1, name2);
313 }
314
315 static struct ast_module *find_resource(const char *resource, int do_lock)
316 {
317         struct ast_module *cur;
318
319         if (do_lock)
320                 AST_LIST_LOCK(&module_list);
321
322         AST_LIST_TRAVERSE(&module_list, cur, entry) {
323                 if (!resource_name_match(resource, cur->resource))
324                         break;
325         }
326
327         if (do_lock)
328                 AST_LIST_UNLOCK(&module_list);
329
330         return cur;
331 }
332
333 #ifdef LOADABLE_MODULES
334 static void unload_dynamic_module(struct ast_module *mod)
335 {
336         void *lib = mod->lib;
337
338         /* WARNING: the structure pointed to by mod is going to
339            disappear when this operation succeeds, so we can't
340            dereference it */
341
342         if (lib)
343                 while (!dlclose(lib));
344 }
345
346 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
347 {
348         char fn[PATH_MAX] = "";
349         void *lib = NULL;
350         struct ast_module *mod;
351         unsigned int wants_global;
352         int space;      /* room needed for the descriptor */
353         int missing_so = 0;
354
355         space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
356         if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
357                 missing_so = 1;
358                 space += 3;     /* room for the extra ".so" */
359         }
360
361         snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
362
363         /* make a first load of the module in 'quiet' mode... don't try to resolve
364            any symbols, and don't export any symbols. this will allow us to peek into
365            the module's info block (if available) to see what flags it has set */
366
367         resource_being_loaded = ast_calloc(1, space);
368         if (!resource_being_loaded)
369                 return NULL;
370         strcpy(resource_being_loaded->resource, resource_in);
371         if (missing_so)
372                 strcat(resource_being_loaded->resource, ".so");
373
374         if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
375                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
376                 ast_free(resource_being_loaded);
377                 return NULL;
378         }
379
380         /* the dlopen() succeeded, let's find out if the module
381            registered itself */
382         /* note that this will only work properly as long as
383            ast_module_register() (which is called by the module's
384            constructor) places the new module at the tail of the
385            module_list
386         */
387         if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
388                 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
389                 /* no, it did not, so close it and return */
390                 while (!dlclose(lib));
391                 /* note that the module's destructor will call ast_module_unregister(),
392                    which will free the structure we allocated in resource_being_loaded */
393                 return NULL;
394         }
395
396         wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
397
398         /* if we are being asked only to load modules that provide global symbols,
399            and this one does not, then close it and return */
400         if (global_symbols_only && !wants_global) {
401                 while (!dlclose(lib));
402                 return NULL;
403         }
404
405         /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
406            on the already-opened library to what we want... if not, we have to
407            close it and start over
408         */
409 #if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
410         if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
411                 ast_log(LOG_WARNING, "Unable to promote flags on module '%s': %s\n", resource_in, dlerror());
412                 while (!dlclose(lib));
413                 ast_free(resource_being_loaded);
414                 return NULL;
415         }
416 #else
417         while (!dlclose(lib));
418         resource_being_loaded = NULL;
419
420         /* start the load process again */
421         resource_being_loaded = ast_calloc(1, space);
422         if (!resource_being_loaded)
423                 return NULL;
424         strcpy(resource_being_loaded->resource, resource_in);
425         if (missing_so)
426                 strcat(resource_being_loaded->resource, ".so");
427
428         if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
429                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
430                 ast_free(resource_being_loaded);
431                 return NULL;
432         }
433
434         /* since the module was successfully opened, and it registered itself
435            the previous time we did that, we're going to assume it worked this
436            time too :) */
437 #endif
438
439         AST_LIST_LAST(&module_list)->lib = lib;
440         resource_being_loaded = NULL;
441
442         return AST_LIST_LAST(&module_list);
443 }
444 #endif
445
446 void ast_module_shutdown(void)
447 {
448         struct ast_module *mod;
449         AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
450
451         /* We have to call the unload() callbacks in reverse order that the modules
452          * exist in the module list so it is the reverse order of how they were
453          * loaded. */
454
455         AST_LIST_LOCK(&module_list);
456         while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
457                 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
458         AST_LIST_UNLOCK(&module_list);
459
460         while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
461                 if (mod->info->unload)
462                         mod->info->unload();
463                 /* Since this should only be called when shutting down "gracefully",
464                  * all channels should be down before we get to this point, meaning
465                  * there will be no module users left. */
466                 AST_LIST_HEAD_DESTROY(&mod->users);
467                 free(mod);
468         }
469 }
470
471 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
472 {
473         struct ast_module *mod;
474         int res = -1;
475         int error = 0;
476
477         AST_LIST_LOCK(&module_list);
478
479         if (!(mod = find_resource(resource_name, 0))) {
480                 AST_LIST_UNLOCK(&module_list);
481                 return 0;
482         }
483
484         if (!(mod->flags.running || mod->flags.declined))
485                 error = 1;
486
487         if (!error && (mod->usecount > 0)) {
488                 if (force)
489                         ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
490                                 resource_name, mod->usecount);
491                 else {
492                         ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
493                                 mod->usecount);
494                         error = 1;
495                 }
496         }
497
498         if (!error) {
499                 __ast_module_user_hangup_all(mod);
500                 res = mod->info->unload();
501
502                 if (res) {
503                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
504                         if (force <= AST_FORCE_FIRM)
505                                 error = 1;
506                         else
507                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
508                 }
509         }
510
511         if (!error)
512                 mod->flags.running = mod->flags.declined = 0;
513
514         AST_LIST_UNLOCK(&module_list);
515
516         if (!error && !mod->lib && mod->info && mod->info->restore_globals)
517                 mod->info->restore_globals();
518
519 #ifdef LOADABLE_MODULES
520         if (!error)
521                 unload_dynamic_module(mod);
522 #endif
523
524         if (!error)
525                 ast_update_use_count();
526
527         return res;
528 }
529
530 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
531 {
532         struct ast_module *cur;
533         int i, which=0, l = strlen(word);
534         char *ret = NULL;
535
536         if (pos != rpos)
537                 return NULL;
538
539         AST_LIST_LOCK(&module_list);
540         AST_LIST_TRAVERSE(&module_list, cur, entry) {
541                 if (!strncasecmp(word, cur->resource, l) &&
542                     (cur->info->reload || !needsreload) &&
543                     ++which > state) {
544                         ret = ast_strdup(cur->resource);
545                         break;
546                 }
547         }
548         AST_LIST_UNLOCK(&module_list);
549
550         if (!ret) {
551                 for (i=0; !ret && reload_classes[i].name; i++) {
552                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
553                                 ret = ast_strdup(reload_classes[i].name);
554                 }
555         }
556
557         return ret;
558 }
559
560 int ast_module_reload(const char *name)
561 {
562         struct ast_module *cur;
563         int res = 0; /* return value. 0 = not found, others, see below */
564         int i;
565
566         if (ast_mutex_trylock(&reloadlock)) {
567                 ast_verbose("The previous reload command didn't finish yet\n");
568                 return -1;      /* reload already in progress */
569         }
570         ast_lastreloadtime = ast_tvnow();
571
572         /* Call "predefined" reload here first */
573         for (i = 0; reload_classes[i].name; i++) {
574                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
575                         reload_classes[i].reload_fn();  /* XXX should check error ? */
576                         res = 2;        /* found and reloaded */
577                 }
578         }
579
580         if (name && res) {
581                 ast_mutex_unlock(&reloadlock);
582                 return res;
583         }
584
585         AST_LIST_LOCK(&module_list);
586         AST_LIST_TRAVERSE(&module_list, cur, entry) {
587                 const struct ast_module_info *info = cur->info;
588
589                 if (name && resource_name_match(name, cur->resource))
590                         continue;
591
592                 if (!cur->flags.running || cur->flags.declined) {
593                         if (!name)
594                                 continue;
595                         ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
596                                 "Before reloading the module, you must run \"module load %s\" "
597                                 "and fix whatever is preventing the module from being initialized.\n",
598                                 name, name);
599                         res = 2; /* Don't report that the module was not found */
600                         break;
601                 }
602
603                 if (!info->reload) {    /* cannot be reloaded */
604                         if (res < 1)    /* store result if possible */
605                                 res = 1;        /* 1 = no reload() method */
606                         continue;
607                 }
608
609                 res = 2;
610                 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
611                 info->reload();
612         }
613         AST_LIST_UNLOCK(&module_list);
614
615         ast_mutex_unlock(&reloadlock);
616
617         return res;
618 }
619
620 static unsigned int inspect_module(const struct ast_module *mod)
621 {
622         if (!mod->info->description) {
623                 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
624                 return 1;
625         }
626
627         if (!mod->info->key) {
628                 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
629                 return 1;
630         }
631
632         if (verify_key((unsigned char *) mod->info->key)) {
633                 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
634                 return 1;
635         }
636
637         if (!ast_strlen_zero(mod->info->buildopt_sum) &&
638             strcmp(buildopt_sum, mod->info->buildopt_sum)) {
639                 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
640                 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
641                 return 1;
642         }
643
644         return 0;
645 }
646
647 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
648 {
649         struct ast_module *mod;
650         enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
651         char tmp[256];
652
653         if ((mod = find_resource(resource_name, 0))) {
654                 if (mod->flags.running) {
655                         ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
656                         return AST_MODULE_LOAD_DECLINE;
657                 }
658                 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
659                         return AST_MODULE_LOAD_SKIP;
660         } else {
661 #ifdef LOADABLE_MODULES
662                 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
663                         /* don't generate a warning message during load_modules() */
664                         if (!global_symbols_only) {
665                                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
666                                 return AST_MODULE_LOAD_DECLINE;
667                         } else {
668                                 return AST_MODULE_LOAD_SKIP;
669                         }
670                 }
671 #else
672                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
673                 return AST_MODULE_LOAD_DECLINE;
674 #endif
675         }
676
677         if (inspect_module(mod)) {
678                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
679 #ifdef LOADABLE_MODULES
680                 unload_dynamic_module(mod);
681 #endif
682                 return AST_MODULE_LOAD_DECLINE;
683         }
684
685         if (!mod->lib && mod->info->backup_globals()) {
686                 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
687                 return AST_MODULE_LOAD_DECLINE;
688         }
689
690         mod->flags.declined = 0;
691
692         if (mod->info->load)
693                 res = mod->info->load();
694
695         switch (res) {
696         case AST_MODULE_LOAD_SUCCESS:
697                 if (!ast_fully_booted) {
698                         ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
699                         if (ast_opt_console)
700                                 ast_verb(0, ".");
701                 } else {
702                         ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
703                 }
704
705                 mod->flags.running = 1;
706
707                 ast_update_use_count();
708                 break;
709         case AST_MODULE_LOAD_DECLINE:
710                 mod->flags.declined = 1;
711                 break;
712         case AST_MODULE_LOAD_FAILURE:
713                 break;
714         case AST_MODULE_LOAD_SKIP:
715                 /* modules should never return this value */
716                 break;
717         }
718
719         return res;
720 }
721
722 int ast_load_resource(const char *resource_name)
723 {
724        AST_LIST_LOCK(&module_list);
725        load_resource(resource_name, 0);
726        AST_LIST_UNLOCK(&module_list);
727
728        return 0;
729 }
730
731 struct load_order_entry {
732         char *resource;
733         AST_LIST_ENTRY(load_order_entry) entry;
734 };
735
736 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
737
738 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
739 {
740         struct load_order_entry *order;
741
742         AST_LIST_TRAVERSE(load_order, order, entry) {
743                 if (!resource_name_match(order->resource, resource))
744                         return NULL;
745         }
746
747         if (!(order = ast_calloc(1, sizeof(*order))))
748                 return NULL;
749
750         order->resource = ast_strdup(resource);
751         AST_LIST_INSERT_TAIL(load_order, order, entry);
752
753         return order;
754 }
755 int load_modules(unsigned int preload_only)
756 {
757         struct ast_config *cfg;
758         struct ast_module *mod;
759         struct load_order_entry *order;
760         struct ast_variable *v;
761         unsigned int load_count;
762         struct load_order load_order;
763         int res = 0;
764         struct ast_flags config_flags = { 0 };
765         int modulecount = 0;
766 #ifdef LOADABLE_MODULES
767         struct dirent *dirent;
768         DIR *dir;
769 #endif
770
771         /* all embedded modules have registered themselves by now */
772         embedding = 0;
773
774         ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
775
776         AST_LIST_HEAD_INIT_NOLOCK(&load_order);
777
778         AST_LIST_LOCK(&module_list);
779
780         if (embedded_module_list.first) {
781                 module_list.first = embedded_module_list.first;
782                 module_list.last = embedded_module_list.last;
783                 embedded_module_list.first = NULL;
784         }
785
786         if (!(cfg = ast_config_load(AST_MODULE_CONFIG, config_flags))) {
787                 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
788                 goto done;
789         }
790
791         /* first, find all the modules we have been explicitly requested to load */
792         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
793                 if (!strcasecmp(v->name, preload_only ? "preload" : "load"))
794                         add_to_load_order(v->value, &load_order);
795         }
796
797         /* check if 'autoload' is on */
798         if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
799                 /* if so, first add all the embedded modules that are not already running to the load order */
800                 AST_LIST_TRAVERSE(&module_list, mod, entry) {
801                         /* if it's not embedded, skip it */
802                         if (mod->lib)
803                                 continue;
804
805                         if (mod->flags.running)
806                                 continue;
807
808                         order = add_to_load_order(mod->resource, &load_order);
809                 }
810
811 #ifdef LOADABLE_MODULES
812                 /* if we are allowed to load dynamic modules, scan the directory for
813                    for all available modules and add them as well */
814                 if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
815                         while ((dirent = readdir(dir))) {
816                                 int ld = strlen(dirent->d_name);
817
818                                 /* Must end in .so to load it.  */
819
820                                 if (ld < 4)
821                                         continue;
822
823                                 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
824                                         continue;
825
826                                 /* if there is already a module by this name in the module_list,
827                                    skip this file */
828                                 if (find_resource(dirent->d_name, 0))
829                                         continue;
830
831                                 add_to_load_order(dirent->d_name, &load_order);
832                         }
833
834                         closedir(dir);
835                 } else {
836                         if (!ast_opt_quiet)
837                                 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
838                                         ast_config_AST_MODULE_DIR);
839                 }
840 #endif
841         }
842
843         /* now scan the config for any modules we are prohibited from loading and
844            remove them from the load order */
845         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
846                 if (strcasecmp(v->name, "noload"))
847                         continue;
848
849                 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
850                         if (!resource_name_match(order->resource, v->value)) {
851                                 AST_LIST_REMOVE_CURRENT(entry);
852                                 ast_free(order->resource);
853                                 ast_free(order);
854                         }
855                 }
856                 AST_LIST_TRAVERSE_SAFE_END;
857         }
858
859         /* we are done with the config now, all the information we need is in the
860            load_order list */
861         ast_config_destroy(cfg);
862
863         load_count = 0;
864         AST_LIST_TRAVERSE(&load_order, order, entry)
865                 load_count++;
866
867         if (load_count)
868                 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
869
870         /* first, load only modules that provide global symbols */
871         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
872                 switch (load_resource(order->resource, 1)) {
873                 case AST_MODULE_LOAD_SUCCESS:
874                         modulecount++;
875                 case AST_MODULE_LOAD_DECLINE:
876                         AST_LIST_REMOVE_CURRENT(entry);
877                         ast_free(order->resource);
878                         ast_free(order);
879                         break;
880                 case AST_MODULE_LOAD_FAILURE:
881                         res = -1;
882                         goto done;
883                 case AST_MODULE_LOAD_SKIP:
884                         /* try again later */
885                         break;
886                 }
887         }
888         AST_LIST_TRAVERSE_SAFE_END;
889
890         /* now load everything else */
891         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
892                 switch (load_resource(order->resource, 0)) {
893                 case AST_MODULE_LOAD_SUCCESS:
894                         modulecount++;
895                 case AST_MODULE_LOAD_DECLINE:
896                         AST_LIST_REMOVE_CURRENT(entry);
897                         ast_free(order->resource);
898                         ast_free(order);
899                         break;
900                 case AST_MODULE_LOAD_FAILURE:
901                         res = -1;
902                         goto done;
903                 case AST_MODULE_LOAD_SKIP:
904                         /* should not happen */
905                         break;
906                 }
907         }
908         AST_LIST_TRAVERSE_SAFE_END;
909
910 done:
911         while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
912                 ast_free(order->resource);
913                 ast_free(order);
914         }
915
916         AST_LIST_UNLOCK(&module_list);
917         
918         /* Tell manager clients that are aggressive at logging in that we're done
919            loading modules. If there's a DNS problem in chan_sip, we might not
920            even reach this */
921         manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
922         
923         return res;
924 }
925
926 void ast_update_use_count(void)
927 {
928         /* Notify any module monitors that the use count for a
929            resource has changed */
930         struct loadupdate *m;
931
932         AST_LIST_LOCK(&module_list);
933         AST_LIST_TRAVERSE(&updaters, m, entry)
934                 m->updater();
935         AST_LIST_UNLOCK(&module_list);
936 }
937
938 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
939                            const char *like)
940 {
941         struct ast_module *cur;
942         int unlock = -1;
943         int total_mod_loaded = 0;
944
945         if (AST_LIST_TRYLOCK(&module_list))
946                 unlock = 0;
947  
948         AST_LIST_TRAVERSE(&module_list, cur, entry) {
949                 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
950         }
951
952         if (unlock)
953                 AST_LIST_UNLOCK(&module_list);
954
955         return total_mod_loaded;
956 }
957
958 /*! \brief Check if module exists */
959 int ast_module_check(const char *name)
960 {
961         struct ast_module *cur;
962
963         if (ast_strlen_zero(name))
964                 return 0;       /* FALSE */
965
966         cur = find_resource(name, 1);
967
968         return (cur != NULL);
969 }
970
971
972 int ast_loader_register(int (*v)(void))
973 {
974         struct loadupdate *tmp;
975
976         if (!(tmp = ast_malloc(sizeof(*tmp))))
977                 return -1;
978
979         tmp->updater = v;
980         AST_LIST_LOCK(&module_list);
981         AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
982         AST_LIST_UNLOCK(&module_list);
983
984         return 0;
985 }
986
987 int ast_loader_unregister(int (*v)(void))
988 {
989         struct loadupdate *cur;
990
991         AST_LIST_LOCK(&module_list);
992         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
993                 if (cur->updater == v)  {
994                         AST_LIST_REMOVE_CURRENT(entry);
995                         break;
996                 }
997         }
998         AST_LIST_TRAVERSE_SAFE_END;
999         AST_LIST_UNLOCK(&module_list);
1000
1001         return cur ? 0 : -1;
1002 }
1003
1004 struct ast_module *ast_module_ref(struct ast_module *mod)
1005 {
1006         ast_atomic_fetchadd_int(&mod->usecount, +1);
1007         ast_update_use_count();
1008
1009         return mod;
1010 }
1011
1012 void ast_module_unref(struct ast_module *mod)
1013 {
1014         ast_atomic_fetchadd_int(&mod->usecount, -1);
1015         ast_update_use_count();
1016 }