#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 extension * | build_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 user * | build_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 extension * | delete_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_profile * | find_profile (const char *name) |
Return a phone profile looked up by name. | |
static struct user * | find_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_profile * | unref_profile (struct phone_profile *prof) |
static struct http_route * | unref_route (struct http_route *route) |
static struct user * | unref_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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_info * | ast_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_container * | http_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_container * | profiles |
static struct ao2_container * | users |
Terry Wilson <twilson@digium.com>
Definition in file res_phoneprov.c.
#define FORMAT "%-40.40s %-30.30s\n" |
#define MAX_PROFILE_BUCKETS 17 |
#define MAX_ROUTE_BUCKETS 563 |
#define MAX_USER_BUCKETS 563 |
Definition at line 63 of file res_phoneprov.c.
#define VAR_BUF_SIZE 4096 |
Definition at line 66 of file res_phoneprov.c.
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 |
Definition at line 104 of file res_phoneprov.c.
00104 { 00105 PP_MACADDRESS, 00106 PP_USERNAME, 00107 PP_FULLNAME, 00108 PP_SECRET, 00109 PP_LABEL, 00110 PP_CALLERID, 00111 PP_TIMEZONE, 00112 PP_LINENUMBER, 00113 PP_LINEKEYS, 00114 PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */ 00115 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 1340 of file res_phoneprov.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1340 of file res_phoneprov.c.
Add an extension to a user ordered by index/linenumber.
Definition at line 839 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(), ast_var_t::entries, phoneprov_file::entry, exten, extension::index, LOG_WARNING, str, user, and var.
00840 { 00841 struct ast_var_t *var; 00842 struct ast_str *str = ast_str_create(16); 00843 00844 if (!str) { 00845 return -1; 00846 } 00847 00848 /* Append profile variables here, and substitute variables on profile 00849 * setvars, so that we can use user specific variables in them */ 00850 AST_LIST_TRAVERSE(user->profile->headp, var, entries) { 00851 struct ast_var_t *var2; 00852 00853 ast_str_substitute_variables_varshead(&str, 0, exten->headp, var->value); 00854 if ((var2 = ast_var_assign(var->name, ast_str_buffer(str)))) { 00855 AST_LIST_INSERT_TAIL(exten->headp, var2, entries); 00856 } 00857 } 00858 00859 ast_free(str); 00860 00861 if (AST_LIST_EMPTY(&user->extensions)) { 00862 AST_LIST_INSERT_HEAD(&user->extensions, exten, entry); 00863 } else { 00864 struct extension *exten_iter; 00865 00866 AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) { 00867 if (exten->index < exten_iter->index) { 00868 AST_LIST_INSERT_BEFORE_CURRENT(exten, entry); 00869 } else if (exten->index == exten_iter->index) { 00870 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress); 00871 return -1; 00872 } else if (!AST_LIST_NEXT(exten_iter, entry)) { 00873 AST_LIST_INSERT_TAIL(&user->extensions, exten, entry); 00874 } 00875 } 00876 AST_LIST_TRAVERSE_SAFE_END; 00877 } 00878 00879 return 0; 00880 }
static struct extension* build_extension | ( | struct ast_config * | cfg, | |
const char * | name | |||
) | [static] |
Definition at line 694 of file res_phoneprov.c.
References ast_calloc, ast_calloc_with_stringfields, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_set, ast_var_assign(), ast_variable_retrieve(), ast_var_t::entries, exten, PP_LINEKEYS, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.
00695 { 00696 struct extension *exten; 00697 struct ast_var_t *var; 00698 const char *tmp; 00699 int i; 00700 00701 if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) { 00702 return NULL; 00703 } 00704 00705 ast_string_field_set(exten, name, name); 00706 00707 if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) { 00708 ast_free(exten); 00709 exten = NULL; 00710 return NULL; 00711 } 00712 00713 for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { 00714 tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); 00715 00716 /* If we didn't get a USERNAME variable, set it to the user->name */ 00717 if (i == PP_USERNAME && !tmp) { 00718 if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) { 00719 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00720 } 00721 continue; 00722 } else if (i == PP_TIMEZONE) { 00723 /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ 00724 set_timezone_variables(exten->headp, tmp); 00725 } else if (i == PP_LINENUMBER) { 00726 if (!tmp) { 00727 tmp = "1"; 00728 } 00729 exten->index = atoi(tmp); 00730 } else if (i == PP_LINEKEYS) { 00731 if (!tmp) { 00732 tmp = "1"; 00733 } 00734 } 00735 00736 if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) { 00737 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00738 } 00739 } 00740 00741 if (!ast_strlen_zero(global_server)) { 00742 if ((var = ast_var_assign("SERVER", global_server))) 00743 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00744 } 00745 00746 if (!ast_strlen_zero(global_serverport)) { 00747 if ((var = ast_var_assign("SERVER_PORT", global_serverport))) 00748 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00749 } 00750 00751 return exten; 00752 }
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.
name | the name of the profile | |
v | ast_variable from parsing phoneprov.conf |
Definition at line 572 of file res_phoneprov.c.
References ao2_alloc, args, AST_APP_ARG, ast_calloc, AST_DECLARE_APP_ARGS, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strip(), ast_strlen_zero(), ast_var_assign(), ast_var_t::entries, ast_variable::name, ast_variable::next, profile_destructor(), unref_profile(), ast_variable::value, and var.
00573 { 00574 struct phone_profile *profile; 00575 struct ast_var_t *var; 00576 00577 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) { 00578 return; 00579 } 00580 00581 if (ast_string_field_init(profile, 32)) { 00582 profile = unref_profile(profile); 00583 return; 00584 } 00585 00586 if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { 00587 profile = unref_profile(profile); 00588 return; 00589 } 00590 00591 AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); 00592 AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); 00593 00594 ast_string_field_set(profile, name, name); 00595 for (; v; v = v->next) { 00596 if (!strcasecmp(v->name, "mime_type")) { 00597 ast_string_field_set(profile, default_mime_type, v->value); 00598 } else if (!strcasecmp(v->name, "setvar")) { 00599 struct ast_var_t *variable; 00600 char *value_copy = ast_strdupa(v->value); 00601 00602 AST_DECLARE_APP_ARGS(args, 00603 AST_APP_ARG(varname); 00604 AST_APP_ARG(varval); 00605 ); 00606 00607 AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); 00608 do { 00609 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00610 break; 00611 args.varname = ast_strip(args.varname); 00612 args.varval = ast_strip(args.varval); 00613 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00614 break; 00615 if ((variable = ast_var_assign(args.varname, args.varval))) 00616 AST_LIST_INSERT_TAIL(profile->headp, variable, entries); 00617 } while (0); 00618 } else if (!strcasecmp(v->name, "staticdir")) { 00619 ast_string_field_set(profile, staticdir, v->value); 00620 } else { 00621 struct phoneprov_file *pp_file; 00622 char *file_extension; 00623 char *value_copy = ast_strdupa(v->value); 00624 00625 AST_DECLARE_APP_ARGS(args, 00626 AST_APP_ARG(filename); 00627 AST_APP_ARG(mimetype); 00628 ); 00629 00630 if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) { 00631 profile = unref_profile(profile); 00632 return; 00633 } 00634 00635 if ((file_extension = strrchr(pp_file->format, '.'))) 00636 file_extension++; 00637 00638 AST_STANDARD_APP_ARGS(args, value_copy); 00639 00640 /* Mime type order of preference 00641 * 1) Specific mime-type defined for file in profile 00642 * 2) Mime determined by extension 00643 * 3) Default mime type specified in profile 00644 * 4) text/plain 00645 */ 00646 ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, 00647 (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); 00648 00649 if (!strcasecmp(v->name, "static_file")) { 00650 ast_string_field_set(pp_file, format, args.filename); 00651 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); 00652 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); 00653 /* Add a route for the static files, as their filenames won't change per-user */ 00654 build_route(pp_file, NULL, NULL); 00655 } else { 00656 ast_string_field_set(pp_file, format, v->name); 00657 ast_string_field_set(pp_file, template, args.filename); 00658 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); 00659 } 00660 } 00661 } 00662 00663 /* Append the global variables to the variables list for this profile. 00664 * This is for convenience later, when we need to provide a single 00665 * variable list for use in substitution. */ 00666 ast_mutex_lock(&globals_lock); 00667 AST_LIST_TRAVERSE(&global_variables, var, entries) { 00668 struct ast_var_t *new_var; 00669 if ((new_var = ast_var_assign(var->name, var->value))) { 00670 AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); 00671 } 00672 } 00673 ast_mutex_unlock(&globals_lock); 00674 00675 ao2_link(profiles, profile); 00676 00677 profile = unref_profile(profile); 00678 }
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.
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 545 of file res_phoneprov.c.
References ao2_alloc, ao2_link, ast_log(), ast_string_field_init, ast_string_field_set, phoneprov_file::format, http_routes, LOG_ERROR, route_destructor(), S_OR, unref_route(), and user.
00546 { 00547 struct http_route *route; 00548 00549 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) { 00550 return; 00551 } 00552 00553 if (ast_string_field_init(route, 32)) { 00554 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); 00555 route = unref_route(route); 00556 return; 00557 } 00558 00559 ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); 00560 route->user = user; 00561 route->file = pp_file; 00562 00563 ao2_link(http_routes, route); 00564 00565 route = unref_route(route); 00566 }
static struct user* build_user | ( | const char * | mac, | |
struct phone_profile * | profile | |||
) | [static] |
Build and return a user structure based on gathered config data.
Definition at line 817 of file res_phoneprov.c.
References ao2_alloc, ast_string_field_init, ast_string_field_set, user::macaddress, user::profile, unref_profile(), unref_user(), user, and user_destructor().
00818 { 00819 struct user *user; 00820 00821 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) { 00822 profile = unref_profile(profile); 00823 return NULL; 00824 } 00825 00826 if (ast_string_field_init(user, 32)) { 00827 profile = unref_profile(profile); 00828 user = unref_user(user); 00829 return NULL; 00830 } 00831 00832 ast_string_field_set(user, macaddress, mac); 00833 user->profile = profile; /* already ref counted by find_profile */ 00834 00835 return user; 00836 }
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 883 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(), phoneprov_file::entry, phoneprov_file::format, str, and user.
00884 { 00885 struct phoneprov_file *pp_file; 00886 struct ast_str *str; 00887 00888 if (!(str = ast_str_create(16))) { 00889 return -1; 00890 } 00891 00892 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { 00893 ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format); 00894 build_route(pp_file, user, ast_str_buffer(str)); 00895 } 00896 00897 ast_free(str); 00898 return 0; 00899 }
Definition at line 680 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, exten, and var.
Referenced by user_destructor().
00681 { 00682 struct ast_var_t *var; 00683 while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) { 00684 ast_var_delete(var); 00685 } 00686 ast_free(exten->headp); 00687 ast_string_field_free_memory(exten); 00688 00689 ast_free(exten); 00690 00691 return NULL; 00692 }
static void delete_file | ( | struct phoneprov_file * | file | ) | [static] |
Definition at line 259 of file res_phoneprov.c.
References ast_string_field_free_memory, and free.
Referenced by profile_destructor().
00260 { 00261 ast_string_field_free_memory(file); 00262 free(file); 00263 }
static void delete_profiles | ( | void | ) | [static] |
Delete all phone profiles, freeing their memory.
Definition at line 1064 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, profiles, and unref_profile().
Referenced by reload(), and unload_module().
01065 { 01066 struct ao2_iterator i; 01067 struct phone_profile *profile; 01068 01069 i = ao2_iterator_init(profiles, 0); 01070 while ((profile = ao2_iterator_next(&i))) { 01071 ao2_unlink(profiles, profile); 01072 profile = unref_profile(profile); 01073 } 01074 ao2_iterator_destroy(&i); 01075 }
static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 1050 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, http_routes, and unref_route().
Referenced by reload(), and unload_module().
01051 { 01052 struct ao2_iterator i; 01053 struct http_route *route; 01054 01055 i = ao2_iterator_init(http_routes, 0); 01056 while ((route = ao2_iterator_next(&i))) { 01057 ao2_unlink(http_routes, route); 01058 route = unref_route(route); 01059 } 01060 ao2_iterator_destroy(&i); 01061 }
static void delete_users | ( | void | ) | [static] |
Delete all users.
Definition at line 803 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, unref_user(), user, and users.
00804 { 00805 struct ao2_iterator i; 00806 struct user *user; 00807 00808 i = ao2_iterator_init(users, 0); 00809 while ((user = ao2_iterator_next(&i))) { 00810 ao2_unlink(users, user); 00811 user = unref_user(user); 00812 } 00813 ao2_iterator_destroy(&i); 00814 }
static struct phone_profile* find_profile | ( | const char * | name | ) | [static] |
Return a phone profile looked up by name.
Definition at line 236 of file res_phoneprov.c.
References ao2_find, phone_profile::name, OBJ_POINTER, and profiles.
00237 { 00238 struct phone_profile tmp = { 00239 .name = name, 00240 }; 00241 00242 return ao2_find(profiles, &tmp, OBJ_POINTER); 00243 }
static struct user* find_user | ( | const char * | macaddress | ) | [static] |
Return a user looked up by name.
Definition at line 762 of file res_phoneprov.c.
References ao2_find, user::macaddress, OBJ_POINTER, and users.
00763 { 00764 struct user tmp = { 00765 .macaddress = macaddress, 00766 }; 00767 00768 return ao2_find(users, &tmp, OBJ_POINTER); 00769 }
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 1213 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, http_routes, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.
01214 { 01215 #define FORMAT "%-40.40s %-30.30s\n" 01216 struct ao2_iterator i; 01217 struct http_route *route; 01218 01219 switch(cmd) { 01220 case CLI_INIT: 01221 e->command = "phoneprov show routes"; 01222 e->usage = 01223 "Usage: phoneprov show routes\n" 01224 " Lists all registered phoneprov http routes.\n"; 01225 return NULL; 01226 case CLI_GENERATE: 01227 return NULL; 01228 } 01229 01230 /* This currently iterates over routes twice, but it is the only place I've needed 01231 * to really separate static an dynamic routes, so I've just left it this way. */ 01232 ast_cli(a->fd, "Static routes\n\n"); 01233 ast_cli(a->fd, FORMAT, "Relative URI", "Physical location"); 01234 i = ao2_iterator_init(http_routes, 0); 01235 while ((route = ao2_iterator_next(&i))) { 01236 if (!route->user) 01237 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01238 route = unref_route(route); 01239 } 01240 ao2_iterator_destroy(&i); 01241 01242 ast_cli(a->fd, "\nDynamic routes\n\n"); 01243 ast_cli(a->fd, FORMAT, "Relative URI", "Template"); 01244 01245 i = ao2_iterator_init(http_routes, 0); 01246 while ((route = ao2_iterator_next(&i))) { 01247 if (route->user) 01248 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01249 route = unref_route(route); 01250 } 01251 ao2_iterator_destroy(&i); 01252 01253 return CLI_SUCCESS; 01254 }
static int load_file | ( | const char * | filename, | |
char ** | ret | |||
) | [static] |
Read a TEXT file into a string and return the length.
Definition at line 313 of file res_phoneprov.c.
References ast_malloc, f, free, and len().
Referenced by phoneprov_callback(), and pp_each_extension_helper().
00314 { 00315 int len = 0; 00316 FILE *f; 00317 00318 if (!(f = fopen(filename, "r"))) { 00319 *ret = NULL; 00320 return -1; 00321 } 00322 00323 fseek(f, 0, SEEK_END); 00324 len = ftell(f); 00325 fseek(f, 0, SEEK_SET); 00326 if (!(*ret = ast_malloc(len + 1))) 00327 return -2; 00328 00329 if (len != fread(*ret, sizeof(char), len, f)) { 00330 free(*ret); 00331 *ret = NULL; 00332 return -3; 00333 } 00334 00335 fclose(f); 00336 00337 (*ret)[len] = '\0'; 00338 00339 return len; 00340 }
static int load_module | ( | void | ) | [static] |
Definition at line 1269 of file res_phoneprov.c.
References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_http_uri_link(), AST_LIST_HEAD_INIT_NOLOCK, ast_mutex_init, global_variables, globals_lock, http_routes, MAX_PROFILE_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profile_cmp_fn(), profile_hash_fn(), profiles, routes_cmp_fn(), routes_hash_fn(), set_config(), users, users_cmp_fn(), and users_hash_fn().
01270 { 01271 profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn); 01272 01273 http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn); 01274 01275 users = ao2_container_alloc(MAX_USER_BUCKETS, users_hash_fn, users_cmp_fn); 01276 01277 AST_LIST_HEAD_INIT_NOLOCK(&global_variables); 01278 ast_mutex_init(&globals_lock); 01279 01280 ast_custom_function_register(&pp_each_user_function); 01281 ast_custom_function_register(&pp_each_extension_function); 01282 ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01283 01284 set_config(); 01285 ast_http_uri_link(&phoneprovuri); 01286 01287 return 0; 01288 }
static int lookup_iface | ( | const char * | iface, | |
struct in_addr * | address | |||
) | [static] |
Definition at line 198 of file res_phoneprov.c.
References ast_copy_string(), ast_log(), errno, LOG_ERROR, and LOG_WARNING.
00199 { 00200 int mysock, res = 0; 00201 struct ifreq ifr; 00202 struct sockaddr_in *sin; 00203 00204 memset(&ifr, 0, sizeof(ifr)); 00205 ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 00206 00207 mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 00208 if (mysock < 0) { 00209 ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno)); 00210 return -1; 00211 } 00212 00213 res = ioctl(mysock, SIOCGIFADDR, &ifr); 00214 00215 close(mysock); 00216 00217 if (res < 0) { 00218 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno)); 00219 memcpy(address, &__ourip, sizeof(__ourip)); 00220 return -1; 00221 } else { 00222 sin = (struct sockaddr_in *)&ifr.ifr_addr; 00223 memcpy(address, &sin->sin_addr, sizeof(*address)); 00224 return 0; 00225 } 00226 }
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 403 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(), phoneprov_file::entry, user::extensions, ast_tcptls_session_instance::fd, http_route::file, extension::headp, http_routes, 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.
00404 { 00405 struct http_route *route; 00406 struct http_route search_route = { 00407 .uri = uri, 00408 }; 00409 struct ast_str *result; 00410 char path[PATH_MAX]; 00411 char *file = NULL; 00412 int len; 00413 int fd; 00414 struct ast_str *http_header; 00415 00416 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) { 00417 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 00418 return -1; 00419 } 00420 00421 if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) { 00422 goto out404; 00423 } 00424 00425 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template); 00426 00427 if (!route->user) { /* Static file */ 00428 00429 fd = open(path, O_RDONLY); 00430 if (fd < 0) { 00431 goto out500; 00432 } 00433 00434 len = lseek(fd, 0, SEEK_END); 00435 lseek(fd, 0, SEEK_SET); 00436 if (len < 0) { 00437 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00438 close(fd); 00439 goto out500; 00440 } 00441 00442 http_header = ast_str_create(80); 00443 ast_str_set(&http_header, 0, "Content-type: %s", 00444 route->file->mime_type); 00445 00446 ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0); 00447 00448 close(fd); 00449 route = unref_route(route); 00450 return 0; 00451 } else { /* Dynamic file */ 00452 struct ast_str *tmp; 00453 00454 len = load_file(path, &file); 00455 if (len < 0) { 00456 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00457 if (file) { 00458 ast_free(file); 00459 } 00460 00461 goto out500; 00462 } 00463 00464 if (!file) { 00465 goto out500; 00466 } 00467 00468 if (!(tmp = ast_str_create(len))) { 00469 if (file) { 00470 ast_free(file); 00471 } 00472 00473 goto out500; 00474 } 00475 00476 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to 00477 * the IP address we are listening on that the phone contacted for this config file */ 00478 if (ast_strlen_zero(global_server)) { 00479 union { 00480 struct sockaddr sa; 00481 struct sockaddr_in sa_in; 00482 } name; 00483 socklen_t namelen = sizeof(name.sa); 00484 int res; 00485 00486 if ((res = getsockname(ser->fd, &name.sa, &namelen))) { 00487 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); 00488 } else { 00489 struct ast_var_t *var; 00490 struct extension *exten_iter; 00491 00492 if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) { 00493 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) { 00494 AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries); 00495 } 00496 } 00497 } 00498 } 00499 00500 ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file); 00501 00502 if (file) { 00503 ast_free(file); 00504 } 00505 00506 http_header = ast_str_create(80); 00507 ast_str_set(&http_header, 0, "Content-type: %s", 00508 route->file->mime_type); 00509 00510 if (!(result = ast_str_create(512))) { 00511 ast_log(LOG_ERROR, "Could not create result string!\n"); 00512 if (tmp) { 00513 ast_free(tmp); 00514 } 00515 ast_free(http_header); 00516 goto out500; 00517 } 00518 ast_str_append(&result, 0, "%s", ast_str_buffer(tmp)); 00519 00520 ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0); 00521 if (tmp) { 00522 ast_free(tmp); 00523 } 00524 00525 route = unref_route(route); 00526 00527 return 0; 00528 } 00529 00530 out404: 00531 ast_http_error(ser, 404, "Not Found", "Nothing to see here. Move along."); 00532 return -1; 00533 00534 out500: 00535 route = unref_route(route); 00536 ast_http_error(ser, 500, "Internal Error", "An internal error has occured."); 00537 return -1; 00538 }
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 1135 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, find_user(), load_file(), LOG_WARNING, str, unref_user(), and user.
Referenced by pp_each_extension_read(), and pp_each_extension_read2().
01136 { 01137 struct user *user; 01138 struct extension *exten; 01139 char path[PATH_MAX]; 01140 char *file; 01141 int filelen; 01142 struct ast_str *str; 01143 AST_DECLARE_APP_ARGS(args, 01144 AST_APP_ARG(mac); 01145 AST_APP_ARG(template); 01146 ); 01147 01148 AST_STANDARD_APP_ARGS(args, data); 01149 01150 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) { 01151 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n"); 01152 return 0; 01153 } 01154 01155 if (!(user = find_user(args.mac))) { 01156 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac); 01157 return 0; 01158 } 01159 01160 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template); 01161 filelen = load_file(path, &file); 01162 if (filelen < 0) { 01163 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen); 01164 if (file) { 01165 ast_free(file); 01166 } 01167 return 0; 01168 } 01169 01170 if (!file) { 01171 return 0; 01172 } 01173 01174 if (!(str = ast_str_create(filelen))) { 01175 return 0; 01176 } 01177 01178 AST_LIST_TRAVERSE(&user->extensions, exten, entry) { 01179 ast_str_substitute_variables_varshead(&str, 0, exten->headp, file); 01180 if (buf) { 01181 size_t slen = len; 01182 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str)); 01183 } else { 01184 ast_str_append(bufstr, len, "%s", ast_str_buffer(str)); 01185 } 01186 } 01187 01188 ast_free(file); 01189 ast_free(str); 01190 01191 user = unref_user(user); 01192 01193 return 0; 01194 }
static int pp_each_extension_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1196 of file res_phoneprov.c.
References pp_each_extension_helper().
01197 { 01198 return pp_each_extension_helper(chan, cmd, data, buf, NULL, len); 01199 }
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 1201 of file res_phoneprov.c.
References pp_each_extension_helper().
01202 { 01203 return pp_each_extension_helper(chan, cmd, data, NULL, buf, len); 01204 }
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 1078 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(), str, string, unref_user(), user, and users.
Referenced by pp_each_user_read(), and pp_each_user_read2().
01079 { 01080 char *tmp; 01081 struct ao2_iterator i; 01082 struct user *user; 01083 struct ast_str *str; 01084 AST_DECLARE_APP_ARGS(args, 01085 AST_APP_ARG(string); 01086 AST_APP_ARG(exclude_mac); 01087 ); 01088 AST_STANDARD_APP_ARGS(args, data); 01089 01090 if (!(str = ast_str_create(16))) { 01091 return -1; 01092 } 01093 01094 /* Fix data by turning %{ into ${ */ 01095 while ((tmp = strstr(args.string, "%{"))) 01096 *tmp = '$'; 01097 01098 i = ao2_iterator_init(users, 0); 01099 while ((user = ao2_iterator_next(&i))) { 01100 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) { 01101 continue; 01102 } 01103 ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string); 01104 if (buf) { 01105 size_t slen = len; 01106 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str)); 01107 } else { 01108 ast_str_append(bufstr, len, "%s", ast_str_buffer(str)); 01109 } 01110 user = unref_user(user); 01111 } 01112 ao2_iterator_destroy(&i); 01113 01114 ast_free(str); 01115 return 0; 01116 }
static int pp_each_user_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 pp_each_user_helper().
01119 { 01120 return pp_each_user_helper(chan, data, buf, NULL, len); 01121 }
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 1123 of file res_phoneprov.c.
References pp_each_user_helper().
01124 { 01125 return pp_each_user_helper(chan, data, NULL, buf, len); 01126 }
static int profile_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 252 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and phone_profile::name.
Referenced by load_module().
00253 { 00254 const struct phone_profile *profile1 = obj, *profile2 = arg; 00255 00256 return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0; 00257 }
static void profile_destructor | ( | void * | obj | ) | [static] |
Definition at line 265 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, phoneprov_file::entry, phone_profile::headp, phone_profile::static_files, and var.
Referenced by build_profile().
00266 { 00267 struct phone_profile *profile = obj; 00268 struct phoneprov_file *file; 00269 struct ast_var_t *var; 00270 00271 while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) 00272 delete_file(file); 00273 00274 while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) 00275 delete_file(file); 00276 00277 while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) 00278 ast_var_delete(var); 00279 00280 ast_free(profile->headp); 00281 ast_string_field_free_memory(profile); 00282 }
static int profile_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 245 of file res_phoneprov.c.
References ast_str_case_hash(), and phone_profile::name.
Referenced by load_module().
00246 { 00247 const struct phone_profile *profile = obj; 00248 00249 return ast_str_case_hash(profile->name); 00250 }
static int reload | ( | void | ) | [static] |
Definition at line 1317 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(), ast_var_t::entries, global_variables, globals_lock, set_config(), and var.
01318 { 01319 struct ast_var_t *var; 01320 01321 delete_routes(); 01322 delete_users(); 01323 delete_profiles(); 01324 01325 ast_mutex_lock(&globals_lock); 01326 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01327 ast_var_delete(var); 01328 } 01329 ast_mutex_unlock(&globals_lock); 01330 01331 set_config(); 01332 01333 return 0; 01334 }
static void route_destructor | ( | void * | obj | ) | [static] |
Definition at line 305 of file res_phoneprov.c.
References ast_string_field_free_memory.
Referenced by build_route().
00306 { 00307 struct http_route *route = obj; 00308 00309 ast_string_field_free_memory(route); 00310 }
static int routes_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 298 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and http_route::uri.
Referenced by load_module().
00299 { 00300 const struct http_route *route1 = obj, *route2 = arg; 00301 00302 return !strcasecmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0; 00303 }
static int routes_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 291 of file res_phoneprov.c.
References ast_str_case_hash(), and http_route::uri.
Referenced by load_module().
00292 { 00293 const struct http_route *route = obj; 00294 00295 return ast_str_case_hash(route->uri); 00296 }
static int set_config | ( | void | ) | [static] |
Definition at line 902 of file res_phoneprov.c.
References ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_var_assign(), ast_variable_browse(), ast_variable_retrieve(), config_flags, CONFIG_STATUS_FILEINVALID, ast_var_t::entries, global_variables, globals_lock, LOG_WARNING, ast_variable::name, ast_variable::next, S_OR, ast_variable::value, and var.
00903 { 00904 struct ast_config *cfg, *phoneprov_cfg; 00905 char *cat; 00906 struct ast_variable *v; 00907 struct ast_flags config_flags = { 0 }; 00908 struct ast_var_t *var; 00909 00910 /* Try to grab the port from sip.conf. If we don't get it here, we'll set it 00911 * to whatever is set in phoneprov.conf or default to 5060 */ 00912 if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) { 00913 ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); 00914 ast_config_destroy(cfg); 00915 } 00916 00917 if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) { 00918 ast_log(LOG_WARNING, "Unable to load users.conf\n"); 00919 return 0; 00920 } 00921 00922 /* Go ahead and load global variables from users.conf so we can append to profiles */ 00923 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00924 if (!strcasecmp(v->name, "vmexten")) { 00925 if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) { 00926 ast_mutex_lock(&globals_lock); 00927 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00928 ast_mutex_unlock(&globals_lock); 00929 } 00930 } 00931 if (!strcasecmp(v->name, "localextenlength")) { 00932 if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) 00933 ast_mutex_lock(&globals_lock); 00934 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00935 ast_mutex_unlock(&globals_lock); 00936 } 00937 } 00938 00939 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags)) || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) { 00940 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); 00941 ast_config_destroy(cfg); 00942 return -1; 00943 } 00944 00945 cat = NULL; 00946 while ((cat = ast_category_browse(phoneprov_cfg, cat))) { 00947 if (!strcasecmp(cat, "general")) { 00948 for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) { 00949 if (!strcasecmp(v->name, "serveraddr")) 00950 ast_copy_string(global_server, v->value, sizeof(global_server)); 00951 else if (!strcasecmp(v->name, "serveriface")) { 00952 struct in_addr addr; 00953 lookup_iface(v->value, &addr); 00954 ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); 00955 } else if (!strcasecmp(v->name, "serverport")) 00956 ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); 00957 else if (!strcasecmp(v->name, "default_profile")) 00958 ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); 00959 } 00960 } else 00961 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat)); 00962 } 00963 00964 ast_config_destroy(phoneprov_cfg); 00965 00966 cat = NULL; 00967 while ((cat = ast_category_browse(cfg, cat))) { 00968 const char *tmp, *mac; 00969 struct user *user; 00970 struct phone_profile *profile; 00971 struct extension *exten; 00972 00973 if (!strcasecmp(cat, "general")) { 00974 continue; 00975 } 00976 00977 if (!strcasecmp(cat, "authentication")) 00978 continue; 00979 00980 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) 00981 continue; 00982 00983 if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { 00984 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); 00985 continue; 00986 } 00987 00988 tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); 00989 if (ast_strlen_zero(tmp)) { 00990 ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); 00991 continue; 00992 } 00993 00994 if (!(user = find_user(mac))) { 00995 if (!(profile = find_profile(tmp))) { 00996 ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); 00997 continue; 00998 } 00999 01000 if (!(user = build_user(mac, profile))) { 01001 ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress); 01002 continue; 01003 } 01004 01005 if (!(exten = build_extension(cfg, cat))) { 01006 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01007 user = unref_user(user); 01008 continue; 01009 } 01010 01011 if (add_user_extension(user, exten)) { 01012 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01013 user = unref_user(user); 01014 exten = delete_extension(exten); 01015 continue; 01016 } 01017 01018 if (build_user_routes(user)) { 01019 ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress); 01020 user = unref_user(user); 01021 continue; 01022 } 01023 01024 ao2_link(users, user); 01025 user = unref_user(user); 01026 } else { 01027 if (!(exten = build_extension(cfg, cat))) { 01028 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01029 user = unref_user(user); 01030 continue; 01031 } 01032 01033 if (add_user_extension(user, exten)) { 01034 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01035 user = unref_user(user); 01036 exten = delete_extension(exten); 01037 continue; 01038 } 01039 01040 user = unref_user(user); 01041 } 01042 } 01043 01044 ast_config_destroy(cfg); 01045 01046 return 0; 01047 }
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).
headp | pointer to list of user variables | |
zone | A time zone. NULL sets variables based on timezone of the machine |
Definition at line 346 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().
00347 { 00348 time_t utc_time; 00349 int dstenable; 00350 time_t dststart; 00351 time_t dstend; 00352 struct ast_tm tm_info; 00353 int tzoffset; 00354 char buffer[21]; 00355 struct ast_var_t *var; 00356 struct timeval when; 00357 00358 time(&utc_time); 00359 ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone); 00360 snprintf(buffer, sizeof(buffer), "%d", tzoffset); 00361 var = ast_var_assign("TZOFFSET", buffer); 00362 if (var) 00363 AST_LIST_INSERT_TAIL(headp, var, entries); 00364 00365 if (!dstenable) 00366 return; 00367 00368 if ((var = ast_var_assign("DST_ENABLE", "1"))) 00369 AST_LIST_INSERT_TAIL(headp, var, entries); 00370 00371 when.tv_sec = dststart; 00372 ast_localtime(&when, &tm_info, zone); 00373 00374 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1); 00375 if ((var = ast_var_assign("DST_START_MONTH", buffer))) 00376 AST_LIST_INSERT_TAIL(headp, var, entries); 00377 00378 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00379 if ((var = ast_var_assign("DST_START_MDAY", buffer))) 00380 AST_LIST_INSERT_TAIL(headp, var, entries); 00381 00382 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00383 if ((var = ast_var_assign("DST_START_HOUR", buffer))) 00384 AST_LIST_INSERT_TAIL(headp, var, entries); 00385 00386 when.tv_sec = dstend; 00387 ast_localtime(&when, &tm_info, zone); 00388 00389 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1); 00390 if ((var = ast_var_assign("DST_END_MONTH", buffer))) 00391 AST_LIST_INSERT_TAIL(headp, var, entries); 00392 00393 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00394 if ((var = ast_var_assign("DST_END_MDAY", buffer))) 00395 AST_LIST_INSERT_TAIL(headp, var, entries); 00396 00397 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00398 if ((var = ast_var_assign("DST_END_HOUR", buffer))) 00399 AST_LIST_INSERT_TAIL(headp, var, entries); 00400 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1290 of file res_phoneprov.c.
References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_http_uri_unlink(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_var_delete(), delete_profiles(), delete_routes(), delete_users(), ast_var_t::entries, global_variables, globals_lock, http_routes, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profiles, users, and var.
01291 { 01292 struct ast_var_t *var; 01293 01294 ast_http_uri_unlink(&phoneprovuri); 01295 ast_custom_function_unregister(&pp_each_user_function); 01296 ast_custom_function_unregister(&pp_each_extension_function); 01297 ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01298 01299 delete_routes(); 01300 delete_users(); 01301 delete_profiles(); 01302 ao2_ref(profiles, -1); 01303 ao2_ref(http_routes, -1); 01304 ao2_ref(users, -1); 01305 01306 ast_mutex_lock(&globals_lock); 01307 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01308 ast_var_delete(var); 01309 } 01310 ast_mutex_unlock(&globals_lock); 01311 01312 ast_mutex_destroy(&globals_lock); 01313 01314 return 0; 01315 }
static struct phone_profile* unref_profile | ( | struct phone_profile * | prof | ) | [static] |
Definition at line 228 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_profile(), build_user(), delete_profiles(), and user_destructor().
00229 { 00230 ao2_ref(prof, -1); 00231 00232 return NULL; 00233 }
static struct http_route* unref_route | ( | struct http_route * | route | ) | [static] |
Definition at line 284 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().
00285 { 00286 ao2_ref(route, -1); 00287 00288 return NULL; 00289 }
Definition at line 754 of file res_phoneprov.c.
Referenced by build_user(), delete_users(), pp_each_extension_helper(), and pp_each_user_helper().
static void user_destructor | ( | void * | obj | ) | [static] |
Free all memory associated with a user.
Definition at line 786 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), phoneprov_file::entry, exten, unref_profile(), and user.
00787 { 00788 struct user *user = obj; 00789 struct extension *exten; 00790 00791 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) { 00792 exten = delete_extension(exten); 00793 } 00794 00795 if (user->profile) { 00796 user->profile = unref_profile(user->profile); 00797 } 00798 00799 ast_string_field_free_memory(user); 00800 }
static int users_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 778 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and user::macaddress.
Referenced by load_module().
00779 { 00780 const struct user *user1 = obj, *user2 = arg; 00781 00782 return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0; 00783 }
static int users_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 771 of file res_phoneprov.c.
References ast_str_case_hash(), and user.
Referenced by load_module().
00772 { 00773 const struct user *user = obj; 00774 00775 return ast_str_case_hash(user->macaddress); 00776 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1340 of file res_phoneprov.c.
struct in_addr __ourip = { .s_addr = 0x00000000, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1340 of file res_phoneprov.c.
char global_default_profile[80] = "" [static] |
Default profile to use if one isn't specified
Definition at line 191 of file res_phoneprov.c.
char global_server[80] = "" [static] |
Server to substitute into templates
Definition at line 189 of file res_phoneprov.c.
char global_serverport[6] = "" [static] |
Server port to substitute into templates
Definition at line 190 of file res_phoneprov.c.
struct varshead global_variables [static] |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
Definition at line 194 of file res_phoneprov.c.
Referenced by load_module(), reload(), set_config(), and unload_module().
ast_mutex_t globals_lock [static] |
Definition at line 195 of file res_phoneprov.c.
struct ao2_container* http_routes [static] |
Definition at line 186 of file res_phoneprov.c.
Referenced by build_route(), delete_routes(), handle_show_routes(), load_module(), phoneprov_callback(), and unload_module().
struct ast_http_uri phoneprovuri [static] |
struct ast_cli_entry pp_cli[] [static] |
Initial value:
{ { .handler = handle_show_routes , .summary = "Show registered phoneprov http routes" ,__VA_ARGS__ }, }
Definition at line 1256 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function pp_each_extension_function [static] |
Initial value:
{ .name = "PP_EACH_EXTENSION", .read = pp_each_extension_read, .read2 = pp_each_extension_read2, }
Definition at line 1206 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function pp_each_user_function [static] |
Initial value:
{ .name = "PP_EACH_USER", .read = pp_each_user_read, .read2 = pp_each_user_read2, }
Definition at line 1128 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
struct pp_variable_lookup pp_variable_list[] [static] |
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 185 of file res_phoneprov.c.
Referenced by delete_profiles(), find_profile(), load_module(), and unload_module().
struct ao2_container* users [static] |
Definition at line 187 of file res_phoneprov.c.