#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 |
Enumerations | |
| enum | flags { FLAG_RUNNING = (1 << 1), FLAG_DECLINED = (1 << 2) } |
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 |
| enum flags |
Definition at line 83 of file loader.c.
00083 { 00084 FLAG_RUNNING = (1 << 1), /* module successfully initialized */ 00085 FLAG_DECLINED = (1 << 2), /* module declined to initialize */ 00086 };
| 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 684 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().
00685 { 00686 struct load_order_entry *order; 00687 00688 AST_LIST_TRAVERSE(load_order, order, entry) { 00689 if (!resource_name_match(order->resource, resource)) 00690 return NULL; 00691 } 00692 00693 if (!(order = ast_calloc(1, sizeof(*order)))) 00694 return NULL; 00695 00696 order->resource = ast_strdup(resource); 00697 AST_LIST_INSERT_TAIL(load_order, order, entry); 00698 00699 return order; 00700 }
| 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 668 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().
00669 { 00670 AST_LIST_LOCK(&module_list); 00671 load_resource(resource_name, 0); 00672 AST_LIST_UNLOCK(&module_list); 00673 00674 return 0; 00675 }
| 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 899 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
00900 { 00901 struct loadupdate *tmp; 00902 00903 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00904 return -1; 00905 00906 tmp->updater = v; 00907 AST_LIST_LOCK(&module_list); 00908 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 00909 AST_LIST_UNLOCK(&module_list); 00910 00911 return 0; 00912 }
| 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 914 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().
00915 { 00916 struct loadupdate *cur; 00917 00918 AST_LIST_LOCK(&module_list); 00919 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 00920 if (cur->updater == v) { 00921 AST_LIST_REMOVE_CURRENT(&updaters, entry); 00922 break; 00923 } 00924 } 00925 AST_LIST_TRAVERSE_SAFE_END; 00926 AST_LIST_UNLOCK(&module_list); 00927 00928 return cur ? 0 : -1; 00929 }
| 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 880 of file loader.c.
References AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_trylock(), and ast_strlen_zero().
Referenced by ifmodule_read().
00881 { 00882 struct ast_module *cur; 00883 int unlock = -1; 00884 int res = 0; 00885 00886 if (ast_strlen_zero(name)) 00887 return 0; /* FALSE */ 00888 00889 if (ast_mutex_trylock(&module_list.lock)) 00890 unlock = 0; 00891 AST_LIST_TRAVERSE(&module_list, cur, entry) 00892 if (!res && !strcasecmp(name, cur->resource)) 00893 res = 1; 00894 if (unlock) 00895 AST_LIST_UNLOCK(&module_list); 00896 return res; 00897 }
| 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 493 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().
00494 { 00495 struct ast_module *cur; 00496 int i, which=0, l = strlen(word); 00497 char *ret = NULL; 00498 00499 if (pos != rpos) 00500 return NULL; 00501 00502 AST_LIST_LOCK(&module_list); 00503 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00504 if (!strncasecmp(word, cur->resource, l) && 00505 (cur->info->reload || !needsreload) && 00506 ++which > state) { 00507 ret = strdup(cur->resource); 00508 break; 00509 } 00510 } 00511 AST_LIST_UNLOCK(&module_list); 00512 00513 if (!ret) { 00514 for (i=0; !ret && reload_classes[i].name; i++) { 00515 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00516 ret = strdup(reload_classes[i].name); 00517 } 00518 } 00519 00520 return ret; 00521 }
| struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 931 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().
00932 { 00933 ast_atomic_fetchadd_int(&mod->usecount, +1); 00934 ast_update_use_count(); 00935 00936 return mod; 00937 }
| 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 523 of file loader.c.
References ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_trylock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), ast_module_info::description, FLAG_DECLINED, FLAG_RUNNING, ast_module::info, option_verbose, ast_module_info::reload, resource_name_match(), and VERBOSE_PREFIX_3.
Referenced by action_updateconfig(), handle_reload(), handle_reload_deprecated(), and monitor_sig_flags().
00524 { 00525 struct ast_module *cur; 00526 int res = 0; /* return value. 0 = not found, others, see below */ 00527 int i; 00528 00529 if (ast_mutex_trylock(&reloadlock)) { 00530 ast_verbose("The previous reload command didn't finish yet\n"); 00531 return -1; /* reload already in progress */ 00532 } 00533 ast_lastreloadtime = time(NULL); 00534 00535 /* Call "predefined" reload here first */ 00536 for (i = 0; reload_classes[i].name; i++) { 00537 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00538 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00539 res = 2; /* found and reloaded */ 00540 } 00541 } 00542 00543 if (name && res) { 00544 ast_mutex_unlock(&reloadlock); 00545 return res; 00546 } 00547 00548 AST_LIST_LOCK(&module_list); 00549 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00550 const struct ast_module_info *info = cur->info; 00551 00552 if (name && resource_name_match(name, cur->resource)) 00553 continue; 00554 00555 if (!ast_test_flag(cur, FLAG_RUNNING | FLAG_DECLINED)) 00556 continue; 00557 00558 if (!info->reload) { /* cannot be reloaded */ 00559 if (res < 1) /* store result if possible */ 00560 res = 1; /* 1 = no reload() method */ 00561 continue; 00562 } 00563 00564 res = 2; 00565 if (option_verbose > 2) 00566 ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description); 00567 info->reload(); 00568 } 00569 AST_LIST_UNLOCK(&module_list); 00570 00571 ast_mutex_unlock(&reloadlock); 00572 00573 return res; 00574 }
| void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 939 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().
00940 { 00941 ast_atomic_fetchadd_int(&mod->usecount, -1); 00942 ast_update_use_count(); 00943 }
| 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 432 of file loader.c.
References __ast_module_user_hangup_all(), ast_clear_flag, AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_flag, ast_update_use_count(), error(), find_resource(), FLAG_DECLINED, FLAG_RUNNING, ast_module::lib, and ast_module::usecount.
Referenced by exit_now(), handle_unload(), handle_unload_deprecated(), reload_module(), and remove_module().
00433 { 00434 struct ast_module *mod; 00435 int res = -1; 00436 int error = 0; 00437 00438 AST_LIST_LOCK(&module_list); 00439 00440 if (!(mod = find_resource(resource_name, 0))) { 00441 AST_LIST_UNLOCK(&module_list); 00442 return 0; 00443 } 00444 00445 if (!ast_test_flag(mod, FLAG_RUNNING | FLAG_DECLINED)) 00446 error = 1; 00447 00448 if (!mod->lib) { 00449 ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n"); 00450 error = 1; 00451 } 00452 00453 if (!error && (mod->usecount > 0)) { 00454 if (force) 00455 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00456 resource_name, mod->usecount); 00457 else { 00458 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00459 mod->usecount); 00460 error = 1; 00461 } 00462 } 00463 00464 if (!error) { 00465 __ast_module_user_hangup_all(mod); 00466 res = mod->info->unload(); 00467 00468 if (res) { 00469 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00470 if (force <= AST_FORCE_FIRM) 00471 error = 1; 00472 else 00473 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00474 } 00475 } 00476 00477 if (!error) 00478 ast_clear_flag(mod, FLAG_RUNNING | FLAG_DECLINED); 00479 00480 AST_LIST_UNLOCK(&module_list); 00481 00482 #if LOADABLE_MODULES 00483 if (!error) 00484 unload_dynamic_module(mod); 00485 #endif 00486 00487 if (!error) 00488 ast_update_use_count(); 00489 00490 return res; 00491 }
| 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 860 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().
00862 { 00863 struct ast_module *cur; 00864 int unlock = -1; 00865 int total_mod_loaded = 0; 00866 00867 if (AST_LIST_TRYLOCK(&module_list)) 00868 unlock = 0; 00869 00870 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00871 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 00872 } 00873 00874 if (unlock) 00875 AST_LIST_UNLOCK(&module_list); 00876 00877 return total_mod_loaded; 00878 }
| 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 848 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().
00849 { 00850 /* Notify any module monitors that the use count for a 00851 resource has changed */ 00852 struct loadupdate *m; 00853 00854 AST_LIST_LOCK(&module_list); 00855 AST_LIST_TRAVERSE(&updaters, m, entry) 00856 m->updater(); 00857 AST_LIST_UNLOCK(&module_list); 00858 }
| static struct ast_module* find_resource | ( | const char * | resource, | |
| int | do_lock | |||
| ) | [static] |
Definition at line 305 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and resource_name_match().
Referenced by ast_unload_resource(), and load_resource().
00306 { 00307 struct ast_module *cur; 00308 00309 if (do_lock) 00310 AST_LIST_LOCK(&module_list); 00311 00312 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00313 if (!resource_name_match(resource, cur->resource)) 00314 break; 00315 } 00316 00317 if (do_lock) 00318 AST_LIST_UNLOCK(&module_list); 00319 00320 return cur; 00321 }
| static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 576 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().
00577 { 00578 if (!mod->info->description) { 00579 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00580 return 1; 00581 } 00582 00583 if (!mod->info->key) { 00584 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00585 return 1; 00586 } 00587 00588 if (verify_key((unsigned char *) mod->info->key)) { 00589 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00590 return 1; 00591 } 00592 00593 return 0; 00594 }
| static int key_matches | ( | const unsigned char * | key1, | |
| const unsigned char * | key2 | |||
| ) | [static] |
Definition at line 258 of file loader.c.
Referenced by verify_key().
00259 { 00260 int x; 00261 00262 for (x = 0; x < 16; x++) { 00263 if (key1[x] != key2[x]) 00264 return 0; 00265 } 00266 00267 return 1; 00268 }
| int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 702 of file loader.c.
References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_load(), AST_LIST_HEAD_INIT_NOLOCK, 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, free, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, option_verbose, load_order_entry::resource, resource_name_match(), and ast_variable::value.
Referenced by main().
00703 { 00704 struct ast_config *cfg; 00705 struct ast_module *mod; 00706 struct load_order_entry *order; 00707 struct ast_variable *v; 00708 unsigned int load_count; 00709 struct load_order load_order; 00710 int res = 0; 00711 #if LOADABLE_MODULES 00712 struct dirent *dirent; 00713 DIR *dir; 00714 #endif 00715 00716 /* all embedded modules have registered themselves by now */ 00717 embedding = 0; 00718 00719 if (option_verbose) 00720 ast_verbose("Asterisk Dynamic Loader Starting:\n"); 00721 00722 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00723 if (option_debug > 1) 00724 ast_log(LOG_DEBUG, "Embedded module found: %s\n", mod->resource); 00725 } 00726 00727 if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { 00728 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00729 return 0; 00730 } 00731 00732 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00733 00734 /* first, find all the modules we have been explicitly requested to load */ 00735 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00736 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) 00737 add_to_load_order(v->value, &load_order); 00738 } 00739 00740 /* check if 'autoload' is on */ 00741 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00742 /* if so, first add all the embedded modules to the load order */ 00743 AST_LIST_TRAVERSE(&module_list, mod, entry) 00744 order = add_to_load_order(mod->resource, &load_order); 00745 00746 #if LOADABLE_MODULES 00747 /* if we are allowed to load dynamic modules, scan the directory for 00748 for all available modules and add them as well */ 00749 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00750 while ((dirent = readdir(dir))) { 00751 int ld = strlen(dirent->d_name); 00752 00753 /* Must end in .so to load it. */ 00754 00755 if (ld < 4) 00756 continue; 00757 00758 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00759 continue; 00760 00761 add_to_load_order(dirent->d_name, &load_order); 00762 00763 } 00764 00765 closedir(dir); 00766 } else { 00767 if (!ast_opt_quiet) 00768 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00769 ast_config_AST_MODULE_DIR); 00770 } 00771 #endif 00772 } 00773 00774 /* now scan the config for any modules we are prohibited from loading and 00775 remove them from the load order */ 00776 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00777 if (strcasecmp(v->name, "noload")) 00778 continue; 00779 00780 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00781 if (!resource_name_match(order->resource, v->value)) { 00782 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00783 free(order->resource); 00784 free(order); 00785 } 00786 } 00787 AST_LIST_TRAVERSE_SAFE_END; 00788 } 00789 00790 /* we are done with the config now, all the information we need is in the 00791 load_order list */ 00792 ast_config_destroy(cfg); 00793 00794 load_count = 0; 00795 AST_LIST_TRAVERSE(&load_order, order, entry) 00796 load_count++; 00797 00798 if (load_count) 00799 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00800 00801 /* first, load only modules that provide global symbols */ 00802 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00803 switch (load_resource(order->resource, 1)) { 00804 case AST_MODULE_LOAD_SUCCESS: 00805 case AST_MODULE_LOAD_DECLINE: 00806 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00807 free(order->resource); 00808 free(order); 00809 break; 00810 case AST_MODULE_LOAD_FAILURE: 00811 res = -1; 00812 goto done; 00813 case AST_MODULE_LOAD_SKIP: 00814 /* try again later */ 00815 break; 00816 } 00817 } 00818 AST_LIST_TRAVERSE_SAFE_END; 00819 00820 /* now load everything else */ 00821 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00822 switch (load_resource(order->resource, 0)) { 00823 case AST_MODULE_LOAD_SUCCESS: 00824 case AST_MODULE_LOAD_DECLINE: 00825 AST_LIST_REMOVE_CURRENT(&load_order, entry); 00826 free(order->resource); 00827 free(order); 00828 break; 00829 case AST_MODULE_LOAD_FAILURE: 00830 res = -1; 00831 goto done; 00832 case AST_MODULE_LOAD_SKIP: 00833 /* should not happen */ 00834 break; 00835 } 00836 } 00837 AST_LIST_TRAVERSE_SAFE_END; 00838 00839 done: 00840 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00841 free(order->resource); 00842 free(order); 00843 } 00844 00845 return res; 00846 }
| static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
| unsigned int | global_symbols_only | |||
| ) | [static] |
Definition at line 596 of file loader.c.
References ast_clear_flag, 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_set_flag, ast_test_flag, ast_update_use_count(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, ast_module_info::description, find_resource(), FLAG_DECLINED, FLAG_RUNNING, ast_module::info, inspect_module(), ast_module_info::load, option_verbose, term_color(), and VERBOSE_PREFIX_1.
Referenced by ast_load_resource().
00597 { 00598 struct ast_module *mod; 00599 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00600 char tmp[256]; 00601 00602 if ((mod = find_resource(resource_name, 0))) { 00603 if (ast_test_flag(mod, FLAG_RUNNING)) { 00604 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00605 return AST_MODULE_LOAD_DECLINE; 00606 } 00607 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00608 return AST_MODULE_LOAD_SKIP; 00609 } else { 00610 #if LOADABLE_MODULES 00611 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00612 /* don't generate a warning message during load_modules() */ 00613 if (!global_symbols_only) { 00614 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00615 return AST_MODULE_LOAD_DECLINE; 00616 } else { 00617 return AST_MODULE_LOAD_SKIP; 00618 } 00619 } 00620 #else 00621 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00622 return AST_MODULE_LOAD_DECLINE; 00623 #endif 00624 } 00625 00626 if (inspect_module(mod)) { 00627 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00628 #if LOADABLE_MODULES 00629 unload_dynamic_module(mod); 00630 #endif 00631 return AST_MODULE_LOAD_DECLINE; 00632 } 00633 00634 ast_clear_flag(mod, FLAG_DECLINED); 00635 00636 if (mod->info->load) 00637 res = mod->info->load(); 00638 00639 switch (res) { 00640 case AST_MODULE_LOAD_SUCCESS: 00641 if (!ast_fully_booted) { 00642 if (option_verbose) 00643 ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00644 if (ast_opt_console && !option_verbose) 00645 ast_verbose( "."); 00646 } else { 00647 if (option_verbose) 00648 ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description); 00649 } 00650 00651 ast_set_flag(mod, FLAG_RUNNING); 00652 00653 ast_update_use_count(); 00654 break; 00655 case AST_MODULE_LOAD_DECLINE: 00656 ast_set_flag(mod, FLAG_DECLINED); 00657 break; 00658 case AST_MODULE_LOAD_FAILURE: 00659 break; 00660 case AST_MODULE_LOAD_SKIP: 00661 /* modules should never return this value */ 00662 break; 00663 } 00664 00665 return res; 00666 }
| static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 245 of file loader.c.
References ast_log(), and LOG_DEBUG.
Referenced by verify_key().
00246 { 00247 int x, pos; 00248 char buf[256]; /* large enough so we don't have to worry */ 00249 00250 for (pos = 0, x = 0; x < 16; x++) 00251 pos += sprintf(buf + pos, " %02x", *d++); 00252 00253 ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf); 00254 00255 return 0; 00256 }
| static int resource_name_match | ( | const char * | name1_in, | |
| const char * | name2_in | |||
| ) | [static] |
Definition at line 287 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and load_modules().
00288 { 00289 char *name1 = (char *) name1_in; 00290 char *name2 = (char *) name2_in; 00291 00292 /* trim off any .so extensions */ 00293 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00294 name1 = ast_strdupa(name1); 00295 name1[strlen(name1) - 3] = '\0'; 00296 } 00297 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00298 name2 = ast_strdupa(name2); 00299 name2[strlen(name2) - 3] = '\0'; 00300 } 00301 00302 return strcasecmp(name1, name2); 00303 }
| static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 270 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00271 { 00272 struct MD5Context c; 00273 unsigned char digest[16]; 00274 00275 MD5Init(&c); 00276 MD5Update(&c, key, strlen((char *)key)); 00277 MD5Final(digest, &c); 00278 00279 if (key_matches(expected_key, digest)) 00280 return 0; 00281 00282 printdigest(digest); 00283 00284 return -1; 00285 }
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 |
1.5.1