Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 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. More...
 
#define SIMPLE_HASH_FN(fname, stype, field)
 Creates a hash function for a structure string field. More...
 
#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. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_phoneprov_add_extension (char *provider_name, struct varshead *vars)
 Adds an extension. More...
 
void ast_phoneprov_delete_extension (char *provider_name, char *macaddress)
 Deletes an extension. More...
 
void ast_phoneprov_delete_extensions (char *provider_name)
 Deletes all extensions for this provider. More...
 
int ast_phoneprov_provider_register (char *provider_name, ast_phoneprov_load_users_cb load_users)
 Registers a config provider to phoneprov. More...
 
void ast_phoneprov_provider_unregister (char *provider_name)
 Unegisters a config provider from phoneprov and frees its resources. More...
 
const char * ast_phoneprov_std_variable_lookup (enum ast_phoneprov_std_variables var)
 Returns the string respresentation of a phoneprov standard variable. More...
 
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. More...
 
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. More...
 
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. More...
 
static int build_user_routes (struct user *user)
 Add an http route for dynamic files attached to the profile of the user. More...
 
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. More...
 
static void delete_providers (void)
 Delete all providers. More...
 
static void delete_routes (void)
 Delete all http routes, freeing their memory. More...
 
static void delete_users (void)
 Delete all users. More...
 
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. More...
 
static struct phoneprov_providerfind_provider (char *name)
 
static struct userfind_user (const char *macaddress)
 Return a user looked up by name. More...
 
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. More...
 
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. More...
 
static int load_module (void)
 Load the module. More...
 
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. More...
 
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. More...
 
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. More...
 
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) More...
 
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. More...
 

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 = "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 = 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 More...
 
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 1156 of file res_phoneprov.c.

◆ FORMATS

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

Definition at line 1155 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 157 of file res_phoneprov.c.

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

◆ SIPUSERS_PROVIDER_NAME

#define SIPUSERS_PROVIDER_NAME   "sipusers"

Definition at line 338 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 1520 of file res_phoneprov.c.

1525{

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1520 of file res_phoneprov.c.

1525{

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

807{
808 struct ast_var_t *pvar, *var2;
809 struct ast_str *str = ast_str_create(16);
810
811 if (!str) {
812 return -1;
813 }
814
815 /* Append profile variables here, and substitute variables on profile
816 * setvars, so that we can use user specific variables in them */
818 if (ast_var_find(exten->headp, pvar->name)) {
819 continue;
820 }
821
823 if ((var2 = ast_var_assign(pvar->name, ast_str_buffer(str)))) {
824 AST_VAR_LIST_INSERT_TAIL(exten->headp, var2);
825 }
826 }
827 ast_free(str);
828
831 } else {
832 struct extension *exten_iter;
833
835 if (exten->index < exten_iter->index) {
837 } else if (exten->index == exten_iter->index) {
838 ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
839 return -1;
840 } else if (!AST_LIST_NEXT(exten_iter, entry)) {
842 }
843 }
845 }
846
847 return 0;
848}
const char * str
Definition: app_jack.c:147
#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.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:599
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Support for dynamic strings.
Definition: strings.h:623
char name[0]
Definition: chanvars.h:31
char * value
Definition: chanvars.h:30
Definition: search.h:40
structure to hold extensions
struct varshead * headp
struct varshead * headp
structure to hold users read from users.conf
const ast_string_field macaddress
struct phone_profile * profile
struct user::@449 extensions

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

1525{

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

1634{
1636 RAII_VAR(struct user *, user, NULL, ao2_cleanup);
1637 RAII_VAR(struct phone_profile *, profile, NULL, ao2_cleanup);
1638 struct extension *exten;
1639 char *profile_name;
1640 char *mac;
1641 char *username;
1642
1643 if (ast_strlen_zero(provider_name)) {
1644 ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1645 return -1;
1646 }
1647 if (!vars) {
1648 ast_log(LOG_ERROR, "Variable list can't be empty.\n");
1649 return -1;
1650 }
1651
1653 if (!username) {
1654 ast_log(LOG_ERROR, "Extension name can't be empty.\n");
1655 return -1;
1656 }
1657
1659 if (!mac) {
1660 ast_log(LOG_ERROR, "MAC Address can't be empty.\n");
1661 return -1;
1662 }
1663
1664 provider = find_provider(provider_name);
1665 if (!provider) {
1666 ast_log(LOG_ERROR, "Provider '%s' wasn't found in the registry.\n", provider_name);
1667 return -1;
1668 }
1669
1670 profile_name = ast_var_find(vars,
1672 if (!profile_name) {
1673 ast_log(LOG_ERROR, "No profile could be found for user '%s' - skipping.\n", username);
1674 return -1;
1675 }
1676 if (!(profile = find_profile(profile_name))) {
1677 ast_log(LOG_ERROR, "Could not look up profile '%s' - skipping.\n", profile_name);
1678 return -1;
1679 }
1680
1681 if (!(user = find_user(mac))) {
1682
1683 if (!(user = build_user(mac, profile, provider_name))) {
1684 ast_log(LOG_ERROR, "Could not create user for '%s' - skipping\n", mac);
1685 return -1;
1686 }
1687
1688 if (!(exten = build_extension(username, vars))) {
1689 ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1690 return -1;
1691 }
1692
1693 if (add_user_extension(user, exten)) {
1694 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
1695 exten = delete_extension(exten);
1696 return -1;
1697 }
1698
1699 if (build_user_routes(user)) {
1700 ast_log(LOG_WARNING, "Could not create http routes for '%s' - skipping\n", user->macaddress);
1701 return -1;
1702 }
1704
1705 } else {
1706 if (strcmp(provider_name, user->provider_name)) {
1707 ast_log(LOG_ERROR, "MAC address '%s' was already added by provider '%s' - skipping\n", user->macaddress, user->provider_name);
1708 return -1;
1709 }
1710
1711 if (!(exten = build_extension(username, vars))) {
1712 ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1713 return -1;
1714 }
1715
1716 if (add_user_extension(user, exten)) {
1717 ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
1718 exten = delete_extension(exten);
1719 return -1;
1720 }
1721 }
1722
1723 return 0;
1724}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static struct prometheus_metrics_provider provider
Definition: bridges.c:201
#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:941

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

1605{
1606 if (!users) {
1607 return;
1608 }
1609
1611 extension_delete_cb, macaddress, provider_name);
1612}
#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
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
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 1614 of file res_phoneprov.c.

1615{
1616 if (!users) {
1617 return;
1618 }
1619
1621}
#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 1533 of file res_phoneprov.c.

1535{
1537
1539 ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1540 return -1;
1541 }
1542
1543 if (!providers) {
1544 ast_log(LOG_WARNING, "Provider '%s' cannot be registered: res_phoneprov not loaded.\n", provider_name);
1545 return -1;
1546 }
1547
1549 if (provider) {
1550 ast_log(LOG_ERROR, "There is already a provider registered named '%s'.\n", provider_name);
1551 ao2_ref(provider, -1);
1552 return -1;
1553 }
1554
1556 if (!provider) {
1557 ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s'.\n", provider_name);
1558 return -1;
1559 }
1560
1562 ao2_ref(provider, -1);
1563 ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s' stringfields.\n", provider_name);
1564 return -1;
1565 }
1566
1568 provider->load_users = load_users;
1569
1571 ao2_ref(provider, -1);
1572
1573 if (provider->load_users()) {
1574 ast_log(LOG_ERROR, "Unable to load provider '%s' users. Register aborted.\n", provider_name);
1576 return -1;
1577 }
1578
1579 return 0;
1580}
#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.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
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(), 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 1623 of file res_phoneprov.c.

1624{
1625 if (!providers) {
1626 return;
1627 }
1628
1629 ast_phoneprov_delete_extensions(provider_name);
1631}
#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(), 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 1524 of file res_phoneprov.c.

1525{
1527 return NULL;
1528 }
1529
1530 return variable_lookup[var];
1531}
#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 689 of file res_phoneprov.c.

690{
691 struct extension *exten;
692 const char *tmp;
693
694 if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
695 return NULL;
696 }
697
699
700 exten->headp = ast_var_list_clone(vars);
701 if (!exten->headp) {
702 ast_log(LOG_ERROR, "Unable to clone variables for extension '%s'\n", name);
703 delete_extension(exten);
704 return NULL;
705 }
706
708 if (!tmp) {
711 exten->index = 1;
712 } else {
713 sscanf(tmp, "%d", &exten->index);
714 }
715
719 }
720
723
724 return exten;
725}
static int tmp()
Definition: bt_open.c:389
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.
Definition: stringfields.h:432

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(), tmp(), 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 585 of file res_phoneprov.c.

586{
587 struct phone_profile *profile;
588
589 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
590 return;
591 }
592
593 if (ast_string_field_init(profile, 32)) {
594 profile = unref_profile(profile);
595 return;
596 }
597
598 if (!(profile->headp = ast_var_list_create())) {
599 profile = unref_profile(profile);
600 return;
601 }
602
605
606 ast_string_field_set(profile, name, name);
607 for (; v; v = v->next) {
608 if (!strcasecmp(v->name, "mime_type")) {
610 } else if (!strcasecmp(v->name, "setvar")) {
611 char value_copy[strlen(v->value) + 1];
612
614 AST_APP_ARG(varname);
615 AST_APP_ARG(varval);
616 );
617
618 strcpy(value_copy, v->value); /* safe */
619 AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
620 do {
621 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
622 break;
623 args.varname = ast_strip(args.varname);
624 args.varval = ast_strip(args.varval);
625 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
626 break;
627 AST_VAR_LIST_INSERT_TAIL(profile->headp, ast_var_assign(args.varname, args.varval));
628 } while (0);
629 } else if (!strcasecmp(v->name, "staticdir")) {
631 } else {
632 struct phoneprov_file *pp_file;
633 char *file_extension;
634 char value_copy[strlen(v->value) + 1];
635
637 AST_APP_ARG(filename);
638 AST_APP_ARG(mimetype);
639 );
640
641 if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
642 profile = unref_profile(profile);
643 return;
644 }
645
646 if ((file_extension = strrchr(pp_file->format, '.')))
647 file_extension++;
648
649 strcpy(value_copy, v->value); /* safe */
650 AST_STANDARD_APP_ARGS(args, value_copy);
651
652 /* Mime type order of preference
653 * 1) Specific mime-type defined for file in profile
654 * 2) Mime determined by extension
655 * 3) Default mime type specified in profile
656 * 4) text/plain
657 */
658 ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
659 (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
660
661 if (!strcasecmp(v->name, "static_file")) {
662 ast_string_field_set(pp_file, format, args.filename);
663 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
664 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
665 /* Add a route for the static files, as their filenames won't change per-user */
666 build_route(pp_file, profile, NULL, NULL);
667 } else {
668 ast_string_field_set(pp_file, format, v->name);
669 ast_string_field_set(pp_file, template, args.filename);
670 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
671 }
672 }
673 }
674
675 ao2_link(profiles, profile);
676
677 profile = unref_profile(profile);
678}
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:206
#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.
Definition: linkedlists.h:681
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.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
#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
struct phone_profile::@448 dynamic_files
const ast_string_field staticdir
const ast_string_field default_mime_type
struct phone_profile::@447 static_files
structure to hold file data
const ast_string_field mime_type
const ast_string_field format
const char * args

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

513{
514 struct http_route *route;
515
516 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
517 return;
518 }
519
520 if (ast_string_field_init(route, 32)) {
521 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
522 route = unref_route(route);
523 return;
524 }
525
526 ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
527 route->user = user;
528 route->file = pp_file;
529 route->profile = profile;
530
531 ao2_link(http_routes, route);
532
533 route = unref_route(route);
534}
static char user[512]
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, user, 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 784 of file res_phoneprov.c.

785{
786 struct user *user;
787
788 if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
789 return NULL;
790 }
791
792 if (ast_string_field_init(user, 64)) {
794 return NULL;
795 }
796
800 ao2_ref(profile, 1);
801
802 return user;
803}
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(), 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 851 of file res_phoneprov.c.

852{
853 struct phoneprov_file *pp_file;
854 struct ast_str *str;
855
856 if (!(str = ast_str_create(16))) {
857 return -1;
858 }
859
863 }
864
865 ast_free(str);
866 return 0;
867}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421

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

681{
684 ast_free(exten);
685
686 return NULL;
687}
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
Definition: stringfields.h:374

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

◆ delete_profiles()

static void delete_profiles ( void  )
static

Delete all phone profiles, freeing their memory.

Definition at line 572 of file res_phoneprov.c.

573{
574 if (!profiles) {
575 return;
576 }
577
579}

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

378{
379 if (!providers) {
380 return;
381 }
382
384}

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

498{
499 if (!http_routes) {
500 return;
501 }
502
504}

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

775{
776 if (!users) {
777 return;
778 }
779
781}

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

1593{
1594 struct user *user = obj;
1595 char *provider_name = data;
1596 char *macaddress = arg;
1597
1598 if (!strcmp(user->provider_name, provider_name) && !strcasecmp(user->macaddress, macaddress)) {
1599 return CMP_MATCH;
1600 }
1601 return 0;
1602}
@ CMP_MATCH
Definition: astobj2.h:1027

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

1583{
1584 char *provider_name = arg;
1585 struct user *user = obj;
1586 if (strcmp(user->provider_name, provider_name)) {
1587 return 0;
1588 }
1589 return CMP_MATCH;
1590}

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

545{
547}

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

372{
374}

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

736{
737 return ao2_find(users, macaddress, OBJ_SEARCH_KEY);
738}

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

1216{
1217 struct ast_config *phoneprov_cfg, *cfg = CONFIG_STATUS_FILEINVALID;
1218 const char *value;
1219 struct ast_variable *v;
1220 struct ast_var_t *var;
1221 struct ast_flags config_flags = { 0 };
1222 struct varshead *defaults = ast_var_list_create();
1223
1224 if (!defaults) {
1225 ast_log(LOG_ERROR, "Unable to create default var list.\n");
1226 return NULL;
1227 }
1228
1229 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1230 || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1231 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1232 ast_var_list_destroy(defaults);
1233 return NULL;
1234 }
1235
1237 if (!value) {
1238 struct in_addr addr;
1240 if (value) {
1241 lookup_iface(value, &addr);
1242 value = ast_inet_ntoa(addr);
1243 }
1244 }
1245 if (value) {
1247 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1248 } else {
1249 ast_log(LOG_WARNING, "Unable to find a valid server address or name.\n");
1250 }
1251
1254 if (cfg && cfg != CONFIG_STATUS_FILEINVALID) {
1255 ast_config_destroy(cfg);
1256 }
1257 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1258
1260 if (!value) {
1261 ast_log(LOG_ERROR, "Unable to load default profile.\n");
1262 ast_config_destroy(phoneprov_cfg);
1263 ast_var_list_destroy(defaults);
1264 return NULL;
1265 }
1267 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1268 ast_config_destroy(phoneprov_cfg);
1269
1270 if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
1271 ast_log(LOG_ERROR, "Unable to load users.conf\n");
1272 ast_var_list_destroy(defaults);
1273 return NULL;
1274 }
1275
1276 /* Go ahead and load global variables from users.conf so we can append to profiles */
1277 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
1280 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1281 }
1284 AST_VAR_LIST_INSERT_TAIL(defaults, var);
1285 }
1286 }
1287 ast_config_destroy(cfg);
1288
1289 return defaults;
1290}
#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:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:928
@ 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:199
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 1173 of file res_phoneprov.c.

1174{
1175 int fd = a->fd;
1176 switch(cmd) {
1177 case CLI_INIT:
1178 e->command = "phoneprov show routes";
1179 e->usage =
1180 "Usage: phoneprov show routes\n"
1181 " Lists all registered phoneprov http routes.\n";
1182 return NULL;
1183 case CLI_GENERATE:
1184 return NULL;
1185 }
1186
1187 /* This currently iterates over routes twice, but it is the only place I've needed
1188 * to really separate static an dynamic routes, so I've just left it this way. */
1189 ast_cli(a->fd, "Static routes\n\n");
1190 ast_cli(a->fd, FORMATS, "Profile", "Relative URI", "Physical location");
1191
1193
1194 ast_cli(a->fd, "\nDynamic routes\n\n");
1195 ast_cli(a->fd, FORMATD, "Provider", "Profile", "Relative URI", "Template");
1196
1198
1199 return CLI_SUCCESS;
1200}
#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 1362 of file res_phoneprov.c.

1363{
1364 struct ast_config *phoneprov_cfg;
1365 struct ast_flags config_flags = { 0 };
1366 char *cat;
1367
1368 if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1369 || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1370 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1371 return -1;
1372 }
1373
1374 cat = NULL;
1375 while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
1376 if (!strcasecmp(cat, "general")) {
1377 continue;
1378 }
1379 build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
1380 }
1381 ast_config_destroy(phoneprov_cfg);
1382
1384 ast_log(LOG_ERROR, "There are no provisioning profiles in phoneprov.conf.\n");
1385 return -1;
1386 }
1387
1388 return 0;
1389}
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:3326
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 399 of file res_phoneprov.c.

400{
401 int len = 0;
402 FILE *f;
403
404 if (!(f = fopen(filename, "r"))) {
405 *ret = NULL;
406 return -1;
407 }
408
409 fseek(f, 0, SEEK_END);
410 len = ftell(f);
411 fseek(f, 0, SEEK_SET);
412 if (!(*ret = ast_malloc(len + 1))) {
413 fclose(f);
414 return -2;
415 }
416
417 if (len != fread(*ret, sizeof(char), len, f)) {
418 fclose(f);
419 ast_free(*ret);
420 *ret = NULL;
421 return -3;
422 }
423
424 fclose(f);
425
426 (*ret)[len] = '\0';
427
428 return len;
429}
#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 1428 of file res_phoneprov.c.

1429{
1431 phone_profile_hash_fn, NULL, phone_profile_cmp_fn);
1432 if (!profiles) {
1433 ast_log(LOG_ERROR, "Unable to allocate profiles container.\n");
1435 }
1436
1438 http_route_hash_fn, NULL, http_route_cmp_fn);
1439 if (!http_routes) {
1440 ast_log(LOG_ERROR, "Unable to allocate routes container.\n");
1441 goto error;
1442 }
1443
1444 if (load_common()) {
1445 ast_log(LOG_ERROR, "Unable to load provisioning profiles.\n");
1446 goto error;
1447 }
1448
1450 user_hash_fn, NULL, user_cmp_fn);
1451 if (!users) {
1452 ast_log(LOG_ERROR, "Unable to allocate users container.\n");
1453 goto error;
1454 }
1455
1457 MAX_PROVIDER_BUCKETS, phoneprov_provider_hash_fn, NULL, phoneprov_provider_cmp_fn);
1458 if (!providers) {
1459 ast_log(LOG_ERROR, "Unable to allocate providers container.\n");
1460 goto error;
1461 }
1462
1463 /* Register ourselves as the provider for users.conf */
1465 ast_log(LOG_WARNING, "Unable register users config provider. Others may succeed.\n");
1466 }
1467
1469
1473
1475
1476error:
1477 unload_module();
1479}
@ 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:676
@ 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:1558
#define MAX_USER_BUCKETS
Definition: res_phoneprov.c:83
#define MAX_ROUTE_BUCKETS
Definition: res_phoneprov.c:82
#define MAX_PROFILE_BUCKETS
Definition: res_phoneprov.c:81
#define MAX_PROVIDER_BUCKETS
Definition: res_phoneprov.c:80
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,...)
Definition: utils/frame.c:999
#define ARRAY_LEN(a)
Definition: utils.h:666

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

1293{
1294 struct ast_config *cfg;
1295 char *cat;
1296 const char *value;
1297 struct ast_flags config_flags = { 0 };
1298 struct varshead *defaults = get_defaults();
1299
1300 if (!defaults) {
1301 ast_log(LOG_WARNING, "Unable to load default variables.\n");
1302 return -1;
1303 }
1304
1305 if (!(cfg = ast_config_load("users.conf", config_flags))
1306 || cfg == CONFIG_STATUS_FILEINVALID) {
1307 ast_log(LOG_WARNING, "Unable to load users.conf\n");
1308 ast_var_list_destroy(defaults);
1309 return -1;
1310 }
1311
1312 cat = NULL;
1313 while ((cat = ast_category_browse(cfg, cat))) {
1314 const char *tmp;
1315 int i;
1316 struct ast_var_t *varx;
1317 struct ast_var_t *vard;
1318
1319 if (strcasecmp(cat, "general") && strcasecmp(cat, "authentication")) {
1320 struct varshead *variables = ast_var_list_create();
1321
1322 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) {
1323 ast_var_list_destroy(variables);
1324 continue;
1325 }
1326
1327 /* Transfer the standard variables */
1328 for (i = 0; i < AST_PHONEPROV_STD_VAR_LIST_LENGTH; i++) {
1329 if (pp_user_lookup[i]) {
1331 if (value) {
1333 value);
1334 AST_VAR_LIST_INSERT_TAIL(variables, varx);
1335 }
1336 }
1337 }
1338
1340 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
1341 ast_var_list_destroy(variables);
1342 continue;
1343 }
1344
1345 /* Apply defaults */
1346 AST_VAR_LIST_TRAVERSE(defaults, vard) {
1347 if (ast_var_find(variables, vard->name)) {
1348 continue;
1349 }
1350 varx = ast_var_assign(vard->name, vard->value);
1351 AST_VAR_LIST_INSERT_TAIL(variables, varx);
1352 }
1353
1355 }
1356 }
1357 ast_config_destroy(cfg);
1358 ast_var_list_destroy(defaults);
1359 return 0;
1360}
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:2199

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, tmp(), ast_var_t::value, value, and variable_lookup.

Referenced by ast_phoneprov_provider_register(), and load_module().

◆ lookup_iface()

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

Definition at line 341 of file res_phoneprov.c.

342{
343 int mysock, res = 0;
344 struct ifreq ifr;
345 struct sockaddr_in *sin;
346
347 memset(&ifr, 0, sizeof(ifr));
348 ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
349
350 mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
351 if (mysock < 0) {
352 ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
353 return -1;
354 }
355
356 res = ioctl(mysock, SIOCGIFADDR, &ifr);
357
358 close(mysock);
359
360 if (res < 0) {
361 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
362 memcpy(address, &__ourip, sizeof(__ourip));
363 return -1;
364 } else {
365 sin = (struct sockaddr_in *)&ifr.ifr_addr;
366 memcpy(address, &sin->sin_addr, sizeof(*address));
367 return 0;
368 }
369}
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 870 of file res_phoneprov.c.

871{
872 struct http_route *route;
873 struct ast_str *result;
874 char path[PATH_MAX];
875 char *file = NULL;
876 char *server;
877 char *newserver = NULL;
878 struct extension *exten_iter;
879 int len;
880 int fd;
881 struct ast_str *http_header;
882
884 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
885 return 0;
886 }
887
888 if (!(route = ao2_find(http_routes, uri, OBJ_SEARCH_KEY))) {
889 goto out404;
890 }
891
892 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
893
894 if (!route->user) { /* Static file */
895
896 fd = open(path, O_RDONLY);
897 if (fd < 0) {
898 goto out500;
899 }
900
901 len = lseek(fd, 0, SEEK_END);
902 lseek(fd, 0, SEEK_SET);
903 if (len < 0) {
904 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
905 close(fd);
906 goto out500;
907 }
908
909 http_header = ast_str_create(80);
910 ast_str_set(&http_header, 0, "Content-type: %s\r\n",
911 route->file->mime_type);
912
913 ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
914
915 close(fd);
916 route = unref_route(route);
917 return 0;
918 } else { /* Dynamic file */
919 struct ast_str *tmp;
920
921 len = load_file(path, &file);
922 if (len < 0) {
923 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
924 if (file) {
925 ast_free(file);
926 }
927
928 goto out500;
929 }
930
931 if (!file) {
932 goto out500;
933 }
934
935 if (!(tmp = ast_str_create(len))) {
936 if (file) {
937 ast_free(file);
938 }
939
940 goto out500;
941 }
942
943 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
944 * the IP address we are listening on that the phone contacted for this config file */
945
946 server = ast_var_find(AST_LIST_FIRST(&route->user->extensions)->headp,
948
949 if (!server) {
950 union {
951 struct sockaddr sa;
952 struct sockaddr_in sa_in;
953 } name;
954 socklen_t namelen = sizeof(name.sa);
955 int res;
956
957 if ((res = getsockname(ast_iostream_get_fd(ser->stream), &name.sa, &namelen))) {
958 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
959 } else {
960 newserver = ast_strdupa(ast_inet_ntoa(name.sa_in.sin_addr));
961
962 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
965 }
966 }
967 }
968
970
971 /* Do not retain dynamic SERVER address because next request from the phone might arrive on
972 * different interface IP address eg. if this is a multi-homed server on multiple subnets */
973 if (newserver) {
974 struct ast_var_t *varns;
975 AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
976 AST_LIST_TRAVERSE_SAFE_BEGIN(exten_iter->headp, varns, entries) {
979 ast_var_delete(varns);
980 }
981 }
983 }
984 }
985
986 ast_free(file);
987
988 http_header = ast_str_create(80);
989 ast_str_set(&http_header, 0, "Content-type: %s\r\n",
990 route->file->mime_type);
991
992 if (!(result = ast_str_create(512))) {
993 ast_log(LOG_ERROR, "Could not create result string!\n");
994 if (tmp) {
995 ast_free(tmp);
996 }
997 ast_free(http_header);
998 goto out500;
999 }
1001
1002 ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
1003 ast_free(tmp);
1004
1005 route = unref_route(route);
1006
1007 return 0;
1008 }
1009
1010out404:
1011 ast_http_error(ser, 404, "Not Found", uri);
1012 return 0;
1013
1014out500:
1015 route = unref_route(route);
1016 ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
1017 return 0;
1018}
#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:2471
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:459
@ 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:651
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
Definition: iostream.c:84
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
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:161
struct ast_var_t::@211 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, make_ari_stubs::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, tmp(), 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 1078 of file res_phoneprov.c.

1079{
1080 struct user *user;
1081 struct extension *exten;
1082 char path[PATH_MAX];
1083 char *file;
1084 int filelen;
1085 struct ast_str *str;
1087 AST_APP_ARG(mac);
1088 AST_APP_ARG(template);
1089 );
1090
1092
1093 if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
1094 ast_log(LOG_WARNING, "PP_EACH_EXTENSION requires both a macaddress and template filename.\n");
1095 return 0;
1096 }
1097
1098 if (!(user = find_user(args.mac))) {
1099 ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
1100 return 0;
1101 }
1102
1103 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
1104 filelen = load_file(path, &file);
1105 if (filelen < 0) {
1106 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
1107 if (file) {
1108 ast_free(file);
1109 }
1110 return 0;
1111 }
1112
1113 if (!file) {
1114 return 0;
1115 }
1116
1117 if (!(str = ast_str_create(filelen))) {
1118 return 0;
1119 }
1120
1123 if (buf) {
1124 size_t slen = len;
1125 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1126 } else {
1127 ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1128 }
1129 }
1130
1131 ast_free(file);
1132 ast_free(str);
1133
1134 user = unref_user(user);
1135
1136 return 0;
1137}
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:2167

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, make_ari_stubs::file, find_user(), extension::headp, len(), load_file(), LOG_WARNING, PATH_MAX, str, unref_user(), and 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 1139 of file res_phoneprov.c.

1140{
1141 return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
1142}
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 1144 of file res_phoneprov.c.

1145{
1146 return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
1147}

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

1022{
1023 char *tmp;
1024 struct ao2_iterator i;
1025 struct user *user;
1026 struct ast_str *str;
1028 AST_APP_ARG(string);
1029 AST_APP_ARG(exclude_mac);
1030 );
1032
1033 if (!(str = ast_str_create(16))) {
1034 return -1;
1035 }
1036
1037 /* Fix data by turning %{ into ${ */
1038 while ((tmp = strstr(args.string, "%{")))
1039 *tmp = '$';
1040
1041 i = ao2_iterator_init(users, 0);
1042 while ((user = ao2_iterator_next(&i))) {
1043 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
1044 continue;
1045 }
1047 if (buf) {
1048 size_t slen = len;
1049 ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1050 } else {
1051 ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1052 }
1053 user = unref_user(user);
1054 }
1056
1057 ast_free(str);
1058 return 0;
1059}
#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, tmp(), unref_user(), and 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 1061 of file res_phoneprov.c.

1062{
1063 return pp_each_user_helper(chan, data, buf, NULL, len);
1064}
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 1066 of file res_phoneprov.c.

1067{
1068 return pp_each_user_helper(chan, data, NULL, buf, len);
1069}

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

◆ profile_destructor()

static void profile_destructor ( void *  obj)
static

Definition at line 549 of file res_phoneprov.c.

550{
551 struct phone_profile *profile = obj;
552 struct phoneprov_file *file;
553 struct ast_var_t *var;
554
555 while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) {
557 }
558
559 while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) {
561 }
562
563 while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) {
565 }
566
567 ast_free(profile->headp);
569}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
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, make_ari_stubs::file, 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 386 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 1481 of file res_phoneprov.c.

1482{
1483 struct ao2_iterator i;
1485
1486 /* Clean everything except the providers */
1487 delete_routes();
1488 delete_users();
1490
1491 /* Reload the profiles */
1492 if (load_common()) {
1493 ast_log(LOG_ERROR, "Unable to reload provisioning profiles.\n");
1494 unload_module();
1496 }
1497
1498 /* For each provider, reload the users */
1501 for(; (provider = ao2_iterator_next(&i)); ao2_ref(provider, -1)) {
1502 if (provider->load_users()) {
1503 ast_log(LOG_ERROR, "Unable to load provider '%s' users. Reload aborted.\n", provider->provider_name);
1504 continue;
1505 }
1506 }
1509
1511}
#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 489 of file res_phoneprov.c.

490{
491 struct http_route *route = obj;
492
494}

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

1158{
1159 int fd = *(int *)arg;
1160 struct http_route *route = obj;
1161
1162 if (data && route->user) {
1163 ast_cli(fd, FORMATD, route->user->provider_name, route->profile->name, route->uri, route->file->template);
1164 }
1165 if (!data && !route->user) {
1166 ast_cli(fd, FORMATS, route->profile->name, route->uri, route->file->template);
1167 }
1168
1169 return CMP_MATCH;
1170}
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 740 of file res_phoneprov.c.

741{
742 struct http_route *route = obj;
743 struct user *user = route->user;
744 char *macaddress = arg;
745
746 if (user && !strcmp(user->macaddress, macaddress)) {
747 return CMP_MATCH;
748 }
749 return 0;
750}

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

436{
437 time_t utc_time;
438 int dstenable;
439 time_t dststart;
440 time_t dstend;
441 struct ast_tm tm_info;
442 int tzoffset;
443 char buffer[21];
444 struct timeval when;
445
446 time(&utc_time);
447 ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
448 snprintf(buffer, sizeof(buffer), "%d", tzoffset);
449 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("TZOFFSET", buffer));
450
451 if (!dstenable) {
452 return;
453 }
454
455 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_ENABLE", "1"));
456
457 when.tv_sec = dststart;
458 ast_localtime(&when, &tm_info, zone);
459
460 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
461 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MONTH", buffer));
462
463 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
464 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_MDAY", buffer));
465
466 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
467 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_START_HOUR", buffer));
468
469 when.tv_sec = dstend;
470 ast_localtime(&when, &tm_info, zone);
471
472 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
473 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MONTH", buffer));
474
475 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
476 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_MDAY", buffer));
477
478 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
479 AST_VAR_LIST_INSERT_TAIL(headp, ast_var_assign("DST_END_HOUR", buffer));
480}
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 1391 of file res_phoneprov.c.

1392{
1397
1398 /* This cleans up the users.conf provider (called specifically for clarity) */
1400
1401 /* This cleans up the framework which also cleans up the providers. */
1404 profiles = NULL;
1405 delete_routes();
1406 delete_users();
1408 http_routes = NULL;
1410 users = NULL;
1413 providers = NULL;
1414
1415 return 0;
1416}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
Definition: http.c:708
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 536 of file res_phoneprov.c.

537{
538 ao2_cleanup(prof);
539
540 return NULL;
541}

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

483{
484 ao2_cleanup(route);
485
486 return NULL;
487}

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

728{
730
731 return NULL;
732}

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

754{
755 struct user *user = obj;
756 struct extension *exten;
757
758 while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
759 exten = delete_extension(exten);
760 }
761
762 if (user->profile) {
764 }
765
766 if (http_routes) {
768 }
769
771}
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(), 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 = "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 = 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 1520 of file res_phoneprov.c.

◆ __ourip

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

for use in lookup_iface

Definition at line 263 of file res_phoneprov.c.

Referenced by lookup_iface().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1520 of file res_phoneprov.c.

◆ http_routes

struct ao2_container* http_routes

◆ phoneprovuri

struct ast_http_uri phoneprovuri
static

Definition at line 1206 of file res_phoneprov.c.

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

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

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

Referenced by load_module(), and unload_module().

◆ pp_general_lookup

const char* pp_general_lookup[]
static

Definition at line 236 of file res_phoneprov.c.

Referenced by get_defaults().

◆ pp_user_lookup

const char* pp_user_lookup[]
static

Definition at line 209 of file res_phoneprov.c.

Referenced by get_defaults(), and load_users().

◆ profiles

struct ao2_container* profiles

◆ providers

struct ao2_container* providers

◆ users

Definition at line 320 of file res_phoneprov.c.

Referenced by load_users().

◆ variable_lookup

const char* variable_lookup[]
static