merging the zap_and_dahdi_trunk branch up to trunk
[asterisk/asterisk.git] / main / loader.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * Kevin P. Fleming <kpfleming@digium.com>
8  * Luigi Rizzo <rizzo@icir.org>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20
21 /*! \file
22  *
23  * \brief Module Loader
24  * \author Mark Spencer <markster@digium.com>
25  * \author Kevin P. Fleming <kpfleming@digium.com>
26  * \author Luigi Rizzo <rizzo@icir.org>
27  * - See ModMngMnt
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/_private.h"
35 #include "asterisk/paths.h"     /* use ast_config_AST_MODULE_DIR */
36 #include <dirent.h>
37
38 #include "asterisk/linkedlists.h"
39 #include "asterisk/module.h"
40 #include "asterisk/config.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/term.h"
43 #include "asterisk/manager.h"
44 #include "asterisk/cdr.h"
45 #include "asterisk/enum.h"
46 #include "asterisk/rtp.h"
47 #include "asterisk/http.h"
48 #include "asterisk/lock.h"
49 #include "asterisk/features.h"
50 #include "asterisk/dsp.h"
51 #include "asterisk/udptl.h"
52
53 #include <dlfcn.h>
54
55 #include "asterisk/md5.h"
56 #include "asterisk/utils.h"
57
58 #ifndef RTLD_NOW
59 #define RTLD_NOW 0
60 #endif
61
62 #ifndef RTLD_LOCAL
63 #define RTLD_LOCAL 0
64 #endif
65
66 struct ast_module_user {
67         struct ast_channel *chan;
68         AST_LIST_ENTRY(ast_module_user) entry;
69 };
70
71 AST_LIST_HEAD(module_user_list, ast_module_user);
72
73 static unsigned char expected_key[] =
74 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
75   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
76
77 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
78
79 static unsigned int embedding = 1; /* we always start out by registering embedded modules,
80                                       since they are here before we dlopen() any
81                                    */
82
83 struct ast_module {
84         const struct ast_module_info *info;
85         void *lib;                                      /* the shared lib, or NULL if embedded */
86         int usecount;                                   /* the number of 'users' currently in this module */
87         struct module_user_list users;                  /* the list of users in the module */
88         struct {
89                 unsigned int running:1;
90                 unsigned int declined:1;
91         } flags;
92         AST_LIST_ENTRY(ast_module) entry;
93         char resource[0];
94 };
95
96 static AST_LIST_HEAD_STATIC(module_list, ast_module);
97
98 /*
99  * module_list is cleared by its constructor possibly after
100  * we start accumulating embedded modules, so we need to
101  * use another list (without the lock) to accumulate them.
102  * Then we update the main list when embedding is done.
103  */
104 static struct module_list embedded_module_list;
105
106 struct loadupdate {
107         int (*updater)(void);
108         AST_LIST_ENTRY(loadupdate) entry;
109 };
110
111 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
112
113 AST_MUTEX_DEFINE_STATIC(reloadlock);
114
115 /* when dynamic modules are being loaded, ast_module_register() will
116    need to know what filename the module was loaded from while it
117    is being registered
118 */
119 struct ast_module *resource_being_loaded;
120
121 /* XXX: should we check for duplicate resource names here? */
122
123 void ast_module_register(const struct ast_module_info *info)
124 {
125         struct ast_module *mod;
126
127         if (embedding) {
128                 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
129                         return;
130                 strcpy(mod->resource, info->name);
131         } else {
132                 mod = resource_being_loaded;
133         }
134
135         mod->info = info;
136         AST_LIST_HEAD_INIT(&mod->users);
137
138         /* during startup, before the loader has been initialized,
139            there are no threads, so there is no need to take the lock
140            on this list to manipulate it. it is also possible that it
141            might be unsafe to use the list lock at that point... so
142            let's avoid it altogether
143         */
144         if (embedding) {
145                 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
146         } else {
147                 AST_LIST_LOCK(&module_list);
148                 /* it is paramount that the new entry be placed at the tail of
149                    the list, otherwise the code that uses dlopen() to load
150                    dynamic modules won't be able to find out if the module it
151                    just opened was registered or failed to load
152                 */
153                 AST_LIST_INSERT_TAIL(&module_list, mod, entry);
154                 AST_LIST_UNLOCK(&module_list);
155         }
156
157         /* give the module a copy of its own handle, for later use in registrations and the like */
158         *((struct ast_module **) &(info->self)) = mod;
159 }
160
161 void ast_module_unregister(const struct ast_module_info *info)
162 {
163         struct ast_module *mod = NULL;
164
165         /* it is assumed that the users list in the module structure
166            will already be empty, or we cannot have gotten to this
167            point
168         */
169         AST_LIST_LOCK(&module_list);
170         AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
171                 if (mod->info == info) {
172                         AST_LIST_REMOVE_CURRENT(entry);
173                         break;
174                 }
175         }
176         AST_LIST_TRAVERSE_SAFE_END;
177         AST_LIST_UNLOCK(&module_list);
178
179         if (mod) {
180                 AST_LIST_HEAD_DESTROY(&mod->users);
181                 ast_free(mod);
182         }
183 }
184
185 struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
186                                               struct ast_channel *chan)
187 {
188         struct ast_module_user *u = ast_calloc(1, sizeof(*u));
189
190         if (!u)
191                 return NULL;
192
193         u->chan = chan;
194
195         AST_LIST_LOCK(&mod->users);
196         AST_LIST_INSERT_HEAD(&mod->users, u, entry);
197         AST_LIST_UNLOCK(&mod->users);
198
199         ast_atomic_fetchadd_int(&mod->usecount, +1);
200
201         ast_update_use_count();
202
203         return u;
204 }
205
206 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
207 {
208         AST_LIST_LOCK(&mod->users);
209         AST_LIST_REMOVE(&mod->users, u, entry);
210         AST_LIST_UNLOCK(&mod->users);
211         ast_atomic_fetchadd_int(&mod->usecount, -1);
212         ast_free(u);
213
214         ast_update_use_count();
215 }
216
217 void __ast_module_user_hangup_all(struct ast_module *mod)
218 {
219         struct ast_module_user *u;
220
221         AST_LIST_LOCK(&mod->users);
222         while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
223                 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
224                 ast_atomic_fetchadd_int(&mod->usecount, -1);
225                 ast_free(u);
226         }
227         AST_LIST_UNLOCK(&mod->users);
228
229         ast_update_use_count();
230 }
231
232 /*! \note
233  * In addition to modules, the reload command handles some extra keywords
234  * which are listed here together with the corresponding handlers.
235  * This table is also used by the command completion code.
236  */
237 static struct reload_classes {
238         const char *name;
239         int (*reload_fn)(void);
240 } reload_classes[] = {  /* list in alpha order, longest match first for cli completion */
241         { "cdr",        ast_cdr_engine_reload },
242         { "dnsmgr",     dnsmgr_reload },
243         { "extconfig",  read_config_maps },
244         { "enum",       ast_enum_reload },
245         { "manager",    reload_manager },
246         { "rtp",        ast_rtp_reload },
247         { "http",       ast_http_reload },
248         { "logger",     logger_reload },
249         { "features",   ast_features_reload },
250         { "dsp",        ast_dsp_reload},
251         { "udptl",      ast_udptl_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                 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
482                 return 0;
483         }
484
485         if (!(mod->flags.running || mod->flags.declined))
486                 error = 1;
487
488         if (!error && (mod->usecount > 0)) {
489                 if (force)
490                         ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
491                                 resource_name, mod->usecount);
492                 else {
493                         ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
494                                 mod->usecount);
495                         error = 1;
496                 }
497         }
498
499         if (!error) {
500                 __ast_module_user_hangup_all(mod);
501                 res = mod->info->unload();
502
503                 if (res) {
504                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
505                         if (force <= AST_FORCE_FIRM)
506                                 error = 1;
507                         else
508                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
509                 }
510         }
511
512         if (!error)
513                 mod->flags.running = mod->flags.declined = 0;
514
515         AST_LIST_UNLOCK(&module_list);
516
517         if (!error && !mod->lib && mod->info && mod->info->restore_globals)
518                 mod->info->restore_globals();
519
520 #ifdef LOADABLE_MODULES
521         if (!error)
522                 unload_dynamic_module(mod);
523 #endif
524
525         if (!error)
526                 ast_update_use_count();
527
528         return res;
529 }
530
531 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
532 {
533         struct ast_module *cur;
534         int i, which=0, l = strlen(word);
535         char *ret = NULL;
536
537         if (pos != rpos)
538                 return NULL;
539
540         AST_LIST_LOCK(&module_list);
541         AST_LIST_TRAVERSE(&module_list, cur, entry) {
542                 if (!strncasecmp(word, cur->resource, l) &&
543                     (cur->info->reload || !needsreload) &&
544                     ++which > state) {
545                         ret = ast_strdup(cur->resource);
546                         break;
547                 }
548         }
549         AST_LIST_UNLOCK(&module_list);
550
551         if (!ret) {
552                 for (i=0; !ret && reload_classes[i].name; i++) {
553                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
554                                 ret = ast_strdup(reload_classes[i].name);
555                 }
556         }
557
558         return ret;
559 }
560
561 int ast_module_reload(const char *name)
562 {
563         struct ast_module *cur;
564         int res = 0; /* return value. 0 = not found, others, see below */
565         int i;
566
567         if (ast_mutex_trylock(&reloadlock)) {
568                 ast_verbose("The previous reload command didn't finish yet\n");
569                 return -1;      /* reload already in progress */
570         }
571         ast_lastreloadtime = ast_tvnow();
572
573         /* Call "predefined" reload here first */
574         for (i = 0; reload_classes[i].name; i++) {
575                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
576                         reload_classes[i].reload_fn();  /* XXX should check error ? */
577                         res = 2;        /* found and reloaded */
578                 }
579         }
580
581         if (name && res) {
582                 ast_mutex_unlock(&reloadlock);
583                 return res;
584         }
585
586         AST_LIST_LOCK(&module_list);
587         AST_LIST_TRAVERSE(&module_list, cur, entry) {
588                 const struct ast_module_info *info = cur->info;
589
590                 if (name && resource_name_match(name, cur->resource))
591                         continue;
592
593                 if (!cur->flags.running || cur->flags.declined) {
594                         if (!name)
595                                 continue;
596                         ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
597                                 "Before reloading the module, you must run \"module load %s\" "
598                                 "and fix whatever is preventing the module from being initialized.\n",
599                                 name, name);
600                         res = 2; /* Don't report that the module was not found */
601                         break;
602                 }
603
604                 if (!info->reload) {    /* cannot be reloaded */
605                         if (res < 1)    /* store result if possible */
606                                 res = 1;        /* 1 = no reload() method */
607                         continue;
608                 }
609
610                 res = 2;
611                 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
612                 info->reload();
613         }
614         AST_LIST_UNLOCK(&module_list);
615
616         ast_mutex_unlock(&reloadlock);
617
618         return res;
619 }
620
621 static unsigned int inspect_module(const struct ast_module *mod)
622 {
623         if (!mod->info->description) {
624                 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
625                 return 1;
626         }
627
628         if (!mod->info->key) {
629                 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
630                 return 1;
631         }
632
633         if (verify_key((unsigned char *) mod->info->key)) {
634                 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
635                 return 1;
636         }
637
638         if (!ast_strlen_zero(mod->info->buildopt_sum) &&
639             strcmp(buildopt_sum, mod->info->buildopt_sum)) {
640                 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
641                 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
642                 return 1;
643         }
644
645         return 0;
646 }
647
648 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
649 {
650         struct ast_module *mod;
651         enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
652         char tmp[256];
653
654         if ((mod = find_resource(resource_name, 0))) {
655                 if (mod->flags.running) {
656                         ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
657                         return AST_MODULE_LOAD_DECLINE;
658                 }
659                 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
660                         return AST_MODULE_LOAD_SKIP;
661         } else {
662 #ifdef LOADABLE_MODULES
663                 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
664                         /* don't generate a warning message during load_modules() */
665                         if (!global_symbols_only) {
666                                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
667                                 return AST_MODULE_LOAD_DECLINE;
668                         } else {
669                                 return AST_MODULE_LOAD_SKIP;
670                         }
671                 }
672 #else
673                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
674                 return AST_MODULE_LOAD_DECLINE;
675 #endif
676         }
677
678         if (inspect_module(mod)) {
679                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
680 #ifdef LOADABLE_MODULES
681                 unload_dynamic_module(mod);
682 #endif
683                 return AST_MODULE_LOAD_DECLINE;
684         }
685
686         if (!mod->lib && mod->info->backup_globals()) {
687                 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
688                 return AST_MODULE_LOAD_DECLINE;
689         }
690
691         mod->flags.declined = 0;
692
693         if (mod->info->load)
694                 res = mod->info->load();
695
696         switch (res) {
697         case AST_MODULE_LOAD_SUCCESS:
698                 if (!ast_fully_booted) {
699                         ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
700                         if (ast_opt_console && !option_verbose)
701                                 ast_verbose( ".");
702                 } else {
703                         ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
704                 }
705
706                 mod->flags.running = 1;
707
708                 ast_update_use_count();
709                 break;
710         case AST_MODULE_LOAD_DECLINE:
711                 mod->flags.declined = 1;
712                 break;
713         case AST_MODULE_LOAD_FAILURE:
714                 break;
715         case AST_MODULE_LOAD_SKIP:
716                 /* modules should never return this value */
717                 break;
718         }
719
720         return res;
721 }
722
723 int ast_load_resource(const char *resource_name)
724 {
725         int res;
726         AST_LIST_LOCK(&module_list);
727         res = load_resource(resource_name, 0);
728         AST_LIST_UNLOCK(&module_list);
729
730         return res;
731 }
732
733 struct load_order_entry {
734         char *resource;
735         AST_LIST_ENTRY(load_order_entry) entry;
736 };
737
738 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
739
740 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
741 {
742         struct load_order_entry *order;
743
744         AST_LIST_TRAVERSE(load_order, order, entry) {
745                 if (!resource_name_match(order->resource, resource))
746                         return NULL;
747         }
748
749         if (!(order = ast_calloc(1, sizeof(*order))))
750                 return NULL;
751
752         order->resource = ast_strdup(resource);
753         AST_LIST_INSERT_TAIL(load_order, order, entry);
754
755         return order;
756 }
757
758 static int translate_module_name(const char *oldname, char *newname)
759 {
760     if (!strcasecmp(oldname, "app_zapbarge.so"))
761         ast_copy_string(newname, "app_dahdibarge.so", 18);
762     else if(!strcasecmp(oldname, "app_zapras.so"))
763         ast_copy_string(newname, "app_dahdiras.so", 16);
764     else if(!strcasecmp(oldname, "app_zapscan.so"))
765         ast_copy_string(newname, "app_dahdiscan.so", 17);
766     else if(!strcasecmp(oldname, "codec_zap.so"))
767         ast_copy_string(newname, "codec_dahdi.so", 16);
768     else
769         return -1; /* no use for newname, oldname is fine */
770
771     return 0;
772 }
773
774 int load_modules(unsigned int preload_only)
775 {
776         struct ast_config *cfg;
777         struct ast_module *mod;
778         struct load_order_entry *order;
779         struct ast_variable *v;
780         unsigned int load_count;
781         struct load_order load_order;
782         int res = 0;
783         struct ast_flags config_flags = { 0 };
784         int modulecount = 0;
785
786         int translate_status;
787         char newname[18]; /* although this would normally be 80, max length in translate_module_name is 18 */
788 #ifdef LOADABLE_MODULES
789         struct dirent *dirent;
790         DIR *dir;
791 #endif
792
793         /* all embedded modules have registered themselves by now */
794         embedding = 0;
795
796         ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
797
798         AST_LIST_HEAD_INIT_NOLOCK(&load_order);
799
800         AST_LIST_LOCK(&module_list);
801
802         if (embedded_module_list.first) {
803                 module_list.first = embedded_module_list.first;
804                 module_list.last = embedded_module_list.last;
805                 embedded_module_list.first = NULL;
806         }
807
808         if (!(cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags))) {
809                 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
810                 goto done;
811         }
812
813         /* first, find all the modules we have been explicitly requested to load */
814         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
815                 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
816                         translate_status = translate_module_name(v->value, newname);
817                                 if (!translate_status)
818                                         ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
819                         add_to_load_order(translate_status ? v->value : newname, &load_order);
820                 }
821         }
822
823         /* check if 'autoload' is on */
824         if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
825                 /* if so, first add all the embedded modules that are not already running to the load order */
826                 AST_LIST_TRAVERSE(&module_list, mod, entry) {
827                         /* if it's not embedded, skip it */
828                         if (mod->lib)
829                                 continue;
830
831                         if (mod->flags.running)
832                                 continue;
833
834                         order = add_to_load_order(mod->resource, &load_order);
835                 }
836
837 #ifdef LOADABLE_MODULES
838                 /* if we are allowed to load dynamic modules, scan the directory for
839                    for all available modules and add them as well */
840                 if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
841                         while ((dirent = readdir(dir))) {
842                                 int ld = strlen(dirent->d_name);
843
844                                 /* Must end in .so to load it.  */
845
846                                 if (ld < 4)
847                                         continue;
848
849                                 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
850                                         continue;
851
852                                 /* if there is already a module by this name in the module_list,
853                                    skip this file */
854                                 if (find_resource(dirent->d_name, 0))
855                                         continue;
856
857                                 add_to_load_order(dirent->d_name, &load_order);
858                         }
859
860                         closedir(dir);
861                 } else {
862                         if (!ast_opt_quiet)
863                                 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
864                                         ast_config_AST_MODULE_DIR);
865                 }
866 #endif
867         }
868
869         /* now scan the config for any modules we are prohibited from loading and
870            remove them from the load order */
871         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
872                 if (strcasecmp(v->name, "noload"))
873                         continue;
874
875                 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
876                         translate_status = translate_module_name(v->value, newname);
877                         if (!resource_name_match(order->resource, translate_status ? v->value : newname)) {
878                                  if (!translate_status)
879                         ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
880                                 AST_LIST_REMOVE_CURRENT(entry);
881                                 ast_free(order->resource);
882                                 ast_free(order);
883                         }
884                 }
885                 AST_LIST_TRAVERSE_SAFE_END;
886         }
887
888         /* we are done with the config now, all the information we need is in the
889            load_order list */
890         ast_config_destroy(cfg);
891
892         load_count = 0;
893         AST_LIST_TRAVERSE(&load_order, order, entry)
894                 load_count++;
895
896         if (load_count)
897                 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
898
899         /* first, load only modules that provide global symbols */
900         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
901                 switch (load_resource(order->resource, 1)) {
902                 case AST_MODULE_LOAD_SUCCESS:
903                         modulecount++;
904                 case AST_MODULE_LOAD_DECLINE:
905                         AST_LIST_REMOVE_CURRENT(entry);
906                         ast_free(order->resource);
907                         ast_free(order);
908                         break;
909                 case AST_MODULE_LOAD_FAILURE:
910                         res = -1;
911                         goto done;
912                 case AST_MODULE_LOAD_SKIP:
913                         /* try again later */
914                         break;
915                 }
916         }
917         AST_LIST_TRAVERSE_SAFE_END;
918
919         /* now load everything else */
920         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
921                 switch (load_resource(order->resource, 0)) {
922                 case AST_MODULE_LOAD_SUCCESS:
923                         modulecount++;
924                 case AST_MODULE_LOAD_DECLINE:
925                         AST_LIST_REMOVE_CURRENT(entry);
926                         ast_free(order->resource);
927                         ast_free(order);
928                         break;
929                 case AST_MODULE_LOAD_FAILURE:
930                         res = -1;
931                         goto done;
932                 case AST_MODULE_LOAD_SKIP:
933                         /* should not happen */
934                         break;
935                 }
936         }
937         AST_LIST_TRAVERSE_SAFE_END;
938
939 done:
940         while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
941                 ast_free(order->resource);
942                 ast_free(order);
943         }
944
945         AST_LIST_UNLOCK(&module_list);
946         
947         /* Tell manager clients that are aggressive at logging in that we're done
948            loading modules. If there's a DNS problem in chan_sip, we might not
949            even reach this */
950         manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
951         
952         return res;
953 }
954
955 void ast_update_use_count(void)
956 {
957         /* Notify any module monitors that the use count for a
958            resource has changed */
959         struct loadupdate *m;
960
961         AST_LIST_LOCK(&updaters);
962         AST_LIST_TRAVERSE(&updaters, m, entry)
963                 m->updater();
964         AST_LIST_UNLOCK(&updaters);
965 }
966
967 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
968                            const char *like)
969 {
970         struct ast_module *cur;
971         int unlock = -1;
972         int total_mod_loaded = 0;
973
974         if (AST_LIST_TRYLOCK(&module_list))
975                 unlock = 0;
976  
977         AST_LIST_TRAVERSE(&module_list, cur, entry) {
978                 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
979         }
980
981         if (unlock)
982                 AST_LIST_UNLOCK(&module_list);
983
984         return total_mod_loaded;
985 }
986
987 /*! \brief Check if module exists */
988 int ast_module_check(const char *name)
989 {
990         struct ast_module *cur;
991
992         if (ast_strlen_zero(name))
993                 return 0;       /* FALSE */
994
995         cur = find_resource(name, 1);
996
997         return (cur != NULL);
998 }
999
1000
1001 int ast_loader_register(int (*v)(void))
1002 {
1003         struct loadupdate *tmp;
1004
1005         if (!(tmp = ast_malloc(sizeof(*tmp))))
1006                 return -1;
1007
1008         tmp->updater = v;
1009         AST_LIST_LOCK(&updaters);
1010         AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
1011         AST_LIST_UNLOCK(&updaters);
1012
1013         return 0;
1014 }
1015
1016 int ast_loader_unregister(int (*v)(void))
1017 {
1018         struct loadupdate *cur;
1019
1020         AST_LIST_LOCK(&updaters);
1021         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
1022                 if (cur->updater == v)  {
1023                         AST_LIST_REMOVE_CURRENT(entry);
1024                         break;
1025                 }
1026         }
1027         AST_LIST_TRAVERSE_SAFE_END;
1028         AST_LIST_UNLOCK(&updaters);
1029
1030         return cur ? 0 : -1;
1031 }
1032
1033 struct ast_module *ast_module_ref(struct ast_module *mod)
1034 {
1035         ast_atomic_fetchadd_int(&mod->usecount, +1);
1036         ast_update_use_count();
1037
1038         return mod;
1039 }
1040
1041 void ast_module_unref(struct ast_module *mod)
1042 {
1043         ast_atomic_fetchadd_int(&mod->usecount, -1);
1044         ast_update_use_count();
1045 }