#include "asterisk.h"
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/enum.h"
#include "asterisk/rtp.h"
#include "asterisk/http.h"
#include "asterisk/lock.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | ast_module |
struct | ast_module_user |
struct | load_order_entry |
struct | loadupdate |
struct | reload_classes |
Defines | |
#define | RTLD_NOW 0 |
Functions | |
ast_module_user * | __ast_module_user_add (struct ast_module *mod, struct ast_channel *chan) |
void | __ast_module_user_hangup_all (struct ast_module *mod) |
void | __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u) |
static struct load_order_entry * | add_to_load_order (const char *resource, struct load_order *load_order) |
AST_LIST_HEAD (module_user_list, ast_module_user) | |
AST_LIST_HEAD_NOLOCK (load_order, load_order_entry) | |
static | AST_LIST_HEAD_STATIC (updaters, loadupdate) |
static | AST_LIST_HEAD_STATIC (module_list, ast_module) |
int | ast_load_resource (const char *resource_name) |
Load a module. | |
int | ast_loader_register (int(*v)(void)) |
Add a procedure to be run when modules have been updated. | |
int | ast_loader_unregister (int(*v)(void)) |
Remove a procedure to be run when modules are updated. | |
char * | ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, int needsreload) |
Match modules names for the Asterisk cli. | |
ast_module * | ast_module_ref (struct ast_module *mod) |
void | ast_module_register (const struct ast_module_info *info) |
int | ast_module_reload (const char *name) |
Reload asterisk modules. | |
void | ast_module_shutdown (void) |
Run the unload() callback for all loaded modules. | |
void | ast_module_unref (struct ast_module *mod) |
void | ast_module_unregister (const struct ast_module_info *info) |
AST_MUTEX_DEFINE_STATIC (reloadlock) | |
int | ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force) |
Unload a module. | |
int | ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like) |
Ask for a list of modules, descriptions, and use counts. | |
void | ast_update_use_count (void) |
Notify when usecount has been changed. | |
static struct ast_module * | find_resource (const char *resource, int do_lock) |
static unsigned int | inspect_module (const struct ast_module *mod) |
static int | key_matches (const unsigned char *key1, const unsigned char *key2) |
int | load_modules (unsigned int preload_only) |
static enum ast_module_load_result | load_resource (const char *resource_name, unsigned int global_symbols_only) |
static int | printdigest (const unsigned char *d) |
static int | resource_name_match (const char *name1_in, const char *name2_in) |
static int | translate_module_name (char *oldname, char *newname) |
static int | verify_key (const unsigned char *key) |
Variables | |
static char | buildopt_sum [33] = AST_BUILDOPT_SUM |
static unsigned int | embedding = 1 |
static unsigned char | expected_key [] |
ast_module * | resource_being_loaded |
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
Definition in file loader.c.
struct ast_module_user* __ast_module_user_add | ( | struct ast_module * | mod, | |
struct ast_channel * | chan | |||
) |
Definition at line 175 of file loader.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::chan, ast_module::usecount, and ast_module::users.
00177 { 00178 struct ast_module_user *u = ast_calloc(1, sizeof(*u)); 00179 00180 if (!u) 00181 return NULL; 00182 00183 u->chan = chan; 00184 00185 AST_LIST_LOCK(&mod->users); 00186 AST_LIST_INSERT_HEAD(&mod->users, u, entry); 00187 AST_LIST_UNLOCK(&mod->users); 00188 00189 ast_atomic_fetchadd_int(&mod->usecount, +1); 00190 00191 ast_update_use_count(); 00192 00193 return u; 00194 }
void __ast_module_user_hangup_all | ( | struct ast_module * | mod | ) |
Definition at line 207 of file loader.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_update_use_count(), ast_module_user::chan, free, ast_module::usecount, and ast_module::users.
Referenced by ast_unload_resource().
00208 { 00209 struct ast_module_user *u; 00210 00211 AST_LIST_LOCK(&mod->users); 00212 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) { 00213 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); 00214 ast_atomic_fetchadd_int(&mod->usecount, -1); 00215 free(u); 00216 } 00217 AST_LIST_UNLOCK(&mod->users); 00218 00219 ast_update_use_count(); 00220 }
void __ast_module_user_remove | ( | struct ast_module * | mod, | |
struct ast_module_user * | u | |||
) |
Definition at line 196 of file loader.c.
References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), free, ast_module::usecount, and ast_module::users.
00197 { 00198 AST_LIST_LOCK(&mod->users); 00199 AST_LIST_REMOVE(&mod->users, u, entry); 00200 AST_LIST_UNLOCK(&mod->users); 00201 ast_atomic_fetchadd_int(&mod->usecount, -1); 00202 free(u); 00203 00204 ast_update_use_count(); 00205 }
static struct load_order_entry* add_to_load_order | ( | const char * | resource, | |
struct load_order * | load_order | |||
) | [static] |
Definition at line 723 of file loader.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, load_order_entry::resource, and resource_name_match().
Referenced by load_modules().
00724 { 00725 struct load_order_entry *order; 00726 00727 AST_LIST_TRAVERSE(load_order, order, entry) { 00728 if (!resource_name_match(order->resource, resource)) 00729 return NULL; 00730 } 00731 00732 if (!(order = ast_calloc(1, sizeof(*order)))) 00733 return NULL; 00734 00735 order->resource = ast_strdup(resource); 00736 AST_LIST_INSERT_TAIL(load_order, order, entry); 00737 00738 return order; 00739 }
AST_LIST_HEAD | ( | module_user_list | , | |
ast_module_user | ||||
) |
AST_LIST_HEAD_NOLOCK | ( | load_order | , | |
load_order_entry | ||||
) |
static AST_LIST_HEAD_STATIC | ( | updaters | , | |
loadupdate | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | module_list | , | |
ast_module | ||||
) | [static] |
int ast_load_resource | ( | const char * | resource_name | ) |
Load a module.
resource_name | The name of the module to load. |
Definition at line 707 of file loader.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().
Referenced by file_ok_sel(), handle_load(), handle_load_deprecated(), and reload().
00708 { 00709 AST_LIST_LOCK(&module_list); 00710 load_resource(resource_name, 0); 00711 AST_LIST_UNLOCK(&module_list); 00712 00713 return 0; 00714 }
int ast_loader_register | ( | int(*)(void) | updater | ) |
Add a procedure to be run when modules have been updated.
updater | The function to run when modules have been updated. |
Definition at line 957 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
00958 { 00959 struct loadupdate *tmp; 00960 00961 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00962 return -1; 00963 00964 tmp->updater = v; 00965 AST_LIST_LOCK(&updaters); 00966 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 00967 AST_LIST_UNLOCK(&updaters); 00968 00969 return 0; 00970 }
int ast_loader_unregister | ( | int(*)(void) | updater | ) |
Remove a procedure to be run when modules are updated.
updater | The updater function to unregister. |
Definition at line 972 of file loader.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, and loadupdate::updater.
Referenced by exit_now().
00973 { 00974 struct loadupdate *cur; 00975 00976 AST_LIST_LOCK(&updaters); 00977 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 00978 if (cur->updater == v) { 00979 AST_LIST_REMOVE_CURRENT(&updaters, entry); 00980 break; 00981 } 00982 } 00983 AST_LIST_TRAVERSE_SAFE_END; 00984 AST_LIST_UNLOCK(&updaters); 00985 00986 return cur ? 0 : -1; 00987 }
char* ast_module_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos, | |||
int | needsreload | |||
) |
Match modules names for the Asterisk cli.
line | Unused by this function, but this should be the line we are matching. | |
word | The partial name to match. | |
pos | The position the word we are completing is in. | |
state | The possible match to return. | |
rpos | The position we should be matching. This should be the same as pos. | |
needsreload | This should be 1 if we need to reload this module and 0 otherwise. This function will only return modules that are reloadble if this is 1. |
Definition at line 515 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module::info, name, ast_module_info::reload, and strdup.
Referenced by complete_mod_2(), complete_mod_3(), complete_mod_3_nr(), complete_mod_4(), and load_module().
00516 { 00517 struct ast_module *cur; 00518 int i, which=0, l = strlen(word); 00519 char *ret = NULL; 00520 00521 if (pos != rpos) 00522 return NULL; 00523 00524 AST_LIST_LOCK(&module_list); 00525 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00526 if (!strncasecmp(word, cur->resource, l) && 00527 (cur->info->reload || !needsreload) && 00528 ++which > state) { 00529 ret = strdup(cur->resource); 00530 break; 00531 } 00532 } 00533 AST_LIST_UNLOCK(&module_list); 00534 00535 if (!ret) { 00536 for (i=0; !ret && reload_classes[i].name; i++) { 00537 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00538 ret = strdup(reload_classes[i].name); 00539 } 00540 } 00541 00542 return ret; 00543 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 989 of file loader.c.
References ast_update_use_count(), and ast_module::usecount.
Referenced by __oh323_new(), alsa_new(), ast_iax2_new(), cli_audio_convert(), cli_audio_convert_deprecated(), complete_orig(), dahdi_new(), features_new(), fn_wrapper(), gtalk_new(), handle_orig(), mgcp_new(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_new(), and skinny_new().
00990 { 00991 ast_atomic_fetchadd_int(&mod->usecount, +1); 00992 ast_update_use_count(); 00993 00994 return mod; 00995 }
void ast_module_register | ( | const struct ast_module_info * | info | ) |
Definition at line 113 of file loader.c.
References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedding, ast_module::info, ast_module_info::name, resource_being_loaded, ast_module_info::self, and ast_module::users.
00114 { 00115 struct ast_module *mod; 00116 00117 if (embedding) { 00118 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1))) 00119 return; 00120 strcpy(mod->resource, info->name); 00121 } else { 00122 mod = resource_being_loaded; 00123 } 00124 00125 mod->info = info; 00126 AST_LIST_HEAD_INIT(&mod->users); 00127 00128 /* during startup, before the loader has been initialized, 00129 there are no threads, so there is no need to take the lock 00130 on this list to manipulate it. it is also possible that it 00131 might be unsafe to use the list lock at that point... so 00132 let's avoid it altogether 00133 */ 00134 if (!embedding) 00135 AST_LIST_LOCK(&module_list); 00136 00137 /* it is paramount that the new entry be placed at the tail of 00138 the list, otherwise the code that uses dlopen() to load 00139 dynamic modules won't be able to find out if the module it 00140 just opened was registered or failed to load 00141 */ 00142 AST_LIST_INSERT_TAIL(&module_list, mod, entry); 00143 00144 if (!embedding) 00145 AST_LIST_UNLOCK(&module_list); 00146 00147 /* give the module a copy of its own handle, for later use in registrations and the like */ 00148 *((struct ast_module **) &(info->self)) = mod; 00149 }
int ast_module_reload | ( | const char * | name | ) |
Reload asterisk modules.
name | the name of the module to reload |
Definition at line 545 of file loader.c.
References ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, LOG_NOTICE, option_verbose, ast_module_info::reload, resource_name_match(), ast_module::running, and VERBOSE_PREFIX_3.
Referenced by action_updateconfig(), handle_reload(), handle_reload_deprecated(), and monitor_sig_flags().
00546 { 00547 struct ast_module *cur; 00548 int res = 0; /* return value. 0 = not found, others, see below */ 00549 int i; 00550 00551 if (ast_mutex_trylock(&reloadlock)) { 00552 ast_verbose("The previous reload command didn't finish yet\n"); 00553 return -1; /* reload already in progress */ 00554 } 00555 ast_lastreloadtime = time(NULL); 00556 00557 /* Call "predefined" reload here first */ 00558 for (i = 0; reload_classes[i].name; i++) { 00559 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00560 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00561 res = 2; /* found and reloaded */ 00562 } 00563 } 00564 00565 if (name && res) { 00566 ast_mutex_unlock(&reloadlock); 00567 return res; 00568 } 00569 00570 AST_LIST_LOCK(&module_list); 00571 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00572 const struct ast_module_info *info = cur->info; 00573 00574 if (name && resource_name_match(name, cur->resource)) 00575 continue; 00576 00577 if (!cur->flags.running || cur->flags.declined) { 00578 if (!name) 00579 continue; 00580 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00581 "Before reloading the module, you must run \"module load %s\" " 00582 "and fix whatever is preventing the module from being initialized.\n", 00583 name, name); 00584 res = 2; /* Don't report that the module was not found */ 00585 break; 00586 } 00587 00588 if (!info->reload) { /* cannot be reloaded */ 00589 if (res < 1) /* store result if possible */ 00590 res = 1; /* 1 = no reload() method */ 00591 continue; 00592 } 00593 00594 res = 2; 00595 if (option_verbose > 2) 00596 ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description); 00597 info->reload(); 00598 } 00599 AST_LIST_UNLOCK(&module_list); 00600 00601 ast_mutex_unlock(&reloadlock); 00602 00603 return res; 00604 }
void ast_module_shutdown | ( | void | ) |
Run the unload() callback for all loaded modules.
This function should be called when Asterisk is shutting down gracefully.
Definition at line 429 of file loader.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free, ast_module::info, ast_module_info::unload, and ast_module::users.
Referenced by quit_handler().
00430 { 00431 struct ast_module *mod; 00432 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module); 00433 00434 /* We have to call the unload() callbacks in reverse order that the modules 00435 * exist in the module list so it is the reverse order of how they were 00436 * loaded. */ 00437 00438 AST_LIST_LOCK(&module_list); 00439 while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry))) 00440 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry); 00441 AST_LIST_UNLOCK(&module_list); 00442 00443 while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) { 00444 if (mod->info->unload) 00445 mod->info->unload(); 00446 /* Since this should only be called when shutting down "gracefully", 00447 * all channels should be down before we get to this point, meaning 00448 * there will be no module users left. */ 00449 AST_LIST_HEAD_DESTROY(&mod->users); 00450 free(mod); 00451 } 00452 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 997 of file loader.c.
References ast_update_use_count(), and ast_module::usecount.
Referenced by alsa_hangup(), ast_closestream(), ast_smdi_interface_destroy(), cli_audio_convert(), cli_audio_convert_deprecated(), complete_orig(), dahdi_destroy_channel_bynum(), dahdi_hangup(), destroy(), gtalk_hangup(), handle_orig(), iax2_predestroy(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), and sip_hangup().
00998 { 00999 ast_atomic_fetchadd_int(&mod->usecount, -1); 01000 ast_update_use_count(); 01001 }
void ast_module_unregister | ( | const struct ast_module_info * | info | ) |
Definition at line 151 of file loader.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, free, ast_module::info, and ast_module::users.
00152 { 00153 struct ast_module *mod = NULL; 00154 00155 /* it is assumed that the users list in the module structure 00156 will already be empty, or we cannot have gotten to this 00157 point 00158 */ 00159 AST_LIST_LOCK(&module_list); 00160 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00161 if (mod->info == info) { 00162 AST_LIST_REMOVE_CURRENT(&module_list, entry); 00163 break; 00164 } 00165 } 00166 AST_LIST_TRAVERSE_SAFE_END; 00167 AST_LIST_UNLOCK(&module_list); 00168 00169 if (mod) { 00170 AST_LIST_HEAD_DESTROY(&mod->users); 00171 free(mod); 00172 } 00173 }
AST_MUTEX_DEFINE_STATIC | ( | reloadlock | ) |
int ast_unload_resource | ( | const char * | resource_name, | |
enum | ast_module_unload_mode | |||
) |
Unload a module.
resource_name | The name of the module to unload. | |
ast_module_unload_mode | The force flag. This should be set using one of the AST_FORCE flags. |
Definition at line 454 of file loader.c.
References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_update_use_count(), ast_module::declined, find_resource(), ast_module::flags, ast_module::lib, ast_module::running, and ast_module::usecount.
Referenced by exit_now(), handle_unload(), handle_unload_deprecated(), reload(), and remove_module().
00455 { 00456 struct ast_module *mod; 00457 int res = -1; 00458 int error = 0; 00459 00460 AST_LIST_LOCK(&module_list); 00461 00462 if (!(mod = find_resource(resource_name, 0))) { 00463 AST_LIST_UNLOCK(&module_list); 00464 return 0; 00465 } 00466 00467 if (!(mod->flags.running || mod->flags.declined)) 00468 error = 1; 00469 00470 if (!mod->lib) { 00471 ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n"); 00472 error = 1; 00473 } 00474 00475 if (!error && (mod->usecount > 0)) { 00476 if (force) 00477 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00478 resource_name, mod->usecount); 00479 else { 00480 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00481 mod->usecount); 00482 error = 1; 00483 } 00484 } 00485 00486 if (!error) { 00487 __ast_module_user_hangup_all(mod); 00488 res = mod->info->unload(); 00489 00490 if (res) { 00491 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00492 if (force <= AST_FORCE_FIRM) 00493 error = 1; 00494 else 00495 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00496 } 00497 } 00498 00499 if (!error) 00500 mod->flags.running = mod->flags.declined = 0; 00501 00502 AST_LIST_UNLOCK(&module_list); 00503 00504 #ifdef LOADABLE_MODULES 00505 if (!error) 00506 unload_dynamic_module(mod); 00507 #endif 00508 00509 if (!error) 00510 ast_update_use_count(); 00511 00512 return res; 00513 }
int ast_update_module_list | ( | int(*)(const char *module, const char *description, int usecnt, const char *like) | modentry, | |
const char * | like | |||
) |
Ask for a list of modules, descriptions, and use counts.
modentry | A callback to an updater function. | |
like | For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module. |
Definition at line 937 of file loader.c.
References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module::info, and ast_module::usecount.
Referenced by handle_modlist(), and mod_update().
00939 { 00940 struct ast_module *cur; 00941 int unlock = -1; 00942 int total_mod_loaded = 0; 00943 00944 if (AST_LIST_TRYLOCK(&module_list)) 00945 unlock = 0; 00946 00947 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00948 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 00949 } 00950 00951 if (unlock) 00952 AST_LIST_UNLOCK(&module_list); 00953 00954 return total_mod_loaded; 00955 }
void ast_update_use_count | ( | void | ) |
Notify when usecount has been changed.
This function calulates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.
Definition at line 925 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and loadupdate::updater.
Referenced by __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), agent_new(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), exit_now(), load_module(), load_resource(), oh323_request(), sip_request_call(), and sipsock_read().
00926 { 00927 /* Notify any module monitors that the use count for a 00928 resource has changed */ 00929 struct loadupdate *m; 00930 00931 AST_LIST_LOCK(&updaters); 00932 AST_LIST_TRAVERSE(&updaters, m, entry) 00933 m->updater(); 00934 AST_LIST_UNLOCK(&updaters); 00935 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 302 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and resource_name_match().
Referenced by ast_unload_resource(), and load_resource().
00303 { 00304 struct ast_module *cur; 00305 00306 if (do_lock) 00307 AST_LIST_LOCK(&module_list); 00308 00309 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00310 if (!resource_name_match(resource, cur->resource)) 00311 break; 00312 } 00313 00314 if (do_lock) 00315 AST_LIST_UNLOCK(&module_list); 00316 00317 return cur; 00318 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 606 of file loader.c.
References ast_log(), AST_MODFLAG_BUILDSUM, ast_strlen_zero(), ast_test_flag, buildopt_sum, ast_module_info::buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, and verify_key().
Referenced by load_resource().
00607 { 00608 if (!mod->info->description) { 00609 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00610 return 1; 00611 } 00612 00613 if (!mod->info->key) { 00614 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00615 return 1; 00616 } 00617 00618 if (verify_key((unsigned char *) mod->info->key)) { 00619 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00620 return 1; 00621 } 00622 00623 if (!ast_test_flag(mod->info, AST_MODFLAG_BUILDSUM)) { 00624 ast_log(LOG_WARNING, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod->resource); 00625 } else if (!ast_strlen_zero(mod->info->buildopt_sum) && 00626 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00627 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00628 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00629 return 1; 00630 } 00631 00632 return 0; 00633 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 255 of file loader.c.
Referenced by verify_key().
00256 { 00257 int x; 00258 00259 for (x = 0; x < 16; x++) { 00260 if (key1[x] != key2[x]) 00261 return 0; 00262 } 00263 00264 return 1; 00265 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 758 of file loader.c.
References add_to_load_order(), ast_config_load(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verbose(), embedding, ast_variable::name, ast_variable::next, option_verbose, translate_module_name(), and ast_variable::value.
Referenced by main().
00759 { 00760 struct ast_config *cfg; 00761 struct ast_module *mod; 00762 struct load_order_entry *order; 00763 struct ast_variable *v; 00764 unsigned int load_count; 00765 struct load_order load_order; 00766 int res = 0; 00767 00768 int translate_status; 00769 char newname[18]; /* although this would normally be 80, max length in translate_module_name is 18 */ 00770 #ifdef LOADABLE_MODULES 00771 struct dirent *dirent; 00772 DIR *dir; 00773 #endif 00774 00775 /* all embedded modules have registered themselves by now */ 00776 embedding = 0; 00777 00778 if (option_verbose) 00779 ast_verbose("Asterisk Dynamic Loader Starting:\n"); 00780 00781 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00782 00783 AST_LIST_LOCK(&module_list); 00784 00785 if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { 00786 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00787 goto done; 00788 } 00789 00790 /* first, find all the modules we have been explicitly requested to load */ 00791 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00792 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { 00793 translate_status = translate_module_name(v->value, newname); 00794 if (!translate_status) 00795 ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname); 00796 add_to_load_order(translate_status ? v->value : newname, &load_order); 00797 } 00798 } 00799 00800 /* check if 'autoload' is on */ 00801 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00802 /* if so, first add all the embedded modules that are not already running to the load order */ 00803 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00804 /* if it's not embedded, skip it */ 00805 if (mod->lib) 00806 continue; 00807 00808 if (mod->flags.running) 00809 continue; 00810 00811 order = add_to_load_order(mod->resource, &load_order); 00812 } 00813 00814 #ifdef LOADABLE_MODULES 00815 /* if we are allowed to load dynamic modules, scan the directory for 00816 for all available modules and add them as well */ 00817 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00818 while ((dirent = readdir(dir))) { 00819 int ld = strlen(dirent->d_name); 00820 00821 /* Must end in .so to load it. */ 00822 00823 if (ld < 4) 00824 continue; 00825 00826 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00827 continue; 00828 00829 /* if there is already a module by this name in the module_list, 00830 skip this file */ 00831 if (find_resource(dirent->d_name, 0)) 00832 continue; 00833 00834 add_to_load_order(dirent->d_name, &load_order); 00835 } 00836 00837 closedir(dir); 00838 } else { 00839 if (!ast_opt_quiet) 00840 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00841 ast_config_AST_MODULE_DIR); 00842 } 00843 #endif 00844 } 00845 00846 /* now scan the config for any modules we are prohibited from loading and 00847 remove them from the load order */ 00848 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00849 if (strcasecmp(v->name, "noload")) 00850 continue; 00851 00852 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00853 translate_status = translate_module_name(v->value, newname); 00854 if (!resource_name_match(order->resource, translate_status ? v->value : newname)) { 00855 if (!translate_status) 00856 ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname); 00857 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00858 free(order->resource); 00859 free(order); 00860 } 00861 } 00862 AST_LIST_TRAVERSE_SAFE_END; 00863 } 00864 00865 /* we are done with the config now, all the information we need is in the 00866 load_order list */ 00867 ast_config_destroy(cfg); 00868 00869 load_count = 0; 00870 AST_LIST_TRAVERSE(&load_order, order, entry) 00871 load_count++; 00872 00873 if (load_count) 00874 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00875 00876 /* first, load only modules that provide global symbols */ 00877 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00878 switch (load_resource(order->resource, 1)) { 00879 case AST_MODULE_LOAD_SUCCESS: 00880 case AST_MODULE_LOAD_DECLINE: 00881 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00882 free(order->resource); 00883 free(order); 00884 break; 00885 case AST_MODULE_LOAD_FAILURE: 00886 res = -1; 00887 goto done; 00888 case AST_MODULE_LOAD_SKIP: 00889 /* try again later */ 00890 break; 00891 } 00892 } 00893 AST_LIST_TRAVERSE_SAFE_END; 00894 00895 /* now load everything else */ 00896 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00897 switch (load_resource(order->resource, 0)) { 00898 case AST_MODULE_LOAD_SUCCESS: 00899 case AST_MODULE_LOAD_DECLINE: 00900 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00901 free(order->resource); 00902 free(order); 00903 break; 00904 case AST_MODULE_LOAD_FAILURE: 00905 res = -1; 00906 goto done; 00907 case AST_MODULE_LOAD_SKIP: 00908 /* should not happen */ 00909 break; 00910 } 00911 } 00912 AST_LIST_TRAVERSE_SAFE_END; 00913 00914 done: 00915 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00916 free(order->resource); 00917 free(order); 00918 } 00919 00920 AST_LIST_UNLOCK(&module_list); 00921 00922 return res; 00923 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 635 of file loader.c.
References ast_fully_booted, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_test_flag, ast_update_use_count(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module_info::load, option_verbose, ast_module::running, term_color(), and VERBOSE_PREFIX_1.
Referenced by ast_load_resource().
00636 { 00637 struct ast_module *mod; 00638 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00639 char tmp[256]; 00640 00641 if ((mod = find_resource(resource_name, 0))) { 00642 if (mod->flags.running) { 00643 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00644 return AST_MODULE_LOAD_DECLINE; 00645 } 00646 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00647 return AST_MODULE_LOAD_SKIP; 00648 } else { 00649 #ifdef LOADABLE_MODULES 00650 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00651 /* don't generate a warning message during load_modules() */ 00652 if (!global_symbols_only) { 00653 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00654 return AST_MODULE_LOAD_DECLINE; 00655 } else { 00656 return AST_MODULE_LOAD_SKIP; 00657 } 00658 } 00659 #else 00660 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00661 return AST_MODULE_LOAD_DECLINE; 00662 #endif 00663 } 00664 00665 if (inspect_module(mod)) { 00666 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00667 #ifdef LOADABLE_MODULES 00668 unload_dynamic_module(mod); 00669 #endif 00670 return AST_MODULE_LOAD_DECLINE; 00671 } 00672 00673 mod->flags.declined = 0; 00674 00675 if (mod->info->load) 00676 res = mod->info->load(); 00677 00678 switch (res) { 00679 case AST_MODULE_LOAD_SUCCESS: 00680 if (!ast_fully_booted) { 00681 if (option_verbose) 00682 ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00683 if (ast_opt_console && !option_verbose) 00684 ast_verbose( "."); 00685 } else { 00686 if (option_verbose) 00687 ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description); 00688 } 00689 00690 mod->flags.running = 1; 00691 00692 ast_update_use_count(); 00693 break; 00694 case AST_MODULE_LOAD_DECLINE: 00695 mod->flags.declined = 1; 00696 break; 00697 case AST_MODULE_LOAD_FAILURE: 00698 break; 00699 case AST_MODULE_LOAD_SKIP: 00700 /* modules should never return this value */ 00701 break; 00702 } 00703 00704 return res; 00705 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 242 of file loader.c.
References ast_log(), and LOG_DEBUG.
Referenced by verify_key().
00243 { 00244 int x, pos; 00245 char buf[256]; /* large enough so we don't have to worry */ 00246 00247 for (pos = 0, x = 0; x < 16; x++) 00248 pos += sprintf(buf + pos, " %02x", *d++); 00249 00250 ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf); 00251 00252 return 0; 00253 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 284 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), and find_resource().
00285 { 00286 char *name1 = (char *) name1_in; 00287 char *name2 = (char *) name2_in; 00288 00289 /* trim off any .so extensions */ 00290 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00291 name1 = ast_strdupa(name1); 00292 name1[strlen(name1) - 3] = '\0'; 00293 } 00294 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00295 name2 = ast_strdupa(name2); 00296 name2[strlen(name2) - 3] = '\0'; 00297 } 00298 00299 return strcasecmp(name1, name2); 00300 }
static int translate_module_name | ( | char * | oldname, | |
char * | newname | |||
) | [static] |
Definition at line 741 of file loader.c.
Referenced by load_modules().
00742 { 00743 if (!strcasecmp(oldname, "app_zapbarge.so")) 00744 ast_copy_string(newname, "app_dahdibarge.so", 18); 00745 else if(!strcasecmp(oldname, "app_zapras.so")) 00746 ast_copy_string(newname, "app_dahdiras.so", 16); 00747 else if(!strcasecmp(oldname, "app_zapscan.so")) 00748 ast_copy_string(newname, "app_dahdiscan.so", 17); 00749 else if(!strcasecmp(oldname, "codec_zap.so")) 00750 ast_copy_string(newname, "codec_dahdi.so", 16); 00751 else 00752 return -1; /* no use for newname, oldname is fine */ 00753 00754 return 0; 00755 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 267 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00268 { 00269 struct MD5Context c; 00270 unsigned char digest[16]; 00271 00272 MD5Init(&c); 00273 MD5Update(&c, key, strlen((char *)key)); 00274 MD5Final(digest, &c); 00275 00276 if (key_matches(expected_key, digest)) 00277 return 0; 00278 00279 printdigest(digest); 00280 00281 return -1; 00282 }
char buildopt_sum[33] = AST_BUILDOPT_SUM [static] |
unsigned int embedding = 1 [static] |
unsigned char expected_key[] [static] |
Initial value:
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3, 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }
Definition at line 71 of file loader.c.
Referenced by verify_key().
struct ast_module* resource_being_loaded |