Asterisk - The Open Source Telephony Project  18.5.0
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 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 VAR_BUF_SIZE   4096
 

Functions

static int add_user_extension (struct user *user, struct extension *exten)
 Add an extension to a user ordered by index/linenumber. More...
 
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
 
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 http_route_cmp_fn (void *obj, void *arg, int flags)
 
static int http_route_hash_fn (const void *obj, const int flags)
 
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 phone_profile_cmp_fn (void *obj, void *arg, int flags)
 
static int phone_profile_hash_fn (const void *obj, const int flags)
 
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 int user_cmp_fn (void *obj, void *arg, int flags)
 
static void user_destructor (void *obj)
 Free all memory associated with a user. More...
 
static int user_hash_fn (const void *obj, const int flags)
 

Variables

static struct in_addr __ourip = { .s_addr = 0x00000000, }
 for use in lookup_iface More...
 
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.

◆ MAX_PROFILE_BUCKETS

#define MAX_PROFILE_BUCKETS   17

Definition at line 81 of file res_phoneprov.c.

Referenced by load_module().

◆ MAX_PROVIDER_BUCKETS

#define MAX_PROVIDER_BUCKETS   17

Definition at line 80 of file res_phoneprov.c.

Referenced by load_module().

◆ MAX_ROUTE_BUCKETS

#define MAX_ROUTE_BUCKETS   563

Definition at line 82 of file res_phoneprov.c.

Referenced by load_module().

◆ MAX_USER_BUCKETS

#define MAX_USER_BUCKETS   563

Definition at line 83 of file res_phoneprov.c.

Referenced by load_module().

◆ 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.

◆ VAR_BUF_SIZE

#define VAR_BUF_SIZE   4096

Definition at line 86 of file res_phoneprov.c.

Function Documentation

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

806 {
807  struct ast_var_t *pvar, *var2;
808  struct ast_str *str = ast_str_create(16);
809 
810  if (!str) {
811  return -1;
812  }
813 
814  /* Append profile variables here, and substitute variables on profile
815  * setvars, so that we can use user specific variables in them */
816  AST_VAR_LIST_TRAVERSE(user->profile->headp, pvar) {
817  if (ast_var_find(exten->headp, pvar->name)) {
818  continue;
819  }
820 
821  ast_str_substitute_variables_varshead(&str, 0, exten->headp, pvar->value);
822  if ((var2 = ast_var_assign(pvar->name, ast_str_buffer(str)))) {
823  AST_VAR_LIST_INSERT_TAIL(exten->headp, var2);
824  }
825  }
826  ast_free(str);
827 
828  if (AST_LIST_EMPTY(&user->extensions)) {
829  AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
830  } else {
831  struct extension *exten_iter;
832 
833  AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
834  if (exten->index < exten_iter->index) {
836  } else if (exten->index == exten_iter->index) {
837  ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
838  return -1;
839  } else if (!AST_LIST_NEXT(exten_iter, entry)) {
840  AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
const char * str
Definition: app_jack.c:147
struct varshead * headp
struct varshead * headp
#define ast_log
Definition: astobj2.c:42
structure to hold extensions
struct phone_profile * profile
char name[0]
Definition: chanvars.h:31
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
char * value
Definition: chanvars.h:30
struct user::@476 extensions
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_free(a)
Definition: astmm.h:182
char * ast_var_find(const struct varshead *head, const char *name)
Definition: chanvars.c:85
#define ast_var_assign(name, value)
Definition: chanvars.h:40
const ast_string_field macaddress
Definition: search.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:598
#define AST_VAR_LIST_TRAVERSE(head, var)
Definition: chanvars.h:49
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ AST_MODULE_INFO()

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_GLOBAL_SYMBOLS AST_MODFLAG_LOAD_ORDER,
"HTTP Phone Provisioning"  ,
support_level = AST_MODULE_SUPPORT_EXTENDED,
load = load_module,
unload = unload_module,
reload = reload,
load_pri = AST_MODPRI_CHANNEL_DEPEND,
requires = "http" 
)

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

Referenced by users_apply_handler().

1622 {
1624  RAII_VAR(struct user *, user, NULL, ao2_cleanup);
1625  RAII_VAR(struct phone_profile *, profile, NULL, ao2_cleanup);
1626  struct extension *exten;
1627  char *profile_name;
1628  char *mac;
1629  char *username;
1630 
1631  if (ast_strlen_zero(provider_name)) {
1632  ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1633  return -1;
1634  }
1635  if (!vars) {
1636  ast_log(LOG_ERROR, "Variable list can't be empty.\n");
1637  return -1;
1638  }
1639 
1641  if (!username) {
1642  ast_log(LOG_ERROR, "Extension name can't be empty.\n");
1643  return -1;
1644  }
1645 
1647  if (!mac) {
1648  ast_log(LOG_ERROR, "MAC Address can't be empty.\n");
1649  return -1;
1650  }
1651 
1652  provider = find_provider(provider_name);
1653  if (!provider) {
1654  ast_log(LOG_ERROR, "Provider '%s' wasn't found in the registry.\n", provider_name);
1655  return -1;
1656  }
1657 
1658  profile_name = ast_var_find(vars,
1660  if (!profile_name) {
1661  ast_log(LOG_ERROR, "No profile could be found for user '%s' - skipping.\n", username);
1662  return -1;
1663  }
1664  if (!(profile = find_profile(profile_name))) {
1665  ast_log(LOG_ERROR, "Could not look up profile '%s' - skipping.\n", profile_name);
1666  return -1;
1667  }
1668 
1669  if (!(user = find_user(mac))) {
1670 
1671  if (!(user = build_user(mac, profile, provider_name))) {
1672  ast_log(LOG_ERROR, "Could not create user for '%s' - skipping\n", mac);
1673  return -1;
1674  }
1675 
1676  if (!(exten = build_extension(username, vars))) {
1677  ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1678  return -1;
1679  }
1680 
1681  if (add_user_extension(user, exten)) {
1682  ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
1683  exten = delete_extension(exten);
1684  return -1;
1685  }
1686 
1687  if (build_user_routes(user)) {
1688  ast_log(LOG_WARNING, "Could not create http routes for '%s' - skipping\n", user->macaddress);
1689  return -1;
1690  }
1691  ao2_link(users, user);
1692 
1693  } else {
1694  if (strcmp(provider_name, user->provider_name)) {
1695  ast_log(LOG_ERROR, "MAC address '%s' was already added by provider '%s' - skipping\n", user->macaddress, user->provider_name);
1696  return -1;
1697  }
1698 
1699  if (!(exten = build_extension(username, vars))) {
1700  ast_log(LOG_ERROR, "Could not create extension for '%s' - skipping\n", user->macaddress);
1701  return -1;
1702  }
1703 
1704  if (add_user_extension(user, exten)) {
1705  ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define LOG_WARNING
Definition: logger.h:274
static int build_user_routes(struct user *user)
Add an http route for dynamic files attached to the profile of the user.
#define NULL
Definition: resample.c:96
list of users found in the config file
static struct user * find_user(const char *macaddress)
Return a user looked up by name.
static struct phoneprov_provider * find_provider(char *name)
#define ast_strlen_zero(foo)
Definition: strings.h:52
structure to hold config providers
#define ast_log
Definition: astobj2.c:42
static struct extension * build_extension(const char *name, struct varshead *vars)
#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:911
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.
structure to hold extensions
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field provider_name
char * ast_var_find(const struct varshead *head, const char *name)
Definition: chanvars.c:85
structure to hold phone profiles read from phoneprov.conf
static const char * variable_lookup[]
structure to hold users read from users.conf
const ast_string_field name
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct extension * delete_extension(struct extension *exten)
const ast_string_field macaddress
static int add_user_extension(struct user *user, struct extension *exten)
Add an extension to a user ordered by index/linenumber.
static struct phone_profile * find_profile(const char *name)
Return a phone profile looked up by name.
static struct prometheus_metrics_provider provider
Definition: bridges.c:178
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

References CMP_MATCH.

Referenced by phoneprov_destroy().

1586  {
1587  return CMP_MATCH;
1588  }
1589  return 0;
1590 }
1591 
1592 void ast_phoneprov_delete_extension(char *provider_name, char *macaddress)
1593 {
void ast_phoneprov_delete_extension(char *provider_name, char *macaddress)
Deletes an extension.

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

1603 {

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

References ao2_alloc, ao2_link, ao2_ref, ast_log, ast_string_field_init, ast_string_field_set, ast_strlen_zero, find_provider(), phoneprov_provider::load_users, LOG_ERROR, LOG_WARNING, NULL, provider, provider_destructor(), var, and variable_lookup.

Referenced by load_module(), and reload_module().

1514  {
1515  return NULL;
1516  }
1517 
1518  return variable_lookup[var];
1519 }
1520 
1521 int ast_phoneprov_provider_register(char *provider_name,
1523 {
1524  struct phoneprov_provider *provider;
1525 
1526  if (ast_strlen_zero(provider_name)) {
1527  ast_log(LOG_ERROR, "Provider name can't be empty.\n");
1528  return -1;
1529  }
1530 
1531  if (!providers) {
1532  ast_log(LOG_WARNING, "Provider '%s' cannot be registered: res_phoneprov not loaded.\n", provider_name);
1533  return -1;
1534  }
1535 
1536  provider = find_provider(provider_name);
1537  if (provider) {
1538  ast_log(LOG_ERROR, "There is already a provider registered named '%s'.\n", provider_name);
1539  ao2_ref(provider, -1);
1540  return -1;
1541  }
1542 
1543  provider = ao2_alloc(sizeof(struct phoneprov_provider), provider_destructor);
1544  if (!provider) {
1545  ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s'.\n", provider_name);
1546  return -1;
1547  }
1548 
1549  if (ast_string_field_init(provider, 32)) {
1550  ao2_ref(provider, -1);
1551  ast_log(LOG_ERROR, "Unable to allocate sufficient memory for provider '%s' stringfields.\n", provider_name);
1552  return -1;
1553  }
1554 
1555  ast_string_field_set(provider, provider_name, provider_name);
1556  provider->load_users = load_users;
1557 
1558  ao2_link(providers, provider);
1559  ao2_ref(provider, -1);
1560 
1561  if (provider->load_users()) {
int ast_phoneprov_provider_register(char *provider_name, ast_phoneprov_load_users_cb load_users)
Registers a config provider to phoneprov.
#define LOG_WARNING
Definition: logger.h:274
static int load_users(void)
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
int(* ast_phoneprov_load_users_cb)(void)
Causes the provider to load its users.
Definition: phoneprov.h:75
static struct phoneprov_provider * find_provider(char *name)
#define ast_strlen_zero(foo)
Definition: strings.h:52
structure to hold config providers
#define ast_log
Definition: astobj2.c:42
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * providers
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void provider_destructor(void *obj)
static const char * variable_lookup[]
ast_phoneprov_load_users_cb load_users
static struct prometheus_metrics_provider provider
Definition: bridges.c:178
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define ao2_link(container, obj)
Definition: astobj2.h:1549

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

References ao2_callback, extensions_delete_cb(), OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by reload_module(), and unload_module().

1604  {
1605  return;
1606  }
1607 
1609 }
1610 
1612 {
static int extensions_delete_cb(void *obj, void *arg, int flags)
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
list of users found in the config file
void ast_phoneprov_provider_unregister(char *provider_name)
Unegisters a config provider from phoneprov and frees its resources.
const ast_string_field provider_name

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

Referenced by load_endpoint(), and users_apply_handler().

1513 {

◆ build_extension()

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

Definition at line 681 of file res_phoneprov.c.

689 {
690  struct extension *exten;
691  const char *tmp;
692 
693  if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
694  return NULL;
695  }
696 
697  ast_string_field_set(exten, name, name);
698 
699  exten->headp = ast_var_list_clone(vars);
700  if (!exten->headp) {
701  ast_log(LOG_ERROR, "Unable to clone variables for extension '%s'\n", name);
702  delete_extension(exten);
703  return NULL;
704  }
705 
707  if (!tmp) {
710  exten->index = 1;
711  } else {
712  sscanf(tmp, "%d", &exten->index);
713  }
714 
717  ast_var_assign(variable_lookup[AST_PHONEPROV_STD_LINEKEYS], "1"));
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int tmp()
Definition: bt_open.c:389
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
#define NULL
Definition: resample.c:96
struct varshead * ast_var_list_clone(struct varshead *head)
Definition: chanvars.c:124
struct varshead * headp
#define ast_log
Definition: astobj2.c:42
structure to hold extensions
#define LOG_ERROR
Definition: logger.h:285
static const char name[]
Definition: cdr_mysql.c:74
char * ast_var_find(const struct varshead *head, const char *name)
Definition: chanvars.c:85
#define ast_var_assign(name, value)
Definition: chanvars.h:40
static const char * variable_lookup[]
static struct extension * delete_extension(struct extension *exten)
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

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

References ao2_alloc, 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, format, phoneprov_file::format, phone_profile::headp, phoneprov_file::mime_type, ast_variable::name, ast_variable::next, NULL, profile_destructor(), S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), and ast_variable::value.

585 {
586  struct phone_profile *profile;
587 
588  if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
589  return;
590  }
591 
592  if (ast_string_field_init(profile, 32)) {
593  profile = unref_profile(profile);
594  return;
595  }
596 
597  if (!(profile->headp = ast_var_list_create())) {
598  profile = unref_profile(profile);
599  return;
600  }
601 
604 
605  ast_string_field_set(profile, name, name);
606  for (; v; v = v->next) {
607  if (!strcasecmp(v->name, "mime_type")) {
609  } else if (!strcasecmp(v->name, "setvar")) {
610  char value_copy[strlen(v->value) + 1];
611 
613  AST_APP_ARG(varname);
614  AST_APP_ARG(varval);
615  );
616 
617  strcpy(value_copy, v->value); /* safe */
618  AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
619  do {
620  if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
621  break;
622  args.varname = ast_strip(args.varname);
623  args.varval = ast_strip(args.varval);
624  if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
625  break;
626  AST_VAR_LIST_INSERT_TAIL(profile->headp, ast_var_assign(args.varname, args.varval));
627  } while (0);
628  } else if (!strcasecmp(v->name, "staticdir")) {
629  ast_string_field_set(profile, staticdir, v->value);
630  } else {
631  struct phoneprov_file *pp_file;
632  char *file_extension;
633  char value_copy[strlen(v->value) + 1];
634 
636  AST_APP_ARG(filename);
637  AST_APP_ARG(mimetype);
638  );
639 
640  if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
641  profile = unref_profile(profile);
642  return;
643  }
644 
645  if ((file_extension = strrchr(pp_file->format, '.')))
646  file_extension++;
647 
648  strcpy(value_copy, v->value); /* safe */
649  AST_STANDARD_APP_ARGS(args, value_copy);
650 
651  /* Mime type order of preference
652  * 1) Specific mime-type defined for file in profile
653  * 2) Mime determined by extension
654  * 3) Default mime type specified in profile
655  * 4) text/plain
656  */
657  ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
658  (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
659 
660  if (!strcasecmp(v->name, "static_file")) {
661  ast_string_field_set(pp_file, format, args.filename);
662  ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
663  AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
664  /* Add a route for the static files, as their filenames won't change per-user */
665  build_route(pp_file, profile, NULL, NULL);
666  } else {
667  ast_string_field_set(pp_file, format, v->name);
668  ast_string_field_set(pp_file, template, args.filename);
669  AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
670  }
const ast_string_field staticdir
struct ast_variable * next
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_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
const ast_string_field format
const char * ast_http_ftype2mtype(const char *ftype) attribute_pure
Return mime type based on extension.
Definition: http.c:203
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
const char * args
#define NULL
Definition: resample.c:96
structure to hold file data
struct varshead * headp
struct phone_profile::@474 static_files
const ast_string_field default_mime_type
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
static void profile_destructor(void *obj)
static struct phone_profile * unref_profile(struct phone_profile *prof)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static const char name[]
Definition: cdr_mysql.c:74
#define ast_var_assign(name, value)
Definition: chanvars.h:40
structure to hold phone profiles read from phoneprov.conf
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:550
struct varshead * ast_var_list_create(void)
Definition: chanvars.c:97
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
struct phone_profile::@475 dynamic_files
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
Definition: search.h:40
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
const ast_string_field mime_type
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ 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
userUser to link to the route (NULL means static route)
uriURI of the route

Definition at line 507 of file res_phoneprov.c.

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

Referenced by build_profile(), and build_user_routes().

512 {
513  struct http_route *route;
514 
515  if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
516  return;
517  }
518 
519  if (ast_string_field_init(route, 32)) {
520  ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
521  route = unref_route(route);
522  return;
523  }
524 
525  ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
526  route->user = user;
527  route->file = pp_file;
528  route->profile = profile;
529 
static char user[512]
static void route_destructor(void *obj)
const ast_string_field format
const ast_string_field uri
struct phoneprov_file * file
#define ast_log
Definition: astobj2.c:42
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct user * user
struct phone_profile * profile
#define LOG_ERROR
Definition: logger.h:285
static struct http_route * unref_route(struct http_route *route)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
structure to hold http routes (valid URIs, and the files they link to)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

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

784 {
785  struct user *user;
786 
787  if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
788  return NULL;
789  }
790 
791  if (ast_string_field_init(user, 64)) {
792  user = unref_user(user);
793  return NULL;
794  }
795 
static char user[512]
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void user_destructor(void *obj)
Free all memory associated with a user.
structure to hold users read from users.conf
static struct user * unref_user(struct user *user)

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

References 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.

851 {
852  struct phoneprov_file *pp_file;
853  struct ast_str *str;
854 
855  if (!(str = ast_str_create(16))) {
856  return -1;
857  }
858 
859  AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
const char * str
Definition: app_jack.c:147
structure to hold file data
struct phone_profile * profile
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct phone_profile::@475 dynamic_files
Definition: search.h:40
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ delete_extension()

static struct extension* delete_extension ( struct extension exten)
static

Definition at line 672 of file res_phoneprov.c.

Referenced by user_destructor().

680 {

◆ delete_file()

static void delete_file ( struct phoneprov_file file)
static

Definition at line 388 of file res_phoneprov.c.

Referenced by profile_destructor().

393 {

◆ delete_profiles()

static void delete_profiles ( void  )
static

Delete all phone profiles, freeing their memory.

Definition at line 567 of file res_phoneprov.c.

572 {
573  if (!profiles) {
574  return;
struct ao2_container * profiles

◆ delete_providers()

static void delete_providers ( void  )
static

Delete all providers.

Definition at line 373 of file res_phoneprov.c.

378 {
379  if (!providers) {
380  return;
struct ao2_container * providers

◆ delete_routes()

static void delete_routes ( void  )
static

Delete all http routes, freeing their memory.

Definition at line 493 of file res_phoneprov.c.

498 {
499  if (!http_routes) {
500  return;
struct ao2_container * http_routes

◆ delete_users()

static void delete_users ( void  )
static

Delete all users.

Definition at line 766 of file res_phoneprov.c.

774 {

◆ extension_delete_cb()

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

Definition at line 1573 of file res_phoneprov.c.

References CMP_MATCH.

1574  {
1575  return 0;
1576  }
1577  return CMP_MATCH;
1578 }
1579 
1580 static int extension_delete_cb(void *obj, void *arg, void *data, int flags)
1581 {
1582  struct user *user = obj;
1583  char *provider_name = data;
const ast_string_field provider_name
structure to hold users read from users.conf
static int extension_delete_cb(void *obj, void *arg, void *data, int flags)

◆ extensions_delete_cb()

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

Definition at line 1563 of file res_phoneprov.c.

Referenced by ast_phoneprov_provider_unregister().

1571 {

◆ find_profile()

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

Return a phone profile looked up by name.

Definition at line 539 of file res_phoneprov.c.

544 {

◆ find_provider()

static struct phoneprov_provider* find_provider ( char *  name)
static

Definition at line 367 of file res_phoneprov.c.

Referenced by ast_phoneprov_provider_register().

372 {

◆ find_user()

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

Return a user looked up by name.

Definition at line 727 of file res_phoneprov.c.

References ao2_cleanup, and NULL.

Referenced by pp_each_extension_helper().

727 {
728  ao2_cleanup(user);
729 
730  return NULL;
#define NULL
Definition: resample.c:96
structure to hold users read from users.conf
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ get_defaults()

static struct varshead* get_defaults ( void  )
static

Definition at line 1191 of file res_phoneprov.c.

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, value, ast_variable::value, var, and variable_lookup.

1199 {
1200  struct ast_config *phoneprov_cfg, *cfg = CONFIG_STATUS_FILEINVALID;
1201  const char *value;
1202  struct ast_variable *v;
1203  struct ast_var_t *var;
1204  struct ast_flags config_flags = { 0 };
1205  struct varshead *defaults = ast_var_list_create();
1206 
1207  if (!defaults) {
1208  ast_log(LOG_ERROR, "Unable to create default var list.\n");
1209  return NULL;
1210  }
1211 
1212  if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1213  || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1214  ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1215  ast_var_list_destroy(defaults);
1216  return NULL;
1217  }
1218 
1219  value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER]);
1220  if (!value) {
1221  struct in_addr addr;
1222  value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER_IFACE]);
1223  if (value) {
1224  lookup_iface(value, &addr);
1225  value = ast_inet_ntoa(addr);
1226  }
1227  }
1228  if (value) {
1230  AST_VAR_LIST_INSERT_TAIL(defaults, var);
1231  } else {
1232  ast_log(LOG_WARNING, "Unable to find a valid server address or name.\n");
1233  }
1234 
1235  value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_SERVER_PORT]);
1236  if (!value) {
1237  if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
1238  value = ast_variable_retrieve(cfg, "general", "bindport");
1239  }
1240  }
1242  if (cfg && cfg != CONFIG_STATUS_FILEINVALID) {
1243  ast_config_destroy(cfg);
1244  }
1245  AST_VAR_LIST_INSERT_TAIL(defaults, var);
1246 
1247  value = ast_variable_retrieve(phoneprov_cfg, "general", pp_general_lookup[AST_PHONEPROV_STD_PROFILE]);
1248  if (!value) {
1249  ast_log(LOG_ERROR, "Unable to load default profile.\n");
1250  ast_config_destroy(phoneprov_cfg);
1251  ast_var_list_destroy(defaults);
1252  return NULL;
1253  }
1255  AST_VAR_LIST_INSERT_TAIL(defaults, var);
1256  ast_config_destroy(phoneprov_cfg);
1257 
1258  if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
1259  ast_log(LOG_ERROR, "Unable to load users.conf\n");
1260  ast_var_list_destroy(defaults);
1261  return NULL;
1262  }
1263 
1264  /* Go ahead and load global variables from users.conf so we can append to profiles */
1265  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
1266  if (!strcasecmp(v->name, pp_user_lookup[AST_PHONEPROV_STD_VOICEMAIL_EXTEN])) {
1267  var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_VOICEMAIL_EXTEN], v->value);
1268  AST_VAR_LIST_INSERT_TAIL(defaults, var);
1269  }
1270  if (!strcasecmp(v->name, pp_user_lookup[AST_PHONEPROV_STD_EXTENSION_LENGTH])) {
1271  var = ast_var_assign(variable_lookup[AST_PHONEPROV_STD_EXTENSION_LENGTH], v->value);
struct ast_variable * next
static const char * pp_general_lookup[]
static const char * pp_user_lookup[]
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
static int lookup_iface(const char *iface, struct in_addr *address)
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define LOG_ERROR
Definition: logger.h:285
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
#define ast_var_assign(name, value)
Definition: chanvars.h:40
static const char * variable_lookup[]
Structure used to handle boolean flags.
Definition: utils.h:199
struct varshead * ast_var_list_create(void)
Definition: chanvars.c:97
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void ast_var_list_destroy(struct varshead *head)
Definition: chanvars.c:109
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51

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

1157 {
1158  int fd = a->fd;
1159  switch(cmd) {
1160  case CLI_INIT:
1161  e->command = "phoneprov show routes";
1162  e->usage =
1163  "Usage: phoneprov show routes\n"
1164  " Lists all registered phoneprov http routes.\n";
1165  return NULL;
1166  case CLI_GENERATE:
1167  return NULL;
1168  }
1169 
1170  /* This currently iterates over routes twice, but it is the only place I've needed
1171  * to really separate static an dynamic routes, so I've just left it this way. */
1172  ast_cli(a->fd, "Static routes\n\n");
1173  ast_cli(a->fd, FORMATS, "Profile", "Relative URI", "Physical location");
1174 
1176 
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
static int route_list_cb(void *obj, void *arg, void *data, int flags)
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
struct ao2_container * http_routes

◆ http_route_cmp_fn()

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

Definition at line 332 of file res_phoneprov.c.

Referenced by load_module().

342 {

◆ http_route_hash_fn()

static int http_route_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 331 of file res_phoneprov.c.

Referenced by load_module().

342 {

◆ load_common()

static int load_common ( void  )
static

Definition at line 1343 of file res_phoneprov.c.

Referenced by load_module().

1351 {
1352  struct ast_config *phoneprov_cfg;
1353  struct ast_flags config_flags = { 0 };
1354  char *cat;
1355 
1356  if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags))
1357  || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
1358  ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
1359  return -1;
1360  }
1361 
1362  cat = NULL;
1363  while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
1364  if (!strcasecmp(cat, "general")) {
1365  continue;
1366  }
1367  build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
1368  }
1369  ast_config_destroy(phoneprov_cfg);
1370 
static void build_profile(const char *name, struct ast_variable *v)
Build a phone profile and add it to the list of phone profiles.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG_STATUS_FILEINVALID
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define LOG_ERROR
Definition: logger.h:285
Structure used to handle boolean flags.
Definition: utils.h:199

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

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

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 
#define NULL
Definition: resample.c:96
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182

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

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_phoneprov_provider_register(), error(), http_route_cmp_fn(), http_route_hash_fn(), load_common(), phoneprov_provider::load_users, LOG_ERROR, LOG_WARNING, MAX_PROFILE_BUCKETS, MAX_PROVIDER_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, NULL, phone_profile_hash_fn(), user_cmp_fn(), and user_hash_fn().

1417 {
1420  if (!profiles) {
1421  ast_log(LOG_ERROR, "Unable to allocate profiles container.\n");
1422  return AST_MODULE_LOAD_DECLINE;
1423  }
1424 
1427  if (!http_routes) {
1428  ast_log(LOG_ERROR, "Unable to allocate routes container.\n");
1429  goto error;
1430  }
1431 
1432  if (load_common()) {
1433  ast_log(LOG_ERROR, "Unable to load provisioning profiles.\n");
1434  goto error;
1435  }
1436 
1439  if (!users) {
1440  ast_log(LOG_ERROR, "Unable to allocate users container.\n");
1441  goto error;
1442  }
1443 
1445  MAX_PROVIDER_BUCKETS, phoneprov_provider_hash_fn, NULL, phoneprov_provider_cmp_fn);
1446  if (!providers) {
1447  ast_log(LOG_ERROR, "Unable to allocate providers container.\n");
1448  goto error;
1449  }
1450 
1451  /* Register ourselves as the provider for sip.conf/users.conf */
1452  if (ast_phoneprov_provider_register(SIPUSERS_PROVIDER_NAME, load_users)) {
1453  ast_log(LOG_WARNING, "Unable register sip/users config provider. Others may succeed.\n");
1454  }
1455 
1457 
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_phoneprov_provider_register(char *provider_name, ast_phoneprov_load_users_cb load_users)
Registers a config provider to phoneprov.
#define LOG_WARNING
Definition: logger.h:274
static int load_users(void)
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
Definition: http.c:673
static int user_hash_fn(const void *obj, const int flags)
static struct ast_custom_function pp_each_user_function
struct ao2_container * profiles
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define NULL
Definition: resample.c:96
list of users found in the config file
static int http_route_cmp_fn(void *obj, void *arg, int flags)
static int load_common(void)
#define MAX_PROFILE_BUCKETS
Definition: res_phoneprov.c:81
#define ast_log
Definition: astobj2.c:42
static int user_cmp_fn(void *obj, void *arg, int flags)
static int phone_profile_cmp_fn(void *obj, void *arg, int flags)
struct ao2_container * providers
static int http_route_hash_fn(const void *obj, const int flags)
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static struct ast_cli_entry pp_cli[]
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_custom_function pp_each_extension_function
#define MAX_PROVIDER_BUCKETS
Definition: res_phoneprov.c:80
static int phone_profile_hash_fn(const void *obj, const int flags)
struct ao2_container * http_routes
#define MAX_ROUTE_BUCKETS
Definition: res_phoneprov.c:82
static struct ast_http_uri phoneprovuri
int error(const char *format,...)
Definition: utils/frame.c:999
#define MAX_USER_BUCKETS
Definition: res_phoneprov.c:83
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508

◆ load_users()

static int load_users ( void  )
static

Definition at line 1273 of file res_phoneprov.c.

1281 {
1282  struct ast_config *cfg;
1283  char *cat;
1284  const char *value;
1285  struct ast_flags config_flags = { 0 };
1286  struct varshead *defaults = get_defaults();
1287 
1288  if (!defaults) {
1289  ast_log(LOG_WARNING, "Unable to load default variables.\n");
1290  return -1;
1291  }
1292 
1293  if (!(cfg = ast_config_load("users.conf", config_flags))
1294  || cfg == CONFIG_STATUS_FILEINVALID) {
1295  ast_log(LOG_WARNING, "Unable to load users.conf\n");
1296  ast_var_list_destroy(defaults);
1297  return -1;
1298  }
1299 
1300  cat = NULL;
1301  while ((cat = ast_category_browse(cfg, cat))) {
1302  const char *tmp;
1303  int i;
1304  struct ast_var_t *varx;
1305  struct ast_var_t *vard;
1306 
1307  if (strcasecmp(cat, "general") && strcasecmp(cat, "authentication")) {
1308  struct varshead *variables = ast_var_list_create();
1309 
1310  if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) {
1311  ast_var_list_destroy(variables);
1312  continue;
1313  }
1314 
1315  /* Transfer the standard variables */
1316  for (i = 0; i < AST_PHONEPROV_STD_VAR_LIST_LENGTH; i++) {
1317  if (pp_user_lookup[i]) {
1318  value = ast_variable_retrieve(cfg, cat, pp_user_lookup[i]);
1319  if (value) {
1320  varx = ast_var_assign(variable_lookup[i],
1321  value);
1322  AST_VAR_LIST_INSERT_TAIL(variables, varx);
1323  }
1324  }
1325  }
1326 
1328  ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
1329  ast_var_list_destroy(variables);
1330  continue;
1331  }
1332 
1333  /* Apply defaults */
1334  AST_VAR_LIST_TRAVERSE(defaults, vard) {
1335  if (ast_var_find(variables, vard->name)) {
1336  continue;
1337  }
1338  varx = ast_var_assign(vard->name, vard->value);
1339  AST_VAR_LIST_INSERT_TAIL(variables, varx);
1340  }
1341 
static const char * pp_user_lookup[]
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
static int tmp()
Definition: bt_open.c:389
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static struct varshead * get_defaults(void)
char name[0]
Definition: chanvars.h:31
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
char * value
Definition: chanvars.h:30
char * ast_var_find(const struct varshead *head, const char *name)
Definition: chanvars.c:85
#define ast_var_assign(name, value)
Definition: chanvars.h:40
static const char * variable_lookup[]
Structure used to handle boolean flags.
Definition: utils.h:199
struct varshead * ast_var_list_create(void)
Definition: chanvars.c:97
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define AST_VAR_LIST_TRAVERSE(head, var)
Definition: chanvars.h:49
void ast_var_list_destroy(struct varshead *head)
Definition: chanvars.c:109
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51

◆ lookup_iface()

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

Definition at line 337 of file res_phoneprov.c.

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

Referenced by get_defaults().

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;
char * address
Definition: f2c.h:59
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int errno
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct in_addr __ourip
for use in lookup_iface

◆ phone_profile_cmp_fn()

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

Definition at line 309 of file res_phoneprov.c.

312 {

◆ phone_profile_hash_fn()

static int phone_profile_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 308 of file res_phoneprov.c.

Referenced by load_module().

312 {

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

870 {
871  struct http_route *route;
872  struct ast_str *result;
873  char path[PATH_MAX];
874  char *file = NULL;
875  char *server;
876  int len;
877  int fd;
878  struct ast_str *http_header;
879 
880  if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
881  ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
882  return 0;
883  }
884 
885  if (!(route = ao2_find(http_routes, uri, OBJ_SEARCH_KEY))) {
886  goto out404;
887  }
888 
889  snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
890 
891  if (!route->user) { /* Static file */
892 
893  fd = open(path, O_RDONLY);
894  if (fd < 0) {
895  goto out500;
896  }
897 
898  len = lseek(fd, 0, SEEK_END);
899  lseek(fd, 0, SEEK_SET);
900  if (len < 0) {
901  ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
902  close(fd);
903  goto out500;
904  }
905 
906  http_header = ast_str_create(80);
907  ast_str_set(&http_header, 0, "Content-type: %s\r\n",
908  route->file->mime_type);
909 
910  ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
911 
912  close(fd);
913  route = unref_route(route);
914  return 0;
915  } else { /* Dynamic file */
916  struct ast_str *tmp;
917 
918  len = load_file(path, &file);
919  if (len < 0) {
920  ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
921  if (file) {
922  ast_free(file);
923  }
924 
925  goto out500;
926  }
927 
928  if (!file) {
929  goto out500;
930  }
931 
932  if (!(tmp = ast_str_create(len))) {
933  if (file) {
934  ast_free(file);
935  }
936 
937  goto out500;
938  }
939 
940  /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
941  * the IP address we are listening on that the phone contacted for this config file */
942 
943  server = ast_var_find(AST_LIST_FIRST(&route->user->extensions)->headp,
945 
946  if (!server) {
947  union {
948  struct sockaddr sa;
949  struct sockaddr_in sa_in;
950  } name;
951  socklen_t namelen = sizeof(name.sa);
952  int res;
953 
954  if ((res = getsockname(ast_iostream_get_fd(ser->stream), &name.sa, &namelen))) {
955  ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
956  } else {
957  struct extension *exten_iter;
958  const char *newserver = ast_inet_ntoa(name.sa_in.sin_addr);
959 
960  AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
961  AST_VAR_LIST_INSERT_TAIL(exten_iter->headp,
963  }
964  }
965  }
966 
967  ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
968 
969  ast_free(file);
970 
971  http_header = ast_str_create(80);
972  ast_str_set(&http_header, 0, "Content-type: %s\r\n",
973  route->file->mime_type);
974 
975  if (!(result = ast_str_create(512))) {
976  ast_log(LOG_ERROR, "Could not create result string!\n");
977  if (tmp) {
978  ast_free(tmp);
979  }
980  ast_free(http_header);
981  goto out500;
982  }
983  ast_str_append(&result, 0, "%s", ast_str_buffer(tmp));
984 
985  ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
986  ast_free(tmp);
987 
988  route = unref_route(route);
989 
990  return 0;
991  }
992 
993 out404:
994  ast_http_error(ser, 404, "Not Found", uri);
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
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:648
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
const ast_string_field template
static int tmp()
Definition: bt_open.c:389
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:1091
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream&#39;s file descriptor.
Definition: iostream.c:84
struct phoneprov_file * file
#define NULL
Definition: resample.c:96
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:456
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:1065
struct varshead * headp
#define ast_log
Definition: astobj2.c:42
structure to hold extensions
const char * method
Definition: res_pjsip.c:4335
static int load_file(const char *filename, char **ret)
Read a TEXT file into a string and return the length.
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
struct user * user
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct user::@476 extensions
static struct http_route * unref_route(struct http_route *route)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * ast_var_find(const struct varshead *head, const char *name)
Definition: chanvars.c:85
#define ast_var_assign(name, value)
Definition: chanvars.h:40
static const char * variable_lookup[]
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_iostream * stream
Definition: tcptls.h:160
struct ao2_container * http_routes
static PGresult * result
Definition: cel_pgsql.c:88
Definition: search.h:40
#define PATH_MAX
Definition: asterisk.h:40
structure to hold http routes (valid URIs, and the files they link to)
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
const ast_string_field mime_type

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

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, exten, user::extensions, make_ari_stubs::file, find_user(), extension::headp, len(), load_file(), LOG_WARNING, ast_custom_function::name, PATH_MAX, pp_each_user_read(), pp_each_user_read2(), str, and user.

Referenced by pp_each_extension_read2().

1054  {
1055  .name = "PP_EACH_USER",
1056  .read = pp_each_user_read,
1057  .read2 = pp_each_user_read2,
1058 };
1059 
1060 /*! \brief A dialplan function that can be used to output a template for each extension attached to a user */
1061 static int pp_each_extension_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len)
1062 {
1063  struct user *user;
1064  struct extension *exten;
1065  char path[PATH_MAX];
1066  char *file;
1067  int filelen;
1068  struct ast_str *str;
1070  AST_APP_ARG(mac);
1071  AST_APP_ARG(template);
1072  );
1073 
1074  AST_STANDARD_APP_ARGS(args, data);
1075 
1076  if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
1077  ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
1078  return 0;
1079  }
1080 
1081  if (!(user = find_user(args.mac))) {
1082  ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
1083  return 0;
1084  }
1085 
1086  snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
1087  filelen = load_file(path, &file);
1088  if (filelen < 0) {
1089  ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
1090  if (file) {
1091  ast_free(file);
1092  }
1093  return 0;
1094  }
1095 
1096  if (!file) {
1097  return 0;
1098  }
1099 
1100  if (!(str = ast_str_create(filelen))) {
1101  return 0;
1102  }
1103 
1104  AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
1105  ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
1106  if (buf) {
1107  size_t slen = len;
1108  ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1109  } else {
1110  ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1111  }
1112  }
1113 
static char user[512]
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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...
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:1091
const char * str
Definition: app_jack.c:147
const char * args
static struct user * find_user(const char *macaddress)
Return a user looked up by name.
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct varshead * headp
#define ast_log
Definition: astobj2.c:42
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: main/utils.c:1919
structure to hold extensions
static int load_file(const char *filename, char **ret)
Read a TEXT file into a string and return the length.
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static int pp_each_user_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct user::@476 extensions
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:182
static int pp_each_user_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
structure to hold users read from users.conf
Definition: search.h:40
#define PATH_MAX
Definition: asterisk.h:40
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define AST_APP_ARG(name)
Define an application argument.

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

1123 {

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

References NULL, and pp_each_extension_helper().

1123 {

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

Referenced by pp_each_user_read2().

997  :
998  route = unref_route(route);
999  ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
1000  return 0;
1001 }
1002 
1003 /*! \brief A dialplan function that can be used to print a string for each phoneprov user */
1004 static int pp_each_user_helper(struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len)
1005 {
1006  char *tmp;
1007  struct ao2_iterator i;
1008  struct user *user;
1009  struct ast_str *str;
1011  AST_APP_ARG(string);
1012  AST_APP_ARG(exclude_mac);
1013  );
1014  AST_STANDARD_APP_ARGS(args, data);
1015 
1016  if (!(str = ast_str_create(16))) {
1017  return -1;
1018  }
1019 
1020  /* Fix data by turning %{ into ${ */
1021  while ((tmp = strstr(args.string, "%{")))
1022  *tmp = '$';
1023 
1024  i = ao2_iterator_init(users, 0);
1025  while ((user = ao2_iterator_next(&i))) {
1026  if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
1027  continue;
1028  }
1029  ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
1030  if (buf) {
1031  size_t slen = len;
1032  ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
1033  } else {
1034  ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
1035  }
static char user[512]
Main Channel structure associated with a channel.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
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:648
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
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:1091
const char * str
Definition: app_jack.c:147
const char * args
list of users found in the config file
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: main/utils.c:1919
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct user::@476 extensions
static struct http_route * unref_route(struct http_route *route)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
structure to hold users read from users.conf
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const ast_string_field macaddress
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.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define AST_APP_ARG(name)
Define an application argument.

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

Referenced by pp_each_extension_helper().

1045 {

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

References NULL, and pp_each_user_helper().

Referenced by pp_each_extension_helper().

1045 {

◆ profile_destructor()

static void profile_destructor ( void *  obj)
static

Definition at line 544 of file res_phoneprov.c.

References ao2_find, ast_free, AST_LIST_REMOVE_HEAD, ast_var_delete(), delete_file(), phone_profile::dynamic_files, ast_var_t::entries, make_ari_stubs::file, phone_profile::headp, OBJ_SEARCH_KEY, phone_profile::static_files, and var.

Referenced by build_profile().

544 {
546 }
547 
548 static void profile_destructor(void *obj)
549 {
550  struct phone_profile *profile = obj;
551  struct phoneprov_file *file;
552  struct ast_var_t *var;
553 
554  while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) {
555  delete_file(file);
556  }
557 
558  while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) {
559  delete_file(file);
560  }
561 
562  while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) {
563  ast_var_delete(var);
564  }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define var
Definition: ast_expr2f.c:614
struct ao2_container * profiles
structure to hold file data
struct varshead * headp
struct phone_profile::@474 static_files
static void profile_destructor(void *obj)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
static const char name[]
Definition: cdr_mysql.c:74
struct ast_var_t::@249 entries
structure to hold phone profiles read from phoneprov.conf
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct phone_profile::@475 dynamic_files
Definition: search.h:40
static void delete_file(struct phoneprov_file *file)

◆ provider_destructor()

static void provider_destructor ( void *  obj)
static

Definition at line 382 of file res_phoneprov.c.

Referenced by ast_phoneprov_provider_register().

387 {

◆ reload()

static int reload ( void  )
static

Definition at line 1462 of file res_phoneprov.c.

1464  :
1465  unload_module();
1466  return AST_MODULE_LOAD_DECLINE;
1467 }
1468 
1469 static int reload(void)
1470 {
1471  struct ao2_iterator i;
1472  struct phoneprov_provider *provider;
1473 
1474  /* Clean everything except the providers */
1475  delete_routes();
1476  delete_users();
1477  delete_profiles();
1478 
1479  /* Reload the profiles */
1480  if (load_common()) {
1481  ast_log(LOG_ERROR, "Unable to reload provisioning profiles.\n");
1482  unload_module();
1483  return AST_MODULE_LOAD_DECLINE;
1484  }
1485 
1486  /* For each provider, reload the users */
1488  i = ao2_iterator_init(providers, 0);
1489  for(; (provider = ao2_iterator_next(&i)); ao2_ref(provider, -1)) {
1490  if (provider->load_users()) {
1491  ast_log(LOG_ERROR, "Unable to load provider '%s' users. Reload aborted.\n", provider->provider_name);
1492  continue;
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 int load_common(void)
structure to hold config providers
#define ast_log
Definition: astobj2.c:42
static int unload_module(void)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ao2_container * providers
#define LOG_ERROR
Definition: logger.h:285
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static void delete_users(void)
Delete all users.
ast_phoneprov_load_users_cb load_users
const ast_string_field provider_name
static int reload(void)
static struct prometheus_metrics_provider provider
Definition: bridges.c:178
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ route_destructor()

static void route_destructor ( void *  obj)
static

Definition at line 485 of file res_phoneprov.c.

Referenced by build_route().

490 {

◆ route_list_cb()

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

Definition at line 1133 of file res_phoneprov.c.

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

1141 {
1142  int fd = *(int *)arg;
1143  struct http_route *route = obj;
1144 
1145  if (data && route->user) {
1146  ast_cli(fd, FORMATD, route->user->provider_name, route->profile->name, route->uri, route->file->template);
const ast_string_field template
const ast_string_field uri
struct phoneprov_file * file
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const ast_string_field name
struct user * user
struct phone_profile * profile
const ast_string_field provider_name
structure to hold http routes (valid URIs, and the files they link to)

◆ routes_delete_cb()

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

Definition at line 732 of file res_phoneprov.c.

References ao2_find, user::macaddress, OBJ_SEARCH_KEY, and http_route::user.

735 {
736  return ao2_find(users, macaddress, OBJ_SEARCH_KEY);
737 }
738 
739 static int routes_delete_cb(void *obj, void *arg, int flags)
740 {
741  struct http_route *route = obj;
742  struct user *user = route->user;
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static int routes_delete_cb(void *obj, void *arg, int flags)
list of users found in the config file
struct user * user
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
structure to hold users read from users.conf
structure to hold http routes (valid URIs, and the files they link to)

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

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.

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));
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
#define ast_var_assign(name, value)
Definition: chanvars.h:40
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
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition: chanvars.h:51

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1372 of file res_phoneprov.c.

1380 {
1385 
1386  /* This cleans up the sip.conf/users.conf provider (called specifically for clarity) */
1387  ast_phoneprov_provider_unregister(SIPUSERS_PROVIDER_NAME);
1388 
1389  /* This cleans up the framework which also cleans up the providers. */
1390  delete_profiles();
1392  profiles = NULL;
1393  delete_routes();
1394  delete_users();
1396  http_routes = NULL;
1397  ao2_cleanup(users);
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_custom_function pp_each_user_function
static void delete_profiles(void)
Delete all phone profiles, freeing their memory.
static void delete_routes(void)
Delete all http routes, freeing their memory.
struct ao2_container * profiles
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
Definition: http.c:705
#define NULL
Definition: resample.c:96
list of users found in the config file
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct ast_cli_entry pp_cli[]
static struct ast_custom_function pp_each_extension_function
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ao2_container * http_routes
static struct ast_http_uri phoneprovuri
void ast_phoneprov_provider_unregister(char *provider_name)
Unegisters a config provider from phoneprov and frees its resources.
static void delete_users(void)
Delete all users.

◆ unref_profile()

static struct phone_profile* unref_profile ( struct phone_profile prof)
static

Definition at line 531 of file res_phoneprov.c.

Referenced by build_profile(), and user_destructor().

536 {

◆ unref_route()

static struct http_route* unref_route ( struct http_route route)
static

Definition at line 478 of file res_phoneprov.c.

Referenced by build_route().

483 {

◆ unref_user()

static struct user* unref_user ( struct user user)
static

Definition at line 719 of file res_phoneprov.c.

727 {

◆ user_cmp_fn()

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

Definition at line 320 of file res_phoneprov.c.

Referenced by load_module().

325 {

◆ user_destructor()

static void user_destructor ( void *  obj)
static

Free all memory associated with a user.

Definition at line 745 of file res_phoneprov.c.

References AST_LIST_REMOVE_HEAD, CMP_MATCH, delete_extension(), exten, user::extensions, user::profile, and unref_profile().

745  {
746  return CMP_MATCH;
747  }
748  return 0;
749 }
750 
751 /*! \brief Free all memory associated with a user */
752 static void user_destructor(void *obj)
753 {
754  struct user *user = obj;
755  struct extension *exten;
756 
757  while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
758  exten = delete_extension(exten);
759  }
760 
761  if (user->profile) {
762  user->profile = unref_profile(user->profile);
763  }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
structure to hold extensions
struct phone_profile * profile
static struct phone_profile * unref_profile(struct phone_profile *prof)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct user::@476 extensions
static void user_destructor(void *obj)
Free all memory associated with a user.
structure to hold users read from users.conf
static struct extension * delete_extension(struct extension *exten)
Definition: search.h:40

◆ user_hash_fn()

static int user_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 319 of file res_phoneprov.c.

Referenced by load_module().

325 {

Variable Documentation

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

◆ http_routes

struct ao2_container* http_routes

Definition at line 330 of file res_phoneprov.c.

◆ phoneprovuri

struct ast_http_uri phoneprovuri
static

Definition at line 1182 of file res_phoneprov.c.

◆ pp_cli

struct ast_cli_entry pp_cli[]
static
Initial value:
= {
AST_CLI_DEFINE(handle_show_routes, "Show registered phoneprov http routes"),
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
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 1178 of file res_phoneprov.c.

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

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

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

◆ profiles

struct ao2_container* profiles

Definition at line 307 of file res_phoneprov.c.

◆ providers

struct ao2_container* providers

◆ users

Definition at line 318 of file res_phoneprov.c.

Referenced by load_users().

◆ variable_lookup

const char* variable_lookup[]
static

Definition at line 182 of file res_phoneprov.c.

Referenced by ast_phoneprov_provider_register(), and get_defaults().