#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 | 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.
#define RTLD_NOW 0 |
struct ast_module_user* __ast_module_user_add | ( | struct ast_module * | mod, | |
struct ast_channel * | chan | |||
) |
Definition at line 179 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.
00181 { 00182 struct ast_module_user *u = ast_calloc(1, sizeof(*u)); 00183 00184 if (!u) 00185 return NULL; 00186 00187 u->chan = chan; 00188 00189 AST_LIST_LOCK(&mod->users); 00190 AST_LIST_INSERT_HEAD(&mod->users, u, entry); 00191 AST_LIST_UNLOCK(&mod->users); 00192 00193 ast_atomic_fetchadd_int(&mod->usecount, +1); 00194 00195 ast_update_use_count(); 00196 00197 return u; 00198 }
void __ast_module_user_hangup_all | ( | struct ast_module * | mod | ) |
Definition at line 211 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().
00212 { 00213 struct ast_module_user *u; 00214 00215 AST_LIST_LOCK(&mod->users); 00216 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) { 00217 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); 00218 ast_atomic_fetchadd_int(&mod->usecount, -1); 00219 free(u); 00220 } 00221 AST_LIST_UNLOCK(&mod->users); 00222 00223 ast_update_use_count(); 00224 }
void __ast_module_user_remove | ( | struct ast_module * | mod, | |
struct ast_module_user * | u | |||
) |
Definition at line 200 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.
00201 { 00202 AST_LIST_LOCK(&mod->users); 00203 AST_LIST_REMOVE(&mod->users, u, entry); 00204 AST_LIST_UNLOCK(&mod->users); 00205 ast_atomic_fetchadd_int(&mod->usecount, -1); 00206 free(u); 00207 00208 ast_update_use_count(); 00209 }
static struct load_order_entry* add_to_load_order | ( | const char * | resource, | |
struct load_order * | load_order | |||
) | [static] |
Definition at line 727 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().
00728 { 00729 struct load_order_entry *order; 00730 00731 AST_LIST_TRAVERSE(load_order, order, entry) { 00732 if (!resource_name_match(order->resource, resource)) 00733 return NULL; 00734 } 00735 00736 if (!(order = ast_calloc(1, sizeof(*order)))) 00737 return NULL; 00738 00739 order->resource = ast_strdup(resource); 00740 AST_LIST_INSERT_TAIL(load_order, order, entry); 00741 00742 return order; 00743 }
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 711 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().
00712 { 00713 AST_LIST_LOCK(&module_list); 00714 load_resource(resource_name, 0); 00715 AST_LIST_UNLOCK(&module_list); 00716 00717 return 0; 00718 }
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 934 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
00935 { 00936 struct loadupdate *tmp; 00937 00938 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00939 return -1; 00940 00941 tmp->updater = v; 00942 AST_LIST_LOCK(&updaters); 00943 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 00944 AST_LIST_UNLOCK(&updaters); 00945 00946 return 0; 00947 }
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 949 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().
00950 { 00951 struct loadupdate *cur; 00952 00953 AST_LIST_LOCK(&updaters); 00954 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 00955 if (cur->updater == v) { 00956 AST_LIST_REMOVE_CURRENT(&updaters, entry); 00957 break; 00958 } 00959 } 00960 AST_LIST_TRAVERSE_SAFE_END; 00961 AST_LIST_UNLOCK(&updaters); 00962 00963 return cur ? 0 : -1; 00964 }
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 519 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().
00520 { 00521 struct ast_module *cur; 00522 int i, which=0, l = strlen(word); 00523 char *ret = NULL; 00524 00525 if (pos != rpos) 00526 return NULL; 00527 00528 AST_LIST_LOCK(&module_list); 00529 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00530 if (!strncasecmp(word, cur->resource, l) && 00531 (cur->info->reload || !needsreload) && 00532 ++which > state) { 00533 ret = strdup(cur->resource); 00534 break; 00535 } 00536 } 00537 AST_LIST_UNLOCK(&module_list); 00538 00539 if (!ret) { 00540 for (i=0; !ret && reload_classes[i].name; i++) { 00541 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00542 ret = strdup(reload_classes[i].name); 00543 } 00544 } 00545 00546 return ret; 00547 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 966 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(), features_new(), fn_wrapper(), gtalk_new(), handle_orig(), mgcp_new(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_new(), skinny_new(), and zt_new().
00967 { 00968 ast_atomic_fetchadd_int(&mod->usecount, +1); 00969 ast_update_use_count(); 00970 00971 return mod; 00972 }
void ast_module_register | ( | const struct ast_module_info * | info | ) |
Definition at line 117 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.
00118 { 00119 struct ast_module *mod; 00120 00121 if (embedding) { 00122 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1))) 00123 return; 00124 strcpy(mod->resource, info->name); 00125 } else { 00126 mod = resource_being_loaded; 00127 } 00128 00129 mod->info = info; 00130 AST_LIST_HEAD_INIT(&mod->users); 00131 00132 /* during startup, before the loader has been initialized, 00133 there are no threads, so there is no need to take the lock 00134 on this list to manipulate it. it is also possible that it 00135 might be unsafe to use the list lock at that point... so 00136 let's avoid it altogether 00137 */ 00138 if (!embedding) 00139 AST_LIST_LOCK(&module_list); 00140 00141 /* it is paramount that the new entry be placed at the tail of 00142 the list, otherwise the code that uses dlopen() to load 00143 dynamic modules won't be able to find out if the module it 00144 just opened was registered or failed to load 00145 */ 00146 AST_LIST_INSERT_TAIL(&module_list, mod, entry); 00147 00148 if (!embedding) 00149 AST_LIST_UNLOCK(&module_list); 00150 00151 /* give the module a copy of its own handle, for later use in registrations and the like */ 00152 *((struct ast_module **) &(info->self)) = mod; 00153 }
int ast_module_reload | ( | const char * | name | ) |
Reload asterisk modules.
name | the name of the module to reload |
Definition at line 549 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().
00550 { 00551 struct ast_module *cur; 00552 int res = 0; /* return value. 0 = not found, others, see below */ 00553 int i; 00554 00555 if (ast_mutex_trylock(&reloadlock)) { 00556 ast_verbose("The previous reload command didn't finish yet\n"); 00557 return -1; /* reload already in progress */ 00558 } 00559 ast_lastreloadtime = time(NULL); 00560 00561 /* Call "predefined" reload here first */ 00562 for (i = 0; reload_classes[i].name; i++) { 00563 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00564 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00565 res = 2; /* found and reloaded */ 00566 } 00567 } 00568 00569 if (name && res) { 00570 ast_mutex_unlock(&reloadlock); 00571 return res; 00572 } 00573 00574 AST_LIST_LOCK(&module_list); 00575 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00576 const struct ast_module_info *info = cur->info; 00577 00578 if (name && resource_name_match(name, cur->resource)) 00579 continue; 00580 00581 if (!cur->flags.running || cur->flags.declined) { 00582 if (!name) 00583 continue; 00584 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00585 "Before reloading the module, you must run \"module load %s\" " 00586 "and fix whatever is preventing the module from being initialized.\n", 00587 name, name); 00588 res = 2; /* Don't report that the module was not found */ 00589 break; 00590 } 00591 00592 if (!info->reload) { /* cannot be reloaded */ 00593 if (res < 1) /* store result if possible */ 00594 res = 1; /* 1 = no reload() method */ 00595 continue; 00596 } 00597 00598 res = 2; 00599 if (option_verbose > 2) 00600 ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description); 00601 info->reload(); 00602 } 00603 AST_LIST_UNLOCK(&module_list); 00604 00605 ast_mutex_unlock(&reloadlock); 00606 00607 return res; 00608 }
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 433 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().
00434 { 00435 struct ast_module *mod; 00436 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module); 00437 00438 /* We have to call the unload() callbacks in reverse order that the modules 00439 * exist in the module list so it is the reverse order of how they were 00440 * loaded. */ 00441 00442 AST_LIST_LOCK(&module_list); 00443 while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry))) 00444 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry); 00445 AST_LIST_UNLOCK(&module_list); 00446 00447 while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) { 00448 if (mod->info->unload) 00449 mod->info->unload(); 00450 /* Since this should only be called when shutting down "gracefully", 00451 * all channels should be down before we get to this point, meaning 00452 * there will be no module users left. */ 00453 AST_LIST_HEAD_DESTROY(&mod->users); 00454 free(mod); 00455 } 00456 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 974 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(), destroy(), gtalk_hangup(), handle_orig(), iax2_predestroy(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_hangup(), and zt_hangup().
00975 { 00976 ast_atomic_fetchadd_int(&mod->usecount, -1); 00977 ast_update_use_count(); 00978 }
void ast_module_unregister | ( | const struct ast_module_info * | info | ) |
Definition at line 155 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.
00156 { 00157 struct ast_module *mod = NULL; 00158 00159 /* it is assumed that the users list in the module structure 00160 will already be empty, or we cannot have gotten to this 00161 point 00162 */ 00163 AST_LIST_LOCK(&module_list); 00164 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00165 if (mod->info == info) { 00166 AST_LIST_REMOVE_CURRENT(&module_list, entry); 00167 break; 00168 } 00169 } 00170 AST_LIST_TRAVERSE_SAFE_END; 00171 AST_LIST_UNLOCK(&module_list); 00172 00173 if (mod) { 00174 AST_LIST_HEAD_DESTROY(&mod->users); 00175 free(mod); 00176 } 00177 }
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 458 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, error(), 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().
00459 { 00460 struct ast_module *mod; 00461 int res = -1; 00462 int error = 0; 00463 00464 AST_LIST_LOCK(&module_list); 00465 00466 if (!(mod = find_resource(resource_name, 0))) { 00467 AST_LIST_UNLOCK(&module_list); 00468 return 0; 00469 } 00470 00471 if (!(mod->flags.running || mod->flags.declined)) 00472 error = 1; 00473 00474 if (!mod->lib) { 00475 ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n"); 00476 error = 1; 00477 } 00478 00479 if (!error && (mod->usecount > 0)) { 00480 if (force) 00481 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00482 resource_name, mod->usecount); 00483 else { 00484 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00485 mod->usecount); 00486 error = 1; 00487 } 00488 } 00489 00490 if (!error) { 00491 __ast_module_user_hangup_all(mod); 00492 res = mod->info->unload(); 00493 00494 if (res) { 00495 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00496 if (force <= AST_FORCE_FIRM) 00497 error = 1; 00498 else 00499 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00500 } 00501 } 00502 00503 if (!error) 00504 mod->flags.running = mod->flags.declined = 0; 00505 00506 AST_LIST_UNLOCK(&module_list); 00507 00508 #ifdef LOADABLE_MODULES 00509 if (!error) 00510 unload_dynamic_module(mod); 00511 #endif 00512 00513 if (!error) 00514 ast_update_use_count(); 00515 00516 return res; 00517 }
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 914 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().
00916 { 00917 struct ast_module *cur; 00918 int unlock = -1; 00919 int total_mod_loaded = 0; 00920 00921 if (AST_LIST_TRYLOCK(&module_list)) 00922 unlock = 0; 00923 00924 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00925 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 00926 } 00927 00928 if (unlock) 00929 AST_LIST_UNLOCK(&module_list); 00930 00931 return total_mod_loaded; 00932 }
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 902 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().
00903 { 00904 /* Notify any module monitors that the use count for a 00905 resource has changed */ 00906 struct loadupdate *m; 00907 00908 AST_LIST_LOCK(&updaters); 00909 AST_LIST_TRAVERSE(&updaters, m, entry) 00910 m->updater(); 00911 AST_LIST_UNLOCK(&updaters); 00912 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 306 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and resource_name_match().
Referenced by ast_unload_resource(), load_modules(), and load_resource().
00307 { 00308 struct ast_module *cur; 00309 00310 if (do_lock) 00311 AST_LIST_LOCK(&module_list); 00312 00313 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00314 if (!resource_name_match(resource, cur->resource)) 00315 break; 00316 } 00317 00318 if (do_lock) 00319 AST_LIST_UNLOCK(&module_list); 00320 00321 return cur; 00322 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 610 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().
00611 { 00612 if (!mod->info->description) { 00613 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00614 return 1; 00615 } 00616 00617 if (!mod->info->key) { 00618 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00619 return 1; 00620 } 00621 00622 if (verify_key((unsigned char *) mod->info->key)) { 00623 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00624 return 1; 00625 } 00626 00627 if (!ast_test_flag(mod->info, AST_MODFLAG_BUILDSUM)) { 00628 ast_log(LOG_WARNING, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod->resource); 00629 } else if (!ast_strlen_zero(mod->info->buildopt_sum) && 00630 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00631 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00632 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00633 return 1; 00634 } 00635 00636 return 0; 00637 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 259 of file loader.c.
Referenced by verify_key().
00260 { 00261 int x; 00262 00263 for (x = 0; x < 16; x++) { 00264 if (key1[x] != key2[x]) 00265 return 0; 00266 } 00267 00268 return 1; 00269 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 745 of file loader.c.
References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_load(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_MODULE_CONFIG, ast_opt_quiet, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), embedding, find_resource(), ast_module::flags, free, ast_module::lib, ast_variable::name, ast_variable::next, option_verbose, load_order_entry::resource, resource_name_match(), ast_module::running, and ast_variable::value.
Referenced by main().
00746 { 00747 struct ast_config *cfg; 00748 struct ast_module *mod; 00749 struct load_order_entry *order; 00750 struct ast_variable *v; 00751 unsigned int load_count; 00752 struct load_order load_order; 00753 int res = 0; 00754 #ifdef LOADABLE_MODULES 00755 struct dirent *dirent; 00756 DIR *dir; 00757 #endif 00758 00759 /* all embedded modules have registered themselves by now */ 00760 embedding = 0; 00761 00762 if (option_verbose) 00763 ast_verbose("Asterisk Dynamic Loader Starting:\n"); 00764 00765 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00766 00767 AST_LIST_LOCK(&module_list); 00768 00769 if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { 00770 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00771 goto done; 00772 } 00773 00774 /* first, find all the modules we have been explicitly requested to load */ 00775 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00776 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) 00777 add_to_load_order(v->value, &load_order); 00778 } 00779 00780 /* check if 'autoload' is on */ 00781 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00782 /* if so, first add all the embedded modules that are not already running to the load order */ 00783 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00784 /* if it's not embedded, skip it */ 00785 if (mod->lib) 00786 continue; 00787 00788 if (mod->flags.running) 00789 continue; 00790 00791 order = add_to_load_order(mod->resource, &load_order); 00792 } 00793 00794 #ifdef LOADABLE_MODULES 00795 /* if we are allowed to load dynamic modules, scan the directory for 00796 for all available modules and add them as well */ 00797 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00798 while ((dirent = readdir(dir))) { 00799 int ld = strlen(dirent->d_name); 00800 00801 /* Must end in .so to load it. */ 00802 00803 if (ld < 4) 00804 continue; 00805 00806 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00807 continue; 00808 00809 /* if there is already a module by this name in the module_list, 00810 skip this file */ 00811 if (find_resource(dirent->d_name, 0)) 00812 continue; 00813 00814 add_to_load_order(dirent->d_name, &load_order); 00815 } 00816 00817 closedir(dir); 00818 } else { 00819 if (!ast_opt_quiet) 00820 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00821 ast_config_AST_MODULE_DIR); 00822 } 00823 #endif 00824 } 00825 00826 /* now scan the config for any modules we are prohibited from loading and 00827 remove them from the load order */ 00828 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00829 if (strcasecmp(v->name, "noload")) 00830 continue; 00831 00832 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00833 if (!resource_name_match(order->resource, v->value)) { 00834 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00835 free(order->resource); 00836 free(order); 00837 } 00838 } 00839 AST_LIST_TRAVERSE_SAFE_END; 00840 } 00841 00842 /* we are done with the config now, all the information we need is in the 00843 load_order list */ 00844 ast_config_destroy(cfg); 00845 00846 load_count = 0; 00847 AST_LIST_TRAVERSE(&load_order, order, entry) 00848 load_count++; 00849 00850 if (load_count) 00851 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00852 00853 /* first, load only modules that provide global symbols */ 00854 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00855 switch (load_resource(order->resource, 1)) { 00856 case AST_MODULE_LOAD_SUCCESS: 00857 case AST_MODULE_LOAD_DECLINE: 00858 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00859 free(order->resource); 00860 free(order); 00861 break; 00862 case AST_MODULE_LOAD_FAILURE: 00863 res = -1; 00864 goto done; 00865 case AST_MODULE_LOAD_SKIP: 00866 /* try again later */ 00867 break; 00868 } 00869 } 00870 AST_LIST_TRAVERSE_SAFE_END; 00871 00872 /* now load everything else */ 00873 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00874 switch (load_resource(order->resource, 0)) { 00875 case AST_MODULE_LOAD_SUCCESS: 00876 case AST_MODULE_LOAD_DECLINE: 00877 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00878 free(order->resource); 00879 free(order); 00880 break; 00881 case AST_MODULE_LOAD_FAILURE: 00882 res = -1; 00883 goto done; 00884 case AST_MODULE_LOAD_SKIP: 00885 /* should not happen */ 00886 break; 00887 } 00888 } 00889 AST_LIST_TRAVERSE_SAFE_END; 00890 00891 done: 00892 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00893 free(order->resource); 00894 free(order); 00895 } 00896 00897 AST_LIST_UNLOCK(&module_list); 00898 00899 return res; 00900 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 639 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().
00640 { 00641 struct ast_module *mod; 00642 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00643 char tmp[256]; 00644 00645 if ((mod = find_resource(resource_name, 0))) { 00646 if (mod->flags.running) { 00647 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00648 return AST_MODULE_LOAD_DECLINE; 00649 } 00650 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00651 return AST_MODULE_LOAD_SKIP; 00652 } else { 00653 #ifdef LOADABLE_MODULES 00654 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00655 /* don't generate a warning message during load_modules() */ 00656 if (!global_symbols_only) { 00657 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00658 return AST_MODULE_LOAD_DECLINE; 00659 } else { 00660 return AST_MODULE_LOAD_SKIP; 00661 } 00662 } 00663 #else 00664 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00665 return AST_MODULE_LOAD_DECLINE; 00666 #endif 00667 } 00668 00669 if (inspect_module(mod)) { 00670 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00671 #ifdef LOADABLE_MODULES 00672 unload_dynamic_module(mod); 00673 #endif 00674 return AST_MODULE_LOAD_DECLINE; 00675 } 00676 00677 mod->flags.declined = 0; 00678 00679 if (mod->info->load) 00680 res = mod->info->load(); 00681 00682 switch (res) { 00683 case AST_MODULE_LOAD_SUCCESS: 00684 if (!ast_fully_booted) { 00685 if (option_verbose) 00686 ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00687 if (ast_opt_console && !option_verbose) 00688 ast_verbose( "."); 00689 } else { 00690 if (option_verbose) 00691 ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description); 00692 } 00693 00694 mod->flags.running = 1; 00695 00696 ast_update_use_count(); 00697 break; 00698 case AST_MODULE_LOAD_DECLINE: 00699 mod->flags.declined = 1; 00700 break; 00701 case AST_MODULE_LOAD_FAILURE: 00702 break; 00703 case AST_MODULE_LOAD_SKIP: 00704 /* modules should never return this value */ 00705 break; 00706 } 00707 00708 return res; 00709 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 246 of file loader.c.
References ast_log(), and LOG_DEBUG.
Referenced by verify_key().
00247 { 00248 int x, pos; 00249 char buf[256]; /* large enough so we don't have to worry */ 00250 00251 for (pos = 0, x = 0; x < 16; x++) 00252 pos += sprintf(buf + pos, " %02x", *d++); 00253 00254 ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf); 00255 00256 return 0; 00257 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 288 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and load_modules().
00289 { 00290 char *name1 = (char *) name1_in; 00291 char *name2 = (char *) name2_in; 00292 00293 /* trim off any .so extensions */ 00294 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00295 name1 = ast_strdupa(name1); 00296 name1[strlen(name1) - 3] = '\0'; 00297 } 00298 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00299 name2 = ast_strdupa(name2); 00300 name2[strlen(name2) - 3] = '\0'; 00301 } 00302 00303 return strcasecmp(name1, name2); 00304 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 271 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00272 { 00273 struct MD5Context c; 00274 unsigned char digest[16]; 00275 00276 MD5Init(&c); 00277 MD5Update(&c, key, strlen((char *)key)); 00278 MD5Final(digest, &c); 00279 00280 if (key_matches(expected_key, digest)) 00281 return 0; 00282 00283 printdigest(digest); 00284 00285 return -1; 00286 }
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 75 of file loader.c.
Referenced by verify_key().
struct ast_module* resource_being_loaded |