#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 1311 of file res_phoneprov.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1311 of file res_phoneprov.c.
Add an extension to a user ordered by index/linenumber.
Definition at line 855 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.
00856 { 00857 struct ast_var_t *var; 00858 00859 /* Append profile variables here, and substitute variables on profile 00860 * setvars, so that we can use user specific variables in them */ 00861 AST_LIST_TRAVERSE(user->profile->headp, var, entries) { 00862 char expand_buf[VAR_BUF_SIZE] = {0,}; 00863 struct ast_var_t *var2; 00864 00865 pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf)); 00866 if ((var2 = ast_var_assign(var->name, expand_buf))) 00867 AST_LIST_INSERT_TAIL(exten->headp, var2, entries); 00868 } 00869 00870 if (AST_LIST_EMPTY(&user->extensions)) { 00871 AST_LIST_INSERT_HEAD(&user->extensions, exten, entry); 00872 } else { 00873 struct extension *exten_iter; 00874 00875 AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) { 00876 if (exten->index < exten_iter->index) { 00877 AST_LIST_INSERT_BEFORE_CURRENT(exten, entry); 00878 } else if (exten->index == exten_iter->index) { 00879 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress); 00880 return -1; 00881 } else if (!AST_LIST_NEXT(exten_iter, entry)) { 00882 AST_LIST_INSERT_TAIL(&user->extensions, exten, entry); 00883 } 00884 } 00885 AST_LIST_TRAVERSE_SAFE_END; 00886 } 00887 00888 return 0; 00889 }
static struct extension* build_extension | ( | struct ast_config * | cfg, | |
const char * | name | |||
) | [static] |
Definition at line 708 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.
00709 { 00710 struct extension *exten; 00711 struct ast_var_t *var; 00712 const char *tmp; 00713 int i; 00714 00715 if (!(exten = ast_calloc(1, sizeof(*exten)))) { 00716 return NULL; 00717 } 00718 00719 if (ast_string_field_init(exten, 32)) { 00720 ast_free(exten); 00721 exten = NULL; 00722 return NULL; 00723 } 00724 00725 ast_string_field_set(exten, name, name); 00726 00727 if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) { 00728 ast_free(exten); 00729 exten = NULL; 00730 return NULL; 00731 } 00732 00733 for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { 00734 tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); 00735 00736 /* If we didn't get a USERNAME variable, set it to the user->name */ 00737 if (i == PP_USERNAME && !tmp) { 00738 if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) { 00739 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00740 } 00741 continue; 00742 } else if (i == PP_TIMEZONE) { 00743 /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ 00744 set_timezone_variables(exten->headp, tmp); 00745 } else if (i == PP_LINENUMBER) { 00746 if (!tmp) { 00747 tmp = "1"; 00748 } 00749 exten->index = atoi(tmp); 00750 } 00751 00752 if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) { 00753 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00754 } 00755 } 00756 00757 if (!ast_strlen_zero(global_server)) { 00758 if ((var = ast_var_assign("SERVER", global_server))) 00759 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00760 } 00761 00762 if (!ast_strlen_zero(global_serverport)) { 00763 if ((var = ast_var_assign("SERVER_PORT", global_serverport))) 00764 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00765 } 00766 00767 return exten; 00768 }
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 582 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.
00583 { 00584 struct phone_profile *profile; 00585 struct ast_var_t *var; 00586 00587 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) { 00588 return; 00589 } 00590 00591 if (ast_string_field_init(profile, 32)) { 00592 profile = unref_profile(profile); 00593 return; 00594 } 00595 00596 if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { 00597 profile = unref_profile(profile); 00598 return; 00599 } 00600 00601 AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); 00602 AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); 00603 00604 ast_string_field_set(profile, name, name); 00605 for (; v; v = v->next) { 00606 if (!strcasecmp(v->name, "mime_type")) { 00607 ast_string_field_set(profile, default_mime_type, v->value); 00608 } else if (!strcasecmp(v->name, "setvar")) { 00609 struct ast_var_t *variable; 00610 char *value_copy = ast_strdupa(v->value); 00611 00612 AST_DECLARE_APP_ARGS(args, 00613 AST_APP_ARG(varname); 00614 AST_APP_ARG(varval); 00615 ); 00616 00617 AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); 00618 do { 00619 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00620 break; 00621 args.varname = ast_strip(args.varname); 00622 args.varval = ast_strip(args.varval); 00623 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00624 break; 00625 if ((variable = ast_var_assign(args.varname, args.varval))) 00626 AST_LIST_INSERT_TAIL(profile->headp, variable, entries); 00627 } while (0); 00628 } else if (!strcasecmp(v->name, "staticdir")) { 00629 ast_string_field_set(profile, staticdir, v->value); 00630 } else { 00631 struct phoneprov_file *pp_file; 00632 char *file_extension; 00633 char *value_copy = ast_strdupa(v->value); 00634 00635 AST_DECLARE_APP_ARGS(args, 00636 AST_APP_ARG(filename); 00637 AST_APP_ARG(mimetype); 00638 ); 00639 00640 if (!(pp_file = ast_calloc(1, sizeof(*pp_file)))) { 00641 profile = unref_profile(profile); 00642 return; 00643 } 00644 if (ast_string_field_init(pp_file, 32)) { 00645 ast_free(pp_file); 00646 profile = unref_profile(profile); 00647 return; 00648 } 00649 00650 if ((file_extension = strrchr(pp_file->format, '.'))) 00651 file_extension++; 00652 00653 AST_STANDARD_APP_ARGS(args, value_copy); 00654 00655 /* Mime type order of preference 00656 * 1) Specific mime-type defined for file in profile 00657 * 2) Mime determined by extension 00658 * 3) Default mime type specified in profile 00659 * 4) text/plain 00660 */ 00661 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")))); 00662 00663 if (!strcasecmp(v->name, "static_file")) { 00664 ast_string_field_set(pp_file, format, args.filename); 00665 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); 00666 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); 00667 /* Add a route for the static files, as their filenames won't change per-user */ 00668 build_route(pp_file, NULL, NULL); 00669 } else { 00670 ast_string_field_set(pp_file, format, v->name); 00671 ast_string_field_set(pp_file, template, args.filename); 00672 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); 00673 } 00674 } 00675 } 00676 00677 /* Append the global variables to the variables list for this profile. 00678 * This is for convenience later, when we need to provide a single 00679 * variable list for use in substitution. */ 00680 ast_mutex_lock(&globals_lock); 00681 AST_LIST_TRAVERSE(&global_variables, var, entries) { 00682 struct ast_var_t *new_var; 00683 if ((new_var = ast_var_assign(var->name, var->value))) { 00684 AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); 00685 } 00686 } 00687 ast_mutex_unlock(&globals_lock); 00688 00689 ao2_link(profiles, profile); 00690 00691 profile = unref_profile(profile); 00692 }
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 555 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.
00556 { 00557 struct http_route *route; 00558 00559 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) { 00560 return; 00561 } 00562 00563 if (ast_string_field_init(route, 32)) { 00564 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); 00565 route = unref_route(route); 00566 return; 00567 } 00568 00569 ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); 00570 route->user = user; 00571 route->file = pp_file; 00572 00573 ao2_link(http_routes, route); 00574 00575 route = unref_route(route); 00576 }
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 832 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().
00833 { 00834 struct user *user; 00835 00836 00837 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) { 00838 profile = unref_profile(profile); 00839 return NULL; 00840 } 00841 00842 if (ast_string_field_init(user, 32)) { 00843 profile = unref_profile(profile); 00844 user = unref_user(user); 00845 return NULL; 00846 } 00847 00848 ast_string_field_set(user, macaddress, mac); 00849 user->profile = profile; /* already ref counted by find_profile */ 00850 00851 return user; 00852 }
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 892 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.
00893 { 00894 struct phoneprov_file *pp_file; 00895 00896 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { 00897 char expand_buf[VAR_BUF_SIZE] = { 0, }; 00898 00899 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf)); 00900 build_route(pp_file, user, expand_buf); 00901 } 00902 00903 return 0; 00904 }
Definition at line 694 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().
00695 { 00696 struct ast_var_t *var; 00697 while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) { 00698 ast_var_delete(var); 00699 } 00700 ast_free(exten->headp); 00701 ast_string_field_free_memory(exten); 00702 00703 ast_free(exten); 00704 00705 return NULL; 00706 }
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 1068 of file res_phoneprov.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_unlink, profiles, and unref_profile().
Referenced by reload(), and unload_module().
01069 { 01070 struct ao2_iterator i; 01071 struct phone_profile *profile; 01072 01073 i = ao2_iterator_init(profiles, 0); 01074 while ((profile = ao2_iterator_next(&i))) { 01075 ao2_unlink(profiles, profile); 01076 profile = unref_profile(profile); 01077 } 01078 }
static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 1055 of file res_phoneprov.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_unlink, http_routes, and unref_route().
Referenced by reload(), and unload_module().
01056 { 01057 struct ao2_iterator i; 01058 struct http_route *route; 01059 01060 i = ao2_iterator_init(http_routes, 0); 01061 while ((route = ao2_iterator_next(&i))) { 01062 ao2_unlink(http_routes, route); 01063 route = unref_route(route); 01064 } 01065 }
static void delete_users | ( | void | ) | [static] |
Delete all users.
Definition at line 819 of file res_phoneprov.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_unlink, unref_user(), user, and users.
00820 { 00821 struct ao2_iterator i; 00822 struct user *user; 00823 00824 i = ao2_iterator_init(users, 0); 00825 while ((user = ao2_iterator_next(&i))) { 00826 ao2_unlink(users, user); 00827 user = unref_user(user); 00828 } 00829 }
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 778 of file res_phoneprov.c.
References ao2_find, user::macaddress, OBJ_POINTER, and users.
00779 { 00780 struct user tmp = { 00781 .macaddress = macaddress, 00782 }; 00783 00784 return ao2_find(users, &tmp, OBJ_POINTER); 00785 }
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 1185 of file res_phoneprov.c.
References 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.
01186 { 01187 #define FORMAT "%-40.40s %-30.30s\n" 01188 struct ao2_iterator i; 01189 struct http_route *route; 01190 01191 switch(cmd) { 01192 case CLI_INIT: 01193 e->command = "phoneprov show routes"; 01194 e->usage = 01195 "Usage: phoneprov show routes\n" 01196 " Lists all registered phoneprov http routes.\n"; 01197 return NULL; 01198 case CLI_GENERATE: 01199 return NULL; 01200 } 01201 01202 /* This currently iterates over routes twice, but it is the only place I've needed 01203 * to really separate static an dynamic routes, so I've just left it this way. */ 01204 ast_cli(a->fd, "Static routes\n\n"); 01205 ast_cli(a->fd, FORMAT, "Relative URI", "Physical location"); 01206 i = ao2_iterator_init(http_routes, 0); 01207 while ((route = ao2_iterator_next(&i))) { 01208 if (!route->user) 01209 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01210 route = unref_route(route); 01211 } 01212 01213 ast_cli(a->fd, "\nDynamic routes\n\n"); 01214 ast_cli(a->fd, FORMAT, "Relative URI", "Template"); 01215 01216 i = ao2_iterator_init(http_routes, 0); 01217 while ((route = ao2_iterator_next(&i))) { 01218 if (route->user) 01219 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01220 route = unref_route(route); 01221 } 01222 01223 return CLI_SUCCESS; 01224 }
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 1240 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().
01241 { 01242 profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn); 01243 01244 http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn); 01245 01246 users = ao2_container_alloc(MAX_USER_BUCKETS, users_hash_fn, users_cmp_fn); 01247 01248 AST_LIST_HEAD_INIT_NOLOCK(&global_variables); 01249 ast_mutex_init(&globals_lock); 01250 01251 ast_custom_function_register(&pp_each_user_function); 01252 ast_custom_function_register(&pp_each_extension_function); 01253 ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01254 01255 set_config(); 01256 ast_http_uri_link(&phoneprovuri); 01257 01258 return 0; 01259 }
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, extension::headp, http_routes, len(), load_file(), LOG_WARNING, phoneprov_file::mime_type, 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 struct sockaddr name; 00498 socklen_t namelen = sizeof(name); 00499 int res; 00500 00501 if ((res = getsockname(ser->fd, &name, &namelen))) { 00502 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); 00503 } else { 00504 struct ast_var_t *var; 00505 struct extension *exten_iter; 00506 00507 if ((var = ast_var_assign("SERVER", ast_inet_ntoa(((struct sockaddr_in *)&name)->sin_addr)))) { 00508 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) { 00509 AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries); 00510 } 00511 } 00512 } 00513 } 00514 00515 pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize); 00516 00517 if (file) { 00518 ast_free(file); 00519 } 00520 00521 ast_str_append(&result, 0, 00522 "Content-Type: %s\r\n" 00523 "Content-length: %d\r\n" 00524 "\r\n" 00525 "%s", route->file->mime_type, (int) strlen(tmp), tmp); 00526 00527 if (tmp) { 00528 ast_free(tmp); 00529 } 00530 00531 route = unref_route(route); 00532 00533 return result; 00534 } 00535 00536 out404: 00537 *status = 404; 00538 *title = strdup("Not Found"); 00539 *contentlength = 0; 00540 return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); 00541 00542 out500: 00543 route = unref_route(route); 00544 *status = 500; 00545 *title = strdup("Internal Server Error"); 00546 *contentlength = 0; 00547 return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); 00548 }
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 1123 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.
01124 { 01125 struct user *user; 01126 struct extension *exten; 01127 char path[PATH_MAX]; 01128 char *file; 01129 int filelen; 01130 AST_DECLARE_APP_ARGS(args, 01131 AST_APP_ARG(mac); 01132 AST_APP_ARG(template); 01133 ); 01134 01135 AST_STANDARD_APP_ARGS(args, data); 01136 01137 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) { 01138 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n"); 01139 return 0; 01140 } 01141 01142 if (!(user = find_user(args.mac))) { 01143 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac); 01144 return 0; 01145 } 01146 01147 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template); 01148 filelen = load_file(path, &file); 01149 if (filelen < 0) { 01150 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen); 01151 if (file) { 01152 ast_free(file); 01153 } 01154 return 0; 01155 } 01156 01157 if (!file) { 01158 return 0; 01159 } 01160 01161 AST_LIST_TRAVERSE(&user->extensions, exten, entry) { 01162 char expand_buf[VAR_BUF_SIZE] = {0,}; 01163 pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf)); 01164 ast_build_string(&buf, &len, "%s", expand_buf); 01165 } 01166 01167 ast_free(file); 01168 01169 user = unref_user(user); 01170 01171 return 0; 01172 }
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 1081 of file res_phoneprov.c.
References 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.
01082 { 01083 char *tmp, expand_buf[VAR_BUF_SIZE] = {0,}; 01084 struct ao2_iterator i; 01085 struct user *user; 01086 AST_DECLARE_APP_ARGS(args, 01087 AST_APP_ARG(string); 01088 AST_APP_ARG(exclude_mac); 01089 ); 01090 AST_STANDARD_APP_ARGS(args, data); 01091 01092 /* Fix data by turning %{ into ${ */ 01093 while ((tmp = strstr(args.string, "%{"))) 01094 *tmp = '$'; 01095 01096 i = ao2_iterator_init(users, 0); 01097 while ((user = ao2_iterator_next(&i))) { 01098 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) { 01099 continue; 01100 } 01101 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf)); 01102 ast_build_string(&buf, &len, "%s", expand_buf); 01103 user = unref_user(user); 01104 } 01105 01106 return 0; 01107 }
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 1288 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.
01289 { 01290 struct ast_var_t *var; 01291 01292 delete_routes(); 01293 delete_users(); 01294 delete_profiles(); 01295 01296 ast_mutex_lock(&globals_lock); 01297 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01298 ast_var_delete(var); 01299 } 01300 ast_mutex_unlock(&globals_lock); 01301 01302 set_config(); 01303 01304 return 0; 01305 }
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 907 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.
00908 { 00909 struct ast_config *cfg, *phoneprov_cfg; 00910 char *cat; 00911 struct ast_variable *v; 00912 struct ast_flags config_flags = { 0 }; 00913 struct ast_var_t *var; 00914 00915 /* Try to grab the port from sip.conf. If we don't get it here, we'll set it 00916 * to whatever is set in phoneprov.conf or default to 5060 */ 00917 if ((cfg = ast_config_load("sip.conf", config_flags))) { 00918 ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); 00919 ast_config_destroy(cfg); 00920 } 00921 00922 if (!(cfg = ast_config_load("users.conf", config_flags))) { 00923 ast_log(LOG_WARNING, "Unable to load users.conf\n"); 00924 return 0; 00925 } 00926 00927 /* Go ahead and load global variables from users.conf so we can append to profiles */ 00928 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00929 if (!strcasecmp(v->name, "vmexten")) { 00930 if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) { 00931 ast_mutex_lock(&globals_lock); 00932 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00933 ast_mutex_unlock(&globals_lock); 00934 } 00935 } 00936 if (!strcasecmp(v->name, "localextenlength")) { 00937 if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) 00938 ast_mutex_lock(&globals_lock); 00939 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00940 ast_mutex_unlock(&globals_lock); 00941 } 00942 } 00943 00944 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))) { 00945 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); 00946 ast_config_destroy(cfg); 00947 return -1; 00948 } 00949 00950 cat = NULL; 00951 while ((cat = ast_category_browse(phoneprov_cfg, cat))) { 00952 if (!strcasecmp(cat, "general")) { 00953 for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) { 00954 if (!strcasecmp(v->name, "serveraddr")) 00955 ast_copy_string(global_server, v->value, sizeof(global_server)); 00956 else if (!strcasecmp(v->name, "serveriface")) { 00957 struct in_addr addr; 00958 lookup_iface(v->value, &addr); 00959 ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); 00960 } else if (!strcasecmp(v->name, "serverport")) 00961 ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); 00962 else if (!strcasecmp(v->name, "default_profile")) 00963 ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); 00964 } 00965 } else 00966 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat)); 00967 } 00968 00969 ast_config_destroy(phoneprov_cfg); 00970 00971 cat = NULL; 00972 while ((cat = ast_category_browse(cfg, cat))) { 00973 const char *tmp, *mac; 00974 struct user *user; 00975 struct phone_profile *profile; 00976 struct extension *exten; 00977 00978 if (!strcasecmp(cat, "general")) { 00979 continue; 00980 } 00981 00982 if (!strcasecmp(cat, "authentication")) 00983 continue; 00984 00985 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) 00986 continue; 00987 00988 if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { 00989 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); 00990 continue; 00991 } 00992 00993 tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); 00994 if (ast_strlen_zero(tmp)) { 00995 ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); 00996 continue; 00997 } 00998 00999 if (!(user = find_user(mac))) { 01000 if (!(profile = find_profile(tmp))) { 01001 ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); 01002 continue; 01003 } 01004 01005 if (!(user = build_user(mac, profile))) { 01006 ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress); 01007 continue; 01008 } 01009 01010 if (!(exten = build_extension(cfg, cat))) { 01011 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01012 user = unref_user(user); 01013 continue; 01014 } 01015 01016 if (add_user_extension(user, exten)) { 01017 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01018 user = unref_user(user); 01019 exten = delete_extension(exten); 01020 continue; 01021 } 01022 01023 if (build_user_routes(user)) { 01024 ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress); 01025 user = unref_user(user); 01026 continue; 01027 } 01028 01029 ao2_link(users, user); 01030 user = unref_user(user); 01031 } else { 01032 if (!(exten = build_extension(cfg, cat))) { 01033 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01034 user = unref_user(user); 01035 continue; 01036 } 01037 01038 if (add_user_extension(user, exten)) { 01039 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01040 user = unref_user(user); 01041 exten = delete_extension(exten); 01042 continue; 01043 } 01044 01045 user = unref_user(user); 01046 } 01047 } 01048 01049 ast_config_destroy(cfg); 01050 01051 return 0; 01052 }
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 1261 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.
01262 { 01263 struct ast_var_t *var; 01264 01265 ast_http_uri_unlink(&phoneprovuri); 01266 ast_custom_function_unregister(&pp_each_user_function); 01267 ast_custom_function_unregister(&pp_each_extension_function); 01268 ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01269 01270 delete_routes(); 01271 delete_users(); 01272 delete_profiles(); 01273 ao2_ref(profiles, -1); 01274 ao2_ref(http_routes, -1); 01275 ao2_ref(users, -1); 01276 01277 ast_mutex_lock(&globals_lock); 01278 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01279 ast_var_delete(var); 01280 } 01281 ast_mutex_unlock(&globals_lock); 01282 01283 ast_mutex_destroy(&globals_lock); 01284 01285 return 0; 01286 }
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 770 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 802 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.
00803 { 00804 struct user *user = obj; 00805 struct extension *exten; 00806 00807 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) { 00808 exten = delete_extension(exten); 00809 } 00810 00811 if (user->profile) { 00812 user->profile = unref_profile(user->profile); 00813 } 00814 00815 ast_string_field_free_memory(user); 00816 }
static int users_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 794 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and user::macaddress.
Referenced by load_module().
00795 { 00796 const struct user *user1 = obj, *user2 = arg; 00797 00798 return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0; 00799 }
static int users_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 787 of file res_phoneprov.c.
References ast_str_hash(), and user.
Referenced by load_module().
00788 { 00789 const struct user *user = obj; 00790 00791 return ast_str_hash(user->macaddress); 00792 }
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 1311 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 1311 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 1226 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.