#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_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 * | ftype2mtype (const char *ftype) |
Return mime type based on extension. | |
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 struct ast_str * | 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 *vars, struct ast_variable *headers, int *status, char **title, int *contentlength) |
Callback that is executed everytime an http request is received by this module. | |
static int | pp_each_extension_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
A dialplan function that can be used to output a template for each extension attached to a user. | |
static int | pp_each_user_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
A dialplan function that can be used to print a string for each phoneprov user. | |
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_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 |
struct { | |
char * ext | |
char * mtype | |
} | mimetypes [] |
Extensions whose mime types we think we know. | |
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 67 of file res_phoneprov.c.
#define VAR_BUF_SIZE 4096 |
Definition at line 70 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_VAR_LIST_LENGTH |
Definition at line 77 of file res_phoneprov.c.
00077 { 00078 PP_MACADDRESS, 00079 PP_USERNAME, 00080 PP_FULLNAME, 00081 PP_SECRET, 00082 PP_LABEL, 00083 PP_CALLERID, 00084 PP_TIMEZONE, 00085 PP_LINENUMBER, 00086 PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */ 00087 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 1320 of file res_phoneprov.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1320 of file res_phoneprov.c.
Add an extension to a user ordered by index/linenumber.
Definition at line 859 of file res_phoneprov.c.
References 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_var_assign(), ast_var_t::entries, phoneprov_file::entry, exten, extension::index, LOG_WARNING, pbx_substitute_variables_varshead(), user, var, and VAR_BUF_SIZE.
00860 { 00861 struct ast_var_t *var; 00862 00863 /* Append profile variables here, and substitute variables on profile 00864 * setvars, so that we can use user specific variables in them */ 00865 AST_LIST_TRAVERSE(user->profile->headp, var, entries) { 00866 char expand_buf[VAR_BUF_SIZE] = {0,}; 00867 struct ast_var_t *var2; 00868 00869 pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf)); 00870 if ((var2 = ast_var_assign(var->name, expand_buf))) 00871 AST_LIST_INSERT_TAIL(exten->headp, var2, entries); 00872 } 00873 00874 if (AST_LIST_EMPTY(&user->extensions)) { 00875 AST_LIST_INSERT_HEAD(&user->extensions, exten, entry); 00876 } else { 00877 struct extension *exten_iter; 00878 00879 AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) { 00880 if (exten->index < exten_iter->index) { 00881 AST_LIST_INSERT_BEFORE_CURRENT(exten, entry); 00882 } else if (exten->index == exten_iter->index) { 00883 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress); 00884 return -1; 00885 } else if (!AST_LIST_NEXT(exten_iter, entry)) { 00886 AST_LIST_INSERT_TAIL(&user->extensions, exten, entry); 00887 } 00888 } 00889 AST_LIST_TRAVERSE_SAFE_END; 00890 } 00891 00892 return 0; 00893 }
static struct extension* build_extension | ( | struct ast_config * | cfg, | |
const char * | name | |||
) | [static] |
Definition at line 711 of file res_phoneprov.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_init, ast_string_field_set, ast_var_assign(), ast_variable_retrieve(), ast_var_t::entries, exten, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.
00712 { 00713 struct extension *exten; 00714 struct ast_var_t *var; 00715 const char *tmp; 00716 int i; 00717 00718 if (!(exten = ast_calloc(1, sizeof(*exten)))) { 00719 return NULL; 00720 } 00721 00722 if (ast_string_field_init(exten, 32)) { 00723 ast_free(exten); 00724 exten = NULL; 00725 return NULL; 00726 } 00727 00728 ast_string_field_set(exten, name, name); 00729 00730 if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) { 00731 ast_free(exten); 00732 exten = NULL; 00733 return NULL; 00734 } 00735 00736 for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { 00737 tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); 00738 00739 /* If we didn't get a USERNAME variable, set it to the user->name */ 00740 if (i == PP_USERNAME && !tmp) { 00741 if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) { 00742 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00743 } 00744 continue; 00745 } else if (i == PP_TIMEZONE) { 00746 /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ 00747 set_timezone_variables(exten->headp, tmp); 00748 } else if (i == PP_LINENUMBER) { 00749 if (!tmp) { 00750 tmp = "1"; 00751 } 00752 exten->index = atoi(tmp); 00753 } 00754 00755 if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) { 00756 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00757 } 00758 } 00759 00760 if (!ast_strlen_zero(global_server)) { 00761 if ((var = ast_var_assign("SERVER", global_server))) 00762 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00763 } 00764 00765 if (!ast_strlen_zero(global_serverport)) { 00766 if ((var = ast_var_assign("SERVER_PORT", global_serverport))) 00767 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00768 } 00769 00770 return exten; 00771 }
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 585 of file res_phoneprov.c.
References ao2_alloc, 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.
00586 { 00587 struct phone_profile *profile; 00588 struct ast_var_t *var; 00589 00590 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) { 00591 return; 00592 } 00593 00594 if (ast_string_field_init(profile, 32)) { 00595 profile = unref_profile(profile); 00596 return; 00597 } 00598 00599 if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { 00600 profile = unref_profile(profile); 00601 return; 00602 } 00603 00604 AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); 00605 AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); 00606 00607 ast_string_field_set(profile, name, name); 00608 for (; v; v = v->next) { 00609 if (!strcasecmp(v->name, "mime_type")) { 00610 ast_string_field_set(profile, default_mime_type, v->value); 00611 } else if (!strcasecmp(v->name, "setvar")) { 00612 struct ast_var_t *variable; 00613 char *value_copy = ast_strdupa(v->value); 00614 00615 AST_DECLARE_APP_ARGS(args, 00616 AST_APP_ARG(varname); 00617 AST_APP_ARG(varval); 00618 ); 00619 00620 AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); 00621 do { 00622 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00623 break; 00624 args.varname = ast_strip(args.varname); 00625 args.varval = ast_strip(args.varval); 00626 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00627 break; 00628 if ((variable = ast_var_assign(args.varname, args.varval))) 00629 AST_LIST_INSERT_TAIL(profile->headp, variable, entries); 00630 } while (0); 00631 } else if (!strcasecmp(v->name, "staticdir")) { 00632 ast_string_field_set(profile, staticdir, v->value); 00633 } else { 00634 struct phoneprov_file *pp_file; 00635 char *file_extension; 00636 char *value_copy = ast_strdupa(v->value); 00637 00638 AST_DECLARE_APP_ARGS(args, 00639 AST_APP_ARG(filename); 00640 AST_APP_ARG(mimetype); 00641 ); 00642 00643 if (!(pp_file = ast_calloc(1, sizeof(*pp_file)))) { 00644 profile = unref_profile(profile); 00645 return; 00646 } 00647 if (ast_string_field_init(pp_file, 32)) { 00648 ast_free(pp_file); 00649 profile = unref_profile(profile); 00650 return; 00651 } 00652 00653 if ((file_extension = strrchr(pp_file->format, '.'))) 00654 file_extension++; 00655 00656 AST_STANDARD_APP_ARGS(args, value_copy); 00657 00658 /* Mime type order of preference 00659 * 1) Specific mime-type defined for file in profile 00660 * 2) Mime determined by extension 00661 * 3) Default mime type specified in profile 00662 * 4) text/plain 00663 */ 00664 ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, (S_OR(S_OR(ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); 00665 00666 if (!strcasecmp(v->name, "static_file")) { 00667 ast_string_field_set(pp_file, format, args.filename); 00668 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); 00669 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); 00670 /* Add a route for the static files, as their filenames won't change per-user */ 00671 build_route(pp_file, NULL, NULL); 00672 } else { 00673 ast_string_field_set(pp_file, format, v->name); 00674 ast_string_field_set(pp_file, template, args.filename); 00675 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); 00676 } 00677 } 00678 } 00679 00680 /* Append the global variables to the variables list for this profile. 00681 * This is for convenience later, when we need to provide a single 00682 * variable list for use in substitution. */ 00683 ast_mutex_lock(&globals_lock); 00684 AST_LIST_TRAVERSE(&global_variables, var, entries) { 00685 struct ast_var_t *new_var; 00686 if ((new_var = ast_var_assign(var->name, var->value))) { 00687 AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); 00688 } 00689 } 00690 ast_mutex_unlock(&globals_lock); 00691 00692 ao2_link(profiles, profile); 00693 00694 profile = unref_profile(profile); 00695 }
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 558 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.
00559 { 00560 struct http_route *route; 00561 00562 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) { 00563 return; 00564 } 00565 00566 if (ast_string_field_init(route, 32)) { 00567 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); 00568 route = unref_route(route); 00569 return; 00570 } 00571 00572 ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); 00573 route->user = user; 00574 route->file = pp_file; 00575 00576 ao2_link(http_routes, route); 00577 00578 route = unref_route(route); 00579 }
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 836 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().
00837 { 00838 struct user *user; 00839 00840 00841 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) { 00842 profile = unref_profile(profile); 00843 return NULL; 00844 } 00845 00846 if (ast_string_field_init(user, 32)) { 00847 profile = unref_profile(profile); 00848 user = unref_user(user); 00849 return NULL; 00850 } 00851 00852 ast_string_field_set(user, macaddress, mac); 00853 user->profile = profile; /* already ref counted by find_profile */ 00854 00855 return user; 00856 }
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 896 of file res_phoneprov.c.
References AST_LIST_FIRST, AST_LIST_TRAVERSE, build_route(), phoneprov_file::entry, phoneprov_file::format, pbx_substitute_variables_varshead(), user, and VAR_BUF_SIZE.
00897 { 00898 struct phoneprov_file *pp_file; 00899 00900 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { 00901 char expand_buf[VAR_BUF_SIZE] = { 0, }; 00902 00903 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf)); 00904 build_route(pp_file, user, expand_buf); 00905 } 00906 00907 return 0; 00908 }
Definition at line 697 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().
00698 { 00699 struct ast_var_t *var; 00700 while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) { 00701 ast_var_delete(var); 00702 } 00703 ast_free(exten->headp); 00704 ast_string_field_free_memory(exten); 00705 00706 ast_free(exten); 00707 00708 return NULL; 00709 }
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 1073 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().
01074 { 01075 struct ao2_iterator i; 01076 struct phone_profile *profile; 01077 01078 i = ao2_iterator_init(profiles, 0); 01079 while ((profile = ao2_iterator_next(&i))) { 01080 ao2_unlink(profiles, profile); 01081 profile = unref_profile(profile); 01082 } 01083 ao2_iterator_destroy(&i); 01084 }
static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 1059 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().
01060 { 01061 struct ao2_iterator i; 01062 struct http_route *route; 01063 01064 i = ao2_iterator_init(http_routes, 0); 01065 while ((route = ao2_iterator_next(&i))) { 01066 ao2_unlink(http_routes, route); 01067 route = unref_route(route); 01068 } 01069 ao2_iterator_destroy(&i); 01070 }
static void delete_users | ( | void | ) | [static] |
Delete all users.
Definition at line 822 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, unref_user(), user, and users.
00823 { 00824 struct ao2_iterator i; 00825 struct user *user; 00826 00827 i = ao2_iterator_init(users, 0); 00828 while ((user = ao2_iterator_next(&i))) { 00829 ao2_unlink(users, user); 00830 user = unref_user(user); 00831 } 00832 ao2_iterator_destroy(&i); 00833 }
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 781 of file res_phoneprov.c.
References ao2_find, user::macaddress, OBJ_POINTER, and users.
00782 { 00783 struct user tmp = { 00784 .macaddress = macaddress, 00785 }; 00786 00787 return ao2_find(users, &tmp, OBJ_POINTER); 00788 }
static char* ftype2mtype | ( | const char * | ftype | ) | [static] |
Return mime type based on extension.
Definition at line 182 of file res_phoneprov.c.
References ARRAY_LEN, ast_strlen_zero(), ext, and mimetypes.
00183 { 00184 int x; 00185 00186 if (ast_strlen_zero(ftype)) 00187 return NULL; 00188 00189 for (x = 0;x < ARRAY_LEN(mimetypes);x++) { 00190 if (!strcasecmp(ftype, mimetypes[x].ext)) 00191 return mimetypes[x].mtype; 00192 } 00193 00194 return NULL; 00195 }
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 1192 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.
01193 { 01194 #define FORMAT "%-40.40s %-30.30s\n" 01195 struct ao2_iterator i; 01196 struct http_route *route; 01197 01198 switch(cmd) { 01199 case CLI_INIT: 01200 e->command = "phoneprov show routes"; 01201 e->usage = 01202 "Usage: phoneprov show routes\n" 01203 " Lists all registered phoneprov http routes.\n"; 01204 return NULL; 01205 case CLI_GENERATE: 01206 return NULL; 01207 } 01208 01209 /* This currently iterates over routes twice, but it is the only place I've needed 01210 * to really separate static an dynamic routes, so I've just left it this way. */ 01211 ast_cli(a->fd, "Static routes\n\n"); 01212 ast_cli(a->fd, FORMAT, "Relative URI", "Physical location"); 01213 i = ao2_iterator_init(http_routes, 0); 01214 while ((route = ao2_iterator_next(&i))) { 01215 if (!route->user) 01216 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01217 route = unref_route(route); 01218 } 01219 ao2_iterator_destroy(&i); 01220 01221 ast_cli(a->fd, "\nDynamic routes\n\n"); 01222 ast_cli(a->fd, FORMAT, "Relative URI", "Template"); 01223 01224 i = ao2_iterator_init(http_routes, 0); 01225 while ((route = ao2_iterator_next(&i))) { 01226 if (route->user) 01227 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01228 route = unref_route(route); 01229 } 01230 ao2_iterator_destroy(&i); 01231 01232 return CLI_SUCCESS; 01233 }
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_exec().
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 1249 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, 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().
01250 { 01251 profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn); 01252 01253 http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn); 01254 01255 users = ao2_container_alloc(MAX_USER_BUCKETS, users_hash_fn, users_cmp_fn); 01256 01257 AST_LIST_HEAD_INIT_NOLOCK(&global_variables); 01258 ast_mutex_init(&globals_lock); 01259 01260 ast_custom_function_register(&pp_each_user_function); 01261 ast_custom_function_register(&pp_each_extension_function); 01262 ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01263 01264 set_config(); 01265 ast_http_uri_link(&phoneprovuri); 01266 01267 return 0; 01268 }
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 struct ast_str* 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 * | vars, | |||
struct ast_variable * | headers, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [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_calloc, ast_config_AST_DATA_DIR, ast_debug, ast_free, ast_get_version(), ast_http_error(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_localtime(), ast_log(), ast_str_append(), ast_str_create(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), ast_var_assign(), buf, phoneprov_file::entry, errno, user::extensions, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, http_route::file, fwrite, extension::headp, http_routes, len(), load_file(), LOG_WARNING, phoneprov_file::mime_type, name, OBJ_POINTER, pbx_substitute_variables_varshead(), strdup, phoneprov_file::template, unref_route(), http_route::uri, http_route::user, var, and VAR_BUF_SIZE.
00404 { 00405 struct http_route *route; 00406 struct http_route search_route = { 00407 .uri = uri, 00408 }; 00409 struct ast_str *result = ast_str_create(512); 00410 char path[PATH_MAX]; 00411 char *file = NULL; 00412 int len; 00413 int fd; 00414 char buf[256]; 00415 struct timeval now = ast_tvnow(); 00416 struct ast_tm tm; 00417 00418 if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) { 00419 goto out404; 00420 } 00421 00422 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template); 00423 00424 if (!route->user) { /* Static file */ 00425 00426 fd = open(path, O_RDONLY); 00427 if (fd < 0) { 00428 goto out500; 00429 } 00430 00431 len = lseek(fd, 0, SEEK_END); 00432 lseek(fd, 0, SEEK_SET); 00433 if (len < 0) { 00434 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00435 close(fd); 00436 goto out500; 00437 } 00438 00439 ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT")); 00440 fprintf(ser->f, "HTTP/1.1 200 OK\r\n" 00441 "Server: Asterisk/%s\r\n" 00442 "Date: %s\r\n" 00443 "Connection: close\r\n" 00444 "Cache-Control: no-cache, no-store\r\n" 00445 "Content-Length: %d\r\n" 00446 "Content-Type: %s\r\n\r\n", 00447 ast_get_version(), buf, len, route->file->mime_type); 00448 00449 while ((len = read(fd, buf, sizeof(buf))) > 0) { 00450 if (fwrite(buf, 1, len, ser->f) != len) { 00451 if (errno != EPIPE) { 00452 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00453 } else { 00454 ast_debug(3, "Requester closed the connection while downloading '%s'\n", path); 00455 } 00456 break; 00457 } 00458 } 00459 00460 close(fd); 00461 route = unref_route(route); 00462 return NULL; 00463 } else { /* Dynamic file */ 00464 int bufsize; 00465 char *tmp; 00466 00467 len = load_file(path, &file); 00468 if (len < 0) { 00469 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00470 if (file) { 00471 ast_free(file); 00472 } 00473 00474 goto out500; 00475 } 00476 00477 if (!file) { 00478 goto out500; 00479 } 00480 00481 /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */ 00482 bufsize = len + VAR_BUF_SIZE; 00483 00484 /* malloc() instead of alloca() here, just in case the file is bigger than 00485 * we have enough stack space for. */ 00486 if (!(tmp = ast_calloc(1, bufsize))) { 00487 if (file) { 00488 ast_free(file); 00489 } 00490 00491 goto out500; 00492 } 00493 00494 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to 00495 * the IP address we are listening on that the phone contacted for this config file */ 00496 if (ast_strlen_zero(global_server)) { 00497 union { 00498 struct sockaddr sa; 00499 struct sockaddr_in sa_in; 00500 } name; 00501 socklen_t namelen = sizeof(name.sa); 00502 int res; 00503 00504 if ((res = getsockname(ser->fd, &name.sa, &namelen))) { 00505 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); 00506 } else { 00507 struct ast_var_t *var; 00508 struct extension *exten_iter; 00509 00510 if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) { 00511 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) { 00512 AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries); 00513 } 00514 } 00515 } 00516 } 00517 00518 pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize); 00519 00520 if (file) { 00521 ast_free(file); 00522 } 00523 00524 ast_str_append(&result, 0, 00525 "Content-Type: %s\r\n" 00526 "Content-length: %d\r\n" 00527 "\r\n" 00528 "%s", route->file->mime_type, (int) strlen(tmp), tmp); 00529 00530 if (tmp) { 00531 ast_free(tmp); 00532 } 00533 00534 route = unref_route(route); 00535 00536 return result; 00537 } 00538 00539 out404: 00540 *status = 404; 00541 *title = strdup("Not Found"); 00542 *contentlength = 0; 00543 return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); 00544 00545 out500: 00546 route = unref_route(route); 00547 *status = 500; 00548 *title = strdup("Internal Server Error"); 00549 *contentlength = 0; 00550 return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); 00551 }
static int pp_each_extension_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
A dialplan function that can be used to output a template for each extension attached to a user.
Definition at line 1130 of file res_phoneprov.c.
References 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_strlen_zero(), extension::entry, exten, find_user(), load_file(), LOG_WARNING, pbx_substitute_variables_varshead(), unref_user(), user, and VAR_BUF_SIZE.
01131 { 01132 struct user *user; 01133 struct extension *exten; 01134 char path[PATH_MAX]; 01135 char *file; 01136 int filelen; 01137 AST_DECLARE_APP_ARGS(args, 01138 AST_APP_ARG(mac); 01139 AST_APP_ARG(template); 01140 ); 01141 01142 AST_STANDARD_APP_ARGS(args, data); 01143 01144 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) { 01145 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n"); 01146 return 0; 01147 } 01148 01149 if (!(user = find_user(args.mac))) { 01150 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac); 01151 return 0; 01152 } 01153 01154 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template); 01155 filelen = load_file(path, &file); 01156 if (filelen < 0) { 01157 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen); 01158 if (file) { 01159 ast_free(file); 01160 } 01161 return 0; 01162 } 01163 01164 if (!file) { 01165 return 0; 01166 } 01167 01168 AST_LIST_TRAVERSE(&user->extensions, exten, entry) { 01169 char expand_buf[VAR_BUF_SIZE] = {0,}; 01170 pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf)); 01171 ast_build_string(&buf, &len, "%s", expand_buf); 01172 } 01173 01174 ast_free(file); 01175 01176 user = unref_user(user); 01177 01178 return 0; 01179 }
static int pp_each_user_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
A dialplan function that can be used to print a string for each phoneprov user.
Definition at line 1087 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, AST_LIST_FIRST, AST_STANDARD_APP_ARGS, ast_strlen_zero(), pbx_substitute_variables_varshead(), unref_user(), user, users, and VAR_BUF_SIZE.
01088 { 01089 char *tmp, expand_buf[VAR_BUF_SIZE] = {0,}; 01090 struct ao2_iterator i; 01091 struct user *user; 01092 AST_DECLARE_APP_ARGS(args, 01093 AST_APP_ARG(string); 01094 AST_APP_ARG(exclude_mac); 01095 ); 01096 AST_STANDARD_APP_ARGS(args, data); 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 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf)); 01108 ast_build_string(&buf, &len, "%s", expand_buf); 01109 user = unref_user(user); 01110 } 01111 ao2_iterator_destroy(&i); 01112 01113 return 0; 01114 }
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_hash(), and phone_profile::name.
Referenced by load_module().
00246 { 00247 const struct phone_profile *profile = obj; 00248 00249 return ast_str_hash(profile->name); 00250 }
static int reload | ( | void | ) | [static] |
Definition at line 1297 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, set_config(), and var.
01298 { 01299 struct ast_var_t *var; 01300 01301 delete_routes(); 01302 delete_users(); 01303 delete_profiles(); 01304 01305 ast_mutex_lock(&globals_lock); 01306 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01307 ast_var_delete(var); 01308 } 01309 ast_mutex_unlock(&globals_lock); 01310 01311 set_config(); 01312 01313 return 0; 01314 }
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 !strcmp(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_hash(), and http_route::uri.
Referenced by load_module().
00292 { 00293 const struct http_route *route = obj; 00294 00295 return ast_str_hash(route->uri); 00296 }
static int set_config | ( | void | ) | [static] |
Definition at line 911 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, ast_var_t::entries, global_variables, LOG_WARNING, ast_variable::name, ast_variable::next, S_OR, ast_variable::value, and var.
00912 { 00913 struct ast_config *cfg, *phoneprov_cfg; 00914 char *cat; 00915 struct ast_variable *v; 00916 struct ast_flags config_flags = { 0 }; 00917 struct ast_var_t *var; 00918 00919 /* Try to grab the port from sip.conf. If we don't get it here, we'll set it 00920 * to whatever is set in phoneprov.conf or default to 5060 */ 00921 if ((cfg = ast_config_load("sip.conf", config_flags))) { 00922 ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); 00923 ast_config_destroy(cfg); 00924 } 00925 00926 if (!(cfg = ast_config_load("users.conf", config_flags))) { 00927 ast_log(LOG_WARNING, "Unable to load users.conf\n"); 00928 return 0; 00929 } 00930 00931 /* Go ahead and load global variables from users.conf so we can append to profiles */ 00932 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00933 if (!strcasecmp(v->name, "vmexten")) { 00934 if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) { 00935 ast_mutex_lock(&globals_lock); 00936 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00937 ast_mutex_unlock(&globals_lock); 00938 } 00939 } 00940 if (!strcasecmp(v->name, "localextenlength")) { 00941 if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) 00942 ast_mutex_lock(&globals_lock); 00943 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00944 ast_mutex_unlock(&globals_lock); 00945 } 00946 } 00947 00948 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))) { 00949 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); 00950 ast_config_destroy(cfg); 00951 return -1; 00952 } 00953 00954 cat = NULL; 00955 while ((cat = ast_category_browse(phoneprov_cfg, cat))) { 00956 if (!strcasecmp(cat, "general")) { 00957 for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) { 00958 if (!strcasecmp(v->name, "serveraddr")) 00959 ast_copy_string(global_server, v->value, sizeof(global_server)); 00960 else if (!strcasecmp(v->name, "serveriface")) { 00961 struct in_addr addr; 00962 lookup_iface(v->value, &addr); 00963 ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); 00964 } else if (!strcasecmp(v->name, "serverport")) 00965 ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); 00966 else if (!strcasecmp(v->name, "default_profile")) 00967 ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); 00968 } 00969 } else 00970 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat)); 00971 } 00972 00973 ast_config_destroy(phoneprov_cfg); 00974 00975 cat = NULL; 00976 while ((cat = ast_category_browse(cfg, cat))) { 00977 const char *tmp, *mac; 00978 struct user *user; 00979 struct phone_profile *profile; 00980 struct extension *exten; 00981 00982 if (!strcasecmp(cat, "general")) { 00983 continue; 00984 } 00985 00986 if (!strcasecmp(cat, "authentication")) 00987 continue; 00988 00989 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) 00990 continue; 00991 00992 if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { 00993 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); 00994 continue; 00995 } 00996 00997 tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); 00998 if (ast_strlen_zero(tmp)) { 00999 ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); 01000 continue; 01001 } 01002 01003 if (!(user = find_user(mac))) { 01004 if (!(profile = find_profile(tmp))) { 01005 ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); 01006 continue; 01007 } 01008 01009 if (!(user = build_user(mac, profile))) { 01010 ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress); 01011 continue; 01012 } 01013 01014 if (!(exten = build_extension(cfg, cat))) { 01015 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01016 user = unref_user(user); 01017 continue; 01018 } 01019 01020 if (add_user_extension(user, exten)) { 01021 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01022 user = unref_user(user); 01023 exten = delete_extension(exten); 01024 continue; 01025 } 01026 01027 if (build_user_routes(user)) { 01028 ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress); 01029 user = unref_user(user); 01030 continue; 01031 } 01032 01033 ao2_link(users, user); 01034 user = unref_user(user); 01035 } else { 01036 if (!(exten = build_extension(cfg, cat))) { 01037 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01038 user = unref_user(user); 01039 continue; 01040 } 01041 01042 if (add_user_extension(user, exten)) { 01043 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01044 user = unref_user(user); 01045 exten = delete_extension(exten); 01046 continue; 01047 } 01048 01049 user = unref_user(user); 01050 } 01051 } 01052 01053 ast_config_destroy(cfg); 01054 01055 return 0; 01056 }
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 1270 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, http_routes, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profiles, users, and var.
01271 { 01272 struct ast_var_t *var; 01273 01274 ast_http_uri_unlink(&phoneprovuri); 01275 ast_custom_function_unregister(&pp_each_user_function); 01276 ast_custom_function_unregister(&pp_each_extension_function); 01277 ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01278 01279 delete_routes(); 01280 delete_users(); 01281 delete_profiles(); 01282 ao2_ref(profiles, -1); 01283 ao2_ref(http_routes, -1); 01284 ao2_ref(users, -1); 01285 01286 ast_mutex_lock(&globals_lock); 01287 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01288 ast_var_delete(var); 01289 } 01290 ast_mutex_unlock(&globals_lock); 01291 01292 ast_mutex_destroy(&globals_lock); 01293 01294 return 0; 01295 }
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 773 of file res_phoneprov.c.
Referenced by build_user(), delete_users(), pp_each_extension_exec(), and pp_each_user_exec().
static void user_destructor | ( | void * | obj | ) | [static] |
Free all memory associated with a user.
Definition at line 805 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.
00806 { 00807 struct user *user = obj; 00808 struct extension *exten; 00809 00810 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) { 00811 exten = delete_extension(exten); 00812 } 00813 00814 if (user->profile) { 00815 user->profile = unref_profile(user->profile); 00816 } 00817 00818 ast_string_field_free_memory(user); 00819 }
static int users_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 797 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and user::macaddress.
Referenced by load_module().
00798 { 00799 const struct user *user1 = obj, *user2 = arg; 00800 00801 return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0; 00802 }
static int users_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 790 of file res_phoneprov.c.
References ast_str_hash(), and user.
Referenced by load_module().
00791 { 00792 const struct user *user = obj; 00793 00794 return ast_str_hash(user->macaddress); 00795 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1320 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 1320 of file res_phoneprov.c.
char* ext |
Definition at line 162 of file res_phoneprov.c.
char global_default_profile[80] = "" [static] |
Default profile to use if one isn't specified
Definition at line 175 of file res_phoneprov.c.
char global_server[80] = "" [static] |
Server to substitute into templates
Definition at line 173 of file res_phoneprov.c.
char global_serverport[6] = "" [static] |
Server port to substitute into templates
Definition at line 174 of file res_phoneprov.c.
struct varshead global_variables [static] |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
Definition at line 178 of file res_phoneprov.c.
Referenced by load_module(), reload(), set_config(), and unload_module().
ast_mutex_t globals_lock [static] |
Definition at line 179 of file res_phoneprov.c.
struct ao2_container* http_routes [static] |
Definition at line 157 of file res_phoneprov.c.
Referenced by build_route(), delete_routes(), handle_show_routes(), load_module(), phoneprov_callback(), and unload_module().
struct { ... } mimetypes[] [static] |
Extensions whose mime types we think we know.
char* mtype |
Definition at line 163 of file res_phoneprov.c.
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 1235 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
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[] [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 156 of file res_phoneprov.c.
Referenced by delete_profiles(), find_profile(), load_module(), and unload_module().
struct ao2_container* users [static] |
Definition at line 158 of file res_phoneprov.c.