#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. | |
int | ast_module_check (char *name) |
Check if module with the name given is loaded. | |
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_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 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 177 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.
00179 { 00180 struct ast_module_user *u = ast_calloc(1, sizeof(*u)); 00181 00182 if (!u) 00183 return NULL; 00184 00185 u->chan = chan; 00186 00187 AST_LIST_LOCK(&mod->users); 00188 AST_LIST_INSERT_HEAD(&mod->users, u, entry); 00189 AST_LIST_UNLOCK(&mod->users); 00190 00191 ast_atomic_fetchadd_int(&mod->usecount, +1); 00192 00193 ast_update_use_count(); 00194 00195 return u; 00196 }
void __ast_module_user_hangup_all | ( | struct ast_module * | mod | ) |
Definition at line 209 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().
00210 { 00211 struct ast_module_user *u; 00212 00213 AST_LIST_LOCK(&mod->users); 00214 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) { 00215 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); 00216 ast_atomic_fetchadd_int(&mod->usecount, -1); 00217 free(u); 00218 } 00219 AST_LIST_UNLOCK(&mod->users); 00220 00221 ast_update_use_count(); 00222 }
void __ast_module_user_remove | ( | struct ast_module * | mod, | |
struct ast_module_user * | u | |||
) |
Definition at line 198 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.
00199 { 00200 AST_LIST_LOCK(&mod->users); 00201 AST_LIST_REMOVE(&mod->users, u, entry); 00202 AST_LIST_UNLOCK(&mod->users); 00203 ast_atomic_fetchadd_int(&mod->usecount, -1); 00204 free(u); 00205 00206 ast_update_use_count(); 00207 }
static struct load_order_entry* add_to_load_order | ( | const char * | resource, | |
struct load_order * | load_order | |||
) | [static] |
Definition at line 682 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().
00683 { 00684 struct load_order_entry *order; 00685 00686 AST_LIST_TRAVERSE(load_order, order, entry) { 00687 if (!resource_name_match(order->resource, resource)) 00688 return NULL; 00689 } 00690 00691 if (!(order = ast_calloc(1, sizeof(*order)))) 00692 return NULL; 00693 00694 order->resource = ast_strdup(resource); 00695 AST_LIST_INSERT_TAIL(load_order, order, entry); 00696 00697 return order; 00698 }
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 666 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_module().
00667 { 00668 AST_LIST_LOCK(&module_list); 00669 load_resource(resource_name, 0); 00670 AST_LIST_UNLOCK(&module_list); 00671 00672 return 0; 00673 }
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 908 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
00909 { 00910 struct loadupdate *tmp; 00911 00912 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00913 return -1; 00914 00915 tmp->updater = v; 00916 AST_LIST_LOCK(&module_list); 00917 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 00918 AST_LIST_UNLOCK(&module_list); 00919 00920 return 0; 00921 }
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 923 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().
00924 { 00925 struct loadupdate *cur; 00926 00927 AST_LIST_LOCK(&module_list); 00928 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 00929 if (cur->updater == v) { 00930 AST_LIST_REMOVE_CURRENT(&updaters, entry); 00931 break; 00932 } 00933 } 00934 AST_LIST_TRAVERSE_SAFE_END; 00935 AST_LIST_UNLOCK(&module_list); 00936 00937 return cur ? 0 : -1; 00938 }
int ast_module_check | ( | char * | name | ) |
Check if module with the name given is loaded.
name | Module name, like "chan_sip.so" |
Definition at line 889 of file loader.c.
References AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_trylock(), and ast_strlen_zero().
Referenced by ifmodule_read().
00890 { 00891 struct ast_module *cur; 00892 int unlock = -1; 00893 int res = 0; 00894 00895 if (ast_strlen_zero(name)) 00896 return 0; /* FALSE */ 00897 00898 if (ast_mutex_trylock(&module_list.lock)) 00899 unlock = 0; 00900 AST_LIST_TRAVERSE(&module_list, cur, entry) 00901 if (!res && !strcasecmp(name, cur->resource)) 00902 res = 1; 00903 if (unlock) 00904 AST_LIST_UNLOCK(&module_list); 00905 return res; 00906 }
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 491 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(), and complete_mod_4().
00492 { 00493 struct ast_module *cur; 00494 int i, which=0, l = strlen(word); 00495 char *ret = NULL; 00496 00497 if (pos != rpos) 00498 return NULL; 00499 00500 AST_LIST_LOCK(&module_list); 00501 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00502 if (!strncasecmp(word, cur->resource, l) && 00503 (cur->info->reload || !needsreload) && 00504 ++which > state) { 00505 ret = strdup(cur->resource); 00506 break; 00507 } 00508 } 00509 AST_LIST_UNLOCK(&module_list); 00510 00511 if (!ret) { 00512 for (i=0; !ret && reload_classes[i].name; i++) { 00513 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00514 ret = strdup(reload_classes[i].name); 00515 } 00516 } 00517 00518 return ret; 00519 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 940 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().
00941 { 00942 ast_atomic_fetchadd_int(&mod->usecount, +1); 00943 ast_update_use_count(); 00944 00945 return mod; 00946 }
void ast_module_register | ( | const struct ast_module_info * | info | ) |
Definition at line 115 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.
00116 { 00117 struct ast_module *mod; 00118 00119 if (embedding) { 00120 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1))) 00121 return; 00122 strcpy(mod->resource, info->name); 00123 } else { 00124 mod = resource_being_loaded; 00125 } 00126 00127 mod->info = info; 00128 AST_LIST_HEAD_INIT(&mod->users); 00129 00130 /* during startup, before the loader has been initialized, 00131 there are no threads, so there is no need to take the lock 00132 on this list to manipulate it. it is also possible that it 00133 might be unsafe to use the list lock at that point... so 00134 let's avoid it altogether 00135 */ 00136 if (!embedding) 00137 AST_LIST_LOCK(&module_list); 00138 00139 /* it is paramount that the new entry be placed at the tail of 00140 the list, otherwise the code that uses dlopen() to load 00141 dynamic modules won't be able to find out if the module it 00142 just opened was registered or failed to load 00143 */ 00144 AST_LIST_INSERT_TAIL(&module_list, mod, entry); 00145 00146 if (!embedding) 00147 AST_LIST_UNLOCK(&module_list); 00148 00149 /* give the module a copy of its own handle, for later use in registrations and the like */ 00150 *((struct ast_module **) &(info->self)) = mod; 00151 }
int ast_module_reload | ( | const char * | name | ) |
Reload asterisk modules.
name | the name of the module to reload |
Definition at line 521 of file loader.c.
References ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, 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().
00522 { 00523 struct ast_module *cur; 00524 int res = 0; /* return value. 0 = not found, others, see below */ 00525 int i; 00526 00527 if (ast_mutex_trylock(&reloadlock)) { 00528 ast_verbose("The previous reload command didn't finish yet\n"); 00529 return -1; /* reload already in progress */ 00530 } 00531 ast_lastreloadtime = time(NULL); 00532 00533 /* Call "predefined" reload here first */ 00534 for (i = 0; reload_classes[i].name; i++) { 00535 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00536 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00537 res = 2; /* found and reloaded */ 00538 } 00539 } 00540 00541 if (name && res) { 00542 ast_mutex_unlock(&reloadlock); 00543 return res; 00544 } 00545 00546 AST_LIST_LOCK(&module_list); 00547 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00548 const struct ast_module_info *info = cur->info; 00549 00550 if (name && resource_name_match(name, cur->resource)) 00551 continue; 00552 00553 if (!(cur->flags.running || cur->flags.declined)) 00554 continue; 00555 00556 if (!info->reload) { /* cannot be reloaded */ 00557 if (res < 1) /* store result if possible */ 00558 res = 1; /* 1 = no reload() method */ 00559 continue; 00560 } 00561 00562 res = 2; 00563 if (option_verbose > 2) 00564 ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description); 00565 info->reload(); 00566 } 00567 AST_LIST_UNLOCK(&module_list); 00568 00569 ast_mutex_unlock(&reloadlock); 00570 00571 return res; 00572 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 948 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().
00949 { 00950 ast_atomic_fetchadd_int(&mod->usecount, -1); 00951 ast_update_use_count(); 00952 }
void ast_module_unregister | ( | const struct ast_module_info * | info | ) |
Definition at line 153 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.
00154 { 00155 struct ast_module *mod = NULL; 00156 00157 /* it is assumed that the users list in the module structure 00158 will already be empty, or we cannot have gotten to this 00159 point 00160 */ 00161 AST_LIST_LOCK(&module_list); 00162 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00163 if (mod->info == info) { 00164 AST_LIST_REMOVE_CURRENT(&module_list, entry); 00165 break; 00166 } 00167 } 00168 AST_LIST_TRAVERSE_SAFE_END; 00169 AST_LIST_UNLOCK(&module_list); 00170 00171 if (mod) { 00172 AST_LIST_HEAD_DESTROY(&mod->users); 00173 free(mod); 00174 } 00175 }
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 430 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_module(), and remove_module().
00431 { 00432 struct ast_module *mod; 00433 int res = -1; 00434 int error = 0; 00435 00436 AST_LIST_LOCK(&module_list); 00437 00438 if (!(mod = find_resource(resource_name, 0))) { 00439 AST_LIST_UNLOCK(&module_list); 00440 return 0; 00441 } 00442 00443 if (!(mod->flags.running || mod->flags.declined)) 00444 error = 1; 00445 00446 if (!mod->lib) { 00447 ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n"); 00448 error = 1; 00449 } 00450 00451 if (!error && (mod->usecount > 0)) { 00452 if (force) 00453 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00454 resource_name, mod->usecount); 00455 else { 00456 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00457 mod->usecount); 00458 error = 1; 00459 } 00460 } 00461 00462 if (!error) { 00463 __ast_module_user_hangup_all(mod); 00464 res = mod->info->unload(); 00465 00466 if (res) { 00467 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00468 if (force <= AST_FORCE_FIRM) 00469 error = 1; 00470 else 00471 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00472 } 00473 } 00474 00475 if (!error) 00476 mod->flags.running = mod->flags.declined = 0; 00477 00478 AST_LIST_UNLOCK(&module_list); 00479 00480 #if LOADABLE_MODULES 00481 if (!error) 00482 unload_dynamic_module(mod); 00483 #endif 00484 00485 if (!error) 00486 ast_update_use_count(); 00487 00488 return res; 00489 }
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 869 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().
00871 { 00872 struct ast_module *cur; 00873 int unlock = -1; 00874 int total_mod_loaded = 0; 00875 00876 if (AST_LIST_TRYLOCK(&module_list)) 00877 unlock = 0; 00878 00879 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00880 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 00881 } 00882 00883 if (unlock) 00884 AST_LIST_UNLOCK(&module_list); 00885 00886 return total_mod_loaded; 00887 }
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 857 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().
00858 { 00859 /* Notify any module monitors that the use count for a 00860 resource has changed */ 00861 struct loadupdate *m; 00862 00863 AST_LIST_LOCK(&module_list); 00864 AST_LIST_TRAVERSE(&updaters, m, entry) 00865 m->updater(); 00866 AST_LIST_UNLOCK(&module_list); 00867 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 303 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().
00304 { 00305 struct ast_module *cur; 00306 00307 if (do_lock) 00308 AST_LIST_LOCK(&module_list); 00309 00310 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00311 if (!resource_name_match(resource, cur->resource)) 00312 break; 00313 } 00314 00315 if (do_lock) 00316 AST_LIST_UNLOCK(&module_list); 00317 00318 return cur; 00319 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 574 of file loader.c.
References ast_log(), ast_module_info::description, ast_module::info, ast_module_info::key, and verify_key().
Referenced by load_resource().
00575 { 00576 if (!mod->info->description) { 00577 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00578 return 1; 00579 } 00580 00581 if (!mod->info->key) { 00582 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00583 return 1; 00584 } 00585 00586 if (verify_key((unsigned char *) mod->info->key)) { 00587 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00588 return 1; 00589 } 00590 00591 return 0; 00592 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 256 of file loader.c.
Referenced by verify_key().
00257 { 00258 int x; 00259 00260 for (x = 0; x < 16; x++) { 00261 if (key1[x] != key2[x]) 00262 return 0; 00263 } 00264 00265 return 1; 00266 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 700 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().
00701 { 00702 struct ast_config *cfg; 00703 struct ast_module *mod; 00704 struct load_order_entry *order; 00705 struct ast_variable *v; 00706 unsigned int load_count; 00707 struct load_order load_order; 00708 int res = 0; 00709 #if LOADABLE_MODULES 00710 struct dirent *dirent; 00711 DIR *dir; 00712 #endif 00713 00714 /* all embedded modules have registered themselves by now */ 00715 embedding = 0; 00716 00717 if (option_verbose) 00718 ast_verbose("Asterisk Dynamic Loader Starting:\n"); 00719 00720 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00721 00722 AST_LIST_LOCK(&module_list); 00723 00724 if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { 00725 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00726 goto done; 00727 } 00728 00729 /* first, find all the modules we have been explicitly requested to load */ 00730 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00731 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) 00732 add_to_load_order(v->value, &load_order); 00733 } 00734 00735 /* check if 'autoload' is on */ 00736 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00737 /* if so, first add all the embedded modules that are not already running to the load order */ 00738 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00739 /* if it's not embedded, skip it */ 00740 if (mod->lib) 00741 continue; 00742 00743 if (mod->flags.running) 00744 continue; 00745 00746 order = add_to_load_order(mod->resource, &load_order); 00747 } 00748 00749 #if LOADABLE_MODULES 00750 /* if we are allowed to load dynamic modules, scan the directory for 00751 for all available modules and add them as well */ 00752 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00753 while ((dirent = readdir(dir))) { 00754 int ld = strlen(dirent->d_name); 00755 00756 /* Must end in .so to load it. */ 00757 00758 if (ld < 4) 00759 continue; 00760 00761 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00762 continue; 00763 00764 /* if there is already a module by this name in the module_list, 00765 skip this file */ 00766 if (find_resource(dirent->d_name, 0)) 00767 continue; 00768 00769 add_to_load_order(dirent->d_name, &load_order); 00770 } 00771 00772 closedir(dir); 00773 } else { 00774 if (!ast_opt_quiet) 00775 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00776 ast_config_AST_MODULE_DIR); 00777 } 00778 #endif 00779 } 00780 00781 /* now scan the config for any modules we are prohibited from loading and 00782 remove them from the load order */ 00783 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00784 if (strcasecmp(v->name, "noload")) 00785 continue; 00786 00787 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00788 if (!resource_name_match(order->resource, v->value)) { 00789 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00790 free(order->resource); 00791 free(order); 00792 } 00793 } 00794 AST_LIST_TRAVERSE_SAFE_END; 00795 } 00796 00797 /* we are done with the config now, all the information we need is in the 00798 load_order list */ 00799 ast_config_destroy(cfg); 00800 00801 load_count = 0; 00802 AST_LIST_TRAVERSE(&load_order, order, entry) 00803 load_count++; 00804 00805 if (load_count) 00806 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00807 00808 /* first, load only modules that provide global symbols */ 00809 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00810 switch (load_resource(order->resource, 1)) { 00811 case AST_MODULE_LOAD_SUCCESS: 00812 case AST_MODULE_LOAD_DECLINE: 00813 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00814 free(order->resource); 00815 free(order); 00816 break; 00817 case AST_MODULE_LOAD_FAILURE: 00818 res = -1; 00819 goto done; 00820 case AST_MODULE_LOAD_SKIP: 00821 /* try again later */ 00822 break; 00823 } 00824 } 00825 AST_LIST_TRAVERSE_SAFE_END; 00826 00827 /* now load everything else */ 00828 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00829 switch (load_resource(order->resource, 0)) { 00830 case AST_MODULE_LOAD_SUCCESS: 00831 case AST_MODULE_LOAD_DECLINE: 00832 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00833 free(order->resource); 00834 free(order); 00835 break; 00836 case AST_MODULE_LOAD_FAILURE: 00837 res = -1; 00838 goto done; 00839 case AST_MODULE_LOAD_SKIP: 00840 /* should not happen */ 00841 break; 00842 } 00843 } 00844 AST_LIST_TRAVERSE_SAFE_END; 00845 00846 done: 00847 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00848 free(order->resource); 00849 free(order); 00850 } 00851 00852 AST_LIST_UNLOCK(&module_list); 00853 00854 return res; 00855 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 594 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().
00595 { 00596 struct ast_module *mod; 00597 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00598 char tmp[256]; 00599 00600 if ((mod = find_resource(resource_name, 0))) { 00601 if (mod->flags.running) { 00602 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00603 return AST_MODULE_LOAD_DECLINE; 00604 } 00605 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00606 return AST_MODULE_LOAD_SKIP; 00607 } else { 00608 #if LOADABLE_MODULES 00609 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00610 /* don't generate a warning message during load_modules() */ 00611 if (!global_symbols_only) { 00612 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00613 return AST_MODULE_LOAD_DECLINE; 00614 } else { 00615 return AST_MODULE_LOAD_SKIP; 00616 } 00617 } 00618 #else 00619 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00620 return AST_MODULE_LOAD_DECLINE; 00621 #endif 00622 } 00623 00624 if (inspect_module(mod)) { 00625 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00626 #if LOADABLE_MODULES 00627 unload_dynamic_module(mod); 00628 #endif 00629 return AST_MODULE_LOAD_DECLINE; 00630 } 00631 00632 mod->flags.declined = 0; 00633 00634 if (mod->info->load) 00635 res = mod->info->load(); 00636 00637 switch (res) { 00638 case AST_MODULE_LOAD_SUCCESS: 00639 if (!ast_fully_booted) { 00640 if (option_verbose) 00641 ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00642 if (ast_opt_console && !option_verbose) 00643 ast_verbose( "."); 00644 } else { 00645 if (option_verbose) 00646 ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description); 00647 } 00648 00649 mod->flags.running = 1; 00650 00651 ast_update_use_count(); 00652 break; 00653 case AST_MODULE_LOAD_DECLINE: 00654 mod->flags.declined = 1; 00655 break; 00656 case AST_MODULE_LOAD_FAILURE: 00657 break; 00658 case AST_MODULE_LOAD_SKIP: 00659 /* modules should never return this value */ 00660 break; 00661 } 00662 00663 return res; 00664 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 243 of file loader.c.
References ast_log(), and LOG_DEBUG.
Referenced by verify_key().
00244 { 00245 int x, pos; 00246 char buf[256]; /* large enough so we don't have to worry */ 00247 00248 for (pos = 0, x = 0; x < 16; x++) 00249 pos += sprintf(buf + pos, " %02x", *d++); 00250 00251 ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf); 00252 00253 return 0; 00254 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 285 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and load_modules().
00286 { 00287 char *name1 = (char *) name1_in; 00288 char *name2 = (char *) name2_in; 00289 00290 /* trim off any .so extensions */ 00291 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00292 name1 = ast_strdupa(name1); 00293 name1[strlen(name1) - 3] = '\0'; 00294 } 00295 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00296 name2 = ast_strdupa(name2); 00297 name2[strlen(name2) - 3] = '\0'; 00298 } 00299 00300 return strcasecmp(name1, name2); 00301 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 268 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00269 { 00270 struct MD5Context c; 00271 unsigned char digest[16]; 00272 00273 MD5Init(&c); 00274 MD5Update(&c, key, strlen((char *)key)); 00275 MD5Final(digest, &c); 00276 00277 if (key_matches(expected_key, digest)) 00278 return 0; 00279 00280 printdigest(digest); 00281 00282 return -1; 00283 }
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 |