Wed Oct 28 13:33:26 2009

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)
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.
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)
 Check if we have a connection error.
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)
 parse the configuration file
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.
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.
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)
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 __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "LDAP realtime interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .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_t) PTHREAD_MUTEX_INITIALIZER )
static LDAP * ldapConn
static char pass [50]
static struct ldap_table_configstatic_table_config
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>

ExtRef:
OpenLDAP http://www.openldap.org

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 1785 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

Definition at line 1785 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 693 of file res_config_ldap.c.

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

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

00696 {
00697    char *new_name = NULL;
00698    char *new_value = NULL;
00699    char *like_pos = strstr(name, " LIKE");
00700 
00701    ast_debug(2, "name='%s' value='%s'\n", name, value);
00702 
00703    if (like_pos) {
00704       int len = like_pos - name;
00705 
00706       name = new_name = ast_strdupa(name);
00707       new_name[len] = '\0';
00708       value = new_value = ast_strdupa(value);
00709       replace_string_in_string(new_value, "\\_", "_");
00710       replace_string_in_string(new_value, "%", "*");
00711    }
00712 
00713    name = convert_attribute_name_to_ldap(table_config, name);
00714 
00715    ast_str_append(filter, 0, "(%s=%s)", name, value);
00716 }

static char* cleaned_basedn ( struct ast_channel channel,
const char *  basedn 
) [static]

Note:
caller should free returned pointer

Definition at line 642 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().

00643 {
00644    char *cbasedn = NULL;
00645    if (basedn) {
00646       char *p = NULL;
00647       cbasedn = substituted(channel, basedn);
00648       if (*cbasedn == '"') {
00649          cbasedn++;
00650          if (!ast_strlen_zero(cbasedn)) {
00651             int len = strlen(cbasedn);
00652             if (cbasedn[len - 1] == '"')
00653                cbasedn[len - 1] = '\0';
00654 
00655          }
00656       }
00657       p = cbasedn;
00658       while (*p) {
00659          if (*p == '|')
00660             *p = ',';
00661          p++;
00662       }
00663    }
00664    ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
00665    return cbasedn;
00666 }

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:
a pointer to category_and_metric struct
b pointer to category_and_metric struct
Return values:
-1 for if b is greater
0 zero for equal
1 if a is greater

Definition at line 1000 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().

01001 {
01002    const struct category_and_metric *as = a;
01003    const struct category_and_metric *bs = b;
01004 
01005    if (as->metric < bs->metric) {
01006       return -1;
01007    } else if (as->metric > bs->metric) {
01008       return 1;
01009    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01010       return strcmp(as->name, bs->name);
01011    } 
01012    /* if the metric and the category name is the same, we check the variable metric */
01013    if (as->var_metric < bs->var_metric) {
01014       return -1;
01015    } else if (as->var_metric > bs->var_metric) {
01016       return 1;
01017    }
01018 
01019    return 0;
01020 }

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_free, ast_log(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), compare_categories(), 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.

01031 {
01032    unsigned int vars_count = 0;
01033    struct ast_variable **vars;
01034    int i = 0;
01035    struct ast_variable *new_v = NULL;
01036    struct ast_category *cur_cat = NULL;
01037    const char *last_category = NULL;
01038    int last_category_metric = 0;
01039    struct category_and_metric *categories;
01040    struct ast_variable **p;
01041 
01042    if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
01043       ast_log(LOG_ERROR, "Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
01044       return NULL;
01045    }
01046 
01047    vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename", file, "commented", "FALSE", NULL);
01048 
01049    if (!vars) {
01050       ast_log(LOG_WARNING, "Could not find config '%s' in database.\n", file);
01051       return NULL;
01052    }
01053 
01054    /*!\note Since the items come back in random order, they need to be sorted
01055     * first, and since the data could easily exceed stack size, this is
01056     * allocated from the heap.
01057     */
01058    if (!(categories = ast_calloc(sizeof(*categories), vars_count))) {
01059       return NULL;
01060    }
01061 
01062    for (vars_count = 0, p = vars; *p; p++) {
01063       struct ast_variable *category = variable_named(*p, "category");
01064       struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
01065       struct ast_variable *var_name = variable_named(*p, "variable_name");
01066       struct ast_variable *var_val = variable_named(*p, "variable_value");
01067       struct ast_variable *var_metric = variable_named(*p, "var_metric");
01068       struct ast_variable *dn = variable_named(*p, "dn");
01069          
01070       ast_debug(3, "category: %s\n", category->value);
01071       ast_debug(3, "var_name: %s\n", var_name->value);
01072       ast_debug(3, "var_val: %s\n", var_val->value);
01073       ast_debug(3, "cat_metric: %s\n", cat_metric->value);
01074 
01075       if (!category) {
01076          ast_log(LOG_ERROR, "No category name in entry '%s'  for file '%s'.\n",
01077                (dn ? dn->value : "?"), file);
01078       } else if (!cat_metric) {
01079          ast_log(LOG_ERROR, "No category metric in entry '%s'(category: %s) for file '%s'.\n",
01080                (dn ? dn->value : "?"), category->value, file);
01081       } else if (!var_metric) {
01082          ast_log(LOG_ERROR, "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
01083                (dn ? dn->value : "?"), category->value, file);
01084       } else if (!var_name) {
01085          ast_log(LOG_ERROR, "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
01086                (dn ? dn->value : "?"), category->value,
01087                cat_metric->value, file);
01088       } else if (!var_val) {
01089          ast_log(LOG_ERROR, "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
01090                (dn ? dn->value : "?"), category->value,
01091                cat_metric->value, var_name->value, file);
01092       } else {
01093          categories[vars_count].name = category->value;
01094          categories[vars_count].metric = atoi(cat_metric->value);
01095          categories[vars_count].variable_name = var_name->value;
01096          categories[vars_count].variable_value = var_val->value;
01097          categories[vars_count].var_metric = atoi(var_metric->value);
01098          vars_count++;
01099       }
01100    }
01101 
01102    qsort(categories, vars_count, sizeof(*categories), compare_categories);
01103 
01104    for (i = 0; i < vars_count; i++) {
01105       if (!strcmp(categories[i].variable_name, "#include")) {
01106          struct ast_flags flags = { 0 };
01107          if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked)) {
01108             break;
01109          }
01110          continue;
01111       }
01112 
01113       if (!last_category || strcmp(last_category, categories[i].name) ||
01114          last_category_metric != categories[i].metric) {
01115 
01116          cur_cat = ast_category_new(categories[i].name, table_name, -1);
01117          if (!cur_cat) {
01118             break;
01119          }
01120          last_category = categories[i].name;
01121          last_category_metric = categories[i].metric;
01122          ast_category_append(cfg, cur_cat);
01123       }
01124 
01125       if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
01126          break;
01127       }
01128 
01129       ast_variable_append(cur_cat, new_v);
01130    }
01131 
01132    ast_free(vars);
01133    ast_free(categories);
01134 
01135    return cfg;
01136 }

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.

Note:
Should be locked before using it

Definition at line 250 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().

00252 {
00253    int i = 0;
00254    struct ldap_table_config *configs[] = { table_config, base_table_config };
00255 
00256    for (i = 0; i < ARRAY_LEN(configs); i++) {
00257       struct ast_variable *attribute;
00258 
00259       if (!configs[i]) {
00260          continue;
00261       }
00262 
00263       attribute = configs[i]->attributes;
00264       for (; attribute; attribute = attribute->next) {
00265          if (strcasecmp(attribute_name, attribute->value) == 0) {
00266             return attribute->name;
00267          }
00268       }
00269    }
00270 
00271    return attribute_name;
00272 }

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

00226 {
00227    int i = 0;
00228    struct ldap_table_config *configs[] = { table_config, base_table_config };
00229 
00230    for (i = 0; i < ARRAY_LEN(configs); i++) {
00231       struct ast_variable *attribute;
00232 
00233       if (!configs[i]) {
00234          continue;
00235       }
00236 
00237       attribute = configs[i]->attributes;
00238       for (; attribute; attribute = attribute->next) {
00239          if (!strcasecmp(attribute_name, attribute->name)) {
00240             return attribute->value;
00241          }
00242       }
00243    }
00244 
00245    return attribute_name;
00246 }

static int is_ldap_connect_error ( int  err  )  [static]

Check if we have a connection error.

Definition at line 545 of file res_config_ldap.c.

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

00546 {
00547    return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00548 }

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

00555 {
00556    if (!table_config) {
00557       ast_log(LOG_ERROR, "No table config\n");
00558       return NULL;
00559    } else {
00560       struct ast_variable **vars = NULL;
00561       struct ast_variable *var = NULL;
00562       int result = -1;
00563       LDAPMessage *ldap_result_msg = NULL;
00564       int tries = 0;
00565 
00566       ast_debug(2, "ldap_loadentry dn=%s\n", dn);
00567 
00568       do {
00569          result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
00570                   "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
00571          if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
00572             ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n", tries + 1);
00573             tries++;
00574             if (tries < 3) {
00575                usleep(500000L * tries);
00576                if (ldapConn) {
00577                   ldap_unbind_ext_s(ldapConn, NULL, NULL);
00578                   ldapConn = NULL;
00579                }
00580                if (!ldap_reconnect()) {
00581                   break;
00582                }
00583             }
00584          }
00585       } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
00586 
00587       if (result != LDAP_SUCCESS) {
00588          ast_log(LOG_WARNING, "Failed to query database. Error: %s.\n", ldap_err2string(result));
00589          ast_debug(2, "dn=%s\n", dn);
00590          ast_mutex_unlock(&ldap_lock);
00591          return NULL;
00592       } else {
00593          int num_entry = 0;
00594          unsigned int *entries_count_ptr = NULL; /*!< not using this */
00595 
00596          if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
00597             ast_debug(3, "num_entry: %d\n", num_entry);
00598 
00599             vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
00600             if (num_entry > 1) {
00601                ast_log(LOG_NOTICE, "More than one entry for dn=%s. Take only 1st one\n", dn);
00602             }
00603          } else {
00604             ast_debug(2, "Could not find any entry dn=%s.\n", dn);
00605          }
00606       }
00607       ldap_msgfree(ldap_result_msg);
00608 
00609       /* Chopping \a vars down to one variable */
00610       if (vars != NULL) {
00611          struct ast_variable **p = vars;
00612          p++;
00613          var = *p;
00614          while (var) {
00615             ast_variables_destroy(var);
00616             p++;
00617          }
00618          vars = ast_realloc(vars, sizeof(struct ast_variable *));
00619       }
00620 
00621       var = *vars;
00622 
00623       return var;
00624    }
00625 }

static int ldap_reconnect ( void   )  [static]

Note:
ldap_lock should have been locked before calling this function.

Definition at line 1686 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().

01687 {
01688    int bind_result = 0;
01689    struct berval cred;
01690 
01691    if (ldapConn) {
01692       ast_debug(2, "Everything seems fine.\n");
01693       return 1;
01694    }
01695 
01696    if (ast_strlen_zero(url)) {
01697       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap database\n");
01698       return 0;
01699    }
01700 
01701    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01702       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01703       return 0;
01704    }
01705 
01706    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01707       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01708    }
01709 
01710    if (!ast_strlen_zero(user)) {
01711       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01712       cred.bv_val = (char *) pass;
01713       cred.bv_len = strlen(pass);
01714       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01715    } else {
01716       ast_debug(2, "bind %s anonymously\n", url);
01717       cred.bv_val = NULL;
01718       cred.bv_len = 0;
01719       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01720    }
01721    if (bind_result == LDAP_SUCCESS) {
01722       ast_debug(2, "Successfully connected to database.\n");
01723       connect_time = time(NULL);
01724       return 1;
01725    } else {
01726       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01727       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01728       ldapConn = NULL;
01729       return 0;
01730    }
01731 }

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

00183 {
00184    struct ast_variable *var;
00185 
00186    if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
00187       return;
00188    }
00189 
00190    if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name))) {
00191       return;
00192    }
00193 
00194    if (table_config->attributes) {
00195       var->next = table_config->attributes;
00196    }
00197    table_config->attributes = var;
00198 }

static int load_module ( void   )  [static]

Definition at line 1520 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_ERROR, LOG_WARNING, and parse_config().

01521 {
01522    if (parse_config() < 0) {
01523       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01524       return 0;
01525    }
01526 
01527    ast_mutex_lock(&ldap_lock);
01528 
01529    if (!ldap_reconnect())  {
01530       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01531    }
01532 
01533    ast_config_engine_register(&ldap_engine);
01534    ast_verb(1, "LDAP RealTime driver loaded.\n");
01535    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01536 
01537    ast_mutex_unlock(&ldap_lock);
01538 
01539    return 0;
01540 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1592 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.

01593 {
01594    struct ast_config *config;
01595    struct ast_flags config_flags = {0};
01596    const char *s, *host;
01597    int port;
01598    char *category_name = NULL;
01599 
01600    config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
01601    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01602       ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
01603       return -1;
01604    }
01605 
01606    if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
01607       ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
01608       user[0] = '\0';
01609    } else {
01610       ast_copy_string(user, s, sizeof(user));
01611    }
01612 
01613    if (!ast_strlen_zero(user)) {
01614       if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
01615          ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
01616          ast_copy_string(pass, "asterisk", sizeof(pass));
01617       } else {
01618          ast_copy_string(pass, s, sizeof(pass));
01619       }
01620    }
01621 
01622    /* URL is preferred, use host and port if not found */
01623    if ((s = ast_variable_retrieve(config, "_general", "url"))) {
01624       ast_copy_string(url, s, sizeof(url));
01625    } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
01626       if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
01627          ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
01628          port = 389;
01629       }
01630 
01631       snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
01632    } else {
01633       ast_log(LOG_ERROR, "No directory URL or host found.\n");
01634       ast_config_destroy(config);
01635       return -1;
01636    }
01637 
01638    if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
01639       ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
01640       ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
01641    } else 
01642       ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
01643 
01644    if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
01645       ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
01646       version = 3;
01647    } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
01648       ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
01649       version = 3;
01650    }
01651 
01652    table_configs_free();
01653 
01654    while ((category_name = ast_category_browse(config, category_name))) {
01655       int is_general = (strcasecmp(category_name, "_general") == 0);
01656       int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
01657       struct ast_variable *var = ast_variable_browse(config, category_name);
01658       
01659       if (var) {
01660          struct ldap_table_config *table_config =
01661             table_config_for_table_name(category_name);
01662          if (!table_config) {
01663             table_config = table_config_new(category_name);
01664             AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
01665             if (is_general)
01666                base_table_config = table_config;
01667             if (is_config)
01668                static_table_config = table_config;
01669          }
01670          for (; var; var = var->next) {
01671             if (!strcasecmp(var->name, "additionalFilter")) {
01672                table_config->additional_filter = ast_strdup(var->value);
01673             } else {
01674                ldap_table_config_add_attribute(table_config, var->name, var->value);
01675             }
01676          }
01677       }
01678    }
01679 
01680    ast_config_destroy(config);
01681 
01682    return 1;
01683 }

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 920 of file res_config_ldap.c.

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

00922 {
00923    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00924    struct ast_variable *var = NULL;
00925 
00926    if (vars) {
00927       struct ast_variable *last_var = NULL;
00928       struct ast_variable **p = vars;
00929       while (*p) {
00930          if (last_var) {
00931             while (last_var->next) {
00932                last_var = last_var->next;
00933             }
00934             last_var->next = *p;
00935          } else {
00936             var = *p;
00937             last_var = var;
00938          }
00939          p++;
00940       }
00941       free(vars);
00942    }
00943    return var;
00944 }

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 903 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

00905 {
00906    struct ast_variable **vars = NULL;
00907    va_list ap;
00908 
00909    va_start(ap, table_name);
00910    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
00911    va_end(ap);
00912 
00913    return vars;
00914 }

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_ptr is a pointer to found entries count (can be NULL)
basedn is the base DN
table_name is the table_name (used dor attribute convertion and additional filter)
ap contains null terminated list of pairs name/value

Definition at line 726 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_ERROR, 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().

00728 {
00729    struct ast_variable **vars = NULL;
00730    const char *newparam = NULL;
00731    const char *newval = NULL;
00732    struct ldap_table_config *table_config = NULL;
00733    char *clean_basedn = cleaned_basedn(NULL, basedn);
00734    struct ast_str *filter = NULL;
00735    int tries = 0;
00736    int result = 0;
00737    LDAPMessage *ldap_result_msg = NULL;
00738 
00739    if (!table_name) {
00740       ast_log(LOG_ERROR, "No table_name specified.\n");
00741       ast_free(clean_basedn);
00742       return NULL;
00743    } 
00744 
00745    if (!(filter = ast_str_create(80))) {
00746       ast_log(LOG_ERROR, "Can't initialize data structures.n");
00747       ast_free(clean_basedn);
00748       return NULL;
00749    }
00750 
00751    /* Get the first parameter and first value in our list of passed paramater/value pairs  */
00752    newparam = va_arg(ap, const char *);
00753    newval = va_arg(ap, const char *);
00754 
00755    if (!newparam || !newval) {
00756       ast_log(LOG_ERROR, "Realtime retrieval requires at least 1 parameter"
00757          " and 1 value to search on.\n");
00758       ast_free(filter);
00759       ast_free(clean_basedn);
00760       return NULL;
00761    }
00762 
00763    ast_mutex_lock(&ldap_lock);
00764 
00765    /* We now have our complete statement; Lets connect to the server and execute it.  */
00766    if (!ldap_reconnect()) {
00767       ast_mutex_unlock(&ldap_lock);
00768       ast_free(filter);
00769       ast_free(clean_basedn);
00770       return NULL;
00771    }
00772 
00773    table_config = table_config_for_table_name(table_name);
00774    if (!table_config) {
00775       ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
00776       ast_mutex_unlock(&ldap_lock);
00777       ast_free(filter);
00778       ast_free(clean_basedn);
00779       return NULL;
00780    }
00781 
00782    ast_str_append(&filter, 0, "(&");
00783 
00784    if (table_config && table_config->additional_filter) {
00785       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
00786    }
00787    if (table_config != base_table_config && base_table_config && 
00788       base_table_config->additional_filter) {
00789       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
00790    }
00791 
00792    /* Create the first part of the query using the first parameter/value pairs we just extracted */
00793    /*   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00794 
00795    append_var_and_value_to_filter(&filter, table_config, newparam, newval);
00796    while ((newparam = va_arg(ap, const char *))) {
00797       newval = va_arg(ap, const char *);
00798       append_var_and_value_to_filter(&filter, table_config, newparam, newval);
00799    }
00800    ast_str_append(&filter, 0, ")");
00801 
00802    do {
00803       /* freeing ldap_result further down */
00804       result = ldap_search_ext_s(ldapConn, clean_basedn,
00805               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
00806               &ldap_result_msg);
00807       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
00808          ast_log(LOG_DEBUG, "Failed to query database. Try %d/10\n", tries + 1);
00809          if (++tries < 10) {
00810             usleep(1);
00811             if (ldapConn) {
00812                ldap_unbind_ext_s(ldapConn, NULL, NULL);
00813                ldapConn = NULL;
00814             }
00815             if (!ldap_reconnect()) {
00816                break;
00817             }
00818          }
00819       }
00820    } while (result != LDAP_SUCCESS && tries < 10 && is_ldap_connect_error(result));
00821 
00822    if (result != LDAP_SUCCESS) {
00823       ast_log(LOG_WARNING, "Failed to query database. Error: %s.\n", ldap_err2string(result));
00824       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
00825    } else {
00826       /* this is where we create the variables from the search result 
00827        * freeing this \a vars outside this function */
00828       if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
00829          /* is this a static var or some other? they are handled different for delimited values */
00830          vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
00831       } else {
00832          ast_debug(1, "Could not find any entry matching %s in base dn %s.\n", ast_str_buffer(filter), clean_basedn);
00833       }
00834 
00835       ldap_msgfree(ldap_result_msg);
00836 
00837       /* TODO: get the default variables from the accountBaseDN, not implemented with delimited values */
00838       if (vars) {
00839          struct ast_variable **p = vars;
00840          while (*p) {
00841             struct ast_variable *append_var = NULL;
00842             struct ast_variable *tmp = *p;
00843             while (tmp) {
00844                if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
00845                   /* Get the variable to compare with for the defaults */
00846                   struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
00847                   
00848                   while (base_var) {
00849                      struct ast_variable *next = base_var->next;
00850                      struct ast_variable *test_var = *p;
00851                      int base_var_found = 0;
00852 
00853                      /* run throught the default values and fill it inn if it is missing */
00854                      while (test_var) {
00855                         if (strcasecmp(test_var->name, base_var->name) == 0) {
00856                            base_var_found = 1;
00857                            break;
00858                         } else {
00859                            test_var = test_var->next;
00860                         }
00861                      }
00862                      if (base_var_found) {
00863                         base_var->next = NULL;
00864                         ast_variables_destroy(base_var);
00865                         base_var = next;
00866                      } else {
00867                         if (append_var) {
00868                            base_var->next = append_var;
00869                         } else {
00870                            base_var->next = NULL;
00871                         }
00872                         append_var = base_var;
00873                         base_var = next;
00874                      }
00875                   }
00876                }
00877                if (!tmp->next && append_var) {
00878                   tmp->next = append_var;
00879                   tmp = NULL;
00880                } else {
00881                   tmp = tmp->next;
00882                }
00883             }
00884             p++;
00885          }
00886       }
00887    }
00888 
00889    if (filter) {
00890       ast_free(filter);
00891    }
00892 
00893    if (clean_basedn) {
00894       ast_free(clean_basedn);
00895    }
00896 
00897    ast_mutex_unlock(&ldap_lock);
00898 
00899    return vars;
00900 }

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.

Note:
Should be locked before using it
Returns:
a linked list of ast_variable variables.

Definition at line 278 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, value, and var.

Referenced by realtime_ldap_result_to_vars().

00280 {
00281    BerElement *ber = NULL;
00282    struct ast_variable *var = NULL;
00283    struct ast_variable *prev = NULL;
00284    int is_delimited = 0;
00285    int i = 0;
00286    char *ldap_attribute_name;
00287    struct berval *value;
00288    int pos = 0;
00289 
00290    ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00291 
00292    while (ldap_attribute_name) {
00293       struct berval **values = NULL;
00294       const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00295       int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00296 
00297       values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
00298       if (values) {
00299          struct berval **v;
00300          char *valptr;
00301 
00302          for (v = values; *v; v++) {
00303             value = *v;
00304             valptr = value->bv_val;
00305             ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
00306             if (is_realmed_password_attribute) {
00307                if (!strncasecmp(valptr, "{md5}", 5)) {
00308                   valptr += 5;
00309                } else {
00310                   valptr = NULL;
00311                }
00312                ast_debug(2, "md5: %s\n", valptr);
00313             }
00314             if (valptr) {
00315                /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
00316                if (is_delimited) {
00317                   i = 0;
00318                   pos = 0;
00319                   while (!ast_strlen_zero(valptr + i)) {
00320                      if (valptr[i] == ';') {
00321                         valptr[i] = '\0';
00322                         if (prev) {
00323                            prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00324                            if (prev->next) {
00325                               prev = prev->next;
00326                            }
00327                         } else {
00328                            prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00329                         }
00330                         pos = i + 1;
00331                      }
00332                      i++;
00333                   }
00334                }
00335                /* for the last delimited value or if the value is not delimited: */
00336                if (prev) {
00337                   prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00338                   if (prev->next) {
00339                      prev = prev->next;
00340                   }
00341                } else {
00342                   prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00343                }
00344             }
00345          }
00346          ldap_value_free_len(values);
00347       }
00348       ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00349    }
00350    ber_free(ber, 0);
00351 
00352    return var;
00353 }

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 361 of file res_config_ldap.c.

References ast_calloc, ast_debug, ast_strdup, ast_strlen_zero(), ast_variable_new(), 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, value, var, and variable_named().

Referenced by ldap_loadentry(), and realtime_ldap_base_ap().

00363 {
00364    struct ast_variable **vars;
00365    int i = 0;
00366    int tot_count = 0;
00367    int entry_index = 0;
00368    LDAPMessage *ldap_entry = NULL;
00369    BerElement *ber = NULL;
00370    struct ast_variable *var = NULL;
00371    struct ast_variable *prev = NULL;
00372    int is_delimited = 0;
00373    char *delim_value = NULL;
00374    int delim_tot_count = 0;
00375    int delim_count = 0;
00376 
00377    /* First find the total count */
00378    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00379 
00380    for (tot_count = 0; ldap_entry; tot_count++) { 
00381       tot_count += semicolon_count_var(realtime_ldap_entry_to_var(table_config, ldap_entry));
00382       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00383    }
00384 
00385    if (entries_count_ptr) {
00386       *entries_count_ptr = tot_count;
00387    }
00388 
00389    /* Now that we have the total count we allocate space and create the variables
00390     * Remember that each element in vars is a linked list that points to realtime variable.
00391     * If the we are dealing with a static realtime variable we create a new element in the \a vars array for each delimited
00392     * 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.
00393     * This memory must be freed outside of this function. */
00394    vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);
00395 
00396    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00397 
00398    i = 0;
00399 
00400    /* For each static realtime variable we may create several entries in the \a vars array if it's delimited */
00401    for (entry_index = 0; ldap_entry; ) { 
00402       int pos = 0;
00403       delim_value = NULL;
00404       delim_tot_count = 0;
00405       delim_count = 0;
00406       
00407       do { /* while delim_count */
00408 
00409          /* Starting new static var */
00410          char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00411          struct berval *value;
00412          while (ldap_attribute_name) {
00413          
00414             const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00415             int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00416             struct berval **values = NULL;
00417 
00418             values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
00419             if (values) {
00420                struct berval **v;
00421                char *valptr;
00422 
00423                for (v = values; *v; v++) {
00424                   value = *v;
00425                   valptr = value->bv_val;
00426                   if (is_realmed_password_attribute) {
00427                      if (strncasecmp(valptr, "{md5}", 5) == 0) {
00428                         valptr += 5;
00429                      } else {
00430                         valptr = NULL;
00431                      }
00432                      ast_debug(2, "md5: %s\n", valptr);
00433                   }
00434                   if (valptr) {
00435                      if (delim_value == NULL && !is_realmed_password_attribute 
00436                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {
00437 
00438                         delim_value = ast_strdup(valptr);
00439 
00440                         if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
00441                            ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
00442                            is_delimited = 1;
00443                         }
00444                      }
00445 
00446                      if (is_delimited != 0 && !is_realmed_password_attribute 
00447                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
00448                         /* for non-Static RealTime, first */
00449 
00450                         for (i = pos; !ast_strlen_zero(valptr + i); i++) {
00451                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00452                            if (delim_value[i] == ';') {
00453                               delim_value[i] = '\0';
00454 
00455                               ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00456                      
00457                               if (prev) {
00458                                  prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00459                                  if (prev->next) {
00460                                     prev = prev->next;
00461                                  }
00462                               } else {
00463                                  prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00464                               }
00465                               pos = i + 1;
00466 
00467                               if (static_table_config == table_config) {
00468                                  break;
00469                               }
00470                            }
00471                         }
00472                         if (ast_strlen_zero(valptr + i)) {
00473                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
00474                            /* Last delimited value */
00475                            ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00476                            if (prev) {
00477                               prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00478                               if (prev->next) {
00479                                  prev = prev->next;
00480                               }
00481                            } else {
00482                               prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00483                            }
00484                            /* Remembering to free memory */
00485                            is_delimited = 0;
00486                            pos = 0;
00487                         }
00488                         free(delim_value);
00489                         delim_value = NULL;
00490                         
00491                         ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00492                      } else {
00493                         /* not delimited */
00494                         if (delim_value) {
00495                            free(delim_value);
00496                            delim_value = NULL;
00497                         }
00498                         ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);
00499 
00500                         if (prev) {
00501                            prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
00502                            if (prev->next) {
00503                               prev = prev->next;
00504                            }
00505                         } else {
00506                            prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
00507                         }
00508                      }
00509                   }
00510                } /*!< for (v = values; *v; v++) */
00511                ldap_value_free_len(values);
00512             }/*!< if (values) */
00513             ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00514          } /*!< while (ldap_attribute_name) */
00515          ber_free(ber, 0);
00516          if (static_table_config == table_config) {
00517             if (option_debug > 2) {
00518                const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
00519                const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
00520                if (tmpdebug && tmpdebug2) {
00521                   ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value);
00522                }
00523             }
00524             vars[entry_index++] = var;
00525             prev = NULL;
00526          }
00527 
00528          delim_count++;
00529       } while (delim_count <= delim_tot_count && static_table_config == table_config);
00530 
00531       if (static_table_config != table_config) {
00532          ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__);
00533             
00534          vars[entry_index++] = var;
00535          prev = NULL;
00536       }
00537       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00538    } /*!< end for loop over ldap_entry */
00539 
00540    return vars;
00541 }

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

Definition at line 1733 of file res_config_ldap.c.

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

01734 {
01735    char status[256], credentials[100] = "";
01736    int ctimesec = time(NULL) - connect_time;
01737 
01738    switch (cmd) {
01739    case CLI_INIT:
01740       e->command = "realtime show ldap status";
01741       e->usage =
01742          "Usage: realtime show ldap status\n"
01743          "               Shows connection information for the LDAP RealTime driver\n";
01744       return NULL;
01745    case CLI_GENERATE:
01746       return NULL;
01747    }
01748 
01749    if (!ldapConn)
01750       return CLI_FAILURE;
01751 
01752    if (!ast_strlen_zero(url)) 
01753       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01754 
01755    if (!ast_strlen_zero(user))
01756       snprintf(credentials, sizeof(credentials), " with username %s", user);
01757 
01758    if (ctimesec > 31536000) {
01759       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01760             status, credentials, ctimesec / 31536000,
01761             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01762             (ctimesec % 3600) / 60, ctimesec % 60);
01763    } else if (ctimesec > 86400) {
01764       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01765             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01766             (ctimesec % 3600) / 60, ctimesec % 60);
01767    } else if (ctimesec > 3600) {
01768       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01769             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01770             ctimesec % 60);
01771    } else if (ctimesec > 60) {
01772       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01773                ctimesec / 60, ctimesec % 60);
01774    } else {
01775       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01776    }
01777 
01778    return CLI_SUCCESS;
01779 }

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 953 of file res_config_ldap.c.

References ast_category_append(), ast_category_new(), ast_config_new(), ast_log(), ast_variable_append(), free, LOG_ERROR, ast_variable::next, ldap_table_config::next, realtime_ldap_base_ap(), and var.

00955 {
00956    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00957    struct ast_config *cfg = NULL;
00958 
00959    if (vars) {
00960       cfg = ast_config_new();
00961       if (!cfg) {
00962          ast_log(LOG_ERROR, "Unable to create a config!\n");
00963       } else {
00964          struct ast_variable **p = vars;
00965 
00966          while (*p) {
00967             struct ast_category *cat = NULL;
00968             cat = ast_category_new("", table_name, -1);
00969             if (!cat) {
00970                ast_log(LOG_ERROR, "Unable to create a new category!\n");
00971                break;
00972             } else {
00973                struct ast_variable *var = *p;
00974                while (var) {
00975                   struct ast_variable *next = var->next;
00976                   var->next = NULL;
00977                   ast_variable_append(cat, var);
00978                   var = next;
00979                }
00980             }
00981             ast_category_append(cfg, cat);
00982             p++;
00983          }
00984       }
00985       free(vars);
00986    }
00987    return cfg;
00988 
00989 }

static int reload ( void   )  [static]

Definition at line 1563 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().

01564 {
01565    /* Aquire control before doing anything to the module itself. */
01566    ast_mutex_lock(&ldap_lock);
01567 
01568    if (ldapConn) {
01569       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01570       ldapConn = NULL;
01571    }
01572 
01573    if (parse_config() < 0) {
01574       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01575       ast_mutex_unlock(&ldap_lock);
01576       return 0;
01577    }     
01578 
01579    if (!ldap_reconnect())  {
01580       ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
01581    }
01582 
01583    ast_verb(2, "LDAP RealTime driver reloaded.\n");
01584 
01585    /* Done reloading. Release lock so others can now use driver. */
01586    ast_mutex_unlock(&ldap_lock);
01587 
01588    return 0;
01589 }

static int replace_string_in_string ( char *  string,
const char *  search,
const char *  by 
) [static]

Replace <search> by <by> in string.

Note:
No check is done on string allocated size !

Definition at line 670 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

00671 {
00672    int search_len = strlen(search);
00673    int by_len = strlen(by);
00674    int replaced = 0;
00675    char *p = strstr(string, search);
00676 
00677    if (p) {
00678       replaced = 1;
00679       while (p) {
00680          if (by_len == search_len) {
00681             memcpy(p, by, by_len);
00682          } else {
00683             memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
00684             memcpy(p, by, by_len);
00685          }
00686          p = strstr(p + by_len, search);
00687       }
00688    }
00689    return replaced;
00690 }

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

00153 {
00154    int count = 0;
00155 
00156    for (; *somestr; somestr++) {
00157       if (*somestr == ';')
00158          count++;
00159    }
00160 
00161    return count;
00162 } 

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

00168 {
00169    struct ast_variable *var_value = variable_named(var, "variable_value");
00170 
00171    if (!var_value) {
00172       return 0;
00173    }
00174 
00175    ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);
00176 
00177    return semicolon_count_str(var_value->value);
00178 }

static char* substituted ( struct ast_channel channel,
const char *  string 
) [static]

Note:
caller should free returned pointer

Definition at line 628 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

00629 {
00630 #define MAXRESULT 2048
00631    char *ret_string = NULL;
00632 
00633    if (!ast_strlen_zero(string)) {
00634       ret_string = ast_calloc(1, MAXRESULT);
00635       pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
00636    }
00637    ast_debug(2, "substituted: string: '%s' => '%s' \n", string, ret_string);
00638    return ret_string;
00639 }

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

00125 {
00126    struct ldap_table_config *c = NULL;
00127 
00128    AST_LIST_TRAVERSE(&table_configs, c, entry) {
00129       if (!strcmp(c->table_name, table_name))
00130          break;
00131    }
00132 
00133    return c;
00134 }

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

00106 {
00107    struct ldap_table_config *p;
00108 
00109    if (!(p = ast_calloc(1, sizeof(*p))))
00110       return NULL;
00111 
00112    if (table_name) {
00113       if (!(p->table_name = ast_strdup(table_name))) {
00114          free(p);
00115          return NULL;
00116       }
00117    }
00118 
00119    return p;
00120 }

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

Definition at line 202 of file res_config_ldap.c.

References ldap_table_config::additional_filter, ast_free, AST_LIST_REMOVE_HEAD, ast_variables_destroy(), ldap_table_config::attributes, base_table_config, ldap_table_config::entry, free, static_table_config, and ldap_table_config::table_name.

Referenced by parse_config(), and unload_module().

00203 {
00204    struct ldap_table_config *c;
00205 
00206    while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
00207       if (c->table_name) {
00208          ast_free(c->table_name);
00209       }
00210       if (c->additional_filter) {
00211          ast_free(c->additional_filter);
00212       }
00213       if (c->attributes) {
00214          ast_variables_destroy(c->attributes);
00215       }
00216       free(c);
00217    }
00218 
00219    base_table_config = NULL;
00220    static_table_config = NULL;
00221 }

static int unload_module ( void   )  [static]

Definition at line 1542 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().

01543 {
01544    /* Aquire control before doing anything to the module itself. */
01545    ast_mutex_lock(&ldap_lock);
01546 
01547    table_configs_free();
01548 
01549    if (ldapConn) {
01550       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01551       ldapConn = NULL;
01552    }
01553    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01554    ast_config_engine_deregister(&ldap_engine);
01555    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01556 
01557    /* Unlock so something else can destroy the lock. */
01558    ast_mutex_unlock(&ldap_lock);
01559 
01560    return 0;
01561 }

static int update2_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

Definition at line 1325 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(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

01326 {
01327    int error = 0;
01328    LDAPMessage *ldap_entry = NULL;
01329    LDAPMod **ldap_mods;
01330    const char *newparam = NULL;
01331    const char *newval = NULL;
01332    char *dn;
01333    int num_entries = 0;
01334    int i = 0;
01335    int mods_size = 0;
01336    int mod_exists = 0;
01337    struct ldap_table_config *table_config = NULL;
01338    char *clean_basedn = NULL;
01339    struct ast_str *filter = NULL;
01340    int tries = 0;
01341    int result = 0;
01342    LDAPMessage *ldap_result_msg = NULL;
01343 
01344    if (!table_name) {
01345       ast_log(LOG_ERROR, "No table_name specified.\n");
01346       return -1;
01347    } 
01348 
01349    if (!(filter = ast_str_create(80))) {
01350       return -1;
01351    }
01352 
01353    ast_mutex_lock(&ldap_lock);
01354 
01355    /* We now have our complete statement; Lets connect to the server and execute it.  */
01356    if (!ldap_reconnect()) {
01357       ast_mutex_unlock(&ldap_lock);
01358       ast_free(filter);
01359       return -1;
01360    }
01361 
01362    table_config = table_config_for_table_name(table_name);
01363    if (!table_config) {
01364       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01365       ast_mutex_unlock(&ldap_lock);
01366       ast_free(filter);
01367       return -1;
01368    }
01369 
01370    clean_basedn = cleaned_basedn(NULL, basedn);
01371 
01372    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01373    ast_str_append(&filter, 0, "(&");
01374    if (table_config && table_config->additional_filter) {
01375       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01376    }
01377    if (table_config != base_table_config && base_table_config
01378       && base_table_config->additional_filter) {
01379       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01380    }
01381 
01382    /* Get multiple lookup keyfields and values */
01383    while ((newparam = va_arg(ap, const char *))) {
01384       newval = va_arg(ap, const char *);
01385       append_var_and_value_to_filter(&filter, table_config, newparam, newval);
01386    }
01387    ast_str_append(&filter, 0, ")");
01388 
01389    /* Create the modification array with the parameter/value pairs we were given, 
01390     * if there are several parameters with the same name, we collect them into 
01391     * one parameter/value pair and delimit them with a semicolon */
01392    newparam = va_arg(ap, const char *);
01393    newparam = convert_attribute_name_to_ldap(table_config, newparam);
01394    newval = va_arg(ap, const char *);
01395    if (!newparam || !newval) {
01396       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01397       ast_free(filter);
01398       ast_free(clean_basedn);
01399       return -1;
01400    }
01401 
01402    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01403    ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
01404    ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
01405 
01406    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01407    ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01408    strcpy(ldap_mods[0]->mod_type, newparam);
01409 
01410    ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
01411    ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01412    strcpy(ldap_mods[0]->mod_values[0], newval);
01413 
01414    while ((newparam = va_arg(ap, const char *))) {
01415       newparam = convert_attribute_name_to_ldap(table_config, newparam);
01416       newval = va_arg(ap, const char *);
01417       mod_exists = 0;
01418 
01419       for (i = 0; i < mods_size - 1; i++) {
01420          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01421             /* We have the parameter allready, adding the value as a semicolon delimited value */
01422             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));
01423             strcat(ldap_mods[i]->mod_values[0], ";");
01424             strcat(ldap_mods[i]->mod_values[0], newval);
01425             mod_exists = 1;   
01426             break;
01427          }
01428       }
01429 
01430       /* create new mod */
01431       if (!mod_exists) {
01432          mods_size++;
01433          ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01434          ldap_mods[mods_size - 1] = NULL;
01435          ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
01436 
01437          ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01438 
01439          ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01440          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01441 
01442          ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
01443          ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01444          strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
01445       }
01446    }
01447    /* freeing ldap_mods further down */
01448 
01449    do {
01450       /* freeing ldap_result further down */
01451       result = ldap_search_ext_s(ldapConn, clean_basedn,
01452               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01453               &ldap_result_msg);
01454       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01455          ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n", tries + 1);
01456          tries++;
01457          if (tries < 3) {
01458             usleep(500000L * tries);
01459             if (ldapConn) {
01460                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01461                ldapConn = NULL;
01462             }
01463             if (!ldap_reconnect()) {
01464                break;
01465             }
01466          }
01467       }
01468    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01469 
01470    if (result != LDAP_SUCCESS) {
01471       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01472       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01473 
01474       ast_mutex_unlock(&ldap_lock);
01475       ast_free(filter);
01476       ast_free(clean_basedn);
01477       ldap_msgfree(ldap_result_msg);
01478       ldap_mods_free(ldap_mods, 0);
01479       return -1;
01480    }
01481    /* Ready to update */
01482    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01483       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01484          ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01485       }
01486 
01487       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01488 
01489       for (i = 0; ldap_entry; i++) { 
01490          dn = ldap_get_dn(ldapConn, ldap_entry);
01491          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01492             ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
01493          }
01494 
01495          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01496       }
01497    }
01498 
01499    ast_mutex_unlock(&ldap_lock);
01500    if (filter) {
01501       ast_free(filter);
01502    }
01503    if (clean_basedn) {
01504       ast_free(clean_basedn);
01505    }
01506    ldap_msgfree(ldap_result_msg);
01507    ldap_mods_free(ldap_mods, 0);
01508    return num_entries;
01509 }

static int update_ldap ( const char *  basedn,
const char *  table_name,
const char *  attribute,
const char *  lookup,
va_list  ap 
) [static]

Definition at line 1140 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().

01142 {
01143    int error = 0;
01144    LDAPMessage *ldap_entry = NULL;
01145    LDAPMod **ldap_mods;
01146    const char *newparam = NULL;
01147    const char *newval = NULL;
01148    char *dn;
01149    int num_entries = 0;
01150    int i = 0;
01151    int mods_size = 0;
01152    int mod_exists = 0;
01153    struct ldap_table_config *table_config = NULL;
01154    char *clean_basedn = NULL;
01155    struct ast_str *filter = NULL;
01156    int tries = 0;
01157    int result = 0;
01158    LDAPMessage *ldap_result_msg = NULL;
01159 
01160    if (!table_name) {
01161       ast_log(LOG_ERROR, "No table_name specified.\n");
01162       return -1;
01163    } 
01164 
01165    if (!(filter = ast_str_create(80))) {
01166       return -1;
01167    }
01168 
01169    if (!attribute || !lookup) {
01170       ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__);
01171       return -1;
01172    }
01173    ast_mutex_lock(&ldap_lock);
01174 
01175    /* We now have our complete statement; Lets connect to the server and execute it.  */
01176    if (!ldap_reconnect()) {
01177       ast_mutex_unlock(&ldap_lock);
01178       return -1;
01179    }
01180 
01181    table_config = table_config_for_table_name(table_name);
01182    if (!table_config) {
01183       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01184       ast_mutex_unlock(&ldap_lock);
01185       return -1;
01186    }
01187 
01188    clean_basedn = cleaned_basedn(NULL, basedn);
01189 
01190    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01191    ast_str_append(&filter, 0, "(&");
01192    if (table_config && table_config->additional_filter) {
01193       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01194    }
01195    if (table_config != base_table_config && base_table_config && base_table_config->additional_filter) {
01196       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01197    }
01198    append_var_and_value_to_filter(&filter, table_config, attribute, lookup);
01199    ast_str_append(&filter, 0, ")");
01200 
01201    /* Create the modification array with the parameter/value pairs we were given, 
01202     * if there are several parameters with the same name, we collect them into 
01203     * one parameter/value pair and delimit them with a semicolon */
01204    newparam = va_arg(ap, const char *);
01205    newparam = convert_attribute_name_to_ldap(table_config, newparam);
01206    newval = va_arg(ap, const char *);
01207    if (!newparam || !newval) {
01208       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01209       return -1;
01210    }
01211 
01212    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01213    ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
01214    ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
01215 
01216    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01217    ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01218    strcpy(ldap_mods[0]->mod_type, newparam);
01219 
01220    ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
01221    ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01222    strcpy(ldap_mods[0]->mod_values[0], newval);
01223 
01224    while ((newparam = va_arg(ap, const char *))) {
01225       newparam = convert_attribute_name_to_ldap(table_config, newparam);
01226       newval = va_arg(ap, const char *);
01227       mod_exists = 0;
01228 
01229       for (i = 0; i < mods_size - 1; i++) {
01230          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01231             /* We have the parameter allready, adding the value as a semicolon delimited value */
01232             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));
01233             strcat(ldap_mods[i]->mod_values[0], ";");
01234             strcat(ldap_mods[i]->mod_values[0], newval);
01235             mod_exists = 1;   
01236             break;
01237          }
01238       }
01239 
01240       /* create new mod */
01241       if (!mod_exists) {
01242          mods_size++;
01243          ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01244          ldap_mods[mods_size - 1] = NULL;
01245          
01246          ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
01247 
01248          ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01249          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01250 
01251          if (strlen(newval) == 0) {
01252             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
01253          } else {
01254             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01255 
01256             ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
01257             ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01258             strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
01259          }
01260       }
01261    }
01262    /* freeing ldap_mods further down */
01263 
01264    do {
01265       /* freeing ldap_result further down */
01266       result = ldap_search_ext_s(ldapConn, clean_basedn,
01267               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01268               &ldap_result_msg);
01269       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01270          ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n", tries + 1);
01271          tries++;
01272          if (tries < 3) {
01273             usleep(500000L * tries);
01274             if (ldapConn) {
01275                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01276                ldapConn = NULL;
01277             }
01278             if (!ldap_reconnect())
01279                break;
01280          }
01281       }
01282    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01283 
01284    if (result != LDAP_SUCCESS) {
01285       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01286       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01287 
01288       ast_mutex_unlock(&ldap_lock);
01289       free(filter);
01290       free(clean_basedn);
01291       ldap_msgfree(ldap_result_msg);
01292       ldap_mods_free(ldap_mods, 0);
01293       return -1;
01294    }
01295    /* Ready to update */
01296    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01297       ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
01298       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01299          if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
01300             ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01301          } else {
01302             ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
01303          }
01304       }
01305       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01306 
01307       for (i = 0; ldap_entry; i++) { 
01308          dn = ldap_get_dn(ldapConn, ldap_entry);
01309          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01310             ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
01311          }
01312 
01313          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01314       }
01315    }
01316 
01317    ast_mutex_unlock(&ldap_lock);
01318    ast_free(filter);
01319    ast_free(clean_basedn);
01320    ldap_msgfree(ldap_result_msg);
01321    ldap_mods_free(ldap_mods, 0);
01322    return num_entries;
01323 }

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, and ast_variable::next.

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

00138 {
00139    for (; var; var = var->next) {
00140       if (!strcasecmp(name, var->name))
00141          break;
00142    }
00143 
00144    return var;
00145 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "LDAP realtime interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1785 of file res_config_ldap.c.

Definition at line 1785 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 handle_cli_realtime_pgsql_status(), and pgsql_reconnect().

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 1511 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

LDAP* ldapConn [static]

Definition at line 65 of file res_config_ldap.c.

char pass[50] [static]

char url[512] [static]

char user[512] [static]

Definition at line 67 of file res_config_ldap.c.

int version = 3 [static]

Definition at line 70 of file res_config_ldap.c.


Generated on Wed Oct 28 13:33:27 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6