res_phoneprov.c File Reference

Phone provisioning application for the asterisk internal http server. More...

#include "asterisk.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/paths.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/strings.h"
#include "asterisk/stringfields.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/acl.h"
#include "asterisk/astobj2.h"
#include "asterisk/ast_version.h"
#include "asterisk/phoneprov.h"

Include dependency graph for res_phoneprov.c:

Go to the source code of this file.

Data Structures

struct  extension
 structure to hold extensions More...
struct  http_route
 structure to hold http routes (valid URIs, and the files they link to) More...
struct  phone_profile
 structure to hold phone profiles read from phoneprov.conf More...
struct  phoneprov_file
 structure to hold file data More...
struct  phoneprov_provider
 structure to hold config providers More...
struct  user
 structure to hold users read from users.conf More...

Defines

#define AST_API_MODULE
#define FORMATD   "%-20.20s %-20.20s %-40.40s %-30.30s\n"
#define FORMATS   "%-20.20s %-40.40s %-30.30s\n"
#define MAX_PROFILE_BUCKETS   17
#define MAX_PROVIDER_BUCKETS   17
#define MAX_ROUTE_BUCKETS   563
#define MAX_USER_BUCKETS   563
#define SIMPLE_CMP_FN(fname, stype, field)
 Creates a compare function for a structure string field.
#define SIMPLE_HASH_FN(fname, stype, field)
 Creates a hash function for a structure string field.
#define SIPUSERS_PROVIDER_NAME   "sipusers"
#define VAR_BUF_SIZE   4096

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int add_user_extension (struct user *user, struct extension *exten)
 Add an extension to a user ordered by index/linenumber.
int ast_phoneprov_add_extension (char *provider_name, struct varshead *vars)
 Adds an extension.
void ast_phoneprov_delete_extension (char *provider_name, char *macaddress)
 Deletes an extension.
void ast_phoneprov_delete_extensions (char *provider_name)
 Deletes all extensions for this provider.
int ast_phoneprov_provider_register (char *provider_name, ast_phoneprov_load_users_cb load_users)
 Registers a config provider to phoneprov.
void ast_phoneprov_provider_unregister (char *provider_name)
 Unegisters a config provider from phoneprov and frees its resources.
const char * ast_phoneprov_std_variable_lookup (enum ast_phoneprov_std_variables var)
 Returns the string respresentation of a phoneprov standard variable.
static struct extensionbuild_extension (const char *name, struct varshead *vars)
static void build_profile (const char *name, struct ast_variable *v)
 Build a phone profile and add it to the list of phone profiles.
static void build_route (struct phoneprov_file *pp_file, struct phone_profile *profile, struct user *user, char *uri)
 Build a route structure and add it to the list of available http routes.
static struct userbuild_user (const char *mac, struct phone_profile *profile, char *provider_name)
 Build and return a user structure based on gathered config data.
static int build_user_routes (struct user *user)
 Add an http route for dynamic files attached to the profile of the user.
static struct extensiondelete_extension (struct extension *exten)
static void delete_file (struct phoneprov_file *file)
static void delete_profiles (void)
 Delete all phone profiles, freeing their memory.
static void delete_providers (void)
 Delete all providers.
static void delete_routes (void)
 Delete all http routes, freeing their memory.
static void delete_users (void)
 Delete all users.
static int extension_delete_cb (void *obj, void *arg, void *data, int flags)
static int extensions_delete_cb (void *obj, void *arg, int flags)
static struct phone_profilefind_profile (const char *name)
 Return a phone profile looked up by name.
static struct phoneprov_providerfind_provider (char *name)
static struct userfind_user (const char *macaddress)
 Return a user looked up by name.
static struct varsheadget_defaults (void)
static char * handle_show_routes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list static and dynamic routes.
static int load_common (void)
static int load_file (const char *filename, char **ret)
 Read a TEXT file into a string and return the length.
static int load_module (void)
 Load the module.
static int load_users (void)
static int lookup_iface (const char *iface, struct in_addr *address)
static int phoneprov_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
 Callback that is executed everytime an http request is received by this module.
static int pp_each_extension_helper (struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len)
 A dialplan function that can be used to output a template for each extension attached to a user.
static int pp_each_extension_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int pp_each_extension_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int pp_each_user_helper (struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len)
 A dialplan function that can be used to print a string for each phoneprov user.
static int pp_each_user_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int pp_each_user_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static void profile_destructor (void *obj)
static void provider_destructor (void *obj)
static int reload (void)
static void route_destructor (void *obj)
static int route_list_cb (void *obj, void *arg, void *data, int flags)
static int routes_delete_cb (void *obj, void *arg, int flags)
static void set_timezone_variables (struct varshead *headp, const char *zone)
 Set all timezone-related variables based on a zone (i.e. America/New_York).
static int unload_module (void)
static struct phone_profileunref_profile (struct phone_profile *prof)
static struct http_routeunref_route (struct http_route *route)
static struct userunref_user (struct user *user)
static void user_destructor (void *obj)
 Free all memory associated with a user.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "HTTP Phone Provisioning" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct in_addr __ourip = { .s_addr = 0x00000000, }
 for use in lookup_iface
static struct ast_module_infoast_module_info = &__mod_info
struct ao2_containerhttp_routes
static struct ast_http_uri phoneprovuri
static struct ast_cli_entry pp_cli []
static struct ast_custom_function pp_each_extension_function
static struct ast_custom_function pp_each_user_function
static const char * pp_general_lookup []
static const char * pp_user_lookup []
struct ao2_containerprofiles
struct ao2_containerproviders
struct ao2_containerusers
static const char * variable_lookup []


Detailed Description

Phone provisioning application for the asterisk internal http server.

Author:
Matthew Brooks <mbrooks@digium.com>

Terry Wilson <twilson@digium.com>

George Joseph <george.joseph@fairview5.com>

Definition in file res_phoneprov.c.


Define Documentation

#define AST_API_MODULE

Definition at line 45 of file res_phoneprov.c.

#define FORMATD   "%-20.20s %-20.20s %-40.40s %-30.30s\n"

Definition at line 1135 of file res_phoneprov.c.

Referenced by handle_show_routes(), and route_list_cb().

#define FORMATS   "%-20.20s %-40.40s %-30.30s\n"

Definition at line 1134 of file res_phoneprov.c.

Referenced by handle_show_routes(), and route_list_cb().

#define MAX_PROFILE_BUCKETS   17

Definition at line 82 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_PROVIDER_BUCKETS   17

Definition at line 81 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_ROUTE_BUCKETS   563

Definition at line 83 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_USER_BUCKETS   563

Definition at line 84 of file res_phoneprov.c.

#define SIMPLE_CMP_FN ( fname,
stype,
field   ) 

Creates a compare function for a structure string field.

Parameters:
fname The name to use for the function
stype The structure type
field The field in the structure to compare
SIMPLE_CMP_FN(mystruct, myfield) will produce a function named mystruct_cmp_fn which compares mystruct->myfield.

Definition at line 158 of file res_phoneprov.c.

#define SIMPLE_HASH_FN ( fname,
stype,
field   ) 

Creates a hash function for a structure string field.

Parameters:
fname The name to use for the function
stype The structure type
field The field in the structure to hash
SIMPLE_HASH_FN(mystruct, myfield) will produce a function named mystruct_hash_fn which hashes mystruct->myfield.

Definition at line 129 of file res_phoneprov.c.

#define SIPUSERS_PROVIDER_NAME   "sipusers"

Definition at line 339 of file res_phoneprov.c.

Referenced by load_module(), load_users(), and unload_module().

#define VAR_BUF_SIZE   4096

Definition at line 87 of file res_phoneprov.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1497 of file res_phoneprov.c.

01502 {

static void __unreg_module ( void   )  [static]

Definition at line 1497 of file res_phoneprov.c.

01502 {

static int add_user_extension ( struct user user,
struct extension exten 
) [static]

Add an extension to a user ordered by index/linenumber.

Definition at line 801 of file res_phoneprov.c.

References ast_free, AST_LIST_EMPTY, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_NEXT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_var_assign(), ast_var_find(), AST_VAR_LIST_INSERT_TAIL(), AST_VAR_LIST_TRAVERSE, user::extensions, extension::headp, phone_profile::headp, extension::index, LOG_WARNING, user::macaddress, ast_var_t::name, user::profile, str, and ast_var_t::value.

Referenced by ast_phoneprov_add_extension().

00802 {
00803    struct ast_var_t *pvar, *var2;
00804    struct ast_str *str = ast_str_create(16);
00805 
00806    if (!str) {
00807       return -1;
00808    }
00809 
00810    /* Append profile variables here, and substitute variables on profile
00811     * setvars, so that we can use user specific variables in them */
00812    AST_VAR_LIST_TRAVERSE(user->profile->headp, pvar) {
00813       if (ast_var_find(exten->headp, pvar->name)) {
00814          continue;
00815       }
00816 
00817       ast_str_substitute_variables_varshead(&str, 0, exten->headp, pvar->value);
00818       if ((var2 = ast_var_assign(pvar->name, ast_str_buffer(str)))) {
00819          AST_VAR_LIST_INSERT_TAIL(exten->headp, var2);
00820       }
00821    }
00822    ast_free(str);
00823 
00824    if (AST_LIST_EMPTY(&user->extensions)) {
00825       AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
00826    } else {
00827       struct extension *exten_iter;
00828 
00829       AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
00830          if (exten->index < exten_iter->index) {
00831             AST_LIST_INSERT_BEFORE_CURRENT(exten, entry);
00832          } else if (exten->index == exten_iter->index) {
00833             ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
00834             return -1;
00835          } else if (!AST_LIST_NEXT(exten_iter, entry)) {
00836             AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
00837          }
00838       }
00839       AST_LIST_TRAVERSE_SAFE_END;
00840    }
00841 
00842    return 0;
00843 }

int ast_phoneprov_add_extension ( char *  provider_name,
struct varshead vars 
)

Adds an extension.

Parameters:
provider_name The name of the provider
defaults An ast_vat_t linked list of the extension's variables. The list is automatically cloned and it must contain at least MACADDRESS and USERNAME entries.
Return values:
0 if successful
non-zero if failure

Definition at line 1612 of file res_phoneprov.c.

References add_user_extension(), ao2_cleanup, ao2_link, ast_log, AST_PHONEPROV_STD_MAC, AST_PHONEPROV_STD_PROFILE, AST_PHONEPROV_STD_USERNAME, ast_strlen_zero, ast_var_find(), build_extension(), build_user(), build_user_routes(), delete_extension(), exten, find_profile(), find_provider(), find_user(), LOG_ERROR, LOG_VERBOSE, LOG_WARNING, extension::name, NULL, and RAII_VAR.

Referenced by load_users(), and users_apply_handler().

01613 {
01614    RAII_VAR(struct phoneprov_provider *, provider, NULL, ao2_cleanup);
01615    RAII_VAR(struct user *, user, NULL, ao2_cleanup);
01616    RAII_VAR(struct phone_profile *, profile, NULL, ao2_cleanup);
01617    struct extension *exten;
01618    char *profile_name;
01619    char *mac;
01620    char *username;
01621 
01622    if (ast_strlen_zero(provider_name)) {
01623       ast_log(LOG_ERROR, "Provider name can't be empty.\n");
01624       return -1;
01625    }
01626    if (!vars) {
01627       ast_log(LOG_ERROR, "Variable list can't be empty.\n");
01628       return -1;
01629    }
01630 
01631    username = ast_var_find(vars, variable_lookup[AST_PHONEPROV_STD_USERNAME]);
01632    if (!username) {
01633       ast_log(LOG_ERROR, "Extension name can't be empty.\n");
01634       return -1;
01635    }
01636 
01637    mac = ast_var_find(vars, variable_lookup[AST_PHONEPROV_STD_MAC]);
01638    if (!mac) {
01639       ast_log(LOG_ERROR, "MAC Address can't be empty.\n");
01640       return -1;
01641    }
01642 
01643    provider = find_provider(provider_name);
01644    if (!provider) {
01645       ast_log(LOG_ERROR, "Provider '%s' wasn't found in the registry.\n", provider_name);
01646       return -1;
01647    }
01648 
01649    profile_name = ast_var_find(vars,
01650       variable_lookup[AST_PHONEPROV_STD_PROFILE]);
01651    if (!profile_name) {
01652       ast_log(LOG_ERROR, "No profile could be found for user '%s' - skipping.\n", username);
01653       return -1;
01654    }
01655    if (!(profile = find_profile(profile_name))) {
01656       ast_log(LOG_ERROR, "Could not look up profile '%s' - skipping.\n", profile_name);
01657       return -1;
01658    }
01659 
01660    if (!(user = find_user(mac))) {
01661 
01662       if (!(user = build_user(mac, profile, provider_name))) {
01663          ast_log(LOG_ERROR, "Could not create user for '%s' - skipping\n", mac);
01664          return -1;
01665       }
01666 
01667       if (!(exten = build_extension(username, vars))) {
01668          ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
01669          return -1;
01670       }
01671 
01672       if (add_user_extension(user, exten)) {
01673          ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01674          exten = delete_extension(exten);
01675          return -1;
01676       }
01677 
01678       if (build_user_routes(user)) {
01679          ast_log(LOG_WARNING, "Could not create http routes for '%s' - skipping\n", user->macaddress);
01680          return -1;
01681       }
01682       ast_log(LOG_VERBOSE, "Created %s/%s for provider '%s'.\n", username, mac, provider_name);
01683       ao2_link(users, user);
01684 
01685    } else {
01686       if (strcmp(provider_name, user->provider_name)) {
01687          ast_log(LOG_ERROR, "MAC address '%s' was already added by provider '%s' - skipping\n", user->macaddress, user->provider_name);
01688          return -1;
01689       }
01690 
01691       if (!(exten = build_extension(username, vars))) {
01692          ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
01693          return -1;
01694       }
01695 
01696       if (add_user_extension(user, exten)) {
01697          ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01698          exten = delete_extension(exten);
01699          return -1;
01700       }
01701       ast_log(LOG_VERBOSE, "Added %s/%s for provider '%s'.\n", username, mac, provider_name);
01702    }
01703 
01704    return 0;
01705 }

void ast_phoneprov_delete_extension ( char *  provider_name,
char *  macaddress 
)

Deletes an extension.

Parameters:
provider_name The name of the provider
macaddress The mac address of the extension

Definition at line 1582 of file res_phoneprov.c.

References ao2_callback_data, extension_delete_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by phoneprov_destroy().

01583 {
01584    if (!users) {
01585       return;
01586    }
01587 
01588    ao2_callback_data(users, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
01589       extension_delete_cb, macaddress, provider_name);
01590 }

void ast_phoneprov_delete_extensions ( char *  provider_name  ) 

Deletes all extensions for this provider.

Parameters:
provider_name The name of the provider

Definition at line 1592 of file res_phoneprov.c.

References ao2_callback, extensions_delete_cb(), OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by ast_phoneprov_provider_unregister().

01593 {
01594    if (!users) {
01595       return;
01596    }
01597 
01598    ao2_callback(users, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, extensions_delete_cb, provider_name);
01599 }

int ast_phoneprov_provider_register ( char *  provider_name,
ast_phoneprov_load_users_cb  load_users 
)

Registers a config provider to phoneprov.

Parameters:
provider_name The name of the provider
load_users Callback that gathers user variables then loads them by calling ast_phoneprov_add_extension once for each extension.
Return values:
0 if successful
non-zero if failure

Definition at line 1510 of file res_phoneprov.c.

References ao2_alloc, ao2_link, ao2_ref, ast_log, ast_phoneprov_provider_unregister(), ast_string_field_init, ast_string_field_set, ast_strlen_zero, find_provider(), phoneprov_provider::load_users, LOG_ERROR, LOG_VERBOSE, LOG_WARNING, and provider_destructor().

Referenced by load_module(), and reload_module().

01512 {
01513    struct phoneprov_provider *provider;
01514 
01515    if (ast_strlen_zero(provider_name)) {
01516       ast_log(LOG_ERROR, "Provider name can't be empty.\n");
01517       return -1;
01518    }
01519 
01520    if (!providers) {
01521       ast_log(LOG_WARNING, "Provider '%s' cannot be registered: res_phoneprov not loaded.\n", provider_name);
01522       return -1;
01523    }
01524 
01525    provider = find_provider(provider_name);
01526    if (provider) {
01527       ast_log(LOG_ERROR, "There is already a provider registered named '%s'.\n", provider_name);
01528       ao2_ref(provider, -1);
01529       return -1;
01530    }
01531 
01532    provider = ao2_alloc(sizeof(struct phoneprov_provider), provider_destructor);
01533    if (!provider) {
01534       ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s'.\n", provider_name);
01535       return -1;
01536    }
01537 
01538    if (ast_string_field_init(provider, 32)) {
01539       ao2_ref(provider, -1);
01540       ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s' stringfields.\n", provider_name);
01541       return -1;
01542    }
01543 
01544    ast_string_field_set(provider, provider_name, provider_name);
01545    provider->load_users = load_users;
01546 
01547    ao2_link(providers, provider);
01548    ao2_ref(provider, -1);
01549 
01550    if (provider->load_users()) {
01551       ast_log(LOG_ERROR, "Unable to load provider '%s' users. Register aborted.\n", provider_name);
01552       ast_phoneprov_provider_unregister(provider_name);
01553       return -1;
01554    }
01555 
01556    ast_log(LOG_VERBOSE, "Registered phoneprov provider '%s'.\n", provider_name);
01557    return 0;
01558 }

void ast_phoneprov_provider_unregister ( char *  provider_name  ) 

Unegisters a config provider from phoneprov and frees its resources.

Parameters:
provider_name The name of the provider

Definition at line 1601 of file res_phoneprov.c.

References ao2_find, ast_log, ast_phoneprov_delete_extensions(), LOG_VERBOSE, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by ast_phoneprov_provider_register(), reload_module(), and unload_module().

01602 {
01603    if (!providers) {
01604       return;
01605    }
01606 
01607    ast_phoneprov_delete_extensions(provider_name);
01608    ao2_find(providers, provider_name, OBJ_SEARCH_KEY | OBJ_NODATA | OBJ_UNLINK);
01609    ast_log(LOG_VERBOSE, "Unegistered phoneprov provider '%s'.\n", provider_name);
01610 }

const char* ast_phoneprov_std_variable_lookup ( enum ast_phoneprov_std_variables  var  ) 

Returns the string respresentation of a phoneprov standard variable.

Parameters:
var One of enum ast_phoneprov_std_variables
Returns:
The string representation or NULL if not found.

Definition at line 1501 of file res_phoneprov.c.

References AST_PHONEPROV_STD_VAR_LIST_LENGTH, and NULL.

Referenced by load_endpoint(), and users_apply_handler().

01502 {
01503    if (var >= AST_PHONEPROV_STD_VAR_LIST_LENGTH) {
01504       return NULL;
01505    }
01506 
01507    return variable_lookup[var];
01508 }

static struct extension* build_extension ( const char *  name,
struct varshead vars 
) [static, read]

Definition at line 684 of file res_phoneprov.c.

References ast_calloc_with_stringfields, ast_log, AST_PHONEPROV_STD_LINEKEYS, AST_PHONEPROV_STD_LINENUMBER, AST_PHONEPROV_STD_TIMEZONE, ast_string_field_set, ast_var_assign(), ast_var_find(), ast_var_list_clone(), AST_VAR_LIST_INSERT_TAIL(), delete_extension(), exten, extension::headp, extension::index, LOG_ERROR, NULL, set_timezone_variables(), and tmp().

Referenced by ast_phoneprov_add_extension().

00685 {
00686    struct extension *exten;
00687    const char *tmp;
00688 
00689    if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
00690       return NULL;
00691    }
00692 
00693    ast_string_field_set(exten, name, name);
00694 
00695    exten->headp = ast_var_list_clone(vars);
00696    if (!exten->headp) {
00697       ast_log(LOG_ERROR, "Unable to clone variables for extension '%s'\n", name);
00698       delete_extension(exten);
00699       return NULL;
00700    }
00701 
00702    tmp = ast_var_find(exten->headp, variable_lookup[AST_PHONEPROV_STD_LINENUMBER]);
00703    if (!tmp) {
00704       AST_VAR_LIST_INSERT_TAIL(exten->headp,
00705          ast_var_assign(variable_lookup[AST_PHONEPROV_STD_LINENUMBER], "1"));
00706       exten->index = 1;
00707    } else {
00708       sscanf(tmp, "%d", &exten->index);
00709    }
00710 
00711    if (!ast_var_find(exten->headp, variable_lookup[AST_PHONEPROV_STD_LINEKEYS])) {
00712       AST_VAR_LIST_INSERT_TAIL(exten->headp,
00713          ast_var_assign(variable_lookup[AST_PHONEPROV_STD_LINEKEYS], "1"));
00714    }
00715 
00716    set_timezone_variables(exten->headp,
00717       ast_var_find(vars, variable_lookup[AST_PHONEPROV_STD_TIMEZONE]));
00718 
00719    return exten;
00720 }

static void build_profile ( const char *  name,
struct ast_variable v 
) [static]

Build a phone profile and add it to the list of phone profiles.

Parameters:
name the name of the profile
v ast_variable from parsing phoneprov.conf

Definition at line 582 of file res_phoneprov.c.

References ao2_alloc, ao2_link, args, AST_APP_ARG, ast_calloc_with_stringfields, AST_DECLARE_APP_ARGS, ast_http_ftype2mtype(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strip(), ast_strlen_zero, ast_var_assign(), ast_var_list_create(), AST_VAR_LIST_INSERT_TAIL(), build_route(), phone_profile::default_mime_type, phone_profile::dynamic_files, format, phoneprov_file::format, phone_profile::headp, phoneprov_file::mime_type, ast_variable::name, ast_variable::next, NULL, profile_destructor(), S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), and ast_variable::value.

Referenced by load_common().

00583 {
00584    struct phone_profile *profile;
00585 
00586    if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
00587       return;
00588    }
00589 
00590    if (ast_string_field_init(profile, 32)) {
00591       profile = unref_profile(profile);
00592       return;
00593    }
00594 
00595    if (!(profile->headp = ast_var_list_create())) {
00596       profile = unref_profile(profile);
00597       return;
00598    }
00599 
00600    AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files);
00601    AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files);
00602 
00603    ast_string_field_set(profile, name, name);
00604    for (; v; v = v->next) {
00605       if (!strcasecmp(v->name, "mime_type")) {
00606          ast_string_field_set(profile, default_mime_type, v->value);
00607       } else if (!strcasecmp(v->name, "setvar")) {
00608          char *value_copy = ast_strdupa(v->value);
00609 
00610          AST_DECLARE_APP_ARGS(args,
00611             AST_APP_ARG(varname);
00612             AST_APP_ARG(varval);
00613          );
00614 
00615          AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
00616          do {
00617             if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
00618                break;
00619             args.varname = ast_strip(args.varname);
00620             args.varval = ast_strip(args.varval);
00621             if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
00622                break;
00623             AST_VAR_LIST_INSERT_TAIL(profile->headp, ast_var_assign(args.varname, args.varval));
00624          } while (0);
00625       } else if (!strcasecmp(v->name, "staticdir")) {
00626          ast_string_field_set(profile, staticdir, v->value);
00627       } else {
00628          struct phoneprov_file *pp_file;
00629          char *file_extension;
00630          char *value_copy = ast_strdupa(v->value);
00631 
00632          AST_DECLARE_APP_ARGS(args,
00633             AST_APP_ARG(filename);
00634             AST_APP_ARG(mimetype);
00635          );
00636 
00637          if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
00638             profile = unref_profile(profile);
00639             return;
00640          }
00641 
00642          if ((file_extension = strrchr(pp_file->format, '.')))
00643             file_extension++;
00644 
00645          AST_STANDARD_APP_ARGS(args, value_copy);
00646 
00647          /* Mime type order of preference
00648           * 1) Specific mime-type defined for file in profile
00649           * 2) Mime determined by extension
00650           * 3) Default mime type specified in profile
00651           * 4) text/plain
00652           */
00653          ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
00654             (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
00655 
00656          if (!strcasecmp(v->name, "static_file")) {
00657             ast_string_field_set(pp_file, format, args.filename);
00658             ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
00659             AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
00660             /* Add a route for the static files, as their filenames won't change per-user */
00661             build_route(pp_file, profile, NULL, NULL);
00662          } else {
00663             ast_string_field_set(pp_file, format, v->name);
00664             ast_string_field_set(pp_file, template, args.filename);
00665             AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
00666          }
00667       }
00668    }
00669 
00670    ao2_link(profiles, profile);
00671 
00672    profile = unref_profile(profile);
00673 }

static void build_route ( struct phoneprov_file pp_file,
struct phone_profile profile,
struct user user,
char *  uri 
) [static]

Build a route structure and add it to the list of available http routes.

Parameters:
pp_file File to link to the route
user User to link to the route (NULL means static route)
uri URI of the route

Definition at line 509 of file res_phoneprov.c.

References ao2_alloc, ao2_link, ast_log, ast_string_field_init, ast_string_field_set, http_route::file, phoneprov_file::format, LOG_ERROR, http_route::profile, route_destructor(), S_OR, unref_route(), and http_route::user.

00510 {
00511    struct http_route *route;
00512 
00513    if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
00514       return;
00515    }
00516 
00517    if (ast_string_field_init(route, 32)) {
00518       ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
00519       route = unref_route(route);
00520       return;
00521    }
00522 
00523    ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
00524    route->user = user;
00525    route->file = pp_file;
00526    route->profile = profile;
00527 
00528    ao2_link(http_routes, route);
00529 
00530    route = unref_route(route);
00531 }

static struct user* build_user ( const char *  mac,
struct phone_profile profile,
char *  provider_name 
) [static, read]

Build and return a user structure based on gathered config data.

Definition at line 779 of file res_phoneprov.c.

References ao2_alloc, ao2_ref, ast_string_field_init, ast_string_field_set, user::macaddress, NULL, user::profile, unref_user(), and user_destructor().

00780 {
00781    struct user *user;
00782 
00783    if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
00784       return NULL;
00785    }
00786 
00787    if (ast_string_field_init(user, 64)) {
00788       user = unref_user(user);
00789       return NULL;
00790    }
00791 
00792    ast_string_field_set(user, macaddress, mac);
00793    ast_string_field_set(user, provider_name, provider_name);
00794    user->profile = profile;
00795    ao2_ref(profile, 1);
00796 
00797    return user;
00798 }

static int build_user_routes ( struct user user  )  [static]

Add an http route for dynamic files attached to the profile of the user.

Definition at line 846 of file res_phoneprov.c.

References ast_free, AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), build_route(), phone_profile::dynamic_files, user::extensions, phoneprov_file::format, user::profile, and str.

Referenced by ast_phoneprov_add_extension().

00847 {
00848    struct phoneprov_file *pp_file;
00849    struct ast_str *str;
00850 
00851    if (!(str = ast_str_create(16))) {
00852       return -1;
00853    }
00854 
00855    AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
00856       ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format);
00857       build_route(pp_file, user->profile, user, ast_str_buffer(str));
00858    }
00859 
00860    ast_free(str);
00861    return 0;
00862 }

static struct extension* delete_extension ( struct extension exten  )  [static, read]

Definition at line 675 of file res_phoneprov.c.

References ast_free, ast_string_field_free_memory, ast_var_list_destroy(), extension::headp, and NULL.

Referenced by ast_phoneprov_add_extension(), build_extension(), and user_destructor().

00676 {
00677    ast_var_list_destroy(exten->headp);
00678    ast_string_field_free_memory(exten);
00679    ast_free(exten);
00680 
00681    return NULL;
00682 }

static void delete_file ( struct phoneprov_file file  )  [static]

Definition at line 393 of file res_phoneprov.c.

References ast_free, and ast_string_field_free_memory.

Referenced by profile_destructor().

00394 {
00395    ast_string_field_free_memory(file);
00396    ast_free(file);
00397 }

static void delete_profiles ( void   )  [static]

Delete all phone profiles, freeing their memory.

Definition at line 569 of file res_phoneprov.c.

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by reload(), and unload_module().

00570 {
00571    if (!profiles) {
00572       return;
00573    }
00574 
00575    ao2_callback(profiles, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00576 }

static void delete_providers ( void   )  [static]

Delete all providers.

Definition at line 378 of file res_phoneprov.c.

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by unload_module().

00379 {
00380    if (!providers) {
00381       return;
00382    }
00383 
00384    ao2_callback(providers, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00385 }

static void delete_routes ( void   )  [static]

Delete all http routes, freeing their memory.

Definition at line 495 of file res_phoneprov.c.

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by reload(), and unload_module().

00496 {
00497    if (!http_routes) {
00498       return;
00499    }
00500 
00501    ao2_callback(http_routes, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00502 }

static void delete_users ( void   )  [static]

Delete all users.

Definition at line 769 of file res_phoneprov.c.

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

00770 {
00771    if (!users) {
00772       return;
00773    }
00774 
00775    ao2_callback(users, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00776 }

static int extension_delete_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 1570 of file res_phoneprov.c.

References CMP_MATCH, user::macaddress, and user::provider_name.

Referenced by ast_phoneprov_delete_extension().

01571 {
01572    struct user *user = obj;
01573    char *provider_name = data;
01574    char *macaddress = arg;
01575 
01576    if (!strcmp(user->provider_name, provider_name) && !strcasecmp(user->macaddress, macaddress)) {
01577       return CMP_MATCH;
01578    }
01579    return 0;
01580 }

static int extensions_delete_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1560 of file res_phoneprov.c.

References CMP_MATCH, user::provider_name, and phoneprov_provider::provider_name.

Referenced by ast_phoneprov_delete_extensions().

01561 {
01562    char *provider_name = arg;
01563    struct user *user = obj;
01564    if (strcmp(user->provider_name, provider_name)) {
01565       return 0;
01566    }
01567    return CMP_MATCH;
01568 }

static struct phone_profile* find_profile ( const char *  name  )  [static, read]

Return a phone profile looked up by name.

Definition at line 541 of file res_phoneprov.c.

References ao2_find, and OBJ_SEARCH_KEY.

Referenced by ast_phoneprov_add_extension().

00542 {
00543    return ao2_find(profiles, name, OBJ_SEARCH_KEY);
00544 }

static struct phoneprov_provider* find_provider ( char *  name  )  [static, read]

Definition at line 372 of file res_phoneprov.c.

References ao2_find, and OBJ_SEARCH_KEY.

Referenced by ast_phoneprov_add_extension(), and ast_phoneprov_provider_register().

00373 {
00374    return ao2_find(providers, name, OBJ_SEARCH_KEY);
00375 }

static struct user* find_user ( const char *  macaddress  )  [static, read]

Return a user looked up by name.

Definition at line 730 of file res_phoneprov.c.

References ao2_find, and OBJ_SEARCH_KEY.

00731 {
00732    return ao2_find(users, macaddress, OBJ_SEARCH_KEY);
00733 }

static struct varshead* get_defaults ( void   )  [static, read]

Definition at line 1194 of file res_phoneprov.c.

References ast_config_destroy(), ast_config_load, ast_inet_ntoa(), ast_log, AST_PHONEPROV_STD_EXTENSION_LENGTH, AST_PHONEPROV_STD_PROFILE, AST_PHONEPROV_STD_SERVER, AST_PHONEPROV_STD_SERVER_IFACE, AST_PHONEPROV_STD_SERVER_PORT, AST_PHONEPROV_STD_VOICEMAIL_EXTEN, ast_var_assign(), ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, LOG_WARNING, lookup_iface(), ast_variable::name, ast_variable::next, NULL, S_OR, ast_variable::value, value, and var.

Referenced by load_users().

01195 {
01196    struct ast_config *phoneprov_cfg;
01197    struct ast_config *cfg;
01198    const char *value;
01199    struct ast_variable *v;
01200    struct ast_var_t *var;
01201    struct ast_flags config_flags = { 0 };
01202    struct varshead *defaults = ast_var_list_create();
01203 
01204    if (!defaults) {
01205       ast_log(LOG_ERROR, "Unable to create default var list.\n");
01206       return NULL;
01207    }
01208 
01209    if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
01210       || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
01211       ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
01212       ast_var_list_destroy(defaults);
01213       return NULL;
01214    }
01215 
01216    value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER]);
01217    if (!value) {
01218       struct in_addr addr;
01219       value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER_IFACE]);
01220       if (value) {
01221          lookup_iface(value, &addr);
01222          value = ast_inet_ntoa(addr);
01223       }
01224    }
01225    if (value) {
01226       var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_SERVER], value);
01227       AST_VAR_LIST_INSERT_TAIL(defaults, var);
01228    } else {
01229       ast_log(LOG_WARNING, "Unable to find a valid server address or name.\n");
01230    }
01231 
01232    value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER_PORT]);
01233    if (!value) {
01234       if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01235          value = ast_variable_retrieve(cfg, "general", "bindport");
01236          ast_config_destroy(cfg);
01237       }
01238    }
01239    var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_SERVER_PORT], S_OR(value, "5060"));
01240    AST_VAR_LIST_INSERT_TAIL(defaults, var);
01241 
01242    value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_PROFILE]);
01243    if (!value) {
01244       ast_log(LOG_ERROR, "Unable to load default profile.\n");
01245       ast_config_destroy(phoneprov_cfg);
01246       ast_var_list_destroy(defaults);
01247       return NULL;
01248    }
01249    var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_PROFILE], value);
01250    AST_VAR_LIST_INSERT_TAIL(defaults, var);
01251    ast_config_destroy(phoneprov_cfg);
01252 
01253    if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
01254       ast_log(LOG_ERROR, "Unable to load users.conf\n");
01255       ast_var_list_destroy(defaults);
01256       return NULL;
01257    }
01258 
01259    /* Go ahead and load global variables from users.conf so we can append to profiles */
01260    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
01261       if (!strcasecmp(v->name, pp_user_lookup[AST_PHONEPROV_STD_VOICEMAIL_EXTEN])) {
01262          var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_VOICEMAIL_EXTEN], v->value);
01263          AST_VAR_LIST_INSERT_TAIL(defaults, var);
01264       }
01265       if (!strcasecmp(v->name, pp_user_lookup[AST_PHONEPROV_STD_EXTENSION_LENGTH])) {
01266          var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_EXTENSION_LENGTH], v->value);
01267          AST_VAR_LIST_INSERT_TAIL(defaults, var);
01268       }
01269    }
01270    ast_config_destroy(cfg);
01271 
01272    return defaults;
01273 }

static char* handle_show_routes ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command to list static and dynamic routes.

Definition at line 1152 of file res_phoneprov.c.

References ao2_callback_data, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMATD, FORMATS, NULL, OBJ_MULTIPLE, OBJ_NODATA, route_list_cb(), and ast_cli_entry::usage.

01153 {
01154    int fd = a->fd;
01155    switch(cmd) {
01156    case CLI_INIT:
01157       e->command = "phoneprov show routes";
01158       e->usage =
01159          "Usage: phoneprov show routes\n"
01160          "       Lists all registered phoneprov http routes.\n";
01161       return NULL;
01162    case CLI_GENERATE:
01163       return NULL;
01164    }
01165 
01166    /* This currently iterates over routes twice, but it is the only place I've needed
01167     * to really separate static an dynamic routes, so I've just left it this way. */
01168    ast_cli(a->fd, "Static routes\n\n");
01169    ast_cli(a->fd, FORMATS, "Profile", "Relative URI", "Physical location");
01170 
01171    ao2_callback_data(http_routes, OBJ_NODATA | OBJ_MULTIPLE, route_list_cb, &fd, NULL);
01172 
01173    ast_cli(a->fd, "\nDynamic routes\n\n");
01174    ast_cli(a->fd, FORMATD, "Provider", "Profile", "Relative URI", "Template");
01175 
01176    ao2_callback_data(http_routes, OBJ_NODATA | OBJ_MULTIPLE, route_list_cb, &fd, (void *)1);
01177 
01178    return CLI_SUCCESS;
01179 }

static int load_common ( void   )  [static]

Definition at line 1343 of file res_phoneprov.c.

References ao2_container_count(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, ast_variable_browse(), build_profile(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, and NULL.

Referenced by load_module(), and reload().

01344 {
01345    struct ast_config *phoneprov_cfg;
01346    struct ast_flags config_flags = { 0 };
01347    char *cat;
01348 
01349    if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
01350       || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
01351       ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
01352       return -1;
01353    }
01354 
01355    cat = NULL;
01356    while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
01357       if (!strcasecmp(cat, "general")) {
01358          continue;
01359       }
01360       build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
01361    }
01362    ast_config_destroy(phoneprov_cfg);
01363 
01364    if (!ao2_container_count(profiles)) {
01365       ast_log(LOG_ERROR, "There are no provisioning profiles in phoneprov.conf.\n");
01366       return -1;
01367    }
01368 
01369    return 0;
01370 }

static int load_file ( const char *  filename,
char **  ret 
) [static]

Read a TEXT file into a string and return the length.

Definition at line 400 of file res_phoneprov.c.

References ast_free, ast_malloc, f, len(), and NULL.

Referenced by phoneprov_callback(), and pp_each_extension_helper().

00401 {
00402    int len = 0;
00403    FILE *f;
00404 
00405    if (!(f = fopen(filename, "r"))) {
00406       *ret = NULL;
00407       return -1;
00408    }
00409 
00410    fseek(f, 0, SEEK_END);
00411    len = ftell(f);
00412    fseek(f, 0, SEEK_SET);
00413    if (!(*ret = ast_malloc(len + 1)))
00414       return -2;
00415 
00416    if (len != fread(*ret, sizeof(char), len, f)) {
00417       ast_free(*ret);
00418       *ret = NULL;
00419       return -3;
00420    }
00421 
00422    fclose(f);
00423 
00424    (*ret)[len] = '\0';
00425 
00426    return len;
00427 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1409 of file res_phoneprov.c.

References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_http_uri_link(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_phoneprov_provider_register(), error(), load_common(), load_users(), LOG_ERROR, LOG_WARNING, MAX_PROFILE_BUCKETS, MAX_PROVIDER_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, SIPUSERS_PROVIDER_NAME, and unload_module.

01410 {
01411    profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, phone_profile_hash_fn, phone_profile_cmp_fn);
01412    if (!profiles) {
01413       ast_log(LOG_ERROR, "Unable to allocate profiles container.\n");
01414       return AST_MODULE_LOAD_DECLINE;
01415    }
01416 
01417    http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, http_route_hash_fn, http_route_cmp_fn);
01418    if (!http_routes) {
01419       ast_log(LOG_ERROR, "Unable to allocate routes container.\n");
01420       goto error;
01421    }
01422 
01423    if (load_common()) {
01424       ast_log(LOG_ERROR, "Unable to load provisioning profiles.\n");
01425       goto error;
01426    }
01427 
01428    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_fn, user_cmp_fn);
01429    if (!users) {
01430       ast_log(LOG_ERROR, "Unable to allocate users container.\n");
01431       goto error;
01432    }
01433 
01434    providers = ao2_container_alloc(MAX_PROVIDER_BUCKETS, phoneprov_provider_hash_fn, phoneprov_provider_cmp_fn);
01435    if (!providers) {
01436       ast_log(LOG_ERROR, "Unable to allocate providers container.\n");
01437       goto error;
01438    }
01439 
01440    /* Register ourselves as the provider for sip.conf/users.conf */
01441    if (ast_phoneprov_provider_register(SIPUSERS_PROVIDER_NAME, load_users)) {
01442       ast_log(LOG_WARNING, "Unable register sip/users config provider.  Others may succeed.\n");
01443    }
01444 
01445    ast_http_uri_link(&phoneprovuri);
01446 
01447    ast_custom_function_register(&pp_each_user_function);
01448    ast_custom_function_register(&pp_each_extension_function);
01449    ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli));
01450 
01451    return AST_MODULE_LOAD_SUCCESS;
01452 
01453 error:
01454    unload_module();
01455    return AST_MODULE_LOAD_DECLINE;
01456 }

static int load_users ( void   )  [static]

Definition at line 1275 of file res_phoneprov.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, ast_phoneprov_add_extension(), AST_PHONEPROV_STD_MAC, AST_PHONEPROV_STD_VAR_LIST_LENGTH, ast_true(), ast_var_assign(), ast_var_find(), ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), AST_VAR_LIST_TRAVERSE, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, get_defaults(), LOG_WARNING, ast_var_t::name, NULL, SIPUSERS_PROVIDER_NAME, tmp(), ast_var_t::value, and value.

Referenced by load_module(), and reload_module().

01276 {
01277    struct ast_config *cfg;
01278    char *cat;
01279    const char *value;
01280    struct ast_flags config_flags = { 0 };
01281    struct varshead *defaults = get_defaults();
01282 
01283    if (!defaults) {
01284       ast_log(LOG_WARNING, "Unable to load default variables.\n");
01285       return -1;
01286    }
01287 
01288    if (!(cfg = ast_config_load("users.conf", config_flags))
01289       || cfg == CONFIG_STATUS_FILEINVALID) {
01290       ast_log(LOG_WARNING, "Unable to load users.conf\n");
01291       return -1;
01292    }
01293 
01294    cat = NULL;
01295    while ((cat = ast_category_browse(cfg, cat))) {
01296       const char *tmp;
01297       int i;
01298       struct ast_var_t *varx;
01299       struct ast_var_t *vard;
01300 
01301       if (strcasecmp(cat, "general") && strcasecmp(cat, "authentication")) {
01302          struct varshead *variables = ast_var_list_create();
01303 
01304          if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) {
01305             ast_var_list_destroy(variables);
01306             continue;
01307          }
01308 
01309          /* Transfer the standard variables */
01310          for (i = 0; i < AST_PHONEPROV_STD_VAR_LIST_LENGTH; i++) {
01311             if (pp_user_lookup[i]) {
01312                value = ast_variable_retrieve(cfg, cat, pp_user_lookup[i]);
01313                if (value) {
01314                   varx = ast_var_assign(variable_lookup[i],
01315                      value);
01316                   AST_VAR_LIST_INSERT_TAIL(variables, varx);
01317                }
01318             }
01319          }
01320 
01321          if (!ast_var_find(variables, variable_lookup[AST_PHONEPROV_STD_MAC])) {
01322             ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
01323             ast_var_list_destroy(variables);
01324             continue;
01325          }
01326 
01327          /* Apply defaults */
01328          AST_VAR_LIST_TRAVERSE(defaults, vard) {
01329             if (ast_var_find(variables, vard->name)) {
01330                continue;
01331             }
01332             varx = ast_var_assign(vard->name, vard->value);
01333             AST_VAR_LIST_INSERT_TAIL(variables, varx);
01334          }
01335 
01336          ast_phoneprov_add_extension(SIPUSERS_PROVIDER_NAME, variables);
01337       }
01338    }
01339    ast_config_destroy(cfg);
01340    return 0;
01341 }

static int lookup_iface ( const char *  iface,
struct in_addr *  address 
) [static]

Definition at line 342 of file res_phoneprov.c.

References ast_copy_string(), ast_log, errno, LOG_ERROR, and LOG_WARNING.

Referenced by get_defaults().

00343 {
00344    int mysock, res = 0;
00345    struct ifreq ifr;
00346    struct sockaddr_in *sin;
00347 
00348    memset(&ifr, 0, sizeof(ifr));
00349    ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
00350 
00351    mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
00352    if (mysock < 0) {
00353       ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
00354       return -1;
00355    }
00356 
00357    res = ioctl(mysock, SIOCGIFADDR, &ifr);
00358 
00359    close(mysock);
00360 
00361    if (res < 0) {
00362       ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
00363       memcpy(address, &__ourip, sizeof(__ourip));
00364       return -1;
00365    } else {
00366       sin = (struct sockaddr_in *)&ifr.ifr_addr;
00367       memcpy(address, &sin->sin_addr, sizeof(*address));
00368       return 0;
00369    }
00370 }

static int phoneprov_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_vars,
struct ast_variable headers 
) [static]

Callback that is executed everytime an http request is received by this module.

Definition at line 865 of file res_phoneprov.c.

References ao2_find, ast_config_AST_DATA_DIR, ast_free, ast_http_error(), AST_HTTP_GET, AST_HTTP_HEAD, ast_http_send(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_log, AST_PHONEPROV_STD_SERVER, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_substitute_variables_varshead(), ast_var_assign(), ast_var_find(), AST_VAR_LIST_INSERT_TAIL(), user::extensions, ast_tcptls_session_instance::fd, http_route::file, extension::headp, len(), load_file(), LOG_ERROR, LOG_WARNING, phoneprov_file::mime_type, name, NULL, OBJ_SEARCH_KEY, result, phoneprov_file::template, tmp(), unref_route(), and http_route::user.

00866 {
00867    struct http_route *route;
00868    struct ast_str *result;
00869    char path[PATH_MAX];
00870    char *file = NULL;
00871    char *server;
00872    int len;
00873    int fd;
00874    struct ast_str *http_header;
00875 
00876    if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
00877       ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
00878       return 0;
00879    }
00880 
00881    if (!(route = ao2_find(http_routes, uri, OBJ_SEARCH_KEY))) {
00882       goto out404;
00883    }
00884 
00885    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
00886 
00887    if (!route->user) { /* Static file */
00888 
00889       fd = open(path, O_RDONLY);
00890       if (fd < 0) {
00891          goto out500;
00892       }
00893 
00894       len = lseek(fd, 0, SEEK_END);
00895       lseek(fd, 0, SEEK_SET);
00896       if (len < 0) {
00897          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00898          close(fd);
00899          goto out500;
00900       }
00901 
00902       http_header = ast_str_create(80);
00903       ast_str_set(&http_header, 0, "Content-type: %s\r\n",
00904          route->file->mime_type);
00905 
00906       ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
00907 
00908       close(fd);
00909       route = unref_route(route);
00910       return 0;
00911    } else { /* Dynamic file */
00912       struct ast_str *tmp;
00913 
00914       len = load_file(path, &file);
00915       if (len < 0) {
00916          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00917          if (file) {
00918             ast_free(file);
00919          }
00920 
00921          goto out500;
00922       }
00923 
00924       if (!file) {
00925          goto out500;
00926       }
00927 
00928       if (!(tmp = ast_str_create(len))) {
00929          if (file) {
00930             ast_free(file);
00931          }
00932 
00933          goto out500;
00934       }
00935 
00936       /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
00937        * the IP address we are listening on that the phone contacted for this config file */
00938 
00939       server = ast_var_find(AST_LIST_FIRST(&route->user->extensions)->headp,
00940          variable_lookup[AST_PHONEPROV_STD_SERVER]);
00941 
00942       if (!server) {
00943          union {
00944             struct sockaddr sa;
00945             struct sockaddr_in sa_in;
00946          } name;
00947          socklen_t namelen = sizeof(name.sa);
00948          int res;
00949 
00950          if ((res = getsockname(ser->fd, &name.sa, &namelen))) {
00951             ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
00952          } else {
00953             struct extension *exten_iter;
00954             const char *newserver = ast_inet_ntoa(name.sa_in.sin_addr);
00955 
00956             AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
00957                AST_VAR_LIST_INSERT_TAIL(exten_iter->headp,
00958                   ast_var_assign(variable_lookup[AST_PHONEPROV_STD_SERVER], newserver));
00959             }
00960          }
00961       }
00962 
00963       ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
00964 
00965       ast_free(file);
00966 
00967       http_header = ast_str_create(80);
00968       ast_str_set(&http_header, 0, "Content-type: %s\r\n",
00969          route->file->mime_type);
00970 
00971       if (!(result = ast_str_create(512))) {
00972          ast_log(LOG_ERROR, "Could not create result string!\n");
00973          if (tmp) {
00974             ast_free(tmp);
00975          }
00976          ast_free(http_header);
00977          goto out500;
00978       }
00979       ast_str_append(&result, 0, "%s", ast_str_buffer(tmp));
00980 
00981       ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
00982       ast_free(tmp);
00983 
00984       route = unref_route(route);
00985 
00986       return 0;
00987    }
00988 
00989 out404:
00990    ast_http_error(ser, 404, "Not Found", uri);
00991    return 0;
00992 
00993 out500:
00994    route = unref_route(route);
00995    ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
00996    return 0;
00997 }

static int pp_each_extension_helper ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
struct ast_str **  bufstr,
int  len 
) [static]

A dialplan function that can be used to output a template for each extension attached to a user.

Definition at line 1057 of file res_phoneprov.c.

References args, AST_APP_ARG, ast_build_string(), ast_config_AST_DATA_DIR, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_strlen_zero, exten, user::extensions, find_user(), extension::headp, load_file(), LOG_WARNING, str, and unref_user().

Referenced by pp_each_extension_read(), and pp_each_extension_read2().

01058 {
01059    struct user *user;
01060    struct extension *exten;
01061    char path[PATH_MAX];
01062    char *file;
01063    int filelen;
01064    struct ast_str *str;
01065    AST_DECLARE_APP_ARGS(args,
01066       AST_APP_ARG(mac);
01067       AST_APP_ARG(template);
01068    );
01069 
01070    AST_STANDARD_APP_ARGS(args, data);
01071 
01072    if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
01073       ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
01074       return 0;
01075    }
01076 
01077    if (!(user = find_user(args.mac))) {
01078       ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
01079       return 0;
01080    }
01081 
01082    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
01083    filelen = load_file(path, &file);
01084    if (filelen < 0) {
01085       ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
01086       if (file) {
01087          ast_free(file);
01088       }
01089       return 0;
01090    }
01091 
01092    if (!file) {
01093       return 0;
01094    }
01095 
01096    if (!(str = ast_str_create(filelen))) {
01097       return 0;
01098    }
01099 
01100    AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
01101       ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
01102       if (buf) {
01103          size_t slen = len;
01104          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01105       } else {
01106          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01107       }
01108    }
01109 
01110    ast_free(file);
01111    ast_free(str);
01112 
01113    user = unref_user(user);
01114 
01115    return 0;
01116 }

static int pp_each_extension_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1118 of file res_phoneprov.c.

References NULL, and pp_each_extension_helper().

01119 {
01120    return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
01121 }

static int pp_each_extension_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 1123 of file res_phoneprov.c.

References NULL, and pp_each_extension_helper().

01124 {
01125    return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
01126 }

static int pp_each_user_helper ( struct ast_channel chan,
char *  data,
char *  buf,
struct ast_str **  bufstr,
int  len 
) [static]

A dialplan function that can be used to print a string for each phoneprov user.

Definition at line 1000 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, args, AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, ast_free, AST_LIST_FIRST, AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_strlen_zero, user::extensions, user::macaddress, str, tmp(), and unref_user().

Referenced by pp_each_user_read(), and pp_each_user_read2().

01001 {
01002    char *tmp;
01003    struct ao2_iterator i;
01004    struct user *user;
01005    struct ast_str *str;
01006    AST_DECLARE_APP_ARGS(args,
01007       AST_APP_ARG(string);
01008       AST_APP_ARG(exclude_mac);
01009    );
01010    AST_STANDARD_APP_ARGS(args, data);
01011 
01012    if (!(str = ast_str_create(16))) {
01013       return -1;
01014    }
01015 
01016    /* Fix data by turning %{ into ${ */
01017    while ((tmp = strstr(args.string, "%{")))
01018       *tmp = '$';
01019 
01020    i = ao2_iterator_init(users, 0);
01021    while ((user = ao2_iterator_next(&i))) {
01022       if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
01023          continue;
01024       }
01025       ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
01026       if (buf) {
01027          size_t slen = len;
01028          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01029       } else {
01030          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01031       }
01032       user = unref_user(user);
01033    }
01034    ao2_iterator_destroy(&i);
01035 
01036    ast_free(str);
01037    return 0;
01038 }

static int pp_each_user_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 1040 of file res_phoneprov.c.

References NULL, and pp_each_user_helper().

01041 {
01042    return pp_each_user_helper(chan, data, buf, NULL, len);
01043 }

static int pp_each_user_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 1045 of file res_phoneprov.c.

References NULL, and pp_each_user_helper().

01046 {
01047    return pp_each_user_helper(chan, data, NULL, buf, len);
01048 }

static void profile_destructor ( void *  obj  )  [static]

Definition at line 546 of file res_phoneprov.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), delete_file(), phone_profile::dynamic_files, ast_var_t::entries, phone_profile::headp, phone_profile::static_files, and var.

Referenced by build_profile().

00547 {
00548    struct phone_profile *profile = obj;
00549    struct phoneprov_file *file;
00550    struct ast_var_t *var;
00551 
00552    while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) {
00553       delete_file(file);
00554    }
00555 
00556    while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) {
00557       delete_file(file);
00558    }
00559 
00560    while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) {
00561       ast_var_delete(var);
00562    }
00563 
00564    ast_free(profile->headp);
00565    ast_string_field_free_memory(profile);
00566 }

static void provider_destructor ( void *  obj  )  [static]

Definition at line 387 of file res_phoneprov.c.

References ast_string_field_free_memory.

Referenced by ast_phoneprov_provider_register().

00388 {
00389    struct phoneprov_provider *provider = obj;
00390    ast_string_field_free_memory(provider);
00391 }

static int reload ( void   )  [static]

Definition at line 1458 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, delete_profiles(), delete_routes(), delete_users(), load_common(), phoneprov_provider::load_users, LOG_ERROR, LOG_VERBOSE, phoneprov_provider::provider_name, and unload_module.

01459 {
01460    struct ao2_iterator i;
01461    struct phoneprov_provider *provider;
01462 
01463    /* Clean everything except the providers */
01464    delete_routes();
01465    delete_users();
01466    delete_profiles();
01467 
01468    /* Reload the profiles */
01469    if (load_common()) {
01470       ast_log(LOG_ERROR, "Unable to reload provisioning profiles.\n");
01471       unload_module();
01472       return AST_MODULE_LOAD_DECLINE;
01473    }
01474 
01475    /* For each provider, reload the users */
01476    ao2_lock(providers);
01477    i = ao2_iterator_init(providers, 0);
01478    for(; (provider = ao2_iterator_next(&i)); ao2_ref(provider, -1)) {
01479       ast_log(LOG_VERBOSE, "Reloading provider '%s' users.\n", provider->provider_name);
01480       if (provider->load_users()) {
01481          ast_log(LOG_ERROR, "Unable to load provider '%s' users. Reload aborted.\n", provider->provider_name);
01482          continue;
01483       }
01484    }
01485    ao2_iterator_destroy(&i);
01486    ao2_unlock(providers);
01487 
01488    return AST_MODULE_LOAD_SUCCESS;
01489 }

static void route_destructor ( void *  obj  )  [static]

Definition at line 487 of file res_phoneprov.c.

References ast_string_field_free_memory.

Referenced by build_route().

00488 {
00489    struct http_route *route = obj;
00490 
00491    ast_string_field_free_memory(route);
00492 }

static int route_list_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 1136 of file res_phoneprov.c.

References ast_cli(), CMP_MATCH, http_route::file, FORMATD, FORMATS, phone_profile::name, http_route::profile, user::provider_name, phoneprov_file::template, http_route::uri, and http_route::user.

Referenced by handle_show_routes().

01137 {
01138    int fd = *(int *)arg;
01139    struct http_route *route = obj;
01140 
01141    if (data && route->user) {
01142       ast_cli(fd, FORMATD, route->user->provider_name, route->profile->name, route->uri, route->file->template);
01143    }
01144    if (!data && !route->user) {
01145       ast_cli(fd, FORMATS, route->profile->name, route->uri, route->file->template);
01146    }
01147 
01148    return CMP_MATCH;
01149 }

static int routes_delete_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 735 of file res_phoneprov.c.

References CMP_MATCH, user::macaddress, and http_route::user.

Referenced by user_destructor().

00736 {
00737    struct http_route *route = obj;
00738    struct user *user = route->user;
00739    char *macaddress = arg;
00740 
00741    if (user && !strcmp(user->macaddress, macaddress)) {
00742       return CMP_MATCH;
00743    }
00744    return 0;
00745 }

static void set_timezone_variables ( struct varshead headp,
const char *  zone 
) [static]

Set all timezone-related variables based on a zone (i.e. America/New_York).

Parameters:
headp pointer to list of user variables
zone A time zone. NULL sets variables based on timezone of the machine

Definition at line 433 of file res_phoneprov.c.

References ast_get_dst_info(), ast_localtime(), ast_var_assign(), AST_VAR_LIST_INSERT_TAIL(), ast_tm::tm_hour, ast_tm::tm_mday, and ast_tm::tm_mon.

Referenced by build_extension().

00434 {
00435    time_t utc_time;
00436    int dstenable;
00437    time_t dststart;
00438    time_t dstend;
00439    struct ast_tm tm_info;
00440    int tzoffset;
00441    char buffer[21];
00442    struct timeval when;
00443 
00444    time(&utc_time);
00445    ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
00446    snprintf(buffer, sizeof(buffer), "%d", tzoffset);
00447    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("TZOFFSET", buffer));
00448 
00449    if (!dstenable) {
00450       return;
00451    }
00452 
00453    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_ENABLE", "1"));
00454 
00455    when.tv_sec = dststart;
00456    ast_localtime(&when, &tm_info, zone);
00457 
00458    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
00459    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MONTH", buffer));
00460 
00461    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00462    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MDAY", buffer));
00463 
00464    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00465    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_HOUR", buffer));
00466 
00467    when.tv_sec = dstend;
00468    ast_localtime(&when, &tm_info, zone);
00469 
00470    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
00471    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MONTH", buffer));
00472 
00473    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00474    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MDAY", buffer));
00475 
00476    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00477    AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_HOUR", buffer));
00478 }

static int unload_module ( void   )  [static]

Definition at line 1372 of file res_phoneprov.c.

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_http_uri_unlink(), ast_phoneprov_provider_unregister(), delete_profiles(), delete_providers(), delete_routes(), delete_users(), NULL, and SIPUSERS_PROVIDER_NAME.

01373 {
01374    ast_http_uri_unlink(&phoneprovuri);
01375    ast_custom_function_unregister(&pp_each_user_function);
01376    ast_custom_function_unregister(&pp_each_extension_function);
01377    ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli));
01378 
01379    /* This cleans up the sip.conf/users.conf provider (called specifically for clarity) */
01380    ast_phoneprov_provider_unregister(SIPUSERS_PROVIDER_NAME);
01381 
01382    /* This cleans up the framework which also cleans up the providers. */
01383    delete_profiles();
01384    ao2_cleanup(profiles);
01385    profiles = NULL;
01386    delete_routes();
01387    delete_users();
01388    ao2_cleanup(http_routes);
01389    http_routes = NULL;
01390    ao2_cleanup(users);
01391    users = NULL;
01392    delete_providers();
01393    ao2_cleanup(providers);
01394    providers = NULL;
01395 
01396    return 0;
01397 }

static struct phone_profile* unref_profile ( struct phone_profile prof  )  [static, read]

Definition at line 533 of file res_phoneprov.c.

References ao2_cleanup, and NULL.

Referenced by build_profile(), and user_destructor().

00534 {
00535    ao2_cleanup(prof);
00536 
00537    return NULL;
00538 }

static struct http_route* unref_route ( struct http_route route  )  [static, read]

Definition at line 480 of file res_phoneprov.c.

References ao2_cleanup, and NULL.

Referenced by build_route(), and phoneprov_callback().

00481 {
00482    ao2_cleanup(route);
00483 
00484    return NULL;
00485 }

static struct user* unref_user ( struct user user  )  [static, read]

Definition at line 722 of file res_phoneprov.c.

References ao2_cleanup, and NULL.

Referenced by build_user(), pp_each_extension_helper(), and pp_each_user_helper().

00723 {
00724    ao2_cleanup(user);
00725 
00726    return NULL;
00727 }

static void user_destructor ( void *  obj  )  [static]

Free all memory associated with a user.

Definition at line 748 of file res_phoneprov.c.

References ao2_callback, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), exten, user::extensions, user::macaddress, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, user::profile, routes_delete_cb(), and unref_profile().

00749 {
00750    struct user *user = obj;
00751    struct extension *exten;
00752 
00753    while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
00754       exten = delete_extension(exten);
00755    }
00756 
00757    if (user->profile) {
00758       user->profile = unref_profile(user->profile);
00759    }
00760 
00761    if (http_routes) {
00762       ao2_callback(http_routes, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, routes_delete_cb, (void *)user->macaddress);
00763    }
00764 
00765    ast_string_field_free_memory(user);
00766 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "HTTP Phone Provisioning" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 1497 of file res_phoneprov.c.

struct in_addr __ourip = { .s_addr = 0x00000000, } [static]

for use in lookup_iface

Definition at line 264 of file res_phoneprov.c.

Definition at line 1497 of file res_phoneprov.c.

Definition at line 335 of file res_phoneprov.c.

struct ast_http_uri phoneprovuri [static]

Definition at line 1185 of file res_phoneprov.c.

struct ast_cli_entry pp_cli[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_show_routes, "Show registered phoneprov http routes"),
}

Definition at line 1181 of file res_phoneprov.c.

Initial value:

 {
   .name = "PP_EACH_EXTENSION",
   .read = pp_each_extension_read,
   .read2 = pp_each_extension_read2,
}

Definition at line 1128 of file res_phoneprov.c.

Initial value:

 {
   .name = "PP_EACH_USER",
   .read = pp_each_user_read,
   .read2 = pp_each_user_read2,
}

Definition at line 1050 of file res_phoneprov.c.

const char* pp_general_lookup[] [static]

Definition at line 237 of file res_phoneprov.c.

const char* pp_user_lookup[] [static]

Definition at line 210 of file res_phoneprov.c.

Definition at line 308 of file res_phoneprov.c.

Definition at line 273 of file res_phoneprov.c.

Definition at line 321 of file res_phoneprov.c.

const char* variable_lookup[] [static]

Definition at line 183 of file res_phoneprov.c.


Generated on Thu Apr 16 06:32:57 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6