Thu Apr 8 01:23:05 2010

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 "asterisk/dsp.h"
#include "asterisk/udptl.h"
#include "asterisk/heap.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
struct  reload_queue_item

Defines

#define RTLD_LOCAL   0
#define RTLD_NOW   0

Functions

struct 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)
 AST_LIST_HEAD (module_user_list, ast_module_user)
 AST_LIST_HEAD_NOLOCK (load_order, load_order_entry)
static AST_LIST_HEAD_STATIC (reload_queue, reload_queue_item)
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 (const char *name)
 Check if module exists.
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.
struct 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)
 AST_MUTEX_DEFINE_STATIC (reloadlock)
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)
int load_modules (unsigned int preload_only)
static enum ast_module_load_result load_resource (const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap)
static int load_resource_list (struct load_order *load_order, unsigned int global_symbols, int *mod_count)
static int mod_load_cmp (void *a, void *b)
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 enum ast_module_load_result start_resource (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 []
struct 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>
  • See ModMngMnt

Definition in file loader.c.


Define Documentation

#define RTLD_LOCAL   0

Definition at line 64 of file loader.c.

#define RTLD_NOW   0

Definition at line 60 of file loader.c.


Function Documentation

struct ast_module_user* __ast_module_user_add ( struct ast_module mod,
struct ast_channel chan 
) [read]

Definition at line 195 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::usecount, and ast_module::users.

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

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

void __ast_module_user_hangup_all ( struct ast_module mod  ) 
void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 216 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::usecount, and ast_module::users.

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

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

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

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

00848 {
00849    struct load_order_entry *order;
00850 
00851    AST_LIST_TRAVERSE(load_order, order, entry) {
00852       if (!resource_name_match(order->resource, resource))
00853          return NULL;
00854    }
00855 
00856    if (!(order = ast_calloc(1, sizeof(*order))))
00857       return NULL;
00858 
00859    order->resource = ast_strdup(resource);
00860    AST_LIST_INSERT_TAIL(load_order, order, entry);
00861 
00862    return order;
00863 }

AST_LIST_HEAD ( module_user_list  ,
ast_module_user   
)
AST_LIST_HEAD_NOLOCK ( load_order  ,
load_order_entry   
)
static AST_LIST_HEAD_STATIC ( reload_queue  ,
reload_queue_item   
) [static]
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.

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 initialization 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 830 of file loader.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().

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

00831 {
00832    int res;
00833    AST_LIST_LOCK(&module_list);
00834    res = load_resource(resource_name, 0, NULL);
00835    AST_LIST_UNLOCK(&module_list);
00836 
00837    return res;
00838 }

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 1129 of file loader.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and loadupdate::updater.

Referenced by show_console().

01130 {
01131    struct loadupdate *tmp;
01132 
01133    if (!(tmp = ast_malloc(sizeof(*tmp))))
01134       return -1;
01135 
01136    tmp->updater = v;
01137    AST_LIST_LOCK(&updaters);
01138    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01139    AST_LIST_UNLOCK(&updaters);
01140 
01141    return 0;
01142 }

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 1144 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().

01145 {
01146    struct loadupdate *cur;
01147 
01148    AST_LIST_LOCK(&updaters);
01149    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01150       if (cur->updater == v)  {
01151          AST_LIST_REMOVE_CURRENT(entry);
01152          break;
01153       }
01154    }
01155    AST_LIST_TRAVERSE_SAFE_END;
01156    AST_LIST_UNLOCK(&updaters);
01157 
01158    return cur ? 0 : -1;
01159 }

int ast_module_check ( const char *  name  ) 

Check if module exists.

Check if module with the name given is loaded.

Definition at line 1116 of file loader.c.

References ast_strlen_zero(), and find_resource().

Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().

01117 {
01118    struct ast_module *cur;
01119 
01120    if (ast_strlen_zero(name))
01121       return 0;       /* FALSE */
01122 
01123    cur = find_resource(name, 1);
01124 
01125    return (cur != NULL);
01126 }

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 541 of file loader.c.

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

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

00542 {
00543    struct ast_module *cur;
00544    int i, which=0, l = strlen(word);
00545    char *ret = NULL;
00546 
00547    if (pos != rpos)
00548       return NULL;
00549 
00550    AST_LIST_LOCK(&module_list);
00551    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00552       if (!strncasecmp(word, cur->resource, l) &&
00553           (cur->info->reload || !needsreload) &&
00554           ++which > state) {
00555          ret = ast_strdup(cur->resource);
00556          break;
00557       }
00558    }
00559    AST_LIST_UNLOCK(&module_list);
00560 
00561    if (!ret) {
00562       for (i=0; !ret && reload_classes[i].name; i++) {
00563          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00564             ret = ast_strdup(reload_classes[i].name);
00565       }
00566    }
00567 
00568    return ret;
00569 }

struct ast_module* ast_module_ref ( struct ast_module mod  )  [read]
void ast_module_register ( const struct ast_module_info info  ) 

Definition at line 133 of file loader.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedded_module_list, embedding, ast_module::info, ast_module_info::name, resource_being_loaded, ast_module_info::self, and ast_module::users.

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

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 636 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::flags, ast_module::info, LOG_NOTICE, queue_reload_request(), ast_module_info::reload, 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().

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

void ast_module_shutdown ( void   ) 

Run the unload() callback for all loaded modules.

This function should be called when Asterisk is shutting down gracefully.

Note:
Some resources, like timers, are started up dynamically, and thus may be still in use, even if all channels are dead. We must therefore check the usecount before asking modules to unload.
If we go through the entire list without changing anything, ignore the usecounts and unload, then exit.

Definition at line 443 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, ast_module_info::unload, ast_module::usecount, and ast_module::users.

Referenced by quit_handler().

00444 {
00445    struct ast_module *mod;
00446    int somethingchanged = 1, final = 0;
00447 
00448    AST_LIST_LOCK(&module_list);
00449 
00450    /*!\note Some resources, like timers, are started up dynamically, and thus
00451     * may be still in use, even if all channels are dead.  We must therefore
00452     * check the usecount before asking modules to unload. */
00453    do {
00454       if (!somethingchanged) {
00455          /*!\note If we go through the entire list without changing
00456           * anything, ignore the usecounts and unload, then exit. */
00457          final = 1;
00458       }
00459 
00460       /* Reset flag before traversing the list */
00461       somethingchanged = 0;
00462 
00463       AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00464          if (!final && mod->usecount) {
00465             continue;
00466          }
00467          AST_LIST_REMOVE_CURRENT(entry);
00468          if (mod->info->unload) {
00469             mod->info->unload();
00470          }
00471          AST_LIST_HEAD_DESTROY(&mod->users);
00472          free(mod);
00473          somethingchanged = 1;
00474       }
00475       AST_LIST_TRAVERSE_SAFE_END;
00476    } while (somethingchanged && !final);
00477 
00478    AST_LIST_UNLOCK(&module_list);
00479 }

void ast_module_unref ( struct ast_module mod  ) 
void ast_module_unregister ( const struct ast_module_info info  ) 

Definition at line 171 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::info, and ast_module::users.

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

AST_MUTEX_DEFINE_STATIC ( reloadlock   ) 
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 571 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, and LOG_NOTICE.

Referenced by main().

00572 {
00573    struct reload_queue_item *item;
00574 
00575    if (!ast_fully_booted) {
00576       return;
00577    }
00578 
00579    AST_LIST_LOCK(&reload_queue);
00580 
00581    if (do_full_reload) {
00582       do_full_reload = 0;
00583       AST_LIST_UNLOCK(&reload_queue);
00584       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00585       ast_module_reload(NULL);
00586       return;
00587    }
00588 
00589    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00590       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00591       ast_module_reload(item->module);
00592       ast_free(item);
00593    }
00594 
00595    AST_LIST_UNLOCK(&reload_queue);
00596 }

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 481 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, ast_module_info::unload, and ast_module::usecount.

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

00482 {
00483    struct ast_module *mod;
00484    int res = -1;
00485    int error = 0;
00486 
00487    AST_LIST_LOCK(&module_list);
00488 
00489    if (!(mod = find_resource(resource_name, 0))) {
00490       AST_LIST_UNLOCK(&module_list);
00491       ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
00492       return 0;
00493    }
00494 
00495    if (!(mod->flags.running || mod->flags.declined))
00496       error = 1;
00497 
00498    if (!error && (mod->usecount > 0)) {
00499       if (force)
00500          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00501             resource_name, mod->usecount);
00502       else {
00503          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00504             mod->usecount);
00505          error = 1;
00506       }
00507    }
00508 
00509    if (!error) {
00510       __ast_module_user_hangup_all(mod);
00511       res = mod->info->unload();
00512 
00513       if (res) {
00514          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00515          if (force <= AST_FORCE_FIRM)
00516             error = 1;
00517          else
00518             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00519       }
00520    }
00521 
00522    if (!error)
00523       mod->flags.running = mod->flags.declined = 0;
00524 
00525    AST_LIST_UNLOCK(&module_list);
00526 
00527    if (!error && !mod->lib && mod->info && mod->info->restore_globals)
00528       mod->info->restore_globals();
00529 
00530 #ifdef LOADABLE_MODULES
00531    if (!error)
00532       unload_dynamic_module(mod);
00533 #endif
00534 
00535    if (!error)
00536       ast_update_use_count();
00537 
00538    return res;
00539 }

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 1095 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().

01097 {
01098    struct ast_module *cur;
01099    int unlock = -1;
01100    int total_mod_loaded = 0;
01101 
01102    if (AST_LIST_TRYLOCK(&module_list))
01103       unlock = 0;
01104  
01105    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01106       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01107    }
01108 
01109    if (unlock)
01110       AST_LIST_UNLOCK(&module_list);
01111 
01112    return total_mod_loaded;
01113 }

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 1083 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(), oh323_request(), scheduler_process_request_queue(), sip_request_call(), start_resource(), and unistim_new().

01084 {
01085    /* Notify any module monitors that the use count for a
01086       resource has changed */
01087    struct loadupdate *m;
01088 
01089    AST_LIST_LOCK(&updaters);
01090    AST_LIST_TRAVERSE(&updaters, m, entry)
01091       m->updater();
01092    AST_LIST_UNLOCK(&updaters);
01093 }

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

Definition at line 325 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and resource_name_match().

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

00326 {
00327    struct ast_module *cur;
00328 
00329    if (do_lock)
00330       AST_LIST_LOCK(&module_list);
00331 
00332    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00333       if (!resource_name_match(resource, cur->resource))
00334          break;
00335    }
00336 
00337    if (do_lock)
00338       AST_LIST_UNLOCK(&module_list);
00339 
00340    return cur;
00341 }

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

Definition at line 703 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, and verify_key().

Referenced by load_resource().

00704 {
00705    if (!mod->info->description) {
00706       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00707       return 1;
00708    }
00709 
00710    if (!mod->info->key) {
00711       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00712       return 1;
00713    }
00714 
00715    if (verify_key((unsigned char *) mod->info->key)) {
00716       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00717       return 1;
00718    }
00719 
00720    if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00721        strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00722       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00723       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00724       return 1;
00725    }
00726 
00727    return 0;
00728 }

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

Definition at line 278 of file loader.c.

Referenced by verify_key().

00279 {
00280    int x;
00281 
00282    for (x = 0; x < 16; x++) {
00283       if (key1[x] != key2[x])
00284          return 0;
00285    }
00286 
00287    return 1;
00288 }

int load_modules ( unsigned  int  ) 

Provided by loader.c

Definition at line 940 of file loader.c.

References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load2(), ast_free, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), AST_MODULE_CONFIG, ast_opt_quiet, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, dir, embedded_module_list, embedding, EVENT_FLAG_SYSTEM, find_resource(), ast_module::flags, ast_module::lib, load_resource_list(), LOG_NOTICE, LOG_WARNING, manager_event, ast_variable::name, ast_variable::next, load_order_entry::resource, resource_name_match(), ast_module::running, and ast_variable::value.

Referenced by main().

00941 {
00942    struct ast_config *cfg;
00943    struct ast_module *mod;
00944    struct load_order_entry *order;
00945    struct ast_variable *v;
00946    unsigned int load_count;
00947    struct load_order load_order;
00948    int res = 0;
00949    struct ast_flags config_flags = { 0 };
00950    int modulecount = 0;
00951 
00952 #ifdef LOADABLE_MODULES
00953    struct dirent *dirent;
00954    DIR *dir;
00955 #endif
00956 
00957    /* all embedded modules have registered themselves by now */
00958    embedding = 0;
00959 
00960    ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
00961 
00962    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
00963 
00964    AST_LIST_LOCK(&module_list);
00965 
00966    if (embedded_module_list.first) {
00967       module_list.first = embedded_module_list.first;
00968       module_list.last = embedded_module_list.last;
00969       embedded_module_list.first = NULL;
00970    }
00971 
00972    if (!(cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags))) {
00973       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
00974       goto done;
00975    }
00976 
00977    /* first, find all the modules we have been explicitly requested to load */
00978    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00979       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
00980          add_to_load_order(v->value, &load_order);
00981       }
00982    }
00983 
00984    /* check if 'autoload' is on */
00985    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
00986       /* if so, first add all the embedded modules that are not already running to the load order */
00987       AST_LIST_TRAVERSE(&module_list, mod, entry) {
00988          /* if it's not embedded, skip it */
00989          if (mod->lib)
00990             continue;
00991 
00992          if (mod->flags.running)
00993             continue;
00994 
00995          order = add_to_load_order(mod->resource, &load_order);
00996       }
00997 
00998 #ifdef LOADABLE_MODULES
00999       /* if we are allowed to load dynamic modules, scan the directory for
01000          for all available modules and add them as well */
01001       if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
01002          while ((dirent = readdir(dir))) {
01003             int ld = strlen(dirent->d_name);
01004 
01005             /* Must end in .so to load it.  */
01006 
01007             if (ld < 4)
01008                continue;
01009 
01010             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
01011                continue;
01012 
01013             /* if there is already a module by this name in the module_list,
01014                skip this file */
01015             if (find_resource(dirent->d_name, 0))
01016                continue;
01017 
01018             add_to_load_order(dirent->d_name, &load_order);
01019          }
01020 
01021          closedir(dir);
01022       } else {
01023          if (!ast_opt_quiet)
01024             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
01025                ast_config_AST_MODULE_DIR);
01026       }
01027 #endif
01028    }
01029 
01030    /* now scan the config for any modules we are prohibited from loading and
01031       remove them from the load order */
01032    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01033       if (strcasecmp(v->name, "noload"))
01034          continue;
01035 
01036       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
01037          if (!resource_name_match(order->resource, v->value)) {
01038             AST_LIST_REMOVE_CURRENT(entry);
01039             ast_free(order->resource);
01040             ast_free(order);
01041          }
01042       }
01043       AST_LIST_TRAVERSE_SAFE_END;
01044    }
01045 
01046    /* we are done with the config now, all the information we need is in the
01047       load_order list */
01048    ast_config_destroy(cfg);
01049 
01050    load_count = 0;
01051    AST_LIST_TRAVERSE(&load_order, order, entry)
01052       load_count++;
01053 
01054    if (load_count)
01055       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
01056 
01057    /* first, load only modules that provide global symbols */
01058    if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
01059       goto done;
01060    }
01061 
01062    /* now load everything else */
01063    if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
01064       goto done;
01065    }
01066 
01067 done:
01068    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
01069       ast_free(order->resource);
01070       ast_free(order);
01071    }
01072 
01073    AST_LIST_UNLOCK(&module_list);
01074    
01075    /* Tell manager clients that are aggressive at logging in that we're done
01076       loading modules. If there's a DNS problem in chan_sip, we might not
01077       even reach this */
01078    manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
01079    
01080    return res;
01081 }

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

loads a resource based upon resource_name. If global_symbols_only is set only modules with global symbols will be loaded.

If the ast_heap is provided (not NULL) the module is found and added to the heap without running the module's load() function. By doing this, modules added to the resource_heap can be initialized later in order by priority.

If the ast_heap is not provided, the module's load function will be executed immediately

Definition at line 776 of file loader.c.

References ast_heap_push(), ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_test_flag, ast_module_info::backup_globals, ast_module::declined, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module::lib, LOG_WARNING, ast_module::running, and start_resource().

Referenced by ast_load_resource(), and load_resource_list().

00777 {
00778    struct ast_module *mod;
00779    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00780 
00781    if ((mod = find_resource(resource_name, 0))) {
00782       if (mod->flags.running) {
00783          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00784          return AST_MODULE_LOAD_DECLINE;
00785       }
00786       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00787          return AST_MODULE_LOAD_SKIP;
00788    } else {
00789 #ifdef LOADABLE_MODULES
00790       if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
00791          /* don't generate a warning message during load_modules() */
00792          if (!global_symbols_only) {
00793             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00794             return AST_MODULE_LOAD_DECLINE;
00795          } else {
00796             return AST_MODULE_LOAD_SKIP;
00797          }
00798       }
00799 #else
00800       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00801       return AST_MODULE_LOAD_DECLINE;
00802 #endif
00803    }
00804 
00805    if (inspect_module(mod)) {
00806       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00807 #ifdef LOADABLE_MODULES
00808       unload_dynamic_module(mod);
00809 #endif
00810       return AST_MODULE_LOAD_DECLINE;
00811    }
00812 
00813    if (!mod->lib && mod->info->backup_globals()) {
00814       ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
00815       return AST_MODULE_LOAD_DECLINE;
00816    }
00817 
00818    mod->flags.declined = 0;
00819 
00820    if (resource_heap) {
00821       ast_heap_push(resource_heap, mod);
00822       res = AST_MODULE_LOAD_PRIORITY;
00823    } else {
00824       res = start_resource(mod);
00825    }
00826 
00827    return res;
00828 }

static int load_resource_list ( struct load_order *  load_order,
unsigned int  global_symbols,
int *  mod_count 
) [static]

loads modules in order by load_pri, updates mod_count

Definition at line 882 of file loader.c.

References ast_free, ast_heap_create(), ast_heap_destroy(), ast_heap_pop(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, load_resource(), mod_load_cmp(), load_order_entry::resource, and start_resource().

Referenced by load_modules().

00883 {
00884    struct ast_heap *resource_heap;
00885    struct load_order_entry *order;
00886    struct ast_module *mod;
00887    int count = 0;
00888    int res = 0;
00889 
00890    if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
00891       return -1;
00892    }
00893 
00894    /* first, add find and add modules to heap */
00895    AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
00896       switch (load_resource(order->resource, global_symbols, resource_heap)) {
00897       case AST_MODULE_LOAD_SUCCESS:
00898       case AST_MODULE_LOAD_DECLINE:
00899          AST_LIST_REMOVE_CURRENT(entry);
00900          ast_free(order->resource);
00901          ast_free(order);
00902          break;
00903       case AST_MODULE_LOAD_FAILURE:
00904          res = -1;
00905          goto done;
00906       case AST_MODULE_LOAD_SKIP:
00907          break;
00908       case AST_MODULE_LOAD_PRIORITY:
00909          AST_LIST_REMOVE_CURRENT(entry);
00910          break;
00911       }
00912    }
00913    AST_LIST_TRAVERSE_SAFE_END;
00914 
00915    /* second remove modules from heap sorted by priority */
00916    while ((mod = ast_heap_pop(resource_heap))) {
00917       switch (start_resource(mod)) {
00918       case AST_MODULE_LOAD_SUCCESS:
00919          count++;
00920       case AST_MODULE_LOAD_DECLINE:
00921          break;
00922       case AST_MODULE_LOAD_FAILURE:
00923          res = -1;
00924          goto done;
00925       case AST_MODULE_LOAD_SKIP:
00926       case AST_MODULE_LOAD_PRIORITY:
00927          break;
00928       }
00929    }
00930 
00931 done:
00932    if (mod_count) {
00933       *mod_count += count;
00934    }
00935    ast_heap_destroy(resource_heap);
00936 
00937    return res;
00938 }

static int mod_load_cmp ( void *  a,
void *  b 
) [static]

Definition at line 865 of file loader.c.

References AST_MODFLAG_LOAD_ORDER, ast_test_flag, ast_module::info, and ast_module_info::load_pri.

Referenced by load_resource_list().

00866 {
00867    struct ast_module *a_mod = (struct ast_module *) a;
00868    struct ast_module *b_mod = (struct ast_module *) b;
00869    int res = -1;
00870    /* if load_pri is not set, default is 255.  Lower is better*/
00871    unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
00872    unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
00873    if (a_pri == b_pri) {
00874       res = 0;
00875    } else if (a_pri < b_pri) {
00876       res = 1;
00877    }
00878    return res;
00879 }

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

Definition at line 265 of file loader.c.

References ast_debug, and buf.

Referenced by verify_key().

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

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

Definition at line 598 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, and LOG_ERROR.

Referenced by ast_module_reload().

00599 {
00600    struct reload_queue_item *item;
00601 
00602    AST_LIST_LOCK(&reload_queue);
00603 
00604    if (do_full_reload) {
00605       AST_LIST_UNLOCK(&reload_queue);
00606       return;
00607    }
00608 
00609    if (ast_strlen_zero(module)) {
00610       /* A full reload request (when module is NULL) wipes out any previous
00611          reload requests and causes the queue to ignore future ones */
00612       while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00613          ast_free(item);
00614       }
00615       do_full_reload = 1;
00616    } else {
00617       /* No reason to add the same module twice */
00618       AST_LIST_TRAVERSE(&reload_queue, item, entry) {
00619          if (!strcasecmp(item->module, module)) {
00620             AST_LIST_UNLOCK(&reload_queue);
00621             return;
00622          }
00623       }
00624       item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
00625       if (!item) {
00626          ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
00627          AST_LIST_UNLOCK(&reload_queue);
00628          return;
00629       }
00630       strcpy(item->module, module);
00631       AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
00632    }
00633    AST_LIST_UNLOCK(&reload_queue);
00634 }

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

Definition at line 307 of file loader.c.

References ast_strdupa.

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

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

static enum ast_module_load_result start_resource ( struct ast_module mod  )  [static]

Definition at line 730 of file loader.c.

References ast_fully_booted, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_update_use_count(), ast_verb, ast_verbose, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, ast_module_info::load, option_verbose, ast_module::running, and term_color().

Referenced by load_resource(), and load_resource_list().

00731 {
00732    char tmp[256];
00733    enum ast_module_load_result res;
00734 
00735    if (!mod->info->load) {
00736       return AST_MODULE_LOAD_FAILURE;
00737    }
00738 
00739    res = mod->info->load();
00740 
00741    switch (res) {
00742    case AST_MODULE_LOAD_SUCCESS:
00743       if (!ast_fully_booted) {
00744          ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00745          if (ast_opt_console && !option_verbose)
00746             ast_verbose( ".");
00747       } else {
00748          ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
00749       }
00750 
00751       mod->flags.running = 1;
00752 
00753       ast_update_use_count();
00754       break;
00755    case AST_MODULE_LOAD_DECLINE:
00756       mod->flags.declined = 1;
00757       break;
00758    case AST_MODULE_LOAD_FAILURE:
00759    case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
00760    case AST_MODULE_LOAD_PRIORITY:
00761       break;
00762    }
00763 
00764    return res;
00765 }

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

Definition at line 290 of file loader.c.

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

Referenced by inspect_module().

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


Variable Documentation

char buildopt_sum[33] = AST_BUILDOPT_SUM [static]

Definition at line 78 of file loader.c.

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 121 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

struct module_list embedded_module_list [static]

Definition at line 105 of file loader.c.

Referenced by ast_module_register(), and load_modules().

unsigned int embedding = 1 [static]

Definition at line 80 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 74 of file loader.c.

Referenced by verify_key().

Definition at line 129 of file loader.c.

Referenced by ast_module_register().


Generated on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1