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