58773cab21b6e07fb2c3ade0f50ff8a4a9a44f48
[asterisk/asterisk.git] / loader.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Module Loader
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  * - See ModMngMnt
25  */
26
27 #include <stdio.h>
28 #include <dirent.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/linkedlists.h"
38 #include "asterisk/module.h"
39 #include "asterisk/options.h"
40 #include "asterisk/config.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/term.h"
44 #include "asterisk/manager.h"
45 #include "asterisk/cdr.h"
46 #include "asterisk/enum.h"
47 #include "asterisk/rtp.h"
48 #include "asterisk/http.h"
49 #include "asterisk/lock.h"
50 #ifdef DLFCNCOMPAT
51 #include "asterisk/dlfcn-compat.h"
52 #else
53 #include <dlfcn.h>
54 #endif
55 #include "asterisk/md5.h"
56 #include "asterisk/utils.h"
57
58 #ifndef RTLD_NOW
59 #define RTLD_NOW 0
60 #endif
61
62 static int modlistver = 0; /* increase whenever the list changes, to protect reload */
63
64 static unsigned char expected_key[] =
65 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
66   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
67
68 /*
69  * Modules can be in a number of different states, as below:
70  * MS_FAILED    attempt to load failed. This is final.
71  * MS_NEW       just added to the list, symbols unresolved.
72  * MS_RESOLVED  all symbols resolved, but supplier modules not active yet.
73  * MS_CANLOAD   all symbols resolved and suppliers are all active
74  *              (or we are in a cyclic dependency and we are breaking a loop)
75  * MS_ACTIVE    load() returned successfully.
76  */
77 enum st_t {  /* possible states of a module */
78         MS_FAILED = 0,              /*!< cannot load */
79         MS_NEW = 1,                 /*!< nothing known */
80         MS_RESOLVED = 2,            /*!< all required resolved */
81         MS_CANLOAD = 3,             /*!< as above, plus cyclic depend.*/
82         MS_ACTIVE = 4,              /*!< all done */
83 };
84
85 /*! \note
86  * All module symbols are in module_symbols.
87  * Modules are then linked in a list of struct module,
88  * whereas updaters are in a list of struct loadupdate.
89  *
90  * Both lists (basically, the entire loader) are protected by
91  * the lock in module_list.
92  *
93  * A second lock, reloadlock, is used to prevent concurrent reloads
94  */
95 struct module {
96         AST_LIST_ENTRY(module) next;
97         struct module_symbols cb;
98         void *lib;              /* the shared lib */
99         char resource[256];
100
101         enum st_t state;
102         int export_refcount;    /* how many users of exported symbols */
103 };
104
105 struct loadupdate {
106         AST_LIST_ENTRY(loadupdate) next;
107         int (*updater)(void);
108 };
109
110 static AST_LIST_HEAD_STATIC(module_list, module);
111 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
112 AST_MUTEX_DEFINE_STATIC(reloadlock);
113
114 /*! \note
115  * helper localuser routines.
116  * All of these routines are extremely expensive, so the use of
117  * macros is totally unnecessary from the point of view of performance:
118  * the extra function call will be totally negligible in all cases.
119  */
120
121 struct localuser *ast_localuser_add(struct ast_module_lock *m,
122         struct ast_channel *chan)
123 {
124         struct localuser *u = ast_calloc(1, sizeof(*u));
125         if (u == NULL)
126                 return NULL;
127         u->chan = chan;
128         ast_mutex_lock(&m->lock);
129         AST_LIST_INSERT_HEAD(&m->u, u, next);
130         m->usecnt++;
131         ast_mutex_unlock(&m->lock);
132         ast_update_use_count();
133         return u;
134 }
135
136 void ast_localuser_remove(struct ast_module_lock *m, struct localuser *u)
137 {
138         ast_mutex_lock(&m->lock);
139         AST_LIST_REMOVE(&m->u, u, next);
140         m->usecnt--;
141         free(u);
142         ast_mutex_unlock(&m->lock);
143         ast_update_use_count();
144 }
145
146 void ast_hangup_localusers(struct ast_module_lock *m)
147 {
148         struct localuser *u;
149         ast_mutex_lock(&m->lock);
150         AST_LIST_TRAVERSE_SAFE_BEGIN(&m->u, u, next) {
151                 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
152                 free(u);
153                 AST_LIST_REMOVE_CURRENT(&m->u, next);
154         }
155         AST_LIST_TRAVERSE_SAFE_END
156         m->usecnt = 0;
157         ast_mutex_unlock(&m->lock);
158         ast_update_use_count();
159 }
160
161 /*--- new-style loader routines ---*/
162
163 /*
164  * For backward compatibility, we have 3 types of loadable modules:
165  *
166  * MOD_0 these are the 'old style' modules, which export a number
167  *       of callbacks, and their full interface, as globally visible
168  *       symbols. The module needs to be loaded with RTLD_LAZY and
169  *       RTLD_GLOBAL to make symbols visible to other modules, and
170  *       to avoid load failures due to cross dependencies.
171  *
172  * MOD_1 almost as above, but the generic callbacks are all into a
173  *       a structure, mod_data. Same load requirements as above.
174  *
175  * MOD_2 this is the 'new style' format for modules. The module must
176  *       explictly declare which simbols are exported and which
177  *       symbols from other modules are used, and the code in this
178  *       loader will implement appropriate checks to load the modules
179  *       in the correct order. Also this allows to load modules
180  *       with RTLD_NOW and RTLD_LOCAL so there is no chance of run-time
181  *       bugs due to unresolved symbols or name conflicts.
182  */
183
184 /*
185  * helper routine to print the symbolic name associated to a state
186  */
187 static const char *st_name(enum st_t state)
188 {
189         /* try to resolve required symbols */
190         const char *st;
191         switch (state) {
192 #define ST(x)  case x: st = # x; break;
193         ST(MS_NEW);
194         ST(MS_FAILED);
195         ST(MS_RESOLVED);
196         ST(MS_ACTIVE);
197         ST(MS_CANLOAD);
198         default:
199                 st = "unknown";
200         }
201         return st;
202 #undef ST
203 }
204
205 /*! \brief
206  * Fetch/release an exported symbol - modify export_refcount by delta
207  * \param delta 1 to fetch a symbol, -1 to release it.
208  * \return on success, return symbol value.
209  * \note Note, modules in MS_FAIL will never match in a 'get' request.
210  * If src is non-NULL, on exit *src points to the source module.
211  *
212  * Must be called with the lock held.
213  */
214 static void *module_symbol_helper(const char *name,
215                 int delta, struct module **src)
216 {
217         void *ret = NULL;
218         struct module *m;
219
220         AST_LIST_TRAVERSE(&module_list, m, next) {
221                 struct symbol_entry *es;
222                 if (delta > 0 && m->state == MS_FAILED)
223                         continue; /* cannot 'get' a symbol from a failed module */
224                 for (es = m->cb.exported_symbols; ret == NULL && es && es->name; es++) {
225                         if (!strcmp(es->name, name)) {
226                                 ret = es->value;
227                                 m->export_refcount += delta;
228                                 if (src)
229                                         *src = m;
230                                 break;
231                         }
232                 }
233                 if (ret)
234                         break;
235         }
236         if (ret == NULL)
237                 ast_log(LOG_WARNING, "symbol %s not found\n", name);
238         return ret;
239 }
240
241 static void *release_module_symbol(const char *name)
242 {
243         return module_symbol_helper(name, -1, NULL);
244 }
245
246 static void *get_module_symbol(const char *name, struct module **src)
247 {
248         return module_symbol_helper(name, +1, src);
249 }
250
251 /*!
252  * \brief Release refcounts to all imported symbols,
253  * and change module state to MS_FAILED.
254  */
255 static void release_module(struct module *m)
256 {
257         struct symbol_entry *s;
258
259         for (s = m->cb.required_symbols; s && s->name != NULL; s++) {
260                 if (s->value != NULL) {
261                         release_module_symbol(s->name);
262                         s->value = NULL;
263                 }
264         }
265         m->state = MS_FAILED;
266 }
267
268 /*! \brief check that no NULL symbols are exported  - the algorithms rely on that. */
269 static int check_exported(struct module *m)
270 {
271         struct symbol_entry *es = m->cb.exported_symbols;
272         int errors = 0;
273
274         if (es == NULL)
275                 return 0;
276         ast_log(LOG_WARNING, "module %s exports the following symbols\n",
277                 es->name);
278         for (; es->name; es++) {
279                 void **p = es->value;
280                 int i;
281
282                 ast_log(LOG_WARNING, "\taddr %p size %8d %s\n",
283                         es->value, es->size, es->name);
284                 for (i = 0; i <  es->size / sizeof(void *); i++, p++) {
285                         if (*p == NULL) {
286                                 ast_log(LOG_WARNING, "\t *** null field at offset %d\n", i);
287                                         errors++;
288                         }
289                 }
290         }
291         return errors;
292 }
293
294 /*!
295  * \brief Resolve symbols and change state accordingly.
296  * \return Return 1 if state changed, 0 otherwise.
297  * \note If MS_FAILED, MS_ACTIVE or MS_CANLOAD there is nothing to do.
298  * If a symbol cannot be resolved (no supplier or supplier in MS_FAIL),
299  * move to MS_FAIL and release all symbols;
300  * If all suppliers are MS_ACTIVE, move to MS_CANLOAD
301  * otherwise move to MS_RESOLVED.
302  */
303 static int resolve(struct module *m)
304 {
305         struct symbol_entry *s;
306
307         if (m->state == MS_FAILED || m->state == MS_ACTIVE || m->state == MS_CANLOAD)
308                 return 0;       /* already decided what to do */
309         /* now it's either MS_NEW or MS_RESOLVED.
310          * Be optimistic and put it in MS_CANLOAD, then try to
311          * resolve and verify symbols, and downgrade as appropriate.
312          */
313         m->state = MS_CANLOAD;
314         for (s = m->cb.required_symbols; s && s->name != NULL; s++) {
315                 void **p = (void **)(s->value);
316
317                 if (*p == NULL)         /* symbol not resolved yet */
318                         *p = get_module_symbol(s->name, &s->src);
319                 if (*p == NULL || s->src->state == MS_FAILED) {        /* fail */
320                         ast_log(LOG_WARNING,
321                                 "Unresolved symbol %s for module %s\n",
322                                 s->name, m->resource);
323                         release_module(m); /* and set to MS_FAILED */
324                         break;
325                 }
326                 if (s->src->state != MS_ACTIVE)
327                         m->state = MS_RESOLVED; /* downgrade */
328         }
329         return 1;
330 }
331
332 /*!
333  * \brief Fixup references and load modules according to their dependency order.
334  * Called when new modules are added to the list.
335  * The algorithm is as follows:
336  * - all modules MS_FAILED are changed to MS_NEW, in case something
337  *      happened that could help them.
338  * - first try to resolve symbols. If successful, change the
339  *   module's state to MS_RESOLVED otherwise to MS_FAILED
340  * - repeat on all modules until there is progress:
341  *    - if it is MS_ACTIVE or MS_FAILED, continue (no progress)
342  *    - if one has all required modules in MS_ACTIVE, try to load it.
343  *      If successful it becomes MS_ACTIVE itself, otherwise
344  *             MS_FAILED and releases all symbols.
345  *             In any case, we have progress.
346  *    - if one of the dependencies is MS_FAILED, release and set to
347  *      MS_FAILED here too. We have progress.
348  * - if we have no progress there is a cyclic dependency.
349  *      Take first and change to MS_CANLOAD, i.e. as if all required are
350  *      MS_ACTIVE. we have progress, so repeat.
351  * \par NOTE:
352  *   - must be called with lock held
353  *   - recursive calls simply return success.
354  */
355 static int fixup(const char *caller)
356 {
357         struct module *m;
358         int total = 0, new = 0, cycle = 0;
359         static int in_fixup = 0;        /* disable recursive calls */
360
361         if (in_fixup)
362                 return 0;
363         in_fixup++;
364         AST_LIST_TRAVERSE(&module_list, m, next) {
365                 total++;
366                 if (m->state == MS_FAILED)
367                         m->state = MS_NEW;
368                 if (m->state == MS_NEW)
369                         new++;
370                 /* print some debugging info for new modules */
371                 if (m->state == MS_NEW &&
372                     (m->cb.exported_symbols || m->cb.required_symbols))
373                         ast_log(LOG_NOTICE,
374                             "module %-30s exports %p requires %p state %s(%d)\n",
375                                 m->resource, m->cb.exported_symbols,
376                                 m->cb.required_symbols,
377                                 st_name(m->state), m->state);
378         }
379         ast_log(LOG_DEBUG, "---- fixup (%s): %d modules, %d new ---\n",
380                 caller, total, new);
381         for (;;cycle++) {
382                 int again = 0;  /* set if we need another round */
383                 
384                 ast_log(LOG_DEBUG, "---- fixup: cycle %d ---\n", cycle);
385                 AST_LIST_TRAVERSE(&module_list, m, next) {
386                         if (resolve(m))
387                                 again = 1;      /* something changed */
388                         if (m->state != MS_CANLOAD)     /* for now, done with this module */
389                                 continue;
390                         /* try to run the load routine */
391                         if (m->cb.load_module()) { /* error */
392                                 ast_log(LOG_WARNING, "load_module %s fail\n",
393                                         m->resource);
394                                 release_module(m); /* and set to MS_FAIL */
395                         } else {
396                                 ast_log(LOG_WARNING, "load_module %s success\n",
397                                         m->resource);
398                                 m->state = MS_ACTIVE;
399                         }
400                         again = 1;      /* something has changed */
401                 }
402                 /* Modules in MS_RESOLVED mean a possible cyclic dependency.
403                  * Break the indecision by setting one to CANLOAD, and repeat.
404                  */
405                 AST_LIST_TRAVERSE(&module_list, m, next) {
406                         if (m->state == MS_RESOLVED) {
407                                 m->state = MS_CANLOAD;
408                                 again = 1;
409                                 break;
410                         }
411                 }
412                 if (!again)     /* we are done */
413                         break;
414         }
415         ast_log(LOG_DEBUG, "---- fixup complete ---\n");
416         in_fixup--;
417         return 0;
418 }
419
420 /* test routines to see which modules depend on global symbols
421  * exported by other modules.
422  */
423 static void check_symbols(void)
424 {
425         struct dirent *d;
426         DIR *mods = opendir(ast_config_AST_MODULE_DIR);
427         void *lib;
428         char buf[1024];
429
430         ast_log(LOG_WARNING, "module dir <%s>\n", ast_config_AST_MODULE_DIR);
431         if (!mods)
432                 return;
433         while((d = readdir(mods))) {
434                 int ld = strlen(d->d_name);
435                 /* Must end in .so to load it.  */
436                 if (ld <= 3 || strcasecmp(d->d_name + ld - 3, ".so"))
437                         continue;
438                 snprintf(buf, sizeof(buf), "%s/%s", ast_config_AST_MODULE_DIR, d->d_name);
439                 lib = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
440                 if (lib == NULL) {
441                         ast_log(LOG_WARNING, "(notice only) module %s error %s\n", d->d_name, dlerror());
442                 }
443                 dlclose(lib);
444         }
445 }
446 /*--- end new-style routines ---*/
447
448 /*! \note
449  * In addition to modules, the reload command handles some extra keywords
450  * which are listed here together with the corresponding handlers.
451  * This table is also used by the command completion code.
452  */
453 static struct reload_classes_t {
454         const char *name;
455         int (*reload_fn)(void);
456 } reload_classes[] = {  /* list in alpha order, longest match first */
457         { "cdr",        ast_cdr_engine_reload },
458         { "dnsmgr",     dnsmgr_reload },
459         { "extconfig",  read_config_maps },
460         { "enum",       ast_enum_reload },
461         { "manager",    reload_manager },
462         { "rtp",        ast_rtp_reload },
463         { "http",       ast_http_reload },
464         { NULL, NULL }
465 };
466
467 static int printdigest(const unsigned char *d)
468 {
469         int x, pos;
470         char buf[256]; /* large enough so we don't have to worry */
471
472         for (pos = 0, x=0; x<16; x++)
473                 pos += sprintf(buf + pos, " %02x", *d++);
474         ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf);
475         return 0;
476 }
477
478 static int key_matches(const unsigned char *key1, const unsigned char *key2)
479 {
480         int x;
481         for (x=0; x<16; x++) {
482                 if (key1[x] != key2[x]) /* mismatch - fail now. */
483                         return 0;
484         }
485         return 1;
486 }
487
488 static int verify_key(const unsigned char *key)
489 {
490         struct MD5Context c;
491         unsigned char digest[16];
492         MD5Init(&c);
493         MD5Update(&c, key, strlen((char *)key));
494         MD5Final(digest, &c);
495         if (key_matches(expected_key, digest))
496                 return 0;
497         printdigest(digest);
498         return -1;
499 }
500
501 int ast_unload_resource(const char *resource_name, int force)
502 {
503         struct module *cur;
504         int res = -1;
505         int error = 0;
506         if (AST_LIST_LOCK(&module_list)) /* XXX should fail here ? */
507                 ast_log(LOG_WARNING, "Failed to lock\n");
508         AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, cur, next) {
509                 struct module_symbols *m = &cur->cb;
510                 
511                 if (strcasecmp(cur->resource, resource_name))   /* not us */
512                         continue;
513                 if ((res = m->usecount()) > 0)  {
514                         if (force) 
515                                 ast_log(LOG_WARNING, "Warning:  Forcing removal of module %s with use count %d\n", resource_name, res);
516                         else {
517                                 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, res);
518                                 error = 1;
519                                 break;
520                         }
521                 }
522                 res = m->unload_module();
523                 if (res) {
524                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
525                         if (force <= AST_FORCE_FIRM) {
526                                 error = 1;
527                                 break;
528                         } else
529                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
530                 }
531                 release_module(cur);    /* XXX */
532                 AST_LIST_REMOVE_CURRENT(&module_list, next);
533                 dlclose(cur->lib);
534                 free(cur);
535                 break;
536         }
537         AST_LIST_TRAVERSE_SAFE_END;
538         if (!error)
539                 modlistver++;
540         AST_LIST_UNLOCK(&module_list);
541         if (!error)     /* XXX maybe within the lock ? */
542                 ast_update_use_count();
543         return res;
544 }
545
546 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
547 {
548         struct module *cur;
549         int i, which=0, l = strlen(word);
550         char *ret = NULL;
551
552         if (pos != rpos)
553                 return NULL;
554         AST_LIST_LOCK(&module_list);
555         AST_LIST_TRAVERSE(&module_list, cur, next) {
556                 if (!strncasecmp(word, cur->resource, l) && (cur->cb.reload || !needsreload) &&
557                                 ++which > state) {
558                         ret = strdup(cur->resource);
559                         break;
560                 }
561         }
562         AST_LIST_UNLOCK(&module_list);
563         if (!ret) {
564                 for (i=0; !ret && reload_classes[i].name; i++) {
565                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
566                                 ret = strdup(reload_classes[i].name);
567                 }
568         }
569         return ret;
570 }
571
572 /*!
573  * \brief Given a function address, find the corresponding module.
574  * This is required as a workaround to the fact that we do not
575  * have a module argument to the load_module() function.
576  * Hopefully the performance implications are small.
577  */
578 struct module *ast_find_module(int (*load_fn)(void))
579 {
580         struct module *cur;
581         AST_LIST_LOCK(&module_list);
582         AST_LIST_TRAVERSE(&module_list, cur, next) {
583                 if (cur->cb.load_module == load_fn)
584                         break;
585         }
586         AST_LIST_UNLOCK(&module_list);
587         return cur;
588 }
589
590 int ast_module_reload(const char *name)
591 {
592         struct module *cur;
593         int res = 0; /* return value. 0 = not found, others, see below */
594         int i, oldversion;
595         int (*reload)(void);
596
597         if (ast_mutex_trylock(&reloadlock)) {
598                 ast_verbose("The previous reload command didn't finish yet\n");
599                 return -1;      /* reload already in progress */
600         }
601         /* Call "predefined" reload here first */
602         for (i = 0; reload_classes[i].name; i++) {
603                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
604                         reload_classes[i].reload_fn();  /* XXX should check error ? */
605                         res = 2;        /* found and reloaded */
606                 }
607         }
608         ast_lastreloadtime = time(NULL);
609
610         AST_LIST_LOCK(&module_list);
611         oldversion = modlistver;
612         AST_LIST_TRAVERSE(&module_list, cur, next) {
613                 struct module_symbols *m = &cur->cb;
614                 if (name && strcasecmp(name, cur->resource))    /* not ours */
615                         continue;
616                 reload = m->reload;
617                 if (!reload) {  /* cannot be reloaded */
618                         if (res < 1)    /* store result if possible */
619                                 res = 1;        /* 1 = no reload() method */
620                         continue;
621                 }
622                 /* drop the lock and try a reload. if successful, break */
623                 AST_LIST_UNLOCK(&module_list);
624                 res = 2;
625                 if (option_verbose > 2) 
626                         ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, m->description());
627                 reload();
628                 AST_LIST_LOCK(&module_list);
629                 if (oldversion != modlistver) /* something changed, abort */
630                         break;
631         }
632         AST_LIST_UNLOCK(&module_list);
633         ast_mutex_unlock(&reloadlock);
634         return res;
635 }
636
637 static int resource_exists(const char *resource, int do_lock)
638 {
639         struct module *cur;
640         if (do_lock && AST_LIST_LOCK(&module_list))
641                 ast_log(LOG_WARNING, "Failed to lock\n");
642         AST_LIST_TRAVERSE(&module_list, cur, next) {
643                 if (!strcasecmp(resource, cur->resource))
644                         break;
645         }
646         if (do_lock)
647                 AST_LIST_UNLOCK(&module_list);
648         return cur ? -1 : 0;
649 }
650
651 /* lookup a symbol with or without leading '_', accept either form in input */
652 static void *find_symbol(struct module *m, const char *name, int verbose)
653 {
654         char *n1;
655         void *s;
656
657         if (name[0] == '_')
658                 name++;
659         if (!(n1 = alloca(strlen(name) + 2))) /* room for leading '_' and final '\0' */
660                 return NULL;
661         n1[0] = '_';
662         strcpy(n1+1, name);
663         s = dlsym(m->lib, n1+1);        /* try without '_' */
664         if (s == NULL)
665                 s = dlsym(m->lib, n1);
666         if (verbose && s == NULL)
667                 ast_log(LOG_WARNING, "No symbol '%s' in module '%s\n",
668                         n1, m->resource);
669         return s;
670 }
671
672 /* XXX cfg is only used for !res_* and #ifdef RTLD_GLOBAL */
673 static struct module * __load_resource(const char *resource_name,
674         const struct ast_config *cfg)
675 {
676         static char fn[256];
677         int errors=0;
678         int res;
679         struct module *cur;
680         struct module_symbols *m, *m1;
681         int flags = RTLD_NOW;
682         unsigned char *key;
683         char tmp[80];
684
685 #ifndef RTLD_GLOBAL
686 #define RTLD_GLOBAL     0       /* so it is a No-op */
687 #endif
688         if (strncasecmp(resource_name, "res_", 4) && cfg) {
689                 char *val = ast_variable_retrieve(cfg, "global", resource_name);
690                 if (val && ast_true(val))
691                         flags |= RTLD_GLOBAL;
692         } else {
693                 /* Resource modules are always loaded global and lazy */
694                 flags = (RTLD_GLOBAL | RTLD_LAZY);
695         }
696         
697         if (AST_LIST_LOCK(&module_list))
698                 ast_log(LOG_WARNING, "Failed to lock\n");
699         if (resource_exists(resource_name, 0)) {
700                 ast_log(LOG_WARNING, "Module '%s' already exists\n", resource_name);
701                 AST_LIST_UNLOCK(&module_list);
702                 return NULL;
703         }
704         if (!(cur = ast_calloc(1, sizeof(*cur)))) {
705                 AST_LIST_UNLOCK(&module_list);
706                 return NULL;
707         }
708         m = &cur->cb;
709         ast_copy_string(cur->resource, resource_name, sizeof(cur->resource));
710         if (resource_name[0] == '/')
711                 ast_copy_string(fn, resource_name, sizeof(fn));
712         else
713                 snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource_name);
714
715         /* open in a sane way */
716         cur->lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
717         if (cur->lib == NULL) {
718                 ast_log(LOG_WARNING, "cannot load %s %s\n", fn, dlerror());
719         } else if ( (m1 = find_symbol(cur, "mod_data", 0)) == NULL || m1->type == MOD_0) {
720                 /* old-style module, close and reload with standard flags */
721                 dlclose(cur->lib);
722                 cur->lib = NULL;
723         }
724         if (cur->lib == NULL)   /* try reopen with the old style */
725                 cur->lib = dlopen(fn, flags);
726
727         if (!cur->lib) {
728                 ast_log(LOG_WARNING, "%s\n", dlerror());
729                 free(cur);
730                 AST_LIST_UNLOCK(&module_list);
731                 return NULL;
732         }
733         m1 = find_symbol(cur, "mod_data", 0);
734         if (m1 != NULL) {       /* new style module */
735                 ast_log(LOG_WARNING, "new style %s (%d) loaded RTLD_LOCAL\n",
736                         resource_name, m1->type);
737                 errors = check_exported(cur);
738                 *m = *m1;
739         } else {
740                 m->type = MOD_0;
741                 m->load_module = find_symbol(cur, "load_module", 1);
742                 m->unload_module = find_symbol(cur, "unload_module", 1);
743                 m->usecount = find_symbol(cur, "usecount", 1);
744                 m->description = find_symbol(cur, "description", 1);
745                 m->key = find_symbol(cur, "key", 1);
746                 m->reload = find_symbol(cur, "reload", 0);
747         }
748         if (!m->load_module)
749                 errors++;
750         if (!m->unload_module)
751                 errors++;
752         if (!m->usecount)
753                 errors++;
754         if (!m->description)
755                 errors++;
756         if (!m->key)
757                 errors++;
758         if (!m->key || !(key = (unsigned char *) m->key())) {
759                 ast_log(LOG_WARNING, "Key routine returned NULL in module %s\n", fn);
760                 key = NULL;
761                 errors++;
762         }
763         if (key && verify_key(key)) {
764                 ast_log(LOG_WARNING, "Unexpected key returned by module %s\n", fn);
765                 errors++;
766         }
767         if (errors) {
768                 ast_log(LOG_WARNING, "%d error%s loading module %s, aborted\n", errors, (errors != 1) ? "s" : "", fn);
769                 dlclose(cur->lib);
770                 free(cur);
771                 AST_LIST_UNLOCK(&module_list);
772                 return NULL;
773         }
774         if (!ast_fully_booted) {
775                 if (option_verbose) 
776                         ast_verbose( " => (%s)\n", term_color(tmp, m->description(), COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
777                 if (ast_opt_console && !option_verbose)
778                         ast_verbose( ".");
779         } else {
780                 if (option_verbose)
781                         ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", fn, m->description());
782         }
783
784         AST_LIST_INSERT_TAIL(&module_list, cur, next);
785         /* add module to end of module_list chain
786            so reload commands will be issued in same order modules were loaded */
787         
788         modlistver++;
789         if (m->type == MOD_2) {
790                 ast_log(LOG_WARNING, "new-style module %s, deferring load()\n",
791                         resource_name);
792                 cur->state = MS_NEW;
793         } else
794                 cur->state = MS_CANLOAD;
795         /* XXX make sure the usecount is 1 before releasing the lock */
796         AST_LIST_UNLOCK(&module_list);
797         
798         if (cur->state == MS_CANLOAD && (res = m->load_module())) {
799                 ast_log(LOG_WARNING, "%s: load_module failed, returning %d\n", resource_name, res);
800                 ast_unload_resource(resource_name, 0);
801                 return NULL;
802         }
803         cur->state = MS_ACTIVE;
804         ast_update_use_count();
805         return cur;
806 }
807
808 /*!
809  * \brief load a single module (API call).
810  * (recursive calls from load_module() succeed.
811  * \return Returns 0 on success, -1 on error.
812  */
813 int ast_load_resource(const char *resource_name)
814 {
815         int o = option_verbose;
816         struct ast_config *cfg = NULL;
817         struct module *m;
818
819         option_verbose = 0;     /* Keep the module file parsing silent */
820         cfg = ast_config_load(AST_MODULE_CONFIG);
821         option_verbose = o;     /* restore verbosity */
822         m = __load_resource(resource_name, cfg);
823         if (cfg)
824                 ast_config_destroy(cfg);
825         return m ? 0 : -1;
826 }       
827
828 #if 0
829 +/*
830 + * load a single module (API call).
831 + * (recursive calls from load_module() succeed.
832 + */
833 +int ast_load_resource(const char *resource_name)
834 +{
835 +       struct module *m;
836 +       int ret;
837 +
838 +       ast_mutex_lock(&modlock);
839 +       m = __load_resource(resource_name, 0);
840 +       fixup(resource_name);
841 +       ret = (m->state == MS_FAILED) ? -1 : 0;
842 +       ast_mutex_unlock(&modlock);
843 +       return ret;
844 +}
845 #endif
846
847 /*! \brief if enabled, log and output on console the module's name, and try load it */
848 static int print_and_load(const char *s, struct ast_config *cfg)
849 {
850         char tmp[80];
851
852         if (option_debug && !option_verbose)
853                 ast_log(LOG_DEBUG, "Loading module %s\n", s);
854         if (option_verbose) {
855                 ast_verbose(VERBOSE_PREFIX_1 "[%s]",
856                         term_color(tmp, s, COLOR_BRWHITE, 0, sizeof(tmp)));
857                 fflush(stdout);
858         }
859         if (__load_resource(s, cfg))
860                 return 0; /* success */
861         ast_log(LOG_WARNING, "Loading module %s failed!\n", s);
862         return -1;
863 }
864
865 static const char *loadorder[] =
866 {
867         "res_",
868         "pbx_",
869         "chan_",
870         NULL,
871 };
872
873 int load_modules(const int preload_only)
874 {
875         struct ast_config *cfg;
876         int x;
877
878         if (option_verbose) {
879                 ast_verbose(preload_only ?
880                         "Asterisk Dynamic Loader loading preload modules:\n" :
881                         "Asterisk Dynamic Loader Starting:\n");
882         }
883
884         if (0)
885                 check_symbols();
886
887         cfg = ast_config_load(AST_MODULE_CONFIG);
888
889         if (cfg) {
890                 const char *cmd = preload_only ? "preload" : "load";
891                 struct ast_variable *v;
892                 /* Load explicitly defined modules */
893                 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
894                         if (strcasecmp(v->name, cmd)) /* not what we are looking for */
895                                 continue;
896                         if (print_and_load(v->value, cfg)) {    /* XXX really fatal ? */
897                                 ast_config_destroy(cfg);
898                                 return -1;
899                         }
900                 }
901         }
902
903         if (preload_only)
904                 goto done;
905
906         if (cfg && !ast_true(ast_variable_retrieve(cfg, "modules", "autoload")))
907                 /* no autoload */
908                 goto done;
909         /*
910          * Load all modules. To help resolving dependencies, we load modules
911          * in the order defined by loadorder[], with the final step for
912          * all modules with other prefixes.
913          * (XXX the new loader does not need this).
914          */
915
916         for (x=0; x<sizeof(loadorder) / sizeof(loadorder[0]); x++) {
917                 struct dirent *d;
918                 DIR *mods = opendir(ast_config_AST_MODULE_DIR);
919                 const char *base = loadorder[x];
920                 int lx = base ? strlen(base) : 0;
921
922                 if (!mods) {
923                         if (!ast_opt_quiet)
924                                 ast_log(LOG_WARNING, "Unable to open modules directory %s.\n",
925                                         ast_config_AST_MODULE_DIR);
926                         break; /* suffices to try once! */
927                 }
928                 while((d = readdir(mods))) {
929                         int ld = strlen(d->d_name);
930                         /* Must end in .so to load it.  */
931                         if (ld > 3 && (!base || !strncasecmp(d->d_name, base, lx)) && 
932                                         !strcasecmp(d->d_name + ld - 3, ".so") &&
933                                         !resource_exists(d->d_name, 1)) {
934                                 /* It's a shared library, check if we are allowed to load it
935                                  * (very inefficient, but oh well).
936                                  */
937                                 if (cfg) {
938                                         struct ast_variable *v;
939                                         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
940                                                 if (!strcasecmp(v->name, "noload") &&
941                                                                 !strcasecmp(v->value, d->d_name)) 
942                                                         break;
943                                         }
944                                         if (v) {
945                                                 if (option_verbose) {
946                                                         ast_verbose( VERBOSE_PREFIX_1 "[skipping %s]\n",
947                                                                         d->d_name);
948                                                         fflush(stdout);
949                                                 }
950                                                 continue;
951                                         }
952                                         
953                                 }
954                                 if (print_and_load(d->d_name, cfg)) {
955                                         ast_config_destroy(cfg);
956                                         return -1;
957                                 }
958                         }
959                 }
960                 closedir(mods);
961         }
962 done:
963         fixup("load_modules");
964         ast_config_destroy(cfg);
965         return 0;
966 }
967
968 void ast_update_use_count(void)
969 {
970         /* Notify any module monitors that the use count for a 
971            resource has changed */
972         struct loadupdate *m;
973         if (AST_LIST_LOCK(&module_list))
974                 ast_log(LOG_WARNING, "Failed to lock\n");
975         AST_LIST_TRAVERSE(&updaters, m, next)
976                 m->updater();
977         AST_LIST_UNLOCK(&module_list);
978 }
979
980 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
981                            const char *like)
982 {
983         struct module *cur;
984         int unlock = -1;
985         int total_mod_loaded = 0;
986
987         if (ast_mutex_trylock(&module_list.lock))
988                 unlock = 0;
989         AST_LIST_TRAVERSE(&module_list, cur, next)
990                 total_mod_loaded += modentry(cur->resource, cur->cb.description(), cur->cb.usecount(), like);
991         if (unlock)
992                 AST_LIST_UNLOCK(&module_list);
993
994         return total_mod_loaded;
995 }
996
997 int ast_loader_register(int (*v)(void)) 
998 {
999         /* XXX Should be more flexible here, taking > 1 verboser XXX */
1000         struct loadupdate *tmp; 
1001         if (!(tmp = ast_malloc(sizeof(*tmp))))
1002                 return -1;
1003         tmp->updater = v;
1004         if (AST_LIST_LOCK(&module_list))
1005                 ast_log(LOG_WARNING, "Failed to lock\n");
1006         AST_LIST_INSERT_HEAD(&updaters, tmp, next);
1007         AST_LIST_UNLOCK(&module_list);
1008         return 0;
1009 }
1010
1011 int ast_loader_unregister(int (*v)(void))
1012 {
1013         struct loadupdate *cur;
1014
1015         if (AST_LIST_LOCK(&module_list))
1016                 ast_log(LOG_WARNING, "Failed to lock\n");
1017         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, next) {
1018                 if (cur->updater == v)  {
1019                         AST_LIST_REMOVE_CURRENT(&updaters, next);
1020                         break;
1021                 }
1022         }
1023         AST_LIST_TRAVERSE_SAFE_END;
1024         AST_LIST_UNLOCK(&module_list);
1025         return cur ? 0 : -1;
1026 }