Wed Apr 6 11:30:08 2011

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"

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
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 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 1807 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

Note:
caller should free returned pointer

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

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

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

01017 {
01018    const struct category_and_metric *as = a;
01019    const struct category_and_metric *bs = b;
01020 
01021    if (as->metric < bs->metric) {
01022       return -1;
01023    } else if (as->metric > bs->metric) {
01024       return 1;
01025    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01026       return strcmp(as->name, bs->name);
01027    } 
01028    /* if the metric and the category name is the same, we check the variable metric */
01029    if (as->var_metric < bs->var_metric) {
01030       return -1;
01031    } else if (as->var_metric > bs->var_metric) {
01032       return 1;
01033    }
01034 
01035    return 0;
01036 }

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]

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 1045 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, ast_category::name, name, realtime_ldap_base(), RES_CONFIG_LDAP_CONF, ast_variable::value, and variable_named().

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

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

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

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

00544 {
00545    return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00546 }

static struct ast_variable* ldap_loadentry ( struct ldap_table_config table_config,
const char *  dn 
) [static]

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 551 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(), ldapConn, LOG_ERROR, LOG_NOTICE, LOG_WARNING, realtime_ldap_result_to_vars(), and var.

Referenced by realtime_ldap_base_ap().

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

static int ldap_reconnect ( void   )  [static]

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

Definition at line 1707 of file res_config_ldap.c.

References ast_debug, ast_log(), ast_strlen_zero(), connect_time, ldapConn, LOG_ERROR, LOG_WARNING, pass, url, and version.

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

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

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

01536 {
01537    if (parse_config() < 0) {
01538       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01539       return 0;
01540    }
01541 
01542    ast_mutex_lock(&ldap_lock);
01543 
01544    if (!ldap_reconnect())  {
01545       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01546    }
01547 
01548    ast_config_engine_register(&ldap_engine);
01549    ast_verb(1, "LDAP RealTime driver loaded.\n");
01550    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01551 
01552    ast_mutex_unlock(&ldap_lock);
01553 
01554    return 0;
01555 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1607 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_distinguished_name, base_table_config, config, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ldap_table_config::entry, ldap_table_config_add_attribute(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, pass, RES_CONFIG_LDAP_CONF, RES_CONFIG_LDAP_DEFAULT_BASEDN, static_table_config, table_config_for_table_name(), table_config_new(), table_configs_free(), url, var, and version.

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

static struct ast_variable* realtime_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

See Asterisk doc.

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

Definition at line 918 of file res_config_ldap.c.

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

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

static struct ast_variable** realtime_ldap_base ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
  ... 
) [static]

same as realtime_ldap_base_ap but take variable arguments count list

Definition at line 901 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

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

static struct ast_variable** realtime_ldap_base_ap ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

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 724 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(), ldapConn, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::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().

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

static struct ast_variable* realtime_ldap_entry_to_var ( struct ldap_table_config table_config,
LDAPMessage *  ldap_entry 
) [static]

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(), ldapConn, 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                }
00310                ast_debug(2, "md5: %s\n", valptr);
00311             }
00312             if (valptr) {
00313                /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
00314                if (is_delimited) {
00315                   i = 0;
00316                   pos = 0;
00317                   while (!ast_strlen_zero(valptr + i)) {
00318                      if (valptr[i] == ';') {
00319                         valptr[i] = '\0';
00320                         if (prev) {
00321                            prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00322                            if (prev->next) {
00323                               prev = prev->next;
00324                            }
00325                         } else {
00326                            prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00327                         }
00328                         pos = i + 1;
00329                      }
00330                      i++;
00331                   }
00332                }
00333                /* for the last delimited value or if the value is not delimited: */
00334                if (prev) {
00335                   prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00336                   if (prev->next) {
00337                      prev = prev->next;
00338                   }
00339                } else {
00340                   prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00341                }
00342             }
00343          }
00344          ldap_value_free_len(values);
00345       }
00346       ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00347    }
00348    ber_free(ber, 0);
00349 
00350    return var;
00351 }

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]

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 359 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, ldapConn, 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().

00361 {
00362    struct ast_variable **vars;
00363    int i = 0;
00364    int tot_count = 0;
00365    int entry_index = 0;
00366    LDAPMessage *ldap_entry = NULL;
00367    BerElement *ber = NULL;
00368    struct ast_variable *var = NULL;
00369    struct ast_variable *prev = NULL;
00370    int is_delimited = 0;
00371    char *delim_value = NULL;
00372    int delim_tot_count = 0;
00373    int delim_count = 0;
00374 
00375    /* First find the total count */
00376    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00377 
00378    for (tot_count = 0; ldap_entry; tot_count++) { 
00379       struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
00380       tot_count += semicolon_count_var(tmp);
00381       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00382       ast_variables_destroy(tmp);
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                      }
00430                      ast_debug(2, "md5: %s\n", valptr);
00431                   }
00432                   if (valptr) {
00433                      if (delim_value == NULL && !is_realmed_password_attribute 
00434                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {
00435 
00436                         delim_value = ast_strdup(valptr);
00437 
00438                         if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
00439                            ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
00440                            is_delimited = 1;
00441                         }
00442                      }
00443 
00444                      if (is_delimited != 0 && !is_realmed_password_attribute 
00445                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
00446                         /* for non-Static RealTime, first */
00447 
00448                         for (i = pos; !ast_strlen_zero(valptr + i); i++) {
00449                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00450                            if (delim_value[i] == ';') {
00451                               delim_value[i] = '\0';
00452 
00453                               ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00454                      
00455                               if (prev) {
00456                                  prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00457                                  if (prev->next) {
00458                                     prev = prev->next;
00459                                  }
00460                               } else {
00461                                  prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00462                               }
00463                               pos = i + 1;
00464 
00465                               if (static_table_config == table_config) {
00466                                  break;
00467                               }
00468                            }
00469                         }
00470                         if (ast_strlen_zero(valptr + i)) {
00471                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
00472                            /* Last delimited value */
00473                            ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00474                            if (prev) {
00475                               prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00476                               if (prev->next) {
00477                                  prev = prev->next;
00478                               }
00479                            } else {
00480                               prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00481                            }
00482                            /* Remembering to free memory */
00483                            is_delimited = 0;
00484                            pos = 0;
00485                         }
00486                         free(delim_value);
00487                         delim_value = NULL;
00488                         
00489                         ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00490                      } else {
00491                         /* not delimited */
00492                         if (delim_value) {
00493                            free(delim_value);
00494                            delim_value = NULL;
00495                         }
00496                         ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);
00497 
00498                         if (prev) {
00499                            prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
00500                            if (prev->next) {
00501                               prev = prev->next;
00502                            }
00503                         } else {
00504                            prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
00505                         }
00506                      }
00507                   }
00508                } /*!< for (v = values; *v; v++) */
00509                ldap_value_free_len(values);
00510             }/*!< if (values) */
00511             ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00512          } /*!< while (ldap_attribute_name) */
00513          ber_free(ber, 0);
00514          if (static_table_config == table_config) {
00515             if (option_debug > 2) {
00516                const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
00517                const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
00518                if (tmpdebug && tmpdebug2) {
00519                   ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value);
00520                }
00521             }
00522             vars[entry_index++] = var;
00523             prev = NULL;
00524          }
00525 
00526          delim_count++;
00527       } while (delim_count <= delim_tot_count && static_table_config == table_config);
00528 
00529       if (static_table_config != table_config) {
00530          ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__);
00531             
00532          vars[entry_index++] = var;
00533          prev = NULL;
00534       }
00535       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00536    } /*!< end for loop over ldap_entry */
00537 
00538    return vars;
00539 }

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

Definition at line 1754 of file res_config_ldap.c.

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

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

static struct ast_config* realtime_multi_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

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 951 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::next, realtime_ldap_base_ap(), and var.

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

static int reload ( void   )  [static]

Definition at line 1578 of file res_config_ldap.c.

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

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

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

Referenced by append_var_and_value_to_filter().

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

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, var, 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 626 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

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

static struct ldap_table_config* table_config_for_table_name ( const char *  table_name  )  [static]

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]

Create a new table_config.

Definition at line 105 of file res_config_ldap.c.

References ast_calloc, ast_strdup, and free.

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 1557 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, ldapConn, and table_configs_free().

01558 {
01559    /* Aquire control before doing anything to the module itself. */
01560    ast_mutex_lock(&ldap_lock);
01561 
01562    table_configs_free();
01563 
01564    if (ldapConn) {
01565       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01566       ldapConn = NULL;
01567    }
01568    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01569    ast_config_engine_deregister(&ldap_engine);
01570    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01571 
01572    /* Unlock so something else can destroy the lock. */
01573    ast_mutex_unlock(&ldap_lock);
01574 
01575    return 0;
01576 }

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

Definition at line 1340 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(), ldapConn, LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

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

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

Definition at line 1156 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(), ldapConn, LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

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

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

Find variable by name.

Definition at line 137 of file res_config_ldap.c.

References var.

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_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static]

Definition at line 1807 of file res_config_ldap.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1807 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 69 of file res_config_ldap.c.

Referenced by parse_config(), and realtime_ldap_status().

struct ldap_table_config* base_table_config [static]

Definition at line 97 of file res_config_ldap.c.

Referenced by convert_attribute_name_from_ldap(), convert_attribute_name_to_ldap(), parse_config(), realtime_ldap_base_ap(), table_configs_free(), update2_ldap(), and update_ldap().

time_t connect_time [static]

Definition at line 71 of file res_config_ldap.c.

Referenced by handle_cli_realtime_pgsql_status(), ldap_reconnect(), pgsql_reconnect(), and realtime_ldap_status().

struct ast_cli_entry ldap_cli[] [static]

Initial value:

 {
   { .handler =  realtime_ldap_status , .summary =  "Shows connection information for the LDAP RealTime driver" ,__VA_ARGS__ },
}

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

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 63 of file res_config_ldap.c.

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

LDAP* ldapConn [static]

Definition at line 65 of file res_config_ldap.c.

Referenced by ldap_loadentry(), ldap_reconnect(), realtime_ldap_base_ap(), realtime_ldap_entry_to_var(), realtime_ldap_result_to_vars(), realtime_ldap_status(), reload(), unload_module(), update2_ldap(), and update_ldap().

char pass[512] [static]

Definition at line 68 of file res_config_ldap.c.

Referenced by __ast_dsp_call_progress(), __get_header(), ast_db_deltree(), ast_db_gettree(), build_transactions(), gtalk_create_candidates(), handle_cli_database_show(), handle_cli_database_showkey(), jingle_create_candidates(), ldap_reconnect(), login_exec(), and parse_config().

struct ldap_table_config* static_table_config [static]

Definition at line 98 of file res_config_ldap.c.

Referenced by parse_config(), realtime_ldap_result_to_vars(), and table_configs_free().

char url[512] [static]

Definition at line 66 of file res_config_ldap.c.

Referenced by acf_curl_helper(), caldav_load_calendar(), dial_exec_full(), ewscal_load_calendar(), exchangecal_load_calendar(), ical_load_calendar(), ldap_reconnect(), parse_config(), queue_exec(), realtime_ldap_status(), reqprep(), respprep(), sendurl_exec(), and sip_sendhtml().

char user[512] [static]

Definition at line 67 of file res_config_ldap.c.

Referenced by action_meetmelist(), add_user_extension(), admin_exec(), authenticate(), authenticate_request(), authenticate_verify(), build_route(), build_user(), build_user_routes(), calltoken_required(), channel_admin_exec(), check_access(), conf_queue_dtmf(), conf_run(), delete_users(), find_user(), get_manager_by_name_locked(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_users(), handle_showmanager(), handle_showmanagers(), iax2_destroy_helper(), manager_displayconnects(), meetmemute(), pp_each_extension_helper(), pp_each_user_helper(), prune_users(), requirecalltoken_mark_auto(), reset_volumes(), send_talking_event(), set_config(), set_listen_volume(), set_talk_volume(), set_user_talking(), tweak_listen_volume(), tweak_talk_volume(), unref_user(), user_add_provider_cb(), user_chan_cb(), user_cmp_cb(), user_delme_cb(), user_destructor(), user_hash_cb(), user_listen_voldown_cb(), user_listen_volup_cb(), user_max_cmp(), user_no_cmp(), user_ref(), user_reset_vol_cb(), user_set_kickme_cb(), user_set_muted_cb(), user_set_unmuted_cb(), user_talk_voldown_cb(), user_talk_volup_cb(), user_unref(), users_data_provider_get(), users_hash_fn(), vm_users_data_provider_get(), and vm_users_data_provider_get_helper().

int version [static]

Definition at line 70 of file res_config_ldap.c.


Generated on Wed Apr 6 11:30:08 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7