Phone provisioning application for the asterisk internal http server. More...
#include "asterisk.h"#include <sys/ioctl.h>#include <sys/socket.h>#include <net/if.h>#include "asterisk/channel.h"#include "asterisk/file.h"#include "asterisk/paths.h"#include "asterisk/pbx.h"#include "asterisk/cli.h"#include "asterisk/module.h"#include "asterisk/http.h"#include "asterisk/utils.h"#include "asterisk/app.h"#include "asterisk/strings.h"#include "asterisk/stringfields.h"#include "asterisk/options.h"#include "asterisk/config.h"#include "asterisk/acl.h"#include "asterisk/astobj2.h"#include "asterisk/ast_version.h"
Go to the source code of this file.
Data Structures | |
| struct | extension |
| struct | http_route |
| structure to hold http routes (valid URIs, and the files they link to) More... | |
| struct | phone_profile |
| structure to hold phone profiles read from phoneprov.conf More... | |
| struct | phoneprov_file |
| structure to hold file data More... | |
| struct | pp_variable_lookup |
| Lookup table to translate between users.conf property names and variables for use in phoneprov templates. More... | |
| struct | user |
| structure to hold users read from users.conf More... | |
Defines | |
| #define | FORMAT "%-40.40s %-30.30s\n" |
| #define | MAX_PROFILE_BUCKETS 17 |
| #define | MAX_ROUTE_BUCKETS 563 |
| #define | MAX_USER_BUCKETS 563 |
| #define | VAR_BUF_SIZE 4096 |
Enumerations | |
| enum | pp_variables { PP_MACADDRESS, PP_USERNAME, PP_FULLNAME, PP_SECRET, PP_LABEL, PP_CALLERID, PP_TIMEZONE, PP_LINENUMBER, PP_LINEKEYS, PP_VAR_LIST_LENGTH } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | add_user_extension (struct user *user, struct extension *exten) |
| Add an extension to a user ordered by index/linenumber. | |
| static struct 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 = "0901e4e500243c855563a2d78b0c03e4" , .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 |
Phone provisioning application for the asterisk internal http server.
Definition in file res_phoneprov.c.
| #define FORMAT "%-40.40s %-30.30s\n" |
| #define MAX_PROFILE_BUCKETS 17 |
Definition at line 61 of file res_phoneprov.c.
Referenced by load_module().
| #define MAX_ROUTE_BUCKETS 563 |
Definition at line 62 of file res_phoneprov.c.
Referenced by load_module().
| #define MAX_USER_BUCKETS 563 |
Definition at line 63 of file res_phoneprov.c.
| #define VAR_BUF_SIZE 4096 |
Definition at line 66 of file res_phoneprov.c.
| enum pp_variables |
| PP_MACADDRESS | |
| PP_USERNAME | |
| PP_FULLNAME | |
| PP_SECRET | |
| PP_LABEL | |
| PP_CALLERID | |
| PP_TIMEZONE | |
| PP_LINENUMBER | |
| PP_LINEKEYS | |
| PP_VAR_LIST_LENGTH |
Definition at line 73 of file res_phoneprov.c.
00073 { 00074 PP_MACADDRESS, 00075 PP_USERNAME, 00076 PP_FULLNAME, 00077 PP_SECRET, 00078 PP_LABEL, 00079 PP_CALLERID, 00080 PP_TIMEZONE, 00081 PP_LINENUMBER, 00082 PP_LINEKEYS, 00083 PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */ 00084 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 1321 of file res_phoneprov.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1321 of file res_phoneprov.c.
Add an extension to a user ordered by index/linenumber.
Definition at line 860 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, user::extensions, extension::headp, phone_profile::headp, extension::index, LOG_WARNING, user::macaddress, ast_var_t::name, pbx_substitute_variables_varshead(), user::profile, ast_var_t::value, var, and VAR_BUF_SIZE.
Referenced by set_config().
00861 { 00862 struct ast_var_t *var; 00863 00864 /* Append profile variables here, and substitute variables on profile 00865 * setvars, so that we can use user specific variables in them */ 00866 AST_LIST_TRAVERSE(user->profile->headp, var, entries) { 00867 char expand_buf[VAR_BUF_SIZE] = {0,}; 00868 struct ast_var_t *var2; 00869 00870 pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf)); 00871 if ((var2 = ast_var_assign(var->name, expand_buf))) 00872 AST_LIST_INSERT_TAIL(exten->headp, var2, entries); 00873 } 00874 00875 if (AST_LIST_EMPTY(&user->extensions)) { 00876 AST_LIST_INSERT_HEAD(&user->extensions, exten, entry); 00877 } else { 00878 struct extension *exten_iter; 00879 00880 AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) { 00881 if (exten->index < exten_iter->index) { 00882 AST_LIST_INSERT_BEFORE_CURRENT(exten, entry); 00883 } else if (exten->index == exten_iter->index) { 00884 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress); 00885 return -1; 00886 } else if (!AST_LIST_NEXT(exten_iter, entry)) { 00887 AST_LIST_INSERT_TAIL(&user->extensions, exten, entry); 00888 } 00889 } 00890 AST_LIST_TRAVERSE_SAFE_END; 00891 } 00892 00893 return 0; 00894 }
| static struct extension* build_extension | ( | struct ast_config * | cfg, | |
| const char * | name | |||
| ) | [static, read] |
Definition at line 709 of file res_phoneprov.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), ast_variable_retrieve(), ast_var_t::entries, exten, extension::headp, extension::index, extension::name, PP_LINEKEYS, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.
Referenced by set_config().
00710 { 00711 struct extension *exten; 00712 struct ast_var_t *var; 00713 const char *tmp; 00714 int i; 00715 00716 if (!(exten = ast_calloc(1, sizeof(*exten)))) { 00717 return NULL; 00718 } 00719 00720 if (ast_string_field_init(exten, 32)) { 00721 ast_free(exten); 00722 exten = NULL; 00723 return NULL; 00724 } 00725 00726 ast_string_field_set(exten, name, name); 00727 00728 if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) { 00729 ast_free(exten); 00730 exten = NULL; 00731 return NULL; 00732 } 00733 00734 for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { 00735 tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); 00736 00737 /* If we didn't get a USERNAME variable, set it to the user->name */ 00738 if (i == PP_USERNAME && !tmp) { 00739 if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) { 00740 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00741 } 00742 continue; 00743 } else if (i == PP_TIMEZONE) { 00744 /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ 00745 set_timezone_variables(exten->headp, tmp); 00746 } else if (i == PP_LINENUMBER) { 00747 if (!tmp) { 00748 tmp = "1"; 00749 } 00750 exten->index = atoi(tmp); 00751 } else if (i == PP_LINEKEYS) { 00752 if (!tmp) { 00753 tmp = "1"; 00754 } 00755 } 00756 00757 if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) { 00758 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00759 } 00760 } 00761 00762 if (!ast_strlen_zero(global_server)) { 00763 if ((var = ast_var_assign("SERVER", global_server))) 00764 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00765 } 00766 00767 if (!ast_strlen_zero(global_serverport)) { 00768 if ((var = ast_var_assign("SERVER_PORT", global_serverport))) 00769 AST_LIST_INSERT_TAIL(exten->headp, var, entries); 00770 } 00771 00772 return exten; 00773 }
| 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 583 of file res_phoneprov.c.
References ao2_alloc, ao2_link, AST_APP_ARG, ast_calloc, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strip(), ast_strlen_zero(), ast_var_assign(), build_route(), phone_profile::default_mime_type, phone_profile::dynamic_files, ast_var_t::entries, phoneprov_file::format, ftype2mtype(), global_variables, phone_profile::headp, phoneprov_file::mime_type, ast_var_t::name, ast_variable::name, ast_variable::next, profile_destructor(), S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), ast_var_t::value, ast_variable::value, and var.
Referenced by set_config().
00584 { 00585 struct phone_profile *profile; 00586 struct ast_var_t *var; 00587 00588 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) { 00589 return; 00590 } 00591 00592 if (ast_string_field_init(profile, 32)) { 00593 profile = unref_profile(profile); 00594 return; 00595 } 00596 00597 if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { 00598 profile = unref_profile(profile); 00599 return; 00600 } 00601 00602 AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); 00603 AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); 00604 00605 ast_string_field_set(profile, name, name); 00606 for (; v; v = v->next) { 00607 if (!strcasecmp(v->name, "mime_type")) { 00608 ast_string_field_set(profile, default_mime_type, v->value); 00609 } else if (!strcasecmp(v->name, "setvar")) { 00610 struct ast_var_t *variable; 00611 char *value_copy = ast_strdupa(v->value); 00612 00613 AST_DECLARE_APP_ARGS(args, 00614 AST_APP_ARG(varname); 00615 AST_APP_ARG(varval); 00616 ); 00617 00618 AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); 00619 do { 00620 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00621 break; 00622 args.varname = ast_strip(args.varname); 00623 args.varval = ast_strip(args.varval); 00624 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00625 break; 00626 if ((variable = ast_var_assign(args.varname, args.varval))) 00627 AST_LIST_INSERT_TAIL(profile->headp, variable, entries); 00628 } while (0); 00629 } else if (!strcasecmp(v->name, "staticdir")) { 00630 ast_string_field_set(profile, staticdir, v->value); 00631 } else { 00632 struct phoneprov_file *pp_file; 00633 char *file_extension; 00634 char *value_copy = ast_strdupa(v->value); 00635 00636 AST_DECLARE_APP_ARGS(args, 00637 AST_APP_ARG(filename); 00638 AST_APP_ARG(mimetype); 00639 ); 00640 00641 if (!(pp_file = ast_calloc(1, sizeof(*pp_file)))) { 00642 profile = unref_profile(profile); 00643 return; 00644 } 00645 if (ast_string_field_init(pp_file, 32)) { 00646 ast_free(pp_file); 00647 profile = unref_profile(profile); 00648 return; 00649 } 00650 00651 if ((file_extension = strrchr(pp_file->format, '.'))) 00652 file_extension++; 00653 00654 AST_STANDARD_APP_ARGS(args, value_copy); 00655 00656 /* Mime type order of preference 00657 * 1) Specific mime-type defined for file in profile 00658 * 2) Mime determined by extension 00659 * 3) Default mime type specified in profile 00660 * 4) text/plain 00661 */ 00662 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")))); 00663 00664 if (!strcasecmp(v->name, "static_file")) { 00665 ast_string_field_set(pp_file, format, args.filename); 00666 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); 00667 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); 00668 /* Add a route for the static files, as their filenames won't change per-user */ 00669 build_route(pp_file, NULL, NULL); 00670 } else { 00671 ast_string_field_set(pp_file, format, v->name); 00672 ast_string_field_set(pp_file, template, args.filename); 00673 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); 00674 } 00675 } 00676 } 00677 00678 /* Append the global variables to the variables list for this profile. 00679 * This is for convenience later, when we need to provide a single 00680 * variable list for use in substitution. */ 00681 ast_mutex_lock(&globals_lock); 00682 AST_LIST_TRAVERSE(&global_variables, var, entries) { 00683 struct ast_var_t *new_var; 00684 if ((new_var = ast_var_assign(var->name, var->value))) { 00685 AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); 00686 } 00687 } 00688 ast_mutex_unlock(&globals_lock); 00689 00690 ao2_link(profiles, profile); 00691 00692 profile = unref_profile(profile); 00693 }
| 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 556 of file res_phoneprov.c.
References ao2_alloc, ao2_link, ast_log(), ast_string_field_init, ast_string_field_set, http_route::file, phoneprov_file::format, LOG_ERROR, route_destructor(), S_OR, unref_route(), and http_route::user.
Referenced by build_profile(), and build_user_routes().
00557 { 00558 struct http_route *route; 00559 00560 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) { 00561 return; 00562 } 00563 00564 if (ast_string_field_init(route, 32)) { 00565 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); 00566 route = unref_route(route); 00567 return; 00568 } 00569 00570 ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); 00571 route->user = user; 00572 route->file = pp_file; 00573 00574 ao2_link(http_routes, route); 00575 00576 route = unref_route(route); 00577 }
| static struct user* build_user | ( | const char * | mac, | |
| struct phone_profile * | profile | |||
| ) | [static, read] |
Build and return a user structure based on gathered config data.
Definition at line 838 of file res_phoneprov.c.
References ao2_alloc, ast_string_field_init, ast_string_field_set, user::macaddress, user::profile, unref_profile(), unref_user(), and user_destructor().
Referenced by set_config().
00839 { 00840 struct user *user; 00841 00842 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) { 00843 profile = unref_profile(profile); 00844 return NULL; 00845 } 00846 00847 if (ast_string_field_init(user, 32)) { 00848 profile = unref_profile(profile); 00849 user = unref_user(user); 00850 return NULL; 00851 } 00852 00853 ast_string_field_set(user, macaddress, mac); 00854 user->profile = profile; /* already ref counted by find_profile */ 00855 00856 return user; 00857 }
| 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 897 of file res_phoneprov.c.
References AST_LIST_FIRST, AST_LIST_TRAVERSE, build_route(), phone_profile::dynamic_files, user::extensions, phoneprov_file::format, pbx_substitute_variables_varshead(), user::profile, and VAR_BUF_SIZE.
Referenced by set_config().
00898 { 00899 struct phoneprov_file *pp_file; 00900 00901 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { 00902 char expand_buf[VAR_BUF_SIZE] = { 0, }; 00903 00904 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf)); 00905 build_route(pp_file, user, expand_buf); 00906 } 00907 00908 return 0; 00909 }
Definition at line 695 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, extension::headp, and var.
Referenced by set_config(), and user_destructor().
00696 { 00697 struct ast_var_t *var; 00698 while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) { 00699 ast_var_delete(var); 00700 } 00701 ast_free(exten->headp); 00702 ast_string_field_free_memory(exten); 00703 00704 ast_free(exten); 00705 00706 return NULL; 00707 }
| static void delete_file | ( | struct phoneprov_file * | file | ) | [static] |
Definition at line 257 of file res_phoneprov.c.
References ast_string_field_free_memory, and free.
Referenced by profile_destructor().
00258 { 00259 ast_string_field_free_memory(file); 00260 free(file); 00261 }
| static void delete_profiles | ( | void | ) | [static] |
Delete all phone profiles, freeing their memory.
Definition at line 1074 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_profile().
Referenced by reload(), and unload_module().
01075 { 01076 struct ao2_iterator i; 01077 struct phone_profile *profile; 01078 01079 i = ao2_iterator_init(profiles, 0); 01080 while ((profile = ao2_iterator_next(&i))) { 01081 ao2_unlink(profiles, profile); 01082 profile = unref_profile(profile); 01083 } 01084 ao2_iterator_destroy(&i); 01085 }
| static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 1060 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_route().
Referenced by reload(), and unload_module().
01061 { 01062 struct ao2_iterator i; 01063 struct http_route *route; 01064 01065 i = ao2_iterator_init(http_routes, 0); 01066 while ((route = ao2_iterator_next(&i))) { 01067 ao2_unlink(http_routes, route); 01068 route = unref_route(route); 01069 } 01070 ao2_iterator_destroy(&i); 01071 }
| static void delete_users | ( | void | ) | [static] |
Delete all users.
Definition at line 824 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_user().
Referenced by reload(), and unload_module().
00825 { 00826 struct ao2_iterator i; 00827 struct user *user; 00828 00829 i = ao2_iterator_init(users, 0); 00830 while ((user = ao2_iterator_next(&i))) { 00831 ao2_unlink(users, user); 00832 user = unref_user(user); 00833 } 00834 ao2_iterator_destroy(&i); 00835 }
| static struct phone_profile* find_profile | ( | const char * | name | ) | [static, read] |
Return a phone profile looked up by name.
Definition at line 234 of file res_phoneprov.c.
References ao2_find, phone_profile::name, and OBJ_POINTER.
Referenced by set_config().
00235 { 00236 struct phone_profile tmp = { 00237 .name = name, 00238 }; 00239 00240 return ao2_find(profiles, &tmp, OBJ_POINTER); 00241 }
| static struct user* find_user | ( | const char * | macaddress | ) | [static, read] |
Return a user looked up by name.
Definition at line 783 of file res_phoneprov.c.
References ao2_find, user::macaddress, and OBJ_POINTER.
Referenced by pp_each_extension_exec(), and set_config().
00784 { 00785 struct user tmp = { 00786 .macaddress = macaddress, 00787 }; 00788 00789 return ao2_find(users, &tmp, OBJ_POINTER); 00790 }
| static char* ftype2mtype | ( | const char * | ftype | ) | [static] |
Return mime type based on extension.
Definition at line 180 of file res_phoneprov.c.
References ARRAY_LEN, ast_strlen_zero(), ext, mimetypes, and mtype.
Referenced by build_profile().
| 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 1193 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, http_route::file, FORMAT, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.
01194 { 01195 #define FORMAT "%-40.40s %-30.30s\n" 01196 struct ao2_iterator i; 01197 struct http_route *route; 01198 01199 switch(cmd) { 01200 case CLI_INIT: 01201 e->command = "phoneprov show routes"; 01202 e->usage = 01203 "Usage: phoneprov show routes\n" 01204 " Lists all registered phoneprov http routes.\n"; 01205 return NULL; 01206 case CLI_GENERATE: 01207 return NULL; 01208 } 01209 01210 /* This currently iterates over routes twice, but it is the only place I've needed 01211 * to really separate static an dynamic routes, so I've just left it this way. */ 01212 ast_cli(a->fd, "Static routes\n\n"); 01213 ast_cli(a->fd, FORMAT, "Relative URI", "Physical location"); 01214 i = ao2_iterator_init(http_routes, 0); 01215 while ((route = ao2_iterator_next(&i))) { 01216 if (!route->user) 01217 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01218 route = unref_route(route); 01219 } 01220 ao2_iterator_destroy(&i); 01221 01222 ast_cli(a->fd, "\nDynamic routes\n\n"); 01223 ast_cli(a->fd, FORMAT, "Relative URI", "Template"); 01224 01225 i = ao2_iterator_init(http_routes, 0); 01226 while ((route = ao2_iterator_next(&i))) { 01227 if (route->user) 01228 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 01229 route = unref_route(route); 01230 } 01231 ao2_iterator_destroy(&i); 01232 01233 return CLI_SUCCESS; 01234 }
| static int load_file | ( | const char * | filename, | |
| char ** | ret | |||
| ) | [static] |
Read a TEXT file into a string and return the length.
Definition at line 311 of file res_phoneprov.c.
References ast_malloc, f, free, and len().
Referenced by phoneprov_callback(), and pp_each_extension_exec().
00312 { 00313 int len = 0; 00314 FILE *f; 00315 00316 if (!(f = fopen(filename, "r"))) { 00317 *ret = NULL; 00318 return -1; 00319 } 00320 00321 fseek(f, 0, SEEK_END); 00322 len = ftell(f); 00323 fseek(f, 0, SEEK_SET); 00324 if (!(*ret = ast_malloc(len + 1))) 00325 return -2; 00326 00327 if (len != fread(*ret, sizeof(char), len, f)) { 00328 free(*ret); 00329 *ret = NULL; 00330 return -3; 00331 } 00332 00333 fclose(f); 00334 00335 (*ret)[len] = '\0'; 00336 00337 return len; 00338 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1250 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, MAX_PROFILE_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, profile_cmp_fn(), profile_hash_fn(), routes_cmp_fn(), routes_hash_fn(), set_config(), users_cmp_fn(), and users_hash_fn().
01251 { 01252 profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn); 01253 01254 http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn); 01255 01256 users = ao2_container_alloc(MAX_USER_BUCKETS, users_hash_fn, users_cmp_fn); 01257 01258 AST_LIST_HEAD_INIT_NOLOCK(&global_variables); 01259 ast_mutex_init(&globals_lock); 01260 01261 ast_custom_function_register(&pp_each_user_function); 01262 ast_custom_function_register(&pp_each_extension_function); 01263 ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01264 01265 set_config(); 01266 ast_http_uri_link(&phoneprovuri); 01267 01268 return 0; 01269 }
| static int lookup_iface | ( | const char * | iface, | |
| struct in_addr * | address | |||
| ) | [static] |
Definition at line 196 of file res_phoneprov.c.
References ast_copy_string(), ast_log(), errno, LOG_ERROR, and LOG_WARNING.
Referenced by set_config().
00197 { 00198 int mysock, res = 0; 00199 struct ifreq ifr; 00200 struct sockaddr_in *sin; 00201 00202 memset(&ifr, 0, sizeof(ifr)); 00203 ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 00204 00205 mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 00206 if (mysock < 0) { 00207 ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno)); 00208 return -1; 00209 } 00210 00211 res = ioctl(mysock, SIOCGIFADDR, &ifr); 00212 00213 close(mysock); 00214 00215 if (res < 0) { 00216 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno)); 00217 memcpy(address, &__ourip, sizeof(__ourip)); 00218 return -1; 00219 } else { 00220 sin = (struct sockaddr_in *)&ifr.ifr_addr; 00221 memcpy(address, &sin->sin_addr, sizeof(*address)); 00222 return 0; 00223 } 00224 }
| 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, read] |
Callback that is executed everytime an http request is received by this module.
Definition at line 401 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, errno, user::extensions, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, http_route::file, fwrite, extension::headp, 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.
00402 { 00403 struct http_route *route; 00404 struct http_route search_route = { 00405 .uri = uri, 00406 }; 00407 struct ast_str *result = ast_str_create(512); 00408 char path[PATH_MAX]; 00409 char *file = NULL; 00410 int len; 00411 int fd; 00412 char buf[256]; 00413 struct timeval now = ast_tvnow(); 00414 struct ast_tm tm; 00415 00416 if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) { 00417 goto out404; 00418 } 00419 00420 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template); 00421 00422 if (!route->user) { /* Static file */ 00423 00424 fd = open(path, O_RDONLY); 00425 if (fd < 0) { 00426 goto out500; 00427 } 00428 00429 len = lseek(fd, 0, SEEK_END); 00430 lseek(fd, 0, SEEK_SET); 00431 if (len < 0) { 00432 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00433 close(fd); 00434 goto out500; 00435 } 00436 00437 ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT")); 00438 fprintf(ser->f, "HTTP/1.1 200 OK\r\n" 00439 "Server: Asterisk/%s\r\n" 00440 "Date: %s\r\n" 00441 "Connection: close\r\n" 00442 "Cache-Control: no-cache, no-store\r\n" 00443 "Content-Length: %d\r\n" 00444 "Content-Type: %s\r\n\r\n", 00445 ast_get_version(), buf, len, route->file->mime_type); 00446 00447 while ((len = read(fd, buf, sizeof(buf))) > 0) { 00448 if (fwrite(buf, 1, len, ser->f) != len) { 00449 if (errno != EPIPE) { 00450 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00451 } else { 00452 ast_debug(3, "Requester closed the connection while downloading '%s'\n", path); 00453 } 00454 break; 00455 } 00456 } 00457 00458 close(fd); 00459 route = unref_route(route); 00460 return NULL; 00461 } else { /* Dynamic file */ 00462 int bufsize; 00463 char *tmp; 00464 00465 len = load_file(path, &file); 00466 if (len < 0) { 00467 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00468 if (file) { 00469 ast_free(file); 00470 } 00471 00472 goto out500; 00473 } 00474 00475 if (!file) { 00476 goto out500; 00477 } 00478 00479 /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */ 00480 bufsize = len + VAR_BUF_SIZE; 00481 00482 /* malloc() instead of alloca() here, just in case the file is bigger than 00483 * we have enough stack space for. */ 00484 if (!(tmp = ast_calloc(1, bufsize))) { 00485 if (file) { 00486 ast_free(file); 00487 } 00488 00489 goto out500; 00490 } 00491 00492 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to 00493 * the IP address we are listening on that the phone contacted for this config file */ 00494 if (ast_strlen_zero(global_server)) { 00495 union { 00496 struct sockaddr sa; 00497 struct sockaddr_in sa_in; 00498 } name; 00499 socklen_t namelen = sizeof(name.sa); 00500 int res; 00501 00502 if ((res = getsockname(ser->fd, &name.sa, &namelen))) { 00503 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); 00504 } else { 00505 struct ast_var_t *var; 00506 struct extension *exten_iter; 00507 00508 if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) { 00509 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) { 00510 AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries); 00511 } 00512 } 00513 } 00514 } 00515 00516 pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize); 00517 00518 if (file) { 00519 ast_free(file); 00520 } 00521 00522 ast_str_append(&result, 0, 00523 "Content-Type: %s\r\n" 00524 "Content-length: %d\r\n" 00525 "\r\n" 00526 "%s", route->file->mime_type, (int) strlen(tmp), tmp); 00527 00528 if (tmp) { 00529 ast_free(tmp); 00530 } 00531 00532 route = unref_route(route); 00533 00534 return result; 00535 } 00536 00537 out404: 00538 *status = 404; 00539 *title = strdup("Not Found"); 00540 *contentlength = 0; 00541 return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); 00542 00543 out500: 00544 route = unref_route(route); 00545 *status = 500; 00546 *title = strdup("Internal Server Error"); 00547 *contentlength = 0; 00548 return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); 00549 }
| 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 1131 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(), exten, user::extensions, find_user(), extension::headp, load_file(), LOG_WARNING, pbx_substitute_variables_varshead(), unref_user(), and VAR_BUF_SIZE.
01132 { 01133 struct user *user; 01134 struct extension *exten; 01135 char path[PATH_MAX]; 01136 char *file; 01137 int filelen; 01138 AST_DECLARE_APP_ARGS(args, 01139 AST_APP_ARG(mac); 01140 AST_APP_ARG(template); 01141 ); 01142 01143 AST_STANDARD_APP_ARGS(args, data); 01144 01145 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) { 01146 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n"); 01147 return 0; 01148 } 01149 01150 if (!(user = find_user(args.mac))) { 01151 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac); 01152 return 0; 01153 } 01154 01155 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template); 01156 filelen = load_file(path, &file); 01157 if (filelen < 0) { 01158 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen); 01159 if (file) { 01160 ast_free(file); 01161 } 01162 return 0; 01163 } 01164 01165 if (!file) { 01166 return 0; 01167 } 01168 01169 AST_LIST_TRAVERSE(&user->extensions, exten, entry) { 01170 char expand_buf[VAR_BUF_SIZE] = {0,}; 01171 pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf)); 01172 ast_build_string(&buf, &len, "%s", expand_buf); 01173 } 01174 01175 ast_free(file); 01176 01177 user = unref_user(user); 01178 01179 return 0; 01180 }
| 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 1088 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(), user::extensions, user::macaddress, pbx_substitute_variables_varshead(), unref_user(), and VAR_BUF_SIZE.
01089 { 01090 char *tmp, expand_buf[VAR_BUF_SIZE] = {0,}; 01091 struct ao2_iterator i; 01092 struct user *user; 01093 AST_DECLARE_APP_ARGS(args, 01094 AST_APP_ARG(string); 01095 AST_APP_ARG(exclude_mac); 01096 ); 01097 AST_STANDARD_APP_ARGS(args, data); 01098 01099 /* Fix data by turning %{ into ${ */ 01100 while ((tmp = strstr(args.string, "%{"))) 01101 *tmp = '$'; 01102 01103 i = ao2_iterator_init(users, 0); 01104 while ((user = ao2_iterator_next(&i))) { 01105 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) { 01106 continue; 01107 } 01108 pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf)); 01109 ast_build_string(&buf, &len, "%s", expand_buf); 01110 user = unref_user(user); 01111 } 01112 ao2_iterator_destroy(&i); 01113 01114 return 0; 01115 }
| static int profile_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 250 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and phone_profile::name.
Referenced by load_module().
00251 { 00252 const struct phone_profile *profile1 = obj, *profile2 = arg; 00253 00254 return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0; 00255 }
| static void profile_destructor | ( | void * | obj | ) | [static] |
Definition at line 263 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), delete_file(), phone_profile::dynamic_files, ast_var_t::entries, phone_profile::headp, phone_profile::static_files, and var.
Referenced by build_profile().
00264 { 00265 struct phone_profile *profile = obj; 00266 struct phoneprov_file *file; 00267 struct ast_var_t *var; 00268 00269 while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) 00270 delete_file(file); 00271 00272 while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) 00273 delete_file(file); 00274 00275 while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) 00276 ast_var_delete(var); 00277 00278 ast_free(profile->headp); 00279 ast_string_field_free_memory(profile); 00280 }
| static int profile_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 243 of file res_phoneprov.c.
References ast_str_case_hash(), and phone_profile::name.
Referenced by load_module().
00244 { 00245 const struct phone_profile *profile = obj; 00246 00247 return ast_str_case_hash(profile->name); 00248 }
| static int reload | ( | void | ) | [static] |
Definition at line 1298 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.
01299 { 01300 struct ast_var_t *var; 01301 01302 delete_routes(); 01303 delete_users(); 01304 delete_profiles(); 01305 01306 ast_mutex_lock(&globals_lock); 01307 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01308 ast_var_delete(var); 01309 } 01310 ast_mutex_unlock(&globals_lock); 01311 01312 set_config(); 01313 01314 return 0; 01315 }
| static void route_destructor | ( | void * | obj | ) | [static] |
Definition at line 303 of file res_phoneprov.c.
References ast_string_field_free_memory.
Referenced by build_route().
00304 { 00305 struct http_route *route = obj; 00306 00307 ast_string_field_free_memory(route); 00308 }
| static int routes_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 296 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and http_route::uri.
Referenced by load_module().
00297 { 00298 const struct http_route *route1 = obj, *route2 = arg; 00299 00300 return !strcasecmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0; 00301 }
| static int routes_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 289 of file res_phoneprov.c.
References ast_str_case_hash(), and http_route::uri.
Referenced by load_module().
00290 { 00291 const struct http_route *route = obj; 00292 00293 return ast_str_case_hash(route->uri); 00294 }
| static int set_config | ( | void | ) | [static] |
Definition at line 912 of file res_phoneprov.c.
References add_user_extension(), ao2_link, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_inet_ntoa(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_true(), ast_var_assign(), ast_variable_browse(), ast_variable_retrieve(), build_extension(), build_profile(), build_user(), build_user_routes(), CONFIG_STATUS_FILEINVALID, delete_extension(), ast_var_t::entries, exten, find_profile(), find_user(), global_variables, LOG_ERROR, LOG_WARNING, lookup_iface(), user::macaddress, extension::name, ast_variable::name, ast_variable::next, S_OR, unref_user(), ast_variable::value, and var.
Referenced by load_module(), and reload().
00913 { 00914 struct ast_config *cfg, *phoneprov_cfg; 00915 char *cat; 00916 struct ast_variable *v; 00917 struct ast_flags config_flags = { 0 }; 00918 struct ast_var_t *var; 00919 00920 /* Try to grab the port from sip.conf. If we don't get it here, we'll set it 00921 * to whatever is set in phoneprov.conf or default to 5060 */ 00922 if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) { 00923 ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); 00924 ast_config_destroy(cfg); 00925 } 00926 00927 if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) { 00928 ast_log(LOG_WARNING, "Unable to load users.conf\n"); 00929 return 0; 00930 } 00931 00932 /* Go ahead and load global variables from users.conf so we can append to profiles */ 00933 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00934 if (!strcasecmp(v->name, "vmexten")) { 00935 if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) { 00936 ast_mutex_lock(&globals_lock); 00937 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00938 ast_mutex_unlock(&globals_lock); 00939 } 00940 } 00941 if (!strcasecmp(v->name, "localextenlength")) { 00942 if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) 00943 ast_mutex_lock(&globals_lock); 00944 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00945 ast_mutex_unlock(&globals_lock); 00946 } 00947 } 00948 00949 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags)) || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) { 00950 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); 00951 ast_config_destroy(cfg); 00952 return -1; 00953 } 00954 00955 cat = NULL; 00956 while ((cat = ast_category_browse(phoneprov_cfg, cat))) { 00957 if (!strcasecmp(cat, "general")) { 00958 for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) { 00959 if (!strcasecmp(v->name, "serveraddr")) 00960 ast_copy_string(global_server, v->value, sizeof(global_server)); 00961 else if (!strcasecmp(v->name, "serveriface")) { 00962 struct in_addr addr; 00963 lookup_iface(v->value, &addr); 00964 ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); 00965 } else if (!strcasecmp(v->name, "serverport")) 00966 ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); 00967 else if (!strcasecmp(v->name, "default_profile")) 00968 ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); 00969 } 00970 } else 00971 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat)); 00972 } 00973 00974 ast_config_destroy(phoneprov_cfg); 00975 00976 cat = NULL; 00977 while ((cat = ast_category_browse(cfg, cat))) { 00978 const char *tmp, *mac; 00979 struct user *user; 00980 struct phone_profile *profile; 00981 struct extension *exten; 00982 00983 if (!strcasecmp(cat, "general")) { 00984 continue; 00985 } 00986 00987 if (!strcasecmp(cat, "authentication")) 00988 continue; 00989 00990 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) 00991 continue; 00992 00993 if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { 00994 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); 00995 continue; 00996 } 00997 00998 tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); 00999 if (ast_strlen_zero(tmp)) { 01000 ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); 01001 continue; 01002 } 01003 01004 if (!(user = find_user(mac))) { 01005 if (!(profile = find_profile(tmp))) { 01006 ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); 01007 continue; 01008 } 01009 01010 if (!(user = build_user(mac, profile))) { 01011 ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress); 01012 continue; 01013 } 01014 01015 if (!(exten = build_extension(cfg, cat))) { 01016 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01017 user = unref_user(user); 01018 continue; 01019 } 01020 01021 if (add_user_extension(user, exten)) { 01022 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01023 user = unref_user(user); 01024 exten = delete_extension(exten); 01025 continue; 01026 } 01027 01028 if (build_user_routes(user)) { 01029 ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress); 01030 user = unref_user(user); 01031 continue; 01032 } 01033 01034 ao2_link(users, user); 01035 user = unref_user(user); 01036 } else { 01037 if (!(exten = build_extension(cfg, cat))) { 01038 ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress); 01039 user = unref_user(user); 01040 continue; 01041 } 01042 01043 if (add_user_extension(user, exten)) { 01044 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress); 01045 user = unref_user(user); 01046 exten = delete_extension(exten); 01047 continue; 01048 } 01049 01050 user = unref_user(user); 01051 } 01052 } 01053 01054 ast_config_destroy(cfg); 01055 01056 return 0; 01057 }
| 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 344 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().
00345 { 00346 time_t utc_time; 00347 int dstenable; 00348 time_t dststart; 00349 time_t dstend; 00350 struct ast_tm tm_info; 00351 int tzoffset; 00352 char buffer[21]; 00353 struct ast_var_t *var; 00354 struct timeval when; 00355 00356 time(&utc_time); 00357 ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone); 00358 snprintf(buffer, sizeof(buffer), "%d", tzoffset); 00359 var = ast_var_assign("TZOFFSET", buffer); 00360 if (var) 00361 AST_LIST_INSERT_TAIL(headp, var, entries); 00362 00363 if (!dstenable) 00364 return; 00365 00366 if ((var = ast_var_assign("DST_ENABLE", "1"))) 00367 AST_LIST_INSERT_TAIL(headp, var, entries); 00368 00369 when.tv_sec = dststart; 00370 ast_localtime(&when, &tm_info, zone); 00371 00372 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1); 00373 if ((var = ast_var_assign("DST_START_MONTH", buffer))) 00374 AST_LIST_INSERT_TAIL(headp, var, entries); 00375 00376 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00377 if ((var = ast_var_assign("DST_START_MDAY", buffer))) 00378 AST_LIST_INSERT_TAIL(headp, var, entries); 00379 00380 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00381 if ((var = ast_var_assign("DST_START_HOUR", buffer))) 00382 AST_LIST_INSERT_TAIL(headp, var, entries); 00383 00384 when.tv_sec = dstend; 00385 ast_localtime(&when, &tm_info, zone); 00386 00387 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1); 00388 if ((var = ast_var_assign("DST_END_MONTH", buffer))) 00389 AST_LIST_INSERT_TAIL(headp, var, entries); 00390 00391 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00392 if ((var = ast_var_assign("DST_END_MDAY", buffer))) 00393 AST_LIST_INSERT_TAIL(headp, var, entries); 00394 00395 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00396 if ((var = ast_var_assign("DST_END_HOUR", buffer))) 00397 AST_LIST_INSERT_TAIL(headp, var, entries); 00398 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1271 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, and var.
01272 { 01273 struct ast_var_t *var; 01274 01275 ast_http_uri_unlink(&phoneprovuri); 01276 ast_custom_function_unregister(&pp_each_user_function); 01277 ast_custom_function_unregister(&pp_each_extension_function); 01278 ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01279 01280 delete_routes(); 01281 delete_users(); 01282 delete_profiles(); 01283 ao2_ref(profiles, -1); 01284 ao2_ref(http_routes, -1); 01285 ao2_ref(users, -1); 01286 01287 ast_mutex_lock(&globals_lock); 01288 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) { 01289 ast_var_delete(var); 01290 } 01291 ast_mutex_unlock(&globals_lock); 01292 01293 ast_mutex_destroy(&globals_lock); 01294 01295 return 0; 01296 }
| static struct phone_profile* unref_profile | ( | struct phone_profile * | prof | ) | [static, read] |
Definition at line 226 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_profile(), build_user(), delete_profiles(), and user_destructor().
00227 { 00228 ao2_ref(prof, -1); 00229 00230 return NULL; 00231 }
| static struct http_route* unref_route | ( | struct http_route * | route | ) | [static, read] |
Definition at line 282 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().
00283 { 00284 ao2_ref(route, -1); 00285 00286 return NULL; 00287 }
Definition at line 775 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_user(), delete_users(), pp_each_extension_exec(), pp_each_user_exec(), and set_config().
00776 { 00777 ao2_ref(user, -1); 00778 00779 return NULL; 00780 }
| static void user_destructor | ( | void * | obj | ) | [static] |
Free all memory associated with a user.
Definition at line 807 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), exten, user::extensions, user::profile, and unref_profile().
Referenced by build_user().
00808 { 00809 struct user *user = obj; 00810 struct extension *exten; 00811 00812 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) { 00813 exten = delete_extension(exten); 00814 } 00815 00816 if (user->profile) { 00817 user->profile = unref_profile(user->profile); 00818 } 00819 00820 ast_string_field_free_memory(user); 00821 }
| static int users_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 799 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and user::macaddress.
Referenced by load_module().
00800 { 00801 const struct user *user1 = obj, *user2 = arg; 00802 00803 return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0; 00804 }
| static int users_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 792 of file res_phoneprov.c.
References ast_str_case_hash(), and user::macaddress.
Referenced by load_module().
00793 { 00794 const struct user *user = obj; 00795 00796 return ast_str_case_hash(user->macaddress); 00797 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1321 of file res_phoneprov.c.
struct in_addr __ourip = { .s_addr = 0x00000000, } [static] |
for use in lookup_iface
Definition at line 69 of file res_phoneprov.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1321 of file res_phoneprov.c.
| char* ext |
Definition at line 160 of file res_phoneprov.c.
char global_default_profile[80] = "" [static] |
Default profile to use if one isn't specified
Definition at line 173 of file res_phoneprov.c.
char global_server[80] = "" [static] |
Server to substitute into templates
Definition at line 171 of file res_phoneprov.c.
char global_serverport[6] = "" [static] |
Server port to substitute into templates
Definition at line 172 of file res_phoneprov.c.
struct varshead global_variables [static] |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
Definition at line 176 of file res_phoneprov.c.
Referenced by build_profile(), load_module(), reload(), set_config(), and unload_module().
ast_mutex_t globals_lock [static] |
Definition at line 177 of file res_phoneprov.c.
struct ao2_container* http_routes [static] |
Definition at line 155 of file res_phoneprov.c.
struct { ... } mimetypes[] [static] |
Extensions whose mime types we think we know.
Referenced by ftype2mtype().
| char* mtype |
Definition at line 161 of file res_phoneprov.c.
struct ast_http_uri phoneprovuri [static] |
Definition at line 1240 of file res_phoneprov.c.
struct ast_cli_entry pp_cli[] [static] |
{
AST_CLI_DEFINE(handle_show_routes, "Show registered phoneprov http routes"),
}
Definition at line 1236 of file res_phoneprov.c.
struct ast_custom_function pp_each_extension_function [static] |
Definition at line 1182 of file res_phoneprov.c.
struct ast_custom_function pp_each_user_function [static] |
Definition at line 1117 of file res_phoneprov.c.
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 154 of file res_phoneprov.c.
struct ao2_container* users [static] |
Definition at line 156 of file res_phoneprov.c.
1.6.2