4c6c2a809ee98e3ed981d7c6c6bb49e3d30663c0
[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 /*** MODULEINFO
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 #include "asterisk/_private.h"
37 #include "asterisk/paths.h"     /* use ast_config_AST_MODULE_DIR */
38 #include <dirent.h>
39
40 #include "asterisk/dlinkedlists.h"
41 #include "asterisk/module.h"
42 #include "asterisk/config.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/term.h"
45 #include "asterisk/manager.h"
46 #include "asterisk/io.h"
47 #include "asterisk/lock.h"
48 #include "asterisk/vector.h"
49 #include "asterisk/app.h"
50 #include "asterisk/test.h"
51 #include "asterisk/cli.h"
52
53 #include <dlfcn.h>
54
55 #include "asterisk/md5.h"
56 #include "asterisk/utils.h"
57
58 /*** DOCUMENTATION
59         <managerEvent language="en_US" name="Reload">
60                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
61                         <synopsis>Raised when a module has been reloaded in Asterisk.</synopsis>
62                         <syntax>
63                                 <parameter name="Module">
64                                         <para>The name of the module that was reloaded, or
65                                         <literal>All</literal> if all modules were reloaded</para>
66                                 </parameter>
67                                 <parameter name="Status">
68                                         <para>The numeric status code denoting the success or failure
69                                         of the reload request.</para>
70                                         <enumlist>
71                                                 <enum name="0"><para>Success</para></enum>
72                                                 <enum name="1"><para>Request queued</para></enum>
73                                                 <enum name="2"><para>Module not found</para></enum>
74                                                 <enum name="3"><para>Error</para></enum>
75                                                 <enum name="4"><para>Reload already in progress</para></enum>
76                                                 <enum name="5"><para>Module uninitialized</para></enum>
77                                                 <enum name="6"><para>Reload not supported</para></enum>
78                                         </enumlist>
79                                 </parameter>
80                         </syntax>
81                 </managerEventInstance>
82         </managerEvent>
83         <managerEvent language="en_US" name="Load">
84                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
85                         <synopsis>Raised when a module has been loaded in Asterisk.</synopsis>
86                         <syntax>
87                                 <parameter name="Module">
88                                         <para>The name of the module that was loaded</para>
89                                 </parameter>
90                                 <parameter name="Status">
91                                         <para>The result of the load request.</para>
92                                         <enumlist>
93                                                 <enum name="Failure"><para>Module could not be loaded properly</para></enum>
94                                                 <enum name="Success"><para>Module loaded and configured</para></enum>
95                                                 <enum name="Decline"><para>Module is not configured</para></enum>
96                                         </enumlist>
97                                 </parameter>
98                         </syntax>
99                 </managerEventInstance>
100         </managerEvent>
101         <managerEvent language="en_US" name="Unload">
102                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
103                         <synopsis>Raised when a module has been unloaded in Asterisk.</synopsis>
104                         <syntax>
105                                 <parameter name="Module">
106                                         <para>The name of the module that was unloaded</para>
107                                 </parameter>
108                                 <parameter name="Status">
109                                         <para>The result of the unload request.</para>
110                                         <enumlist>
111                                                 <enum name="Success"><para>Module unloaded successfully</para></enum>
112                                         </enumlist>
113                                 </parameter>
114                         </syntax>
115                 </managerEventInstance>
116         </managerEvent>
117  ***/
118
119 #ifndef RTLD_NOW
120 #define RTLD_NOW 0
121 #endif
122
123 #ifndef RTLD_LOCAL
124 #define RTLD_LOCAL 0
125 #endif
126
127 struct ast_module_user {
128         struct ast_channel *chan;
129         AST_LIST_ENTRY(ast_module_user) entry;
130 };
131
132 AST_DLLIST_HEAD(module_user_list, ast_module_user);
133
134 static const unsigned char expected_key[] =
135 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
136   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
137
138 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
139
140 AST_VECTOR(module_vector, struct ast_module *);
141
142 /*! Used with AST_VECTOR_CALLBACK_VOID to create a
143  * comma separated list of module names for error messages. */
144 #define STR_APPEND_TEXT(txt, str) \
145         ast_str_append(str, 0, "%s%s", \
146                 ast_str_strlen(*(str)) > 0 ? ", " : "", \
147                 txt)
148
149 /* Built-in module registrations need special handling at startup */
150 static unsigned int loader_ready;
151
152 /*! String container for deferring output of startup errors. */
153 static struct ast_vector_string startup_errors;
154 static struct ast_str *startup_error_builder;
155
156 #if defined(HAVE_PERMANENT_DLOPEN) || defined(AST_XML_DOCS)
157 static char *get_name_from_resource(const char *resource)
158 {
159         int len;
160         const char *last_three;
161         char *mod_name;
162
163         if (!resource) {
164                 return NULL;
165         }
166
167         len = strlen(resource);
168         if (len > 3) {
169                 last_three = &resource[len-3];
170                 if (!strcasecmp(last_three, ".so")) {
171                         mod_name = ast_calloc(1, len - 2);
172                         if (mod_name) {
173                                 ast_copy_string(mod_name, resource, len - 2);
174                                 return mod_name;
175                         } else {
176                                 /* Unable to allocate memory. */
177                                 return NULL;
178                         }
179                 }
180         }
181
182         /* Resource is the name - happens when manually unloading a module. */
183         mod_name = ast_calloc(1, len + 1);
184         if (mod_name) {
185                 ast_copy_string(mod_name, resource, len + 1);
186                 return mod_name;
187         }
188
189         /* Unable to allocate memory. */
190         return NULL;
191 }
192 #endif
193
194 #if defined(HAVE_PERMANENT_DLOPEN)
195 #define FIRST_DLOPEN 999
196
197 struct ao2_container *info_list = NULL;
198
199 struct info_list_obj {
200         const struct ast_module_info *info;
201         int dlopened;
202         char name[0];
203 };
204
205 static struct info_list_obj *info_list_obj_alloc(const char *name,
206         const struct ast_module_info *info)
207 {
208         struct info_list_obj *new_entry;
209
210         new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL);
211
212         if (!new_entry) {
213                 return NULL;
214         }
215
216         strcpy(new_entry->name, name); /* SAFE */
217         new_entry->info = info;
218         new_entry->dlopened = FIRST_DLOPEN;
219
220         return new_entry;
221 }
222
223 AO2_STRING_FIELD_CMP_FN(info_list_obj, name)
224
225 static void manual_mod_reg(const void *lib, const char *resource)
226 {
227         struct info_list_obj *obj_tmp;
228         char *mod_name;
229
230         if (lib) {
231                 mod_name = get_name_from_resource(resource);
232                 if (mod_name) {
233                         obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
234                         if (obj_tmp) {
235                                 if (obj_tmp->dlopened == FIRST_DLOPEN) {
236                                         obj_tmp->dlopened = 1;
237                                 } else {
238                                         ast_module_register(obj_tmp->info);
239                                 }
240                                 ao2_ref(obj_tmp, -1);
241                         }
242                         ast_free(mod_name);
243                 }
244         }
245 }
246
247 static void manual_mod_unreg(const char *resource)
248 {
249         struct info_list_obj *obj_tmp;
250         char *mod_name;
251
252         /* When Asterisk shuts down the destructor is called automatically. */
253         if (ast_shutdown_final()) {
254                 return;
255         }
256
257         mod_name = get_name_from_resource(resource);
258         if (mod_name) {
259                 obj_tmp = ao2_find(info_list, mod_name, OBJ_SEARCH_KEY);
260                 if (obj_tmp) {
261                         ast_module_unregister(obj_tmp->info);
262                         ao2_ref(obj_tmp, -1);
263                 }
264                 ast_free(mod_name);
265         }
266 }
267 #endif
268
269 static __attribute__((format(printf, 1, 2))) void module_load_error(const char *fmt, ...)
270 {
271         char *copy = NULL;
272         va_list ap;
273
274         va_start(ap, fmt);
275         if (startup_error_builder) {
276                 ast_str_set_va(&startup_error_builder, 0, fmt, ap);
277                 copy = ast_strdup(ast_str_buffer(startup_error_builder));
278                 if (!copy || AST_VECTOR_APPEND(&startup_errors, copy)) {
279                         ast_log(LOG_ERROR, "%s", ast_str_buffer(startup_error_builder));
280                         ast_free(copy);
281                 }
282         } else {
283                 ast_log_ap(LOG_ERROR, fmt, ap);
284         }
285         va_end(ap);
286 }
287
288 /*!
289  * \brief Internal flag to indicate all modules have been initially loaded.
290  */
291 static int modules_loaded;
292
293 struct ast_module {
294         const struct ast_module_info *info;
295         /*! Used to get module references into refs log */
296         void *ref_debug;
297         /*! The shared lib. */
298         void *lib;
299         /*! Number of 'users' and other references currently holding the module. */
300         int usecount;
301         /*! List of users holding the module. */
302         struct module_user_list users;
303
304         /*! List of required module names. */
305         struct ast_vector_string requires;
306         /*! List of optional api modules. */
307         struct ast_vector_string optional_modules;
308         /*! List of modules this enhances. */
309         struct ast_vector_string enhances;
310
311         /*!
312          * \brief Vector holding pointers to modules we have a reference to.
313          *
314          * When one module requires another, the required module gets added
315          * to this list with a reference.
316          */
317         struct module_vector reffed_deps;
318         struct {
319                 /*! The module running and ready to accept requests. */
320                 unsigned int running:1;
321                 /*! The module has declined to start. */
322                 unsigned int declined:1;
323                 /*! This module is being held open until it's time to shutdown. */
324                 unsigned int keepuntilshutdown:1;
325                 /*! The module is built-in. */
326                 unsigned int builtin:1;
327                 /*! The admin has declared this module is required. */
328                 unsigned int required:1;
329                 /*! This module is marked for preload. */
330                 unsigned int preload:1;
331         } flags;
332         AST_DLLIST_ENTRY(ast_module) entry;
333         char resource[0];
334 };
335
336 static AST_DLLIST_HEAD_STATIC(module_list, ast_module);
337
338
339 struct load_results_map {
340         int result;
341         const char *name;
342 };
343
344 static const struct load_results_map load_results[] = {
345         { AST_MODULE_LOAD_SUCCESS, "Success" },
346         { AST_MODULE_LOAD_DECLINE, "Decline" },
347         { AST_MODULE_LOAD_SKIP, "Skip" },
348         { AST_MODULE_LOAD_PRIORITY, "Priority" },
349         { AST_MODULE_LOAD_FAILURE, "Failure" },
350 };
351 #define AST_MODULE_LOAD_UNKNOWN_STRING          "Unknown"               /* Status string for unknown load status */
352
353 static void publish_load_message_type(const char* type, const char *name, const char *status);
354 static void publish_reload_message(const char *name, enum ast_module_reload_result result);
355 static void publish_load_message(const char *name, enum ast_module_load_result result);
356 static void publish_unload_message(const char *name, const char* status);
357
358
359 /*
360  * module_list is cleared by its constructor possibly after
361  * we start accumulating built-in modules, so we need to
362  * use another list (without the lock) to accumulate them.
363  */
364 static struct module_list builtin_module_list;
365
366 static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b)
367 {
368         return strcasecmp(a->resource, b->resource);
369 }
370
371 static int module_vector_cmp(struct ast_module *a, struct ast_module *b)
372 {
373         int preload_diff = (int)b->flags.preload - (int)a->flags.preload;
374         /* if load_pri is not set, default is 128.  Lower is better */
375         int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER)
376                 ? a->info->load_pri : AST_MODPRI_DEFAULT;
377         int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER)
378                 ? b->info->load_pri : AST_MODPRI_DEFAULT;
379
380         if (preload_diff) {
381                 /* -1 preload a but not b */
382                 /*  0 preload both or neither */
383                 /*  1 preload b but not a */
384                 return preload_diff;
385         }
386
387         /*
388          * Returns comparison values for a vector sorted by priority.
389          * <0 a_pri < b_pri
390          * =0 a_pri == b_pri
391          * >0 a_pri > b_pri
392          */
393         return a_pri - b_pri;
394 }
395
396 static struct ast_module *find_resource(const char *resource, int do_lock);
397
398 /*!
399  * \internal
400  * \brief Add a reference from mod to dep.
401  *
402  * \param mod Owner of the new reference.
403  * \param dep Module to reference
404  * \param missing Vector to store name of \a dep if it is not running.
405  *
406  * This function returns failure if \a dep is not running and \a missing
407  * is NULL.  If \a missing is not NULL errors will only be returned for
408  * allocation failures.
409  *
410  * \retval 0 Success
411  * \retval -1 Failure
412  *
413  * \note Adding a second reference to the same dep will return success
414  *       without doing anything.
415  */
416 static int module_reffed_deps_add(struct ast_module *mod, struct ast_module *dep,
417         struct ast_vector_const_string *missing)
418 {
419         if (!dep->flags.running) {
420                 return !missing ? -1 : AST_VECTOR_APPEND(missing, dep->info->name);
421         }
422
423         if (AST_VECTOR_GET_CMP(&mod->reffed_deps, dep, AST_VECTOR_ELEM_DEFAULT_CMP)) {
424                 /* Skip duplicate. */
425                 return 0;
426         }
427
428         if (AST_VECTOR_APPEND(&mod->reffed_deps, dep)) {
429                 return -1;
430         }
431
432         ast_module_ref(dep);
433
434         return 0;
435 }
436
437 /*!
438  * \internal
439  * \brief Add references for modules that enhance a dependency.
440  *
441  * \param mod Owner of the new references.
442  * \param dep Module to check for enhancers.
443  * \param missing Vector to store name of any enhancer that is not running or declined.
444  *
445  * \retval 0 Success
446  * \retval -1 Failure
447  */
448 static int module_reffed_deps_add_dep_enhancers(struct ast_module *mod,
449         struct ast_module *dep, struct ast_vector_const_string *missing)
450 {
451         struct ast_module *cur;
452
453         AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
454                 if (cur->flags.declined) {
455                         continue;
456                 }
457
458                 if (!AST_VECTOR_GET_CMP(&cur->enhances, dep->info->name, !strcasecmp)) {
459                         /* dep is not enhanced by cur. */
460                         continue;
461                 }
462
463                 /* dep is enhanced by cur, therefore mod requires cur. */
464                 if (module_reffed_deps_add(mod, cur, missing)) {
465                         return -1;
466                 }
467         }
468
469         return 0;
470 }
471
472 /*!
473  * \internal
474  * \brief Add references to a list of dependencies.
475  *
476  * \param mod Owner of the new references.
477  * \param vec List of required modules to process
478  * \param missing Vector to store names of modules that are not running.
479  * \param ref_enhancers Reference all enhancers of each required module.
480  * \param isoptional Modules that are not loaded can be ignored.
481  *
482  * \retval 0 Success
483  * \retval -1 Failure
484  */
485 static int module_deps_process_reqlist(struct ast_module *mod,
486         struct ast_vector_string *vec, struct ast_vector_const_string *missing,
487         int ref_enhancers, int isoptional)
488 {
489         int idx;
490
491         for (idx = 0; idx < AST_VECTOR_SIZE(vec); idx++) {
492                 const char *depname = AST_VECTOR_GET(vec, idx);
493                 struct ast_module *dep = find_resource(depname, 0);
494
495                 if (!dep || !dep->flags.running) {
496                         if (isoptional && !dep) {
497                                 continue;
498                         }
499
500                         if (missing && !AST_VECTOR_APPEND(missing, depname)) {
501                                 continue;
502                         }
503
504                         return -1;
505                 }
506
507                 if (module_reffed_deps_add(mod, dep, missing)) {
508                         return -1;
509                 }
510
511                 if (ref_enhancers && module_reffed_deps_add_dep_enhancers(mod, dep, missing)) {
512                         return -1;
513                 }
514         }
515
516         return 0;
517 }
518
519 /*!
520  * \internal
521  * \brief Grab all references required to start the module.
522  *
523  * \param mod The module we're trying to start.
524  * \param missing Vector to store a list of missing dependencies.
525  *
526  * \retval 0 Success
527  * \retval -1 Failure
528  *
529  * \note module_list must be locked.
530  *
531  * \note Caller is responsible for initializing and freeing the vector.
532  *       Elements are safely read only while module_list remains locked.
533  */
534 static int module_deps_reference(struct ast_module *mod, struct ast_vector_const_string *missing)
535 {
536         int res = 0;
537
538         /* Grab references to modules we enhance but not other enhancements. */
539         res |= module_deps_process_reqlist(mod, &mod->enhances, missing, 0, 0);
540
541         /* Grab references to modules we require plus enhancements. */
542         res |= module_deps_process_reqlist(mod, &mod->requires, missing, 1, 0);
543
544         /* Grab references to optional modules including enhancements. */
545         res |= module_deps_process_reqlist(mod, &mod->optional_modules, missing, 1, 1);
546
547         return res;
548 }
549
550 /*!
551  * \brief Recursively find required dependencies that are not running.
552  *
553  * \param mod Module to scan for dependencies.
554  * \param missingdeps Vector listing modules that must be started first.
555  *
556  * \retval 0 All dependencies resolved.
557  * \retval -1 Failed to resolve some dependencies.
558  *
559  * An error from this function usually means a required module is not even
560  * loaded.  This function is safe from infinite recursion, but dependency
561  * loops are not reported as an error from here.  On success missingdeps
562  * will contain a list of every module that needs to be running before this
563  * module can start.  missingdeps is sorted by load priority so any missing
564  * dependencies can be started if needed.
565  */
566 static int module_deps_missing_recursive(struct ast_module *mod, struct module_vector *missingdeps)
567 {
568         int i = 0;
569         int res = -1;
570         struct ast_vector_const_string localdeps;
571         struct ast_module *dep;
572
573         /*
574          * localdeps stores a copy of all dependencies that mod could not reference.
575          * First we discard modules that we've already found. We add all newly found
576          * modules to the missingdeps vector then scan them recursively.  This will
577          * ensure we quickly run out of stuff to do.
578          */
579         AST_VECTOR_INIT(&localdeps, 0);
580         if (module_deps_reference(mod, &localdeps)) {
581                 goto clean_return;
582         }
583
584         while (i < AST_VECTOR_SIZE(&localdeps)) {
585                 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
586                 if (!dep) {
587                         goto clean_return;
588                 }
589
590                 if (AST_VECTOR_GET_CMP(missingdeps, dep, AST_VECTOR_ELEM_DEFAULT_CMP)) {
591                         /* Skip common dependency.  We have already searched it. */
592                         AST_VECTOR_REMOVE(&localdeps, i, 0);
593                 } else {
594                         /* missingdeps is the real list so keep it sorted. */
595                         if (AST_VECTOR_ADD_SORTED(missingdeps, dep, module_vector_cmp)) {
596                                 goto clean_return;
597                         }
598                         i++;
599                 }
600         }
601
602         res = 0;
603         for (i = 0; !res && i < AST_VECTOR_SIZE(&localdeps); i++) {
604                 dep = find_resource(AST_VECTOR_GET(&localdeps, i), 0);
605                 /* We've already confirmed dep is loaded in the first loop. */
606                 res = module_deps_missing_recursive(dep, missingdeps);
607         }
608
609 clean_return:
610         AST_VECTOR_FREE(&localdeps);
611
612         return res;
613 }
614
615 const char *ast_module_name(const struct ast_module *mod)
616 {
617         if (!mod || !mod->info) {
618                 return NULL;
619         }
620
621         return mod->info->name;
622 }
623
624 struct loadupdate {
625         int (*updater)(void);
626         AST_LIST_ENTRY(loadupdate) entry;
627 };
628
629 static AST_DLLIST_HEAD_STATIC(updaters, loadupdate);
630
631 AST_MUTEX_DEFINE_STATIC(reloadlock);
632
633 struct reload_queue_item {
634         AST_LIST_ENTRY(reload_queue_item) entry;
635         char module[0];
636 };
637
638 static int do_full_reload = 0;
639
640 static AST_DLLIST_HEAD_STATIC(reload_queue, reload_queue_item);
641
642 /*!
643  * \internal
644  *
645  * This variable is set by load_dynamic_module so ast_module_register
646  * can know what pointer is being registered.
647  *
648  * This is protected by the module_list lock.
649  */
650 static struct ast_module * volatile resource_being_loaded;
651
652 /*!
653  * \internal
654  * \brief Used by AST_MODULE_INFO to register with the module loader.
655  *
656  * This function is automatically called when each module is opened.
657  * It must never be used from outside AST_MODULE_INFO.
658  */
659 void ast_module_register(const struct ast_module_info *info)
660 {
661         struct ast_module *mod;
662
663         if (!loader_ready) {
664                 mod = ast_std_calloc(1, sizeof(*mod) + strlen(info->name) + 1);
665                 if (!mod) {
666                         /* We haven't even reached main() yet, if we can't
667                          * allocate memory at this point just give up. */
668                         fprintf(stderr, "Allocation failure during startup.\n");
669                         exit(2);
670                 }
671                 strcpy(mod->resource, info->name); /* safe */
672                 mod->info = info;
673                 mod->flags.builtin = 1;
674                 AST_DLLIST_INSERT_TAIL(&builtin_module_list, mod, entry);
675
676                 /* ast_module_register for built-in modules is run again during module preload. */
677                 return;
678         }
679
680         /*
681          * This lock protects resource_being_loaded as well as the module
682          * list.  Normally we already have a lock on module_list when we
683          * begin the load but locking again from here prevents corruption
684          * if an asterisk module is dlopen'ed from outside the module loader.
685          */
686         AST_DLLIST_LOCK(&module_list);
687         mod = resource_being_loaded;
688         if (!mod) {
689                 AST_DLLIST_UNLOCK(&module_list);
690                 return;
691         }
692
693         ast_debug(5, "Registering module %s\n", info->name);
694
695         /* This tells load_dynamic_module that we're registered. */
696         resource_being_loaded = NULL;
697
698         mod->info = info;
699         if (ast_opt_ref_debug) {
700                 mod->ref_debug = ao2_t_alloc_options(0, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK, info->name);
701         }
702         AST_LIST_HEAD_INIT(&mod->users);
703         AST_VECTOR_INIT(&mod->requires, 0);
704         AST_VECTOR_INIT(&mod->optional_modules, 0);
705         AST_VECTOR_INIT(&mod->enhances, 0);
706         AST_VECTOR_INIT(&mod->reffed_deps, 0);
707
708         AST_DLLIST_INSERT_TAIL(&module_list, mod, entry);
709         AST_DLLIST_UNLOCK(&module_list);
710
711         /* give the module a copy of its own handle, for later use in registrations and the like */
712         *((struct ast_module **) &(info->self)) = mod;
713
714 #if defined(HAVE_PERMANENT_DLOPEN)
715         if (mod->flags.builtin != 1) {
716                 struct info_list_obj *obj_tmp = ao2_find(info_list, info->name,
717                         OBJ_SEARCH_KEY);
718
719                 if (!obj_tmp) {
720                         obj_tmp = info_list_obj_alloc(info->name, info);
721                         if (obj_tmp) {
722                                 ao2_link(info_list, obj_tmp);
723                                 ao2_ref(obj_tmp, -1);
724                         }
725                 } else {
726                         ao2_ref(obj_tmp, -1);
727                 }
728         }
729 #endif
730 }
731
732 static int module_post_register(struct ast_module *mod)
733 {
734         int res;
735
736         /* Split lists from mod->info. */
737         res  = ast_vector_string_split(&mod->requires, mod->info->requires, ",", 0, strcasecmp);
738         res |= ast_vector_string_split(&mod->optional_modules, mod->info->optional_modules, ",", 0, strcasecmp);
739         res |= ast_vector_string_split(&mod->enhances, mod->info->enhances, ",", 0, strcasecmp);
740
741         return res;
742 }
743
744 static void module_destroy(struct ast_module *mod)
745 {
746         AST_VECTOR_CALLBACK_VOID(&mod->requires, ast_free);
747         AST_VECTOR_FREE(&mod->requires);
748
749         AST_VECTOR_CALLBACK_VOID(&mod->optional_modules, ast_free);
750         AST_VECTOR_FREE(&mod->optional_modules);
751
752         AST_VECTOR_CALLBACK_VOID(&mod->enhances, ast_free);
753         AST_VECTOR_FREE(&mod->enhances);
754
755         /* Release references to all dependencies. */
756         AST_VECTOR_CALLBACK_VOID(&mod->reffed_deps, ast_module_unref);
757         AST_VECTOR_FREE(&mod->reffed_deps);
758
759         AST_LIST_HEAD_DESTROY(&mod->users);
760         ao2_cleanup(mod->ref_debug);
761         if (mod->flags.builtin) {
762                 ast_std_free(mod);
763         } else {
764                 ast_free(mod);
765         }
766 }
767
768 void ast_module_unregister(const struct ast_module_info *info)
769 {
770         struct ast_module *mod = NULL;
771
772         /* it is assumed that the users list in the module structure
773            will already be empty, or we cannot have gotten to this
774            point
775         */
776         AST_DLLIST_LOCK(&module_list);
777         AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&module_list, mod, entry) {
778                 if (mod->info == info) {
779                         AST_DLLIST_REMOVE_CURRENT(entry);
780                         break;
781                 }
782         }
783         AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
784         AST_DLLIST_UNLOCK(&module_list);
785
786         if (mod && !mod->usecount) {
787                 /*
788                  * We are intentionally leaking mod if usecount is not zero.
789                  * This is necessary if the module is being forcefully unloaded.
790                  * In addition module_destroy is not safe to run after exit()
791                  * is called.  ast_module_unregister is run during cleanup of
792                  * the process when libc releases each module's shared object
793                  * library.
794                  */
795                 ast_debug(5, "Unregistering module %s\n", info->name);
796                 module_destroy(mod);
797         }
798 }
799
800 struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast_channel *chan)
801 {
802         struct ast_module_user *u;
803
804         u = ast_calloc(1, sizeof(*u));
805         if (!u) {
806                 return NULL;
807         }
808
809         u->chan = chan;
810
811         AST_LIST_LOCK(&mod->users);
812         AST_LIST_INSERT_HEAD(&mod->users, u, entry);
813         AST_LIST_UNLOCK(&mod->users);
814
815         if (mod->ref_debug) {
816                 ao2_ref(mod->ref_debug, +1);
817         }
818
819         ast_atomic_fetchadd_int(&mod->usecount, +1);
820
821         ast_update_use_count();
822
823         return u;
824 }
825
826 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
827 {
828         if (!u) {
829                 return;
830         }
831
832         AST_LIST_LOCK(&mod->users);
833         u = AST_LIST_REMOVE(&mod->users, u, entry);
834         AST_LIST_UNLOCK(&mod->users);
835         if (!u) {
836                 /*
837                  * Was not in the list.  Either a bad pointer or
838                  * __ast_module_user_hangup_all() has been called.
839                  */
840                 return;
841         }
842
843         if (mod->ref_debug) {
844                 ao2_ref(mod->ref_debug, -1);
845         }
846
847         ast_atomic_fetchadd_int(&mod->usecount, -1);
848         ast_free(u);
849
850         ast_update_use_count();
851 }
852
853 void __ast_module_user_hangup_all(struct ast_module *mod)
854 {
855         struct ast_module_user *u;
856
857         AST_LIST_LOCK(&mod->users);
858         while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
859                 if (u->chan) {
860                         ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
861                 }
862
863                 if (mod->ref_debug) {
864                         ao2_ref(mod->ref_debug, -1);
865                 }
866
867                 ast_atomic_fetchadd_int(&mod->usecount, -1);
868                 ast_free(u);
869         }
870         AST_LIST_UNLOCK(&mod->users);
871
872         ast_update_use_count();
873 }
874
875 static int printdigest(const unsigned char *d)
876 {
877         int x, pos;
878         char buf[256]; /* large enough so we don't have to worry */
879
880         for (pos = 0, x = 0; x < 16; x++)
881                 pos += sprintf(buf + pos, " %02hhx", *d++);
882
883         ast_debug(1, "Unexpected signature:%s\n", buf);
884
885         return 0;
886 }
887
888 static int key_matches(const unsigned char *key1, const unsigned char *key2)
889 {
890         int x;
891
892         for (x = 0; x < 16; x++) {
893                 if (key1[x] != key2[x])
894                         return 0;
895         }
896
897         return 1;
898 }
899
900 static int verify_key(const unsigned char *key)
901 {
902         struct MD5Context c;
903         unsigned char digest[16];
904
905         MD5Init(&c);
906         MD5Update(&c, key, strlen((char *)key));
907         MD5Final(digest, &c);
908
909         if (key_matches(expected_key, digest))
910                 return 0;
911
912         printdigest(digest);
913
914         return -1;
915 }
916
917 static size_t resource_name_baselen(const char *name)
918 {
919         size_t len = strlen(name);
920
921         if (len > 3 && !strcasecmp(name + len - 3, ".so")) {
922                 return len - 3;
923         }
924
925         return len;
926 }
927
928 static int resource_name_match(const char *name1, size_t baselen1, const char *name2)
929 {
930         if (baselen1 != resource_name_baselen(name2)) {
931                 return -1;
932         }
933
934         return strncasecmp(name1, name2, baselen1);
935 }
936
937 static struct ast_module *find_resource(const char *resource, int do_lock)
938 {
939         struct ast_module *cur;
940         size_t resource_baselen = resource_name_baselen(resource);
941
942         if (do_lock) {
943                 AST_DLLIST_LOCK(&module_list);
944         }
945
946         AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
947                 if (!resource_name_match(resource, resource_baselen, cur->resource)) {
948                         break;
949                 }
950         }
951
952         if (do_lock) {
953                 AST_DLLIST_UNLOCK(&module_list);
954         }
955
956         return cur;
957 }
958
959 /*!
960  * \brief dlclose(), with failure logging.
961  */
962 static void logged_dlclose(const char *name, void *lib)
963 {
964         char *error;
965
966         if (!lib) {
967                 return;
968         }
969
970         /* Clear any existing error */
971         dlerror();
972         if (dlclose(lib)) {
973                 error = dlerror();
974                 ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
975                         S_OR(name, "unknown"), S_OR(error, "Unknown error"));
976 #if defined(HAVE_PERMANENT_DLOPEN)
977         } else {
978                 manual_mod_unreg(name);
979 #endif
980         }
981 }
982
983 #if defined(HAVE_RTLD_NOLOAD)
984 /*!
985  * \brief Check to see if the given resource is loaded.
986  *
987  * \param resource_name Name of the resource, including .so suffix.
988  * \return False (0) if module is not loaded.
989  * \return True (non-zero) if module is loaded.
990  */
991 static int is_module_loaded(const char *resource_name)
992 {
993         char fn[PATH_MAX] = "";
994         void *lib;
995
996         snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR,
997                 resource_name);
998
999         lib = dlopen(fn, RTLD_LAZY | RTLD_NOLOAD);
1000
1001         if (lib) {
1002                 logged_dlclose(resource_name, lib);
1003                 return 1;
1004         }
1005
1006         return 0;
1007 }
1008 #endif
1009
1010 static void unload_dynamic_module(struct ast_module *mod)
1011 {
1012 #if defined(HAVE_RTLD_NOLOAD)
1013         char *name = ast_strdupa(ast_module_name(mod));
1014 #endif
1015         void *lib = mod->lib;
1016
1017         /* WARNING: the structure pointed to by mod is going to
1018            disappear when this operation succeeds, so we can't
1019            dereference it */
1020         logged_dlclose(ast_module_name(mod), lib);
1021
1022         /* There are several situations where the module might still be resident
1023          * in memory.
1024          *
1025          * If somehow there was another dlopen() on the same module (unlikely,
1026          * since that all is supposed to happen in loader.c).
1027          *
1028          * Avoid the temptation of repeating the dlclose(). The other code that
1029          * dlopened the module still has its module reference, and should close
1030          * it itself. In other situations, dlclose() will happily return success
1031          * for as many times as you wish to call it.
1032          */
1033 #if defined(HAVE_RTLD_NOLOAD)
1034         if (is_module_loaded(name)) {
1035                 ast_log(LOG_WARNING, "Module '%s' could not be completely unloaded\n", name);
1036         }
1037 #endif
1038 }
1039
1040 static int load_dlopen_missing(struct ast_str **list, struct ast_vector_string *deps)
1041 {
1042         int i;
1043         int c = 0;
1044
1045         for (i = 0; i < AST_VECTOR_SIZE(deps); i++) {
1046                 const char *dep = AST_VECTOR_GET(deps, i);
1047                 if (!find_resource(dep, 0)) {
1048                         STR_APPEND_TEXT(dep, list);
1049                         c++;
1050                 }
1051         }
1052
1053         return c;
1054 }
1055
1056 /*!
1057  * \internal
1058  * \brief Attempt to dlopen a module.
1059  *
1060  * \param resource_in The module name to load.
1061  * \param so_ext ".so" or blank if ".so" is already part of resource_in.
1062  * \param filename Passed directly to dlopen.
1063  * \param flags Passed directly to dlopen.
1064  * \param suppress_logging Do not log any error from dlopen.
1065  *
1066  * \return Pointer to opened module, NULL on error.
1067  *
1068  * \warning module_list must be locked before calling this function.
1069  */
1070 static struct ast_module *load_dlopen(const char *resource_in, const char *so_ext,
1071         const char *filename, int flags, unsigned int suppress_logging)
1072 {
1073         struct ast_module *mod;
1074
1075         ast_assert(!resource_being_loaded);
1076
1077         mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);
1078         if (!mod) {
1079                 return NULL;
1080         }
1081
1082         sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */
1083
1084         resource_being_loaded = mod;
1085         mod->lib = dlopen(filename, flags);
1086 #if defined(HAVE_PERMANENT_DLOPEN)
1087         manual_mod_reg(mod->lib, mod->resource);
1088 #endif
1089         if (resource_being_loaded) {
1090                 struct ast_str *list;
1091                 int c = 0;
1092                 const char *dlerror_msg = ast_strdupa(S_OR(dlerror(), ""));
1093
1094                 resource_being_loaded = NULL;
1095                 if (mod->lib) {
1096                         module_load_error("Module '%s' did not register itself during load\n", resource_in);
1097                         logged_dlclose(resource_in, mod->lib);
1098
1099                         goto error_return;
1100                 }
1101
1102                 if (suppress_logging) {
1103                         goto error_return;
1104                 }
1105
1106                 resource_being_loaded = mod;
1107                 mod->lib = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
1108 #if defined(HAVE_PERMANENT_DLOPEN)
1109                 manual_mod_reg(mod->lib, mod->resource);
1110 #endif
1111                 if (resource_being_loaded) {
1112                         resource_being_loaded = NULL;
1113
1114                         module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1115                         logged_dlclose(resource_in, mod->lib);
1116
1117                         goto error_return;
1118                 }
1119
1120                 list = ast_str_create(64);
1121                 if (list) {
1122                         if (module_post_register(mod)) {
1123                                 goto loaded_error;
1124                         }
1125
1126                         c = load_dlopen_missing(&list, &mod->requires);
1127                         c += load_dlopen_missing(&list, &mod->enhances);
1128 #ifndef OPTIONAL_API
1129                         c += load_dlopen_missing(&list, &mod->optional_modules);
1130 #endif
1131                 }
1132
1133                 if (list && ast_str_strlen(list)) {
1134                         module_load_error("Error loading module '%s', missing %s: %s\n",
1135                                 resource_in, c == 1 ? "dependency" : "dependencies", ast_str_buffer(list));
1136                 } else {
1137                         module_load_error("Error loading module '%s': %s\n", resource_in, dlerror_msg);
1138                 }
1139
1140 loaded_error:
1141                 ast_free(list);
1142                 unload_dynamic_module(mod);
1143
1144                 return NULL;
1145
1146 error_return:
1147                 ast_free(mod);
1148
1149                 return NULL;
1150         }
1151
1152         return mod;
1153 }
1154
1155 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int suppress_logging)
1156 {
1157         char fn[PATH_MAX];
1158         struct ast_module *mod;
1159         size_t resource_in_len = strlen(resource_in);
1160         const char *so_ext = "";
1161
1162         if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) {
1163                 so_ext = ".so";
1164         }
1165
1166         snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);
1167
1168         /* Try loading in quiet mode first with RTLD_LOCAL.  The majority of modules do not
1169          * export symbols so this allows the least number of calls to dlopen. */
1170         mod = load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_LOCAL, suppress_logging);
1171
1172         if (!mod || !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
1173                 return mod;
1174         }
1175
1176         /* Close the module so we can reopen with correct flags. */
1177         logged_dlclose(resource_in, mod->lib);
1178
1179         return load_dlopen(resource_in, so_ext, fn, RTLD_NOW | RTLD_GLOBAL, 0);
1180 }
1181
1182 int modules_shutdown(void)
1183 {
1184         struct ast_module *mod;
1185         int somethingchanged;
1186         int res;
1187
1188         AST_DLLIST_LOCK(&module_list);
1189
1190         /*!\note Some resources, like timers, are started up dynamically, and thus
1191          * may be still in use, even if all channels are dead.  We must therefore
1192          * check the usecount before asking modules to unload. */
1193         do {
1194                 /* Reset flag before traversing the list */
1195                 somethingchanged = 0;
1196
1197                 AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&module_list, mod, entry) {
1198                         if (mod->usecount) {
1199                                 ast_debug(1, "Passing on %s: its use count is %d\n",
1200                                         mod->resource, mod->usecount);
1201                                 continue;
1202                         }
1203                         AST_DLLIST_REMOVE_CURRENT(entry);
1204                         if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
1205                                 ast_verb(1, "Unloading %s\n", mod->resource);
1206                                 mod->info->unload();
1207                         }
1208                         module_destroy(mod);
1209                         somethingchanged = 1;
1210                 }
1211                 AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
1212                 if (!somethingchanged) {
1213                         AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
1214                                 if (mod->flags.keepuntilshutdown) {
1215                                         ast_module_unref(mod);
1216                                         mod->flags.keepuntilshutdown = 0;
1217                                         somethingchanged = 1;
1218                                 }
1219                         }
1220                 }
1221         } while (somethingchanged);
1222
1223         res = AST_DLLIST_EMPTY(&module_list);
1224         AST_DLLIST_UNLOCK(&module_list);
1225
1226         return !res;
1227 }
1228
1229 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
1230 {
1231         struct ast_module *mod;
1232         int res = -1;
1233         int error = 0;
1234
1235         AST_DLLIST_LOCK(&module_list);
1236
1237         if (!(mod = find_resource(resource_name, 0))) {
1238                 AST_DLLIST_UNLOCK(&module_list);
1239                 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
1240                 return -1;
1241         }
1242
1243         if (!mod->flags.running || mod->flags.declined) {
1244                 ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
1245                 error = 1;
1246         }
1247
1248         if (!error && (mod->usecount > 0)) {
1249                 if (force)
1250                         ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
1251                                 resource_name, mod->usecount);
1252                 else {
1253                         ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
1254                                 mod->usecount);
1255                         error = 1;
1256                 }
1257         }
1258
1259         if (!error) {
1260                 /* Request any channels attached to the module to hangup. */
1261                 __ast_module_user_hangup_all(mod);
1262
1263                 ast_verb(1, "Unloading %s\n", mod->resource);
1264                 res = mod->info->unload();
1265                 if (res) {
1266                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
1267                         if (force <= AST_FORCE_FIRM) {
1268                                 error = 1;
1269                         } else {
1270                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
1271                         }
1272                 }
1273
1274                 if (!error) {
1275                         /*
1276                          * Request hangup on any channels that managed to get attached
1277                          * while we called the module unload function.
1278                          */
1279                         __ast_module_user_hangup_all(mod);
1280                         sched_yield();
1281                 }
1282         }
1283
1284         if (!error)
1285                 mod->flags.running = mod->flags.declined = 0;
1286
1287         AST_DLLIST_UNLOCK(&module_list);
1288
1289         if (!error) {
1290                 unload_dynamic_module(mod);
1291                 ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
1292                 ast_update_use_count();
1293                 publish_unload_message(resource_name, "Success");
1294         }
1295
1296         return res;
1297 }
1298
1299 static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type)
1300 {
1301         switch (type) {
1302         case AST_MODULE_HELPER_UNLOAD:
1303                 return !mod->usecount && mod->flags.running && !mod->flags.declined;
1304
1305         case AST_MODULE_HELPER_RELOAD:
1306                 return mod->flags.running && mod->info->reload;
1307
1308         case AST_MODULE_HELPER_RUNNING:
1309                 return mod->flags.running;
1310
1311         case AST_MODULE_HELPER_LOADED:
1312                 /* if we have a 'struct ast_module' then we're loaded. */
1313                 return 1;
1314         default:
1315                 /* This function is not called for AST_MODULE_HELPER_LOAD. */
1316                 /* Unknown ast_module_helper_type. Assume it doesn't match. */
1317                 ast_assert(0);
1318
1319                 return 0;
1320         }
1321 }
1322
1323 struct module_load_word {
1324         const char *word;
1325         size_t len;
1326         size_t moddir_len;
1327 };
1328
1329 static int module_load_helper_on_file(const char *dir_name, const char *filename, void *obj)
1330 {
1331         struct module_load_word *word = obj;
1332         struct ast_module *mod;
1333         char *filename_merged = NULL;
1334
1335         /* dir_name will never be shorter than word->moddir_len. */
1336         dir_name += word->moddir_len;
1337         if (!ast_strlen_zero(dir_name)) {
1338                 ast_assert(dir_name[0] == '/');
1339
1340                 dir_name += 1;
1341                 if (ast_asprintf(&filename_merged, "%s/%s", dir_name, filename) < 0) {
1342                         /* If we can't allocate the string just give up! */
1343                         return -1;
1344                 }
1345                 filename = filename_merged;
1346         }
1347
1348         if (!strncasecmp(filename, word->word, word->len)) {
1349                 /* Don't list files that are already loaded! */
1350                 mod = find_resource(filename, 0);
1351                 if (!mod || !mod->flags.running) {
1352                         ast_cli_completion_add(ast_strdup(filename));
1353                 }
1354         }
1355
1356         ast_free(filename_merged);
1357
1358         return 0;
1359 }
1360
1361 static void module_load_helper(const char *word)
1362 {
1363         struct module_load_word word_l = {
1364                 .word = word,
1365                 .len = strlen(word),
1366                 .moddir_len = strlen(ast_config_AST_MODULE_DIR),
1367         };
1368
1369         AST_DLLIST_LOCK(&module_list);
1370         ast_file_read_dirs(ast_config_AST_MODULE_DIR, module_load_helper_on_file, &word_l, -1);
1371         AST_DLLIST_UNLOCK(&module_list);
1372 }
1373
1374 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
1375 {
1376         struct ast_module *mod;
1377         int which = 0;
1378         int wordlen = strlen(word);
1379         char *ret = NULL;
1380
1381         if (pos != rpos) {
1382                 return NULL;
1383         }
1384
1385         if (type == AST_MODULE_HELPER_LOAD) {
1386                 module_load_helper(word);
1387
1388                 return NULL;
1389         }
1390
1391         AST_DLLIST_LOCK(&module_list);
1392         AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
1393                 if (!module_matches_helper_type(mod, type)) {
1394                         continue;
1395                 }
1396
1397                 if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) {
1398                         ret = ast_strdup(mod->resource);
1399                         break;
1400                 }
1401         }
1402         AST_DLLIST_UNLOCK(&module_list);
1403
1404         return ret;
1405 }
1406
1407 void ast_process_pending_reloads(void)
1408 {
1409         struct reload_queue_item *item;
1410
1411         modules_loaded = 1;
1412
1413         AST_LIST_LOCK(&reload_queue);
1414
1415         if (do_full_reload) {
1416                 do_full_reload = 0;
1417                 AST_LIST_UNLOCK(&reload_queue);
1418                 ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
1419                 ast_module_reload(NULL);
1420                 return;
1421         }
1422
1423         while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
1424                 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
1425                 ast_module_reload(item->module);
1426                 ast_free(item);
1427         }
1428
1429         AST_LIST_UNLOCK(&reload_queue);
1430 }
1431
1432 static void queue_reload_request(const char *module)
1433 {
1434         struct reload_queue_item *item;
1435
1436         AST_LIST_LOCK(&reload_queue);
1437
1438         if (do_full_reload) {
1439                 AST_LIST_UNLOCK(&reload_queue);
1440                 return;
1441         }
1442
1443         if (ast_strlen_zero(module)) {
1444                 /* A full reload request (when module is NULL) wipes out any previous
1445                    reload requests and causes the queue to ignore future ones */
1446                 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
1447                         ast_free(item);
1448                 }
1449                 do_full_reload = 1;
1450         } else {
1451                 /* No reason to add the same module twice */
1452                 AST_LIST_TRAVERSE(&reload_queue, item, entry) {
1453                         if (!strcasecmp(item->module, module)) {
1454                                 AST_LIST_UNLOCK(&reload_queue);
1455                                 return;
1456                         }
1457                 }
1458                 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
1459                 if (!item) {
1460                         ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
1461                         AST_LIST_UNLOCK(&reload_queue);
1462                         return;
1463                 }
1464                 strcpy(item->module, module);
1465                 AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
1466         }
1467         AST_LIST_UNLOCK(&reload_queue);
1468 }
1469
1470 /*!
1471  * \since 12
1472  * \internal
1473  * \brief Publish a \ref stasis message regarding the type.
1474  */
1475 static void publish_load_message_type(const char* type, const char *name, const char *status)
1476 {
1477         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1478         RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
1479         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1480         RAII_VAR(struct ast_json *, event_object, NULL, ast_json_unref);
1481
1482         ast_assert(type != NULL);
1483         ast_assert(!ast_strlen_zero(name));
1484         ast_assert(!ast_strlen_zero(status));
1485
1486         if (!ast_manager_get_generic_type()) {
1487                 return;
1488         }
1489
1490         event_object = ast_json_pack("{s:s, s:s}",
1491                         "Module", name,
1492                         "Status", status);
1493         json_object = ast_json_pack("{s:s, s:i, s:o}",
1494                         "type", type,
1495                         "class_type", EVENT_FLAG_SYSTEM,
1496                         "event", ast_json_ref(event_object));
1497         if (!json_object) {
1498                 return;
1499         }
1500
1501         payload = ast_json_payload_create(json_object);
1502         if (!payload) {
1503                 return;
1504         }
1505
1506         message = stasis_message_create(ast_manager_get_generic_type(), payload);
1507         if (!message) {
1508                 return;
1509         }
1510
1511         stasis_publish(ast_manager_get_topic(), message);
1512 }
1513
1514 static const char* loadresult2str(enum ast_module_load_result result)
1515 {
1516         int i;
1517         for (i = 0; i < ARRAY_LEN(load_results); i++) {
1518                 if (load_results[i].result == result) {
1519                         return load_results[i].name;
1520                 }
1521         }
1522
1523         ast_log(LOG_WARNING, "Failed to find correct load result status. result %d\n", result);
1524         return AST_MODULE_LOAD_UNKNOWN_STRING;
1525 }
1526
1527 /*!
1528  * \internal
1529  * \brief Publish a \ref stasis message regarding the load result
1530  */
1531 static void publish_load_message(const char *name, enum ast_module_load_result result)
1532 {
1533         const char *status;
1534
1535         status = loadresult2str(result);
1536
1537         publish_load_message_type("Load", name, status);
1538 }
1539
1540 /*!
1541  * \internal
1542  * \brief Publish a \ref stasis message regarding the unload result
1543  */
1544 static void publish_unload_message(const char *name, const char* status)
1545 {
1546         publish_load_message_type("Unload", name, status);
1547 }
1548
1549 /*!
1550  * \since 12
1551  * \internal
1552  * \brief Publish a \ref stasis message regarding the reload result
1553  */
1554 static void publish_reload_message(const char *name, enum ast_module_reload_result result)
1555 {
1556         char res_buffer[8];
1557
1558         snprintf(res_buffer, sizeof(res_buffer), "%u", result);
1559         publish_load_message_type("Reload", S_OR(name, "All"), res_buffer);
1560 }
1561
1562 enum ast_module_reload_result ast_module_reload(const char *name)
1563 {
1564         struct ast_module *cur;
1565         enum ast_module_reload_result res = AST_MODULE_RELOAD_NOT_FOUND;
1566         size_t name_baselen = name ? resource_name_baselen(name) : 0;
1567
1568         /* If we aren't fully booted, we just pretend we reloaded but we queue this
1569            up to run once we are booted up. */
1570         if (!modules_loaded) {
1571                 queue_reload_request(name);
1572                 res = AST_MODULE_RELOAD_QUEUED;
1573                 goto module_reload_exit;
1574         }
1575
1576         if (ast_mutex_trylock(&reloadlock)) {
1577                 ast_verb(3, "The previous reload command didn't finish yet\n");
1578                 res = AST_MODULE_RELOAD_IN_PROGRESS;
1579                 goto module_reload_exit;
1580         }
1581         ast_sd_notify("RELOAD=1");
1582         ast_lastreloadtime = ast_tvnow();
1583
1584         if (ast_opt_lock_confdir) {
1585                 int try;
1586                 int lockres;
1587                 for (try = 1, lockres = AST_LOCK_TIMEOUT; try < 6 && (lockres == AST_LOCK_TIMEOUT); try++) {
1588                         lockres = ast_lock_path(ast_config_AST_CONFIG_DIR);
1589                         if (lockres == AST_LOCK_TIMEOUT) {
1590                                 ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
1591                         }
1592                 }
1593                 if (lockres != AST_LOCK_SUCCESS) {
1594                         ast_log(AST_LOG_WARNING, "Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
1595                         res = AST_MODULE_RELOAD_ERROR;
1596                         goto module_reload_done;
1597                 }
1598         }
1599
1600         AST_DLLIST_LOCK(&module_list);
1601         AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
1602                 const struct ast_module_info *info = cur->info;
1603
1604                 if (name && resource_name_match(name, name_baselen, cur->resource)) {
1605                         continue;
1606                 }
1607
1608                 if (!cur->flags.running || cur->flags.declined) {
1609                         if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1610                                 res = AST_MODULE_RELOAD_UNINITIALIZED;
1611                         }
1612                         if (!name) {
1613                                 continue;
1614                         }
1615                         break;
1616                 }
1617
1618                 if (!info->reload) {    /* cannot be reloaded */
1619                         if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1620                                 res = AST_MODULE_RELOAD_NOT_IMPLEMENTED;
1621                         }
1622                         if (!name) {
1623                                 continue;
1624                         }
1625                         break;
1626                 }
1627                 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
1628                 if (info->reload() == AST_MODULE_LOAD_SUCCESS) {
1629                         res = AST_MODULE_RELOAD_SUCCESS;
1630                 } else if (res == AST_MODULE_RELOAD_NOT_FOUND) {
1631                         res = AST_MODULE_RELOAD_ERROR;
1632                 }
1633                 if (name) {
1634                         break;
1635                 }
1636         }
1637         AST_DLLIST_UNLOCK(&module_list);
1638
1639         if (ast_opt_lock_confdir) {
1640                 ast_unlock_path(ast_config_AST_CONFIG_DIR);
1641         }
1642 module_reload_done:
1643         ast_mutex_unlock(&reloadlock);
1644         ast_sd_notify("READY=1");
1645
1646 module_reload_exit:
1647         publish_reload_message(name, res);
1648         return res;
1649 }
1650
1651 static unsigned int inspect_module(const struct ast_module *mod)
1652 {
1653         if (!mod->info->description) {
1654                 module_load_error("Module '%s' does not provide a description.\n", mod->resource);
1655                 return 1;
1656         }
1657
1658         if (!mod->info->key) {
1659                 module_load_error("Module '%s' does not provide a license key.\n", mod->resource);
1660                 return 1;
1661         }
1662
1663         if (verify_key((unsigned char *) mod->info->key)) {
1664                 module_load_error("Module '%s' did not provide a valid license key.\n", mod->resource);
1665                 return 1;
1666         }
1667
1668         if (!ast_strlen_zero(mod->info->buildopt_sum) &&
1669             strcmp(buildopt_sum, mod->info->buildopt_sum)) {
1670                 module_load_error("Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
1671                 module_load_error("Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
1672                 return 1;
1673         }
1674
1675         return 0;
1676 }
1677
1678 static enum ast_module_load_result start_resource(struct ast_module *mod)
1679 {
1680         char tmp[256];
1681         enum ast_module_load_result res;
1682
1683         if (mod->flags.running) {
1684                 return AST_MODULE_LOAD_SUCCESS;
1685         }
1686
1687         if (!mod->info->load) {
1688                 mod->flags.declined = 1;
1689
1690                 return mod->flags.required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
1691         }
1692
1693         if (module_deps_reference(mod, NULL)) {
1694                 struct module_vector missing;
1695                 int i;
1696
1697                 AST_VECTOR_INIT(&missing, 0);
1698                 if (module_deps_missing_recursive(mod, &missing)) {
1699                         module_load_error("%s has one or more unknown dependencies.\n", mod->info->name);
1700                 }
1701                 for (i = 0; i < AST_VECTOR_SIZE(&missing); i++) {
1702                         module_load_error("%s loaded before dependency %s!\n", mod->info->name,
1703                                 AST_VECTOR_GET(&missing, i)->info->name);
1704                 }
1705                 AST_VECTOR_FREE(&missing);
1706
1707                 return AST_MODULE_LOAD_DECLINE;
1708         }
1709
1710         if (!ast_fully_booted) {
1711                 ast_verb(1, "Loading %s.\n", mod->resource);
1712         }
1713         res = mod->info->load();
1714
1715         switch (res) {
1716         case AST_MODULE_LOAD_SUCCESS:
1717                 if (!ast_fully_booted) {
1718                         ast_verb(2, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
1719                 } else {
1720                         ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
1721                 }
1722
1723                 mod->flags.running = 1;
1724                 if (mod->flags.builtin) {
1725                         /* Built-in modules cannot be unloaded. */
1726                         ast_module_shutdown_ref(mod);
1727                 }
1728
1729                 ast_update_use_count();
1730                 break;
1731         case AST_MODULE_LOAD_DECLINE:
1732                 mod->flags.declined = 1;
1733                 if (mod->flags.required) {
1734                         res = AST_MODULE_LOAD_FAILURE;
1735                 }
1736                 break;
1737         case AST_MODULE_LOAD_FAILURE:
1738                 mod->flags.declined = 1;
1739                 break;
1740         case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
1741         case AST_MODULE_LOAD_PRIORITY:
1742                 break;
1743         }
1744
1745         /* Make sure the newly started module is at the end of the list */
1746         AST_DLLIST_LOCK(&module_list);
1747         AST_DLLIST_REMOVE(&module_list, mod, entry);
1748         AST_DLLIST_INSERT_TAIL(&module_list, mod, entry);
1749         AST_DLLIST_UNLOCK(&module_list);
1750
1751         return res;
1752 }
1753
1754 /*! loads a resource based upon resource_name. If global_symbols_only is set
1755  *  only modules with global symbols will be loaded.
1756  *
1757  *  If the module_vector is provided (not NULL) the module is found and added to the
1758  *  vector without running the module's load() function.  By doing this, modules
1759  *  can be initialized later in order by priority and dependencies.
1760  *
1761  *  If the module_vector is not provided, the module's load function will be executed
1762  *  immediately */
1763 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int suppress_logging,
1764         struct module_vector *module_priorities, int required, int preload)
1765 {
1766         struct ast_module *mod;
1767         enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
1768
1769         if ((mod = find_resource(resource_name, 0))) {
1770                 if (mod->flags.running) {
1771                         ast_log(LOG_WARNING, "Module '%s' already loaded and running.\n", resource_name);
1772                         return AST_MODULE_LOAD_DECLINE;
1773                 }
1774         } else {
1775                 mod = load_dynamic_module(resource_name, suppress_logging);
1776                 if (!mod) {
1777                         return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
1778                 }
1779
1780                 if (module_post_register(mod)) {
1781                         goto prestart_error;
1782                 }
1783         }
1784
1785         mod->flags.required |= required;
1786         mod->flags.preload |= preload;
1787
1788         if (inspect_module(mod)) {
1789                 goto prestart_error;
1790         }
1791
1792         mod->flags.declined = 0;
1793
1794         if (module_priorities) {
1795                 if (AST_VECTOR_ADD_SORTED(module_priorities, mod, module_vector_cmp)) {
1796                         goto prestart_error;
1797                 }
1798                 res = AST_MODULE_LOAD_PRIORITY;
1799         } else {
1800                 res = start_resource(mod);
1801         }
1802
1803         if (ast_fully_booted && !ast_shutdown_final()) {
1804                 publish_load_message(resource_name, res);
1805         }
1806
1807         return res;
1808
1809 prestart_error:
1810         module_load_error("Module '%s' could not be loaded.\n", resource_name);
1811         unload_dynamic_module(mod);
1812         res = required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
1813         if (ast_fully_booted && !ast_shutdown_final()) {
1814                 publish_load_message(resource_name, res);
1815         }
1816         return res;
1817 }
1818
1819 int ast_load_resource(const char *resource_name)
1820 {
1821         int res;
1822         AST_DLLIST_LOCK(&module_list);
1823         res = load_resource(resource_name, 0, NULL, 0, 0);
1824         if (!res) {
1825                 ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
1826         }
1827         AST_DLLIST_UNLOCK(&module_list);
1828
1829         return res;
1830 }
1831
1832 struct load_order_entry {
1833         char *resource;
1834         int required;
1835         int preload;
1836         int builtin;
1837         AST_LIST_ENTRY(load_order_entry) entry;
1838 };
1839
1840 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
1841
1842 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required, int preload, int builtin)
1843 {
1844         struct load_order_entry *order;
1845         size_t resource_baselen = resource_name_baselen(resource);
1846
1847         AST_LIST_TRAVERSE(load_order, order, entry) {
1848                 if (!resource_name_match(resource, resource_baselen, order->resource)) {
1849                         /* Make sure we have the proper setting for the required field
1850                            (we might have both load= and required= lines in modules.conf) */
1851                         order->required |= required;
1852                         order->preload |= preload;
1853                         return order;
1854                 }
1855         }
1856
1857         order = ast_calloc(1, sizeof(*order));
1858         if (!order) {
1859                 return NULL;
1860         }
1861
1862         order->resource = ast_strdup(resource);
1863         if (!order->resource) {
1864                 ast_free(order);
1865
1866                 return NULL;
1867         }
1868         order->required = required;
1869         order->preload = preload;
1870         order->builtin = builtin;
1871         AST_LIST_INSERT_TAIL(load_order, order, entry);
1872
1873         return order;
1874 }
1875
1876 AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);
1877
1878 static enum ast_module_load_result start_resource_attempt(struct ast_module *mod, int *count)
1879 {
1880         enum ast_module_load_result lres;
1881
1882         /* Try to grab required references. */
1883         if (module_deps_reference(mod, NULL)) {
1884                 /* We're likely to retry so not an error. */
1885                 ast_debug(1, "Module %s is missing dependencies\n", mod->resource);
1886                 return AST_MODULE_LOAD_SKIP;
1887         }
1888
1889         lres = start_resource(mod);
1890         ast_debug(3, "START: %-46s[%d] %d\n",
1891                 mod->resource,
1892                 ast_test_flag(mod->info, AST_MODFLAG_LOAD_ORDER) ? mod->info->load_pri : AST_MODPRI_DEFAULT,
1893                 lres);
1894
1895         if (lres == AST_MODULE_LOAD_SUCCESS) {
1896                 (*count)++;
1897         } else if (lres == AST_MODULE_LOAD_FAILURE) {
1898                 module_load_error("*** Failed to load %smodule %s\n",
1899                         mod->flags.required ? "required " : "",
1900                         mod->resource);
1901         }
1902
1903         return lres;
1904 }
1905
1906 static int resource_list_recursive_decline(struct module_vector *resources, struct ast_module *mod,
1907         struct ast_str **printmissing)
1908 {
1909         struct module_vector missingdeps;
1910         struct ast_vector_const_string localdeps;
1911         int i = 0;
1912         int res = -1;
1913
1914         mod->flags.declined = 1;
1915         if (mod->flags.required) {
1916                 module_load_error("Required module %s declined to load.\n", ast_module_name(mod));
1917
1918                 return -2;
1919         }
1920
1921         module_load_error("%s declined to load.\n", ast_module_name(mod));
1922
1923         if (!*printmissing) {
1924                 *printmissing = ast_str_create(64);
1925                 if (!*printmissing) {
1926                         return -1;
1927                 }
1928         } else {
1929                 ast_str_reset(*printmissing);
1930         }
1931
1932         AST_VECTOR_INIT(&missingdeps, 0);
1933         AST_VECTOR_INIT(&localdeps, 0);
1934
1935         /* Decline everything that depends on 'mod' from resources so we can
1936          * print a concise list. */
1937         while (res != -2 && i < AST_VECTOR_SIZE(resources)) {
1938                 struct ast_module *dep = AST_VECTOR_GET(resources, i);
1939                 i++;
1940
1941                 AST_VECTOR_RESET(&missingdeps, AST_VECTOR_ELEM_CLEANUP_NOOP);
1942                 if (dep->flags.declined || module_deps_missing_recursive(dep, &missingdeps)) {
1943                         continue;
1944                 }
1945
1946                 if (AST_VECTOR_GET_CMP(&missingdeps, mod, AST_VECTOR_ELEM_DEFAULT_CMP)) {
1947                         dep->flags.declined = 1;
1948                         if (dep->flags.required) {
1949                                 module_load_error("Cannot load required module %s that depends on %s\n",
1950                                         ast_module_name(dep), ast_module_name(mod));
1951                                 res = -2;
1952                         } else {
1953                                 AST_VECTOR_APPEND(&localdeps, ast_module_name(dep));
1954                         }
1955                 }
1956         }
1957         AST_VECTOR_FREE(&missingdeps);
1958
1959         if (res != -2 && AST_VECTOR_SIZE(&localdeps)) {
1960                 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, printmissing);
1961                 module_load_error("Declined modules which depend on %s: %s\n",
1962                         ast_module_name(mod), ast_str_buffer(*printmissing));
1963         }
1964         AST_VECTOR_FREE(&localdeps);
1965
1966         return res;
1967 }
1968
1969 static int start_resource_list(struct module_vector *resources, int *mod_count)
1970 {
1971         struct module_vector missingdeps;
1972         int res = 0;
1973         struct ast_str *printmissing = NULL;
1974
1975         AST_VECTOR_INIT(&missingdeps, 0);
1976         while (res != -2 && AST_VECTOR_SIZE(resources)) {
1977                 struct ast_module *mod = AST_VECTOR_REMOVE(resources, 0, 1);
1978                 enum ast_module_load_result lres;
1979
1980                 if (mod->flags.declined) {
1981                         ast_debug(1, "%s is already declined, skipping\n", ast_module_name(mod));
1982                         continue;
1983                 }
1984
1985 retry_load:
1986                 lres = start_resource_attempt(mod, mod_count);
1987                 if (lres == AST_MODULE_LOAD_SUCCESS) {
1988                         /* No missing dependencies, successful. */
1989                         continue;
1990                 }
1991
1992                 if (lres == AST_MODULE_LOAD_FAILURE) {
1993                         res = -2;
1994                         break;
1995                 }
1996
1997                 if (lres == AST_MODULE_LOAD_DECLINE) {
1998                         res = resource_list_recursive_decline(resources, mod, &printmissing);
1999                         continue;
2000                 }
2001
2002                 if (module_deps_missing_recursive(mod, &missingdeps)) {
2003                         AST_VECTOR_RESET(&missingdeps, AST_VECTOR_ELEM_CLEANUP_NOOP);
2004                         module_load_error("Failed to resolve dependencies for %s\n", ast_module_name(mod));
2005                         res = resource_list_recursive_decline(resources, mod, &printmissing);
2006                         continue;
2007                 }
2008
2009                 if (!AST_VECTOR_SIZE(&missingdeps)) {
2010                         module_load_error("%s load function returned an invalid result. "
2011                                 "This is a bug in the module.\n", ast_module_name(mod));
2012                         /* Dependencies were met but the module failed to start and the result
2013                          * code was not AST_MODULE_LOAD_FAILURE or AST_MODULE_LOAD_DECLINE. */
2014                         res = resource_list_recursive_decline(resources, mod, &printmissing);
2015                         continue;
2016                 }
2017
2018                 ast_debug(1, "%s has %d dependencies\n",
2019                         ast_module_name(mod), (int)AST_VECTOR_SIZE(&missingdeps));
2020                 while (AST_VECTOR_SIZE(&missingdeps)) {
2021                         int didwork = 0;
2022                         int i = 0;
2023
2024                         while (i < AST_VECTOR_SIZE(&missingdeps)) {
2025                                 struct ast_module *dep = AST_VECTOR_GET(&missingdeps, i);
2026
2027                                 if (dep->flags.declined) {
2028                                         ast_debug(1, "%s tried to start %s but it's already declined\n",
2029                                                 ast_module_name(mod), ast_module_name(dep));
2030                                         i++;
2031                                         continue;
2032                                 }
2033
2034                                 ast_debug(1, "%s trying to start %s\n", ast_module_name(mod), ast_module_name(dep));
2035                                 lres = start_resource_attempt(dep, mod_count);
2036                                 if (lres == AST_MODULE_LOAD_SUCCESS) {
2037                                         ast_debug(1, "%s started %s\n", ast_module_name(mod), ast_module_name(dep));
2038                                         AST_VECTOR_REMOVE(&missingdeps, i, 1);
2039                                         AST_VECTOR_REMOVE_CMP_ORDERED(resources, dep,
2040                                                 AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP);
2041                                         didwork++;
2042                                         continue;
2043                                 }
2044
2045                                 if (lres == AST_MODULE_LOAD_FAILURE) {
2046                                         module_load_error("Failed to load %s.\n", ast_module_name(dep));
2047                                         res = -2;
2048                                         goto exitpoint;
2049                                 }
2050
2051                                 ast_debug(1, "%s failed to start %s\n", ast_module_name(mod), ast_module_name(dep));
2052                                 i++;
2053                         }
2054
2055                         if (!didwork) {
2056                                 break;
2057                         }
2058                 }
2059
2060                 if (AST_VECTOR_SIZE(&missingdeps)) {
2061                         if (!printmissing) {
2062                                 printmissing = ast_str_create(64);
2063                         } else {
2064                                 ast_str_reset(printmissing);
2065                         }
2066
2067                         if (printmissing) {
2068                                 struct ast_vector_const_string localdeps;
2069
2070                                 AST_VECTOR_INIT(&localdeps, 0);
2071                                 module_deps_reference(mod, &localdeps);
2072                                 AST_VECTOR_CALLBACK_VOID(&localdeps, STR_APPEND_TEXT, &printmissing);
2073                                 AST_VECTOR_FREE(&localdeps);
2074                         }
2075
2076                         module_load_error("Failed to load %s due to dependencies: %s.\n",
2077                                 ast_module_name(mod),
2078                                 printmissing ? ast_str_buffer(printmissing) : "allocation failure creating list");
2079                         res = resource_list_recursive_decline(resources, mod, &printmissing);
2080
2081                         AST_VECTOR_RESET(&missingdeps, AST_VECTOR_ELEM_CLEANUP_NOOP);
2082
2083                         continue;
2084                 }
2085
2086                 /* If we're here it means that we started with missingdeps and they're all loaded
2087                  * now.  It's impossible to reach this point a second time for the same module. */
2088                 goto retry_load;
2089         }
2090
2091 exitpoint:
2092         ast_free(printmissing);
2093         AST_VECTOR_FREE(&missingdeps);
2094
2095         return res;
2096 }
2097
2098 /*! loads modules in order by load_pri, updates mod_count
2099         \return -1 on failure to load module, -2 on failure to load required module, otherwise 0
2100 */
2101 static int load_resource_list(struct load_order *load_order, int *mod_count)
2102 {
2103         struct module_vector module_priorities;
2104         struct load_order_entry *order;
2105         int attempt = 0;
2106         int count = 0;
2107         int res = 0;
2108         int didwork;
2109         int lasttry = 0;
2110
2111         if (AST_VECTOR_INIT(&module_priorities, 500)) {
2112                 ast_log(LOG_ERROR, "Failed to initialize module loader.\n");
2113
2114                 return -1;
2115         }
2116
2117         while (res != -2) {
2118                 didwork = 0;
2119
2120                 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
2121                         enum ast_module_load_result lres;
2122
2123                         /* Suppress log messages unless this is the last pass */
2124                         lres = load_resource(order->resource, !lasttry, &module_priorities, order->required, order->preload);
2125                         ast_debug(3, "PASS %d: %-46s %d\n", attempt, order->resource, lres);
2126                         switch (lres) {
2127                         case AST_MODULE_LOAD_SUCCESS:
2128                         case AST_MODULE_LOAD_SKIP:
2129                                 /* We're supplying module_priorities so SUCCESS isn't possible but we
2130                                  * still have to test for it.  SKIP is only used when we try to start a
2131                                  * module that is missing dependencies. */
2132                                 break;
2133                         case AST_MODULE_LOAD_DECLINE:
2134                                 res = -1;
2135                                 break;
2136                         case AST_MODULE_LOAD_FAILURE:
2137                                 /* LOAD_FAILURE only happens for required modules */
2138                                 if (lasttry) {
2139                                         /* This run is just to print errors. */
2140                                         module_load_error("*** Failed to load module %s - Required\n", order->resource);
2141                                         fprintf(stderr, "*** Failed to load module %s - Required\n", order->resource);
2142                                         res =  -2;
2143                                 }
2144                                 break;
2145                         case AST_MODULE_LOAD_PRIORITY:
2146                                 /* load_resource worked and the module was added to module_priorities */
2147                                 AST_LIST_REMOVE_CURRENT(entry);
2148                                 ast_free(order->resource);
2149                                 ast_free(order);
2150                                 didwork = 1;
2151                                 break;
2152                         }
2153                 }
2154                 AST_LIST_TRAVERSE_SAFE_END;
2155
2156                 if (!didwork) {
2157                         if (lasttry) {
2158                                 break;
2159                         }
2160                         /* We know the next try is going to fail, it's only being performed
2161                          * so we can print errors. */
2162                         lasttry = 1;
2163                 }
2164                 attempt++;
2165         }
2166
2167         if (res != -2) {
2168                 res = start_resource_list(&module_priorities, &count);
2169         }
2170
2171         if (mod_count) {
2172                 *mod_count += count;
2173         }
2174         AST_VECTOR_FREE(&module_priorities);
2175
2176         return res;
2177 }
2178
2179 static int loader_builtin_init(struct load_order *load_order)
2180 {
2181         struct ast_module *mod;
2182
2183         /*
2184          * All built-in modules have registered the first time, now it's time to complete
2185          * the registration and add them to the priority list.
2186          */
2187         loader_ready = 1;
2188
2189         while ((resource_being_loaded = AST_DLLIST_REMOVE_HEAD(&builtin_module_list, entry))) {
2190                 /* ast_module_register doesn't finish when first run by built-in modules. */
2191                 ast_module_register(resource_being_loaded->info);
2192         }
2193
2194         /* Add all built-in modules to the load order. */
2195         AST_DLLIST_TRAVERSE(&module_list, mod, entry) {
2196                 if (!mod->flags.builtin) {
2197                         continue;
2198                 }
2199
2200                 /* Parse dependendencies from mod->info. */
2201                 if (module_post_register(mod)) {
2202                         return -1;
2203                 }
2204
2205                 /* Built-in modules are not preloaded, most have an early load priority. */
2206                 if (!add_to_load_order(mod->resource, load_order, 0, 0, 1)) {
2207                         return -1;
2208                 }
2209         }
2210
2211         return 0;
2212 }
2213
2214 static int loader_config_init(struct load_order *load_order)
2215 {
2216         int res = -1;
2217         struct load_order_entry *order;
2218         struct ast_config *cfg;
2219         struct ast_variable *v;
2220         struct ast_flags config_flags = { 0 };
2221
2222         cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
2223         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
2224                 ast_log(LOG_WARNING, "'%s' invalid or missing.\n", AST_MODULE_CONFIG);
2225
2226                 return -1;
2227         }
2228
2229         /* first, find all the modules we have been explicitly requested to load */
2230         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2231                 int required;
2232                 int preload = 0;
2233
2234                 if (!strncasecmp(v->name, "preload", strlen("preload"))) {
2235                         preload = 1;
2236                         if (!strcasecmp(v->name, "preload")) {
2237                                 required = 0;
2238                         } else if (!strcasecmp(v->name, "preload-require")) {
2239                                 required = 1;
2240                         } else {
2241                                 ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2242                                 goto done;
2243                         }
2244                 } else if (!strcasecmp(v->name, "load")) {
2245                         required = 0;
2246                 } else if (!strcasecmp(v->name, "require")) {
2247                         required = 1;
2248                 } else if (!strcasecmp(v->name, "noload") || !strcasecmp(v->name, "autoload")) {
2249                         continue;
2250                 } else {
2251                         ast_log(LOG_ERROR, "Unknown configuration option '%s'", v->name);
2252                         goto done;
2253                 }
2254
2255                 if (required) {
2256                         ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
2257                 }
2258
2259                 if (!add_to_load_order(v->value, load_order, required, preload, 0)) {
2260                         goto done;
2261                 }
2262         }
2263
2264         /* check if 'autoload' is on */
2265         if (ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
2266                 /* if we are allowed to load dynamic modules, scan the directory for
2267                    for all available modules and add them as well */
2268                 DIR *dir = opendir(ast_config_AST_MODULE_DIR);
2269                 struct dirent *dirent;
2270
2271                 if (dir) {
2272                         while ((dirent = readdir(dir))) {
2273                                 int ld = strlen(dirent->d_name);
2274
2275                                 /* Must end in .so to load it.  */
2276
2277                                 if (ld < 4)
2278                                         continue;
2279
2280                                 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
2281                                         continue;
2282
2283                                 /* if there is already a module by this name in the module_list,
2284                                    skip this file */
2285                                 if (find_resource(dirent->d_name, 0))
2286                                         continue;
2287
2288                                 if (!add_to_load_order(dirent->d_name, load_order, 0, 0, 0)) {
2289                                         closedir(dir);
2290                                         goto done;
2291                                 }
2292                         }
2293
2294                         closedir(dir);
2295                 } else {
2296                         ast_log(LOG_ERROR, "Unable to open modules directory '%s'.\n", ast_config_AST_MODULE_DIR);
2297                         goto done;
2298                 }
2299         }
2300
2301         /* now scan the config for any modules we are prohibited from loading and
2302            remove them from the load order */
2303         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
2304                 size_t baselen;
2305
2306                 if (strcasecmp(v->name, "noload")) {
2307                         continue;
2308                 }
2309
2310                 baselen = resource_name_baselen(v->value);
2311                 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
2312                         if (!resource_name_match(v->value, baselen, order->resource)) {
2313                                 if (order->builtin) {
2314                                         ast_log(LOG_ERROR, "%s is a built-in module, you cannot specify 'noload'.\n", v->value);
2315                                         goto done;
2316                                 }
2317
2318                                 if (order->required) {
2319                                         ast_log(LOG_ERROR, "%s is configured with '%s' and 'noload', this is impossible.\n",
2320                                                 v->value, order->preload ? "preload-require" : "require");
2321                                         goto done;
2322                                 }
2323                                 AST_LIST_REMOVE_CURRENT(entry);
2324                                 ast_free(order->resource);
2325                                 ast_free(order);
2326                         }
2327                 }
2328                 AST_LIST_TRAVERSE_SAFE_END;
2329         }
2330
2331         res = 0;
2332 done:
2333         ast_config_destroy(cfg);
2334
2335         return res;
2336 }
2337
2338 int load_modules(void)
2339 {
2340         struct load_order_entry *order;
2341         unsigned int load_count;
2342         struct load_order load_order;
2343         int res = 0;
2344         int modulecount = 0;
2345         int i;
2346         struct ast_module *cur;
2347 #ifdef AST_XML_DOCS
2348         struct ast_str *warning_msg;
2349         char deprecated_in[33];
2350         char removed_in[33];
2351         char replacement[129];
2352 #endif
2353         struct timeval start_time = ast_tvnow();
2354         struct timeval end_time;
2355         int64_t usElapsed;
2356
2357         ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
2358
2359 #if defined(HAVE_PERMANENT_DLOPEN)
2360         info_list = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,
2361                 info_list_obj_cmp_fn); /* must not be cleaned at shutdown */
2362         if (!info_list) {
2363                 fprintf(stderr, "Module info list allocation failure.\n");
2364                 return 1;
2365         }
2366 #endif
2367
2368         AST_LIST_HEAD_INIT_NOLOCK(&load_order);
2369         AST_DLLIST_LOCK(&module_list);
2370
2371         AST_VECTOR_INIT(&startup_errors, 0);
2372         startup_error_builder = ast_str_create(64);
2373
2374         res = loader_builtin_init(&load_order);
2375         if (res) {
2376                 goto done;
2377         }
2378
2379         res = loader_config_init(&load_order);
2380         if (res) {
2381                 goto done;
2382         }
2383
2384         load_count = 0;
2385         AST_LIST_TRAVERSE(&load_order, order, entry)
2386                 load_count++;
2387
2388         if (load_count)
2389                 ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);
2390
2391         res = load_resource_list(&load_order, &modulecount);
2392         if (res == -1) {
2393                 ast_log(LOG_WARNING, "Some non-required modules failed to load.\n");
2394                 res = 0;
2395         }
2396
2397 done:
2398         while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
2399                 ast_free(order->resource);
2400                 ast_free(order);
2401         }
2402
2403 #ifdef AST_XML_DOCS
2404         warning_msg = ast_str_create(512);
2405 #endif
2406
2407         AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
2408 #ifdef AST_XML_DOCS
2409                 char *mod_name = NULL;
2410                 struct ast_xml_xpath_results *results;
2411 #endif
2412
2413                 if (!cur->flags.running || cur->flags.declined) {
2414                         continue;
2415                 }
2416
2417 #ifdef AST_XML_DOCS
2418                 mod_name = get_name_from_resource(cur->resource);
2419                 if (!warning_msg || !mod_name) {
2420                         /* If we can't allocate memory, we have bigger issues */
2421                         ast_free(mod_name);
2422                         continue;
2423                 }
2424
2425                 /* Clear out the previous values */
2426                 deprecated_in[0] = removed_in[0] = replacement[0] = 0;
2427
2428                 results = ast_xmldoc_query("/docs/module[@name='%s']", mod_name);
2429                 if (results) {
2430                         struct ast_xml_node *deprecated_node, *removed_node, *replacement_node;
2431                         struct ast_xml_node *metadata_nodes = ast_xml_node_get_children(ast_xml_xpath_get_first_result(results));
2432
2433                         deprecated_node = ast_xml_find_element(metadata_nodes, "deprecated_in", NULL, NULL);
2434                         if (deprecated_node) {
2435                                 const char *result_tmp = ast_xml_get_text(deprecated_node);
2436                                 if (!ast_strlen_zero(result_tmp)) {
2437                                         ast_copy_string(deprecated_in, result_tmp, sizeof(deprecated_in));
2438                                 }
2439                         }
2440
2441                         removed_node = ast_xml_find_element(metadata_nodes, "removed_in", NULL, NULL);
2442                         if (removed_node) {
2443                                 const char *result_tmp = ast_xml_get_text(removed_node);
2444                                 if (!ast_strlen_zero(result_tmp)) {
2445                                         ast_copy_string(removed_in, result_tmp, sizeof(removed_in));
2446                                 }
2447                         }
2448
2449                         replacement_node = ast_xml_find_element(metadata_nodes, "replacement", NULL, NULL);
2450                         if (replacement_node) {
2451                                 const char *result_tmp = ast_xml_get_text(replacement_node);
2452                                 if (!ast_strlen_zero(result_tmp)) {
2453                                         ast_copy_string(replacement, result_tmp, sizeof(replacement));
2454                                 }
2455                         }
2456
2457                         ast_xml_xpath_results_free(results);
2458                 }
2459
2460                 ast_str_reset(warning_msg);
2461
2462                 if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED || !ast_strlen_zero(deprecated_in)
2463                         || !ast_strlen_zero(removed_in) || !ast_strlen_zero(replacement)) {
2464                         int already_butted = 0;
2465
2466                         ast_str_append(&warning_msg, -1, "Module '%s' has been loaded", mod_name);
2467                         if (!ast_strlen_zero(deprecated_in)) {
2468                                 ast_str_append(&warning_msg, -1, " but %s deprecated in Asterisk version %s",
2469                                          cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED ? "was" : "will be", deprecated_in);
2470                                 already_butted = 1;
2471                         }
2472
2473                         if (!ast_strlen_zero(removed_in)) {
2474                                 ast_str_append(&warning_msg, -1, " %s will be removed in Asterisk version %s", already_butted ? "and" : "but", removed_in);
2475                         } else {
2476                                 ast_str_append(&warning_msg, -1, " %s may be removed in a future release", already_butted ? "and" : "but");
2477                         }
2478
2479                         ast_str_append(&warning_msg, -1, ".");
2480
2481                         if (!ast_strlen_zero(replacement)) {
2482                                 ast_str_append(&warning_msg, -1, " Its replacement is '%s'.", replacement);
2483                         }
2484                 }
2485
2486                 if (ast_str_strlen(warning_msg)) {
2487                         ast_log(LOG_WARNING, "%s\n", ast_str_buffer(warning_msg));
2488                 }
2489
2490                 ast_free(mod_name);
2491 #else
2492                 if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED) {
2493                         ast_log(LOG_WARNING, "The deprecated module '%s' has been loaded and is running, it may be removed in a future version\n", cur->resource);
2494                 }
2495 #endif
2496         }
2497
2498 #ifdef AST_XML_DOCS
2499         ast_free(warning_msg);
2500 #endif
2501
2502         AST_DLLIST_UNLOCK(&module_list);
2503
2504
2505         for (i = 0; i < AST_VECTOR_SIZE(&startup_errors); i++) {
2506                 char *str = AST_VECTOR_GET(&startup_errors, i);
2507
2508                 ast_log(LOG_ERROR, "%s", str);
2509                 ast_free(str);
2510         }
2511         AST_VECTOR_FREE(&startup_errors);
2512
2513         ast_free(startup_error_builder);
2514         startup_error_builder = NULL;
2515
2516         end_time = ast_tvnow();
2517         usElapsed = ast_tvdiff_us(end_time, start_time);
2518
2519 #ifdef AST_XML_DOCS
2520         ast_debug(1, "Loader time with AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2521 #else
2522         ast_debug(1, "Loader time without AST_XML_DOCS: %" PRId64 ".%06" PRId64 "\n", usElapsed / 1000000, usElapsed % 1000000);
2523 #endif
2524
2525         return res;
2526 }
2527
2528 void ast_update_use_count(void)
2529 {
2530         /* Notify any module monitors that the use count for a
2531            resource has changed */
2532         struct loadupdate *m;
2533
2534         AST_LIST_LOCK(&updaters);
2535         AST_LIST_TRAVERSE(&updaters, m, entry)
2536                 m->updater();
2537         AST_LIST_UNLOCK(&updaters);
2538 }
2539
2540 /*!
2541  * \internal
2542  * \brief Build an alpha sorted list of modules.
2543  *
2544  * \param alpha_module_list Pointer to uninitialized module_vector.
2545  *
2546  * This function always initializes alpha_module_list.
2547  *
2548  * \pre module_list must be locked.
2549  */
2550 static int alpha_module_list_create(struct module_vector *alpha_module_list)
2551 {
2552         struct ast_module *cur;
2553
2554         if (AST_VECTOR_INIT(alpha_module_list, 32)) {
2555                 return -1;
2556         }
2557
2558         AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
2559                 if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
2560                         return -1;
2561                 }
2562         }
2563
2564         return 0;
2565 }
2566
2567 int ast_update_module_list(int (*modentry)(const char *module, const char *description,
2568                                            int usecnt, const char *status, const char *like,
2569                                                                                    enum ast_module_support_level support_level),
2570                            const char *like)
2571 {
2572         int total_mod_loaded = 0;
2573         struct module_vector alpha_module_list;
2574
2575         AST_DLLIST_LOCK(&module_list);
2576
2577         if (!alpha_module_list_create(&alpha_module_list)) {
2578                 int idx;
2579
2580                 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2581                         struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2582
2583                         total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2584                                 cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
2585                 }
2586         }
2587
2588         AST_DLLIST_UNLOCK(&module_list);
2589         AST_VECTOR_FREE(&alpha_module_list);
2590
2591         return total_mod_loaded;
2592 }
2593
2594 int ast_update_module_list_data(int (*modentry)(const char *module, const char *description,
2595                                                 int usecnt, const char *status, const char *like,
2596                                                 enum ast_module_support_level support_level,
2597                                                 void *data),
2598                                 const char *like, void *data)
2599 {
2600         int total_mod_loaded = 0;
2601         struct module_vector alpha_module_list;
2602
2603         AST_DLLIST_LOCK(&module_list);
2604
2605         if (!alpha_module_list_create(&alpha_module_list)) {
2606                 int idx;
2607
2608                 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2609                         struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2610
2611                         total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
2612                                 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
2613                 }
2614         }
2615
2616         AST_DLLIST_UNLOCK(&module_list);
2617         AST_VECTOR_FREE(&alpha_module_list);
2618
2619         return total_mod_loaded;
2620 }
2621
2622 int ast_update_module_list_condition(int (*modentry)(const char *module, const char *description,
2623                                                      int usecnt, const char *status,
2624                                                      const char *like,
2625                                                      enum ast_module_support_level support_level,
2626                                                      void *data, const char *condition),
2627                                      const char *like, void *data, const char *condition)
2628 {
2629         int conditions_met = 0;
2630         struct module_vector alpha_module_list;
2631
2632         AST_DLLIST_LOCK(&module_list);
2633
2634         if (!alpha_module_list_create(&alpha_module_list)) {
2635                 int idx;
2636
2637                 for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
2638                         struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
2639
2640                         conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
2641                                 cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
2642                                 condition);
2643                 }
2644         }
2645
2646         AST_DLLIST_UNLOCK(&module_list);
2647         AST_VECTOR_FREE(&alpha_module_list);
2648
2649         return conditions_met;
2650 }
2651
2652 /*! \brief Check if module exists */
2653 int ast_module_check(const char *name)
2654 {
2655         struct ast_module *cur;
2656
2657         if (ast_strlen_zero(name))
2658                 return 0;       /* FALSE */
2659
2660         cur = find_resource(name, 1);
2661
2662         return (cur != NULL);
2663 }
2664
2665
2666 int ast_loader_register(int (*v)(void))
2667 {
2668         struct loadupdate *tmp;
2669
2670         if (!(tmp = ast_malloc(sizeof(*tmp))))
2671                 return -1;
2672
2673         tmp->updater = v;
2674         AST_LIST_LOCK(&updaters);
2675         AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
2676         AST_LIST_UNLOCK(&updaters);
2677
2678         return 0;
2679 }
2680
2681 int ast_loader_unregister(int (*v)(void))
2682 {
2683         struct loadupdate *cur;
2684
2685         AST_LIST_LOCK(&updaters);
2686         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
2687                 if (cur->updater == v)  {
2688                         AST_LIST_REMOVE_CURRENT(entry);
2689                         break;
2690                 }
2691         }
2692         AST_LIST_TRAVERSE_SAFE_END;
2693         AST_LIST_UNLOCK(&updaters);
2694
2695         return cur ? 0 : -1;
2696 }
2697
2698 struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, int line, const char *func)
2699 {
2700         if (!mod) {
2701                 return NULL;
2702         }
2703
2704         if (mod->ref_debug) {
2705                 __ao2_ref(mod->ref_debug, +1, "", file, line, func);
2706         }
2707
2708         ast_atomic_fetchadd_int(&mod->usecount, +1);
2709         ast_update_use_count();
2710
2711         return mod;
2712 }
2713
2714 struct ast_module *__ast_module_running_ref(struct ast_module *mod,
2715         const char *file, int line, const char *func)
2716 {
2717         if (!mod || !mod->flags.running) {
2718                 return NULL;
2719         }
2720
2721         return __ast_module_ref(mod, file, line, func);
2722 }
2723
2724 void __ast_module_shutdown_ref(struct ast_module *mod, const char *file, int line, const char *func)
2725 {
2726         if (!mod || mod->flags.keepuntilshutdown) {
2727                 return;
2728         }
2729
2730         __ast_module_ref(mod, file, line, func);
2731         mod->flags.keepuntilshutdown = 1;
2732 }
2733
2734 void __ast_module_unref(struct ast_module *mod, const char *file, int line, const char *func)
2735 {
2736         if (!mod) {
2737                 return;
2738         }
2739
2740         if (mod->ref_debug) {
2741                 __ao2_ref(mod->ref_debug, -1, "", file, line, func);
2742         }
2743
2744         ast_atomic_fetchadd_int(&mod->usecount, -1);
2745         ast_update_use_count();
2746 }
2747
2748 const char *support_level_map [] = {
2749         [AST_MODULE_SUPPORT_UNKNOWN] = "unknown",
2750         [AST_MODULE_SUPPORT_CORE] = "core",
2751         [AST_MODULE_SUPPORT_EXTENDED] = "extended",
2752         [AST_MODULE_SUPPORT_DEPRECATED] = "deprecated",
2753 };
2754
2755 const char *ast_module_support_level_to_string(enum ast_module_support_level support_level)
2756 {
2757         return support_level_map[support_level];
2758 }