Thu Apr 28 2011 17:16:17

Asterisk developer's documentation


res_config_ldap.c File Reference

ldap plugin for portable configuration engine (ARA) More...

#include "asterisk.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <ldap.h>
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
Include dependency graph for res_config_ldap.c:

Go to the source code of this file.

Data Structures

struct  category_and_metric
struct  ldap_table_config
 Table configuration. More...
struct  table_configs
 Should be locked before using it. More...

Defines

#define MAXRESULT   2048
#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"
#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void append_var_and_value_to_filter (struct ast_str **filter, struct ldap_table_config *table_config, const char *name, const char *value)
 Append a name=value filter string. The filter string can grow.
static char * cleaned_basedn (struct ast_channel *channel, const char *basedn)
 caller should free returned pointer
static int compare_categories (const void *a, const void *b)
 Sorting alogrithm for qsort to find the order of the variables a and b.
static struct ast_configconfig_ldap (const char *basedn, const char *table_name, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *sugg_incl, const char *who_asked)
 See Asterisk doc.
static const char * convert_attribute_name_from_ldap (struct ldap_table_config *table_config, const char *attribute_name)
 Convert ldap attribute name to variable name - Should be locked before using it.
static const char * convert_attribute_name_to_ldap (struct ldap_table_config *table_config, const char *attribute_name)
 Convert variable name to ldap attribute name - Should be locked before using it.
static int is_ldap_connect_error (int err)
static struct ast_variableldap_loadentry (struct ldap_table_config *table_config, const char *dn)
 Get LDAP entry by dn and return attributes as variables - Should be locked before using it This is used for setting the default values of an object(i.e., with accountBaseDN)
static int ldap_reconnect (void)
static void ldap_table_config_add_attribute (struct ldap_table_config *table_config, const char *attribute_name, const char *attribute_value)
 add attribute to table config - Should be locked before using it
static int load_module (void)
static int parse_config (void)
static struct ast_variablerealtime_ldap (const char *basedn, const char *table_name, va_list ap)
 See Asterisk doc.
static struct ast_variable ** realtime_ldap_base (unsigned int *entries_count_ptr, const char *basedn, const char *table_name,...)
 same as realtime_ldap_base_ap but take variable arguments count list
static struct ast_variable ** realtime_ldap_base_ap (unsigned int *entries_count_ptr, const char *basedn, const char *table_name, va_list ap)
 LDAP base function.
static struct ast_variablerealtime_ldap_entry_to_var (struct ldap_table_config *table_config, LDAPMessage *ldap_entry)
 Get variables from ldap entry attributes - Should be locked before using it.
static struct ast_variable ** realtime_ldap_result_to_vars (struct ldap_table_config *table_config, LDAPMessage *ldap_result_msg, unsigned int *entries_count_ptr)
 Get variables from ldap entry attributes - Should be locked before using it.
static char * realtime_ldap_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_configrealtime_multi_ldap (const char *basedn, const char *table_name, va_list ap)
 See Asterisk doc.
static int reload (void)
static int replace_string_in_string (char *string, const char *search, const char *by)
 Replace <search> by <by> in string. No check is done on string allocated size !
static int semicolon_count_str (const char *somestr)
 for the semicolon delimiter
static int semicolon_count_var (struct ast_variable *var)
static char * substituted (struct ast_channel *channel, const char *string)
 caller should free returned pointer
static struct ldap_table_configtable_config_for_table_name (const char *table_name)
 Find a table_config - Should be locked before using it.
static struct ldap_table_configtable_config_new (const char *table_name)
 Create a new table_config.
static void table_configs_free (void)
 Free table_config.
static int unload_module (void)
static int update2_ldap (const char *basedn, const char *table_name, va_list ap)
static int update_ldap (const char *basedn, const char *table_name, const char *attribute, const char *lookup, va_list ap)
static struct ast_variablevariable_named (struct ast_variable *var, const char *name)
 Find variable by name.

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "LDAP realtime interface" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static char base_distinguished_name [512]
static struct ldap_table_configbase_table_config
static time_t connect_time
static struct ast_cli_entry ldap_cli []
static struct ast_config_engine ldap_engine
static ast_mutex_t ldap_lock = AST_MUTEX_INIT_VALUE
static LDAP * ldapConn
static char pass [512]
static struct ldap_table_configstatic_table_config
static struct table_configs table_configs
static char url [512]
static char user [512]
static int version = 3

Detailed Description

ldap plugin for portable configuration engine (ARA)

Author:
Mark Spencer <markster@digium.com>
Manuel Guesdon
Carl-Einar Thorner <cthorner@voicerd.com>
Russell Bryant <russell@digium.com>

Definition in file res_config_ldap.c.


Define Documentation

#define MAXRESULT   2048
#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"

Definition at line 60 of file res_config_ldap.c.

Referenced by config_ldap(), and parse_config().

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 61 of file res_config_ldap.c.

Referenced by parse_config().


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 1783 of file res_config_ldap.c.

static void __unreg_module ( void  ) [static]

Definition at line 1783 of file res_config_ldap.c.

static void append_var_and_value_to_filter ( struct ast_str **  filter,
struct ldap_table_config table_config,
const char *  name,
const char *  value 
) [static]

Append a name=value filter string. The filter string can grow.

Definition at line 683 of file res_config_ldap.c.

References ast_debug, ast_str_append(), ast_strdupa, convert_attribute_name_to_ldap(), len(), name, and replace_string_in_string().

Referenced by realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

{
   char *new_name = NULL;
   char *new_value = NULL;
   char *like_pos = strstr(name, " LIKE");

   ast_debug(2, "name='%s' value='%s'\n", name, value);

   if (like_pos) {
      int len = like_pos - name;
      name = new_name = ast_strdupa(name);
      new_name[len] = '\0';
      value = new_value = ast_strdupa(value);
      replace_string_in_string(new_value, "\\_", "_");
      replace_string_in_string(new_value, "%", "*");
   }

   name = convert_attribute_name_to_ldap(table_config, name);

   ast_str_append(filter, 0, "(%s=%s)", name, value);
}
static char* cleaned_basedn ( struct ast_channel channel,
const char *  basedn 
) [static]

caller should free returned pointer

Definition at line 633 of file res_config_ldap.c.

References ast_debug, ast_strlen_zero(), len(), and substituted().

Referenced by realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

{
   char *cbasedn = NULL;
   if (basedn) {
      char *p = NULL;
      cbasedn = substituted(channel, basedn);
      if (*cbasedn == '"') {
         cbasedn++;
         if (!ast_strlen_zero(cbasedn)) {
            int len = strlen(cbasedn);
            if (cbasedn[len - 1] == '"')
               cbasedn[len - 1] = '\0';

         }
      }
      p = cbasedn;
      while (*p) {
         if (*p == '|')
            *p = ',';
         p++;
      }
   }
   ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
   return cbasedn;
}
static int compare_categories ( const void *  a,
const void *  b 
) [static]

Sorting alogrithm for qsort to find the order of the variables a and b.

Parameters:
apointer to category_and_metric struct
bpointer to category_and_metric struct
Return values:
-1for if b is greater
0zero for equal
1if a is greater

Definition at line 1001 of file res_config_ldap.c.

References category_and_metric::metric, category_and_metric::name, and category_and_metric::var_metric.

Referenced by config_ldap().

{
   const struct category_and_metric *as = a;
   const struct category_and_metric *bs = b;

   if (as->metric < bs->metric)
      return -1;
   else if (as->metric > bs->metric)
      return 1;
   else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0)
      return strcmp(as->name, bs->name);

   /* if the metric and the category name is the same, we check the variable metric */
   if (as->var_metric < bs->var_metric)
      return -1;
   else if (as->var_metric > bs->var_metric)
      return 1;

   return 0;
}
static struct ast_config* config_ldap ( const char *  basedn,
const char *  table_name,
const char *  file,
struct ast_config cfg,
struct ast_flags  config_flags,
const char *  sugg_incl,
const char *  who_asked 
) [static, read]

See Asterisk doc.

This is for Static Realtime (again: I think...)

load the configuration stuff for the .conf files called on a reload

Note:
Since the items come back in random order, they need to be sorted first, and since the data could easily exceed stack size, this is allocated from the heap.

Definition at line 1029 of file res_config_ldap.c.

References ast_calloc, ast_category_append(), ast_category_new(), ast_config_internal_load(), ast_debug, ast_log(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), compare_categories(), free, LOG_ERROR, LOG_WARNING, category_and_metric::metric, name, category_and_metric::name, realtime_ldap_base(), RES_CONFIG_LDAP_CONF, ast_variable::value, category_and_metric::var_metric, category_and_metric::variable_name, variable_named(), and category_and_metric::variable_value.

{
   unsigned int vars_count = 0;
   struct ast_variable **vars;
   int i = 0;
   struct ast_variable *new_v = NULL;
   struct ast_category *cur_cat = NULL;
   const char *last_category = NULL;
   int last_category_metric = 0;
   struct category_and_metric *categories;
   struct ast_variable **p;

   if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
      ast_log(LOG_ERROR, "Cannot configure myself.\n");
      return NULL;
   }

   vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename",
            file, "commented", "FALSE", NULL);

   if (!vars) {
      ast_log(LOG_WARNING, "Could not find config '%s' in database.\n", file);
      return NULL;
   }

   /*!\note Since the items come back in random order, they need to be sorted
    * first, and since the data could easily exceed stack size, this is
    * allocated from the heap.
    */
   if (!(categories = ast_calloc(sizeof(*categories), vars_count)))
      return NULL;

   for (vars_count = 0, p = vars; *p; p++) {
      struct ast_variable *category = variable_named(*p, "category");
      struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
      struct ast_variable *var_name = variable_named(*p, "variable_name");
      struct ast_variable *var_val = variable_named(*p, "variable_value");
      struct ast_variable *var_metric = variable_named(*p, "var_metric");
      struct ast_variable *dn = variable_named(*p, "dn");
         
      ast_debug(1, "category: %s\n", category->value);
      ast_debug(1, "var_name: %s\n", var_name->value);
      ast_debug(1, "var_val: %s\n", var_val->value);
      ast_debug(1, "cat_metric: %s\n", cat_metric->value);

      if (!category) {
         ast_log(LOG_ERROR,
               "No category name in entry '%s'  for file '%s'.\n",
               (dn ? dn->value : "?"), file);
      } else if (!cat_metric) {
         ast_log(LOG_ERROR,
               "No category metric in entry '%s'(category: %s) for file '%s'.\n",
               (dn ? dn->value : "?"), category->value, file);
      } else if (!var_metric) {
         ast_log(LOG_ERROR,
               "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
               (dn ? dn->value : "?"), category->value, file);
      } else if (!var_name) {
         ast_log(LOG_ERROR,
               "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
               (dn ? dn->value : "?"), category->value,
               cat_metric->value, file);
      } else if (!var_val) {
         ast_log(LOG_ERROR,
               "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
               (dn ? dn->value : "?"), category->value,
               cat_metric->value, var_name->value, file);
      } else {
         categories[vars_count].name = category->value;
         categories[vars_count].metric = atoi(cat_metric->value);
         categories[vars_count].variable_name = var_name->value;
         categories[vars_count].variable_value = var_val->value;
         categories[vars_count].var_metric = atoi(var_metric->value);
         vars_count++;
      }
   }

   qsort(categories, vars_count, sizeof(*categories), compare_categories);

   for (i = 0; i < vars_count; i++) {
      if (!strcmp(categories[i].variable_name, "#include")) {
         struct ast_flags flags = { 0 };
         if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked))
            break;
         continue;
      }

      if (!last_category || strcmp(last_category, categories[i].name) ||
         last_category_metric != categories[i].metric) {
         cur_cat = ast_category_new(categories[i].name, table_name, -1);
         if (!cur_cat)
            break;
         last_category = categories[i].name;
         last_category_metric = categories[i].metric;
         ast_category_append(cfg, cur_cat);
      }

      if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name)))
         break;

      ast_variable_append(cur_cat, new_v);
   }

   free(vars);
   free(categories);

   return cfg;
}
static const char* convert_attribute_name_from_ldap ( struct ldap_table_config table_config,
const char *  attribute_name 
) [static]

Convert ldap attribute name to variable name - Should be locked before using it.

Definition at line 240 of file res_config_ldap.c.

References ARRAY_LEN, ldap_table_config::attributes, base_table_config, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by realtime_ldap_entry_to_var(), and realtime_ldap_result_to_vars().

{
   int i = 0;
   struct ldap_table_config *configs[] = { table_config, base_table_config };

   for (i = 0; i < ARRAY_LEN(configs); i++) {
      struct ast_variable *attribute;

      if (!configs[i])
         continue;

      attribute = configs[i]->attributes;
      for (; attribute; attribute = attribute->next) {
         if (strcasecmp(attribute_name, attribute->value) == 0)
            return attribute->name;
      }
   }

   return attribute_name;
}
static const char* convert_attribute_name_to_ldap ( struct ldap_table_config table_config,
const char *  attribute_name 
) [static]

Convert variable name to ldap attribute name - Should be locked before using it.

Definition at line 217 of file res_config_ldap.c.

References ARRAY_LEN, ldap_table_config::attributes, base_table_config, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by append_var_and_value_to_filter(), update2_ldap(), and update_ldap().

{
   int i = 0;
   struct ldap_table_config *configs[] = { table_config, base_table_config };

   for (i = 0; i < ARRAY_LEN(configs); i++) {
      struct ast_variable *attribute;

      if (!configs[i])
         continue;

      attribute = configs[i]->attributes;
      for (; attribute; attribute = attribute->next) {
         if (!strcasecmp(attribute_name, attribute->name))
            return attribute->value;
      }
   }

   return attribute_name;
}
static int is_ldap_connect_error ( int  err) [static]

Definition at line 532 of file res_config_ldap.c.

Referenced by ldap_loadentry(), realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

{
   return (err == LDAP_SERVER_DOWN
         || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
}
static struct ast_variable* ldap_loadentry ( struct ldap_table_config table_config,
const char *  dn 
) [static, read]

Get LDAP entry by dn and return attributes as variables - Should be locked before using it This is used for setting the default values of an object(i.e., with accountBaseDN)

< not using this

Definition at line 541 of file res_config_ldap.c.

References ast_debug, ast_log(), ast_mutex_unlock(), ast_realloc, ast_variables_destroy(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, realtime_ldap_result_to_vars(), and var.

Referenced by realtime_ldap_base_ap().

{
   if (!table_config) {
      ast_log(LOG_ERROR, "No table config\n");
      return NULL;
   } else {
      struct ast_variable **vars = NULL;
      struct ast_variable *var = NULL;
      int result = -1;
      LDAPMessage *ldap_result_msg = NULL;
      int tries = 0;

      ast_debug(2, "ldap_loadentry dn=%s\n", dn);

      do {
         result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
                  "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
         if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
            ast_log(LOG_WARNING,
               "Failed to query database. Try %d/3\n",
               tries + 1);
            tries++;
            if (tries < 3) {
               usleep(500000L * tries);
               if (ldapConn) {
                  ldap_unbind_ext_s(ldapConn, NULL, NULL);
                  ldapConn = NULL;
               }
               if (!ldap_reconnect())
                  break;
            }
         }
      } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));

      if (result != LDAP_SUCCESS) {
         ast_log(LOG_WARNING,
               "Failed to query database. Check debug for more info.\n");
         ast_debug(2, "dn=%s\n", dn);
         ast_debug(2, "Query Failed because: %s\n",
            ldap_err2string(result));
         ast_mutex_unlock(&ldap_lock);
         return NULL;
      } else {
         int num_entry = 0;
         unsigned int *entries_count_ptr = NULL; /*!< not using this */
         if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
            ast_debug(3, "num_entry: %d\n", num_entry);

            vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
            if (num_entry > 1)
               ast_log(LOG_NOTICE, "More than one entry for dn=%s. Take only 1st one\n", dn);
         } else {
            ast_debug(2, "Could not find any entry dn=%s.\n", dn);
         }
      }
      ldap_msgfree(ldap_result_msg);

      /* Chopping \a vars down to one variable */
      if (vars != NULL) {
         struct ast_variable **p = vars;
         p++;
         var = *p;
         while (var) {
            ast_variables_destroy(var);
            p++;
         }
         vars = ast_realloc(vars, sizeof(struct ast_variable *));
      }

      var = *vars;

      return var;
   }
}
static int ldap_reconnect ( void  ) [static]
Note:
ldap_lock should have been locked before calling this function.

Definition at line 1684 of file res_config_ldap.c.

References ast_debug, ast_log(), ast_strlen_zero(), LOG_ERROR, and LOG_WARNING.

Referenced by ldap_loadentry(), load_module(), realtime_ldap_base_ap(), reload(), update2_ldap(), and update_ldap().

{
   int bind_result = 0;
   struct berval cred;

   if (ldapConn) {
      ast_debug(2, "Everything seems fine.\n");
      return 1;
   }

   if (ast_strlen_zero(url)) {
      ast_log(LOG_ERROR, "Not enough parameters to connect to ldap database\n");
      return 0;
   }

   if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
      ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
      return 0;
   }

   if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
      ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
   }

   if (!ast_strlen_zero(user)) {
      ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
      cred.bv_val = (char *) pass;
      cred.bv_len = strlen(pass);
      bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
   } else {
      ast_debug(2, "bind %s anonymously\n", url);
      cred.bv_val = NULL;
      cred.bv_len = 0;
      bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
   }
   if (bind_result == LDAP_SUCCESS) {
      ast_debug(2, "Successfully connected to database.\n");
      connect_time = time(NULL);
      return 1;
   } else {
      ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
      ldap_unbind_ext_s(ldapConn, NULL, NULL);
      ldapConn = NULL;
      return 0;
   }
}
static void ldap_table_config_add_attribute ( struct ldap_table_config table_config,
const char *  attribute_name,
const char *  attribute_value 
) [static]

add attribute to table config - Should be locked before using it

Definition at line 180 of file res_config_ldap.c.

References ast_strlen_zero(), ast_variable_new(), ldap_table_config::attributes, ast_variable::next, ldap_table_config::table_name, and var.

Referenced by parse_config().

{
   struct ast_variable *var;

   if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value))
      return;

   if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name)))
      return;

   if (table_config->attributes)
      var->next = table_config->attributes;
   table_config->attributes = var;
}
static int load_module ( void  ) [static]

Definition at line 1522 of file res_config_ldap.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_config_engine_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, ldap_cli, ldap_engine, ldap_lock, ldap_reconnect(), LOG_NOTICE, LOG_WARNING, and parse_config().

{
   if (parse_config() < 0) {
      ast_log(LOG_NOTICE, "Cannot load LDAP RealTime driver.\n");
      return 0;
   }

   ast_mutex_lock(&ldap_lock);

   if (!ldap_reconnect()) 
      ast_log(LOG_WARNING, "Couldn't establish connection. Check debug.\n");

   ast_config_engine_register(&ldap_engine);
   ast_verb(1, "LDAP RealTime driver loaded.\n");
   ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));

   ast_mutex_unlock(&ldap_lock);

   return 0;
}
int parse_config ( void  ) [static]

< using the [config] context for Static RealTime

Definition at line 1591 of file res_config_ldap.c.

References ldap_table_config::additional_filter, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_INSERT_HEAD, ast_log(), ast_strdup, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), base_table_config, config, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ldap_table_config::entry, ldap_table_config_add_attribute(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, RES_CONFIG_LDAP_CONF, RES_CONFIG_LDAP_DEFAULT_BASEDN, s, static_table_config, table_config_for_table_name(), table_config_new(), table_configs_free(), ast_variable::value, and var.

Referenced by load_module(), and reload().

{
   struct ast_config *config;
   struct ast_flags config_flags = {0};
   const char *s, *host;
   int port;
   char *category_name = NULL;

   config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
   if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
      ast_log(LOG_WARNING, "Cannot load configuration %s\n", RES_CONFIG_LDAP_CONF);
      return -1;
   }

   if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
      ast_log(LOG_WARNING, "No directory user found, anonymous binding as default.\n");
      user[0] = '\0';
   } else 
      ast_copy_string(user, s, sizeof(user));

   if (!ast_strlen_zero(user)) {
      if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
         ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
         ast_copy_string(pass, "asterisk", sizeof(pass));
      } else {
         ast_copy_string(pass, s, sizeof(pass));
      }
   }

   /* URL is preferred, use host and port if not found */
   if ((s = ast_variable_retrieve(config, "_general", "url"))) {
      ast_copy_string(url, s, sizeof(url));
   } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
      if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
         ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
         port = 389;
      }

      snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
   } else {
      ast_log(LOG_ERROR, "No directory URL or host found.\n");
      ast_config_destroy(config);
      return -1;
   }

   if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
      ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
      ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
   } else 
      ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));

   if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
      ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
      version = 3;
   } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
      ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
      version = 3;
   }

   table_configs_free();

   while ((category_name = ast_category_browse(config, category_name))) {
      int is_general = (strcasecmp(category_name, "_general") == 0);
      int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
      struct ast_variable *var = ast_variable_browse(config, category_name);
      
      if (var) {
         struct ldap_table_config *table_config =
            table_config_for_table_name(category_name);
         if (!table_config) {
            table_config = table_config_new(category_name);
            AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
            if (is_general)
               base_table_config = table_config;
            if (is_config)
               static_table_config = table_config;
         }
         for (; var; var = var->next) {
            if (!strcasecmp(var->name, "additionalFilter")) {
               table_config->additional_filter = ast_strdup(var->value);
            } else {
               ldap_table_config_add_attribute(table_config, var->name, var->value);
            }
         }
      }
   }

   ast_config_destroy(config);

   return 1;
}
static struct ast_variable* realtime_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

See Asterisk doc.

For Realtime Dynamic(i.e., switch, queues, and directory) -- I think

Definition at line 904 of file res_config_ldap.c.

References free, ast_variable::next, realtime_ldap_base_ap(), and var.

{
   struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
   struct ast_variable *var = NULL;

   if (vars) {
      struct ast_variable *last_var = NULL;
      struct ast_variable **p = vars;
      while (*p) {
         if (last_var) {
            while (last_var->next)
               last_var = last_var->next;
            last_var->next = *p;
         } else {
            var = *p;
            last_var = var;
         }
         p++;
      }
      free(vars);
   }
   return var;
}
static struct ast_variable** realtime_ldap_base ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
  ... 
) [static, read]

same as realtime_ldap_base_ap but take variable arguments count list

Definition at line 887 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

{
   struct ast_variable **vars = NULL;
   va_list ap;

   va_start(ap, table_name);
   vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
   va_end(ap);

   return vars;
}
static struct ast_variable** realtime_ldap_base_ap ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

LDAP base function.

Returns:
a null terminated array of ast_variable (one per entry) or NULL if no entry is found or if an error occured caller should free the returned array and ast_variables
Parameters:
entries_count_ptris a pointer to found entries count (can be NULL)
basednis the base DN
table_nameis the table_name (used dor attribute convertion and additional filter)
apcontains null terminated list of pairs name/value

Definition at line 715 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_variables_destroy(), base_table_config, cleaned_basedn(), filter(), is_ldap_connect_error(), ldap_loadentry(), ldap_lock, ldap_reconnect(), LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, ldap_table_config::next, realtime_ldap_result_to_vars(), table_config_for_table_name(), and ast_variable::value.

Referenced by realtime_ldap(), realtime_ldap_base(), and realtime_multi_ldap().

{
   struct ast_variable **vars = NULL;
   const char *newparam = NULL;
   const char *newval = NULL;
   struct ldap_table_config *table_config = NULL;
   char *clean_basedn = cleaned_basedn(NULL, basedn);
   struct ast_str *filter = NULL;
   int tries = 0;
   int result = 0;
   LDAPMessage *ldap_result_msg = NULL;

   if (!table_name) {
      ast_log(LOG_WARNING, "No table_name specified.\n");
      ast_free(clean_basedn);
      return NULL;
   } 

   if (!(filter = ast_str_create(80))) {
      ast_free(clean_basedn);
      return NULL;
   }

   /* Get the first parameter and first value in our list of passed paramater/value pairs  */
   newparam = va_arg(ap, const char *);
   newval = va_arg(ap, const char *);

   if (!newparam || !newval) {
      ast_log(LOG_WARNING, "Realtime retrieval requires at least 1 parameter"
         " and 1 value to search on.\n");
      ast_free(filter);
      ast_free(clean_basedn);
      return NULL;
   }

   ast_mutex_lock(&ldap_lock);

   /* We now have our complete statement; Lets connect to the server and execute it.  */
   if (!ldap_reconnect()) {
      ast_mutex_unlock(&ldap_lock);
      ast_free(filter);
      ast_free(clean_basedn);
      return NULL;
   }

   table_config = table_config_for_table_name(table_name);
   if (!table_config) {
      ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
      ast_mutex_unlock(&ldap_lock);
      ast_free(filter);
      ast_free(clean_basedn);
      return NULL;
   }

   ast_str_append(&filter, 0, "(&");

   if (table_config && table_config->additional_filter)
      ast_str_append(&filter, 0, "%s", table_config->additional_filter);
   if (table_config != base_table_config && base_table_config && 
      base_table_config->additional_filter) {
      ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
   }

   /* Create the first part of the query using the first parameter/value pairs we just extracted */
   /*   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */

   append_var_and_value_to_filter(&filter, table_config, newparam, newval);
   while ((newparam = va_arg(ap, const char *))) {
      newval = va_arg(ap, const char *);
      append_var_and_value_to_filter(&filter, table_config, newparam, newval);
   }
   ast_str_append(&filter, 0, ")");

   do {
      /* freeing ldap_result further down */
      result = ldap_search_ext_s(ldapConn, clean_basedn,
              LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
              &ldap_result_msg);
      if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
         ast_log(LOG_DEBUG, "Failed to query database. Try %d/10\n",
            tries + 1);
         if (++tries < 10) {
            usleep(1);
            if (ldapConn) {
               ldap_unbind_ext_s(ldapConn, NULL, NULL);
               ldapConn = NULL;
            }
            if (!ldap_reconnect())
               break;
         }
      }
   } while (result != LDAP_SUCCESS && tries < 10 && is_ldap_connect_error(result));

   if (result != LDAP_SUCCESS) {
      ast_log(LOG_WARNING, "Failed to query database. Check debug for more info.\n");
      ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
      ast_log(LOG_WARNING, "Query Failed because: %s\n", ldap_err2string(result));
   } else {
      /* this is where we create the variables from the search result 
       * freeing this \a vars outside this function */
      if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
         /* is this a static var or some other? they are handled different for delimited values */
         vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
      } else {
         ast_debug(1, "Could not find any entry matching %s in base dn %s.\n",
            ast_str_buffer(filter), clean_basedn);
      }

      ldap_msgfree(ldap_result_msg);

      /* TODO: get the default variables from the accountBaseDN, not implemented with delimited values */
      if (vars) {
         struct ast_variable **p = vars;
         while (*p) {
            struct ast_variable *append_var = NULL;
            struct ast_variable *tmp = *p;
            while (tmp) {
               if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
                  /* Get the variable to compare with for the defaults */
                  struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
                  
                  while (base_var) {
                     struct ast_variable *next = base_var->next;
                     struct ast_variable *test_var = *p;
                     int base_var_found = 0;

                     /* run throught the default values and fill it inn if it is missing */
                     while (test_var) {
                        if (strcasecmp(test_var->name, base_var->name) == 0) {
                           base_var_found = 1;
                           break;
                        } else
                           test_var = test_var->next;
                     }
                     if (base_var_found) {
                        base_var->next = NULL;
                        ast_variables_destroy(base_var);
                        base_var = next;
                     } else {
                        if (append_var)
                           base_var->next = append_var;
                        else
                           base_var->next = NULL;
                        append_var = base_var;
                        base_var = next;
                     }
                  }
               }
               if (!tmp->next && append_var) {
                  tmp->next = append_var;
                  tmp = NULL;
               } else
                  tmp = tmp->next;
            }
            p++;
         }
      }
   }

   if (filter)
      ast_free(filter);

   if (clean_basedn)
      ast_free(clean_basedn);

   ast_mutex_unlock(&ldap_lock);

   return vars;
}
static struct ast_variable* realtime_ldap_entry_to_var ( struct ldap_table_config table_config,
LDAPMessage *  ldap_entry 
) [static, read]

Get variables from ldap entry attributes - Should be locked before using it.

Returns:
a linked list of ast_variable variables.

Definition at line 265 of file res_config_ldap.c.

References ast_debug, ast_strlen_zero(), ast_variable_new(), convert_attribute_name_from_ldap(), ast_variable::next, ldap_table_config::table_name, and var.

Referenced by realtime_ldap_result_to_vars().

{
   BerElement *ber = NULL;
   struct ast_variable *var = NULL;
   struct ast_variable *prev = NULL;
   int is_delimited = 0;
   int i = 0;
   char *ldap_attribute_name;
   struct berval *value;
   int pos = 0;

   ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);

   while (ldap_attribute_name) {
      struct berval **values = NULL;
      const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
      int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;

      values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
      if (values) {
         struct berval **v;
         char *valptr;

         for (v = values; *v; v++) {
            value = *v;
            valptr = value->bv_val;
            ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
            if (is_realmed_password_attribute) {
               if (!strncasecmp(valptr, "{md5}", 5)) {
                  valptr += 5;
               }
               ast_debug(2, "md5: %s\n", valptr);
            }
            if (valptr) {
               /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
               if (is_delimited) {
                  i = 0;
                  pos = 0;
                  while (!ast_strlen_zero(valptr + i)) {
                     if (valptr[i] == ';'){
                        valptr[i] = '\0';
                        if (prev) {
                           prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
                           if (prev->next) {
                              prev = prev->next;
                           }
                        } else {
                           prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
                        }
                        pos = i + 1;
                     }
                     i++;
                  }
               }
               /* for the last delimited value or if the value is not delimited: */
               if (prev) {
                  prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
                  if (prev->next) {
                     prev = prev->next;
                  }
               } else {
                  prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
               }
            }
         }
         ldap_value_free_len(values);
      }
      ldap_memfree(ldap_attribute_name);
      ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
   }
   ber_free(ber, 0);

   return var;
}
static struct ast_variable** realtime_ldap_result_to_vars ( struct ldap_table_config table_config,
LDAPMessage *  ldap_result_msg,
unsigned int *  entries_count_ptr 
) [static, read]

Get variables from ldap entry attributes - Should be locked before using it.

The results are freed outside this function so is the vars array.

Returns:
vars - an array of ast_variable variables terminated with a null.

Definition at line 347 of file res_config_ldap.c.

References ast_calloc, ast_debug, ast_strdup, ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), convert_attribute_name_from_ldap(), free, ast_variable::next, option_debug, realtime_ldap_entry_to_var(), semicolon_count_str(), semicolon_count_var(), static_table_config, ldap_table_config::table_name, ast_variable::value, var, and variable_named().

Referenced by ldap_loadentry(), and realtime_ldap_base_ap().

{
   struct ast_variable **vars;
   int i = 0;
   int tot_count = 0;
   int entry_index = 0;
   LDAPMessage *ldap_entry = NULL;
   BerElement *ber = NULL;
   struct ast_variable *var = NULL;
   struct ast_variable *prev = NULL;
   int is_delimited = 0;
   char *delim_value = NULL;
   int delim_tot_count = 0;
   int delim_count = 0;

   /* First find the total count */
   ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);

   for (tot_count = 0; ldap_entry; tot_count++){ 
      struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
      tot_count += semicolon_count_var(tmp);
      ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
      ast_variables_destroy(tmp);
   }

   if (entries_count_ptr)
      *entries_count_ptr = tot_count;
   /* Now that we have the total count we allocate space and create the variables
    * Remember that each element in vars is a linked list that points to realtime variable.
    * If the we are dealing with a static realtime variable we create a new element in the \a vars array for each delimited
    * value in \a variable_value; otherwise, we keep \a vars static and increase the length of the linked list of variables in the array element.
    * This memory must be freed outside of this function. */
   vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);

   ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);

   i = 0;

   /* For each static realtime variable we may create several entries in the \a vars array if it's delimited */
   for (entry_index = 0; ldap_entry; ) { 
      int pos = 0;
      delim_value = NULL;
      delim_tot_count = 0;
      delim_count = 0;
      
      do { /* while delim_count */

         /* Starting new static var */
         char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
         struct berval *value;
         while (ldap_attribute_name) {
         
            const char *attribute_name =
               convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
            int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
            struct berval **values = NULL;

            values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
            if (values) {
               struct berval **v;
               char *valptr;

               for (v = values; *v; v++) {
                  value = *v;
                  valptr = value->bv_val;
                  if (is_realmed_password_attribute) {
                     if (strncasecmp(valptr, "{md5}", 5) == 0) {
                        valptr += 5;
                     }
                     ast_debug(2, "md5: %s\n", valptr);
                  }
                  if (valptr) {
                     if (delim_value == NULL 
                        && !is_realmed_password_attribute 
                        && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {

                        delim_value = ast_strdup(valptr);

                        if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
                           ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
                           is_delimited = 1;
                        }
                     }

                     if (is_delimited != 0 
                        && !is_realmed_password_attribute 
                        && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
                        /* for non-Static RealTime, first */

                        for (i = pos; !ast_strlen_zero(valptr + i); i++) {
                           ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
                           if (delim_value[i] == ';') {
                              delim_value[i] = '\0';

                              ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
                     
                              if (prev) {
                                 prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
                                 if (prev->next) {
                                    prev = prev->next;
                                 }
                              } else {
                                 prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
                              }
                              pos = i + 1;

                              if (static_table_config == table_config) {
                                 break;
                              }
                           }
                        }
                        if (ast_strlen_zero(valptr + i)) {
                           ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
                           /* Last delimited value */
                           ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
                           if (prev) {
                              prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
                              if (prev->next) {
                                 prev = prev->next;
                              }
                           } else {
                              prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
                           }
                           /* Remembering to free memory */
                           is_delimited = 0;
                           pos = 0;
                        }
                        free(delim_value);
                        delim_value = NULL;
                        
                        ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
                     } else {
                        /* not delimited */
                        if (delim_value) {
                           free(delim_value);
                           delim_value = NULL;
                        }
                        ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);

                        if (prev) {
                           prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
                           if (prev->next) {
                              prev = prev->next;
                           }
                        } else {
                           prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
                        }
                     }
                  }
               } /*!< for (v = values; *v; v++) */
               ldap_value_free_len(values);
            }/*!< if (values) */
            ldap_memfree(ldap_attribute_name);
            ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
         } /*!< while (ldap_attribute_name) */
         ber_free(ber, 0);
         if (static_table_config == table_config) {
            if (option_debug > 2) {
               const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
               const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
               if (tmpdebug && tmpdebug2) {
                  ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value);
               }
            }
            vars[entry_index++] = var;
            prev = NULL;
         }

         delim_count++;
      } while (delim_count <= delim_tot_count && static_table_config == table_config);

      if (static_table_config != table_config) {
         ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__);
            
         vars[entry_index++] = var;
         prev = NULL;
      }
      ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
   } /*!< end for loop over ldap_entry */

   return vars;
}
static char * realtime_ldap_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1731 of file res_config_ldap.c.

References ast_cli(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, connect_time, ast_cli_args::fd, status, and ast_cli_entry::usage.

{
   char status[256], credentials[100] = "";
   int ctimesec = time(NULL) - connect_time;

   switch (cmd) {
   case CLI_INIT:
      e->command = "realtime show ldap status";
      e->usage =
         "Usage: realtime show ldap status\n"
         "               Shows connection information for the LDAP RealTime driver\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (!ldapConn)
      return CLI_FAILURE;

   if (!ast_strlen_zero(url)) 
      snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);

   if (!ast_strlen_zero(user))
      snprintf(credentials, sizeof(credentials), " with username %s", user);

   if (ctimesec > 31536000) {
      ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
            status, credentials, ctimesec / 31536000,
            (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
            (ctimesec % 3600) / 60, ctimesec % 60);
   } else if (ctimesec > 86400) {
      ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
            status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
            (ctimesec % 3600) / 60, ctimesec % 60);
   } else if (ctimesec > 3600) {
      ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
            status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
            ctimesec % 60);
   } else if (ctimesec > 60) {
      ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
               ctimesec / 60, ctimesec % 60);
   } else {
      ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
   }

   return CLI_SUCCESS;
}
static struct ast_config* realtime_multi_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

See Asterisk doc.

this function will be called for the switch statment if no match is found with the realtime_ldap function(i.e. it is a failover); however, the ast_load_realtime wil match on wildcharacters also depending on what the mode is set to this is an area of asterisk that could do with a lot of modification I think this function returns Realtime dynamic objects

Definition at line 936 of file res_config_ldap.c.

References ast_category_append(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_log(), ast_strdupa, ast_variable_append(), free, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, ldap_table_config::next, realtime_ldap_base_ap(), ast_variable::value, and var.

{
        char *op;
        const char *initfield = NULL;
        const char *newparam, *newval;
   struct ast_variable **vars =
      realtime_ldap_base_ap(NULL, basedn, table_name, ap);
   struct ast_config *cfg = NULL;

        newparam = va_arg(ap, const char *);
        newval = va_arg(ap, const char *);
        if (!newparam || !newval) {
            ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
            return NULL;
        }
        initfield = ast_strdupa(newparam);
        if ((op = strchr(initfield, ' '))) {
                *op = '\0';
        }

   if (vars) {
      cfg = ast_config_new();
      if (!cfg) {
         ast_log(LOG_ERROR, "Unable to create a config!\n");
      } else {
         struct ast_variable **p = vars;

         while (*p) {
            struct ast_category *cat = NULL;
            cat = ast_category_new("", table_name, -1);
            if (!cat) {
               ast_log(LOG_ERROR, "Unable to create a new category!\n");
               break;
            } else {
               struct ast_variable *var = *p;
               while (var) {
                  struct ast_variable *next = var->next;
                                                if (initfield && !strcmp(initfield, var->name)) {
                                                        ast_category_rename(cat, var->value);
                                                }
                  var->next = NULL;
                  ast_variable_append(cat, var);
                  var = next;
               }
            }
            ast_category_append(cfg, cat);
            p++;
         }
      }
      free(vars);
   }
   return cfg;

}
static int reload ( void  ) [static]

Definition at line 1564 of file res_config_ldap.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, ldap_lock, ldap_reconnect(), LOG_NOTICE, LOG_WARNING, and parse_config().

{
   /* Aquire control before doing anything to the module itself. */
   ast_mutex_lock(&ldap_lock);

   if (ldapConn) {
      ldap_unbind_ext_s(ldapConn, NULL, NULL);
      ldapConn = NULL;
   }

   if (parse_config() < 0) {
      ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
      ast_mutex_unlock(&ldap_lock);
      return 0;
   }     

   if (!ldap_reconnect()) 
      ast_log(LOG_WARNING, "Couldn't establish connection. Check debug.\n");

   ast_verb(2, "LDAP RealTime reloaded.\n");

   /* Done reloading. Release lock so others can now use driver. */
   ast_mutex_unlock(&ldap_lock);

   return 0;
}
static int replace_string_in_string ( char *  string,
const char *  search,
const char *  by 
) [static]

Replace <search> by <by> in string. No check is done on string allocated size !

Definition at line 660 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

{
   int search_len = strlen(search);
   int by_len = strlen(by);
   int replaced = 0;
   char *p = strstr(string, search);
   if (p) {
      replaced = 1;
      while (p) {
         if (by_len == search_len)
            memcpy(p, by, by_len);
         else {
            memmove(p + by_len, p + search_len,
                  strlen(p + search_len) + 1);
            memcpy(p, by, by_len);
         }
         p = strstr(p + by_len, search);
      }
   }
   return replaced;
}
static int semicolon_count_str ( const char *  somestr) [static]

for the semicolon delimiter

Parameters:
somestr- pointer to a string
Returns:
number of occurances of the delimiter(semicolon)

Definition at line 152 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

{
   int count = 0;

   for (; *somestr; somestr++) {
      if (*somestr == ';')
         count++;
   }

   return count;
} 
static int semicolon_count_var ( struct ast_variable var) [static]

Definition at line 167 of file res_config_ldap.c.

References ast_debug, semicolon_count_str(), ast_variable::value, and variable_named().

Referenced by realtime_ldap_result_to_vars().

{
   struct ast_variable *var_value = variable_named(var, "variable_value");

   if (!var_value)
      return 0;

   ast_debug(1, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);

   return semicolon_count_str(var_value->value);
}
static char* substituted ( struct ast_channel channel,
const char *  string 
) [static]

caller should free returned pointer

Definition at line 618 of file res_config_ldap.c.

References ast_calloc, ast_debug, ast_strlen_zero(), MAXRESULT, and pbx_substitute_variables_helper().

Referenced by cleaned_basedn().

{
#define MAXRESULT 2048
   char *ret_string = NULL;

   if (!ast_strlen_zero(string)) {
      ret_string = ast_calloc(1, MAXRESULT);
      pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
   }
   ast_debug(2, "substituted: string: '%s' => '%s' \n",
      string, ret_string);
   return ret_string;
}
static struct ldap_table_config* table_config_for_table_name ( const char *  table_name) [static, read]

Find a table_config - Should be locked before using it.

Note:
This function assumes ldap_lock to be locked.

Definition at line 124 of file res_config_ldap.c.

References AST_LIST_TRAVERSE, ldap_table_config::entry, and ldap_table_config::table_name.

Referenced by parse_config(), realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

{
   struct ldap_table_config *c = NULL;

   AST_LIST_TRAVERSE(&table_configs, c, entry) {
      if (!strcmp(c->table_name, table_name))
         break;
   }

   return c;
}
static struct ldap_table_config* table_config_new ( const char *  table_name) [static, read]

Create a new table_config.

Definition at line 105 of file res_config_ldap.c.

References ast_calloc, ast_strdup, free, and ldap_table_config::table_name.

Referenced by parse_config().

{
   struct ldap_table_config *p;

   if (!(p = ast_calloc(1, sizeof(*p))))
      return NULL;

   if (table_name) {
      if (!(p->table_name = ast_strdup(table_name))) {
         free(p);
         return NULL;
      }
   }

   return p;
}
static void table_configs_free ( void  ) [static]
static int unload_module ( void  ) [static]

Definition at line 1543 of file res_config_ldap.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_config_engine_deregister(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, ldap_cli, ldap_engine, ldap_lock, and table_configs_free().

{
   /* Aquire control before doing anything to the module itself. */
   ast_mutex_lock(&ldap_lock);

   table_configs_free();

   if (ldapConn) {
      ldap_unbind_ext_s(ldapConn, NULL, NULL);
      ldapConn = NULL;
   }
   ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
   ast_config_engine_deregister(&ldap_engine);
   ast_verb(1, "LDAP RealTime unloaded.\n");

   /* Unlock so something else can destroy the lock. */
   ast_mutex_unlock(&ldap_lock);

   return 0;
}
static int update2_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

Definition at line 1329 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_realloc, ast_str_append(), ast_str_buffer(), ast_str_create(), base_table_config, cleaned_basedn(), convert_attribute_name_to_ldap(), filter(), free, is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

{
   int error = 0;
   LDAPMessage *ldap_entry = NULL;
   LDAPMod **ldap_mods;
   const char *newparam = NULL;
   const char *newval = NULL;
   char *dn;
   int num_entries = 0;
   int i = 0;
   int mods_size = 0;
   int mod_exists = 0;
   struct ldap_table_config *table_config = NULL;
   char *clean_basedn = NULL;
   struct ast_str *filter = NULL;
   int tries = 0;
   int result = 0;
   LDAPMessage *ldap_result_msg = NULL;

   if (!table_name) {
      ast_log(LOG_WARNING, "No table_name specified.\n");
      return -1;
   } 

   if (!(filter = ast_str_create(80)))
      return -1;

   ast_mutex_lock(&ldap_lock);

   /* We now have our complete statement; Lets connect to the server and execute it.  */
   if (!ldap_reconnect()) {
      ast_mutex_unlock(&ldap_lock);
      ast_free(filter);
      return -1;
   }

   table_config = table_config_for_table_name(table_name);
   if (!table_config) {
      ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
      ast_mutex_unlock(&ldap_lock);
      ast_free(filter);
      return -1;
   }

   clean_basedn = cleaned_basedn(NULL, basedn);

   /* Create the filter with the table additional filter and the parameter/value pairs we were given */
   ast_str_append(&filter, 0, "(&");
   if (table_config && table_config->additional_filter) {
      ast_str_append(&filter, 0, "%s", table_config->additional_filter);
   }
   if (table_config != base_table_config && base_table_config
      && base_table_config->additional_filter) {
      ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
   }

   /* Get multiple lookup keyfields and values */
   while ((newparam = va_arg(ap, const char *))) {
      newval = va_arg(ap, const char *);
      append_var_and_value_to_filter(&filter, table_config, newparam, newval);
   }
   ast_str_append(&filter, 0, ")");

   /* Create the modification array with the parameter/value pairs we were given, 
    * if there are several parameters with the same name, we collect them into 
    * one parameter/value pair and delimit them with a semicolon */
   newparam = va_arg(ap, const char *);
   newparam = convert_attribute_name_to_ldap(table_config, newparam);
   newval = va_arg(ap, const char *);
   if (!newparam || !newval) {
      ast_log(LOG_WARNING,
            "LINE(%d): need at least one parameter to modify.\n", __LINE__);
      ast_free(filter);
      ast_free(clean_basedn);
      return -1;
   }

   mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
   ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
   ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));

   ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
   ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
   strcpy(ldap_mods[0]->mod_type, newparam);

   ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
   ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
   strcpy(ldap_mods[0]->mod_values[0], newval);

   while ((newparam = va_arg(ap, const char *))) {
      newparam = convert_attribute_name_to_ldap(table_config, newparam);
      newval = va_arg(ap, const char *);
      mod_exists = 0;

      for (i = 0; i < mods_size - 1; i++) {
         if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
            /* We have the parameter allready, adding the value as a semicolon delimited value */
            ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
            strcat(ldap_mods[i]->mod_values[0], ";");
            strcat(ldap_mods[i]->mod_values[0], newval);
            mod_exists = 1;   
            break;
         }
      }

      /* create new mod */
      if (!mod_exists) {
         mods_size++;
         ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
         ldap_mods[mods_size - 1] = NULL;
         ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));

         ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;

         ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
         strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);

         ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
         ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
         strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
      }
   }
   /* freeing ldap_mods further down */

   do {
      /* freeing ldap_result further down */
      result = ldap_search_ext_s(ldapConn, clean_basedn,
              LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
              &ldap_result_msg);
      if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
         ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n",
            tries + 1);
         tries++;
         if (tries < 3) {
            usleep(500000L * tries);
            if (ldapConn) {
               ldap_unbind_ext_s(ldapConn, NULL, NULL);
               ldapConn = NULL;
            }
            if (!ldap_reconnect())
               break;
         }
      }
   } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));

   if (result != LDAP_SUCCESS) {
      ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n");
      ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
      ast_log(LOG_WARNING, "Query Failed because: %s\n",
         ldap_err2string(result));

      ast_mutex_unlock(&ldap_lock);
      free(filter);
      free(clean_basedn);
      ldap_msgfree(ldap_result_msg);
      ldap_mods_free(ldap_mods, 0);
      return -1;
   }
   /* Ready to update */
   if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
      for (i = 0; option_debug > 2 && i < mods_size - 1; i++)
         ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);

      ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);

      for (i = 0; ldap_entry; i++) { 
         dn = ldap_get_dn(ldapConn, ldap_entry);
         if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) 
            ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
         ldap_memfree(dn);
         ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
      }
   }

   ast_mutex_unlock(&ldap_lock);
   if (filter)
      free(filter);
   if (clean_basedn)
      free(clean_basedn);
   ldap_msgfree(ldap_result_msg);
   ldap_mods_free(ldap_mods, 0);
   return num_entries;
}
static int update_ldap ( const char *  basedn,
const char *  table_name,
const char *  attribute,
const char *  lookup,
va_list  ap 
) [static]

Definition at line 1142 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_calloc, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_realloc, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_strdup, base_table_config, cleaned_basedn(), convert_attribute_name_to_ldap(), filter(), free, is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

{
   int error = 0;
   LDAPMessage *ldap_entry = NULL;
   LDAPMod **ldap_mods;
   const char *newparam = NULL;
   const char *newval = NULL;
   char *dn;
   int num_entries = 0;
   int i = 0;
   int mods_size = 0;
   int mod_exists = 0;
   struct ldap_table_config *table_config = NULL;
   char *clean_basedn = NULL;
   struct ast_str *filter = NULL;
   int tries = 0;
   int result = 0;
   LDAPMessage *ldap_result_msg = NULL;

   if (!table_name) {
      ast_log(LOG_WARNING, "No table_name specified.\n");
      return -1;
   } 

   if (!(filter = ast_str_create(80)))
      return -1;

   if (!attribute || !lookup) {
      ast_log(LOG_WARNING,
            "LINE(%d): search parameters are empty.\n", __LINE__);
      return -1;
   }
   ast_mutex_lock(&ldap_lock);

   /* We now have our complete statement; Lets connect to the server and execute it.  */
   if (!ldap_reconnect()) {
      ast_mutex_unlock(&ldap_lock);
      return -1;
   }

   table_config = table_config_for_table_name(table_name);
   if (!table_config) {
      ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
      ast_mutex_unlock(&ldap_lock);
      return -1;
   }

   clean_basedn = cleaned_basedn(NULL, basedn);

   /* Create the filter with the table additional filter and the parameter/value pairs we were given */
   ast_str_append(&filter, 0, "(&");
   if (table_config && table_config->additional_filter) {
      ast_str_append(&filter, 0, "%s", table_config->additional_filter);
   }
   if (table_config != base_table_config && base_table_config
      && base_table_config->additional_filter) {
      ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
   }
   append_var_and_value_to_filter(&filter, table_config, attribute, lookup);
   ast_str_append(&filter, 0, ")");

   /* Create the modification array with the parameter/value pairs we were given, 
    * if there are several parameters with the same name, we collect them into 
    * one parameter/value pair and delimit them with a semicolon */
   newparam = va_arg(ap, const char *);
   newparam = convert_attribute_name_to_ldap(table_config, newparam);
   newval = va_arg(ap, const char *);
   if (!newparam || !newval) {
      ast_log(LOG_WARNING,
            "LINE(%d): need at least one parameter to modify.\n", __LINE__);
      return -1;
   }

   mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
   ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
   ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));

   ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
   ldap_mods[0]->mod_type = ast_strdup(newparam);

   ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
   ldap_mods[0]->mod_values[0] = ast_strdup(newval);

   while ((newparam = va_arg(ap, const char *))) {
      newparam = convert_attribute_name_to_ldap(table_config, newparam);
      newval = va_arg(ap, const char *);
      mod_exists = 0;

      for (i = 0; i < mods_size - 1; i++) {
         if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
            /* We have the parameter allready, adding the value as a semicolon delimited value */
            ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
            strcat(ldap_mods[i]->mod_values[0], ";");
            strcat(ldap_mods[i]->mod_values[0], newval);
            mod_exists = 1;   
            break;
         }
      }

      /* create new mod */
      if (!mod_exists) {
         mods_size++;
         ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
         ldap_mods[mods_size - 1] = NULL;
         
         ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));

         ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
         strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);

         if (strlen(newval) == 0) {
            ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
         } else {
            ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;

            ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
            ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
            strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
         }
      }
   }
   /* freeing ldap_mods further down */

   do {
      /* freeing ldap_result further down */
      result = ldap_search_ext_s(ldapConn, clean_basedn,
              LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
              &ldap_result_msg);
      if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
         ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n",
            tries + 1);
         tries++;
         if (tries < 3) {
            usleep(500000L * tries);
            if (ldapConn) {
               ldap_unbind_ext_s(ldapConn, NULL, NULL);
               ldapConn = NULL;
            }
            if (!ldap_reconnect())
               break;
         }
      }
   } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));

   if (result != LDAP_SUCCESS) {
      ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n");
      ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
      ast_log(LOG_WARNING, "Query Failed because: %s\n",
         ldap_err2string(result));

      ast_mutex_unlock(&ldap_lock);
      free(filter);
      free(clean_basedn);
      ldap_msgfree(ldap_result_msg);
      ldap_mods_free(ldap_mods, 0);
      return -1;
   }
   /* Ready to update */
   if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
      ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
      for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
         if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
            ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
         } else {
            ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
         }
      }
      ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);

      for (i = 0; ldap_entry; i++) { 
         dn = ldap_get_dn(ldapConn, ldap_entry);
         if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) 
            ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
         ldap_memfree(dn);
         ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
      }
   }

   ast_mutex_unlock(&ldap_lock);
   free(filter);
   free(clean_basedn);
   ldap_msgfree(ldap_result_msg);
   ldap_mods_free(ldap_mods, 0);
   return num_entries;
}
static struct ast_variable* variable_named ( struct ast_variable var,
const char *  name 
) [static, read]

Find variable by name.

Definition at line 137 of file res_config_ldap.c.

References ast_variable::name, ast_variable::next, and var.

Referenced by config_ldap(), realtime_ldap_result_to_vars(), and semicolon_count_var().

{
   for (; var; var = var->next) {
      if (!strcasecmp(name, var->name))
         break;
   }

   return var;
}

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "LDAP realtime interface" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1783 of file res_config_ldap.c.

Definition at line 1783 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 69 of file res_config_ldap.c.

time_t connect_time [static]

Definition at line 71 of file res_config_ldap.c.

Referenced by realtime_ldap_status().

struct ast_cli_entry ldap_cli[] [static]
Initial value:
 {
   AST_CLI_DEFINE(realtime_ldap_status, "Shows connection information for the LDAP RealTime driver"),
}

Definition at line 100 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

Definition at line 1513 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = AST_MUTEX_INIT_VALUE [static]
LDAP* ldapConn [static]

Definition at line 65 of file res_config_ldap.c.

struct table_configs table_configs [static]
char url[512] [static]