#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"
Include dependency graph for loader.c:
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 |
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 735 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().
00736 { 00737 struct load_order_entry *order; 00738 00739 AST_LIST_TRAVERSE(load_order, order, entry) { 00740 if (!resource_name_match(order->resource, resource)) 00741 return NULL; 00742 } 00743 00744 if (!(order = ast_calloc(1, sizeof(*order)))) 00745 return NULL; 00746 00747 order->resource = ast_strdup(resource); 00748 AST_LIST_INSERT_TAIL(load_order, order, entry); 00749 00750 return order; 00751 }
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 719 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().
00720 { 00721 AST_LIST_LOCK(&module_list); 00722 load_resource(resource_name, 0); 00723 AST_LIST_UNLOCK(&module_list); 00724 00725 return 0; 00726 }
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 942 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
00943 { 00944 struct loadupdate *tmp; 00945 00946 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00947 return -1; 00948 00949 tmp->updater = v; 00950 AST_LIST_LOCK(&updaters); 00951 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 00952 AST_LIST_UNLOCK(&updaters); 00953 00954 return 0; 00955 }
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 957 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().
00958 { 00959 struct loadupdate *cur; 00960 00961 AST_LIST_LOCK(&updaters); 00962 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 00963 if (cur->updater == v) { 00964 AST_LIST_REMOVE_CURRENT(&updaters, entry); 00965 break; 00966 } 00967 } 00968 AST_LIST_TRAVERSE_SAFE_END; 00969 AST_LIST_UNLOCK(&updaters); 00970 00971 return cur ? 0 : -1; 00972 }
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 525 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().
00526 { 00527 struct ast_module *cur; 00528 int i, which=0, l = strlen(word); 00529 char *ret = NULL; 00530 00531 if (pos != rpos) 00532 return NULL; 00533 00534 AST_LIST_LOCK(&module_list); 00535 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00536 if (!strncasecmp(word, cur->resource, l) && 00537 (cur->info->reload || !needsreload) && 00538 ++which > state) { 00539 ret = strdup(cur->resource); 00540 break; 00541 } 00542 } 00543 AST_LIST_UNLOCK(&module_list); 00544 00545 if (!ret) { 00546 for (i=0; !ret && reload_classes[i].name; i++) { 00547 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00548 ret = strdup(reload_classes[i].name); 00549 } 00550 } 00551 00552 return ret; 00553 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 974 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().
00975 { 00976 ast_atomic_fetchadd_int(&mod->usecount, +1); 00977 ast_update_use_count(); 00978 00979 return mod; 00980 }
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 555 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().
00556 { 00557 struct ast_module *cur; 00558 int res = 0; /* return value. 0 = not found, others, see below */ 00559 int i; 00560 00561 if (ast_mutex_trylock(&reloadlock)) { 00562 ast_verbose("The previous reload command didn't finish yet\n"); 00563 return -1; /* reload already in progress */ 00564 } 00565 ast_lastreloadtime = time(NULL); 00566 00567 /* Call "predefined" reload here first */ 00568 for (i = 0; reload_classes[i].name; i++) { 00569 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00570 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00571 res = 2; /* found and reloaded */ 00572 } 00573 } 00574 00575 if (name && res) { 00576 ast_mutex_unlock(&reloadlock); 00577 return res; 00578 } 00579 00580 AST_LIST_LOCK(&module_list); 00581 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00582 const struct ast_module_info *info = cur->info; 00583 00584 if (name && resource_name_match(name, cur->resource)) 00585 continue; 00586 00587 if (!cur->flags.running || cur->flags.declined) { 00588 if (!name) 00589 continue; 00590 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00591 "Before reloading the module, you must run \"module load %s\" " 00592 "and fix whatever is preventing the module from being initialized.\n", 00593 name, name); 00594 res = 2; /* Don't report that the module was not found */ 00595 break; 00596 } 00597 00598 if (!info->reload) { /* cannot be reloaded */ 00599 if (res < 1) /* store result if possible */ 00600 res = 1; /* 1 = no reload() method */ 00601 continue; 00602 } 00603 00604 res = 2; 00605 if (option_verbose > 2) 00606 ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description); 00607 info->reload(); 00608 } 00609 AST_LIST_UNLOCK(&module_list); 00610 00611 ast_mutex_unlock(&reloadlock); 00612 00613 return res; 00614 }
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 439 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().
00440 { 00441 struct ast_module *mod; 00442 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module); 00443 00444 /* We have to call the unload() callbacks in reverse order that the modules 00445 * exist in the module list so it is the reverse order of how they were 00446 * loaded. */ 00447 00448 AST_LIST_LOCK(&module_list); 00449 while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry))) 00450 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry); 00451 AST_LIST_UNLOCK(&module_list); 00452 00453 while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) { 00454 if (mod->info->unload) 00455 mod->info->unload(); 00456 /* Since this should only be called when shutting down "gracefully", 00457 * all channels should be down before we get to this point, meaning 00458 * there will be no module users left. */ 00459 AST_LIST_HEAD_DESTROY(&mod->users); 00460 free(mod); 00461 } 00462 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 982 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().
00983 { 00984 ast_atomic_fetchadd_int(&mod->usecount, -1); 00985 ast_update_use_count(); 00986 }
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 464 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().
00465 { 00466 struct ast_module *mod; 00467 int res = -1; 00468 int error = 0; 00469 00470 AST_LIST_LOCK(&module_list); 00471 00472 if (!(mod = find_resource(resource_name, 0))) { 00473 AST_LIST_UNLOCK(&module_list); 00474 return 0; 00475 } 00476 00477 if (!(mod->flags.running || mod->flags.declined)) 00478 error = 1; 00479 00480 if (!mod->lib) { 00481 ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n"); 00482 error = 1; 00483 } 00484 00485 if (!error && (mod->usecount > 0)) { 00486 if (force) 00487 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00488 resource_name, mod->usecount); 00489 else { 00490 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00491 mod->usecount); 00492 error = 1; 00493 } 00494 } 00495 00496 if (!error) { 00497 __ast_module_user_hangup_all(mod); 00498 res = mod->info->unload(); 00499 00500 if (res) { 00501 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00502 if (force <= AST_FORCE_FIRM) 00503 error = 1; 00504 else 00505 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00506 } 00507 } 00508 00509 if (!error) 00510 mod->flags.running = mod->flags.declined = 0; 00511 00512 AST_LIST_UNLOCK(&module_list); 00513 00514 #ifdef LOADABLE_MODULES 00515 if (!error) 00516 unload_dynamic_module(mod); 00517 #endif 00518 00519 if (!error) 00520 ast_update_use_count(); 00521 00522 return res; 00523 }
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 922 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().
00924 { 00925 struct ast_module *cur; 00926 int unlock = -1; 00927 int total_mod_loaded = 0; 00928 00929 if (AST_LIST_TRYLOCK(&module_list)) 00930 unlock = 0; 00931 00932 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00933 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 00934 } 00935 00936 if (unlock) 00937 AST_LIST_UNLOCK(&module_list); 00938 00939 return total_mod_loaded; 00940 }
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 910 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().
00911 { 00912 /* Notify any module monitors that the use count for a 00913 resource has changed */ 00914 struct loadupdate *m; 00915 00916 AST_LIST_LOCK(&updaters); 00917 AST_LIST_TRAVERSE(&updaters, m, entry) 00918 m->updater(); 00919 AST_LIST_UNLOCK(&updaters); 00920 }
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 616 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().
00617 { 00618 if (!mod->info->description) { 00619 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00620 return 1; 00621 } 00622 00623 if (!mod->info->key) { 00624 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00625 return 1; 00626 } 00627 00628 if (verify_key((unsigned char *) mod->info->key)) { 00629 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00630 return 1; 00631 } 00632 00633 if (!ast_test_flag(mod->info, AST_MODFLAG_BUILDSUM)) { 00634 /* 00635 ast_log(LOG_WARNING, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod->resource); 00636 */ 00637 } else if (!ast_strlen_zero(mod->info->buildopt_sum) && 00638 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00639 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00640 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00641 return 1; 00642 } 00643 00644 return 0; 00645 }
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 753 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().
00754 { 00755 struct ast_config *cfg; 00756 struct ast_module *mod; 00757 struct load_order_entry *order; 00758 struct ast_variable *v; 00759 unsigned int load_count; 00760 struct load_order load_order; 00761 int res = 0; 00762 #ifdef LOADABLE_MODULES 00763 struct dirent *dirent; 00764 DIR *dir; 00765 #endif 00766 00767 /* all embedded modules have registered themselves by now */ 00768 embedding = 0; 00769 00770 if (option_verbose) 00771 ast_verbose("Asterisk Dynamic Loader Starting:\n"); 00772 00773 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00774 00775 AST_LIST_LOCK(&module_list); 00776 00777 if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { 00778 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00779 goto done; 00780 } 00781 00782 /* first, find all the modules we have been explicitly requested to load */ 00783 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00784 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) 00785 add_to_load_order(v->value, &load_order); 00786 } 00787 00788 /* check if 'autoload' is on */ 00789 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00790 /* if so, first add all the embedded modules that are not already running to the load order */ 00791 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00792 /* if it's not embedded, skip it */ 00793 if (mod->lib) 00794 continue; 00795 00796 if (mod->flags.running) 00797 continue; 00798 00799 order = add_to_load_order(mod->resource, &load_order); 00800 } 00801 00802 #ifdef LOADABLE_MODULES 00803 /* if we are allowed to load dynamic modules, scan the directory for 00804 for all available modules and add them as well */ 00805 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00806 while ((dirent = readdir(dir))) { 00807 int ld = strlen(dirent->d_name); 00808 00809 /* Must end in .so to load it. */ 00810 00811 if (ld < 4) 00812 continue; 00813 00814 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00815 continue; 00816 00817 /* if there is already a module by this name in the module_list, 00818 skip this file */ 00819 if (find_resource(dirent->d_name, 0)) 00820 continue; 00821 00822 add_to_load_order(dirent->d_name, &load_order); 00823 } 00824 00825 closedir(dir); 00826 } else { 00827 if (!ast_opt_quiet) 00828 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00829 ast_config_AST_MODULE_DIR); 00830 } 00831 #endif 00832 } 00833 00834 /* now scan the config for any modules we are prohibited from loading and 00835 remove them from the load order */ 00836 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00837 if (strcasecmp(v->name, "noload")) 00838 continue; 00839 00840 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00841 if (!resource_name_match(order->resource, v->value)) { 00842 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00843 free(order->resource); 00844 free(order); 00845 } 00846 } 00847 AST_LIST_TRAVERSE_SAFE_END; 00848 } 00849 00850 /* we are done with the config now, all the information we need is in the 00851 load_order list */ 00852 ast_config_destroy(cfg); 00853 00854 load_count = 0; 00855 AST_LIST_TRAVERSE(&load_order, order, entry) 00856 load_count++; 00857 00858 if (load_count) 00859 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00860 00861 /* first, load only modules that provide global symbols */ 00862 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00863 switch (load_resource(order->resource, 1)) { 00864 case AST_MODULE_LOAD_SUCCESS: 00865 case AST_MODULE_LOAD_DECLINE: 00866 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00867 free(order->resource); 00868 free(order); 00869 break; 00870 case AST_MODULE_LOAD_FAILURE: 00871 res = -1; 00872 goto done; 00873 case AST_MODULE_LOAD_SKIP: 00874 /* try again later */ 00875 break; 00876 } 00877 } 00878 AST_LIST_TRAVERSE_SAFE_END; 00879 00880 /* now load everything else */ 00881 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00882 switch (load_resource(order->resource, 0)) { 00883 case AST_MODULE_LOAD_SUCCESS: 00884 case AST_MODULE_LOAD_DECLINE: 00885 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00886 free(order->resource); 00887 free(order); 00888 break; 00889 case AST_MODULE_LOAD_FAILURE: 00890 res = -1; 00891 goto done; 00892 case AST_MODULE_LOAD_SKIP: 00893 /* should not happen */ 00894 break; 00895 } 00896 } 00897 AST_LIST_TRAVERSE_SAFE_END; 00898 00899 done: 00900 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00901 free(order->resource); 00902 free(order); 00903 } 00904 00905 AST_LIST_UNLOCK(&module_list); 00906 00907 return res; 00908 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 647 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().
00648 { 00649 struct ast_module *mod; 00650 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00651 char tmp[256]; 00652 00653 if ((mod = find_resource(resource_name, 0))) { 00654 if (mod->flags.running) { 00655 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00656 return AST_MODULE_LOAD_DECLINE; 00657 } 00658 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00659 return AST_MODULE_LOAD_SKIP; 00660 } else { 00661 #ifdef LOADABLE_MODULES 00662 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00663 /* don't generate a warning message during load_modules() */ 00664 if (!global_symbols_only) { 00665 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00666 return AST_MODULE_LOAD_DECLINE; 00667 } else { 00668 return AST_MODULE_LOAD_SKIP; 00669 } 00670 } 00671 #else 00672 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00673 return AST_MODULE_LOAD_DECLINE; 00674 #endif 00675 } 00676 00677 if (inspect_module(mod)) { 00678 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00679 #ifdef LOADABLE_MODULES 00680 unload_dynamic_module(mod); 00681 #endif 00682 return AST_MODULE_LOAD_DECLINE; 00683 } 00684 00685 mod->flags.declined = 0; 00686 00687 if (mod->info->load) 00688 res = mod->info->load(); 00689 00690 switch (res) { 00691 case AST_MODULE_LOAD_SUCCESS: 00692 if (!ast_fully_booted) { 00693 if (option_verbose) 00694 ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00695 if (ast_opt_console && !option_verbose) 00696 ast_verbose( "."); 00697 } else { 00698 if (option_verbose) 00699 ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description); 00700 } 00701 00702 mod->flags.running = 1; 00703 00704 ast_update_use_count(); 00705 break; 00706 case AST_MODULE_LOAD_DECLINE: 00707 mod->flags.declined = 1; 00708 break; 00709 case AST_MODULE_LOAD_FAILURE: 00710 break; 00711 case AST_MODULE_LOAD_SKIP: 00712 /* modules should never return this value */ 00713 break; 00714 } 00715 00716 return res; 00717 }
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 |