Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:03 2009

## Asterisk developer's documentation

# loader.c File Reference

Module Loader. More...

`#include <stdio.h>`
`#include <dirent.h>`
`#include <unistd.h>`
`#include <stdlib.h>`
`#include <string.h>`
`#include "asterisk.h"`
`#include "asterisk/module.h"`
`#include "asterisk/options.h"`
`#include "asterisk/config.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/term.h"`
`#include "asterisk/manager.h"`
`#include "asterisk/cdr.h"`
`#include "asterisk/enum.h"`
`#include "asterisk/rtp.h"`
`#include "asterisk/lock.h"`
`#include <dlfcn.h>`
`#include "asterisk/md5.h"`

Include dependency graph for loader.c:

Go to the source code of this file.

## Data Structures

struct | loadupdate
struct | module

## Defines

#define | RTLD_NOW 0

## Functions

static int | __load_resource (const char *resource_name, const struct ast_config *cfg)
int | ast_load_resource (const char *resource_name)
| Load a module.
int | ast_loader_register (int(*v)(void))
| Add a procedure to be run when modules have been updated.
int | ast_loader_unregister (int(*v)(void))
| Remove a procedure to be run when modules are updated.
char * | ast_module_helper (char *line, char *word, int pos, int state, int rpos, int needsreload)
| Match modules names for the Asterisk cli.
int | ast_module_reload (const char *name)
| Reload asterisk modules.
| AST_MUTEX_DEFINE_STATIC (reloadlock)
| AST_MUTEX_DEFINE_STATIC (modlock)
static int | ast_resource_exists (char *resource)
int | ast_unload_resource (const char *resource_name, int force)
| Unloads 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 int | key_matches (unsigned char *key1, unsigned char *key2)
int | load_modules (const int preload_only)
static int | printdigest (unsigned char *d)
static int | verify_key (unsigned char *key)

## Variables

static unsigned char | expected_key []
static const char * | loadorder []
static int | modlistver = 0
static struct module * | module_list = NULL
static struct loadupdate * | updaters

## Detailed Description

Module Loader.

Definition in file loader.c.

## Define Documentation

#define RTLD_NOW 0

Definition at line 54 of file loader.c.

Referenced by __load_resource(), dlopen(), and loadModule().

## Function Documentation

static int __load_resource | ( | const char * | resource_name,
|  | const struct ast_config * | cfg |
| ) |  |  | `[static]`

Definition at line 271 of file loader.c.

References ast_config_AST_MODULE_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_unload_resource(), ast_update_use_count(), ast_variable_retrieve(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, module::description, dlclose(), dlerror(), dlopen(), dlsym(), free, fully_booted, module::key, key(), module::lib, module::load_module, LOG_WARNING, malloc, module::next, option_console, option_verbose, module::reload, module::resource, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, term_color(), module::unload_module, module::usecount, VERBOSE_PREFIX_1, and verify_key().

Referenced by ast_load_resource(), and load_modules().

    00272 {
    00273    static char fn[256];
    00274    int errors=0;
    00275    int res;
    00276    struct module *m;
    00277    int flags=RTLD_NOW;
    00278 #ifdef RTLD_GLOBAL
    00279    char *val;
    00280 #endif
    00281    unsigned char *key;
    00282    char tmp[80];
    00283
    00284    if (strncasecmp(resource_name, "res_", 4)) {
    00285 #ifdef RTLD_GLOBAL
    00286       if (cfg) {
    00287          if ((val = ast_variable_retrieve(cfg, "global", resource_name))
    00288                && ast_true(val))
    00289             flags |= RTLD_GLOBAL;
    00290       }
    00291 #endif
    00292    } else {
    00293       /* Resource modules are always loaded global and lazy */
    00294 #ifdef RTLD_GLOBAL
    00295       flags = (RTLD_GLOBAL | RTLD_LAZY);
    00296 #else
    00297       flags = RTLD_LAZY;
    00298 #endif
    00299    }
    00300
    00301    if (ast_mutex_lock(&modlock))
    00302       ast_log(LOG_WARNING, "Failed to lock\n");
    00303    m = module_list;
    00304    while(m) {
    00305       if (!strcasecmp(m->resource, resource_name)) {
    00306          ast_log(LOG_WARNING, "Module '%s' already exists\n", resource_name);
    00307          ast_mutex_unlock(&modlock);
    00308          return -1;
    00309       }
    00310       m = m->next;
    00311    }
    00312    m = malloc(sizeof(struct module));
    00313    if (!m) {
    00314       ast_log(LOG_WARNING, "Out of memory\n");
    00315       ast_mutex_unlock(&modlock);
    00316       return -1;
    00317    }
    00318    strncpy(m->resource, resource_name, sizeof(m->resource)-1);
    00319    if (resource_name[0] == '/') {
    00320       strncpy(fn, resource_name, sizeof(fn)-1);
    00321    } else {
    00322       snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_MODULE_DIR, resource_name);
    00323    }
    00324    m->lib = dlopen(fn, flags);
    00325    if (!m->lib) {
    00326       ast_log(LOG_WARNING, "%s\n", dlerror());
    00327       free(m);
    00328       ast_mutex_unlock(&modlock);
    00329       return -1;
    00330    }
    00331    m->load_module = dlsym(m->lib, "load_module");
    00332    if (m->load_module == NULL)
    00333       m->load_module = dlsym(m->lib, "_load_module");
    00334    if (!m->load_module) {
    00335       ast_log(LOG_WARNING, "No load_module in module %s\n", fn);
    00336       errors++;
    00337    }
    00338    m->unload_module = dlsym(m->lib, "unload_module");
    00339    if (m->unload_module == NULL)
    00340       m->unload_module = dlsym(m->lib, "_unload_module");
    00341    if (!m->unload_module) {
    00342       ast_log(LOG_WARNING, "No unload_module in module %s\n", fn);
    00343       errors++;
    00344    }
    00345    m->usecount = dlsym(m->lib, "usecount");
    00346    if (m->usecount == NULL)
    00347       m->usecount = dlsym(m->lib, "_usecount");
    00348    if (!m->usecount) {
    00349       ast_log(LOG_WARNING, "No usecount in module %s\n", fn);
    00350       errors++;
    00351    }
    00352    m->description = dlsym(m->lib, "description");
    00353    if (m->description == NULL)
    00354       m->description = dlsym(m->lib, "_description");
    00355    if (!m->description) {
    00356       ast_log(LOG_WARNING, "No description in module %s\n", fn);
    00357       errors++;
    00358    }
    00359    m->key = dlsym(m->lib, "key");
    00360    if (m->key == NULL)
    00361       m->key = dlsym(m->lib, "_key");
    00362    if (!m->key) {
    00363       ast_log(LOG_WARNING, "No key routine in module %s\n", fn);
    00364       errors++;
    00365    }
    00366
    00367    m->reload = dlsym(m->lib, "reload");
    00368    if (m->reload == NULL)
    00369       m->reload = dlsym(m->lib, "_reload");
    00370
    00371    if (!m->key || !(key = (unsigned char *) m->key())) {
    00372       ast_log(LOG_WARNING, "Key routine returned NULL in module %s\n", fn);
    00373       key = NULL;
    00374       errors++;
    00375    }
    00376    if (key && verify_key(key)) {
    00377       ast_log(LOG_WARNING, "Unexpected key returned by module %s\n", fn);
    00378       errors++;
    00379    }
    00380    if (errors) {
    00381       ast_log(LOG_WARNING, "%d error%s loading module %s, aborted\n", errors, (errors != 1) ? "s" : "", fn);
    00382       dlclose(m->lib);
    00383       free(m);
    00384       ast_mutex_unlock(&modlock);
    00385       return -1;
    00386    }
    00387    if (!fully_booted) {
    00388       if (option_verbose)
    00389          ast_verbose( " => (%s)\n", term_color(tmp, m->description(), COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
    00390       if (option_console && !option_verbose)
    00391          ast_verbose( ".");
    00392    } else {
    00393       if (option_verbose)
    00394          ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", fn, m->description());
    00395    }
    00396
    00397    /* add module 'm' to end of module_list chain
    00398       so reload commands will be issued in same order modules were loaded */
    00399    m->next = NULL;
    00400    if (module_list == NULL) {
    00401       /* empty list so far, add at front */
    00402       module_list = m;
    00403    }
    00404    else {
    00405       struct module *i;
    00406       /* find end of chain, and add there */
    00407       for (i = module_list; i->next; i = i->next)
    00408          ;
    00409       i->next = m;
    00410    }
    00411
    00412    modlistver = rand();
    00413    ast_mutex_unlock(&modlock);
    00414    if ((res = m->load_module())) {
    00415       ast_log(LOG_WARNING, "%s: load_module failed, returning %d\n", m->resource, res);
    00416       ast_unload_resource(resource_name, 0);
    00417       return -1;
    00418    }
    00419    ast_update_use_count();
    00420    return 0;
    00421 }

int ast_load_resource | ( | const char * | resource_name | ) |

Load a module.

Parameters:

  | resource_name | The filename 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:
  Zero on success, -1 on error.

Definition at line 423 of file loader.c.

References __load_resource(), ast_config_destroy(), ast_config_load(), AST_MODULE_CONFIG, cfg, and option_verbose.

Referenced by file_ok_sel(), handle_load(), load_module(), and reload_module().

    00424 {
    00425    int o;
    00426    struct ast_config *cfg = NULL;
    00427    int res;
    00428
    00429    /* Keep the module file parsing silent */
    00430    o = option_verbose;
    00431    option_verbose = 0;
    00432    cfg = ast_config_load(AST_MODULE_CONFIG);
    00433    option_verbose = o;
    00434    res = __load_resource(resource_name, cfg);
    00435    if (cfg)
    00436       ast_config_destroy(cfg);
    00437    return res;
    00438 }

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.

Returns:
  Zero on success and -1 on failure.

Definition at line 609 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, malloc, loadupdate::next, loadupdate::updater, and updaters.

Referenced by show_console().

    00610 {
    00611    struct loadupdate *tmp;
    00612    /* XXX Should be more flexible here, taking > 1 verboser XXX */
    00613    if ((tmp = malloc(sizeof (struct loadupdate)))) {
    00614       tmp->updater = v;
    00615       if (ast_mutex_lock(&modlock))
    00616          ast_log(LOG_WARNING, "Failed to lock\n");
    00617       tmp->next = updaters;
    00618       updaters = tmp;
    00619       ast_mutex_unlock(&modlock);
    00620       return 0;
    00621    }
    00622    return -1;
    00623 }

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.

Returns:
  Zero on success, -1 on failure.

Definition at line 625 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, loadupdate::next, loadupdate::updater, and updaters.

Referenced by exit_now().

    00626 {
    00627    int res = -1;
    00628    struct loadupdate *tmp, *tmpl=NULL;
    00629    if (ast_mutex_lock(&modlock))
    00630       ast_log(LOG_WARNING, "Failed to lock\n");
    00631    tmp = updaters;
    00632    while(tmp) {
    00633       if (tmp->updater == v)  {
    00634          if (tmpl)
    00635             tmpl->next = tmp->next;
    00636          else
    00637             updaters = tmp->next;
    00638          break;
    00639       }
    00640       tmpl = tmp;
    00641       tmp = tmp->next;
    00642    }
    00643    if (tmp)
    00644       res = 0;
    00645    ast_mutex_unlock(&modlock);
    00646    return res;
    00647 }

char* ast_module_helper | ( | char * | line,
|  | 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.

Returns:
  A possible completion of the partial match, or NULL if no matches were found.

Definition at line 166 of file loader.c.

References ast_mutex_lock(), ast_mutex_unlock(), module::next, module::reload, module::resource, and strdup.

Referenced by complete_mod_2(), and complete_mod_4().

    00167 {
    00168    struct module *m;
    00169    int which=0;
    00170    char *ret;
    00171
    00172    if (pos != rpos)
    00173       return NULL;
    00174    ast_mutex_lock(&modlock);
    00175    m = module_list;
    00176    while(m) {
    00177       if (!strncasecmp(word, m->resource, strlen(word)) && (m->reload || !needsreload)) {
    00178          if (++which > state)
    00179             break;
    00180       }
    00181       m = m->next;
    00182    }
    00183    if (m) {
    00184       ret = strdup(m->resource);
    00185    } else {
    00186       ret = NULL;
    00187       if (!strncasecmp(word, "extconfig", strlen(word))) {
    00188          if (++which > state)
    00189             ret = strdup("extconfig");
    00190       } else if (!strncasecmp(word, "manager", strlen(word))) {
    00191          if (++which > state)
    00192             ret = strdup("manager");
    00193       } else if (!strncasecmp(word, "enum", strlen(word))) {
    00194          if (++which > state)
    00195             ret = strdup("enum");
    00196       } else if (!strncasecmp(word, "rtp", strlen(word))) {
    00197          if (++which > state)
    00198             ret = strdup("rtp");
    00199       }
    00200
    00201    }
    00202    ast_mutex_unlock(&modlock);
    00203    return ret;
    00204 }

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:
  Zero if the specified module was not found, 1 if the module was found but cannot be reloaded, -1 if a reload operation is already in progress, and 2 if the specfied module was found and reloaded.

Definition at line 206 of file loader.c.

References ast_cdr_engine_reload(), ast_enum_reload(), ast_lastreloadtime, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_rtp_reload(), ast_verbose(), module::description, dnsmgr_reload(), module::next, option_verbose, read_config_maps(), module::reload, reload(), reload_manager(), module::resource, and VERBOSE_PREFIX_3.

Referenced by handle_reload(), and monitor_sig_flags().

    00207 {
    00208    struct module *m;
    00209    int reloaded = 0;
    00210    int oldversion;
    00211    int (*reload)(void);
    00212    /* We'll do the logger and manager the favor of calling its reload here first */
    00213
    00214    if (ast_mutex_trylock(&reloadlock)) {
    00215       ast_verbose("The previous reload command didn't finish yet\n");
    00216       return -1;
    00217    }
    00218    time(&ast_lastreloadtime);
    00219
    00220    if (!name || !strcasecmp(name, "extconfig")) {
    00221       read_config_maps();
    00222       reloaded = 2;
    00223    }
    00224    if (!name || !strcasecmp(name, "manager")) {
    00225       reload_manager();
    00226       reloaded = 2;
    00227    }
    00228    if (!name || !strcasecmp(name, "cdr")) {
    00229       ast_cdr_engine_reload();
    00230       reloaded = 2;
    00231    }
    00232    if (!name || !strcasecmp(name, "enum")) {
    00233       ast_enum_reload();
    00234       reloaded = 2;
    00235    }
    00236    if (!name || !strcasecmp(name, "rtp")) {
    00237       ast_rtp_reload();
    00238       reloaded = 2;
    00239    }
    00240    if (!name || !strcasecmp(name, "dnsmgr")) {
    00241       dnsmgr_reload();
    00242       reloaded = 2;
    00243    }
    00244
    00245    ast_mutex_lock(&modlock);
    00246    oldversion = modlistver;
    00247    m = module_list;
    00248    while(m) {
    00249       if (!name || !strcasecmp(name, m->resource)) {
    00250          if (reloaded < 1)
    00251             reloaded = 1;
    00252          reload = m->reload;
    00253          ast_mutex_unlock(&modlock);
    00254          if (reload) {
    00255             reloaded = 2;
    00256             if (option_verbose > 2)
    00257                ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", m->resource, m->description());
    00258             reload();
    00259          }
    00260          ast_mutex_lock(&modlock);
    00261          if (oldversion != modlistver)
    00262             break;
    00263       }
    00264       m = m->next;
    00265    }
    00266    ast_mutex_unlock(&modlock);
    00267    ast_mutex_unlock(&reloadlock);
    00268    return reloaded;
    00269 }

AST_MUTEX_DEFINE_STATIC | ( | reloadlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | modlock |  | ) |

static int ast_resource_exists | ( | char * | resource | ) | `[static]`

Definition at line 440 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, module::next, and module::resource.

Referenced by load_modules().

    00441 {
    00442    struct module *m;
    00443    if (ast_mutex_lock(&modlock))
    00444       ast_log(LOG_WARNING, "Failed to lock\n");
    00445    m = module_list;
    00446    while(m) {
    00447       if (!strcasecmp(resource, m->resource))
    00448          break;
    00449       m = m->next;
    00450    }
    00451    ast_mutex_unlock(&modlock);
    00452    if (m)
    00453       return -1;
    00454    else
    00455       return 0;
    00456 }

int ast_unload_resource | ( | const char * | resource_name,
|  | int | force |
| ) |  |  |

Unloads a module.

Parameters:

  | resource_name | The name of the module to unload.
  | force | 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).

Returns:
  Zero on success, -1 on error.

Definition at line 122 of file loader.c.

References AST_FORCE_FIRM, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), dlclose(), free, module::lib, LOG_WARNING, module::next, module::resource, module::unload_module, and module::usecount.

Referenced by __load_resource(), exit_now(), handle_unload(), reload_module(), and remove_module().

    00123 {
    00124    struct module *m, *ml = NULL;
    00125    int res = -1;
    00126    if (ast_mutex_lock(&modlock))
    00127       ast_log(LOG_WARNING, "Failed to lock\n");
    00128    m = module_list;
    00129    while(m) {
    00130       if (!strcasecmp(m->resource, resource_name)) {
    00131          if ((res = m->usecount()) > 0)  {
    00132             if (force)
    00133                ast_log(LOG_WARNING, "Warning:  Forcing removal of module %s with use count %d\n", resource_name, res);
    00134             else {
    00135                ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, res);
    00136                ast_mutex_unlock(&modlock);
    00137                return -1;
    00138             }
    00139          }
    00140          res = m->unload_module();
    00141          if (res) {
    00142             ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
    00143             if (force <= AST_FORCE_FIRM) {
    00144                ast_mutex_unlock(&modlock);
    00145                return -1;
    00146             } else
    00147                ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
    00148          }
    00149          if (ml)
    00150             ml->next = m->next;
    00151          else
    00152             module_list = m->next;
    00153          dlclose(m->lib);
    00154          free(m);
    00155          break;
    00156       }
    00157       ml = m;
    00158       m = m->next;
    00159    }
    00160    modlistver = rand();
    00161    ast_mutex_unlock(&modlock);
    00162    ast_update_use_count();
    00163    return res;
    00164 }

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

References ast_mutex_trylock(), ast_mutex_unlock(), module::description, module::next, module::resource, and module::usecount.

Referenced by handle_modlist(), and mod_update().

    00591 {
    00592    struct module *m;
    00593    int unlock = -1;
    00594    int total_mod_loaded = 0;
    00595
    00596    if (ast_mutex_trylock(&modlock))
    00597       unlock = 0;
    00598    m = module_list;
    00599    while (m) {
    00600       total_mod_loaded += modentry(m->resource, m->description(), m->usecount(), like);
    00601       m = m->next;
    00602    }
    00603    if (unlock)
    00604       ast_mutex_unlock(&modlock);
    00605
    00606    return total_mod_loaded;
    00607 }

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 LOCAL_USER macros take care of calling this function for you.

Definition at line 573 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, loadupdate::next, loadupdate::updater, and updaters.

Referenced by __load_resource(), __oh323_new(), adpcm_destroy(), adpcmtolin_new(), agent_new(), alaw_destroy(), alawtolin_new(), alawtoulaw_new(), alsa_new(), aopen_decusecnt(), aopen_incusecnt(), ast_iax2_new(), ast_modem_new(), ast_unload_resource(), au_close(), au_open(), au_rewrite(), bestdata_decusecnt(), bestdata_incusecnt(), exit_now(), features_new(), g723_close(), g723_destroy(), g723_open(), g723_rewrite(), g723tolin_new(), g726_16_open(), g726_16_rewrite(), g726_24_open(), g726_24_rewrite(), g726_32_open(), g726_32_rewrite(), g726_40_open(), g726_40_rewrite(), g726_close(), g726_destroy(), g726tolin_new(), g729_close(), g729_open(), g729_rewrite(), gsm_close(), gsm_open(), gsm_rewrite(), h263_close(), h263_open(), h263_rewrite(), i4l_decusecnt(), i4l_incusecnt(), iax2_predestroy(), ilbc_close(), ilbc_open(), ilbc_rewrite(), lintoadpcm_new(), lintoalaw_new(), lintog723_new(), lintog726_new(), lintoulaw_new(), load_module(), local_new(), mgcp_hangup(), mgcp_new(), modem_hangup(), nbs_new(), ogg_vorbis_close(), ogg_vorbis_open(), ogg_vorbis_rewrite(), oh323_hangup(), oh323_request(), oss_new(), pcm_close(), pcm_open(), pcm_rewrite(), phone_check_exception(), phone_hangup(), phone_new(), sip_hangup(), sip_new(), sip_request_call(), sipsock_read(), skinny_new(), slinear_close(), slinear_open(), slinear_rewrite(), ulaw_destroy(), ulawtoalaw_new(), ulawtolin_new(), vox_close(), vox_open(), vox_rewrite(), vpb_hangup(), vpb_new(), wav_close(), wav_open(), wav_rewrite(), zt_hangup(), and zt_new().

    00574 {
    00575    /* Notify any module monitors that the use count for a
    00576       resource has changed */
    00577    struct loadupdate *m;
    00578    if (ast_mutex_lock(&modlock))
    00579       ast_log(LOG_WARNING, "Failed to lock\n");
    00580    m = updaters;
    00581    while(m) {
    00582       m->updater();
    00583       m = m->next;
    00584    }
    00585    ast_mutex_unlock(&modlock);
    00586
    00587 }

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

Definition at line 99 of file loader.c.

References match().

Referenced by verify_key().

    00100 {
    00101    int match = 1;
    00102    int x;
    00103    for (x=0; x<16; x++) {
    00104       match &= (key1[x] == key2[x]);
    00105    }
    00106    return match;
    00107 }

int load_modules | ( | const int | preload_only | ) |

Definition at line 466 of file loader.c.

References __load_resource(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load(), ast_log(), AST_MODULE_CONFIG, ast_resource_exists(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), cfg, COLOR_BRWHITE, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, option_debug, option_quiet, option_verbose, term_color(), ast_variable::value, and VERBOSE_PREFIX_1.

Referenced by main().

    00467 {
    00468    struct ast_config *cfg;
    00469    struct ast_variable *v;
    00470    char tmp[80];
    00471
    00472    if (option_verbose) {
    00473       if (preload_only)
    00474          ast_verbose("Asterisk Dynamic Loader loading preload modules:\n");
    00475       else
    00476          ast_verbose("Asterisk Dynamic Loader Starting:\n");
    00477    }
    00478
    00479    cfg = ast_config_load(AST_MODULE_CONFIG);
    00480    if (cfg) {
    00481       int doload;
    00482
    00483       /* Load explicitly defined modules */
    00484       for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
    00485          doload = 0;
    00486
    00487          if (preload_only)
    00488             doload = !strcasecmp(v->name, "preload");
    00489          else
    00490             doload = !strcasecmp(v->name, "load");
    00491
    00492              if (doload) {
    00493             if (option_debug && !option_verbose)
    00494                ast_log(LOG_DEBUG, "Loading module %s\n", v->value);
    00495             if (option_verbose) {
    00496                ast_verbose(VERBOSE_PREFIX_1 "[%s]", term_color(tmp, v->value, COLOR_BRWHITE, 0, sizeof(tmp)));
    00497                fflush(stdout);
    00498             }
    00499             if (__load_resource(v->value, cfg)) {
    00500                ast_log(LOG_WARNING, "Loading module %s failed!\n", v->value);
    00501                ast_config_destroy(cfg);
    00502                return -1;
    00503             }
    00504          }
    00505       }
    00506    }
    00507
    00508    if (preload_only) {
    00509       ast_config_destroy(cfg);
    00510       return 0;
    00511    }
    00512
    00513    if (!cfg || ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
    00514       /* Load all modules */
    00515       DIR *mods;
    00516       struct dirent *d;
    00517       int x;
    00518
    00519       /* Loop through each order */
    00520       for (x=0; x<sizeof(loadorder) / sizeof(loadorder[0]); x++) {
    00521          mods = opendir((char *)ast_config_AST_MODULE_DIR);
    00522          if (mods) {
    00523             while((d = readdir(mods))) {
    00524                /* Must end in .so to load it.  */
    00525                if ((strlen(d->d_name) > 3) &&
    00526                    (!loadorder[x] || !strncasecmp(d->d_name, loadorder[x], strlen(loadorder[x]))) &&
    00527                    !strcasecmp(d->d_name + strlen(d->d_name) - 3, ".so") &&
    00528                   !ast_resource_exists(d->d_name)) {
    00529                   /* It's a shared library -- Just be sure we're allowed to load it -- kinda
    00530                      an inefficient way to do it, but oh well. */
    00531                   if (cfg) {
    00532                      v = ast_variable_browse(cfg, "modules");
    00533                      while(v) {
    00534                         if (!strcasecmp(v->name, "noload") &&
    00535                             !strcasecmp(v->value, d->d_name))
    00536                            break;
    00537                         v = v->next;
    00538                      }
    00539                      if (v) {
    00540                         if (option_verbose) {
    00541                            ast_verbose( VERBOSE_PREFIX_1 "[skipping %s]\n", d->d_name);
    00542                            fflush(stdout);
    00543                         }
    00544                         continue;
    00545                      }
    00546
    00547                   }
    00548                   if (option_debug && !option_verbose)
    00549                      ast_log(LOG_DEBUG, "Loading module %s\n", d->d_name);
    00550                   if (option_verbose) {
    00551                      ast_verbose( VERBOSE_PREFIX_1 "[%s]", term_color(tmp, d->d_name, COLOR_BRWHITE, 0, sizeof(tmp)));
    00552                      fflush(stdout);
    00553                   }
    00554                   if (__load_resource(d->d_name, cfg)) {
    00555                      ast_log(LOG_WARNING, "Loading module %s failed!\n", d->d_name);
    00556                      if (cfg)
    00557                         ast_config_destroy(cfg);
    00558                      return -1;
    00559                   }
    00560                }
    00561             }
    00562             closedir(mods);
    00563          } else {
    00564             if (!option_quiet)
    00565                ast_log(LOG_WARNING, "Unable to open modules directory %s.\n", (char *)ast_config_AST_MODULE_DIR);
    00566          }
    00567       }
    00568    }
    00569    ast_config_destroy(cfg);
    00570    return 0;
    00571 }

static int printdigest | ( | unsigned char * | d | ) | `[static]`

Definition at line 84 of file loader.c.

References ast_log(), and LOG_DEBUG.

Referenced by verify_key().

    00085 {
    00086    int x;
    00087    char buf[256];
    00088    char buf2[16];
    00089    snprintf(buf, sizeof(buf), "Unexpected signature:");
    00090    for (x=0; x<16; x++) {
    00091       snprintf(buf2, sizeof(buf2), " %02x", *(d++));
    00092       strcat(buf, buf2);
    00093    }
    00094    strcat(buf, "\n");
    00095    ast_log(LOG_DEBUG, "%s", buf);
    00096    return 0;
    00097 }

static int verify_key | ( | unsigned char * | key | ) | `[static]`

Definition at line 109 of file loader.c.

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

Referenced by __load_resource().

    00110 {
    00111    struct MD5Context c;
    00112    unsigned char digest[16];
    00113    MD5Init(&c);
    00114    MD5Update(&c, key, strlen((char *)key));
    00115    MD5Final(digest, &c);
    00116    if (key_matches(expected_key, digest))
    00117       return 0;
    00118    printdigest(digest);
    00119    return -1;
    00120 }

## Variable Documentation

unsigned char expected_key[]`[static]`

Initial value:

    { 0x8e, 0x93, 0x22, 0x83, 0xf5, 0xc3, 0xc0, 0x75,
      0xff, 0x8b, 0xa9, 0xbe, 0x7c, 0x43, 0x74, 0x63 }

Definition at line 63 of file loader.c.

const char* loadorder[]`[static]`

Definition at line 458 of file loader.c.

int modlistver = 0`[static]`

Definition at line 61 of file loader.c.

struct module* module_list = NULL`[static]`

Definition at line 60 of file loader.c.

struct loadupdate * updaters`[static]`

Referenced by ast_loader_register(), ast_loader_unregister(), and ast_update_use_count().