Thu Jul 9 13:41:22 2009

Asterisk developer's documentation


loader.c File Reference

Module Loader. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <dirent.h>
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.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 "asterisk/features.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  ast_module
struct  ast_module_user
struct  load_order
struct  load_order_entry
struct  loadupdate
struct  module_list
struct  module_user_list
struct  reload_classes
struct  reload_queue
struct  reload_queue_item
struct  updaters

Defines

#define RTLD_LOCAL   0
#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_entryadd_to_load_order (const char *resource, struct load_order *load_order)
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 (const 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_moduleast_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)
void ast_process_pending_reloads (void)
 Process reload requests received during startup.
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_modulefind_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)
static struct ast_moduleload_dynamic_module (const char *resource_in, unsigned int global_symbols_only)
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 void queue_reload_request (const char *module)
static int resource_name_match (const char *name1_in, const char *name2_in)
static void unload_dynamic_module (struct ast_module *mod)
static int verify_key (const unsigned char *key)

Variables

static char buildopt_sum [33] = AST_BUILDOPT_SUM
static int do_full_reload = 0
static struct module_list embedded_module_list
static unsigned int embedding = 1
static unsigned char expected_key []
static ast_mutex_t reloadlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
ast_moduleresource_being_loaded


Detailed Description

Module Loader.

Author:
Mark Spencer <markster@digium.com>

Kevin P. Fleming <kpfleming@digium.com>

Luigi Rizzo <rizzo@icir.org>

Definition in file loader.c.


Define Documentation

#define RTLD_LOCAL   0

Definition at line 61 of file loader.c.

Referenced by load_dynamic_module().

#define RTLD_NOW   0

Definition at line 57 of file loader.c.

Referenced by load_dynamic_module().


Function Documentation

struct ast_module_user* __ast_module_user_add ( struct ast_module mod,
struct ast_channel chan 
)

Definition at line 192 of file loader.c.

References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::chan, ast_module_user::entry, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_write(), and pbx_exec().

00194 {
00195    struct ast_module_user *u = ast_calloc(1, sizeof(*u));
00196 
00197    if (!u)
00198       return NULL;
00199 
00200    u->chan = chan;
00201 
00202    AST_LIST_LOCK(&mod->users);
00203    AST_LIST_INSERT_HEAD(&mod->users, u, entry);
00204    AST_LIST_UNLOCK(&mod->users);
00205 
00206    ast_atomic_fetchadd_int(&mod->usecount, +1);
00207 
00208    ast_update_use_count();
00209 
00210    return u;
00211 }

void __ast_module_user_hangup_all ( struct ast_module mod  ) 

Definition at line 224 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_update_use_count(), ast_module_user::chan, ast_module_user::entry, ast_module::usecount, and ast_module::users.

Referenced by ast_unload_resource().

00225 {
00226    struct ast_module_user *u;
00227 
00228    AST_LIST_LOCK(&mod->users);
00229    while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
00230       ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
00231       ast_atomic_fetchadd_int(&mod->usecount, -1);
00232       ast_free(u);
00233    }
00234    AST_LIST_UNLOCK(&mod->users);
00235 
00236    ast_update_use_count();
00237 }

void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 213 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::entry, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_write(), and pbx_exec().

00214 {
00215    AST_LIST_LOCK(&mod->users);
00216    AST_LIST_REMOVE(&mod->users, u, entry);
00217    AST_LIST_UNLOCK(&mod->users);
00218    ast_atomic_fetchadd_int(&mod->usecount, -1);
00219    ast_free(u);
00220 
00221    ast_update_use_count();
00222 }

static struct load_order_entry* add_to_load_order ( const char *  resource,
struct load_order load_order 
) [static]

Definition at line 804 of file loader.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, ast_module_user::entry, load_order_entry::resource, and resource_name_match().

Referenced by load_modules().

00805 {
00806    struct load_order_entry *order;
00807 
00808    AST_LIST_TRAVERSE(load_order, order, entry) {
00809       if (!resource_name_match(order->resource, resource))
00810          return NULL;
00811    }
00812 
00813    if (!(order = ast_calloc(1, sizeof(*order))))
00814       return NULL;
00815 
00816    order->resource = ast_strdup(resource);
00817    AST_LIST_INSERT_TAIL(load_order, order, entry);
00818 
00819    return order;
00820 }

int ast_load_resource ( const char *  resource_name  ) 

Load a module.

Parameters:
resource_name The name of the module to load.
This function is run by the PBX to load the modules. It performs all loading and initilization tasks. Basically, to load a module, just give it the name of the module and it will do the rest.

Returns:
See possible enum values for ast_module_load_result.

Definition at line 787 of file loader.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().

Referenced by file_ok_sel(), handle_load(), manager_moduleload(), and reload().

00788 {
00789    int res;
00790    AST_LIST_LOCK(&module_list);
00791    res = load_resource(resource_name, 0);
00792    AST_LIST_UNLOCK(&module_list);
00793 
00794    return res;
00795 }

int ast_loader_register ( int(*)(void)  updater  ) 

Add a procedure to be run when modules have been updated.

Parameters:
updater The function to run when modules have been updated.
This function adds the given function to a linked list of functions to be run when the modules are updated.

Return values:
0 on success
-1 on failure.

Definition at line 1041 of file loader.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.

Referenced by show_console().

01042 {
01043    struct loadupdate *tmp;
01044 
01045    if (!(tmp = ast_malloc(sizeof(*tmp))))
01046       return -1;
01047 
01048    tmp->updater = v;
01049    AST_LIST_LOCK(&updaters);
01050    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01051    AST_LIST_UNLOCK(&updaters);
01052 
01053    return 0;
01054 }

int ast_loader_unregister ( int(*)(void)  updater  ) 

Remove a procedure to be run when modules are updated.

Parameters:
updater The updater function to unregister.
This removes the given function from the updater list.

Return values:
0 on success
-1 on failure.

Definition at line 1056 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().

01057 {
01058    struct loadupdate *cur;
01059 
01060    AST_LIST_LOCK(&updaters);
01061    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01062       if (cur->updater == v)  {
01063          AST_LIST_REMOVE_CURRENT(entry);
01064          break;
01065       }
01066    }
01067    AST_LIST_TRAVERSE_SAFE_END;
01068    AST_LIST_UNLOCK(&updaters);
01069 
01070    return cur ? 0 : -1;
01071 }

int ast_module_check ( const char *  name  ) 

Check if module with the name given is loaded.

Parameters:
name Module name, like "chan_sip.so"
Return values:
1 if true
0 if false

Definition at line 1028 of file loader.c.

References ast_strlen_zero(), and find_resource().

Referenced by ifmodule_read(), and manager_modulecheck().

01029 {
01030    struct ast_module *cur;
01031 
01032    if (ast_strlen_zero(name))
01033       return 0;       /* FALSE */
01034 
01035    cur = find_resource(name, 1);
01036 
01037    return (cur != NULL);
01038 }

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.

Parameters:
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.
Return values:
A possible completion of the partial match.
NULL if no matches were found.

Definition at line 523 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module_user::entry, ast_module::info, name, ast_module_info::reload, and ast_module::resource.

Referenced by handle_modlist(), handle_reload(), handle_unload(), and load_module().

00524 {
00525    struct ast_module *cur;
00526    int i, which=0, l = strlen(word);
00527    char *ret = NULL;
00528 
00529    if (pos != rpos)
00530       return NULL;
00531 
00532    AST_LIST_LOCK(&module_list);
00533    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00534       if (!strncasecmp(word, cur->resource, l) &&
00535           (cur->info->reload || !needsreload) &&
00536           ++which > state) {
00537          ret = ast_strdup(cur->resource);
00538          break;
00539       }
00540    }
00541    AST_LIST_UNLOCK(&module_list);
00542 
00543    if (!ret) {
00544       for (i=0; !ret && reload_classes[i].name; i++) {
00545          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00546             ret = ast_strdup(reload_classes[i].name);
00547       }
00548    }
00549 
00550    return ret;
00551 }

struct ast_module* ast_module_ref ( struct ast_module mod  ) 

Definition at line 1073 of file loader.c.

References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.

Referenced by __oh323_new(), agi_handle_command(), alsa_new(), ast_agi_register(), ast_iax2_new(), dahdi_new(), fn_wrapper(), gtalk_new(), handle_cli_file_convert(), handle_orig(), mgcp_new(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_new(), skinny_new(), and usbradio_new().

01074 {
01075    ast_atomic_fetchadd_int(&mod->usecount, +1);
01076    ast_update_use_count();
01077 
01078    return mod;
01079 }

void ast_module_register ( const struct ast_module_info info  ) 

Definition at line 130 of file loader.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedding, ast_module_user::entry, ast_module::info, resource_being_loaded, and ast_module::users.

00131 {
00132    struct ast_module *mod;
00133 
00134    if (embedding) {
00135       if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
00136          return;
00137       strcpy(mod->resource, info->name);
00138    } else {
00139       mod = resource_being_loaded;
00140    }
00141 
00142    mod->info = info;
00143    AST_LIST_HEAD_INIT(&mod->users);
00144 
00145    /* during startup, before the loader has been initialized,
00146       there are no threads, so there is no need to take the lock
00147       on this list to manipulate it. it is also possible that it
00148       might be unsafe to use the list lock at that point... so
00149       let's avoid it altogether
00150    */
00151    if (embedding) {
00152       AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
00153    } else {
00154       AST_LIST_LOCK(&module_list);
00155       /* it is paramount that the new entry be placed at the tail of
00156          the list, otherwise the code that uses dlopen() to load
00157          dynamic modules won't be able to find out if the module it
00158          just opened was registered or failed to load
00159       */
00160       AST_LIST_INSERT_TAIL(&module_list, mod, entry);
00161       AST_LIST_UNLOCK(&module_list);
00162    }
00163 
00164    /* give the module a copy of its own handle, for later use in registrations and the like */
00165    *((struct ast_module **) &(info->self)) = mod;
00166 }

int ast_module_reload ( const char *  name  ) 

Reload asterisk modules.

Parameters:
name the name of the module to reload
This function reloads the specified module, or if no modules are specified, it will reload all loaded modules.

Note:
Modules are reloaded using their reload() functions, not unloading them and loading them again.
Returns:
0 if the specified module was not found.
Return values:
1 if the module was found but cannot be reloaded.
-1 if a reload operation is already in progress.
2 if the specfied module was found and reloaded.

Definition at line 618 of file loader.c.

References ast_fully_booted, ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_tvnow(), ast_verb, ast_verbose(), ast_module::declined, ast_module_info::description, ast_module_user::entry, ast_module::flags, ast_module::info, LOG_NOTICE, queue_reload_request(), ast_module_info::reload, ast_module::resource, resource_name_match(), and ast_module::running.

Referenced by action_reload(), action_updateconfig(), ast_process_pending_reloads(), handle_reload(), manager_moduleload(), and monitor_sig_flags().

00619 {
00620    struct ast_module *cur;
00621    int res = 0; /* return value. 0 = not found, others, see below */
00622    int i;
00623 
00624    /* If we aren't fully booted, we just pretend we reloaded but we queue this
00625       up to run once we are booted up. */
00626    if (!ast_fully_booted) {
00627       queue_reload_request(name);
00628       return 0;
00629    }
00630 
00631    if (ast_mutex_trylock(&reloadlock)) {
00632       ast_verbose("The previous reload command didn't finish yet\n");
00633       return -1;  /* reload already in progress */
00634    }
00635    ast_lastreloadtime = ast_tvnow();
00636 
00637    /* Call "predefined" reload here first */
00638    for (i = 0; reload_classes[i].name; i++) {
00639       if (!name || !strcasecmp(name, reload_classes[i].name)) {
00640          reload_classes[i].reload_fn();   /* XXX should check error ? */
00641          res = 2; /* found and reloaded */
00642       }
00643    }
00644 
00645    if (name && res) {
00646       ast_mutex_unlock(&reloadlock);
00647       return res;
00648    }
00649 
00650    AST_LIST_LOCK(&module_list);
00651    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00652       const struct ast_module_info *info = cur->info;
00653 
00654       if (name && resource_name_match(name, cur->resource))
00655          continue;
00656 
00657       if (!cur->flags.running || cur->flags.declined) {
00658          if (!name)
00659             continue;
00660          ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
00661             "Before reloading the module, you must run \"module load %s\" "
00662             "and fix whatever is preventing the module from being initialized.\n",
00663             name, name);
00664          res = 2; /* Don't report that the module was not found */
00665          break;
00666       }
00667 
00668       if (!info->reload) { /* cannot be reloaded */
00669          if (res < 1)   /* store result if possible */
00670             res = 1; /* 1 = no reload() method */
00671          continue;
00672       }
00673 
00674       res = 2;
00675       ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
00676       info->reload();
00677    }
00678    AST_LIST_UNLOCK(&module_list);
00679 
00680    ast_mutex_unlock(&reloadlock);
00681 
00682    return res;
00683 }

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 438 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, ast_module_user::entry, free, ast_module::info, ast_module_info::unload, and ast_module::users.

Referenced by quit_handler().

00439 {
00440    struct ast_module *mod;
00441    AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
00442 
00443    /* We have to call the unload() callbacks in reverse order that the modules
00444     * exist in the module list so it is the reverse order of how they were
00445     * loaded. */
00446 
00447    AST_LIST_LOCK(&module_list);
00448    while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
00449       AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
00450    AST_LIST_UNLOCK(&module_list);
00451 
00452    while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
00453       if (mod->info->unload)
00454          mod->info->unload();
00455       /* Since this should only be called when shutting down "gracefully",
00456        * all channels should be down before we get to this point, meaning
00457        * there will be no module users left. */
00458       AST_LIST_HEAD_DESTROY(&mod->users);
00459       free(mod);
00460    }
00461 }

void ast_module_unref ( struct ast_module mod  ) 

Definition at line 1081 of file loader.c.

References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.

Referenced by agi_handle_command(), alsa_hangup(), ast_agi_unregister(), ast_smdi_interface_destroy(), dahdi_destroy_channel_bynum(), dahdi_hangup(), destroy(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_hangup(), and usbradio_hangup().

01082 {
01083    ast_atomic_fetchadd_int(&mod->usecount, -1);
01084    ast_update_use_count();
01085 }

void ast_module_unregister ( const struct ast_module_info info  ) 

Definition at line 168 of file loader.c.

References ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module_user::entry, ast_module::info, and ast_module::users.

00169 {
00170    struct ast_module *mod = NULL;
00171 
00172    /* it is assumed that the users list in the module structure
00173       will already be empty, or we cannot have gotten to this
00174       point
00175    */
00176    AST_LIST_LOCK(&module_list);
00177    AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00178       if (mod->info == info) {
00179          AST_LIST_REMOVE_CURRENT(entry);
00180          break;
00181       }
00182    }
00183    AST_LIST_TRAVERSE_SAFE_END;
00184    AST_LIST_UNLOCK(&module_list);
00185 
00186    if (mod) {
00187       AST_LIST_HEAD_DESTROY(&mod->users);
00188       ast_free(mod);
00189    }
00190 }

void ast_process_pending_reloads ( void   ) 

Process reload requests received during startup.

This function requests that the loader execute the pending reload requests that were queued during server startup.

Note:
This function will do nothing if the server has not completely started up. Once called, the reload queue is emptied, and further invocations will have no affect.

Definition at line 553 of file loader.c.

References ast_free, ast_fully_booted, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_module_reload(), do_full_reload, ast_module_user::entry, LOG_NOTICE, and reload_queue_item::module.

Referenced by main().

00554 {
00555    struct reload_queue_item *item;
00556 
00557    if (!ast_fully_booted) {
00558       return;
00559    }
00560 
00561    AST_LIST_LOCK(&reload_queue);
00562 
00563    if (do_full_reload) {
00564       do_full_reload = 0;
00565       AST_LIST_UNLOCK(&reload_queue);
00566       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00567       ast_module_reload(NULL);
00568       return;
00569    }
00570 
00571    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00572       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00573       ast_module_reload(item->module);
00574       ast_free(item);
00575    }
00576 
00577    AST_LIST_UNLOCK(&reload_queue);
00578 }

int ast_unload_resource ( const char *  resource_name,
enum  ast_module_unload_mode 
)

Unload a module.

Parameters:
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.
This function unloads a module. It will only unload modules that are not in use (usecount not zero), unless AST_FORCE_FIRM or AST_FORCE_HARD is specified. Setting AST_FORCE_FIRM or AST_FORCE_HARD will unload the module regardless of consequences (NOT RECOMMENDED).

Return values:
0 on success.
-1 on error.

Definition at line 463 of file loader.c.

References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_update_use_count(), ast_module::declined, find_resource(), ast_module::flags, ast_module::info, ast_module::lib, LOG_WARNING, ast_module_info::restore_globals, ast_module::running, unload_dynamic_module(), and ast_module::usecount.

Referenced by exit_now(), handle_unload(), manager_moduleload(), reload(), and remove_module().

00464 {
00465    struct ast_module *mod;
00466    int res = -1;
00467    int error = 0;
00468 
00469    AST_LIST_LOCK(&module_list);
00470 
00471    if (!(mod = find_resource(resource_name, 0))) {
00472       AST_LIST_UNLOCK(&module_list);
00473       ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
00474       return 0;
00475    }
00476 
00477    if (!(mod->flags.running || mod->flags.declined))
00478       error = 1;
00479 
00480    if (!error && (mod->usecount > 0)) {
00481       if (force)
00482          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00483             resource_name, mod->usecount);
00484       else {
00485          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00486             mod->usecount);
00487          error = 1;
00488       }
00489    }
00490 
00491    if (!error) {
00492       __ast_module_user_hangup_all(mod);
00493       res = mod->info->unload();
00494 
00495       if (res) {
00496          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00497          if (force <= AST_FORCE_FIRM)
00498             error = 1;
00499          else
00500             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00501       }
00502    }
00503 
00504    if (!error)
00505       mod->flags.running = mod->flags.declined = 0;
00506 
00507    AST_LIST_UNLOCK(&module_list);
00508 
00509    if (!error && !mod->lib && mod->info && mod->info->restore_globals)
00510       mod->info->restore_globals();
00511 
00512 #ifdef LOADABLE_MODULES
00513    if (!error)
00514       unload_dynamic_module(mod);
00515 #endif
00516 
00517    if (!error)
00518       ast_update_use_count();
00519 
00520    return res;
00521 }

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.

Parameters:
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.
Returns:
the number of modules loaded

Definition at line 1007 of file loader.c.

References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module::info, ast_module::resource, and ast_module::usecount.

Referenced by handle_modlist(), and mod_update().

01009 {
01010    struct ast_module *cur;
01011    int unlock = -1;
01012    int total_mod_loaded = 0;
01013 
01014    if (AST_LIST_TRYLOCK(&module_list))
01015       unlock = 0;
01016  
01017    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01018       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01019    }
01020 
01021    if (unlock)
01022       AST_LIST_UNLOCK(&module_list);
01023 
01024    return total_mod_loaded;
01025 }

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.

Note:
The ast_module_user_* functions take care of calling this function for you.

Definition at line 995 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(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), exit_now(), handle_request_do(), load_module(), load_resource(), oh323_request(), sip_request_call(), and unistim_new().

00996 {
00997    /* Notify any module monitors that the use count for a
00998       resource has changed */
00999    struct loadupdate *m;
01000 
01001    AST_LIST_LOCK(&updaters);
01002    AST_LIST_TRAVERSE(&updaters, m, entry)
01003       m->updater();
01004    AST_LIST_UNLOCK(&updaters);
01005 }

static struct ast_module* find_resource ( const char *  resource,
int  do_lock 
) [static]

Definition at line 320 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module_user::entry, ast_module::resource, and resource_name_match().

Referenced by ast_module_check(), ast_unload_resource(), and load_resource().

00321 {
00322    struct ast_module *cur;
00323 
00324    if (do_lock)
00325       AST_LIST_LOCK(&module_list);
00326 
00327    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00328       if (!resource_name_match(resource, cur->resource))
00329          break;
00330    }
00331 
00332    if (do_lock)
00333       AST_LIST_UNLOCK(&module_list);
00334 
00335    return cur;
00336 }

static unsigned int inspect_module ( const struct ast_module mod  )  [static]

Definition at line 685 of file loader.c.

References ast_log(), ast_strlen_zero(), buildopt_sum, ast_module_info::buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, LOG_WARNING, ast_module::resource, and verify_key().

Referenced by load_resource().

00686 {
00687    if (!mod->info->description) {
00688       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00689       return 1;
00690    }
00691 
00692    if (!mod->info->key) {
00693       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00694       return 1;
00695    }
00696 
00697    if (verify_key((unsigned char *) mod->info->key)) {
00698       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00699       return 1;
00700    }
00701 
00702    if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00703        strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00704       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00705       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00706       return 1;
00707    }
00708 
00709    return 0;
00710 }

static int key_matches ( const unsigned char *  key1,
const unsigned char *  key2 
) [static]

Definition at line 273 of file loader.c.

Referenced by verify_key().

00274 {
00275    int x;
00276 
00277    for (x = 0; x < 16; x++) {
00278       if (key1[x] != key2[x])
00279          return 0;
00280    }
00281 
00282    return 1;
00283 }

static struct ast_module* load_dynamic_module ( const char *  resource_in,
unsigned int  global_symbols_only 
) [static]

Definition at line 351 of file loader.c.

References ast_calloc, ast_config_AST_MODULE_DIR, ast_free, AST_LIST_LAST, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, ast_test_flag, ast_module::info, ast_module::lib, LOG_WARNING, ast_module::resource, resource_being_loaded, RTLD_LOCAL, and RTLD_NOW.

Referenced by load_resource().

00352 {
00353    char fn[PATH_MAX] = "";
00354    void *lib = NULL;
00355    struct ast_module *mod;
00356    unsigned int wants_global;
00357    int space;  /* room needed for the descriptor */
00358    int missing_so = 0;
00359 
00360    space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
00361    if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
00362       missing_so = 1;
00363       space += 3; /* room for the extra ".so" */
00364    }
00365 
00366    snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
00367 
00368    /* make a first load of the module in 'quiet' mode... don't try to resolve
00369       any symbols, and don't export any symbols. this will allow us to peek into
00370       the module's info block (if available) to see what flags it has set */
00371 
00372    resource_being_loaded = ast_calloc(1, space);
00373    if (!resource_being_loaded)
00374       return NULL;
00375    strcpy(resource_being_loaded->resource, resource_in);
00376    if (missing_so)
00377       strcat(resource_being_loaded->resource, ".so");
00378 
00379    if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
00380       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00381       ast_free(resource_being_loaded);
00382       return NULL;
00383    }
00384 
00385    /* the dlopen() succeeded, let's find out if the module
00386       registered itself */
00387    /* note that this will only work properly as long as
00388       ast_module_register() (which is called by the module's
00389       constructor) places the new module at the tail of the
00390       module_list
00391    */
00392    if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
00393       ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
00394       /* no, it did not, so close it and return */
00395       while (!dlclose(lib));
00396       /* note that the module's destructor will call ast_module_unregister(),
00397          which will free the structure we allocated in resource_being_loaded */
00398       return NULL;
00399    }
00400 
00401    wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
00402 
00403    /* if we are being asked only to load modules that provide global symbols,
00404       and this one does not, then close it and return */
00405    if (global_symbols_only && !wants_global) {
00406       while (!dlclose(lib));
00407       return NULL;
00408    }
00409 
00410    while (!dlclose(lib));
00411    resource_being_loaded = NULL;
00412 
00413    /* start the load process again */
00414    resource_being_loaded = ast_calloc(1, space);
00415    if (!resource_being_loaded)
00416       return NULL;
00417    strcpy(resource_being_loaded->resource, resource_in);
00418    if (missing_so)
00419       strcat(resource_being_loaded->resource, ".so");
00420 
00421    if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
00422       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00423       ast_free(resource_being_loaded);
00424       return NULL;
00425    }
00426 
00427    /* since the module was successfully opened, and it registered itself
00428       the previous time we did that, we're going to assume it worked this
00429       time too :) */
00430 
00431    AST_LIST_LAST(&module_list)->lib = lib;
00432    resource_being_loaded = NULL;
00433 
00434    return AST_LIST_LAST(&module_list);
00435 }

int load_modules ( unsigned  int  ) 

Provided by loader.c

Definition at line 822 of file loader.c.

References add_to_load_order(), ast_config_load, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verb, dir, embedding, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by main().

00823 {
00824    struct ast_config *cfg;
00825    struct ast_module *mod;
00826    struct load_order_entry *order;
00827    struct ast_variable *v;
00828    unsigned int load_count;
00829    struct load_order load_order;
00830    int res = 0;
00831    struct ast_flags config_flags = { 0 };
00832    int modulecount = 0;
00833 
00834 #ifdef LOADABLE_MODULES
00835    struct dirent *dirent;
00836    DIR *dir;
00837 #endif
00838 
00839    /* all embedded modules have registered themselves by now */
00840    embedding = 0;
00841 
00842    ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
00843 
00844    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
00845 
00846    AST_LIST_LOCK(&module_list);
00847 
00848    if (embedded_module_list.first) {
00849       module_list.first = embedded_module_list.first;
00850       module_list.last = embedded_module_list.last;
00851       embedded_module_list.first = NULL;
00852    }
00853 
00854    if (!(cfg = ast_config_load(AST_MODULE_CONFIG, config_flags))) {
00855       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
00856       goto done;
00857    }
00858 
00859    /* first, find all the modules we have been explicitly requested to load */
00860    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00861       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
00862          add_to_load_order(v->value, &load_order);
00863       }
00864    }
00865 
00866    /* check if 'autoload' is on */
00867    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
00868       /* if so, first add all the embedded modules that are not already running to the load order */
00869       AST_LIST_TRAVERSE(&module_list, mod, entry) {
00870          /* if it's not embedded, skip it */
00871          if (mod->lib)
00872             continue;
00873 
00874          if (mod->flags.running)
00875             continue;
00876 
00877          order = add_to_load_order(mod->resource, &load_order);
00878       }
00879 
00880 #ifdef LOADABLE_MODULES
00881       /* if we are allowed to load dynamic modules, scan the directory for
00882          for all available modules and add them as well */
00883       if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
00884          while ((dirent = readdir(dir))) {
00885             int ld = strlen(dirent->d_name);
00886 
00887             /* Must end in .so to load it.  */
00888 
00889             if (ld < 4)
00890                continue;
00891 
00892             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
00893                continue;
00894 
00895             /* if there is already a module by this name in the module_list,
00896                skip this file */
00897             if (find_resource(dirent->d_name, 0))
00898                continue;
00899 
00900             add_to_load_order(dirent->d_name, &load_order);
00901          }
00902 
00903          closedir(dir);
00904       } else {
00905          if (!ast_opt_quiet)
00906             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
00907                ast_config_AST_MODULE_DIR);
00908       }
00909 #endif
00910    }
00911 
00912    /* now scan the config for any modules we are prohibited from loading and
00913       remove them from the load order */
00914    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00915       if (strcasecmp(v->name, "noload"))
00916          continue;
00917 
00918       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00919          if (!resource_name_match(order->resource, v->value)) {
00920             AST_LIST_REMOVE_CURRENT(entry);
00921             ast_free(order->resource);
00922             ast_free(order);
00923          }
00924       }
00925       AST_LIST_TRAVERSE_SAFE_END;
00926    }
00927 
00928    /* we are done with the config now, all the information we need is in the
00929       load_order list */
00930    ast_config_destroy(cfg);
00931 
00932    load_count = 0;
00933    AST_LIST_TRAVERSE(&load_order, order, entry)
00934       load_count++;
00935 
00936    if (load_count)
00937       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
00938 
00939    /* first, load only modules that provide global symbols */
00940    AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00941       switch (load_resource(order->resource, 1)) {
00942       case AST_MODULE_LOAD_SUCCESS:
00943          modulecount++;
00944       case AST_MODULE_LOAD_DECLINE:
00945          AST_LIST_REMOVE_CURRENT(entry);
00946          ast_free(order->resource);
00947          ast_free(order);
00948          break;
00949       case AST_MODULE_LOAD_FAILURE:
00950          res = -1;
00951          goto done;
00952       case AST_MODULE_LOAD_SKIP:
00953          /* try again later */
00954          break;
00955       }
00956    }
00957    AST_LIST_TRAVERSE_SAFE_END;
00958 
00959    /* now load everything else */
00960    AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00961       switch (load_resource(order->resource, 0)) {
00962       case AST_MODULE_LOAD_SUCCESS:
00963          modulecount++;
00964       case AST_MODULE_LOAD_DECLINE:
00965          AST_LIST_REMOVE_CURRENT(entry);
00966          ast_free(order->resource);
00967          ast_free(order);
00968          break;
00969       case AST_MODULE_LOAD_FAILURE:
00970          res = -1;
00971          goto done;
00972       case AST_MODULE_LOAD_SKIP:
00973          /* should not happen */
00974          break;
00975       }
00976    }
00977    AST_LIST_TRAVERSE_SAFE_END;
00978 
00979 done:
00980    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
00981       ast_free(order->resource);
00982       ast_free(order);
00983    }
00984 
00985    AST_LIST_UNLOCK(&module_list);
00986    
00987    /* Tell manager clients that are aggressive at logging in that we're done
00988       loading modules. If there's a DNS problem in chan_sip, we might not
00989       even reach this */
00990    manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
00991    
00992    return res;
00993 }

static enum ast_module_load_result load_resource ( const char *  resource_name,
unsigned int  global_symbols_only 
) [static]

Definition at line 712 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_verb, ast_verbose(), ast_module_info::backup_globals, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module::lib, ast_module_info::load, load_dynamic_module(), LOG_WARNING, option_verbose, ast_module::running, term_color(), and unload_dynamic_module().

Referenced by ast_load_resource().

00713 {
00714    struct ast_module *mod;
00715    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00716    char tmp[256];
00717 
00718    if ((mod = find_resource(resource_name, 0))) {
00719       if (mod->flags.running) {
00720          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00721          return AST_MODULE_LOAD_DECLINE;
00722       }
00723       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00724          return AST_MODULE_LOAD_SKIP;
00725    } else {
00726 #ifdef LOADABLE_MODULES
00727       if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
00728          /* don't generate a warning message during load_modules() */
00729          if (!global_symbols_only) {
00730             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00731             return AST_MODULE_LOAD_DECLINE;
00732          } else {
00733             return AST_MODULE_LOAD_SKIP;
00734          }
00735       }
00736 #else
00737       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00738       return AST_MODULE_LOAD_DECLINE;
00739 #endif
00740    }
00741 
00742    if (inspect_module(mod)) {
00743       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00744 #ifdef LOADABLE_MODULES
00745       unload_dynamic_module(mod);
00746 #endif
00747       return AST_MODULE_LOAD_DECLINE;
00748    }
00749 
00750    if (!mod->lib && mod->info->backup_globals()) {
00751       ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
00752       return AST_MODULE_LOAD_DECLINE;
00753    }
00754 
00755    mod->flags.declined = 0;
00756 
00757    if (mod->info->load)
00758       res = mod->info->load();
00759 
00760    switch (res) {
00761    case AST_MODULE_LOAD_SUCCESS:
00762       if (!ast_fully_booted) {
00763          ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00764          if (ast_opt_console && !option_verbose)
00765             ast_verbose( ".");
00766       } else {
00767          ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
00768       }
00769 
00770       mod->flags.running = 1;
00771 
00772       ast_update_use_count();
00773       break;
00774    case AST_MODULE_LOAD_DECLINE:
00775       mod->flags.declined = 1;
00776       break;
00777    case AST_MODULE_LOAD_FAILURE:
00778       break;
00779    case AST_MODULE_LOAD_SKIP:
00780       /* modules should never return this value */
00781       break;
00782    }
00783 
00784    return res;
00785 }

static int printdigest ( const unsigned char *  d  )  [static]

Definition at line 260 of file loader.c.

References ast_debug, and buf.

Referenced by verify_key().

00261 {
00262    int x, pos;
00263    char buf[256]; /* large enough so we don't have to worry */
00264 
00265    for (pos = 0, x = 0; x < 16; x++)
00266       pos += sprintf(buf + pos, " %02x", *d++);
00267 
00268    ast_debug(1, "Unexpected signature:%s\n", buf);
00269 
00270    return 0;
00271 }

static void queue_reload_request ( const char *  module  )  [static]

Definition at line 580 of file loader.c.

References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), do_full_reload, ast_module_user::entry, LOG_ERROR, and reload_queue_item::module.

Referenced by ast_module_reload().

00581 {
00582    struct reload_queue_item *item;
00583 
00584    AST_LIST_LOCK(&reload_queue);
00585 
00586    if (do_full_reload) {
00587       AST_LIST_UNLOCK(&reload_queue);
00588       return;
00589    }
00590 
00591    if (ast_strlen_zero(module)) {
00592       /* A full reload request (when module is NULL) wipes out any previous
00593          reload requests and causes the queue to ignore future ones */
00594       while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00595          ast_free(item);
00596       }
00597       do_full_reload = 1;
00598    } else {
00599       /* No reason to add the same module twice */
00600       AST_LIST_TRAVERSE(&reload_queue, item, entry) {
00601          if (!strcasecmp(item->module, module)) {
00602             AST_LIST_UNLOCK(&reload_queue);
00603             return;
00604          }
00605       }
00606       item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
00607       if (!item) {
00608          ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
00609          AST_LIST_UNLOCK(&reload_queue);
00610          return;
00611       }
00612       strcpy(item->module, module);
00613       AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
00614    }
00615    AST_LIST_UNLOCK(&reload_queue);
00616 }

static int resource_name_match ( const char *  name1_in,
const char *  name2_in 
) [static]

Definition at line 302 of file loader.c.

References ast_strdupa.

Referenced by add_to_load_order(), ast_module_reload(), and find_resource().

00303 {
00304    char *name1 = (char *) name1_in;
00305    char *name2 = (char *) name2_in;
00306 
00307    /* trim off any .so extensions */
00308    if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
00309       name1 = ast_strdupa(name1);
00310       name1[strlen(name1) - 3] = '\0';
00311    }
00312    if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
00313       name2 = ast_strdupa(name2);
00314       name2[strlen(name2) - 3] = '\0';
00315    }
00316 
00317    return strcasecmp(name1, name2);
00318 }

static void unload_dynamic_module ( struct ast_module mod  )  [static]

Definition at line 339 of file loader.c.

References ast_module::lib.

Referenced by ast_unload_resource(), and load_resource().

00340 {
00341    void *lib = mod->lib;
00342 
00343    /* WARNING: the structure pointed to by mod is going to
00344       disappear when this operation succeeds, so we can't
00345       dereference it */
00346 
00347    if (lib)
00348       while (!dlclose(lib));
00349 }

static int verify_key ( const unsigned char *  key  )  [static]

Definition at line 285 of file loader.c.

References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().

Referenced by inspect_module().

00286 {
00287    struct MD5Context c;
00288    unsigned char digest[16];
00289 
00290    MD5Init(&c);
00291    MD5Update(&c, key, strlen((char *)key));
00292    MD5Final(digest, &c);
00293 
00294    if (key_matches(expected_key, digest))
00295       return 0;
00296 
00297    printdigest(digest);
00298 
00299    return -1;
00300 }


Variable Documentation

char buildopt_sum[33] = AST_BUILDOPT_SUM [static]

Definition at line 75 of file loader.c.

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 118 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

struct module_list embedded_module_list [static]

Definition at line 102 of file loader.c.

unsigned int embedding = 1 [static]

Definition at line 77 of file loader.c.

Referenced by ast_module_register(), and load_modules().

unsigned char expected_key[] [static]

Initial value:

{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
  0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }

Definition at line 71 of file loader.c.

Referenced by verify_key().

ast_mutex_t reloadlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 111 of file loader.c.

struct ast_module* resource_being_loaded

Definition at line 126 of file loader.c.

Referenced by ast_module_register(), and load_dynamic_module().


Generated on Thu Jul 9 13:41:23 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7