Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
res_phoneprov.c File Reference

Phone provisioning application for the asterisk internal http server. More...

#include "asterisk.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/paths.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/strings.h"
#include "asterisk/stringfields.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/acl.h"
#include "asterisk/astobj2.h"
#include "asterisk/ast_version.h"
#include "asterisk/phoneprov.h"
Include dependency graph for res_phoneprov.c:

Go to the source code of this file.

Data Structures

struct  extension
 structure to hold extensions More...
 
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  phoneprov_provider
 structure to hold config providers More...
 
struct  user
 structure to hold users read from phoneprov_users.conf More...
 

Macros

#define AST_API_MODULE
 
#define FORMATD   "%-20.20s %-20.20s %-40.40s %-30.30s\n"
 
#define FORMATS   "%-20.20s %-40.40s %-30.30s\n"
 
#define MAX_PROFILE_BUCKETS   17
 
#define MAX_PROVIDER_BUCKETS   17
 
#define MAX_ROUTE_BUCKETS   563
 
#define MAX_USER_BUCKETS   563
 
#define SIMPLE_CMP_FN(fname, stype, field)
 Creates a compare function for a structure string field.
 
#define SIMPLE_HASH_FN(fname, stype, field)
 Creates a hash function for a structure string field.
 
#define SIPUSERS_PROVIDER_NAME   "sipusers"
 
#define VAR_BUF_SIZE   4096
 

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.
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_phoneprov_add_extension (char *provider_name, struct varshead *vars)
 Adds an extension.
 
void ast_phoneprov_delete_extension (char *provider_name, char *macaddress)
 Deletes an extension.
 
void ast_phoneprov_delete_extensions (char *provider_name)
 Deletes all extensions for this provider.
 
int ast_phoneprov_provider_register (char *provider_name, ast_phoneprov_load_users_cb load_users)
 Registers a config provider to phoneprov.
 
void ast_phoneprov_provider_unregister (char *provider_name)
 Unegisters a config provider from phoneprov and frees its resources.
 
const char * ast_phoneprov_std_variable_lookup (enum ast_phoneprov_std_variables var)
 Returns the string respresentation of a phoneprov standard variable.
 
static struct extensionbuild_extension (const char *name, struct varshead *vars)
 
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 phone_profile *profile, struct user *user, char *uri)
 Build a route structure and add it to the list of available http routes.
 
static struct userbuild_user (const char *mac, struct phone_profile *profile, char *provider_name)
 Build and return a user structure based on gathered config data.
 
static int build_user_routes (struct user *user)
 Add an http route for dynamic files attached to the profile of the user.
 
static struct extensiondelete_extension (struct extension *exten)
 
static void delete_file (struct phoneprov_file *file)
 
static void delete_profiles (void)
 Delete all phone profiles, freeing their memory.
 
static void delete_providers (void)
 Delete all providers.
 
static void delete_routes (void)
 Delete all http routes, freeing their memory.
 
static void delete_users (void)
 Delete all users.
 
static int extension_delete_cb (void *obj, void *arg, void *data, int flags)
 
static int extensions_delete_cb (void *obj, void *arg, int flags)
 
static struct phone_profilefind_profile (const char *name)
 Return a phone profile looked up by name.
 
static struct phoneprov_providerfind_provider (char *name)
 
static struct userfind_user (const char *macaddress)
 Return a user looked up by name.
 
static struct varsheadget_defaults (void)
 
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_common (void)
 
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)
 Load the module.
 
static int load_users (void)
 
static int lookup_iface (const char *iface, struct in_addr *address)
 
static int phoneprov_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
 Callback that is executed everytime an http request is received by this module.
 
static int pp_each_extension_helper (struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len)
 A dialplan function that can be used to output a template for each extension attached to a user.
 
static int pp_each_extension_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int pp_each_extension_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
 
static int pp_each_user_helper (struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len)
 A dialplan function that can be used to print a string for each phoneprov user.
 
static int pp_each_user_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int pp_each_user_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
 
static void profile_destructor (void *obj)
 
static void provider_destructor (void *obj)
 
static int reload (void)
 
static void route_destructor (void *obj)
 
static int route_list_cb (void *obj, void *arg, void *data, int flags)
 
static int routes_delete_cb (void *obj, void *arg, int flags)
 
static void set_timezone_variables (struct varshead *headp, const char *zone)
 Set all timezone-related variables based on a zone (i.e. America/New_York)
 
static int unload_module (void)
 
static struct phone_profileunref_profile (struct phone_profile *prof)
 
static struct http_routeunref_route (struct http_route *route)
 
static struct userunref_user (struct user *user)
 
static void user_destructor (void *obj)
 Free all memory associated with a user.
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "HTTP Phone Provisioning" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .requires = "http", }
 
static struct in_addr __ourip = { .s_addr = 0x00000000, }
 for use in lookup_iface
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct ao2_containerhttp_routes
 
static struct ast_http_uri phoneprovuri
 
static struct ast_cli_entry pp_cli []
 
static struct ast_custom_function pp_each_extension_function
 
static struct ast_custom_function pp_each_user_function
 
static const char * pp_general_lookup []
 
static const char * pp_user_lookup []
 
struct ao2_containerprofiles
 
struct ao2_containerproviders
 
struct ao2_containerusers
 
static const char * variable_lookup []
 

Detailed Description

Phone provisioning application for the asterisk internal http server.

Author
Matthew Brooks mbroo.nosp@m.ks@d.nosp@m.igium.nosp@m..com
Terry Wilson twils.nosp@m.on@d.nosp@m.igium.nosp@m..com
George Joseph georg.nosp@m.e.jo.nosp@m.seph@.nosp@m.fair.nosp@m.view5.nosp@m..com

Definition in file res_phoneprov.c.

Macro Definition Documentation

◆ AST_API_MODULE

#define AST_API_MODULE

Definition at line 45 of file res_phoneprov.c.

◆ FORMATD

#define FORMATD   "%-20.20s %-20.20s %-40.40s %-30.30s\n"

Definition at line 1162 of file res_phoneprov.c.

◆ FORMATS

#define FORMATS   "%-20.20s %-40.40s %-30.30s\n"

Definition at line 1161 of file res_phoneprov.c.

◆ MAX_PROFILE_BUCKETS

#define MAX_PROFILE_BUCKETS   17

Definition at line 81 of file res_phoneprov.c.

◆ MAX_PROVIDER_BUCKETS

#define MAX_PROVIDER_BUCKETS   17

Definition at line 80 of file res_phoneprov.c.

◆ MAX_ROUTE_BUCKETS

#define MAX_ROUTE_BUCKETS   563

Definition at line 82 of file res_phoneprov.c.

◆ MAX_USER_BUCKETS

#define MAX_USER_BUCKETS   563

Definition at line 83 of file res_phoneprov.c.

◆ SIMPLE_CMP_FN

#define SIMPLE_CMP_FN (   fname,
  stype,
  field 
)

Creates a compare function for a structure string field.

Parameters
fnameThe name to use for the function
stypeThe structure type
fieldThe field in the structure to compare

SIMPLE_CMP_FN(mystruct, myfield) will produce a function named mystruct_cmp_fn which compares mystruct->myfield.

Definition at line 163 of file res_phoneprov.c.

165{ \
166 const struct stype *object_left = obj, *object_right = arg; \
167 const char *right_key = arg; \
168 int cmp; \
169 switch (flags & OBJ_SEARCH_MASK) { \
170 case OBJ_SEARCH_OBJECT: \
171 right_key = object_right->field; \
172 case OBJ_SEARCH_KEY: \
173 cmp = strcmp(object_left->field, right_key); \
174 break; \
176 cmp = strncmp(object_left->field, right_key, strlen(right_key)); \
177 break; \
178 default: \
179 cmp = 0; \
180 break; \
181 } \
182 if (cmp) { \
183 return 0; \
184 } \
185 return CMP_MATCH; \
186}
@ CMP_MATCH
Definition astobj2.h:1027
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition astobj2.h:1072
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition astobj2.h:1101

◆ SIMPLE_HASH_FN

#define SIMPLE_HASH_FN (   fname,
  stype,
  field 
)

Creates a hash function for a structure string field.

Parameters
fnameThe name to use for the function
stypeThe structure type
fieldThe field in the structure to hash

SIMPLE_HASH_FN(mystruct, myfield) will produce a function named mystruct_hash_fn which hashes mystruct->myfield.

Definition at line 134 of file res_phoneprov.c.

136{ \
137 const struct stype *provider = obj; \
138 const char *key; \
139 switch (flags & OBJ_SEARCH_MASK) { \
140 case OBJ_SEARCH_KEY: \
141 key = obj; \
142 break; \
143 case OBJ_SEARCH_OBJECT: \
144 provider = obj; \
145 key = provider->field; \
146 break; \
147 default: \
148 ast_assert(0); \
149 return 0; \
150 } \
151 return ast_str_hash(key); \
152}
static struct prometheus_metrics_provider provider
Definition bridges.c:201
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition strings.h:1259

◆ SIPUSERS_PROVIDER_NAME

#define SIPUSERS_PROVIDER_NAME   "sipusers"

Definition at line 344 of file res_phoneprov.c.

◆ VAR_BUF_SIZE

#define VAR_BUF_SIZE   4096

Definition at line 86 of file res_phoneprov.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1526 of file res_phoneprov.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1526 of file res_phoneprov.c.

◆ add_user_extension()

static int add_user_extension ( struct user user,
struct extension exten 
)
static

Add an extension to a user ordered by index/linenumber.

Definition at line 812 of file res_phoneprov.c.

813{
814 struct ast_var_t *pvar, *var2;
815 struct ast_str *str = ast_str_create(16);
816
817 if (!str) {
818 return -1;
819 }
820
821 /* Append profile variables here, and substitute variables on profile
822 * setvars, so that we can use user specific variables in them */
824 if (ast_var_find(exten->headp, pvar->name)) {
825 continue;
826 }
827
829 if ((var2 = ast_var_assign(pvar->name, ast_str_buffer(str)))) {
830 AST_VAR_LIST_INSERT_TAIL(exten->headp, var2);
831 }
832 }
833 ast_free(str);
834
836 AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
837 } else {
838 struct extension *exten_iter;
839
841 if (exten->index < exten_iter->index) {
843 } else if (exten->index == exten_iter->index) {
844 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
845 return -1;
846 } else if (!AST_LIST_NEXT(exten_iter, entry)) {
848 }
849 }
851 }
852
853 return 0;
854}
const char * str
Definition app_jack.c:150
#define ast_free(a)
Definition astmm.h:180
#define ast_log
Definition astobj2.c:42
char * ast_var_find(const struct varshead *head, const char *name)
Definition chanvars.c:85
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition chanvars.h:51
#define AST_VAR_LIST_TRAVERSE(head, var)
Definition chanvars.h:49
#define ast_var_assign(name, value)
Definition chanvars.h:40
#define LOG_WARNING
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
Support for dynamic strings.
Definition strings.h:623
char name[0]
Definition chanvars.h:31
char * value
Definition chanvars.h:30
structure to hold extensions
struct extension::@483 entry
struct varshead * headp
struct varshead * headp
structure to hold users read from phoneprov_users.conf
struct user::@486 extensions
const ast_string_field macaddress
struct phone_profile * profile

References ast_free, AST_LIST_EMPTY, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_NEXT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_str_buffer(), ast_str_create, ast_str_substitute_variables_varshead(), ast_var_assign, ast_var_find(), AST_VAR_LIST_INSERT_TAIL(), AST_VAR_LIST_TRAVERSE, extension::entry, user::extensions, extension::headp, phone_profile::headp, extension::index, LOG_WARNING, user::macaddress, ast_var_t::name, user::profile, str, and ast_var_t::value.

Referenced by ast_phoneprov_add_extension().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1526 of file res_phoneprov.c.

◆ ast_phoneprov_add_extension()

int ast_phoneprov_add_extension ( char *  provider_name,
struct varshead vars 
)

Adds an extension.

Parameters
provider_nameThe name of the provider
varsAn ast_vat_t linked list of the extension's variables. The list is automatically cloned and it must contain at least MACADDRESS and USERNAME entries.
Return values
0if successful
non-zeroif failure

Definition at line 1639 of file res_phoneprov.c.

1640{
1642 RAII_VAR(struct user *, user, NULL, ao2_cleanup);
1643 RAII_VAR(struct phone_profile *, profile, NULL, ao2_cleanup);
1644 struct extension *exten;
1645 char *profile_name;
1646 char *mac;
1647 char *username;
1648
1649 if (ast_strlen_zero(provider_name)) {
1650 ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1651 return -1;
1652 }
1653 if (!vars) {
1654 ast_log(LOG_ERROR, "Variable list can't be empty.\n");
1655 return -1;
1656 }
1657
1659 if (!username) {
1660 ast_log(LOG_ERROR, "Extension name can't be empty.\n");
1661 return -1;
1662 }
1663
1665 if (!mac) {
1666 ast_log(LOG_ERROR, "MAC Address can't be empty.\n");
1667 return -1;
1668 }
1669
1670 provider = find_provider(provider_name);
1671 if (!provider) {
1672 ast_log(LOG_ERROR, "Provider '%s' wasn't found in the registry.\n", provider_name);
1673 return -1;
1674 }
1675
1676 profile_name = ast_var_find(vars,
1678 if (!profile_name) {
1679 ast_log(LOG_ERROR, "No profile could be found for user '%s' - skipping.\n", username);
1680 return -1;
1681 }
1682 if (!(profile = find_profile(profile_name))) {
1683 ast_log(LOG_ERROR, "Could not look up profile '%s' - skipping.\n", profile_name);
1684 return -1;
1685 }
1686
1687 if (!(user = find_user(mac))) {
1688
1689 if (!(user = build_user(mac, profile, provider_name))) {
1690 ast_log(LOG_ERROR, "Could not create user for '%s' - skipping\n", mac);
1691 return -1;
1692 }
1693
1694 if (!(exten = build_extension(username, vars))) {
1695 ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1696 return -1;
1697 }
1698
1699 if (add_user_extension(user, exten)) {
1700 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
1701 exten = delete_extension(exten);
1702 return -1;
1703 }
1704
1705 if (build_user_routes(user)) {
1706 ast_log(LOG_WARNING, "Could not create http routes for '%s' - skipping\n", user->macaddress);
1707 return -1;
1708 }
1710
1711 } else {
1712 if (strcmp(provider_name, user->provider_name)) {
1713 ast_log(LOG_ERROR, "MAC address '%s' was already added by provider '%s' - skipping\n", user->macaddress, user->provider_name);
1714 return -1;
1715 }
1716
1717 if (!(exten = build_extension(username, vars))) {
1718 ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1719 return -1;
1720 }
1721
1722 if (add_user_extension(user, exten)) {
1723 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
1724 exten = delete_extension(exten);
1725 return -1;
1726 }
1727 }
1728
1729 return 0;
1730}
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define LOG_ERROR
@ AST_PHONEPROV_STD_MAC
Definition phoneprov.h:30
@ AST_PHONEPROV_STD_USERNAME
Definition phoneprov.h:32
@ AST_PHONEPROV_STD_PROFILE
Definition phoneprov.h:31
static struct user * build_user(const char *mac, struct phone_profile *profile, char *provider_name)
Build and return a user structure based on gathered config data.
static struct user * find_user(const char *macaddress)
Return a user looked up by name.
static struct phone_profile * find_profile(const char *name)
Return a phone profile looked up by name.
static struct phoneprov_provider * find_provider(char *name)
static int build_user_routes(struct user *user)
Add an http route for dynamic files attached to the profile of the user.
static const char * variable_lookup[]
static struct extension * delete_extension(struct extension *exten)
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(const char *name, struct varshead *vars)
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
const ast_string_field name
structure to hold phone profiles read from phoneprov.conf
structure to hold config providers
const ast_string_field provider_name
list of users found in the config file
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References add_user_extension(), ao2_cleanup, ao2_link, ast_log, AST_PHONEPROV_STD_MAC, AST_PHONEPROV_STD_PROFILE, AST_PHONEPROV_STD_USERNAME, ast_strlen_zero(), ast_var_find(), build_extension(), build_user(), build_user_routes(), delete_extension(), find_profile(), find_provider(), find_user(), LOG_ERROR, LOG_WARNING, user::macaddress, extension::name, NULL, user::profile, provider, user::provider_name, RAII_VAR, and variable_lookup.

Referenced by load_users(), and users_apply_handler().

◆ ast_phoneprov_delete_extension()

void ast_phoneprov_delete_extension ( char *  provider_name,
char *  macaddress 
)

Deletes an extension.

Parameters
provider_nameThe name of the provider
macaddressThe mac address of the extension

Definition at line 1610 of file res_phoneprov.c.

1611{
1612 if (!users) {
1613 return;
1614 }
1615
1617 extension_delete_cb, macaddress, provider_name);
1618}
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition astobj2.h:1723
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_MULTIPLE
Definition astobj2.h:1049
@ OBJ_UNLINK
Definition astobj2.h:1039
static int extension_delete_cb(void *obj, void *arg, void *data, int flags)

References ao2_callback_data, extension_delete_cb(), user::macaddress, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, and user::provider_name.

Referenced by phoneprov_destroy().

◆ ast_phoneprov_delete_extensions()

void ast_phoneprov_delete_extensions ( char *  provider_name)

Deletes all extensions for this provider.

Parameters
provider_nameThe name of the provider

Definition at line 1620 of file res_phoneprov.c.

1621{
1622 if (!users) {
1623 return;
1624 }
1625
1627}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
static int extensions_delete_cb(void *obj, void *arg, int flags)

References ao2_callback, extensions_delete_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and user::provider_name.

Referenced by ast_phoneprov_provider_unregister().

◆ ast_phoneprov_provider_register()

int ast_phoneprov_provider_register ( char *  provider_name,
ast_phoneprov_load_users_cb  load_users 
)

Registers a config provider to phoneprov.

Parameters
provider_nameThe name of the provider
load_usersCallback that gathers user variables then loads them by calling ast_phoneprov_add_extension once for each extension.
Return values
0if successful
non-zeroif failure

Definition at line 1539 of file res_phoneprov.c.

1541{
1543
1545 ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1546 return -1;
1547 }
1548
1549 if (!providers) {
1550 ast_log(LOG_WARNING, "Provider '%s' cannot be registered: res_phoneprov not loaded.\n", provider_name);
1551 return -1;
1552 }
1553
1555 if (provider) {
1556 ast_log(LOG_ERROR, "There is already a provider registered named '%s'.\n", provider_name);
1557 ao2_ref(provider, -1);
1558 return -1;
1559 }
1560
1562 if (!provider) {
1563 ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s'.\n", provider_name);
1564 return -1;
1565 }
1566
1568 ao2_ref(provider, -1);
1569 ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s' stringfields.\n", provider_name);
1570 return -1;
1571 }
1572
1574 provider->load_users = load_users;
1575
1577 ao2_ref(provider, -1);
1578
1579 if (provider->load_users()) {
1580 ast_log(LOG_ERROR, "Unable to load provider '%s' users. Register aborted.\n", provider_name);
1582 return -1;
1583 }
1584
1585 return 0;
1586}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
static void provider_destructor(void *obj)
void ast_phoneprov_provider_unregister(char *provider_name)
Unegisters a config provider from phoneprov and frees its resources.
static int load_users(void)
struct ao2_container * providers
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
const ast_string_field provider_name

References ao2_alloc, ao2_link, ao2_ref, ast_log, ast_phoneprov_provider_unregister(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), find_provider(), load_users(), LOG_ERROR, LOG_WARNING, provider, provider_destructor(), phoneprov_provider::provider_name, and providers.

Referenced by load_module(), load_module(), and reload_module().

◆ ast_phoneprov_provider_unregister()

void ast_phoneprov_provider_unregister ( char *  provider_name)

Unegisters a config provider from phoneprov and frees its resources.

Parameters
provider_nameThe name of the provider

Definition at line 1629 of file res_phoneprov.c.

1630{
1631 if (!providers) {
1632 return;
1633 }
1634
1635 ast_phoneprov_delete_extensions(provider_name);
1637}
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
void ast_phoneprov_delete_extensions(char *provider_name)
Deletes all extensions for this provider.

References ao2_find, ast_phoneprov_delete_extensions(), OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, user::provider_name, and providers.

Referenced by ast_phoneprov_provider_register(), reload_module(), unload_module(), and unload_module().

◆ ast_phoneprov_std_variable_lookup()

const char * ast_phoneprov_std_variable_lookup ( enum ast_phoneprov_std_variables  var)

Returns the string respresentation of a phoneprov standard variable.

Parameters
varOne of enum ast_phoneprov_std_variables
Returns
The string representation or NULL if not found.

Definition at line 1530 of file res_phoneprov.c.

1531{
1533 return NULL;
1534 }
1535
1536 return variable_lookup[var];
1537}
#define var
Definition ast_expr2f.c:605
@ AST_PHONEPROV_STD_VAR_LIST_LENGTH
Definition phoneprov.h:53

References AST_PHONEPROV_STD_VAR_LIST_LENGTH, NULL, var, and variable_lookup.

Referenced by load_endpoint(), and users_apply_handler().

◆ build_extension()

static struct extension * build_extension ( const char *  name,
struct varshead vars 
)
static

Definition at line 695 of file res_phoneprov.c.

696{
697 struct extension *exten;
698 const char *tmp;
699
700 if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
701 return NULL;
702 }
703
705
706 exten->headp = ast_var_list_clone(vars);
707 if (!exten->headp) {
708 ast_log(LOG_ERROR, "Unable to clone variables for extension '%s'\n", name);
709 delete_extension(exten);
710 return NULL;
711 }
712
714 if (!tmp) {
717 exten->index = 1;
718 } else {
719 sscanf(tmp, "%d", &exten->index);
720 }
721
725 }
726
729
730 return exten;
731}
struct varshead * ast_var_list_clone(struct varshead *head)
Definition chanvars.c:124
static const char name[]
Definition format_mp3.c:68
@ AST_PHONEPROV_STD_LINENUMBER
Definition phoneprov.h:38
@ AST_PHONEPROV_STD_TIMEZONE
Definition phoneprov.h:37
@ AST_PHONEPROV_STD_LINEKEYS
Definition phoneprov.h:39
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)
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.

References ast_calloc_with_stringfields, ast_log, AST_PHONEPROV_STD_LINEKEYS, AST_PHONEPROV_STD_LINENUMBER, AST_PHONEPROV_STD_TIMEZONE, ast_string_field_set, ast_var_assign, ast_var_find(), ast_var_list_clone(), AST_VAR_LIST_INSERT_TAIL(), delete_extension(), extension::headp, extension::index, LOG_ERROR, name, NULL, set_timezone_variables(), and variable_lookup.

Referenced by ast_phoneprov_add_extension().

◆ build_profile()

static void build_profile ( const char *  name,
struct ast_variable v 
)
static

Build a phone profile and add it to the list of phone profiles.

Parameters
namethe name of the profile
vast_variable from parsing phoneprov.conf

Definition at line 591 of file res_phoneprov.c.

592{
593 struct phone_profile *profile;
594
595 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
596 return;
597 }
598
599 if (ast_string_field_init(profile, 32)) {
600 profile = unref_profile(profile);
601 return;
602 }
603
604 if (!(profile->headp = ast_var_list_create())) {
605 profile = unref_profile(profile);
606 return;
607 }
608
611
612 ast_string_field_set(profile, name, name);
613 for (; v; v = v->next) {
614 if (!strcasecmp(v->name, "mime_type")) {
616 } else if (!strcasecmp(v->name, "setvar")) {
617 char value_copy[strlen(v->value) + 1];
618
620 AST_APP_ARG(varname);
621 AST_APP_ARG(varval);
622 );
623
624 strcpy(value_copy, v->value); /* safe */
625 AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
626 do {
627 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
628 break;
629 args.varname = ast_strip(args.varname);
630 args.varval = ast_strip(args.varval);
631 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
632 break;
633 AST_VAR_LIST_INSERT_TAIL(profile->headp, ast_var_assign(args.varname, args.varval));
634 } while (0);
635 } else if (!strcasecmp(v->name, "staticdir")) {
637 } else {
638 struct phoneprov_file *pp_file;
639 char *file_extension;
640 char value_copy[strlen(v->value) + 1];
641
643 AST_APP_ARG(filename);
644 AST_APP_ARG(mimetype);
645 );
646
647 if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
648 profile = unref_profile(profile);
649 return;
650 }
651
652 if ((file_extension = strrchr(pp_file->format, '.')))
653 file_extension++;
654
655 strcpy(value_copy, v->value); /* safe */
656 AST_STANDARD_APP_ARGS(args, value_copy);
657
658 /* Mime type order of preference
659 * 1) Specific mime-type defined for file in profile
660 * 2) Mime determined by extension
661 * 3) Default mime type specified in profile
662 * 4) text/plain
663 */
664 ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
665 (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
666
667 if (!strcasecmp(v->name, "static_file")) {
668 ast_string_field_set(pp_file, format, args.filename);
669 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
670 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
671 /* Add a route for the static files, as their filenames won't change per-user */
672 build_route(pp_file, profile, NULL, NULL);
673 } else {
674 ast_string_field_set(pp_file, format, v->name);
675 ast_string_field_set(pp_file, template, args.filename);
676 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
677 }
678 }
679 }
680
681 ao2_link(profiles, profile);
682
683 profile = unref_profile(profile);
684}
struct varshead * ast_var_list_create(void)
Definition chanvars.c:97
const char * ast_http_ftype2mtype(const char *ftype) attribute_pure
Return mime type based on extension.
Definition http.c:219
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
static void profile_destructor(void *obj)
static struct phone_profile * unref_profile(struct phone_profile *prof)
struct ao2_container * profiles
static void build_route(struct phoneprov_file *pp_file, struct phone_profile *profile, struct user *user, char *uri)
Build a route structure and add it to the list of available http routes.
static struct @519 args
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition strings.h:223
struct ast_variable * next
const ast_string_field staticdir
struct phone_profile::@484 static_files
struct phone_profile::@485 dynamic_files
const ast_string_field default_mime_type
structure to hold file data
const ast_string_field mime_type
struct phoneprov_file::@482 entry
const ast_string_field format

References ao2_alloc, ao2_link, args, AST_APP_ARG, ast_calloc_with_stringfields, AST_DECLARE_APP_ARGS, ast_http_ftype2mtype(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, 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, ast_var_list_create(), AST_VAR_LIST_INSERT_TAIL(), build_route(), phone_profile::default_mime_type, phone_profile::dynamic_files, phoneprov_file::entry, phoneprov_file::format, phone_profile::headp, phoneprov_file::mime_type, name, ast_variable::name, ast_variable::next, NULL, profile_destructor(), profiles, S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), and ast_variable::value.

Referenced by load_common().

◆ build_route()

static void build_route ( struct phoneprov_file pp_file,
struct phone_profile profile,
struct user user,
char *  uri 
)
static

Build a route structure and add it to the list of available http routes.

Parameters
pp_fileFile to link to the route
profile
userUser to link to the route (NULL means static route)
uriURI of the route

Definition at line 518 of file res_phoneprov.c.

519{
520 struct http_route *route;
521
522 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
523 return;
524 }
525
526 if (ast_string_field_init(route, 32)) {
527 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
528 route = unref_route(route);
529 return;
530 }
531
532 ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
533 route->user = user;
534 route->file = pp_file;
535 route->profile = profile;
536
537 ao2_link(http_routes, route);
538
539 route = unref_route(route);
540}
struct ao2_container * http_routes
static void route_destructor(void *obj)
static struct http_route * unref_route(struct http_route *route)
structure to hold http routes (valid URIs, and the files they link to)
const ast_string_field uri
struct phone_profile * profile
struct phoneprov_file * file
struct user * user

References ao2_alloc, ao2_link, ast_log, ast_string_field_init, ast_string_field_set, http_route::file, phoneprov_file::format, http_routes, LOG_ERROR, http_route::profile, route_destructor(), S_OR, unref_route(), http_route::uri, and http_route::user.

Referenced by build_profile(), and build_user_routes().

◆ build_user()

static struct user * build_user ( const char *  mac,
struct phone_profile profile,
char *  provider_name 
)
static

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

Definition at line 790 of file res_phoneprov.c.

791{
792 struct user *user;
793
794 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
795 return NULL;
796 }
797
798 if (ast_string_field_init(user, 64)) {
800 return NULL;
801 }
802
806 ao2_ref(profile, 1);
807
808 return user;
809}
static void user_destructor(void *obj)
Free all memory associated with a user.
static struct user * unref_user(struct user *user)

References ao2_alloc, ao2_ref, ast_string_field_init, ast_string_field_set, user::macaddress, NULL, user::profile, user::provider_name, unref_user(), and user_destructor().

Referenced by ast_phoneprov_add_extension().

◆ build_user_routes()

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

858{
859 struct phoneprov_file *pp_file;
860 struct ast_str *str;
861
862 if (!(str = ast_str_create(16))) {
863 return -1;
864 }
865
866 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
869 }
870
871 ast_free(str);
872 return 0;
873}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.

References ast_free, AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_str_buffer(), ast_str_create, ast_str_substitute_variables_varshead(), build_route(), phone_profile::dynamic_files, user::extensions, phoneprov_file::format, user::profile, and str.

Referenced by ast_phoneprov_add_extension().

◆ delete_extension()

static struct extension * delete_extension ( struct extension exten)
static

Definition at line 686 of file res_phoneprov.c.

687{
690 ast_free(exten);
691
692 return NULL;
693}
void ast_var_list_destroy(struct varshead *head)
Definition chanvars.c:109
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

References ast_free, ast_string_field_free_memory, ast_var_list_destroy(), extension::headp, and NULL.

Referenced by ast_phoneprov_add_extension(), build_extension(), and user_destructor().

◆ delete_file()

static void delete_file ( struct phoneprov_file file)
static

Definition at line 398 of file res_phoneprov.c.

399{
401 ast_free(file);
402}

References ast_free, and ast_string_field_free_memory.

Referenced by profile_destructor().

◆ delete_profiles()

static void delete_profiles ( void  )
static

Delete all phone profiles, freeing their memory.

Definition at line 578 of file res_phoneprov.c.

579{
580 if (!profiles) {
581 return;
582 }
583
585}

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and profiles.

Referenced by reload(), and unload_module().

◆ delete_providers()

static void delete_providers ( void  )
static

Delete all providers.

Definition at line 383 of file res_phoneprov.c.

384{
385 if (!providers) {
386 return;
387 }
388
390}

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and providers.

Referenced by unload_module().

◆ delete_routes()

static void delete_routes ( void  )
static

Delete all http routes, freeing their memory.

Definition at line 503 of file res_phoneprov.c.

504{
505 if (!http_routes) {
506 return;
507 }
508
510}

References ao2_callback, http_routes, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by reload(), and unload_module().

◆ delete_users()

static void delete_users ( void  )
static

Delete all users.

Definition at line 780 of file res_phoneprov.c.

781{
782 if (!users) {
783 return;
784 }
785
787}

References ao2_callback, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by reload(), and unload_module().

◆ extension_delete_cb()

static int extension_delete_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 1598 of file res_phoneprov.c.

1599{
1600 struct user *user = obj;
1601 char *provider_name = data;
1602 char *macaddress = arg;
1603
1604 if (!strcmp(user->provider_name, provider_name) && !strcasecmp(user->macaddress, macaddress)) {
1605 return CMP_MATCH;
1606 }
1607 return 0;
1608}

References CMP_MATCH, user::macaddress, and user::provider_name.

Referenced by ast_phoneprov_delete_extension().

◆ extensions_delete_cb()

static int extensions_delete_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1588 of file res_phoneprov.c.

1589{
1590 char *provider_name = arg;
1591 struct user *user = obj;
1592 if (strcmp(user->provider_name, provider_name)) {
1593 return 0;
1594 }
1595 return CMP_MATCH;
1596}

References CMP_MATCH, phoneprov_provider::provider_name, and user::provider_name.

Referenced by ast_phoneprov_delete_extensions().

◆ find_profile()

static struct phone_profile * find_profile ( const char *  name)
static

Return a phone profile looked up by name.

Definition at line 550 of file res_phoneprov.c.

551{
553}

References ao2_find, name, OBJ_SEARCH_KEY, and profiles.

Referenced by ast_phoneprov_add_extension().

◆ find_provider()

static struct phoneprov_provider * find_provider ( char *  name)
static

Definition at line 377 of file res_phoneprov.c.

378{
380}

References ao2_find, name, OBJ_SEARCH_KEY, and providers.

Referenced by ast_phoneprov_add_extension(), and ast_phoneprov_provider_register().

◆ find_user()

static struct user * find_user ( const char *  macaddress)
static

Return a user looked up by name.

Definition at line 741 of file res_phoneprov.c.

742{
743 return ao2_find(users, macaddress, OBJ_SEARCH_KEY);
744}

References ao2_find, user::macaddress, and OBJ_SEARCH_KEY.

Referenced by ast_phoneprov_add_extension(), and pp_each_extension_helper().

◆ get_defaults()

static struct varshead * get_defaults ( void  )
static

Definition at line 1221 of file res_phoneprov.c.

1222{
1223 struct ast_config *phoneprov_cfg, *cfg = CONFIG_STATUS_FILEINVALID;
1224 const char *value;
1225 struct ast_variable *v;
1226 struct ast_var_t *var;
1227 struct ast_flags config_flags = { 0 };
1228 struct varshead *defaults = ast_var_list_create();
1229
1230 if (!defaults) {
1231 ast_log(LOG_ERROR, "Unable to create default var list.\n");
1232 return NULL;
1233 }
1234
1235 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1236 || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1237 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1238 ast_var_list_destroy(defaults);
1239 return NULL;
1240 }
1241
1243 if (!value) {
1244 struct in_addr addr;
1246 if (value) {
1247 lookup_iface(value, &addr);
1248 value = ast_inet_ntoa(addr);
1249 }
1250 }
1251 if (value) {
1253 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1254 } else {
1255 ast_log(LOG_WARNING, "Unable to find a valid server address or name.\n");
1256 }
1257
1260 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) {
1261 ast_config_destroy(cfg);
1262 }
1263 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1264
1266 if (!value) {
1267 ast_log(LOG_ERROR, "Unable to load default profile.\n");
1268 ast_config_destroy(phoneprov_cfg);
1269 ast_var_list_destroy(defaults);
1270 return NULL;
1271 }
1273 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1274 ast_config_destroy(phoneprov_cfg);
1275
1276 if (!(cfg = ast_config_load("phoneprov_users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
1277 ast_log(LOG_ERROR, "Unable to load phoneprov_users.conf\n");
1278 ast_var_list_destroy(defaults);
1279 return NULL;
1280 }
1281
1282 /* Go ahead and load global variables from phoneprov_users.conf so we can append to profiles */
1283 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
1286 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1287 }
1290 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1291 }
1292 }
1293 ast_config_destroy(cfg);
1294
1295 return defaults;
1296}
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition utils.c:964
@ AST_PHONEPROV_STD_SERVER_IFACE
Definition phoneprov.h:42
@ AST_PHONEPROV_STD_SERVER_PORT
Definition phoneprov.h:41
@ AST_PHONEPROV_STD_SERVER
Definition phoneprov.h:40
@ AST_PHONEPROV_STD_EXTENSION_LENGTH
Definition phoneprov.h:44
@ AST_PHONEPROV_STD_VOICEMAIL_EXTEN
Definition phoneprov.h:43
static const char * pp_general_lookup[]
static const char * pp_user_lookup[]
static int lookup_iface(const char *iface, struct in_addr *address)
Structure used to handle boolean flags.
Definition utils.h:220
Structure for variables, used for configurations and for channel variables.
int value
Definition syslog.c:37

References ast_config_destroy(), ast_config_load, ast_inet_ntoa(), ast_log, AST_PHONEPROV_STD_EXTENSION_LENGTH, AST_PHONEPROV_STD_PROFILE, AST_PHONEPROV_STD_SERVER, AST_PHONEPROV_STD_SERVER_IFACE, AST_PHONEPROV_STD_SERVER_PORT, AST_PHONEPROV_STD_VOICEMAIL_EXTEN, ast_var_assign, ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, LOG_WARNING, lookup_iface(), ast_variable::name, ast_variable::next, NULL, pp_general_lookup, pp_user_lookup, S_OR, ast_variable::value, value, var, and variable_lookup.

Referenced by load_users().

◆ handle_show_routes()

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

1180{
1181 int fd = a->fd;
1182 switch(cmd) {
1183 case CLI_INIT:
1184 e->command = "phoneprov show routes";
1185 e->usage =
1186 "Usage: phoneprov show routes\n"
1187 " Lists all registered phoneprov http routes.\n";
1188 return NULL;
1189 case CLI_GENERATE:
1190 return NULL;
1191 }
1192
1193 /* This currently iterates over routes twice, but it is the only place I've needed
1194 * to really separate static an dynamic routes, so I've just left it this way. */
1195 ast_cli(a->fd, "Static routes\n\n");
1196 ast_cli(a->fd, FORMATS, "Profile", "Relative URI", "Physical location");
1197
1199
1200 ast_cli(a->fd, "\nDynamic routes\n\n");
1201 ast_cli(a->fd, FORMATD, "Provider", "Profile", "Relative URI", "Template");
1202
1204
1205 return CLI_SUCCESS;
1206}
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define FORMATS
static int route_list_cb(void *obj, void *arg, void *data, int flags)
#define FORMATD
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
static struct test_val a

References a, ao2_callback_data, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, FORMATD, FORMATS, http_routes, NULL, OBJ_MULTIPLE, OBJ_NODATA, route_list_cb(), and ast_cli_entry::usage.

◆ load_common()

static int load_common ( void  )
static

Definition at line 1368 of file res_phoneprov.c.

1369{
1370 struct ast_config *phoneprov_cfg;
1371 struct ast_flags config_flags = { 0 };
1372 char *cat;
1373
1374 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1375 || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1376 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1377 return -1;
1378 }
1379
1380 cat = NULL;
1381 while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
1382 if (!strcasecmp(cat, "general")) {
1383 continue;
1384 }
1385 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
1386 }
1387 ast_config_destroy(phoneprov_cfg);
1388
1390 ast_log(LOG_ERROR, "There are no provisioning profiles in phoneprov.conf.\n");
1391 return -1;
1392 }
1393
1394 return 0;
1395}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition extconf.c:3324
static void build_profile(const char *name, struct ast_variable *v)
Build a phone profile and add it to the list of phone profiles.

References ao2_container_count(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, ast_variable_browse(), build_profile(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, NULL, and profiles.

Referenced by load_module(), and reload().

◆ load_file()

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

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

Definition at line 405 of file res_phoneprov.c.

406{
407 int len = 0;
408 FILE *f;
409
410 if (!(f = fopen(filename, "r"))) {
411 *ret = NULL;
412 return -1;
413 }
414
415 fseek(f, 0, SEEK_END);
416 len = ftell(f);
417 fseek(f, 0, SEEK_SET);
418 if (!(*ret = ast_malloc(len + 1))) {
419 fclose(f);
420 return -2;
421 }
422
423 if (len != fread(*ret, sizeof(char), len, f)) {
424 fclose(f);
425 ast_free(*ret);
426 *ret = NULL;
427 return -3;
428 }
429
430 fclose(f);
431
432 (*ret)[len] = '\0';
433
434 return len;
435}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References ast_free, ast_malloc, len(), and NULL.

Referenced by make_ari_stubs::main(), phoneprov_callback(), and pp_each_extension_helper().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1434 of file res_phoneprov.c.

1435{
1437 phone_profile_hash_fn, NULL, phone_profile_cmp_fn);
1438 if (!profiles) {
1439 ast_log(LOG_ERROR, "Unable to allocate profiles container.\n");
1441 }
1442
1444 http_route_hash_fn, NULL, http_route_cmp_fn);
1445 if (!http_routes) {
1446 ast_log(LOG_ERROR, "Unable to allocate routes container.\n");
1447 goto error;
1448 }
1449
1450 if (load_common()) {
1451 ast_log(LOG_ERROR, "Unable to load provisioning profiles.\n");
1452 goto error;
1453 }
1454
1456 user_hash_fn, NULL, user_cmp_fn);
1457 if (!users) {
1458 ast_log(LOG_ERROR, "Unable to allocate users container.\n");
1459 goto error;
1460 }
1461
1463 MAX_PROVIDER_BUCKETS, phoneprov_provider_hash_fn, NULL, phoneprov_provider_cmp_fn);
1464 if (!providers) {
1465 ast_log(LOG_ERROR, "Unable to allocate providers container.\n");
1466 goto error;
1467 }
1468
1469 /* Register ourselves as the provider for phoneprov_users.conf */
1471 ast_log(LOG_WARNING, "Unable register users config provider. Others may succeed.\n");
1472 }
1473
1475
1479
1481
1482error:
1483 unload_module();
1485}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
Definition http.c:689
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562
#define MAX_USER_BUCKETS
#define MAX_ROUTE_BUCKETS
#define MAX_PROFILE_BUCKETS
#define MAX_PROVIDER_BUCKETS
static struct ast_custom_function pp_each_extension_function
static int load_common(void)
static struct ast_cli_entry pp_cli[]
static struct ast_custom_function pp_each_user_function
static struct ast_http_uri phoneprovuri
#define SIPUSERS_PROVIDER_NAME
static int unload_module(void)
int ast_phoneprov_provider_register(char *provider_name, ast_phoneprov_load_users_cb load_users)
Registers a config provider to phoneprov.
int error(const char *format,...)
#define ARRAY_LEN(a)
Definition utils.h:706

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ARRAY_LEN, ast_cli_register_multiple, ast_custom_function_register, ast_http_uri_link(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_phoneprov_provider_register(), error(), http_routes, load_common(), load_users(), LOG_ERROR, LOG_WARNING, MAX_PROFILE_BUCKETS, MAX_PROVIDER_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, NULL, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profiles, providers, SIPUSERS_PROVIDER_NAME, and unload_module().

◆ load_users()

static int load_users ( void  )
static

Definition at line 1298 of file res_phoneprov.c.

1299{
1300 struct ast_config *cfg;
1301 char *cat;
1302 const char *value;
1303 struct ast_flags config_flags = { 0 };
1304 struct varshead *defaults = get_defaults();
1305
1306 if (!defaults) {
1307 ast_log(LOG_WARNING, "Unable to load default variables.\n");
1308 return -1;
1309 }
1310
1311 if (!(cfg = ast_config_load("phoneprov_users.conf", config_flags))
1312 || cfg == CONFIG_STATUS_FILEINVALID) {
1313 ast_log(LOG_WARNING, "Unable to load phoneprov_users.conf\n");
1314 ast_var_list_destroy(defaults);
1315 return -1;
1316 }
1317
1318 cat = NULL;
1319 while ((cat = ast_category_browse(cfg, cat))) {
1320 const char *tmp;
1321 int i;
1322 struct ast_var_t *varx;
1323 struct ast_var_t *vard;
1324
1325 if (strcasecmp(cat, "general") && strcasecmp(cat, "authentication")) {
1326 struct varshead *variables = ast_var_list_create();
1327
1328 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) {
1329 ast_var_list_destroy(variables);
1330 continue;
1331 }
1332
1333 /* Transfer the standard variables */
1334 for (i = 0; i < AST_PHONEPROV_STD_VAR_LIST_LENGTH; i++) {
1335 if (pp_user_lookup[i]) {
1337 if (value) {
1339 value);
1340 AST_VAR_LIST_INSERT_TAIL(variables, varx);
1341 }
1342 }
1343 }
1344
1346 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
1347 ast_var_list_destroy(variables);
1348 continue;
1349 }
1350
1351 /* Apply defaults */
1352 AST_VAR_LIST_TRAVERSE(defaults, vard) {
1353 if (ast_var_find(variables, vard->name)) {
1354 continue;
1355 }
1356 varx = ast_var_assign(vard->name, vard->value);
1357 AST_VAR_LIST_INSERT_TAIL(variables, varx);
1358 }
1359
1361 }
1362 }
1363 ast_config_destroy(cfg);
1364 ast_var_list_destroy(defaults);
1365 return 0;
1366}
int ast_phoneprov_add_extension(char *provider_name, struct varshead *vars)
Adds an extension.
static struct varshead * get_defaults(void)
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2235

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, ast_phoneprov_add_extension(), AST_PHONEPROV_STD_MAC, AST_PHONEPROV_STD_VAR_LIST_LENGTH, ast_true(), ast_var_assign, ast_var_find(), ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), AST_VAR_LIST_TRAVERSE, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, get_defaults(), LOG_WARNING, ast_var_t::name, NULL, pp_user_lookup, SIPUSERS_PROVIDER_NAME, ast_var_t::value, value, and variable_lookup.

Referenced by actual_load_config(), ast_phoneprov_provider_register(), and load_module().

◆ lookup_iface()

static int lookup_iface ( const char *  iface,
struct in_addr *  address 
)
static

Definition at line 347 of file res_phoneprov.c.

348{
349 int mysock, res = 0;
350 struct ifreq ifr;
351 struct sockaddr_in *sin;
352
353 memset(&ifr, 0, sizeof(ifr));
354 ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
355
356 mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
357 if (mysock < 0) {
358 ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
359 return -1;
360 }
361
362 res = ioctl(mysock, SIOCGIFADDR, &ifr);
363
364 close(mysock);
365
366 if (res < 0) {
367 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
368 memcpy(address, &__ourip, sizeof(__ourip));
369 return -1;
370 } else {
371 sin = (struct sockaddr_in *)&ifr.ifr_addr;
372 memcpy(address, &sin->sin_addr, sizeof(*address));
373 return 0;
374 }
375}
char * address
Definition f2c.h:59
int errno
static struct in_addr __ourip
for use in lookup_iface
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425

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

Referenced by get_defaults().

◆ phoneprov_callback()

static int phoneprov_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_vars,
struct ast_variable headers 
)
static

Callback that is executed everytime an http request is received by this module.

Definition at line 876 of file res_phoneprov.c.

877{
878 struct http_route *route;
879 struct ast_str *result;
880 char path[PATH_MAX];
881 char *file = NULL;
882 char *server;
883 char *newserver = NULL;
884 struct extension *exten_iter;
885 int len;
886 int fd;
887 struct ast_str *http_header;
888
890 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
891 return 0;
892 }
893
894 if (!(route = ao2_find(http_routes, uri, OBJ_SEARCH_KEY))) {
895 goto out404;
896 }
897
898 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
899
900 if (!route->user) { /* Static file */
901
902 fd = open(path, O_RDONLY);
903 if (fd < 0) {
904 goto out500;
905 }
906
907 len = lseek(fd, 0, SEEK_END);
908 lseek(fd, 0, SEEK_SET);
909 if (len < 0) {
910 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
911 close(fd);
912 goto out500;
913 }
914
915 http_header = ast_str_create(80);
916 ast_str_set(&http_header, 0, "Content-type: %s\r\n",
917 route->file->mime_type);
918
919 ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
920
921 close(fd);
922 route = unref_route(route);
923 return 0;
924 } else { /* Dynamic file */
925 struct ast_str *tmp;
926
927 len = load_file(path, &file);
928 if (len < 0) {
929 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
930 if (file) {
931 ast_free(file);
932 }
933
934 goto out500;
935 }
936
937 if (!file) {
938 goto out500;
939 }
940
941 if (!(tmp = ast_str_create(len))) {
942 if (file) {
943 ast_free(file);
944 }
945
946 goto out500;
947 }
948
949 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
950 * the IP address we are listening on that the phone contacted for this config file */
951
952 server = ast_var_find(AST_LIST_FIRST(&route->user->extensions)->headp,
954
955 if (!server) {
956 union {
957 struct sockaddr sa;
958 struct sockaddr_in sa_in;
959 } name;
960 socklen_t namelen = sizeof(name.sa);
961 int res;
962
963 if ((res = getsockname(ast_iostream_get_fd(ser->stream), &name.sa, &namelen))) {
964 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
965 } else {
966 newserver = ast_strdupa(ast_inet_ntoa(name.sa_in.sin_addr));
967
968 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
971 }
972 }
973 }
974
976
977 /* Do not retain dynamic SERVER address because next request from the phone might arrive on
978 * different interface IP address eg. if this is a multi-homed server on multiple subnets */
979 if (newserver) {
980 struct ast_var_t *varns;
981 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
982 AST_LIST_TRAVERSE_SAFE_BEGIN(exten_iter->headp, varns, entries) {
985 ast_var_delete(varns);
986 }
987 }
989 }
990 }
991
992 ast_free(file);
993
994 http_header = ast_str_create(80);
995 ast_str_set(&http_header, 0, "Content-type: %s\r\n",
996 route->file->mime_type);
997
998 if (!(result = ast_str_create(512))) {
999 ast_log(LOG_ERROR, "Could not create result string!\n");
1000 if (tmp) {
1001 ast_free(tmp);
1002 }
1003 ast_free(http_header);
1004 goto out500;
1005 }
1006 ast_str_append(&result, 0, "%s", ast_str_buffer(tmp));
1007
1008 ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
1009 ast_free(tmp);
1010
1011 route = unref_route(route);
1012
1013 return 0;
1014 }
1015
1016out404:
1017 ast_http_error(ser, 404, "Not Found", uri);
1018 return 0;
1019
1020out500:
1021 route = unref_route(route);
1022 ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
1023 return 0;
1024}
#define PATH_MAX
Definition asterisk.h:40
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
static PGresult * result
Definition cel_pgsql.c:84
const char * ast_var_name(const struct ast_var_t *var)
Definition chanvars.c:60
void ast_var_delete(struct ast_var_t *var)
Definition extconf.c:2469
void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition http.c:472
@ AST_HTTP_GET
Definition http.h:60
@ AST_HTTP_HEAD
Definition http.h:62
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
Definition http.c:664
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
Definition iostream.c:85
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
const char * ast_config_AST_DATA_DIR
Definition options.c:159
static int load_file(const char *filename, char **ret)
Read a TEXT file into a string and return the length.
const char * method
Definition res_pjsip.c:1279
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
struct ast_iostream * stream
Definition tcptls.h:162
struct ast_var_t::@224 entries
const ast_string_field template

References ao2_find, ast_config_AST_DATA_DIR, ast_free, ast_http_error(), AST_HTTP_GET, AST_HTTP_HEAD, ast_http_send(), ast_inet_ntoa(), ast_iostream_get_fd(), AST_LIST_FIRST, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, AST_PHONEPROV_STD_SERVER, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_substitute_variables_varshead(), ast_strdupa, ast_var_assign, ast_var_delete(), ast_var_find(), AST_VAR_LIST_INSERT_TAIL(), ast_var_name(), ast_var_t::entries, user::extensions, http_route::file, extension::headp, http_routes, len(), load_file(), LOG_ERROR, LOG_WARNING, method, phoneprov_file::mime_type, name, NULL, OBJ_SEARCH_KEY, PATH_MAX, result, ast_tcptls_session_instance::stream, phoneprov_file::template, unref_route(), http_route::user, and variable_lookup.

◆ pp_each_extension_helper()

static int pp_each_extension_helper ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
struct ast_str **  bufstr,
int  len 
)
static

A dialplan function that can be used to output a template for each extension attached to a user.

Definition at line 1084 of file res_phoneprov.c.

1085{
1086 struct user *user;
1087 struct extension *exten;
1088 char path[PATH_MAX];
1089 char *file;
1090 int filelen;
1091 struct ast_str *str;
1093 AST_APP_ARG(mac);
1094 AST_APP_ARG(template);
1095 );
1096
1098
1099 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
1100 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requires both a macaddress and template filename.\n");
1101 return 0;
1102 }
1103
1104 if (!(user = find_user(args.mac))) {
1105 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
1106 return 0;
1107 }
1108
1109 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
1110 filelen = load_file(path, &file);
1111 if (filelen < 0) {
1112 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
1113 if (file) {
1114 ast_free(file);
1115 }
1116 return 0;
1117 }
1118
1119 if (!file) {
1120 return 0;
1121 }
1122
1123 if (!(str = ast_str_create(filelen))) {
1124 return 0;
1125 }
1126
1127 AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
1129 if (buf) {
1130 size_t slen = len;
1131 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1132 } else {
1133 ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1134 }
1135 }
1136
1137 ast_free(file);
1138 ast_free(str);
1139
1140 user = unref_user(user);
1141
1142 return 0;
1143}
char buf[BUFSIZE]
Definition eagi_proxy.c:66
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition utils.c:2203

References args, AST_APP_ARG, ast_build_string(), ast_config_AST_DATA_DIR, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_substitute_variables_varshead(), ast_strlen_zero(), buf, user::extensions, find_user(), extension::headp, len(), load_file(), LOG_WARNING, PATH_MAX, str, and unref_user().

Referenced by pp_each_extension_read(), and pp_each_extension_read2().

◆ pp_each_extension_read()

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

Definition at line 1145 of file res_phoneprov.c.

1146{
1147 return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
1148}
static int pp_each_extension_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len)
A dialplan function that can be used to output a template for each extension attached to a user.

References buf, len(), NULL, and pp_each_extension_helper().

◆ pp_each_extension_read2()

static int pp_each_extension_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
)
static

Definition at line 1150 of file res_phoneprov.c.

1151{
1152 return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
1153}

References buf, len(), NULL, and pp_each_extension_helper().

◆ pp_each_user_helper()

static int pp_each_user_helper ( struct ast_channel chan,
char *  data,
char *  buf,
struct ast_str **  bufstr,
int  len 
)
static

A dialplan function that can be used to print a string for each phoneprov user.

Definition at line 1027 of file res_phoneprov.c.

1028{
1029 char *tmp;
1030 struct ao2_iterator i;
1031 struct user *user;
1032 struct ast_str *str;
1034 AST_APP_ARG(string);
1035 AST_APP_ARG(exclude_mac);
1036 );
1038
1039 if (!(str = ast_str_create(16))) {
1040 return -1;
1041 }
1042
1043 /* Fix data by turning %{ into ${ */
1044 while ((tmp = strstr(args.string, "%{")))
1045 *tmp = '$';
1046
1047 i = ao2_iterator_init(users, 0);
1048 while ((user = ao2_iterator_next(&i))) {
1049 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
1050 continue;
1051 }
1053 if (buf) {
1054 size_t slen = len;
1055 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1056 } else {
1057 ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1058 }
1059 user = unref_user(user);
1060 }
1062
1063 ast_free(str);
1064 return 0;
1065}
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, args, AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, ast_free, AST_LIST_FIRST, AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_substitute_variables_varshead(), ast_strlen_zero(), buf, user::extensions, len(), user::macaddress, str, and unref_user().

Referenced by pp_each_user_read(), and pp_each_user_read2().

◆ pp_each_user_read()

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

Definition at line 1067 of file res_phoneprov.c.

1068{
1069 return pp_each_user_helper(chan, data, buf, NULL, len);
1070}
static int pp_each_user_helper(struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len)
A dialplan function that can be used to print a string for each phoneprov user.

References buf, len(), NULL, and pp_each_user_helper().

◆ pp_each_user_read2()

static int pp_each_user_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
)
static

Definition at line 1072 of file res_phoneprov.c.

1073{
1074 return pp_each_user_helper(chan, data, NULL, buf, len);
1075}

References buf, len(), NULL, and pp_each_user_helper().

◆ profile_destructor()

static void profile_destructor ( void *  obj)
static

Definition at line 555 of file res_phoneprov.c.

556{
557 struct phone_profile *profile = obj;
558 struct phoneprov_file *file;
559 struct ast_var_t *var;
560
561 while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) {
562 delete_file(file);
563 }
564
565 while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) {
566 delete_file(file);
567 }
568
569 while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) {
571 }
572
573 ast_free(profile->headp);
575}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static void delete_file(struct phoneprov_file *file)

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

◆ provider_destructor()

static void provider_destructor ( void *  obj)
static

Definition at line 392 of file res_phoneprov.c.

References ast_string_field_free_memory, and provider.

Referenced by ast_phoneprov_provider_register().

◆ reload()

static int reload ( void  )
static

Definition at line 1487 of file res_phoneprov.c.

1488{
1489 struct ao2_iterator i;
1491
1492 /* Clean everything except the providers */
1493 delete_routes();
1494 delete_users();
1496
1497 /* Reload the profiles */
1498 if (load_common()) {
1499 ast_log(LOG_ERROR, "Unable to reload provisioning profiles.\n");
1500 unload_module();
1502 }
1503
1504 /* For each provider, reload the users */
1507 for(; (provider = ao2_iterator_next(&i)); ao2_ref(provider, -1)) {
1508 if (provider->load_users()) {
1509 ast_log(LOG_ERROR, "Unable to load provider '%s' users. Reload aborted.\n", provider->provider_name);
1510 continue;
1511 }
1512 }
1515
1517}
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
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.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, delete_profiles(), delete_routes(), delete_users(), load_common(), LOG_ERROR, provider, providers, and unload_module().

◆ route_destructor()

static void route_destructor ( void *  obj)
static

Definition at line 495 of file res_phoneprov.c.

496{
497 struct http_route *route = obj;
498
500}

References ast_string_field_free_memory.

Referenced by build_route().

◆ route_list_cb()

static int route_list_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 1163 of file res_phoneprov.c.

1164{
1165 int fd = *(int *)arg;
1166 struct http_route *route = obj;
1167
1168 if (data && route->user) {
1169 ast_cli(fd, FORMATD, route->user->provider_name, route->profile->name, route->uri, route->file->template);
1170 }
1171 if (!data && !route->user) {
1172 ast_cli(fd, FORMATS, route->profile->name, route->uri, route->file->template);
1173 }
1174
1175 return CMP_MATCH;
1176}
const ast_string_field name

References ast_cli(), CMP_MATCH, http_route::file, FORMATD, FORMATS, phone_profile::name, http_route::profile, user::provider_name, phoneprov_file::template, http_route::uri, and http_route::user.

Referenced by handle_show_routes().

◆ routes_delete_cb()

static int routes_delete_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 746 of file res_phoneprov.c.

747{
748 struct http_route *route = obj;
749 struct user *user = route->user;
750 char *macaddress = arg;
751
752 if (user && !strcmp(user->macaddress, macaddress)) {
753 return CMP_MATCH;
754 }
755 return 0;
756}

References CMP_MATCH, user::macaddress, and http_route::user.

Referenced by user_destructor().

◆ set_timezone_variables()

static void set_timezone_variables ( struct varshead headp,
const char *  zone 
)
static

Set all timezone-related variables based on a zone (i.e. America/New_York)

Parameters
headppointer to list of user variables
zoneA time zone. NULL sets variables based on timezone of the machine

Definition at line 441 of file res_phoneprov.c.

442{
443 time_t utc_time;
444 int dstenable;
445 time_t dststart;
446 time_t dstend;
447 struct ast_tm tm_info;
448 int tzoffset;
449 char buffer[21];
450 struct timeval when;
451
452 time(&utc_time);
453 ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
454 snprintf(buffer, sizeof(buffer), "%d", tzoffset);
455 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("TZOFFSET", buffer));
456
457 if (!dstenable) {
458 return;
459 }
460
461 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_ENABLE", "1"));
462
463 when.tv_sec = dststart;
464 ast_localtime(&when, &tm_info, zone);
465
466 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
467 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MONTH", buffer));
468
469 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
470 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MDAY", buffer));
471
472 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
473 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_HOUR", buffer));
474
475 when.tv_sec = dstend;
476 ast_localtime(&when, &tm_info, zone);
477
478 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
479 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MONTH", buffer));
480
481 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
482 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MDAY", buffer));
483
484 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
485 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_HOUR", buffer));
486}
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition localtime.c:1739
void ast_get_dst_info(const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone)
Definition localtime.c:1754

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

Referenced by build_extension().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1397 of file res_phoneprov.c.

1398{
1403
1404 /* This cleans up the phoneprov_users.conf provider (called specifically for clarity) */
1406
1407 /* This cleans up the framework which also cleans up the providers. */
1410 profiles = NULL;
1411 delete_routes();
1412 delete_users();
1414 http_routes = NULL;
1416 users = NULL;
1419 providers = NULL;
1420
1421 return 0;
1422}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
Definition http.c:721
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static void delete_providers(void)
Delete all providers.

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_http_uri_unlink(), ast_phoneprov_provider_unregister(), delete_profiles(), delete_providers(), delete_routes(), delete_users(), http_routes, NULL, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profiles, providers, and SIPUSERS_PROVIDER_NAME.

Referenced by load_module(), and reload().

◆ unref_profile()

static struct phone_profile * unref_profile ( struct phone_profile prof)
static

Definition at line 542 of file res_phoneprov.c.

543{
544 ao2_cleanup(prof);
545
546 return NULL;
547}

References ao2_cleanup, and NULL.

Referenced by build_profile(), and user_destructor().

◆ unref_route()

static struct http_route * unref_route ( struct http_route route)
static

Definition at line 488 of file res_phoneprov.c.

489{
490 ao2_cleanup(route);
491
492 return NULL;
493}

References ao2_cleanup, and NULL.

Referenced by build_route(), and phoneprov_callback().

◆ unref_user()

static struct user * unref_user ( struct user user)
static

Definition at line 733 of file res_phoneprov.c.

734{
736
737 return NULL;
738}

References ao2_cleanup, and NULL.

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

◆ user_destructor()

static void user_destructor ( void *  obj)
static

Free all memory associated with a user.

Definition at line 759 of file res_phoneprov.c.

760{
761 struct user *user = obj;
762 struct extension *exten;
763
764 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
765 exten = delete_extension(exten);
766 }
767
768 if (user->profile) {
770 }
771
772 if (http_routes) {
774 }
775
777}
static int routes_delete_cb(void *obj, void *arg, int flags)

References ao2_callback, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), extension::entry, user::extensions, http_routes, user::macaddress, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, user::profile, routes_delete_cb(), and unref_profile().

Referenced by build_user().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "HTTP Phone Provisioning" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .requires = "http", }
static

Definition at line 1526 of file res_phoneprov.c.

◆ __ourip

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

for use in lookup_iface

Definition at line 269 of file res_phoneprov.c.

269{ .s_addr = 0x00000000, };

Referenced by lookup_iface().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1526 of file res_phoneprov.c.

◆ http_routes

struct ao2_container* http_routes

◆ phoneprovuri

struct ast_http_uri phoneprovuri
static

Definition at line 1212 of file res_phoneprov.c.

1212 {
1213 .callback = phoneprov_callback,
1214 .description = "Asterisk HTTP Phone Provisioning Tool",
1215 .uri = "phoneprov",
1216 .has_subtree = 1,
1217 .data = NULL,
1218 .key = __FILE__,
1219};
static int phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
Callback that is executed everytime an http request is received by this module.

Referenced by load_module(), and unload_module().

◆ pp_cli

struct ast_cli_entry pp_cli[]
static
Initial value:
= {
{ .handler = handle_show_routes , .summary = "Show registered phoneprov http routes" ,},
}
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.

Definition at line 1208 of file res_phoneprov.c.

1208 {
1209 AST_CLI_DEFINE(handle_show_routes, "Show registered phoneprov http routes"),
1210};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ pp_each_extension_function

struct ast_custom_function pp_each_extension_function
static
Initial value:
= {
.name = "PP_EACH_EXTENSION",
}
static int pp_each_extension_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int pp_each_extension_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)

Definition at line 1155 of file res_phoneprov.c.

1155 {
1156 .name = "PP_EACH_EXTENSION",
1157 .read = pp_each_extension_read,
1158 .read2 = pp_each_extension_read2,
1159};

Referenced by load_module(), and unload_module().

◆ pp_each_user_function

struct ast_custom_function pp_each_user_function
static
Initial value:
= {
.name = "PP_EACH_USER",
}
static int pp_each_user_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int pp_each_user_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)

Definition at line 1077 of file res_phoneprov.c.

1077 {
1078 .name = "PP_EACH_USER",
1079 .read = pp_each_user_read,
1080 .read2 = pp_each_user_read2,
1081};

Referenced by load_module(), and unload_module().

◆ pp_general_lookup

const char* pp_general_lookup[]
static

Definition at line 242 of file res_phoneprov.c.

242 {
244 [AST_PHONEPROV_STD_PROFILE] = "default_profile",
253 [AST_PHONEPROV_STD_SERVER] = "serveraddr",
254 [AST_PHONEPROV_STD_SERVER_PORT] = "serverport",
255 [AST_PHONEPROV_STD_SERVER_IFACE] = "serveriface",
266};
@ AST_PHONEPROV_STD_DST_END_MDAY
Definition phoneprov.h:51
@ AST_PHONEPROV_STD_DST_START_MDAY
Definition phoneprov.h:48
@ AST_PHONEPROV_STD_CALLERID
Definition phoneprov.h:36
@ AST_PHONEPROV_STD_DST_START_MONTH
Definition phoneprov.h:47
@ AST_PHONEPROV_STD_TZOFFSET
Definition phoneprov.h:45
@ AST_PHONEPROV_STD_DST_END_MONTH
Definition phoneprov.h:50
@ AST_PHONEPROV_STD_LABEL
Definition phoneprov.h:35
@ AST_PHONEPROV_STD_DST_END_HOUR
Definition phoneprov.h:52
@ AST_PHONEPROV_STD_DST_ENABLE
Definition phoneprov.h:46
@ AST_PHONEPROV_STD_DISPLAY_NAME
Definition phoneprov.h:33
@ AST_PHONEPROV_STD_SECRET
Definition phoneprov.h:34
@ AST_PHONEPROV_STD_DST_START_HOUR
Definition phoneprov.h:49

Referenced by get_defaults().

◆ pp_user_lookup

const char* pp_user_lookup[]
static

◆ profiles

struct ao2_container* profiles

◆ providers

struct ao2_container* providers

◆ users

Definition at line 326 of file res_phoneprov.c.

◆ variable_lookup

const char* variable_lookup[]
static

Definition at line 188 of file res_phoneprov.c.

188 {
189 [AST_PHONEPROV_STD_MAC] = "MAC",
190 [AST_PHONEPROV_STD_PROFILE] = "PROFILE",
191 [AST_PHONEPROV_STD_USERNAME] = "USERNAME",
192 [AST_PHONEPROV_STD_DISPLAY_NAME] = "DISPLAY_NAME",
193 [AST_PHONEPROV_STD_SECRET] = "SECRET",
194 [AST_PHONEPROV_STD_LABEL] = "LABEL",
195 [AST_PHONEPROV_STD_CALLERID] = "CALLERID",
196 [AST_PHONEPROV_STD_TIMEZONE] = "TIMEZONE",
198 [AST_PHONEPROV_STD_LINEKEYS] = "LINEKEYS",
199 [AST_PHONEPROV_STD_SERVER] = "SERVER",
200 [AST_PHONEPROV_STD_SERVER_PORT] = "SERVER_PORT",
201 [AST_PHONEPROV_STD_SERVER_IFACE] = "SERVER_IFACE",
202 [AST_PHONEPROV_STD_VOICEMAIL_EXTEN] = "VOICEMAIL_EXTEN",
203 [AST_PHONEPROV_STD_EXTENSION_LENGTH] = "EXTENSION_LENGTH",
204 [AST_PHONEPROV_STD_TZOFFSET] = "TZOFFSET",
205 [AST_PHONEPROV_STD_DST_ENABLE] = "DST_ENABLE",
206 [AST_PHONEPROV_STD_DST_START_MONTH] = "DST_START_MONTH",
207 [AST_PHONEPROV_STD_DST_START_MDAY] = "DST_START_MDAY",
208 [AST_PHONEPROV_STD_DST_START_HOUR] = "DST_START_HOUR",
209 [AST_PHONEPROV_STD_DST_END_MONTH] = "DST_END_MONTH",
210 [AST_PHONEPROV_STD_DST_END_MDAY] = "DST_END_MDAY",
211 [AST_PHONEPROV_STD_DST_END_HOUR] = "DST_END_HOUR",
212};

Referenced by ast_phoneprov_add_extension(), ast_phoneprov_std_variable_lookup(), build_extension(), get_defaults(), load_users(), and phoneprov_callback().