Wed Jan 27 20:02:48 2016

Asterisk developer's documentation


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"

Go to the source code of this file.

Data Structures

struct  extension
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  pp_variable_lookup
 Lookup table to translate between users.conf property names and variables for use in phoneprov templates. More...
struct  user
 structure to hold users read from users.conf More...

Defines

#define FORMAT   "%-40.40s %-30.30s\n"
#define MAX_PROFILE_BUCKETS   17
#define MAX_ROUTE_BUCKETS   563
#define MAX_USER_BUCKETS   563
#define VAR_BUF_SIZE   4096

Enumerations

enum  pp_variables {
  PP_MACADDRESS, PP_USERNAME, PP_FULLNAME, PP_SECRET,
  PP_LABEL, PP_CALLERID, PP_TIMEZONE, PP_LINENUMBER,
  PP_LINEKEYS, PP_VAR_LIST_LENGTH
}

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.
static struct extensionbuild_extension (struct ast_config *cfg, const char *name)
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 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)
 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_routes (void)
 Delete all http routes, freeing their memory.
static void delete_users (void)
 Delete all users.
static struct phone_profilefind_profile (const char *name)
 Return a phone profile looked up by name.
static struct userfind_user (const char *macaddress)
 Return a user looked up by name.
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_file (const char *filename, char **ret)
 Read a TEXT file into a string and return the length.
static int load_module (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 int profile_cmp_fn (void *obj, void *arg, int flags)
static void profile_destructor (void *obj)
static int profile_hash_fn (const void *obj, const int flags)
static int reload (void)
static void route_destructor (void *obj)
static int routes_cmp_fn (void *obj, void *arg, int flags)
static int routes_hash_fn (const void *obj, const int flags)
static int set_config (void)
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.
static int users_cmp_fn (void *obj, void *arg, int flags)
static int users_hash_fn (const void *obj, const int flags)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip = { .s_addr = 0x00000000, }
 for use in lookup_iface
static struct ast_module_infoast_module_info = &__mod_info
static char global_default_profile [80] = ""
static char global_server [80] = ""
static char global_serverport [6] = ""
static struct varshead global_variables
 List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
static ast_mutex_t globals_lock
static 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 struct pp_variable_lookup pp_variable_list []
 Lookup table to translate between users.conf property names and variables for use in phoneprov templates.
static struct ao2_containerprofiles
static struct ao2_containerusers

Detailed Description

Phone provisioning application for the asterisk internal http server.

Author:
Matthew Brooks <mbrooks@digium.com>
Terry Wilson <twilson@digium.com>

Definition in file res_phoneprov.c.


Define Documentation

#define FORMAT   "%-40.40s %-30.30s\n"
#define MAX_PROFILE_BUCKETS   17

Definition at line 65 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_ROUTE_BUCKETS   563

Definition at line 66 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_USER_BUCKETS   563

Definition at line 67 of file res_phoneprov.c.

#define VAR_BUF_SIZE   4096

Definition at line 70 of file res_phoneprov.c.


Enumeration Type Documentation

Enumerator:
PP_MACADDRESS 
PP_USERNAME 
PP_FULLNAME 
PP_SECRET 
PP_LABEL 
PP_CALLERID 
PP_TIMEZONE 
PP_LINENUMBER 
PP_LINEKEYS 
PP_VAR_LIST_LENGTH 

Definition at line 108 of file res_phoneprov.c.

00108                   {
00109    PP_MACADDRESS,
00110    PP_USERNAME,
00111    PP_FULLNAME,
00112    PP_SECRET,
00113    PP_LABEL,
00114    PP_CALLERID,
00115    PP_TIMEZONE,
00116    PP_LINENUMBER,
00117    PP_LINEKEYS,
00118    PP_VAR_LIST_LENGTH,  /* This entry must always be the last in the list */
00119 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1344 of file res_phoneprov.c.

static void __unreg_module ( void   )  [static]

Definition at line 1344 of file res_phoneprov.c.

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 843 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, 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(), user::extensions, extension::headp, phone_profile::headp, extension::index, LOG_WARNING, user::macaddress, ast_var_t::name, user::profile, str, ast_var_t::value, and var.

Referenced by set_config().

00844 {
00845    struct ast_var_t *var;
00846    struct ast_str *str = ast_str_create(16);
00847 
00848    if (!str) {
00849       return -1;
00850    }
00851 
00852    /* Append profile variables here, and substitute variables on profile
00853     * setvars, so that we can use user specific variables in them */
00854    AST_LIST_TRAVERSE(user->profile->headp, var, entries) {
00855       struct ast_var_t *var2;
00856 
00857       ast_str_substitute_variables_varshead(&str, 0, exten->headp, var->value);
00858       if ((var2 = ast_var_assign(var->name, ast_str_buffer(str)))) {
00859          AST_LIST_INSERT_TAIL(exten->headp, var2, entries);
00860       }
00861    }
00862 
00863    ast_free(str);
00864 
00865    if (AST_LIST_EMPTY(&user->extensions)) {
00866       AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
00867    } else {
00868       struct extension *exten_iter;
00869 
00870       AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
00871          if (exten->index < exten_iter->index) {
00872             AST_LIST_INSERT_BEFORE_CURRENT(exten, entry);
00873          } else if (exten->index == exten_iter->index) {
00874             ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
00875             return -1;
00876          } else if (!AST_LIST_NEXT(exten_iter, entry)) {
00877             AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
00878          }
00879       }
00880       AST_LIST_TRAVERSE_SAFE_END;
00881    }
00882 
00883    return 0;
00884 }

static struct extension* build_extension ( struct ast_config cfg,
const char *  name 
) [static, read]

Definition at line 698 of file res_phoneprov.c.

References ast_calloc, ast_calloc_with_stringfields, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), ast_variable_retrieve(), exten, extension::headp, extension::index, extension::name, PP_LINEKEYS, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.

Referenced by set_config().

00699 {
00700    struct extension *exten;
00701    struct ast_var_t *var;
00702    const char *tmp;
00703    int i;
00704 
00705    if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
00706       return NULL;
00707    }
00708 
00709    ast_string_field_set(exten, name, name);
00710 
00711    if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) {
00712       ast_free(exten);
00713       exten = NULL;
00714       return NULL;
00715    }
00716 
00717    for (i = 0; i < PP_VAR_LIST_LENGTH; i++) {
00718       tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var);
00719 
00720       /* If we didn't get a USERNAME variable, set it to the user->name */
00721       if (i == PP_USERNAME && !tmp) {
00722          if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) {
00723             AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00724          }
00725          continue;
00726       } else if (i == PP_TIMEZONE) {
00727          /* perfectly ok if tmp is NULL, will set variables based on server's time zone */
00728          set_timezone_variables(exten->headp, tmp);
00729       } else if (i == PP_LINENUMBER) {
00730          if (!tmp) {
00731             tmp = "1";
00732          }
00733          exten->index = atoi(tmp);
00734       } else if (i == PP_LINEKEYS) {
00735          if (!tmp) {
00736             tmp = "1";
00737          }
00738       }
00739 
00740       if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) {
00741          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00742       }
00743    }
00744 
00745    if (!ast_strlen_zero(global_server)) {
00746       if ((var = ast_var_assign("SERVER", global_server)))
00747          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00748    }
00749 
00750    if (!ast_strlen_zero(global_serverport)) {
00751       if ((var = ast_var_assign("SERVER_PORT", global_serverport)))
00752          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00753    }
00754 
00755    return exten;
00756 }

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 576 of file res_phoneprov.c.

References ao2_alloc, ao2_link, args, AST_APP_ARG, ast_calloc, ast_calloc_with_stringfields, AST_DECLARE_APP_ARGS, ast_http_ftype2mtype(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, 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(), build_route(), phone_profile::default_mime_type, phone_profile::dynamic_files, phoneprov_file::format, global_variables, phone_profile::headp, phoneprov_file::mime_type, ast_var_t::name, ast_variable::name, ast_variable::next, profile_destructor(), S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), ast_var_t::value, ast_variable::value, and var.

Referenced by set_config().

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

static void build_route ( struct phoneprov_file pp_file,
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 549 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, route_destructor(), S_OR, unref_route(), and http_route::user.

Referenced by build_profile(), and build_user_routes().

00550 {
00551    struct http_route *route;
00552 
00553    if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
00554       return;
00555    }
00556 
00557    if (ast_string_field_init(route, 32)) {
00558       ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
00559       route = unref_route(route);
00560       return;
00561    }
00562 
00563    ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
00564    route->user = user;
00565    route->file = pp_file;
00566 
00567    ao2_link(http_routes, route);
00568 
00569    route = unref_route(route);
00570 }

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

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

Definition at line 821 of file res_phoneprov.c.

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

Referenced by set_config().

00822 {
00823    struct user *user;
00824 
00825    if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
00826       profile = unref_profile(profile);
00827       return NULL;
00828    }
00829 
00830    if (ast_string_field_init(user, 32)) {
00831       profile = unref_profile(profile);
00832       user = unref_user(user);
00833       return NULL;
00834    }
00835 
00836    ast_string_field_set(user, macaddress, mac);
00837    user->profile = profile; /* already ref counted by find_profile */
00838 
00839    return user;
00840 }

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

00888 {
00889    struct phoneprov_file *pp_file;
00890    struct ast_str *str;
00891 
00892    if (!(str = ast_str_create(16))) {
00893       return -1;
00894    }
00895 
00896    AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
00897       ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format);
00898       build_route(pp_file, user, ast_str_buffer(str));
00899    }
00900 
00901    ast_free(str);
00902    return 0;
00903 }

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

Definition at line 684 of file res_phoneprov.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), extension::headp, and var.

Referenced by set_config(), and user_destructor().

00685 {
00686    struct ast_var_t *var;
00687    while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) {
00688       ast_var_delete(var);
00689    }
00690    ast_free(exten->headp);
00691    ast_string_field_free_memory(exten);
00692 
00693    ast_free(exten);
00694 
00695    return NULL;
00696 }

static void delete_file ( struct phoneprov_file file  )  [static]

Definition at line 263 of file res_phoneprov.c.

References ast_string_field_free_memory, and free.

Referenced by profile_destructor().

00264 {
00265    ast_string_field_free_memory(file);
00266    free(file);
00267 }

static void delete_profiles ( void   )  [static]

Delete all phone profiles, freeing their memory.

Definition at line 1068 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_profile().

Referenced by reload(), and unload_module().

01069 {
01070    struct ao2_iterator i;
01071    struct phone_profile *profile;
01072 
01073    i = ao2_iterator_init(profiles, 0);
01074    while ((profile = ao2_iterator_next(&i))) {
01075       ao2_unlink(profiles, profile);
01076       profile = unref_profile(profile);
01077    }
01078    ao2_iterator_destroy(&i);
01079 }

static void delete_routes ( void   )  [static]

Delete all http routes, freeing their memory.

Definition at line 1054 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_route().

Referenced by reload(), and unload_module().

01055 {
01056    struct ao2_iterator i;
01057    struct http_route *route;
01058 
01059    i = ao2_iterator_init(http_routes, 0);
01060    while ((route = ao2_iterator_next(&i))) {
01061       ao2_unlink(http_routes, route);
01062       route = unref_route(route);
01063    }
01064    ao2_iterator_destroy(&i);
01065 }

static void delete_users ( void   )  [static]

Delete all users.

Definition at line 807 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_user().

Referenced by reload(), and unload_module().

00808 {
00809    struct ao2_iterator i;
00810    struct user *user;
00811 
00812    i = ao2_iterator_init(users, 0);
00813    while ((user = ao2_iterator_next(&i))) {
00814       ao2_unlink(users, user);
00815       user = unref_user(user);
00816    }
00817    ao2_iterator_destroy(&i);
00818 }

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

Return a phone profile looked up by name.

Definition at line 240 of file res_phoneprov.c.

References ao2_find, phone_profile::name, and OBJ_POINTER.

Referenced by set_config().

00241 {
00242    struct phone_profile tmp = {
00243       .name = name,
00244    };
00245 
00246    return ao2_find(profiles, &tmp, OBJ_POINTER);
00247 }

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

Return a user looked up by name.

Definition at line 766 of file res_phoneprov.c.

References ao2_find, user::macaddress, and OBJ_POINTER.

Referenced by pp_each_extension_helper(), and set_config().

00767 {
00768    struct user tmp = {
00769       .macaddress = macaddress,
00770    };
00771 
00772    return ao2_find(users, &tmp, OBJ_POINTER);
00773 }

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 1217 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, http_route::file, FORMAT, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.

01218 {
01219 #define FORMAT "%-40.40s  %-30.30s\n"
01220    struct ao2_iterator i;
01221    struct http_route *route;
01222 
01223    switch(cmd) {
01224    case CLI_INIT:
01225       e->command = "phoneprov show routes";
01226       e->usage =
01227          "Usage: phoneprov show routes\n"
01228          "       Lists all registered phoneprov http routes.\n";
01229       return NULL;
01230    case CLI_GENERATE:
01231       return NULL;
01232    }
01233 
01234    /* This currently iterates over routes twice, but it is the only place I've needed
01235     * to really separate static an dynamic routes, so I've just left it this way. */
01236    ast_cli(a->fd, "Static routes\n\n");
01237    ast_cli(a->fd, FORMAT, "Relative URI", "Physical location");
01238    i = ao2_iterator_init(http_routes, 0);
01239    while ((route = ao2_iterator_next(&i))) {
01240       if (!route->user)
01241          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01242       route = unref_route(route);
01243    }
01244    ao2_iterator_destroy(&i);
01245 
01246    ast_cli(a->fd, "\nDynamic routes\n\n");
01247    ast_cli(a->fd, FORMAT, "Relative URI", "Template");
01248 
01249    i = ao2_iterator_init(http_routes, 0);
01250    while ((route = ao2_iterator_next(&i))) {
01251       if (route->user)
01252          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01253       route = unref_route(route);
01254    }
01255    ao2_iterator_destroy(&i);
01256 
01257    return CLI_SUCCESS;
01258 }

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

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

Definition at line 317 of file res_phoneprov.c.

References ast_malloc, f, free, and len().

Referenced by phoneprov_callback(), and pp_each_extension_helper().

00318 {
00319    int len = 0;
00320    FILE *f;
00321 
00322    if (!(f = fopen(filename, "r"))) {
00323       *ret = NULL;
00324       return -1;
00325    }
00326 
00327    fseek(f, 0, SEEK_END);
00328    len = ftell(f);
00329    fseek(f, 0, SEEK_SET);
00330    if (!(*ret = ast_malloc(len + 1)))
00331       return -2;
00332 
00333    if (len != fread(*ret, sizeof(char), len, f)) {
00334       free(*ret);
00335       *ret = NULL;
00336       return -3;
00337    }
00338 
00339    fclose(f);
00340 
00341    (*ret)[len] = '\0';
00342 
00343    return len;
00344 }

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

Definition at line 202 of file res_phoneprov.c.

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

Referenced by set_config().

00203 {
00204    int mysock, res = 0;
00205    struct ifreq ifr;
00206    struct sockaddr_in *sin;
00207 
00208    memset(&ifr, 0, sizeof(ifr));
00209    ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
00210 
00211    mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
00212    if (mysock < 0) {
00213       ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
00214       return -1;
00215    }
00216 
00217    res = ioctl(mysock, SIOCGIFADDR, &ifr);
00218 
00219    close(mysock);
00220 
00221    if (res < 0) {
00222       ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
00223       memcpy(address, &__ourip, sizeof(__ourip));
00224       return -1;
00225    } else {
00226       sin = (struct sockaddr_in *)&ifr.ifr_addr;
00227       memcpy(address, &sin->sin_addr, sizeof(*address));
00228       return 0;
00229    }
00230 }

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 407 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_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_substitute_variables_varshead(), ast_strlen_zero(), ast_var_assign(), user::extensions, ast_tcptls_session_instance::fd, http_route::file, extension::headp, len(), load_file(), LOG_ERROR, LOG_WARNING, phoneprov_file::mime_type, name, OBJ_POINTER, phoneprov_file::template, unref_route(), http_route::uri, http_route::user, and var.

00408 {
00409    struct http_route *route;
00410    struct http_route search_route = {
00411       .uri = uri,
00412    };
00413    struct ast_str *result;
00414    char path[PATH_MAX];
00415    char *file = NULL;
00416    int len;
00417    int fd;
00418    struct ast_str *http_header;
00419 
00420    if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
00421       ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
00422       return -1;
00423    }
00424 
00425    if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) {
00426       goto out404;
00427    }
00428 
00429    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
00430 
00431    if (!route->user) { /* Static file */
00432 
00433       fd = open(path, O_RDONLY);
00434       if (fd < 0) {
00435          goto out500;
00436       }
00437 
00438       len = lseek(fd, 0, SEEK_END);
00439       lseek(fd, 0, SEEK_SET);
00440       if (len < 0) {
00441          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00442          close(fd);
00443          goto out500;
00444       }
00445 
00446       http_header = ast_str_create(80);
00447       ast_str_set(&http_header, 0, "Content-type: %s\r\n",
00448          route->file->mime_type);
00449 
00450       ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
00451 
00452       close(fd);
00453       route = unref_route(route);
00454       return 0;
00455    } else { /* Dynamic file */
00456       struct ast_str *tmp;
00457 
00458       len = load_file(path, &file);
00459       if (len < 0) {
00460          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00461          if (file) {
00462             ast_free(file);
00463          }
00464 
00465          goto out500;
00466       }
00467 
00468       if (!file) {
00469          goto out500;
00470       }
00471 
00472       if (!(tmp = ast_str_create(len))) {
00473          if (file) {
00474             ast_free(file);
00475          }
00476 
00477          goto out500;
00478       }
00479 
00480       /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
00481        * the IP address we are listening on that the phone contacted for this config file */
00482       if (ast_strlen_zero(global_server)) {
00483          union {
00484             struct sockaddr sa;
00485             struct sockaddr_in sa_in;
00486          } name;
00487          socklen_t namelen = sizeof(name.sa);
00488          int res;
00489 
00490          if ((res = getsockname(ser->fd, &name.sa, &namelen))) {
00491             ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
00492          } else {
00493             struct ast_var_t *var;
00494             struct extension *exten_iter;
00495 
00496             if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) {
00497                AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
00498                   AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries);
00499                }
00500             }
00501          }
00502       }
00503 
00504       ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
00505 
00506       if (file) {
00507          ast_free(file);
00508       }
00509 
00510       http_header = ast_str_create(80);
00511       ast_str_set(&http_header, 0, "Content-type: %s\r\n",
00512          route->file->mime_type);
00513 
00514       if (!(result = ast_str_create(512))) {
00515          ast_log(LOG_ERROR, "Could not create result string!\n");
00516          if (tmp) {
00517             ast_free(tmp);
00518          }
00519          ast_free(http_header);
00520          goto out500;
00521       }
00522       ast_str_append(&result, 0, "%s", ast_str_buffer(tmp)); 
00523 
00524       ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
00525       if (tmp) {
00526          ast_free(tmp);
00527       }
00528 
00529       route = unref_route(route);
00530 
00531       return 0;
00532    }
00533 
00534 out404:
00535    ast_http_error(ser, 404, "Not Found", "Nothing to see here.  Move along.");
00536    return -1;
00537 
00538 out500:
00539    route = unref_route(route);
00540    ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
00541    return -1;
00542 }

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

01140 {
01141    struct user *user;
01142    struct extension *exten;
01143    char path[PATH_MAX];
01144    char *file;
01145    int filelen;
01146    struct ast_str *str;
01147    AST_DECLARE_APP_ARGS(args,
01148       AST_APP_ARG(mac);
01149       AST_APP_ARG(template);
01150    );
01151 
01152    AST_STANDARD_APP_ARGS(args, data);
01153 
01154    if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
01155       ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
01156       return 0;
01157    }
01158 
01159    if (!(user = find_user(args.mac))) {
01160       ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
01161       return 0;
01162    }
01163 
01164    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
01165    filelen = load_file(path, &file);
01166    if (filelen < 0) {
01167       ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
01168       if (file) {
01169          ast_free(file);
01170       }
01171       return 0;
01172    }
01173 
01174    if (!file) {
01175       return 0;
01176    }
01177 
01178    if (!(str = ast_str_create(filelen))) {
01179       return 0;
01180    }
01181 
01182    AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
01183       ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
01184       if (buf) {
01185          size_t slen = len;
01186          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01187       } else {
01188          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01189       }
01190    }
01191 
01192    ast_free(file);
01193    ast_free(str);
01194 
01195    user = unref_user(user);
01196 
01197    return 0;
01198 }

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

Definition at line 1200 of file res_phoneprov.c.

References pp_each_extension_helper().

01201 {
01202    return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
01203 }

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 1205 of file res_phoneprov.c.

References pp_each_extension_helper().

01206 {
01207    return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
01208 }

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

Referenced by pp_each_user_read(), and pp_each_user_read2().

01083 {
01084    char *tmp;
01085    struct ao2_iterator i;
01086    struct user *user;
01087    struct ast_str *str;
01088    AST_DECLARE_APP_ARGS(args,
01089       AST_APP_ARG(string);
01090       AST_APP_ARG(exclude_mac);
01091    );
01092    AST_STANDARD_APP_ARGS(args, data);
01093 
01094    if (!(str = ast_str_create(16))) {
01095       return -1;
01096    }
01097 
01098    /* Fix data by turning %{ into ${ */
01099    while ((tmp = strstr(args.string, "%{")))
01100       *tmp = '$';
01101 
01102    i = ao2_iterator_init(users, 0);
01103    while ((user = ao2_iterator_next(&i))) {
01104       if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
01105          continue;
01106       }
01107       ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
01108       if (buf) {
01109          size_t slen = len;
01110          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01111       } else {
01112          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01113       }
01114       user = unref_user(user);
01115    }
01116    ao2_iterator_destroy(&i);
01117 
01118    ast_free(str);
01119    return 0;
01120 }

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

Definition at line 1122 of file res_phoneprov.c.

References pp_each_user_helper().

01123 {
01124    return pp_each_user_helper(chan, data, buf, NULL, len);
01125 }

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 1127 of file res_phoneprov.c.

References pp_each_user_helper().

01128 {
01129    return pp_each_user_helper(chan, data, NULL, buf, len);
01130 }

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

Definition at line 256 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and phone_profile::name.

Referenced by load_module().

00257 {
00258    const struct phone_profile *profile1 = obj, *profile2 = arg;
00259 
00260    return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0;
00261 }

static void profile_destructor ( void *  obj  )  [static]

Definition at line 269 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, phone_profile::headp, phone_profile::static_files, and var.

Referenced by build_profile().

00270 {
00271    struct phone_profile *profile = obj;
00272    struct phoneprov_file *file;
00273    struct ast_var_t *var;
00274 
00275    while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry)))
00276       delete_file(file);
00277 
00278    while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry)))
00279       delete_file(file);
00280 
00281    while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries)))
00282       ast_var_delete(var);
00283 
00284    ast_free(profile->headp);
00285    ast_string_field_free_memory(profile);
00286 }

static int profile_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 249 of file res_phoneprov.c.

References ast_str_case_hash(), and phone_profile::name.

Referenced by load_module().

00250 {
00251    const struct phone_profile *profile = obj;
00252 
00253    return ast_str_case_hash(profile->name);
00254 }

static int reload ( void   )  [static]

Definition at line 1321 of file res_phoneprov.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_var_delete(), delete_profiles(), delete_routes(), delete_users(), global_variables, set_config(), and var.

01322 {
01323    struct ast_var_t *var;
01324 
01325    delete_routes();
01326    delete_users();
01327    delete_profiles();
01328 
01329    ast_mutex_lock(&globals_lock);
01330    while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
01331       ast_var_delete(var);
01332    }
01333    ast_mutex_unlock(&globals_lock);
01334 
01335    set_config();
01336 
01337    return 0;
01338 }

static void route_destructor ( void *  obj  )  [static]

Definition at line 309 of file res_phoneprov.c.

References ast_string_field_free_memory.

Referenced by build_route().

00310 {
00311    struct http_route *route = obj;
00312 
00313    ast_string_field_free_memory(route);
00314 }

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

Definition at line 302 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and http_route::uri.

Referenced by load_module().

00303 {
00304    const struct http_route *route1 = obj, *route2 = arg;
00305 
00306    return !strcasecmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0;
00307 }

static int routes_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 295 of file res_phoneprov.c.

References ast_str_case_hash(), and http_route::uri.

Referenced by load_module().

00296 {
00297    const struct http_route *route = obj;
00298 
00299    return ast_str_case_hash(route->uri);
00300 }

static int set_config ( void   )  [static]

Definition at line 906 of file res_phoneprov.c.

References add_user_extension(), ao2_link, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_inet_ntoa(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_true(), ast_var_assign(), ast_variable_browse(), ast_variable_retrieve(), build_extension(), build_profile(), build_user(), build_user_routes(), CONFIG_STATUS_FILEINVALID, delete_extension(), exten, find_profile(), find_user(), global_variables, LOG_ERROR, LOG_WARNING, lookup_iface(), user::macaddress, extension::name, ast_variable::name, ast_variable::next, S_OR, unref_user(), ast_variable::value, and var.

Referenced by load_module(), and reload().

00907 {
00908    struct ast_config *cfg, *phoneprov_cfg;
00909    char *cat;
00910    struct ast_variable *v;
00911    struct ast_flags config_flags = { 0 };
00912    struct ast_var_t *var;
00913 
00914    /* Try to grab the port from sip.conf.  If we don't get it here, we'll set it
00915     * to whatever is set in phoneprov.conf or default to 5060 */
00916    if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
00917       ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport));
00918       ast_config_destroy(cfg);
00919    }
00920 
00921    if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00922       ast_log(LOG_WARNING, "Unable to load users.conf\n");
00923       return 0;
00924    }
00925 
00926    /* Go ahead and load global variables from users.conf so we can append to profiles */
00927    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00928       if (!strcasecmp(v->name, "vmexten")) {
00929          if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) {
00930             ast_mutex_lock(&globals_lock);
00931             AST_LIST_INSERT_TAIL(&global_variables, var, entries);
00932             ast_mutex_unlock(&globals_lock);
00933          }
00934       }
00935       if (!strcasecmp(v->name, "localextenlength")) {
00936          if ((var = ast_var_assign("EXTENSION_LENGTH", v->value)))
00937             ast_mutex_lock(&globals_lock);
00938             AST_LIST_INSERT_TAIL(&global_variables, var, entries);
00939             ast_mutex_unlock(&globals_lock);
00940       }
00941    }
00942 
00943    if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags)) || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
00944       ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
00945       ast_config_destroy(cfg);
00946       return -1;
00947    }
00948 
00949    cat = NULL;
00950    while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
00951       if (!strcasecmp(cat, "general")) {
00952          for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) {
00953             if (!strcasecmp(v->name, "serveraddr"))
00954                ast_copy_string(global_server, v->value, sizeof(global_server));
00955             else if (!strcasecmp(v->name, "serveriface")) {
00956                struct in_addr addr;
00957                lookup_iface(v->value, &addr);
00958                ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server));
00959             } else if (!strcasecmp(v->name, "serverport"))
00960                ast_copy_string(global_serverport, v->value, sizeof(global_serverport));
00961             else if (!strcasecmp(v->name, "default_profile"))
00962                ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile));
00963          }
00964       } else
00965          build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
00966    }
00967 
00968    ast_config_destroy(phoneprov_cfg);
00969 
00970    cat = NULL;
00971    while ((cat = ast_category_browse(cfg, cat))) {
00972       const char *tmp, *mac;
00973       struct user *user;
00974       struct phone_profile *profile;
00975       struct extension *exten;
00976 
00977       if (!strcasecmp(cat, "general")) {
00978          continue;
00979       }
00980 
00981       if (!strcasecmp(cat, "authentication"))
00982          continue;
00983 
00984       if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp)))
00985          continue;
00986 
00987       if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) {
00988          ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
00989          continue;
00990       }
00991 
00992       tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile);
00993       if (ast_strlen_zero(tmp)) {
00994          ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac);
00995          continue;
00996       }
00997 
00998       if (!(user = find_user(mac))) {
00999          if (!(profile = find_profile(tmp))) {
01000             ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp);
01001             continue;
01002          }
01003 
01004          if (!(user = build_user(mac, profile))) {
01005             ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress);
01006             continue;
01007          }
01008 
01009          if (!(exten = build_extension(cfg, cat))) {
01010             ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
01011             user = unref_user(user);
01012             continue;
01013          }
01014 
01015          if (add_user_extension(user, exten)) {
01016             ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01017             user = unref_user(user);
01018             exten = delete_extension(exten);
01019             continue;
01020          }
01021 
01022          if (build_user_routes(user)) {
01023             ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress);
01024             user = unref_user(user);
01025             continue;
01026          }
01027 
01028          ao2_link(users, user);
01029          user = unref_user(user);
01030       } else {
01031          if (!(exten = build_extension(cfg, cat))) {
01032             ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
01033             user = unref_user(user);
01034             continue;
01035          }
01036 
01037          if (add_user_extension(user, exten)) {
01038             ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01039             user = unref_user(user);
01040             exten = delete_extension(exten);
01041             continue;
01042          }
01043 
01044          user = unref_user(user);
01045       }
01046    }
01047 
01048    ast_config_destroy(cfg);
01049 
01050    return 0;
01051 }

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 350 of file res_phoneprov.c.

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

Referenced by build_extension().

00351 {
00352    time_t utc_time;
00353    int dstenable;
00354    time_t dststart;
00355    time_t dstend;
00356    struct ast_tm tm_info;
00357    int tzoffset;
00358    char buffer[21];
00359    struct ast_var_t *var;
00360    struct timeval when;
00361 
00362    time(&utc_time);
00363    ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
00364    snprintf(buffer, sizeof(buffer), "%d", tzoffset);
00365    var = ast_var_assign("TZOFFSET", buffer);
00366    if (var)
00367       AST_LIST_INSERT_TAIL(headp, var, entries);
00368 
00369    if (!dstenable)
00370       return;
00371 
00372    if ((var = ast_var_assign("DST_ENABLE", "1")))
00373       AST_LIST_INSERT_TAIL(headp, var, entries);
00374 
00375    when.tv_sec = dststart;
00376    ast_localtime(&when, &tm_info, zone);
00377 
00378    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
00379    if ((var = ast_var_assign("DST_START_MONTH", buffer)))
00380       AST_LIST_INSERT_TAIL(headp, var, entries);
00381 
00382    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00383    if ((var = ast_var_assign("DST_START_MDAY", buffer)))
00384       AST_LIST_INSERT_TAIL(headp, var, entries);
00385 
00386    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00387    if ((var = ast_var_assign("DST_START_HOUR", buffer)))
00388       AST_LIST_INSERT_TAIL(headp, var, entries);
00389 
00390    when.tv_sec = dstend;
00391    ast_localtime(&when, &tm_info, zone);
00392 
00393    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
00394    if ((var = ast_var_assign("DST_END_MONTH", buffer)))
00395       AST_LIST_INSERT_TAIL(headp, var, entries);
00396 
00397    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00398    if ((var = ast_var_assign("DST_END_MDAY", buffer)))
00399       AST_LIST_INSERT_TAIL(headp, var, entries);
00400 
00401    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00402    if ((var = ast_var_assign("DST_END_HOUR", buffer)))
00403       AST_LIST_INSERT_TAIL(headp, var, entries);
00404 }

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

Definition at line 232 of file res_phoneprov.c.

References ao2_ref.

Referenced by build_profile(), build_user(), delete_profiles(), and user_destructor().

00233 {
00234    ao2_ref(prof, -1);
00235 
00236    return NULL;
00237 }

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

Definition at line 288 of file res_phoneprov.c.

References ao2_ref.

Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().

00289 {
00290    ao2_ref(route, -1);
00291 
00292    return NULL;
00293 }

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

Definition at line 758 of file res_phoneprov.c.

References ao2_ref.

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

00759 {
00760    ao2_ref(user, -1);
00761 
00762    return NULL;
00763 }

static void user_destructor ( void *  obj  )  [static]

Free all memory associated with a user.

Definition at line 790 of file res_phoneprov.c.

References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), exten, user::extensions, user::profile, and unref_profile().

Referenced by build_user().

00791 {
00792    struct user *user = obj;
00793    struct extension *exten;
00794 
00795    while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
00796       exten = delete_extension(exten);
00797    }
00798 
00799    if (user->profile) {
00800       user->profile = unref_profile(user->profile);
00801    }
00802 
00803    ast_string_field_free_memory(user);
00804 }

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

Definition at line 782 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and user::macaddress.

Referenced by load_module().

00783 {
00784    const struct user *user1 = obj, *user2 = arg;
00785 
00786    return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0;
00787 }

static int users_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 775 of file res_phoneprov.c.

References ast_str_case_hash(), and user::macaddress.

Referenced by load_module().

00776 {
00777    const struct user *user = obj;
00778 
00779    return ast_str_case_hash(user->macaddress);
00780 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1344 of file res_phoneprov.c.

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

for use in lookup_iface

Definition at line 104 of file res_phoneprov.c.

Definition at line 1344 of file res_phoneprov.c.

char global_default_profile[80] = "" [static]

Default profile to use if one isn't specified

Definition at line 195 of file res_phoneprov.c.

char global_server[80] = "" [static]

Server to substitute into templates

Definition at line 193 of file res_phoneprov.c.

char global_serverport[6] = "" [static]

Server port to substitute into templates

Definition at line 194 of file res_phoneprov.c.

struct varshead global_variables [static]

List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.

Definition at line 198 of file res_phoneprov.c.

Referenced by build_profile(), load_module(), reload(), set_config(), and unload_module().

Definition at line 199 of file res_phoneprov.c.

Referenced by load_config(), and set_pvt_defaults().

struct ao2_container* http_routes [static]

Definition at line 190 of file res_phoneprov.c.

struct ast_http_uri phoneprovuri [static]

Definition at line 1264 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 1260 of file res_phoneprov.c.

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

Definition at line 1210 of file res_phoneprov.c.

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

Definition at line 1132 of file res_phoneprov.c.

Lookup table to translate between users.conf property names and variables for use in phoneprov templates.

Referenced by build_extension().

struct ao2_container* profiles [static]

Definition at line 189 of file res_phoneprov.c.

struct ao2_container* users [static]

Definition at line 191 of file res_phoneprov.c.


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1