Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:35 2007

Asterisk developer's documentation :: Codename Pineapple


loader.c File Reference


Detailed Description

Module Loader.

Author:
Mark Spencer <markster@digium.com>

Kevin P. Fleming <kpfleming@digium.com>

Luigi Rizzo <rizzo@icir.org>

Definition in file loader.c.

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

Include dependency graph for loader.c:

Go to the source code of this file.

Data Structures

struct  ast_module
struct  ast_module_user
struct  load_order_entry
struct  loadupdate
struct  reload_classes

Defines

#define RTLD_NOW   0

Enumerations

enum  flags { FLAG_RUNNING = (1 << 1), FLAG_DECLINED = (1 << 2) }

Functions

ast_module_user__ast_module_user_add (struct ast_module *mod, struct ast_channel *chan)
void __ast_module_user_hangup_all (struct ast_module *mod)
void __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u)
static struct load_order_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 (updaters, loadupdate)
static AST_LIST_HEAD_STATIC (module_list, ast_module)
int ast_load_resource (const char *resource_name)
 Load a module.
int ast_loader_register (int(*v)(void))
 Add a procedure to be run when modules have been updated.
int ast_loader_unregister (int(*v)(void))
 Remove a procedure to be run when modules are updated.
int ast_module_check (char *name)
 Check if module with the name given is loaded.
char * ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, int needsreload)
 Match modules names for the Asterisk cli.
ast_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_unref (struct ast_module *mod)
void ast_module_unregister (const struct ast_module_info *info)
 AST_MUTEX_DEFINE_STATIC (reloadlock)
int ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force)
 Unload a module.
int ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like)
 Ask for a list of modules, descriptions, and use counts.
void ast_update_use_count (void)
 Notify when usecount has been changed.
static struct ast_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)
static int printdigest (const unsigned char *d)
static int resource_name_match (const char *name1_in, const char *name2_in)
static int verify_key (const unsigned char *key)

Variables

static unsigned int embedding = 1
static unsigned char expected_key []
ast_moduleresource_being_loaded


Define Documentation

#define RTLD_NOW   0
 

Definition at line 65 of file loader.c.

Referenced by dlopen(), and loadModule().


Enumeration Type Documentation

enum flags
 

Enumerator:
FLAG_RUNNING 
FLAG_DECLINED 

Definition at line 83 of file loader.c.

00083            {
00084    FLAG_RUNNING = (1 << 1),      /* module successfully initialized */
00085    FLAG_DECLINED = (1 << 2),     /* module declined to initialize */
00086 };


Function Documentation

struct ast_module_user* __ast_module_user_add struct ast_module mod,
struct ast_channel chan
 

Definition at line 179 of file loader.c.

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

00181 {
00182    struct ast_module_user *u = ast_calloc(1, sizeof(*u));
00183 
00184    if (!u)
00185       return NULL;
00186 
00187    u->chan = chan;
00188 
00189    AST_LIST_LOCK(&mod->users);
00190    AST_LIST_INSERT_HEAD(&mod->users, u, entry);
00191    AST_LIST_UNLOCK(&mod->users);
00192 
00193    ast_atomic_fetchadd_int(&mod->usecount, +1);
00194 
00195    ast_update_use_count();
00196 
00197    return u;
00198 }

void __ast_module_user_hangup_all struct ast_module mod  ) 
 

Definition at line 211 of file loader.c.

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

Referenced by ast_unload_resource().

00212 {
00213    struct ast_module_user *u;
00214 
00215    AST_LIST_LOCK(&mod->users);
00216    while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
00217       ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
00218       ast_atomic_fetchadd_int(&mod->usecount, -1);
00219       free(u);
00220    }
00221    AST_LIST_UNLOCK(&mod->users);
00222 
00223         ast_update_use_count();
00224 }

void __ast_module_user_remove struct ast_module mod,
struct ast_module_user u
 

Definition at line 200 of file loader.c.

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

00201 {
00202    AST_LIST_LOCK(&mod->users);
00203    AST_LIST_REMOVE(&mod->users, u, entry);
00204    AST_LIST_UNLOCK(&mod->users);
00205    ast_atomic_fetchadd_int(&mod->usecount, -1);
00206    free(u);
00207 
00208    ast_update_use_count();
00209 }

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

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

00679 {
00680    struct load_order_entry *order;
00681 
00682    AST_LIST_TRAVERSE(load_order, order, entry) {
00683       if (!resource_name_match(order->resource, resource))
00684          return NULL;
00685    }
00686 
00687    if (!(order = ast_calloc(1, sizeof(*order))))
00688       return NULL;
00689 
00690    order->resource = ast_strdup(resource);
00691    AST_LIST_INSERT_TAIL(load_order, order, entry);
00692 
00693    return order;
00694 }

AST_LIST_HEAD module_user_list  ,
ast_module_user 
 

AST_LIST_HEAD_NOLOCK load_order  ,
load_order_entry 
 

static AST_LIST_HEAD_STATIC updaters  ,
loadupdate 
[static]
 

static AST_LIST_HEAD_STATIC module_list  ,
ast_module 
[static]
 

int ast_load_resource const char *  resource_name  ) 
 

Load a module.

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

References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().

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

00663 {
00664        AST_LIST_LOCK(&module_list);
00665        load_resource(resource_name, 0);
00666        AST_LIST_UNLOCK(&module_list);
00667 
00668        return 0;
00669 }

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

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.

Referenced by show_console().

00889 {
00890    struct loadupdate *tmp;
00891 
00892    if (!(tmp = ast_malloc(sizeof(*tmp))))
00893       return -1;
00894 
00895    tmp->updater = v;
00896    AST_LIST_LOCK(&module_list);
00897    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
00898    AST_LIST_UNLOCK(&module_list);
00899 
00900    return 0;
00901 }

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

00904 {
00905    struct loadupdate *cur;
00906 
00907    AST_LIST_LOCK(&module_list);
00908    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
00909       if (cur->updater == v)  {
00910          AST_LIST_REMOVE_CURRENT(&updaters, entry);
00911          break;
00912       }
00913    }
00914    AST_LIST_TRAVERSE_SAFE_END;
00915    AST_LIST_UNLOCK(&module_list);
00916 
00917    return cur ? 0 : -1;
00918 }

int ast_module_check char *  name  ) 
 

Check if module with the name given is loaded.

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

Definition at line 875 of file loader.c.

References ast_strlen_zero(), and find_resource().

00876 {
00877    struct ast_module *cur;
00878 
00879    if (ast_strlen_zero(name))
00880       return 0;       /* FALSE */
00881 
00882    cur = find_resource(name, 1);
00883 
00884    return (cur != NULL);
00885 }

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 489 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 handle_modlist(), handle_reload(), and handle_unload().

00490 {
00491    struct ast_module *cur;
00492    int i, which=0, l = strlen(word);
00493    char *ret = NULL;
00494 
00495    if (pos != rpos)
00496       return NULL;
00497 
00498    AST_LIST_LOCK(&module_list);
00499    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00500       if (!strncasecmp(word, cur->resource, l) &&
00501           (cur->info->reload || !needsreload) &&
00502           ++which > state) {
00503          ret = strdup(cur->resource);
00504          break;
00505       }
00506    }
00507    AST_LIST_UNLOCK(&module_list);
00508 
00509    if (!ret) {
00510       for (i=0; !ret && reload_classes[i].name; i++) {
00511          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00512             ret = strdup(reload_classes[i].name);
00513       }
00514    }
00515 
00516    return ret;
00517 }

struct ast_module* ast_module_ref struct ast_module mod  ) 
 

Definition at line 920 of file loader.c.

References ast_update_use_count(), and ast_module::usecount.

Referenced by __oh323_new(), alsa_new(), ast_iax2_new(), cli_audio_convert(), complete_orig(), fn_wrapper(), gtalk_new(), handle_orig(), mgcp_new(), oss_new(), phone_check_exception(), phone_new(), sip_new(), and skinny_new().

00921 {
00922    ast_atomic_fetchadd_int(&mod->usecount, +1);
00923    ast_update_use_count();
00924 
00925    return mod;
00926 }

void ast_module_register const struct ast_module_info info  ) 
 

Definition at line 117 of file loader.c.

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

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

int ast_module_reload const char *  name  ) 
 

Reload asterisk modules.

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

References ast_mutex_trylock(), and ast_verbose().

Referenced by action_updateconfig(), and handle_reload().

00520 {
00521    struct ast_module *cur;
00522    int res = 0; /* return value. 0 = not found, others, see below */
00523    int i;
00524 
00525    if (ast_mutex_trylock(&reloadlock)) {
00526       ast_verbose("The previous reload command didn't finish yet\n");
00527       return -1;  /* reload already in progress */
00528    }
00529 
00530    /* Call "predefined" reload here first */
00531    for (i = 0; reload_classes[i].name; i++) {
00532       if (!name || !strcasecmp(name, reload_classes[i].name)) {
00533          reload_classes[i].reload_fn();   /* XXX should check error ? */
00534          res = 2; /* found and reloaded */
00535       }
00536    }
00537    ast_lastreloadtime = time(NULL);
00538 
00539    if (name && res)
00540       return res;
00541 
00542    AST_LIST_LOCK(&module_list);
00543    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00544       const struct ast_module_info *info = cur->info;
00545 
00546       if (name && resource_name_match(name, cur->resource))
00547          continue;
00548 
00549       if (!ast_test_flag(cur, FLAG_RUNNING | FLAG_DECLINED))
00550          continue;
00551 
00552       if (!info->reload) { /* cannot be reloaded */
00553          if (res < 1)   /* store result if possible */
00554             res = 1; /* 1 = no reload() method */
00555          continue;
00556       }
00557 
00558       res = 2;
00559       if (option_verbose > 2)
00560          ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description);
00561       info->reload();
00562    }
00563    AST_LIST_UNLOCK(&module_list);
00564 
00565    ast_mutex_unlock(&reloadlock);
00566 
00567    return res;
00568 }

void ast_module_unref struct ast_module mod  ) 
 

Definition at line 928 of file loader.c.

References ast_update_use_count(), and ast_module::usecount.

Referenced by alsa_hangup(), ast_closestream(), ast_smdi_interface_destroy(), cli_audio_convert(), complete_orig(), destroy(), gtalk_hangup(), handle_orig(), iax2_predestroy(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_hangup(), and zt_hangup().

00929 {
00930    ast_atomic_fetchadd_int(&mod->usecount, -1);
00931    ast_update_use_count();
00932 }

void ast_module_unregister const struct ast_module_info info  ) 
 

Definition at line 155 of file loader.c.

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

00156 {
00157    struct ast_module *mod = NULL;
00158 
00159    /* it is assumed that the users list in the module structure
00160       will already be empty, or we cannot have gotten to this
00161       point
00162    */
00163    AST_LIST_LOCK(&module_list);
00164    AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00165       if (mod->info == info) {
00166          AST_LIST_REMOVE_CURRENT(&module_list, entry);
00167          break;
00168       }
00169    }
00170    AST_LIST_TRAVERSE_SAFE_END;
00171    AST_LIST_UNLOCK(&module_list);
00172 
00173    if (mod) {
00174       AST_LIST_HEAD_DESTROY(&mod->users);
00175       free(mod);
00176    }
00177 }

AST_MUTEX_DEFINE_STATIC reloadlock   ) 
 

int ast_unload_resource const char *  resource_name,
enum  ast_module_unload_mode
 

Unload a module.

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

References __ast_module_user_hangup_all(), ast_clear_flag, AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_flag, ast_update_use_count(), error(), find_resource(), FLAG_DECLINED, FLAG_RUNNING, and ast_module::usecount.

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

00434 {
00435    struct ast_module *mod;
00436    int res = -1;
00437    int error = 0;
00438 
00439    AST_LIST_LOCK(&module_list);
00440 
00441    if (!(mod = find_resource(resource_name, 0))) {
00442       AST_LIST_UNLOCK(&module_list);
00443       return 0;
00444    }
00445 
00446    if (!ast_test_flag(mod, FLAG_RUNNING | FLAG_DECLINED))
00447       error = 1;
00448 
00449    if (!error && (mod->usecount > 0)) {
00450       if (force)
00451          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00452             resource_name, mod->usecount);
00453       else {
00454          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00455             mod->usecount);
00456          error = 1;
00457       }
00458    }
00459 
00460    if (!error) {
00461       __ast_module_user_hangup_all(mod);
00462       res = mod->info->unload();
00463 
00464       if (res) {
00465          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00466          if (force <= AST_FORCE_FIRM)
00467             error = 1;
00468          else
00469             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00470       }
00471    }
00472 
00473    if (!error)
00474       ast_clear_flag(mod, FLAG_RUNNING | FLAG_DECLINED);
00475 
00476    AST_LIST_UNLOCK(&module_list);
00477 
00478 #if LOADABLE_MODULES
00479    if (!error)
00480       unload_dynamic_module(mod);
00481 #endif
00482 
00483    if (!error)
00484       ast_update_use_count();
00485 
00486    return res;
00487 }

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

00856 {
00857    struct ast_module *cur;
00858    int unlock = -1;
00859    int total_mod_loaded = 0;
00860 
00861    if (AST_LIST_TRYLOCK(&module_list))
00862       unlock = 0;
00863 
00864    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00865       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
00866    }
00867 
00868    if (unlock)
00869       AST_LIST_UNLOCK(&module_list);
00870 
00871    return total_mod_loaded;
00872 }

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 842 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(), load_module(), load_resource(), oh323_request(), process_sip_queue(), and sip_request_call().

00843 {
00844    /* Notify any module monitors that the use count for a
00845       resource has changed */
00846    struct loadupdate *m;
00847 
00848    AST_LIST_LOCK(&module_list);
00849    AST_LIST_TRAVERSE(&updaters, m, entry)
00850       m->updater();
00851    AST_LIST_UNLOCK(&module_list);
00852 }

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

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

00307 {
00308    struct ast_module *cur;
00309 
00310    if (do_lock)
00311       AST_LIST_LOCK(&module_list);
00312 
00313    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00314       if (!resource_name_match(resource, cur->resource))
00315          break;
00316    }
00317 
00318    if (do_lock)
00319       AST_LIST_UNLOCK(&module_list);
00320 
00321    return cur;
00322 }

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

Definition at line 570 of file loader.c.

References ast_log(), ast_module_info::description, ast_module::info, ast_module_info::key, and verify_key().

Referenced by load_resource().

00571 {
00572    if (!mod->info->description) {
00573       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00574       return 1;
00575    }
00576 
00577    if (!mod->info->key) {
00578       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00579       return 1;
00580    }
00581 
00582    if (verify_key((unsigned char *) mod->info->key)) {
00583       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00584       return 1;
00585    }
00586 
00587    return 0;
00588 }

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

Definition at line 259 of file loader.c.

Referenced by verify_key().

00260 {
00261    int x;
00262 
00263    for (x = 0; x < 16; x++) {
00264       if (key1[x] != key2[x])
00265          return 0;
00266    }
00267 
00268    return 1;
00269 }

int load_modules unsigned  int  ) 
 

Provided by loader.c

Definition at line 696 of file loader.c.

References add_to_load_order(), ast_config_load(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_TRAVERSE, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verbose(), embedding, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, option_verbose, and ast_variable::value.

00697 {
00698    struct ast_config *cfg;
00699    struct ast_module *mod;
00700    struct load_order_entry *order;
00701    struct ast_variable *v;
00702    unsigned int load_count;
00703    struct load_order load_order;
00704    int res = 0;
00705 #if LOADABLE_MODULES
00706    struct dirent *dirent;
00707    DIR *dir;
00708 #endif
00709 
00710    /* all embedded modules have registered themselves by now */
00711    embedding = 0;
00712 
00713    if (option_verbose)
00714       ast_verbose("Asterisk Dynamic Loader Starting:\n");
00715 
00716    AST_LIST_TRAVERSE(&module_list, mod, entry) {
00717       if (option_debug > 1)
00718          ast_log(LOG_DEBUG, "Embedded module found: %s\n", mod->resource);
00719    }
00720 
00721    if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) {
00722       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
00723       return 0;
00724    }
00725 
00726    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
00727 
00728    /* first, find all the modules we have been explicitly requested to load */
00729    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00730       if (!strcasecmp(v->name, preload_only ? "preload" : "load"))
00731          add_to_load_order(v->value, &load_order);
00732    }
00733 
00734    /* check if 'autoload' is on */
00735    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
00736       /* if so, first add all the embedded modules to the load order */
00737       AST_LIST_TRAVERSE(&module_list, mod, entry)
00738          order = add_to_load_order(mod->resource, &load_order);
00739 
00740 #if LOADABLE_MODULES
00741       /* if we are allowed to load dynamic modules, scan the directory for
00742          for all available modules and add them as well */
00743       if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
00744          while ((dirent = readdir(dir))) {
00745             int ld = strlen(dirent->d_name);
00746 
00747             /* Must end in .so to load it.  */
00748 
00749             if (ld < 4)
00750                continue;
00751 
00752             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
00753                 continue;
00754 
00755             add_to_load_order(dirent->d_name, &load_order);
00756 
00757          }
00758 
00759          closedir(dir);
00760       } else {
00761          if (!ast_opt_quiet)
00762             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
00763                ast_config_AST_MODULE_DIR);
00764       }
00765 #endif
00766    }
00767 
00768    /* now scan the config for any modules we are prohibited from loading and
00769       remove them from the load order */
00770    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00771       if (strcasecmp(v->name, "noload"))
00772          continue;
00773 
00774       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00775          if (!resource_name_match(order->resource, v->value)) {
00776             AST_LIST_REMOVE_CURRENT(&load_order, entry);
00777             free(order->resource);
00778             free(order);
00779          }
00780       }
00781       AST_LIST_TRAVERSE_SAFE_END;
00782    }
00783 
00784    /* we are done with the config now, all the information we need is in the
00785       load_order list */
00786    ast_config_destroy(cfg);
00787 
00788    load_count = 0;
00789    AST_LIST_TRAVERSE(&load_order, order, entry)
00790       load_count++;
00791 
00792    if (load_count)
00793       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
00794 
00795    /* first, load only modules that provide global symbols */
00796    AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00797       switch (load_resource(order->resource, 1)) {
00798       case AST_MODULE_LOAD_SUCCESS:
00799       case AST_MODULE_LOAD_DECLINE:
00800          AST_LIST_REMOVE_CURRENT(&load_order, entry);
00801          free(order->resource);
00802          free(order);
00803          break;
00804       case AST_MODULE_LOAD_FAILURE:
00805          res = -1;
00806          goto done;
00807       case AST_MODULE_LOAD_SKIP:
00808          /* try again later */
00809          break;
00810       }
00811    }
00812    AST_LIST_TRAVERSE_SAFE_END;
00813 
00814    /* now load everything else */
00815    AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
00816       switch (load_resource(order->resource, 0)) {
00817       case AST_MODULE_LOAD_SUCCESS:
00818       case AST_MODULE_LOAD_DECLINE:
00819          AST_LIST_REMOVE_CURRENT(&load_order, entry);
00820          free(order->resource);
00821          free(order);
00822          break;
00823       case AST_MODULE_LOAD_FAILURE:
00824          res = -1;
00825          goto done;
00826       case AST_MODULE_LOAD_SKIP:
00827          /* should not happen */
00828          break;
00829       }
00830    }
00831    AST_LIST_TRAVERSE_SAFE_END;
00832 
00833 done:
00834    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
00835       free(order->resource);
00836       free(order);
00837    }
00838 
00839    return res;
00840 }

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

Definition at line 590 of file loader.c.

References ast_clear_flag, ast_fully_booted, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_set_flag, ast_test_flag, ast_update_use_count(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, ast_module_info::description, find_resource(), FLAG_DECLINED, FLAG_RUNNING, ast_module::info, inspect_module(), ast_module_info::load, option_verbose, term_color(), and VERBOSE_PREFIX_1.

Referenced by ast_load_resource().

00591 {
00592    struct ast_module *mod;
00593    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00594    char tmp[256];
00595 
00596    if ((mod = find_resource(resource_name, 0))) {
00597       if (ast_test_flag(mod, FLAG_RUNNING)) {
00598          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00599          return AST_MODULE_LOAD_DECLINE;
00600       }
00601       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00602          return AST_MODULE_LOAD_SKIP;
00603    } else {
00604 #if LOADABLE_MODULES
00605       if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
00606          /* don't generate a warning message during load_modules() */
00607          if (!global_symbols_only) {
00608             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00609             return AST_MODULE_LOAD_DECLINE;
00610          } else {
00611             return AST_MODULE_LOAD_SKIP;
00612          }
00613       }
00614 #else
00615       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00616       return AST_MODULE_LOAD_DECLINE;
00617 #endif
00618    }
00619 
00620    if (inspect_module(mod)) {
00621       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00622 #if LOADABLE_MODULES
00623       unload_dynamic_module(mod);
00624 #endif
00625       return AST_MODULE_LOAD_DECLINE;
00626    }
00627 
00628    ast_clear_flag(mod, FLAG_DECLINED);
00629 
00630    if (mod->info->load)
00631       res = mod->info->load();
00632 
00633    switch (res) {
00634    case AST_MODULE_LOAD_SUCCESS:
00635       if (!ast_fully_booted) {
00636          if (option_verbose)
00637             ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00638          if (ast_opt_console && !option_verbose)
00639             ast_verbose( ".");
00640       } else {
00641          if (option_verbose)
00642             ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description);
00643       }
00644 
00645       ast_set_flag(mod, FLAG_RUNNING);
00646 
00647       ast_update_use_count();
00648       break;
00649    case AST_MODULE_LOAD_DECLINE:
00650       ast_set_flag(mod, FLAG_DECLINED);
00651       break;
00652    case AST_MODULE_LOAD_FAILURE:
00653       break;
00654    case AST_MODULE_LOAD_SKIP:
00655       /* modules should never return this value */
00656       break;
00657    }
00658 
00659    return res;
00660 }

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

Definition at line 245 of file loader.c.

References ast_log(), LOG_DEBUG, and option_debug.

Referenced by verify_key().

00246 {
00247    int x, pos;
00248    char buf[256]; /* large enough so we don't have to worry */
00249 
00250    for (pos = 0, x = 0; x < 16; x++)
00251       pos += sprintf(buf + pos, " %02x", *d++);
00252 
00253    if (option_debug)
00254       ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf);
00255 
00256    return 0;
00257 }

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

Definition at line 288 of file loader.c.

References ast_strdupa.

Referenced by add_to_load_order(), and find_resource().

00289 {
00290    char *name1 = (char *) name1_in;
00291    char *name2 = (char *) name2_in;
00292 
00293    /* trim off any .so extensions */
00294    if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
00295       name1 = ast_strdupa(name1);
00296       name1[strlen(name1) - 3] = '\0';
00297    }
00298    if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
00299       name2 = ast_strdupa(name2);
00300       name2[strlen(name2) - 3] = '\0';
00301    }
00302 
00303    return strcasecmp(name1, name2);
00304 }

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

Definition at line 271 of file loader.c.

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

Referenced by inspect_module().

00272 {
00273    struct MD5Context c;
00274    unsigned char digest[16];
00275 
00276    MD5Init(&c);
00277    MD5Update(&c, key, strlen((char *)key));
00278    MD5Final(digest, &c);
00279 
00280    if (key_matches(expected_key, digest))
00281       return 0;
00282 
00283    printdigest(digest);
00284 
00285    return -1;
00286 }


Variable Documentation

unsigned int embedding = 1 [static]
 

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

Referenced by verify_key().

struct ast_module* resource_being_loaded
 

Definition at line 113 of file loader.c.

Referenced by ast_module_register().


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen