Sat Feb 11 06:36:23 2012

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_LOAD_ORDER , .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, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
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 = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static LDAP * ldapConn
static char pass [512]
static struct ldap_table_configstatic_table_config
static char url [512]
static char user [512]
static int version


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

Referenced by config_ldap(), and parse_config().

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 62 of file res_config_ldap.c.

Referenced by parse_config().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1816 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

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

01026 {
01027    const struct category_and_metric *as = a;
01028    const struct category_and_metric *bs = b;
01029 
01030    if (as->metric < bs->metric) {
01031       return -1;
01032    } else if (as->metric > bs->metric) {
01033       return 1;
01034    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01035       return strcmp(as->name, bs->name);
01036    } 
01037    /* if the metric and the category name is the same, we check the variable metric */
01038    if (as->var_metric < bs->var_metric) {
01039       return -1;
01040    } else if (as->var_metric > bs->var_metric) {
01041       return 1;
01042    }
01043 
01044    return 0;
01045 }

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

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

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

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

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

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

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_free, ast_log(), ast_mutex_unlock, 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 directory. 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 directory. 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 
00613          /* Only take the first one. */
00614          var = *vars;
00615 
00616          /* Destroy the rest. */
00617          while (*++p) {
00618             ast_variables_destroy(*p);
00619          }
00620          ast_free(vars);
00621       }
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 1716 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().

01717 {
01718    int bind_result = 0;
01719    struct berval cred;
01720 
01721    if (ldapConn) {
01722       ast_debug(2, "Everything seems fine.\n");
01723       return 1;
01724    }
01725 
01726    if (ast_strlen_zero(url)) {
01727       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
01728       return 0;
01729    }
01730 
01731    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01732       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01733       return 0;
01734    }
01735 
01736    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01737       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01738    }
01739 
01740    if (!ast_strlen_zero(user)) {
01741       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01742       cred.bv_val = (char *) pass;
01743       cred.bv_len = strlen(pass);
01744       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01745    } else {
01746       ast_debug(2, "bind %s anonymously\n", url);
01747       cred.bv_val = NULL;
01748       cred.bv_len = 0;
01749       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01750    }
01751    if (bind_result == LDAP_SUCCESS) {
01752       ast_debug(2, "Successfully connected to directory.\n");
01753       connect_time = time(NULL);
01754       return 1;
01755    } else {
01756       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01757       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01758       ldapConn = NULL;
01759       return 0;
01760    }
01761 }

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

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

static int load_module ( void   )  [static]

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

01545 {
01546    if (parse_config() < 0) {
01547       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01548       return 0;
01549    }
01550 
01551    ast_mutex_lock(&ldap_lock);
01552 
01553    if (!ldap_reconnect())  {
01554       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01555    }
01556 
01557    ast_config_engine_register(&ldap_engine);
01558    ast_verb(1, "LDAP RealTime driver loaded.\n");
01559    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01560 
01561    ast_mutex_unlock(&ldap_lock);
01562 
01563    return 0;
01564 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1616 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, static_table_config, table_config_for_table_name(), table_config_new(), table_configs_free(), ast_variable::value, and var.

01617 {
01618    struct ast_config *config;
01619    struct ast_flags config_flags = {0};
01620    const char *s, *host;
01621    int port;
01622    char *category_name = NULL;
01623 
01624    /* Make sure that global variables are reset */
01625    url[0] = '\0';
01626    user[0] = '\0';
01627    pass[0] = '\0';
01628    base_distinguished_name[0] = '\0';
01629    version = 3;
01630 
01631    config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
01632    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01633       ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
01634       return -1;
01635    }
01636 
01637    if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
01638       ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
01639       user[0] = '\0';
01640    } else {
01641       ast_copy_string(user, s, sizeof(user));
01642    }
01643 
01644    if (!ast_strlen_zero(user)) {
01645       if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
01646          ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
01647          ast_copy_string(pass, "asterisk", sizeof(pass));
01648       } else {
01649          ast_copy_string(pass, s, sizeof(pass));
01650       }
01651    }
01652 
01653    /* URL is preferred, use host and port if not found */
01654    if ((s = ast_variable_retrieve(config, "_general", "url"))) {
01655       ast_copy_string(url, s, sizeof(url));
01656    } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
01657       if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
01658          ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
01659          port = 389;
01660       }
01661 
01662       snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
01663    } else {
01664       ast_log(LOG_ERROR, "No directory URL or host found.\n");
01665       ast_config_destroy(config);
01666       return -1;
01667    }
01668 
01669    if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
01670       ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
01671       ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
01672    } else 
01673       ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
01674 
01675    if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
01676       ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
01677    } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
01678       ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
01679       version = 3;
01680    }
01681 
01682    table_configs_free();
01683 
01684    while ((category_name = ast_category_browse(config, category_name))) {
01685       int is_general = (strcasecmp(category_name, "_general") == 0);
01686       int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
01687       struct ast_variable *var = ast_variable_browse(config, category_name);
01688       
01689       if (var) {
01690          struct ldap_table_config *table_config =
01691             table_config_for_table_name(category_name);
01692          if (!table_config) {
01693             table_config = table_config_new(category_name);
01694             AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
01695             if (is_general)
01696                base_table_config = table_config;
01697             if (is_config)
01698                static_table_config = table_config;
01699          }
01700          for (; var; var = var->next) {
01701             if (!strcasecmp(var->name, "additionalFilter")) {
01702                table_config->additional_filter = ast_strdup(var->value);
01703             } else {
01704                ldap_table_config_add_attribute(table_config, var->name, var->value);
01705             }
01706          }
01707       }
01708    }
01709 
01710    ast_config_destroy(config);
01711 
01712    return 1;
01713 }

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

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

00927 {
00928    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00929    struct ast_variable *var = NULL;
00930 
00931    if (vars) {
00932       struct ast_variable *last_var = NULL;
00933       struct ast_variable **p = vars;
00934 
00935       /* Chain the vars array of lists into one list to return. */
00936       while (*p) {
00937          if (last_var) {
00938             while (last_var->next) {
00939                last_var = last_var->next;
00940             }
00941             last_var->next = *p;
00942          } else {
00943             var = *p;
00944             last_var = var;
00945          }
00946          p++;
00947       }
00948       free(vars);
00949    }
00950    return var;
00951 }

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

References realtime_ldap_base_ap().

Referenced by config_ldap().

00910 {
00911    struct ast_variable **vars = NULL;
00912    va_list ap;
00913 
00914    va_start(ap, table_name);
00915    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
00916    va_end(ap);
00917 
00918    return vars;
00919 }

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

Todo:
XXX The interactions with base_var and append_var may cause a memory leak of base_var nodes. Also the append_var list and base_var list may get cross linked.

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_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_debug(1, "Failed to query directory. 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 directory. 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                         /*!
00868                          * \todo XXX The interactions with base_var and append_var may
00869                          * cause a memory leak of base_var nodes.  Also the append_var
00870                          * list and base_var list may get cross linked.
00871                          */
00872                         if (append_var) {
00873                            base_var->next = append_var;
00874                         } else {
00875                            base_var->next = NULL;
00876                         }
00877                         append_var = base_var;
00878                         base_var = next;
00879                      }
00880                   }
00881                }
00882                if (!tmp->next && append_var) {
00883                   tmp->next = append_var;
00884                   tmp = NULL;
00885                } else {
00886                   tmp = tmp->next;
00887                }
00888             }
00889             p++;
00890          }
00891       }
00892    }
00893 
00894    if (filter) {
00895       ast_free(filter);
00896    }
00897 
00898    if (clean_basedn) {
00899       ast_free(clean_basedn);
00900    }
00901 
00902    ast_mutex_unlock(&ldap_lock);
00903 
00904    return vars;
00905 }

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

00281 {
00282    BerElement *ber = NULL;
00283    struct ast_variable *var = NULL;
00284    struct ast_variable *prev = NULL;
00285    int is_delimited = 0;
00286    int i = 0;
00287    char *ldap_attribute_name;
00288    struct berval *value;
00289    int pos = 0;
00290 
00291    ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00292 
00293    while (ldap_attribute_name) {
00294       struct berval **values = NULL;
00295       const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00296       int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00297 
00298       values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
00299       if (values) {
00300          struct berval **v;
00301          char *valptr;
00302 
00303          for (v = values; *v; v++) {
00304             value = *v;
00305             valptr = value->bv_val;
00306             ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
00307             if (is_realmed_password_attribute) {
00308                if (!strncasecmp(valptr, "{md5}", 5)) {
00309                   valptr += 5;
00310                }
00311                ast_debug(2, "md5: %s\n", valptr);
00312             }
00313             if (valptr) {
00314                /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
00315                if (is_delimited) {
00316                   i = 0;
00317                   pos = 0;
00318                   while (!ast_strlen_zero(valptr + i)) {
00319                      if (valptr[i] == ';') {
00320                         valptr[i] = '\0';
00321                         if (prev) {
00322                            prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00323                            if (prev->next) {
00324                               prev = prev->next;
00325                            }
00326                         } else {
00327                            prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00328                         }
00329                         pos = i + 1;
00330                      }
00331                      i++;
00332                   }
00333                }
00334                /* for the last delimited value or if the value is not delimited: */
00335                if (prev) {
00336                   prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00337                   if (prev->next) {
00338                      prev = prev->next;
00339                   }
00340                } else {
00341                   prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00342                }
00343             }
00344          }
00345          ldap_value_free_len(values);
00346       }
00347       ldap_memfree(ldap_attribute_name);
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(), 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, 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       struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
00382       tot_count += semicolon_count_var(tmp);
00383       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00384       ast_variables_destroy(tmp);
00385    }
00386 
00387    if (entries_count_ptr) {
00388       *entries_count_ptr = tot_count;
00389    }
00390 
00391    /* Now that we have the total count we allocate space and create the variables
00392     * Remember that each element in vars is a linked list that points to realtime variable.
00393     * If the we are dealing with a static realtime variable we create a new element in the \a vars array for each delimited
00394     * 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.
00395     * This memory must be freed outside of this function. */
00396    vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);
00397 
00398    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00399 
00400    i = 0;
00401 
00402    /* For each static realtime variable we may create several entries in the \a vars array if it's delimited */
00403    for (entry_index = 0; ldap_entry; ) {
00404       int pos = 0;
00405       delim_value = NULL;
00406       delim_tot_count = 0;
00407       delim_count = 0;
00408 
00409       do { /* while delim_count */
00410 
00411          /* Starting new static var */
00412          char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00413          struct berval *value;
00414          while (ldap_attribute_name) {
00415             const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00416             int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00417             struct berval **values = NULL;
00418 
00419             values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
00420             if (values) {
00421                struct berval **v;
00422                char *valptr;
00423 
00424                for (v = values; *v; v++) {
00425                   value = *v;
00426                   valptr = value->bv_val;
00427                   if (is_realmed_password_attribute) {
00428                      if (strncasecmp(valptr, "{md5}", 5) == 0) {
00429                         valptr += 5;
00430                      }
00431                      ast_debug(2, "md5: %s\n", valptr);
00432                   }
00433                   if (valptr) {
00434                      if (delim_value == NULL && !is_realmed_password_attribute
00435                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {
00436 
00437                         delim_value = ast_strdup(valptr);
00438 
00439                         if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
00440                            ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
00441                            is_delimited = 1;
00442                         }
00443                      }
00444 
00445                      if (is_delimited != 0 && !is_realmed_password_attribute
00446                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
00447                         /* for non-Static RealTime, first */
00448 
00449                         for (i = pos; !ast_strlen_zero(valptr + i); i++) {
00450                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00451                            if (delim_value[i] == ';') {
00452                               delim_value[i] = '\0';
00453 
00454                               ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00455 
00456                               if (prev) {
00457                                  prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00458                                  if (prev->next) {
00459                                     prev = prev->next;
00460                                  }
00461                               } else {
00462                                  prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00463                               }
00464                               pos = i + 1;
00465 
00466                               if (static_table_config == table_config) {
00467                                  break;
00468                               }
00469                            }
00470                         }
00471                         if (ast_strlen_zero(valptr + i)) {
00472                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
00473                            /* Last delimited value */
00474                            ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00475                            if (prev) {
00476                               prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00477                               if (prev->next) {
00478                                  prev = prev->next;
00479                               }
00480                            } else {
00481                               prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00482                            }
00483                            /* Remembering to free memory */
00484                            is_delimited = 0;
00485                            pos = 0;
00486                         }
00487                         free(delim_value);
00488                         delim_value = NULL;
00489 
00490                         ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00491                      } else {
00492                         /* not delimited */
00493                         if (delim_value) {
00494                            free(delim_value);
00495                            delim_value = NULL;
00496                         }
00497                         ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);
00498 
00499                         if (prev) {
00500                            prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
00501                            if (prev->next) {
00502                               prev = prev->next;
00503                            }
00504                         } else {
00505                            prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
00506                         }
00507                      }
00508                   }
00509                } /*!< for (v = values; *v; v++) */
00510                ldap_value_free_len(values);
00511             }/*!< if (values) */
00512             ldap_memfree(ldap_attribute_name);
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 1763 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.

01764 {
01765    char status[256], credentials[100] = "";
01766    int ctimesec = time(NULL) - connect_time;
01767 
01768    switch (cmd) {
01769    case CLI_INIT:
01770       e->command = "realtime show ldap status";
01771       e->usage =
01772          "Usage: realtime show ldap status\n"
01773          "         Shows connection information for the LDAP RealTime driver\n";
01774       return NULL;
01775    case CLI_GENERATE:
01776       return NULL;
01777    }
01778 
01779    if (!ldapConn)
01780       return CLI_FAILURE;
01781 
01782    if (!ast_strlen_zero(url)) 
01783       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01784 
01785    if (!ast_strlen_zero(user))
01786       snprintf(credentials, sizeof(credentials), " with username %s", user);
01787 
01788    if (ctimesec > 31536000) {
01789       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01790             status, credentials, ctimesec / 31536000,
01791             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01792             (ctimesec % 3600) / 60, ctimesec % 60);
01793    } else if (ctimesec > 86400) {
01794       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01795             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01796             (ctimesec % 3600) / 60, ctimesec % 60);
01797    } else if (ctimesec > 3600) {
01798       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01799             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01800             ctimesec % 60);
01801    } else if (ctimesec > 60) {
01802       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01803                ctimesec / 60, ctimesec % 60);
01804    } else {
01805       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01806    }
01807 
01808    return CLI_SUCCESS;
01809 }

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

00962 {
00963    char *op;
00964    const char *initfield = NULL;
00965    const char *newparam, *newval;
00966    struct ast_variable **vars =
00967       realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00968    struct ast_config *cfg = NULL;
00969 
00970    newparam = va_arg(ap, const char *);
00971    newval = va_arg(ap, const char *);
00972    if (!newparam || !newval) {
00973        ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00974        return NULL;
00975    }
00976    initfield = ast_strdupa(newparam);
00977    if ((op = strchr(initfield, ' '))) {
00978       *op = '\0';
00979    }
00980 
00981    if (vars) {
00982       cfg = ast_config_new();
00983       if (!cfg) {
00984          ast_log(LOG_ERROR, "Unable to create a config!\n");
00985       } else {
00986          struct ast_variable **p = vars;
00987 
00988          while (*p) {
00989             struct ast_category *cat = NULL;
00990             cat = ast_category_new("", table_name, -1);
00991             if (!cat) {
00992                ast_log(LOG_ERROR, "Unable to create a new category!\n");
00993                break;
00994             } else {
00995                struct ast_variable *var = *p;
00996                while (var) {
00997                   struct ast_variable *next = var->next;
00998                   if (initfield && !strcmp(initfield, var->name)) {
00999                      ast_category_rename(cat, var->value);
01000                   }
01001                   var->next = NULL;
01002                   ast_variable_append(cat, var);
01003                   var = next;
01004                }
01005             }
01006             ast_category_append(cfg, cat);
01007             p++;
01008          }
01009       }
01010       free(vars);
01011    }
01012    return cfg;
01013 
01014 }

static int reload ( void   )  [static]

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

01588 {
01589    /* Aquire control before doing anything to the module itself. */
01590    ast_mutex_lock(&ldap_lock);
01591 
01592    if (ldapConn) {
01593       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01594       ldapConn = NULL;
01595    }
01596 
01597    if (parse_config() < 0) {
01598       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01599       ast_mutex_unlock(&ldap_lock);
01600       return 0;
01601    }     
01602 
01603    if (!ldap_reconnect())  {
01604       ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
01605    }
01606 
01607    ast_verb(2, "LDAP RealTime driver reloaded.\n");
01608 
01609    /* Done reloading. Release lock so others can now use driver. */
01610    ast_mutex_unlock(&ldap_lock);
01611 
01612    return 0;
01613 }

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

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

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

static int semicolon_count_var ( struct ast_variable var  )  [static]

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

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

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

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

static struct ldap_table_config* table_config_new ( const char *  table_name  )  [static, read]

Create a new table_config.

Definition at line 106 of file res_config_ldap.c.

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

Referenced by parse_config().

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

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

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

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

static int unload_module ( void   )  [static]

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

01567 {
01568    /* Aquire control before doing anything to the module itself. */
01569    ast_mutex_lock(&ldap_lock);
01570 
01571    table_configs_free();
01572 
01573    if (ldapConn) {
01574       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01575       ldapConn = NULL;
01576    }
01577    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01578    ast_config_engine_deregister(&ldap_engine);
01579    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01580 
01581    /* Unlock so something else can destroy the lock. */
01582    ast_mutex_unlock(&ldap_lock);
01583 
01584    return 0;
01585 }

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

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

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

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

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

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

static struct ast_variable* variable_named ( struct ast_variable var,
const char *  name 
) [static, read]

Find variable by name.

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

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static]

Definition at line 1816 of file res_config_ldap.c.

Definition at line 1816 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 70 of file res_config_ldap.c.

time_t connect_time [static]

Definition at line 72 of file res_config_ldap.c.

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

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

Definition at line 1535 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

LDAP* ldapConn [static]

Definition at line 66 of file res_config_ldap.c.

char pass[512] [static]

char url[512] [static]

char user[512] [static]

Definition at line 68 of file res_config_ldap.c.

int version [static]

Definition at line 71 of file res_config_ldap.c.


Generated on Sat Feb 11 06:36:24 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6