Fri Mar 8 17:30:11 2019

Asterisk developer's documentation


loader.c File Reference

Module Loader. More...

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

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_NOW   0

Enumerations

enum  module_load_pass { LOAD_FIRST, LOAD_GLOBAL_SYMBOLS, LOAD_ALL, LOAD_DONE }
 

Load modules in this order.

More...

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.
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, enum module_load_pass load_pass)
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 int translate_module_name (char *oldname, char *newname)
static int verify_key (const unsigned char *key)

Variables

static char buildopt_sum [33] = AST_BUILDOPT_SUM
static int do_full_reload = 0
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_NOW   0

Definition at line 61 of file loader.c.


Enumeration Type Documentation

Load modules in this order.

Enumerator:
LOAD_FIRST 

AST_MODFLAG_LOAD_FIRST.

LOAD_GLOBAL_SYMBOLS 

AST_MODFLAG_GLOBAL_SYMBOLS.

LOAD_ALL 

everything that is left

LOAD_DONE 

Must remain at the end.

Definition at line 121 of file loader.c.

00121                       {
00122    /*! \brief AST_MODFLAG_LOAD_FIRST */
00123    LOAD_FIRST,
00124    /*! \brief AST_MODFLAG_GLOBAL_SYMBOLS */
00125    LOAD_GLOBAL_SYMBOLS,
00126    /*! \brief everything that is left */
00127    LOAD_ALL,
00128 
00129    /*! \brief Must remain at the end. */
00130    LOAD_DONE,
00131 };


Function Documentation

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

Definition at line 197 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.

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

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

References ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), free, ast_module::usecount, and ast_module::users.

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

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

References AST_LIST_LOCK, AST_LIST_UNLOCK, LOAD_ALL, and load_resource().

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

00832 {
00833        AST_LIST_LOCK(&module_list);
00834        load_resource(resource_name, LOAD_ALL);
00835        AST_LIST_UNLOCK(&module_list);
00836 
00837        return 0;
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.

Returns:
Zero on success and -1 on failure.

Definition at line 1067 of file loader.c.

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

Referenced by show_console().

01068 {
01069    struct loadupdate *tmp;
01070 
01071    if (!(tmp = ast_malloc(sizeof(*tmp))))
01072       return -1;
01073 
01074    tmp->updater = v;
01075    AST_LIST_LOCK(&updaters);
01076    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01077    AST_LIST_UNLOCK(&updaters);
01078 
01079    return 0;
01080 }

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

01083 {
01084    struct loadupdate *cur;
01085 
01086    AST_LIST_LOCK(&updaters);
01087    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01088       if (cur->updater == v)  {
01089          AST_LIST_REMOVE_CURRENT(&updaters, entry);
01090          break;
01091       }
01092    }
01093    AST_LIST_TRAVERSE_SAFE_END;
01094    AST_LIST_UNLOCK(&updaters);
01095 
01096    return cur ? 0 : -1;
01097 }

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.
Returns:
A possible completion of the partial match, or NULL if no matches were found.

Definition at line 551 of file loader.c.

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

Referenced by complete_mod_2(), complete_mod_2_nr(), complete_mod_3(), complete_mod_3_nr(), complete_mod_4(), and load_module().

00552 {
00553    struct ast_module *cur;
00554    int i, which=0, l = strlen(word);
00555    char *ret = NULL;
00556 
00557    if (pos != rpos)
00558       return NULL;
00559 
00560    AST_LIST_LOCK(&module_list);
00561    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00562       if (!strncasecmp(word, cur->resource, l) &&
00563           (cur->info->reload || !needsreload) &&
00564           ++which > state) {
00565          ret = strdup(cur->resource);
00566          break;
00567       }
00568    }
00569    AST_LIST_UNLOCK(&module_list);
00570 
00571    if (!ret) {
00572       for (i=0; !ret && reload_classes[i].name; i++) {
00573          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00574             ret = strdup(reload_classes[i].name);
00575       }
00576    }
00577 
00578    return ret;
00579 }

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

Definition at line 135 of file loader.c.

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

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

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 646 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_verbose(), ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, LOG_NOTICE, option_verbose, queue_reload_request(), ast_module_info::reload, resource_name_match(), ast_module::running, and VERBOSE_PREFIX_3.

Referenced by action_updateconfig(), ast_process_pending_reloads(), handle_reload(), handle_reload_deprecated(), and monitor_sig_flags().

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

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 450 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, ast_module::declined, ast_module::flags, free, ast_module::info, ast_module::running, ast_module_info::unload, ast_module::usecount, and ast_module::users.

Referenced by quit_handler().

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

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

Definition at line 173 of file loader.c.

References AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, free, ast_module::info, and ast_module::users.

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

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

00582 {
00583    struct reload_queue_item *item;
00584 
00585    if (!ast_fully_booted) {
00586       return;
00587    }
00588 
00589    AST_LIST_LOCK(&reload_queue);
00590 
00591    if (do_full_reload) {
00592       do_full_reload = 0;
00593       AST_LIST_UNLOCK(&reload_queue);
00594       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00595       ast_module_reload(NULL);
00596       return;
00597    }
00598 
00599    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00600       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00601       ast_module_reload(item->module);
00602       ast_free(item);
00603    }
00604 
00605    AST_LIST_UNLOCK(&reload_queue);
00606 }

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

Returns:
Zero on success, -1 on error.

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

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

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

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

01049 {
01050    struct ast_module *cur;
01051    int unlock = -1;
01052    int total_mod_loaded = 0;
01053 
01054    if (AST_LIST_TRYLOCK(&module_list))
01055       unlock = 0;
01056 
01057    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01058       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01059    }
01060 
01061    if (unlock)
01062       AST_LIST_UNLOCK(&module_list);
01063 
01064    return total_mod_loaded;
01065 }

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

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and loadupdate::updater.

Referenced by __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), agent_new(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), exit_now(), load_module(), load_resource(), oh323_request(), scheduler_process_request_queue(), sip_request_call(), and sipsock_read().

01036 {
01037    /* Notify any module monitors that the use count for a
01038       resource has changed */
01039    struct loadupdate *m;
01040 
01041    AST_LIST_LOCK(&updaters);
01042    AST_LIST_TRAVERSE(&updaters, m, entry)
01043       m->updater();
01044    AST_LIST_UNLOCK(&updaters);
01045 }

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

References ast_log(), AST_MODFLAG_BUILDSUM, ast_strlen_zero(), ast_test_flag, 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().

00715 {
00716    if (!mod->info->description) {
00717       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00718       return 1;
00719    }
00720 
00721    if (!mod->info->key) {
00722       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00723       return 1;
00724    }
00725 
00726    if (verify_key((unsigned char *) mod->info->key)) {
00727       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00728       return 1;
00729    }
00730 
00731    if (!ast_test_flag(mod->info, AST_MODFLAG_BUILDSUM)) {
00732       ast_log(LOG_WARNING, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod->resource);
00733    } else if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00734          strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00735       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00736       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00737       return 1;
00738    }
00739 
00740    return 0;
00741 }

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

References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load(), 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_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_quiet, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), embedding, find_resource(), ast_module::flags, free, ast_module::lib, LOAD_DONE, load_resource(), LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, option_verbose, load_order_entry::resource, resource_name_match(), ast_module::running, translate_module_name(), and ast_variable::value.

Referenced by main().

00883 {
00884    struct ast_config *cfg;
00885    struct ast_module *mod;
00886    struct load_order_entry *order;
00887    struct ast_variable *v;
00888    unsigned int load_count;
00889    struct load_order load_order;
00890    int res = 0;
00891    int load_pass;
00892 
00893    int translate_status;
00894    char newname[18]; /* although this would normally be 80, max length in translate_module_name is 18 */
00895 #ifdef LOADABLE_MODULES
00896    struct dirent *dirent;
00897    DIR *dir;
00898 #endif
00899 
00900    /* all embedded modules have registered themselves by now */
00901    embedding = 0;
00902 
00903    if (option_verbose)
00904       ast_verbose("Asterisk Dynamic Loader Starting:\n");
00905 
00906    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
00907 
00908    AST_LIST_LOCK(&module_list);
00909 
00910    if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) {
00911       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
00912       goto done;
00913    }
00914 
00915    /* first, find all the modules we have been explicitly requested to load */
00916    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00917       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
00918          translate_status = translate_module_name(v->value, newname);
00919             if (!translate_status)
00920                ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
00921          add_to_load_order(translate_status ? v->value : newname, &load_order);
00922       }
00923    }
00924 
00925    /* check if 'autoload' is on */
00926    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
00927       /* if so, first add all the embedded modules that are not already running to the load order */
00928       AST_LIST_TRAVERSE(&module_list, mod, entry) {
00929          /* if it's not embedded, skip it */
00930          if (mod->lib)
00931             continue;
00932 
00933          if (mod->flags.running)
00934             continue;
00935 
00936          order = add_to_load_order(mod->resource, &load_order);
00937       }
00938 
00939 #ifdef LOADABLE_MODULES
00940       /* if we are allowed to load dynamic modules, scan the directory for
00941          for all available modules and add them as well */
00942       if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
00943          while ((dirent = readdir(dir))) {
00944             int ld = strlen(dirent->d_name);
00945 
00946             /* Must end in .so to load it.  */
00947 
00948             if (ld < 4)
00949                continue;
00950 
00951             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
00952                continue;
00953 
00954             /* if there is already a module by this name in the module_list,
00955                skip this file */
00956             if (find_resource(dirent->d_name, 0))
00957                continue;
00958 
00959             add_to_load_order(dirent->d_name, &load_order);
00960          }
00961 
00962          closedir(dir);
00963       } else {
00964          if (!ast_opt_quiet)
00965             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
00966                ast_config_AST_MODULE_DIR);
00967       }
00968 #endif
00969    }
00970 
00971    /* now scan the config for any modules we are prohibited from loading and
00972       remove them from the load order */
00973    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00974       if (strcasecmp(v->name, "noload"))
00975          continue;
00976 
00977       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00978          translate_status = translate_module_name(v->value, newname);
00979          if (!resource_name_match(order->resource, translate_status ? v->value : newname)) {
00980                if (!translate_status)
00981                   ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
00982             AST_LIST_REMOVE_CURRENT(&load_order, entry);
00983             free(order->resource);
00984             free(order);
00985          }
00986       }
00987       AST_LIST_TRAVERSE_SAFE_END;
00988    }
00989 
00990    /* we are done with the config now, all the information we need is in the
00991       load_order list */
00992    ast_config_destroy(cfg);
00993 
00994    load_count = 0;
00995    AST_LIST_TRAVERSE(&load_order, order, entry)
00996       load_count++;
00997 
00998    if (load_count)
00999       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
01000 
01001    for (load_pass = 0; load_pass < LOAD_DONE; load_pass++) {
01002       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
01003          switch (load_resource(order->resource, load_pass)) {
01004          case AST_MODULE_LOAD_SUCCESS:
01005          case AST_MODULE_LOAD_DECLINE:
01006             AST_LIST_REMOVE_CURRENT(&load_order, entry);
01007             free(order->resource);
01008             free(order);
01009             break;
01010          case AST_MODULE_LOAD_FAILURE:
01011             res = -1;
01012             goto done;
01013          case AST_MODULE_LOAD_SKIP:
01014             /* 
01015              * Try again later. This result is received when a module is
01016              * deferred because it is not a part of the current pass. 
01017              */
01018             break;
01019          }
01020       }
01021       AST_LIST_TRAVERSE_SAFE_END;
01022    }
01023 
01024 done:
01025    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
01026       free(order->resource);
01027       free(order);
01028    }
01029 
01030    AST_LIST_UNLOCK(&module_list);
01031 
01032    return res;
01033 }

static enum ast_module_load_result load_resource ( const char *  resource_name,
enum module_load_pass  load_pass 
) [static]

Definition at line 743 of file loader.c.

References ast_fully_booted, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_FIRST, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_test_flag, ast_update_use_count(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module_info::load, LOAD_ALL, LOAD_DONE, LOAD_FIRST, LOAD_GLOBAL_SYMBOLS, LOG_ERROR, LOG_WARNING, option_verbose, ast_module::running, term_color(), and VERBOSE_PREFIX_1.

Referenced by ast_load_resource(), and load_modules().

00744 {
00745    struct ast_module *mod;
00746    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00747    char tmp[256];
00748 
00749    if ((mod = find_resource(resource_name, 0))) {
00750       if (mod->flags.running) {
00751          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00752          return AST_MODULE_LOAD_DECLINE;
00753       }
00754 
00755       switch (load_pass) {
00756       case LOAD_FIRST:
00757          if (!ast_test_flag(mod->info, AST_MODFLAG_LOAD_FIRST)) {
00758             return AST_MODULE_LOAD_SKIP;
00759          }
00760          break;
00761       case LOAD_GLOBAL_SYMBOLS:
00762          if (!ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {
00763             return AST_MODULE_LOAD_SKIP;
00764          }
00765          break;
00766       case LOAD_ALL:
00767          break;
00768       case LOAD_DONE:
00769          ast_log(LOG_ERROR, "This should never happen, -EFLAMES!\n");
00770          break;
00771       }
00772    } else {
00773 #ifdef LOADABLE_MODULES
00774       if (!(mod = load_dynamic_module(resource_name, load_pass))) {
00775          /* don't generate a warning message during load_modules() */
00776          if (load_pass == LOAD_ALL) {
00777             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00778             return AST_MODULE_LOAD_DECLINE;
00779          } else {
00780             return AST_MODULE_LOAD_SKIP;
00781          }
00782       }
00783 #else
00784       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00785       return AST_MODULE_LOAD_DECLINE;
00786 #endif
00787    }
00788 
00789    if (inspect_module(mod)) {
00790       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00791 #ifdef LOADABLE_MODULES
00792       unload_dynamic_module(mod);
00793 #endif
00794       return AST_MODULE_LOAD_DECLINE;
00795    }
00796 
00797    mod->flags.declined = 0;
00798 
00799    if (mod->info->load)
00800       res = mod->info->load();
00801 
00802    switch (res) {
00803    case AST_MODULE_LOAD_SUCCESS:
00804       if (!ast_fully_booted) {
00805          if (option_verbose)
00806             ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00807          if (ast_opt_console && !option_verbose)
00808             ast_verbose( ".");
00809       } else {
00810          if (option_verbose)
00811             ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description);
00812       }
00813 
00814       mod->flags.running = 1;
00815 
00816       ast_update_use_count();
00817       break;
00818    case AST_MODULE_LOAD_DECLINE:
00819       mod->flags.declined = 1;
00820       break;
00821    case AST_MODULE_LOAD_FAILURE:
00822       break;
00823    case AST_MODULE_LOAD_SKIP:
00824       /* modules should never return this value */
00825       break;
00826    }
00827 
00828    return res;
00829 }

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

Definition at line 265 of file loader.c.

References ast_log(), and LOG_DEBUG.

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_log(LOG_DEBUG, "Unexpected signature:%s\n", buf);
00274 
00275    return 0;
00276 }

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

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

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

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 int translate_module_name ( char *  oldname,
char *  newname 
) [static]

Definition at line 865 of file loader.c.

References ast_copy_string().

Referenced by load_modules().

00866 {
00867    if (!strcasecmp(oldname, "app_zapbarge.so"))
00868       ast_copy_string(newname, "app_dahdibarge.so", 18);
00869    else if(!strcasecmp(oldname, "app_zapras.so"))
00870       ast_copy_string(newname, "app_dahdiras.so", 16);
00871    else if(!strcasecmp(oldname, "app_zapscan.so"))
00872       ast_copy_string(newname, "app_dahdiscan.so", 17);
00873    else if(!strcasecmp(oldname, "codec_zap.so"))
00874       ast_copy_string(newname, "codec_dahdi.so", 16);
00875    else
00876       return -1; /* no use for newname, oldname is fine */
00877 
00878    return 0;
00879 }

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

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 110 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

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

Definition at line 118 of file loader.c.

Referenced by ast_module_register().


Generated on 8 Mar 2019 for Asterisk - the Open Source PBX by  doxygen 1.6.1